最近兩天成功把OpenCV移植到arm開發板,過程中遇到許多問題,於是寫下此篇文章記錄一番,方便自己日後複習,或許還可以幫助到其他人。OpenCV移植所需要做的東西還是挺多的,所以文章比較長。
移植過程參考了 KayChanGeek 大神的一些關於OpenCV移植的文章。
移植用到的工具如下:
1、Ubuntu 16.04,64位
2、cmake,用於生成編譯OpenCV源碼的Makefile,可以直接輸入如下命令安裝:
sudo apt-get install cmake cmake-qt-gui
3、OpenCV源碼,3.2.0版本的,各版本源碼可到OpenCV官網直接下載
https://www.opencv.org/releases.html
4、交叉編譯工具,arm-linux-gcc-4.4.3
編譯 OpenCV3.0 以上版本建議使用比較高版本的交叉編譯工具,否則編譯過程會出現一些奇怪的錯誤。我試過用4.4.1版本的交叉編譯工具去編譯 OpenCV3.2.0 ,結果就有奇怪的錯誤(當時忘記截圖了,有點後悔),然後改爲4.4.3版本的,就沒有那個錯誤了。
5、需要用到的第三方庫,JPEG、PNG這些
第三方庫源碼可在他們的官網下載到,若懶去找的話可以在這裏一併下載我所用到的第三方庫和交叉編譯工具,裏面也有交叉編譯環境的搭建過程,具體文件如下圖:
移植步驟:
1、交叉編譯第三方庫
參考自:https://blog.csdn.net/KayChanGEEK/article/details/78550141
先把第三方庫複製到虛擬機下任一目錄,並在該目錄下創建一個文件夾來保存編譯後的文件,然後把裏面的壓縮包全部解壓用到的命令如下:
解壓.tart.gz使用命令tar -xzvf xxx.tar.gz,
解壓.tar.bz2使用命令tar -xjvf xxx.tar.bz2,
解壓.tar.xz先用xz -d xxx.tar.xz,這時候會輸出對應的.tar文件,再用tar -xvf xxx.tar解壓即可
這時文件夾有如下文件,其中 3rdlib 文件夾就是我用來保存編譯後的文件的文件夾
--prefix用於指定生成文件的存放位置,具體內容是根據具體情況而定,例如我的是/usr/local/opencv_lib/3rdlib,下面的這個變量的值我就用 /.../ 代替
交叉編譯libz
cd zlib-1.2.8
CC=arm-linux-gcc ./configure --prefix=/.../ --shared
打開Makefile,將AR=ar改成AR=arm-linux-ar,RANLIB改成arm-linux-ranlib。
make
make install
交叉編譯libjpeg
cd jpeg-9b
./configure --host=arm-linux --prefix=/.../ --enable-shared --enable-static
make
make install
交叉編譯libpng
編譯libpng有點不同,因爲libpng庫是不需要configure的,在scripts目錄下已經提供makefile,把scripts目錄下makefile.linux拷貝到源碼包根目錄中,並修改makefile的zlib庫的路徑
以下是安裝libpng的具體步驟:
(1)cp scripts/makefile.linux makefile
(2)vim makefile
(3)makefile中找到zlib相關的兩行,修改成實際的zlib/lib和zlib/include,再找到prefix項,修改爲你想prefix的目錄中,
如果此處是交叉編譯的話,還需要在cc那邊把gcc修改成您系統的交叉編譯器,比如:arm-linux-gcc
(4)保存並且make make install
交叉編譯yasm
cd yasm-1.3.0
CC=arm-linux-gcc ./configure --host=arm-linux --prefix=/.../ --enable-shared --disable-asm
make
make install
交叉編譯libx264
cd x264-snapshot-20171114-2245
CC=arm-linux-gcc ./configure --host=arm-linux --prefix=/.../ --enable-shared --disable-asm
make
make install
交叉編譯libxvid
cd xvidcore-1.3.3
cd build/generic
./configure --host=arm-linux --prefix=/.../ --disable-assembly
make
make install
交叉編譯ffmpeg
cd ffmpeg-3.4
./configure --prefix=/.../ --enable-shared --disable-static --enable-gpl --enable-cross-compile --arch=arm --disable-stripping --target-os=linux --enable-libx264 --enable-libxvid --cc=arm-linux-gcc --enable-swscale --extra-ldflags=-L/.../lib --extra-cflags=-I/.../include
make
make install
編譯FFmpeg可能會遇到一個問題,就是老是提示說找不到perf_event.h,這個文件爲Linux本身自帶的,用於Linux性能的檢測與調優,我把包含這個頭文件的的源文件的#include<linux/perf_event.h>這一行給註釋了,就可以了。具體什麼源文件我忘記了,可以在編譯信息那裏很直觀地看到。
2、編譯OpenCV源碼
進入opencv源碼目錄下,建立了2個文件夾 build_arm(存放cmake生成的文件)和output_arm(存放編譯後生成的文件),進入build_arm目錄下,運行cmake,
cmake-gui
按下圖填寫:
注意:原則上第三方庫的路徑是可以任意的,但是在這裏需要把第三方庫編譯出來的include文件夾和lib文件夾下的東西全部拷貝到/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi下對應的文件夾裏,否則會出現找不到第三方庫的錯誤。這個錯誤應該是跟某個地方的路徑設置有關,但是我還沒找到具體是那個地方。
這裏的庫我只剩下了JPEG、PNG、FFmpeg和opencl的,因爲其他的我都沒編譯。
在build_arm目錄下打開CMakeCache.txt文件,找到CMAKE_EXE_LINKER_FLAGS,在其後面加上-lpthread -lrt -ldl鏈接屬性,如下圖所示:
然後make,make install就可以了。
編譯過程可能遇到的錯誤:
①
打開這個文件修改abs 爲 fabs。
②出現重複定義
typedef ::int8_t int8_t;
typedef ::uint8_t uint8_t;
typedef ::int16_t int16_t;
typedef ::uint16_t uint16_t;
typedef ::int32_t int32_t;
typedef ::uint32_t uint32_t;
typedef ::int64_t int64_t;
typedef ::uint64_t uint64_t;
打開 cvdef.h 文件把上述代碼註釋掉
如無意外,編譯就完成了,在output_arm/lib目錄下可以看到生成的庫文件
把OpenCV庫文件和第三方的庫文件一起拷貝到開發板的/lib目錄下,移植就算完成了。
接下來可以稍稍測試一下:
寫一個測試程序:
配置pkg-config,打開/etc/ld.so.conf文件,在最後一行添加剛纔編譯輸出的庫路徑/opt/arm/opencv-3.2.0/output_arm/lib,再進行ldconfig等配置,具體過程如下:
vim /etc/ld.so.conf
將目錄/opt/arm/opencv-3.2.0/output_arm/lib添加到文件末尾,目錄是你自己的output_arm目錄
ldconfig
export PKG_CONFIG_PATH=/opt/arm/opencv-3.2.0/output_arm/lib/pkgconfig:$PKG_CONFIG_PATH
pkg-config --libs --cflags opencv
這時候看到輸出信息如下圖,說明pkg-config配置成功,注意箭頭標註的這兩個路徑一定要是你的output_arm的實際路徑
然後就是編譯測試程序:arm-linux-g++ opencv_test.cpp -o opencv_test `pkg-config --cflags --libs opencv`
file opencv_test 查看文件屬性
如果是ARM就代表成功啦。
初次移植OpenCV,如果文中有什麼不對的,歡迎指出。