从OpenCV源码到arm动态库的全过程
最近两天成功把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.****.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,如果文中有什么不对的,欢迎指出。