移植opencv2.4.2到tiny6410的实例

环境:

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


解决方法:
修改OpenCV-2.3.1/modules/flann/include/opencv2/flann/dist.h文件第63行的源码:{ return fabsl(x); }改为{ return fabs(x); }
其实就是删了个l这个字母。

然后再
make
当然,还有非常大概率遇到一下错误:
Linking CXX executable ../../bin/opencv_test_calib3d
../../lib/libopencv_core.so: undefined reference to `pthread_key_create'
../../lib/libopencv_core.so: undefined reference to `pthread_getspecific'
../../lib/libopencv_ts.so: undefined reference to `pthread_key_delete'
../../lib/libopencv_core.so: undefined reference to `pthread_once'
../../lib/libopencv_core.so: undefined reference to `clock_gettime'
../../lib/libopencv_core.so: undefined reference to `pthread_setspecific'
collect2: ld returned 1 exit status
make[2]: *** [bin/opencv_test_calib3d] Error 1
make[1]: *** [modules/calib3d/CMakeFiles/opencv_test_calib3d.dir/all] Error 2
make: *** [all] Error 2

解决方法:
修改opencv_arm目录下的CMakeCache.txt,CMAKE_EXE_LINKER_FLAGS原来为空,加上-lpthread -lrt,如下图:


注意:每次错误产生,经修改后,只要再次执行make命令就接着编译,

编译成功后,执行
sudo make intall
就会安装opencv。
将opencv安装到
/usr/local/arm     这个位置。

安装好之后,来尝试交叉编译一个例子试试。
我这里使用的是opencv中文官网中的例子。
只不过考虑到我目前是通过NFS,在 终端中使用minicom来运行omapl138中的linux,所以将里面涉及到窗口及显示的函数去掉了。

例子如下,命名为main.cpp:(功能是将一副彩色图片转换为灰度图)
[cpp]  view plain copy
  1. #include "cv.h"  
  2. #include "highgui.h"  
  3.   
  4. int main( int argc, char** argv )  
  5. {  
  6.   IplImage* pImg; //声明IplImage指针  
  7.   
  8.   //载入图像,强制转化为Gray  
  9.   if( argc == 3 &&  
  10.       (pImg = cvLoadImage( argv[1], 0)) != 0 )  
  11.     {  
  12.   
  13.       IplImage* pImg2 = cvCreateImage(cvGetSize(pImg),  
  14.                       pImg->depth,  
  15.                       pImg->nChannels);  
  16.       cvCopy(pImg, pImg2, NULL);  
  17.   
  18.       cvSaveImage(argv[2], pImg2);//把图像写入文件  
  19.   
  20.   
  21.       cvReleaseImage( &pImg ); //释放图像  
  22.       cvReleaseImage( &pImg2 ); //释放图像  
  23.       return 0;  
  24.     }  
  25.   
  26.   return -1;  
  27. }  

下面说一下我的编译方法。依然使用DVSDK中的交叉编译链。
我为了方便将main.cpp拷入/home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/bin文件夹,即交叉编译器所在文件夹
并且在终端中进入。直接
cd /home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/bin

在终端运行如下命令(此命令为手动输入库文件极其目录的方法):
./arm-arago-linux-gnueabi-gcc main.cpp -o main1 -I/usr/local/arm/include/opencv -I/usr/local/arm/include -L/usr/local/arm/lib -lpthread -ldl -lopencv_core -lrt -lopencv_highgui
然后出现了警告:
/home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/bin/../lib/gcc/arm-arago-linux-gnueabi/4.3.3/../../../../arm-arago-linux-gnueabi/bin/ld: warning: ../../lib/libopencv_core.so, needed by /usr/local/arm/lib/libopencv_highgui.so, not found (try using -rpath or -rpath-link)
/home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/bin/../lib/gcc/arm-arago-linux-gnueabi/4.3.3/../../../../arm-arago-linux-gnueabi/bin/ld: warning: ../../lib/libopencv_imgproc.so, needed by /usr/local/arm/lib/libopencv_highgui.so, not found (try using -rpath or -rpath-link)

这个问题是因为交叉编译器没有找到这两个库(网上是这么说的)。我将libopencv_core.so,libopencv_imgproc.so,这两个库拷贝到了
/home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/lib   中,即交叉编译器的lib中。
然后再运行编译命令。就ok了。没有任何错误和警告了。

这里要说明的是:
./arm-arago-linux-gnueabi-gcc main.cpp -o main1 -I/usr/local/arm/include/opencv -I/usr/local/arm/include -L/usr/local/arm/lib -lpthread -ldl -lrt -lopencv_core  -lopencv_highgui
这个命令中。-I后面都是头文件include目录。-L后面是库文件目录。而那些带 - 的参数,就是我们要用到的库文件,这个例子里我只用到了
libopencv_core.so和libopencv_highgui.so这两个库,所以就只有-lopencv_core -lopencv_highgui这两个。
要是程序用到了其他库,那么在参数后面添加就行了。

/*以下是更新部分
以上是编译程序的第一种方法,另外一种便是通过配置
/usr/local/lib/pkgconfig中的opencv.pc文件并使用  `pkg-config --cflags --libs opencv`  来进行编译

这种方法面去了输入一大堆配置参数的麻烦。建议使用这种方法

因为我在以前安装过PC版的正常的opencv,所以在/usr/local/lib/pkgconfig里会有opencv.pc这个文件。
如果以前没有安装过,可能就没有这个文件,可以尝试自己新建一个,应该也行。

首先 sudo gedit /usr/local/lib/pkgconfig/opencv.pc 
将第一行的
prefix=/usr/local  更改为
prefix=/usr/local/arm     这个目录在cmake配置的时候提到过。即arm的opencv的安装目录。
然后再在Libs里加入-lpthread -lrt。

下面将整个opencv.pc文件贴出。
[plain]  view plain copy
  1. # Package Information for pkg-config  
  2.   
  3. prefix=/usr/local/arm  
  4. exec_prefix=${prefix}  
  5. libdir=${exec_prefix}/lib  
  6. includedir_old=${prefix}/include/opencv  
  7. includedir_new=${prefix}/include  
  8.   
  9. Name: OpenCV  
  10. Description: Open Source Computer Vision Library  
  11. Version: 2.3.1  
  12. Libs: -L${libdir} -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_flann -lpthread -lrt  
  13. Cflags: -I${includedir_old} -I${includedir_new}  
保存了opencv.pc之后,建议将/usr/local/arm/lib  里的13个文件都复制进/home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/lib 中,
不然会出现类似与上面蓝色字体的警告。

进入/home/yr/ti-dvsdk_omapl138-evm_04_03_00_06/linux-devkit/bin目录,并运行命令
./arm-arago-linux-gnueabi-gcc `pkg-config --cflags --libs opencv` main.cpp -o main   

就ok了。
以上是更新部分*/


例子编译完啦。到底能不能在arm上运行,这个还要等板子在身边之后再测试了。结果会在此文更新。
转自:http://blog.csdn.net/yr119111/article/details/7732336

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值