经过这么多天的挣扎终于把Opencv移植的问题搞定了。先说明一下,我之前已经成功移植了Opencv2.4.8(目前最新版本,照着论坛教程做其实很简单),且通过了各种测试。但是,由于我想之后在zedboard上处理视频,所以要添加ffmpeg第三方库(能够支持avi视频),并且希望能够支持除bmp之外的其它图片格式(jpeg和png)。那么我就需要在移植Opencv的时候集成这些第三方库。看似很简单,但是书上根本没有交待如何集成,书上甚至让我们把WITH_XXX都给勾选掉,所以自己动手丰衣足食,在论坛上和网上找了一周的帖子和教程,自己搞了无数遍的实验。经验就是:不要绝对相信任何一个教程,不是他们在骗你,而是你们的微小环境差异就可能导致很大的不同,最后给大家奉献一个自己验证通过的教程,希望对遇到同样问题的你有帮助。废话不多说,开始!

一、PC上安装Opencv

    安装环境是:Ubuntu13.10(内核是3.3的),Opencv-2.4.3

    由于在计算机上安装,所以很简单,只需要将我们集成的库先利用apt-get来安装,到最后安装Opencv的时候能够找到ffmpeg或其它库的依赖库就好了。这里我把需要安装的库列举一下,有些可能不是必须的,本人对依赖库研究也不是很深:

  • apt-get install zlib1g-dev
  • apt-get install libjpeg8-dev
  • apt-get install libpng12-dev
  • apt-get install libx264-dev
  • apt-get install libxvidcore-dev
  • apt-get install libtiff-dev
  • apt-get install ffmpeg
  • apt-get install libv4l-dev
  • apt-get install libgtk2.0-dev
  • apt-get install build-essential libavcodec-dev libavformat-dev libswscale-dev libjasper-dev cmake  cmake-curses-gui cmake-qt-gui
 

    最后一个命令安装了很多库,但是有可能输入进去会报错,这也是依赖库的问题。解决方法就是一个一个的安装,这样每个库安装都会检测依赖关系,要么修复要么下载依赖库就不会出现依赖的问题了。

    下面就是讲Opencv的压缩包进行解压,我解压到了/opt/zedboard/opencv_pc/下,当然你也可以根据自己的需要自定义,因为这只不过是一个编译的目录,最终都是要安装到/usr/local下的。解压之后进入到OpenCV-2.4.3的文件夹,创建一个build文件夹,在build文件夹下执行:

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ../

因为不是交叉编译,所以不用设置编译器,后面的PREFIX是在设置安装目录,一定不能把最后的“ ../”给省略了!然后利用我们安装的cmake-gui命令,在图形界面下对Opencv进行配置。

cmake-gui

此时会弹出一个图形界面,选择路径,一个是Opecv-2.4.3,一个是下面的Build,上面需要我们修改的只是最后面的WITH_XXX,根据我们安装的库,我们选择如下图所示:

选择完后,点击Configure,之后会报出一些消息,尽管会提示你有一些文件找不到,但是不用管它,再点击Generate,然后关闭对话框。最后输入:

make 

make install

    注意,在make的时候需要很久,但是一定要关注是否100%的编译通过了,我有些时候在等待的时候就去做别的事情的,回来的时候没有看有没有报错,直接就make install。实际上,如果中间编译出错,那么我只安装了部分的库,而且还不能用。正确编译的最后几行代码应该如下图所示:

 

二、Opencv+ffmpeg的交叉移植

单纯的Opencv移植在论坛里面有好多教程,大家可以参考。我这里是只介绍我的这种“另类”方法,在移植第三方库的时候引用了thinki_cao的博客,小辉辉同学的文章给了我很大的帮助。本来想在这里给出一个链接,但是很遗憾,他前些天不小心把文章弄的不可见了。所以在他的博客里面找不到那篇文章了,所以在交叉编译的第三方库的内容我就总结在我的博客里面了,但是类似的文章还有很多,给出一个链接

http://www.linuxidc.com/Linux/2013-08/89293p2.htm

下面就是我的总结:

首先,说明一些Opencv+ffmpeg移植过程中的关键问题。一共有两个,一个是要自己交叉编译ffmpeg的依赖库,这个在其它的论坛教程中也有涉及,但是比较繁琐,我将最简单的交叉编译方法给大家做了个总结。第二个,也是我一直在解决的问题就是V4l的问题。因为我们用的zedboard使用的是3.3的Linux内核,在这个内核中已经不支持V4l1了,而是支持V4l2。我的PC使用的Ubuntu13.10也是3.3的内核,按理说应该没有什么问题。但是万恶的OpenCV在交叉编译的时候,必须要同时支持V4l1/V4l2才能够正常编译通过。我想这可能是OpenCV对于V4l的依赖来自于两个版本吧,这个只是个人猜想。所以,你会发现即使你选择了WITH_V4l但是在移植之后仍然无法使用相关函数。下面是我的方法,仅作为参考:

首先我安装了CetOS-6.5,为什么用这个?因为它是2.6的内核,除此之外最重要的是在/usr/include/linux/路径下有Videodev.h和Videodev2.h这两个文件。这个是非常关键的。我试过同样是2.6内核的Ubuntu系统,都只是有Vediodev2.h,也就是说只支持V4l2。但是至于为什么CentOS有两个文件我也不是很清楚,只是我询问了一个大神,他一次就编译通过了,细问才知道人家用的是“神奇”的CentOS。好了,不废话了,安装虚拟机之后要重新建立交叉编译环境。跟Ubuntu一样,连bash都不用改,直接安装就行了,然后添加必要的路径,别忘了source加载。

下面是重点,在/opt/zedboard/opencv_zed/下创建一个install和opencv-lib两个文件夹。前者是用来作为OpenCV移植库的安装目录,后者则是用来安装交叉编译的第三方库。

OpenCV交叉编译时各个库的依赖关系:
OpenCV
        |--------zlib                
        |--------jpeg
        |--------libpng
                    |--------zlib 
        |--------tiff
                    |--------zlib 
        |--------ffmpeg
                    |--------x264
                    |--------xvidcore
其中各个源码包之间的依赖关系还是有一定的讲究的,否则很容易编译通不过,这里建议下载较新的稳定版进行交叉编译,下面列出本人已经成功编译通过的源码包版本:
ffmpeg-0.10.11
tiff-4.0.3
jpeg-8d
x264-snapshot-20120528-2245-stable
libpng-1.5.14
xvidcore-1.3.2
OpenCV-2.4.3
zlib-1.2.7
 
首先建立一个路径:
export ZYNQ_CV_INSTALL=/opt/zedboard/opencv_zed/opencv-lib    #OpenCV第三方库交叉编译库的安装路径
 
依赖库的配置以及注意事项如下:
zlib-1.2.7
export CC=arm-xilinx-linux-gnueabi-gcc
./configure --prefix=$ZYNQ_CV_INSTALL --shared
make
make install
注意:这里需要事先声明CC变量,zlib中没有配置--host之类的选项,第一步的时候可能会报出一个错误,如下图,这个没有关系,我们可以继续进行。
 
 
jpeg-8d
./configure --prefix=$ZYNQ_CV_INSTALL --host=arm-xilinx-linux-gnueabi --enable-shared
make
make install
 
libpng 1.5.14
./configure --prefix=$ZYNQ_CV_INSTALL --host=arm-xilinx-linux-gnueabi --enable-arm-neon --enable-shared --with-pkgconfigdir=$ZYNQ_CV_INSTALL/lib/pkgconfig LDFLAGS=-L$ZYNQ_CV_INSTALL/lib CPPFLAGS=-I$ZYNQ_CV_INSTALL/include
make
make install
注意:libpng编译过程中可能会用到zlib之类的库,因此我们需要添加额外的LDFLAGS和CFLAGS变量,更多的信息可以通过./configure --help进行参考

 
x264-snapshot-20120528-2245-stable
./configure --host=arm-linux --cross-prefix=arm-xilinx-linux-gnueabi- --enable-shared   --disable-asm  --prefix=$ZYNQ_CV_INSTALL
make
make install
 
xvidcore-1.3.2
cd build/generic
./configure --prefix=$ZYNQ_CV_INSTALL --host=arm-xilinx-linux-gnueabi  --disable-assembly
make
make install
注意:xvidcore的编译中可能会调用arm指令集,但是在ZEDBoard上的ARM v7指令集的CortexA9核心只能支持Thumb/Thumb2,因此这里需要禁用汇编选项--disable-assembly
 
tiff-4.0.3
./configure --prefix=$ZYNQ_CV_INSTALL --host=arm-xilinx-linux-gnueabi --enable-shared LDFLAGS=-L$ZYNQ_CV_INSTALL/lib CFLAGS=-I$ZYNQ_CV_INSTALL/include 
make
make install
注意:tiff编译过程中可能会用到zlib之类的库,因此我们需要添加额外的LDFLAGS和CFLAGS变量,更多的信息可以通过./configure --help进行参考

ffmpeg-0.10.3 //注意,这里一定要选ffmpeg-0.X的版本,1,2版本虽然新,但是会生成一个time.h文件,与Linux系统内的time.h会冲突,导致在交叉编译的时候出错
./configure --prefix=$ZYNQ_CV_INSTALL --enable-shared   --disable-static --enable-gpl --enable-cross-compile --arch=arm --disable-stripping --target-os=linux --enable-libx264 --enable-libxvid --cc=arm-xilinx-linux-gnueabi-gcc --enable-swscale --extra-cflags=-I$ZYNQ_CV_INSTALL/include --extra-ldflags=-L$ZYNQ_CV_INSTALL/lib --disable-asm
make
make install
注意:ffmpeg编译过程中可能会用到x264,xvid,zlib等之类的库,因此我们需要添加额外的LDFLAGS和CFLAGS变量,更多的信息可以通过./configure --help进行参考,另外这里的--disable-asm与xvidcore中的--disable-assembly的作用是一样的,否则也是不能编译通过的
 
至此,第三方库已经都安装在了opencv-lib文件夹下。下面进行Opencv的交叉移植过程。将OpenCV2.4.3解压到opencv-zed/下, 进入源码目录再新建一个build文件夹并进入build文件夹目录:

cd OpenCV-2.4.3

mkdir build

cd build 

在当前目录下新建toolchain.cmake文档,内容如下:
###########user defined#############
set( CMAKE_SYSTEM_NAME Linux )
set( CMAKE_SYSTEM_PROCESSOR arm )
set( CMAKE_C_COMPILER arm-xilinx-linux-gnueabi-gcc )
set( CMAKE_CXX_COMPILER arm-xilinx-linux-gnueabi-g++ )
###########user defined#############
set( CMAKE_FIND_ROOT_PATH "/opt/zedboard/opencv_zed/opencv-lib" )
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
######################################
注意:最后的四行是用于交叉编译情况下依赖库查找路径以及查找模式的,它对于cmake能否找到依赖库来说非常重要
下面就是重点了,我们需要将我一开始说的videodev.h这个文件拷贝到交叉编译器相应的目录下:
 cp /usr/include/linux/videodev.h /root/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/arm-xilinx-linux-gnueabi/libc/usr/include/linux/
这样一来,在后面的编译过程中就能够找到videodev.h这个文件了。 然后进行cmake的配置:
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake ../
cmake-gui
跟在PC上一样进行配置,这里需要修改PREFIX对应的安装路径,我选择的是/opt/zedboard/opencv_zed/install,然后再选择需要添加的库,如下图:
点击Configure,下面会打出各种信息,我把我的信息帖在下面,各位可以比对一下是不是哪个地方还有错误“
 
Detected version of GNU GCC: 46 (406)
Could NOT find Jasper  (missing:  JASPER_LIBRARY JASPER_INCLUDE_DIR)
checking for module 'libv4l1'
  package 'libv4l1' not found
Looking for linux/videodev.h
Looking for linux/videodev.h - found
Looking for linux/videodev2.h
Looking for linux/videodev2.h - found
checking for module 'libavcodec'
  package 'libavcodec' not found
checking for module 'libavformat'
  package 'libavformat' not found
checking for module 'libavutil'
  package 'libavutil' not found
checking for module 'libswscale'
  package 'libswscale' not found
Looking for libavformat/avformat.h
Looking for libavformat/avformat.h - found
Looking for ffmpeg/avformat.h
Looking for ffmpeg/avformat.h - not found
Could NOT find PythonLibs  (missing:  PYTHON_LIBRARIES PYTHON_INCLUDE_PATH)

General configuration for OpenCV 2.4.3 =====================================

  Platform:
    Host:                        Linux 2.6.32-431.el6.i686 i686
    Target:                      Linux arm
    CMake:                       2.6.4
    CMake generator:             Unix Makefiles
    CMake build tool:            /usr/bin/gmake
    Configuration:               Release

  C/C++:
    Built as dynamic libs?:      YES
    C++ Compiler:                /root/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/bin/arm-xilinx-linux-gnueabi-g++  (ver 4.6.1)
    C++ flags (Release):         -W -Wall -Werror=return-type -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -O3 -DNDEBUG  -DNDEBUG
    C++ flags (Debug):           -W -Wall -Werror=return-type -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -g  -O0 -DDEBUG -D_DEBUG -ggdb3
    C Compiler:                  /root/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/bin/arm-xilinx-linux-gnueabi-gcc
    C flags (Release):           -W -Wall -Werror=return-type -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -O3 -DNDEBUG  -DNDEBUG
    C flags (Debug):             -W -Wall -Werror=return-type -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -g  -O0 -DDEBUG -D_DEBUG -ggdb3
    Linker flags (Release):
    Linker flags (Debug):
    Precompiled headers:         YES

  OpenCV modules:
    To be built:                 core imgproc flann highgui features2d calib3d ml video objdetect contrib nonfree photo legacy gpu stitching ts videostab
    Disabled:                    world
    Disabled by dependency:      -
    Unavailable:                 androidcamera java ocl python

  GUI: 
    QT 4.x:                      NO
    GTK+ 2.x:                    NO
    GThread :                    NO
    GtkGlExt:                    NO
    OpenGL support:              NO

  Media I/O: 
    ZLib:                        /opt/zedboard/opencv_zed/opencv-lib/lib/libz.so (ver 1.2.7)
    JPEG:                        /opt/zedboard/opencv_zed/opencv-lib/lib/libjpeg.so (ver 80)
    PNG:                         /opt/zedboard/opencv_zed/opencv-lib/lib/libpng.so (ver 1.5.14)
    TIFF:                        /opt/zedboard/opencv_zed/opencv-lib/lib/libtiff.so (ver 42 - 4.0.3)
    JPEG 2000:                   build (ver 1.900.1)
    OpenEXR:                     build (ver 1.7.1)

  Video I/O:
    DC1394 1.x:                  NO
    DC1394 2.x:                  NO
    FFMPEG:                      NO
      codec:                     NO
      format:                    NO
      util:                      NO
      swscale:                   NO
      gentoo-style:              YES
    GStreamer:                   NO
    OpenNI:                      NO
    OpenNI PrimeSensor Modules:  NO
    PvAPI:                       NO
    GigEVisionSDK:               NO
    UniCap:                      NO
    UniCap ucil:                 NO
    V4L/V4L2:                    YES/YES
    XIMEA:                       NO
    Xine:                        NO

  Other third-party libraries:
    Use TBB:                     NO
    Use OpenCL:                  NO
    Use Eigen:                   NO

  Python:
    Interpreter:                 /usr/bin/python2.6 (ver 2.6.6)

  Documentation:
    Build Documentation:         NO
    Sphinx:                      NO
    PdfLaTeX compiler:           NO

  Tests and samples:
    Tests:                       YES
    Performance tests:           YES
    Examples:                    NO

  Install path:                  /opt/zedboard/opencv_zed/install

  cvconfig.h is in:              /opt/zedboard/opencv_zed/OpenCV-2.4.3/build
-----------------------------------------------------------------

Configuring done
 
我红的标注的地方是特别需要校对的,如果V4l1/V4l2对应的是NO/YES,那说明Viedodev.h这个文件没找到。点击Generate。然后关闭对话框。
 
make
make install
安装之后,不要着急,还没有大功告成。我们可以利用历程给出的edge_detection.cpp来对交叉编译进行验证。将路径移到edge_detection.cpp所在文件夹下,然后执行:
arm-xilinx-linux-gnueabi-g++  -I /opt/zedboard/opencv_zed/install/include -I /opt/zedboard/opencv_zed/install/include/opencv -L /opt/zedboard/opencv_zed/install/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_flann ./edge_detection.cpp -o ./edge_detectioni.o
发现,报了很多错,不要着急。仔细一看是在交叉工具链中没有找到第三方库,所以需要将opencv-lib中的各个库文件,拷贝我们的安装文件夹install下(拷贝到交叉工具链下也可以,不过移植过去还是找不到库,所以为了方便之后镜像制作和移植,就拷贝到install下最好):
 
 cp -r /opt/zedboard/opencv_zed/opencv-lib/* /opt/zedboard/opencv_zed/install/
这样就将刚刚编译的第三方库加到了交叉编译工具链中。再一次执行上面的代码,成功编译出edge_detectioni.o。可以查看一下编译出来的文件,可以看到是我们想要的ARM平台执行文件。
这里有个问题,为什么编译出来的是2.6内核执行的文件?Zed不是支持3.3内核的吗?我用交叉编译工具应该是编译出来3.3内核的执行文件啊。我还是初学者,各位可以帮我解决一下疑问。
 
 
 
我们目前已经算是成功了。但是我不想用两个PC机啊!所以我把opencv_zed这个文件夹压缩打包转移到了Ubuntu13.10的虚拟机上!在同样了路径下解压,跟之前的路径保持一样。然后同样利用交叉编译指令进行.cpp文件的交叉编译。成功!说明,尽管CentOS6.5与Ubuntu13.10的内核不同,但是文件神马的都是通用的,不愧都是Linux的孪生兄弟。
 
制作镜像之后挂在到文件系统中,我选择的是/usr/local/这个路径,具体步骤:

制作镜像的方法:OpenCV库:

dd if=/dev/zero of=cv_lib.img bs=1M count=120//这里的count与bs组合起来表示制作120M的镜像,具体可以根据实际链接库总的大小来设置count 

mkfs.ext4 -F cv_lib.img

chmod 777 cv_lib.img  

mount cv_lib.img -o loop /mnt

cp -rf $ZYNQ_CV_INSTALL/* /mnt   

umount /mnt

在开发板上跑程序,发现不行,原来是缺少了stdc++的库,因此需要将交叉编译工具下的stdc++库拷贝到镜像中来:

cp /root/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/arm-xilinx-linux-gnueabi/libc/usr/lib/libstdc++.so* /opt/zedboard/opencv_zed/install/lib

重新制作镜像,然后在zed上运行程序,结果如下图:

说明这三种图片格式都是支持的,移植成功。对于是否支持V4l,我也做了验证,在zed上用Qt+Opencv实现了USB摄像头图像的采集,没有用到超全天晴的方法,完全是依赖Opencv的视频接口实现的。

希望上面的方法能够对你有帮助。

转载网站: http://www.eefocus.com/beiyangguangdian/blog/14-03/302119_52e49.html