下面实现OpenCV的交叉编译和程序测试。
将上次在CentOS编译出的库文件夹/usr/local/arm/opencv-lib和/usr/local/arm/opencv-arm分别拷贝到Ubuntu中的相同目录下,用来之后的OpenCV程序的交叉编译。
step1: 交叉编译准备工作
为了方便我们需要将前面复制过来的两个文件夹合并,指令:
cp -r /usr/local/arm/opencv-lib/* /usr/local/arm/opencv-arm/
然后代码中若用到了打印函数,需要用到libstdc++的库,所以我们需要将这个库也顺便复制到OpenCV的库文件夹中。指令:
cd /opt/pkg/petalinux/petalinux-v2015.4-final/tools/linux-i386/arm-xilinx-linux-gnueabi
find ./ -name '*libstdc++.so.6*'
cp ./arm-xilinx-linux-gnueabi/libc/usr/lib/libstdc++.so /usr/local/arm/opencv-arm/lib/
cp ./arm-xilinx-linux-gnueabi/libc/usr/lib/libstdc++.so.6 /usr/local/arm/opencv-arm/lib/
cp ./arm-xilinx-linux-gnueabi/libc/usr/lib/libstdc++.so.6.0.20 /usr/local/arm/opencv-arm/lib/
这样就得到了交叉编译的所有依赖库文件,在下面的文件中。
/usr/local/arm/opencv-arm
接着需要把所有库文件下载到板子的非易失存储器当中去。
首先在Ubuntu中生成OpenCV的库镜像文件。
cd /usr/local/arm
#查看opencv--arm文件夹大小,我的为110MB左右
#镜像的名字opencv_lib.img和大小120M,可以根据实际链接库的大小进行设置
dd if=/dev/zero of=opencv_lib.img bs=1M count=120
mkfs.ext2 -F opencv_lib.img
chmod go+w opencv_lib.img
mount opencv_lib.img -o loop /mnt
#复制相应的库的即将压缩的镜像中
cp -r /usr/local/arm/opencv-arm/* /mnt
chmod go-w opencv_lib.img
umount /mnt
通过U盘复制opencv_lib.img这个文件夹到系统的eMMC存储器当中,并挂载库和连接。
mkdir /mnt/usb
mkdir /mnt/emmc
mount /dev/sda0 /mnt/usb
mount /dev/mmcblk0p2 /mnt/emmc
cp /mnt/usb/opencv_lib.img /mnt/emmc
umount /mnt/usb
mkdir /usr/lib/opencv
mount /mnt/emmc/opencv_lib.img /usr/lib/opencv
LD_LIBRARY_PATH=/usr/lib/opencv/lib/
step2: 交叉编译
为了方便使用eclipse来进行OpenCV程序的开发,可以参考:
http://docs.opencv.org/2.4/doc/tutorials/introduction/linux_eclipse/linux_eclipse.html
打开eclipse。
File -> New -> C/C++ Project
选择C++ Managed Build并进入工程设置界面:
Project name : arm_opencv_temp
Project type : Empty Project
Toolchain : Cross GCC
点击Next,Next。
然后选择gcc交叉编译器所在目录:
Cross compiler prefix : arm-xilinx-linux-gnueabi-
Cross compiler path : /opt/pkg/petalinux/petalinux-v2015.4-final/tools/linux-i386/arm-xilinx-linux-gnueabi/bin
点击Finish,完成设置。
在左边的Project Explorer右键点击刚才建立的arm_opencv_temp工程,选择新建一个文件夹src,并在src中新建一个C++文件,arm_opencv_temp.cpp。
打开c++源文件,并粘贴如下代码到文件中。
这里的代码实现的是通过USB摄像头采集图像并保存为avi视频格式。
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include "iostream"
using namespace std;
int main()
{
CvCapture* capture=cvCaptureFromCAM(-1);
CvVideoWriter* video=NULL;
IplImage* frame=NULL;
int n;
if(!capture) //如果不能打开摄像头给出警告
{
cout<<"Can not open the camera."<<endl;
return -1;
}
else
{
frame=cvQueryFrame(capture); //首先取得摄像头中的一帧
video=cvCreateVideoWriter("camera.avi", CV_FOURCC('X', 'V', 'I', 'D'), 25,
cvSize(frame->width,frame->height)); //创建CvVideoWriter对象并分配空间
//保存的文件名为camera.avi,编码要在运行程序时选择,大小就是摄像头视频的大小,帧频率是32
if(video) //如果能创建CvVideoWriter对象则表明成功
{
cout<<"VideoWriter has created."<<endl;
}
// cvNamedWindow("Camera Video",1); //新建一个窗口
int i = 0;
while(i <= 200) // 让它循环200次自动停止录取
{
frame=cvQueryFrame(capture); //从CvCapture中获得一帧
if(!frame)
{
cout<<"Can not get frame from the capture."<<endl;
break;
}
n=cvWriteFrame(video,frame); //判断是否写入成功,如果返回的是1,表示写入成功
cout<<n<<endl;
// cvShowImage("Camera Video",frame); //显示视频内容的图片
i++;
// if(cvWaitKey(2)>0)
// break; //有其他键盘响应,则退出
}
cvReleaseVideoWriter(&video);
cvReleaseCapture(&capture);
// cvDestroyWindow("Camera Video");
}
return 0;
}
因为我的opencv交叉编译库中没有图形界面的支持,所以我注释掉了关于图形显示的函数调用。包括:
//cvNamedWindow("Camera Video",1);
//cvShowImage("Camera Video",frame); //显示视频内容的图片
//if(cvWaitKey(2)>0)
// break;
//cvDestroyWindow("Camera Video");
保存源文件后,发现很多错误。这是因为我们还没有连接到我们的opencv交叉编译库。
按照下面的图进行配置:
其中的Cross G++ Linker -> Libraries -> Libraries(-l)中包含了所有的opencv库文件:
opencv_core opencv_highgui opencv_imgproc opencv_nonfree opencv_ml
opencv_video opencv_videostab opencv_features2d opencv_gpu
opencv_calib3d opencv_objdetect opencv_photo opencv_stitching
opencv_ts opencv_superres opencv_contrib opencv_legacy opencv_flann
尤其注意最后一张图片的配置,需要向Miscellaneous的Linker flags添加如下信息,才能够保证编译器顺利找到我们的交叉编译库所在目录。
-Wl,-rpath-link,/usr/local/arm/opencv-arm/lib
设置完成后点击OK,Ctrl+B进行编译。我们就可以在工程目录下的Debug文件中找到arm平台上的可执行文件arm_opencv_temp。
编译成功打印的log信息:
11:19:16 **** Incremental Build of configuration Debug for project arm_opencv_temp ****
make all
Building target: arm_opencv_temp
Invoking: Cross G++ Linker
arm-xilinx-linux-gnueabi-g++ -L/usr/local/arm/opencv-arm/lib -Wl,-rpath-link,/usr/local/arm/opencv-arm/lib -o "arm_opencv_temp" ./src/arm_opencv_temp.o -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_nonfree -lopencv_ml -lopencv_video -lopencv_videostab -lopencv_features2d -lopencv_gpu -lopencv_calib3d -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_ts -lopencv_superres -lopencv_contrib -lopencv_legacy -lopencv_flann
Finished building target: arm_opencv_temp
11:19:18 Build Finished (took 2s.937ms)
在板子上插入USB摄像头,并复制运行程序,即可实现嵌入式平台的USB摄像头视频采集和保存的功能。
存在的问题:
使用纯软件的方法进行摄像头读取,jpeg解压以及avi视频的存储,速度很慢,例子中的200帧图像需要很久才能处理完成!
先这样吧,之后再想解决办法。
step3: Ubuntu OpenCV的安装与测试
前面已经实现了OpenCV的交叉编译和测试,但是为了方便,我们还是需要在PC机的Ubuntu上安装OpenCV。这样就能够在PC上完成程序编译与功能验证以后,再进行交叉编译,最终确保程序能够在目标平台上正常运行。
Ubuntu上的OpenCV安装起来还是比较方便的。
下载好OpenCV源码后,首先安装必要的第三方库:
apt-get install cmake-curses-gui
apt-get install cmake-gui
apt-get install build-essential libgtk2.0-dev libjpeg-dev libtiff5-dev libjasper-dev libopenexr-dev cmake python-dev python-numpy python-tk libtbb-dev libeigen3-dev yasm libfaac-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev libx264-dev libqt4-dev libqt4-opengl-dev sphinx-common texlive-latex-extra libv4l-dev libdc1394-22-dev libavcodec-dev libavformat-dev libswscale-dev default-jdk ant libvtk5-qt4-dev
解压源码后,进行编译配置:
mkdir build
cd build
cmake -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D WITH_QT=ON -D WITH_OPENGL=ON -D WITH_VTK=ON ..
cmake-gui
弹出的gui中,勾选WITH
WITH_FFMPEG
WITH_JASPER
WITH_JPEG
WITH_OPENEXR
WITH_PNG
WITH_TIFF
WITH_V4L
WITH_LIBV4L
WITH_GTK
编译,安装:
make
make install
修改环境变量:
gedit /etc/ld.so.conf.d/opencv.conf
#增加
/usr/local/lib
#保存关闭
ldconfig
gedit /etc/bash.bashrc
#增加
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH
#保存关闭
source /etc/bash.bashrc
这样,就完成了Ubuntu的OpenCV安装。
同交叉编译的OpenCV一样,我们也使用eclipse IDE来进行程序开发。
eclipse 的工程配置基本和交叉编译相同,只是不用选择交叉编译器,而是直接使用Linux系统中自带的G++编译器进行编译。
由于编译OpenCV时,选择了WITH_GTK,所以可以直接在使用诸如cvShowImage的命令实现图形界面的显示。