环境:
Ubuntu10.04
OK6410开发板
ARM Linux3.01系统
QT4.7.1
OpenCV-2.0.0
arm-linux-g++ 4.3.2 / arm-linux-gcc 4.3.2
CMake-gui 2.8.0
(建议先参考我的另外一篇博文《Ubuntu上安装Opencv-2.0.0》)
OpenCV2.0.0交叉编译过程:
1、在usr/local新建文件夹
# mkdir opencv
把下载的OpenCV-2.0.0.tar.bz2解压到 usr/local/opencv 目录下
2、然后在usr/local/opencv 新建一个 opencv-arm 文件夹,作为CMake编译arm版本的工作目录
# mkdir opencv-arm
如下图所示:
3、在终端里调出CMake gui界面:
# cmake-gui
按照下图方式选择源码目录和build目录
然后点击Configure按钮,保持generator为Unix Makefiles,选择Specify options for cross-compiling,点击Next
按照如下方式配置:
注:/usr/local/arm/4.3.2 为交叉编译工具 arm-linux-g++/gcc 的所在包含文件夹(在bin文件夹里面)
然后点击 “Finish” 按钮;
修改默认配置,默认安装目录为/usr/local,但我想对它统一归类,所以我在/usr/local/arm/4.3.2/lib目录下新建了一个opencv文件夹,在Cmake-gui里修改CMAKE_INSTALL_PREFIX变量改为/usr/local/arm/4.3.2/lib/opencv/
(另外,如果没有安装tiff图像的支持,请去掉WITH_TIFF)
然后点击Generate按钮生成Makefile;
4、在终端界面中,进入目录/usr/local/opencv/opencv-arm,运行make编译opencv
编译时发现如下错误:
Linking CXX executable ../../bin/opencv_createsamples
../../lib/libcxcore.so: undefined reference to `clock_gettime’
../../lib/libcxcore.so: undefined reference to `pthread_key_create’
../../lib/libcxcore.so: undefined reference to `pthread_getspecific’
../../lib/libcxcore.so: undefined reference to `pthread_setspecific’
原因是cmake不认识我定义的arm-linux系统标记,没有加上库pthread和rt的链接选项
此时需要修改CMakeCache.txt,CMAKE_EXE_LINKER_FLAGS原来为空,加上-lpthread -lrt,如下图:
重新make编译,错误消除,编译成功之后的界面如下:
5、然后运行make install,将opencv生成的库和头文件安装到目录/usr/local/arm/4.3.2/lib/opencv/,结果如下:
6、把这5个 .so 库文件拷贝到ARM板系统中的 /lib 目录下面:(如下是添加之后的截图)
7、下来就是编写验证程序了:
首先得确保摄像头在ARM板上的使用是正常的,具体情况请查阅我的另外一篇博文:
《摄像头在liunx上的QT显示和OK6410 ARM开发板上的使用》
在这篇文章里我曾提到过要使用opencv,但是摄像头出来的是UVC格式,所以我要走一个图像转换流程:UVC转QImage转IplImage;
8、还是那个简单思路:现在ubuntu PC上实现,然后再移植至ARM上;
具体工程代码下载请看附录。
主要涉及opencv的代码如下:
void Widget::paintEvent(QPaintEvent *) { uchar * pImgBuf; unsigned int len; camReturn = m_camera->get_frame((void **)&pImgBuf,&len); convert_yuv_to_rgb_buffer(pImgBuf,imgBuf,image_width,image_height); frame->loadFromData((uchar *)imgBuf,/*len*/image_width * image_height * 3 * sizeof(char)); IplImage* src = QImageToIplImage(frame); if (!src) { printf("img error!"); return; } //更改图像大小(后期对人脸检测时间控制会有很大帮助) double sizeScale = imgSizeScaleSmall; CvSize img_cvsize; img_cvsize.width = src->width * sizeScale; img_cvsize.height = src->height * sizeScale; IplImage* dst = cvCreateImage(img_cvsize, src->depth, src->nChannels); cvResize(src, dst, CV_INTER_LINEAR); //opencv函数更改图片大小 // cvSaveImage("jason.jpg", src); //ARM对opencv的highgui支持极其差,这个函数不能使用 //更改图像大小,清晰度会下降 sizeScale = imgSizeScaleBig; img_cvsize.width = dst->width * sizeScale; img_cvsize.height = dst->height * sizeScale; IplImage* img = cvCreateImage(img_cvsize, dst->depth, dst->nChannels); cvResize(dst, img, CV_INTER_LINEAR); QImage qimage = QImage((uchar *)img->imageData, img->width,img->height, image_Format); //IplImage为BGR格式,QImage为RGB格式,所以要交换B和R通道显示才正常 //可以用OpenCV的cvConcertImage函数交换,也可以用QImage的rgbSwapped函数交换; qimage = qimage.rgbSwapped(); ui->m_imgLabel->setPixmap(QPixmap::fromImage(qimage)); camReturn = m_camera->unget_frame(); cvReleaseImage(&img); //释放图片内存 cvReleaseImage(&src); }
其中,QImage转IplImage的处理函数如下:(在此感谢此篇博文的帮助:关于QImage和IplImage之间转换的实现)
IplImage* Widget::QImageToIplImage(const QImage * qImage) { int width = qImage->width(); int height = qImage->height(); CvSize Size; Size.height = height; Size.width = width; IplImage *IplImageBuffer = cvCreateImage(Size, IPL_DEPTH_8U, 3); for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { QRgb rgb = qImage->pixel(x, y); cvSet2D(IplImageBuffer, y, x, CV_RGB(qRed(rgb), qGreen(rgb), qBlue(rgb))); } } return IplImageBuffer; }
运行结果如下图所示:
这里得注意一个问题,就是摄像头的名词,我的ubuntu上的名称为:/dev/video0,在ARM上为:/dev/video2;注意修改此处的代码
注:
对于编译时出现的缺少或者不能打开opencv相应的文件或库,原因是你的Makefile里面的环境路径配置有问题,不要把我的工程直接不做修改就拿来编译,会出问题的,(不过编译出来的最终程序也许可以使用)因为我安装的opencv路径可能和你的不一样,具体修改方式请打开Makefile文件,参照原来的内容进行修改。
附录:
1、Opencv2.0在PC Ubuntu上的应用
2、Opencv2.0在ARM Ok6410 linux3.0.1上的应用
参考文献:
【1】mini6410成功移植OPENCV-2.0.0实现人脸检测 http://blog.csdn.net/gfocean/article/details/6341155
【2】关于QImage和IplImage之间转换的实现 http://blog.csdn.net/gfocean/article/details/6440844
==========================================================================================================================================
更新:测试结果就是,本文中使用的main.cpp这个例子,在SBC3730这块板子上运行成功!
所以我估计在omapl138上也会成功。
更新:更新了 编译命令 `pkg-config --cflags --libs opencv` 的更改以及使用方法
首先,opencv是个好东西,对于我这样的菜鸟,来说,既是好用的工具,也是最好的学习资料。
此次移植是在ubuntu12.04 32位,针对omapl138的arm端来进行的。(其实只要是arm应该都一样)
本来呢,是想移植到c6748的。但是我感觉这个对我来说难度有点大。。而网上对于移植arm的资料也很多。
所以先移植到arm再说把。
不过还是希望有高手能给我指导一下,将opencv移植至c6748该怎么做。在CCS里或者linux里都行。因为我想使用gpp+dsp模式。将算法做成包,然后跑在dsp端。
此文有一部分综合了网上多人的方法,也有自己在进行移植时的经验。
当然,移植的效果还没有给出,因为板子不在身边,无法进行测试。等有板子了,再进行测试,确定是否移植成功。
结果会在本文更新。
好。先下载opencv。
下载OpenCV 2.3.1 , http://sourceforge.net/projects/opencvlibrary/files/
然后解压
tar xvf OpenCV-2.3.1.tar.bz2
在此要说明的是,此次移植是在前面omapl138的DVSDK都安装并且配置好的情况下进行的。
我的DVSDK安装路径是/home/yr/ti-dvsdk_omapl138-evm_04_03_00_06
我使用omapl138中的交叉编译链。
即交叉编译链存在于
/home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/bin 这个目录中。
刚才解压了opencv,现在在你的工作目录里建立一个新的文件夹opencv_arm。名称和具体路径看个人爱好。
然后进入终端运行cmake-gui。如果以前没有安装过,终端会提示你使用apt-get命令安装。
安装好之后就可以运行了。
cmake-gui
之后出现下面的界面
选择source code目录 /home/yr/OpenCV-2.3.1
以及build目录 /home/yr/opencv_arm
点configure
然后按照下图中所选择的:
generator为Unix Makefiles,选择Specify options for cross-compiling
next之后,在下图这几个位置填写路径
Operating System填写arm-arago-linux
Compilers里,C选择 /home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/bin/arm-arago-linux-gnueabi-gcc
C++选择 /home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/bin/arm-arago-linux-gnueabi-g++
可以看出来我都是用的DVSDK中的目录。
Target Root选择 /home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit
然后finish。
cmake便返回下图
图中红色部分是我们可以配置的位置。这里要提醒一下的是,更改完配置之后,记得再点一下左下角的configure按钮。不然更改不会应用。
具体的配置当然是根据需要来进行的。
这里要说明一下:
因为在之前安装过opencv 是x86版本的,即在PC上使用的,所以/usr/local中的include以及lib都有opencv的相关库存在,
所以为了方便自己使用以及不出问题,建议将arm版的opencv的安装目录更改一下,
我将下图位置的CMAKE_INSTALL_PREFIX后面的/usr/local改成了
/usr/local/arm
同时,我还更改了一些配置,却掉了一些我不用的功能,以及导致编译出错的功能。比如
WITH_CUDA是我用不到的功能,
WITH_TIFF是因为我在编译的时候出错了,
然后我去掉了这个功能。(我在网上看到,有人没有去掉这个功能也能编译,可能是因为我系统里缺少什么东西吧?)
配置更改完了之后点一下左下角的configure。然后再点generate.
到这里,cmake的工作做完了。
从终端进入 opencv_arm这个文件夹然后
make。
但是,肯定会出错。
必然会遇到的错误如下:
/home/yr/OpenCV-2.3.1/modules/flann/include/opencv2/flann/dist.h: In function 'T cvflann::abs(T) [with T = long double]':
/home/yr/OpenCV-2.3.1/modules/flann/include/opencv2/flann/dist.h:63: error: 'fabsl' was not declared in this scope
make[2]: *** [modules/flann/CMakeFiles/opencv_flann_pch_dephelp.dir/opencv_flann_pch_dephelp.obj] Error 1
make[1]: *** [modules/flann/CMakeFiles/opencv_flann_pch_dephelp.dir/all] Error 2
make: *** [all] Error 2