ARM交叉編譯OpenCV錯誤總結(jié)

搬運自本人 CSDN 博客:https://blog.csdn.net/ajianyingxiaoqinghan/article/details/71155560


ARM交叉編譯OpenCV錯誤總結(jié)

最近嘗試給兩個ARM板子與用交叉編譯配置OpenCV,為此查了很多資料,學(xué)了很多交叉編譯的操作。
經(jīng)過多次的交叉編譯全都失敗,都不能成功的在目標(biāo)板上運行簡單的OpenCV的Demo程序。最后都是在對板子失去希望的時候,破罐破摔的直接用ARM板自己編譯。諷刺的是,這樣雖然效率低到極致,但最后還真的成功了…… 在Demo程序在ARM板自行編譯成功的OpenCV環(huán)境中順利的跑起來的時候,筆者感覺茫然無措,根本沒有什么開心的情緒,一是感覺終于解脫了,二是感覺自己學(xué)了這么長時間的交叉編譯,最后還是沒有用,還寫了這么多技術(shù)博客,深深的無力感……
筆者決定還是痛定思痛,還是得總結(jié)一下這段時間交叉編譯的錯誤所在。在中間的一些操作中,筆者總感覺自己交叉編譯的過程中,就是還是那么差了一點點才導(dǎo)致失敗。雖然已經(jīng)沒有精力再重新搞一遍交叉編譯。這些疑點還是可以記錄下來,以后有機會的時候,筆者會重新拿出來看,也許真的是這些原因?qū)е挛医徊婢幾g錯誤呢?

筆者的兩個ARM板配置如下:

  • 迅為i.MX6Q開發(fā)板
    • 操作系統(tǒng):Linux
    • 發(fā)行版:Debian GNU/Linux (BeagleBoard.org Debian Image)
    • CPU:1GHz四核
    • 容量:16GBytes eMMC
  • BeagleBone Black
    • 操作系統(tǒng):Linux
    • 發(fā)行版:Ubuntu 12.04
    • CPU:1GHz單核
    • 容量:4GBytes eMMC

之前筆者寫的交叉編譯相關(guān)技術(shù)博客地址如下:
《 Ubuntu 14.04 LTS下使用arm-linux-gcc交叉編譯OpenCV 2.4.9》
《Windows系統(tǒng)下遠(yuǎn)程連接BeagleBone Black開源電路板桌面》
《Windows系統(tǒng)下通過PSCP傳輸文件至BeagleBone Black》
《交叉編譯學(xué)習(xí)筆記(一)——交叉編譯和交叉工具鏈》
《交叉編譯學(xué)習(xí)筆記(二)——交叉編譯器的命名規(guī)則》
《程序生成之編譯、鏈接、加載淺析》

一. BeagleBone Black編譯總結(jié)

BeagleBone Black(即BBB)上OpenCV的編譯是真的痛苦。
主要原因是它的4GBytes的容量實在讓我絕望,而且我拿到板子的時候基本上也只有1GBytes的剩余容量了,OpenCV編譯過程中生成的中間文件大小都得有2GB啊…… 這導(dǎo)致筆者幾乎從一開始就否定了直接用BBB編譯的想法,一直在嘗試交叉編譯……

1. 編譯成功方法

諷刺的是交叉編譯一直失敗,最后我還是直接在ARM上編譯成功的,即先設(shè)置各項CMake選項,然后對OpenCV進(jìn)行make操作,最后make install,并make clean清除中間文件。
為什么筆者能在1GBytes的剩余容量中編譯出2GB的中間文件?這就是最蛋疼的地方所在…… 筆者OpenCV源碼路徑是<code>/root/Desktop/opencv-2.4.9</code>,編譯生成路徑是源碼路徑下的/build路徑。在make過程中,中間文件基本存在于<code>/root/Desktop/opencv-2.4.9/build/module</code>中,所以在make過程中,筆者會在終端顯示<font color=ff0000>已經(jīng)將上一個模塊編譯結(jié)束后,直接手動將對應(yīng)模塊路徑下的中間文件刪除</font>……
筆者當(dāng)時想反正<code>make install</code>指令的目標(biāo)一般都是<code>/include</code>, <code>/lib</code>, <code>/bin</code>文件夾,這些中間文件占的空間又這么大,刪除也不會對<code>make install</code>指令有什么影響……
事實證明我是正確的,但是過程很繁瑣,不能像在PC機上編譯時,只要放在那里編譯就好,筆者可以去看電視劇…… 這種盯著終端輸出信息,手動刪除編譯中間文件的操作,需要進(jìn)行兩遍:make一次,make install一次。如果中間跑神了,make過程中出現(xiàn)了錯誤提示說容量不夠?qū)е耺ake失敗,那就慘了,需要重新多來一次……

最后make, make install成功后,寫了一個Demo文件test_opencv.cpp,內(nèi)容如下:

#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <iostream>
#include <vector>

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
    const char* imagename = "/root/Desktop/miska.jpg";
    Mat img = imread(imagename);

    if(img.empty())
    {
        fprintf(stderr, "Can not load image %s\n", imagename);
        return -1;
    }
    else
        printf("Read Image Success.\n");

    Mat imgGray;
    cvtColor(img, imgGray, CV_BGR2GRAY);

    const char* imgGrayName = "/root/Desktop/miska_gray.jpg";
    vector<int> params;
    params.push_back(CV_IMWRITE_JPEG_QUALITY);
    params.push_back(90);
    imwrite(imgGrayName, imgGray, params);
    
    if(imgGray.empty())
    {
        fprintf(stderr, "Can not save image %s\n", imgGrayName);
        return -1;
    }
    else
        printf("Save Image Gray Success.\n");

    imshow("Image", imgGray);
    waitKey();

    return 0;
}

然后在cpp文件所在目錄下,輸入指令如下:

arm-linux-gnueabihf-g++ `pkg-config --cflags --libs opencv` test_opencv.cpp -lpthread -lrt -o test_opencv_g++_show

然后就生成了test_opencv_g++_show的可執(zhí)行文件。這時候輸入指令:

./test_opencv_g++_show

便出現(xiàn)如圖所示:


miska.jpg 灰度圖

除了顯示出圖片之外,在桌面上還存儲了相應(yīng)的灰度圖.jpg文件miska_gray.jpg。

這就是筆者愚蠢但有效的移植方法……

2. 錯誤情況總結(jié)與猜想

(1) error while loading shared libraries: libopencv_highgui.so.2.4

其實上面成功的內(nèi)容并不是在make install之后直接就完成的。
筆者對test_opencv.cpp進(jìn)行編譯指令如下:

arm-linux-gnueabihf-g++ `pkg-config --cflags --libs opencv` test_opencv.cpp -lpthread -lrt -o test_opencv_g++_show

卻出現(xiàn)如下錯誤提示:
<code>error while loading shared libraries: libopencv_highgui.so.2.4</code>
后來筆者參考了網(wǎng)上的資料,原來是筆者的OpenCV路徑?jīng)]有設(shè)置。
參考地址:
http://blog.csdn.net/gaobobo138968/article/details/24253703
http://blog.csdn.net/fangquan1980/article/details/49363173

首先,筆者在進(jìn)行make install命令之前,設(shè)定的install路徑為<code>/usr/local/arm/opencv-install/</code>,生成的庫文件都是動態(tài)鏈接庫。而在Linux系統(tǒng)中,文件<code>/etc/ld.so.conf</code>中記錄著動態(tài)函數(shù)庫所在目錄。所以筆者需要在<code>/etc/ld.so.conf</code>中將路徑<code>/usr/local/arm/opencv-install/</code>添加進(jìn)去。
然后就需要執(zhí)行指令:

ldconfig

這樣就將<code>/etc/ld.so.conf</code>中的內(nèi)容讀入了高速緩存,同時<code>/etc/ld.so.cache</code>文件中開始記錄數(shù)據(jù)。
重新用arm-linux-gnueabihf-g++編譯Demo程序,就編譯成功,且能成功運行了。

(2) file not recognized

之前筆者的OpenCV是交叉編譯的,且交叉編譯的過程已經(jīng)在我之前的博客中《 Ubuntu 14.04 LTS下使用arm-linux-gcc交叉編譯OpenCV 2.4.9》有過記錄。
筆者把編譯后的目錄opencv-install放置在和PC機相同的路徑(即<code>/usr/local/arm/opencv-install/</code>)
之后使用arm-linux-gnueabihf-g++編譯Demo程序,然而出現(xiàn)錯誤:
<code>/usr/local/arm/opencv-install/lib/libopencv_calib3d.so: flie not recognized: File format not recognized
collect2: ld returned 1 exit status</code>
也就是因為這個原因,筆者放棄了用PC機交叉編譯……

網(wǎng)上查了查原因,有人出現(xiàn)這樣的問題,但卻是因為文件格式,或者是x86的32/64位系統(tǒng)版本,或者是直接就沒有用arm-linux-gcc系列的編譯器之類的原因,況且我用的也是arm平臺的編譯器(筆者在PC機端用的編譯器是arm-none-linux-gcc-4.3.2,在BeagleBone Black板上的編譯器是4.6.3版本的arm-linux-gnueabihf-gcc),雖然版本不同,但筆者認(rèn)為在PC機上用的編譯器應(yīng)該是被BBB的編譯器向下兼容的。

對于這種情況,筆者感覺只有兩種操作可能解決:
1、用4.6.3版本的arm-linux-gnueabihf-gcc編譯相關(guān)庫;(其實也嘗試過,但是在編譯ffmpeg源碼時貌似出了問題…… )
2、當(dāng)時確實沒有用過ldconfig命令,也可能是這個原因?……

(3) 使用錯誤的編譯器

這個本來都不想回憶的,因為實在太低級失誤了…… 筆者曾經(jīng)用了gcc的編譯器編譯Demo程序,然而庫文件是交叉編譯的arm-linux-gcc版本,結(jié)果肯定是運行不了的…… 具體什么情況忘了,記著這個教訓(xùn)就好了……

二. 迅為i.MX6Q開發(fā)板編譯總結(jié)

1. 編譯成功方法

雖然交叉編譯失敗,但是ARM本機編譯方面,相比起來迅為的ARM開發(fā)板比BBB簡單的多了。畢竟i.MX6Q的CPU可以使用多核編譯,而且eMMC容量也大得多,所以不需要盯著終端輸出信息各種手動刪除中間文件騰空間,只需要簡單的cmake, make, make install,之后就可以編譯運行了……
其他的基本可以參照BBB的成功范例。

2. 錯誤情況總結(jié)與猜想

i.MX6Q的系統(tǒng)是和PC機一樣的Ubuntu,所以錯誤情況比較少,基本上還是可以參考BBB的總結(jié)……(原諒筆者的懶惰,一是因為錯誤情況少,二是因為時間稍微有點久遠(yuǎn)了……)

后記:

筆者真的是已經(jīng)沒有精力再專門重新編譯了……所以只有在此處記錄為博客,以后如果真有重新交叉編譯的情況,再重新嘗試。
希望個人的錯誤總結(jié)也可以有點價值吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容