一、交叉编译opencv
继上一篇博客:“在Linux下配置opencv”之后,我以为直接将编译命令:g++ `pkg-config --cflags opencv` -o TestOpencv TestOpencv.cpp `pkg-config --libs opencv` 中的g++直接改成arm-linux-gnueabihf-g++就可以编译生成树莓派里可以执行的文件了。但事实上并非如此,而是在编译时出现了如下错误:
系统提示我libopencv_shap.so文件格式无法识别。然后我以此为关键词在网上查找资料,发现有人指出libopencv_shap.so是x86的,然而目标文件却是arm的。也就是说,需要先链接arm架构的库,即需要先交叉编译opencv(资料引自:http://tieba.baidu.com/p/4618016956)。这时我才明白原来我之前在Linux PC下编译的opencv库是不能在arm构架的树莓派上运行的。于是我便在Linux PC中使用树莓派交叉编译工具编译opencv库。网络上的资料都大同小异,基本都是使用cmake-gui来配置opencv。我最开始是参照下面这篇博客(https://blog.csdn.net/sun_28/article/details/52760463)进行配置的。后来又搜索到了另一篇文章(http://bbs.elecfans.com/m/jishu_531776_1_1.html),上面有实例介绍。然后我就参照他的编译指令将我的程序进行编译,指令如下:
arm-linux-gnueabihf-g++ TestOpencv.cpp -o TestOpencvForRaspberry `pkg-config --cflags --libs opencv` -lpthread -lrt -ldl
然而出现如下错误:
到网上查找资料并未有任何收获,后来向老师请教,她说这么多的同类型错误应该是配置的问题,然后我意识到可能是在交叉编译opencv时有些选项选择不正确。如下图所示:
我把其中能选的都选上了(有些勾选之后,点击图片左下角的“configure”是会提示有错误的)。然后重新make install,这次得的到的库文件(在CMAKE_INSTALL_PREFIX选项指定的文件夹的lib文件夹下面)不是.a文件,而是.so文件,后来我又去看之前参照配置opencv的博客,发现他没有勾选BUILD_SHARED_LIBS,采用的是静态编译。然后将.so文件放到了交叉编译工具里的lib目录下重新编译程序。这次就没有出现大批量的未定义标识符的错误,而是出现了如下错误:
错误的原因应该是交叉编译工具找不到动态链接库,但是我确实将动态链接库放进去了,后来我到交叉编译工具的目录下去查看。发现不止一个lib目录,还有/usr/lib,/usr/local/lib,于是我将xxxx.so文件放到所有的lib文件夹中去了,再次编译程序就没有问题了。
二、移植opencv库
然后我将交叉编译好的xxxx.so文件拷贝到了树莓派上的/lib目录下,将可执行文件TestOpencvForRaspberry拷贝到了~/Public/executable_files目录下。然后给TestOpencvForRaspberry添加可执行权限并执行程序,却提示如下错误:
提示我加载动态库的时候出现了问题,然后使用ldd指令查看依赖库,有如下回馈:
问题就是../../libopencv_xxxxx.so => not found,一直不明白这是怎么回事,只有把可执行文件放在当前用户的home目录或者根目录及其非home的子目录下才能正确执行。如下图所示:
然后不管把可执行文件放入其他任何地方都是无法执行,而且提示相同的错误。
后来自己用树莓派交叉编译工具编译了一个非opencv的动态链接库,将其放置到树莓派的/lib目录下,然后执行相应的程序,程序正确执行。现在初步怀疑在使用树莓派交叉编译opencv库的时候出现了错误。
三、解决方法
针对上述问题的解决方法:直接在树莓派上编译安装opencv生成动态链接库(.so文件)。并在Linux PC中也使用树莓派交叉编译工具编译相应版本的opencv,这样树莓派就不需要再编译程序而只要执行程序了。
1、在树莓派上安装opencv,转载自:https://blog.csdn.net/leaves_joe/article/details/67656340
软件源更新
sudo apt-get update
升级本地所有安装包,最新系统可以不升级,版本过高反而需要降级才能安装
sudo apt-get upgrade
升级树莓派固件,固件比较新或者是Ubuntu则不用执行
sudo rpi-update
然后安装构建OpenCV的相关工具:
安装build-essential、cmake、git和pkg-config
sudo apt-get install build-essential cmake git pkg-config
/安装常用图像工具包:
安装jpeg格式图像工具包
sudo apt-get install libjpeg8-dev
安装tif格式图像工具包
sudo apt-get install libtiff5-dev
安装JPEG-2000图像工具包
sudo apt-get install libjasper-dev
安装png图像工具包
sudo apt-get install libpng12-dev
安装视频I/O包(注意最后一个包的数字“4”后面是“L”):
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
下面安装gtk2.0(树莓派很可能下载错误,更换中科大或者清华源即可,ubuntu有可能出现包版本过高的情况,需要将依赖包降级安装):
sudo apt-get install libgtk2.0-dev
优化函数包:
sudo apt-get install libatlas-base-dev gfortran
如果你希望在Python中使用OpenCV,那么你还需要安装Python的开发包:
sudo apt-get install python-dev python3-dev
执行到这里就把OpenCV的依赖包全部安装好了,之后要开始编译OpenCV源代码了,请大家用wget工具下载到用户目录下(源码要放在有执行权限的位置,不是安装位置),命令如下:
使用wget下载OpenCV源码,觉得慢的话可以到https://github.com/opencv/opencv/releases下载OpenCV的源代码
tar.gz格式,需要解压好,放到用户目录下
但是OpenCV_contrib请大家使用wget,亲测直接到Github下载zip文件的话,会有编译问题
下载OpenCV
wget -O opencv-3.4.3.zip https://github.com/Itseez/opencv/archive/3.4.3.zip
解压OpenCV
unzip opencv-3.4.3.zip
下载OpenCV_contrib库:
wget -O opencv_contrib-3.4.3.zip https://github.com/Itseez/opencv_contrib/archive/3.4.3.zip
解压OpenCV_contrib库:
unzip opencv_contrib-3.4.3.zip
找到你下载的源码文件夹并打开,tar.gz解压后文件夹名应该是opencv-3.4.3(版本号可能会变化),git方式下载的文件夹名应该是opencv。
打开源码文件夹,这里以我修改文章时最新的3.4.3为例
cd opencv-3.4.3
之后我们新建一个名为release的文件夹用来存放cmake编译时产生的临时文件:
新建release文件夹
mkdir release
进入release文件夹
cd release
提示!如果希望将其他库跟OpenCV连接起来使用,请提前配置好再进行接下来的编译
设置cmake编译参数,安装目录默认为/usr/local ,注意参数名、等号和参数值之间不能有空格,但每行末尾“\”之前有空格,参数值最后是两个英文的点(注意!如果在root用户下执行cmake命令,请将OPENCV_EXTRA_MODULES_PATH的值改为绝对路径,如:/home/joeya/opencv_contrib-3.4.3/modules):
/** CMAKE_BUILD_TYPE是编译方式
* CMAKE_INSTALL_PREFIX是安装目录
* OPENCV_EXTRA_MODULES_PATH是加载额外模块
* INSTALL_PYTHON_EXAMPLES是安装官方python例程
* BUILD_EXAMPLES是编译例程(这两个可以不加,不加编译稍微快一点点,
*想要C语言的例程的话,在最后一行前加参数INSTALL_C_EXAMPLES=ON \)
**/
sudo cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=..../opencv_contrib-3.4.3/modules \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D BUILD_EXAMPLES=ON ..
之后开始正式编译过程(如果之前一步因为网络问题导致cmake下载缺失文件失败的话,可以尝试使用手机热点,并将release文件夹删除掉,重新创建release文件夹并cmake):
/** 编译,以管理员身份,否则容易出错
* make命令参数-j4指允许make使用最多4个线程进行编译
* 所以可以根据自己机器的情况进行更改
**/
sudo make -j4
// 安装
sudo make install
// 更新动态链接库
sudo ldconfig
到这里,OpenCV的编译完成,已经可以正常使用了。
2019.5.1补充:
1、如果上面“CMAKE_INSTALL_PREFIX”设置的不是/usr/local,需要修改/etc/bash.bashrc中变量
LD_LIBRARY_PATH的值,具体为:
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opencv的安装位置,一直写到动态库的目录,如.../.../lib"
2、上述过程在搭载ubuntu mate 16.04系统的树莓派中是没有问题的,能正常够执行交叉编译的opencv
程序,但是对于搭载2018-11-13-raspbian-stretch(可能每个版本都会)系统的树莓派在执行同一个程序
时,却会提示有一些动态库缺失,但是树莓派自己编译的opencv程序能正常执行,由于直接在树莓派上编译程
序影响效率(后期不仅仅只有opencv相关的程序),我就直接把ubuntu mate 16.04系统中的与opencv相关的
动态库复制到2018-11-13-raspbian-stretch系统的树莓派中,然后再在有问题的树莓派上执行程序就能解决
问题。
2、在ubuntu上交叉编译opencv,参考:https://blog.csdn.net/sun_28/article/details/52760463
1)、解压完opencv后,进入其下目录,执行指令:
sudo cmake-gui
然后就会弹出如下菜单,其中第一行为opencv文件的位置,第二行为安装位置。(我的安装位置为/usr/local/rasopencv343)
2)、填写完毕之后,点击左下角的configure,进入编辑器选择界面。
3)、选择Specify options for cross-compiling,并点击Next进入编译器设置界面如下图
如图填写编译工具信息,其中比较重要的是Compilers下的C, C++, Target Root项。
其中C项代表的是树莓派编译工具的gcc编译器,如本文的
/home/apple/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
而C++项表示树莓派编译工具的g++编译器,如本文的
/home/apple/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-g++
Target Root代表标准库与头文件的搜索起始位置,可以理解为对应交叉编译工具的根目录。
/home/apple/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf
4)、点击Finish生成一系列编译配置。
5)、在安装目录中创建一个新文件夹(比如ras)作为opencv(生成的库)的装载位置。(我的为/usr/local/rasopencv343/ras)
6)、修改参数:
在Search栏上输入CMAKE_INSTALL_PREFIX,将对应value的值表示生成的库的装载位置,我的为/usr/local/opencv343/ras
在Search栏上输入OPENCV_EXTRA_MODULES_PATH,将对应value的值表示扩展模块的文件所在位置,
即 opencv_contrib-***的位置,我的为/home/username/Document/opencv_contrib-3.4.4/build
注意:路径要写到build,这部分参考自https://blog.csdn.net/leaves_joe/article/details/67656340
7)、点击Configure,进度条完成后,再点击Generate,即会在/usr/local/rasopencv343目录下产生Makefile编译文件。
8)、进入/usr/local/rasopencv343目录,修改CMakeCache.txt文件。在该文件中查找CMAKE_CXX_FLAGS:STRING,并为其赋值-lpthread -lrt -ldl
9)、然后依次执行如下指令即可完成编译安装
sudo make
sudo make install
3、交叉编译的过成功可能遇见的问题:
.../common.cc:52:2:error #error "No suitable threading library avaiable"...
解决方法:在common.cc文件中靠前的位置添加一个宏定义:#define HAVE_PTHREAD
这样,在ubuntu上交叉编译的opencv程序就可以在树莓派上的任意目录下执行了。
4、如果在树莓派上使用Raspberry Pi Camera V2摄像头,则需要进行如下设置:
1)、开启树莓派的摄像头功能
sudo raspi-config
选择第三个。
2)、启动摄像头功能
选择第一个。
3)、重启树莓派
4)、重启之后使用如下指令打开/etc/modules文件
sudo nano /etc/modules
然后在末尾添加上 :
i2v-dev
bcm2835-v4l2 #注意v4后面是小写字母l,不是数字1
5)、关闭当前终端,重开一个终端就可以时文件生效。
6)、若还是无法启动摄像头,则可以尝试在树莓派启动之前先插上摄像头。