opencv.png

本文禁止转载

前言

  继上次完成FFmpeg的交叉编译之后,遂将交叉编译库移植到了全志A40开发板中,在Qt5 Demo中测试发现,RTSP 视频流无法播放,报一堆Qt 库错误,真是无语了。但是在Linux环境下,用FFmpeg 编译出来的测试样例却可以直接播放RTSP 视频流。经过一番查找资料发现,原来...第三方解码库编译时,需要加入QT 模块路径,这样在Qt环境中运行时,才能找到对应的库。了解了这个之后,我便放弃了重新编译FFmpeg的想法,因为有个更合适的图像、视觉解码库——OpenCV ,并且它自带了FFmpeg。

  这篇文章,主要记录的是OpenCV-Qt5的交叉编译实现,过程可谓非常艰辛曲折,坑太多了。。。


前期准备

环境

  • 宿主机环境:windows7 专业版
  • 宿主机环境: Windows7 64位 专业版
  • Ubuntu环境:Ubuntu 12.04
  • 内核版本: Linux 3.10
  • 交叉编译器:arm-linux-gnueabihf-
  • Ubuntu gcc/g++ : gcc version 4.8.4
  • cmake版本:cmake version 3.18.1

提前编译

一、交叉编译Qt5源码

  这一步是必须的,因为后面填写OpenCV-Qt 模块路径的时候,一定要指向这里,并且,务必注意是交叉编译,Ubuntu下若未指定编译器和平台,默认是编译Linux-x86版本的。这里交叉编译的篇幅很长,就不展开讲,google/百度很多教程,按照教程自行编译完成。

编译完成之后,需要建立一个Qt 环境的文件系统,我这里使用的是buildroot 来做的。不然后面OpenCV 环境依赖没法通过。

二、编译cmake-gui

  必须从源代码构建cmake-gui,在cmake源代码中其被打包为cmake-qt-gui,所以构建时须加入关键参数:--qt-gui
这里以cmake-3.18.1.tar.gz源码为例:

tar xvf cmake-3.18.1.tar.gz
cd cmake-3.18.1
./bootstrap
make
make install

先运行./bootstrap 进行一次预编译,并安装生成cmake,然后重启Ubuntu,返回刚才cmake目录,执行二次编译,这次是生成cmake-gui

cd cmake-3.18.1
./configure --qt-gui
make
make install

这里编译生成cmake-gui 的目的,是为了OpenCV 配置时,可以使用可视化界面进行配置参数,当然,也可以不进行这一步,但是不使用可视化界面的话,cmake 后面携带的参数会非常多,不过,也可以将参数整在一起写成一个脚本。

三、交叉编译zlib

zlib是提供数据压缩用的函式库,OpenCV 中,libpng 和FFmpeg 模块都会用到这个库,所以要提前交叉编译,不然编译时会卡在unchar char转换失败的错误,这里非常地莫名奇妙,明明未修改任何源码,可是未将这个库加入编译路径的话,转换失败的错误就会一直存在。

如下图所示:

error_.png

编译方法:
1、这里以zlib-1.2.11.tar.gz 源码包为例:

tar xvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
mkdir build
export CC=arm-linux-gnueabihf-gcc
./configure --prefix=$PWD/build
make
make install

编译完成之后,会在build目录下生成libz.so、libz.so.1、libz.so.1.2.11 这三个库。


编译OpenCV

首先去下载OpenCV 源码,这里以opencv-4.3.0.zip为例

tar xvf opencv-4.3.0.zip
cd opencv-4.3.0
mkdir build
cmake-gui

出现cmake-gui界面,分别填入源码路径和输出路径,然后点击Configure,在弹出的窗口中,选择Unix MakeFiles,并勾选指定交叉编译链进行编译。

如图:
cmake_config_cross.png

然后单击Next ,进入交叉编译链的配置。Operating System 填写为:Linux,而非 arm-linux,网上很多人写的是arm-linux,这里也是坑。C Compilers 选择Qt 库中的 arm-linux-gnueabihf-gcc,C++ Compilers 选择arm-linux-gnueabihf-g++。这里一定要使用Qt 环境中的交叉编译器,而非ubuntu 本地的gcc/g++编译器。

Target Root 选择 Qt 文件系统的程序执行路径,其路径在:~/buildroot/host/usr/bin 目录下。这里需要注意的是:除了先前的Qt交叉编译,还需要事先建立一个Qt环境的文件系统,不然这一步中的Target Root你没法填,这里坑惨了我...

cmake_config.png

设置完成,点击 Finsh 会自动寻找依赖。此时中间界面是一片爆红的,再次点击 Configure , cmake会逐项进行查找,并罗列未找到的依赖项目。

接下来,按需勾选需要用到的OpenCV 模块,我这里勾选了以下这些模块,非全部罗列

BUILD:

BUILD_JPEG
BUILD_PNG
BUILD_PACKAGE
BUILD_SHARED_LIBS
BUILD_TESTS
BUILD_opencv_apps
BUILD_opencvcalib3d
BUILD_opencv_core
BUILD_opencv_dnn
BUILD_opencv_features2d
BUILD_opencv_gapi
BUILD_opencv_highgui
BUILD_opencv_imgproc
BUILD_opencv_imgcodecs
BUILD_opencv_photo
BUILD_opencv_video


WITH:

WITH_FFMPEG
WITH_GSTREAMER
WITH_QT
WITH_JPEG
WITH_PNG
WITH_OPENCL
WITH_LAPACK
WITH_V4L

在勾选了WITH_QT 之后,还需将QT 的库执行路径填到到OpenCV 的编译依赖中,分别需要添加以下库路径执行选项:

  • Qt5_DIR
  • Qt5Core_DIR
  • Qt5Gui_DIR
  • Qt5Test_DIR
  • QT_MAKE_EXECUTABLE
  • QT5Network_DIR
  • QT5NetworkAuth_DIR
  • Qt5Concurrent_DIR
  • Qt5Widgets_DIR
  • QT5Multimedia_DIR
  • QT5MultimediaWidgets_DIR
  • Qt5OpenGL_DIR

这里的库路径是根据你的Qt 程序来选择对应的库,比如:我需要在Qt 程序中,调用OpenCV 库来播放一段RTSP 视频流,那么它就一定会用到 QT5Network、QT5Widgets、QT5Core、Qt5Gui等模块,其他同理。

Qt 库路径示例:~/buildroot/qt-everywhere-opensource-src-5.9.0/Qt-5.9.0/lib


待全部配置完成之后,点击 Configure ,并逐步排查依赖项的路径,以及相关参数的设置。直到不出现报错为止,如下图所示,显示Configration done 即表示初步配置没错。然后就可以点击 Generate ,生成 MakeFile 文件了。

opencv_cmake.png

以下是我的 Configure 配置生成的日志,供参考

Configure Log

========General configuration for OpenCV 4.3.0 ============

  Version control:               unknown

  Platform:
    Timestamp:                   2020-09-08T02:03:50Z
    Host:                        Linux 3.13.0-117-generic x86_64
    Target:                      Linux
    CMake:                       3.18.1
    CMake generator:             Unix Makefiles
    CMake build tool:            /usr/bin/make
    Configuration:               Release

  CPU/HW features:
    Baseline:
      requested:                 DETECT

  C/C++:
    Built as dynamic libs?:      YES
    C++ standard:                11
    C++ Compiler:                /你的Qt交叉编译链路径/buildroot/host/opt/ext-toolchain/bin/arm-linux-gnueabihf-g++  (ver 5.3.1)
    C++ flags (Release):         -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG  -DNDEBUG
    C++ flags (Debug):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -fvisibility-inlines-hidden -g  -O0 -DDEBUG -D_DEBUG
    C Compiler:                  /你的Qt交叉编译链路径/buildroot/host/opt/ext-toolchain/bin/arm-linux-gnueabihf-gcc
    C flags (Release):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -O3 -DNDEBUG  -DNDEBUG
    C flags (Debug):             -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -g  -O0 -DDEBUG -D_DEBUG
    Linker flags (Release):      -Wl,--gc-sections -Wl,--as-needed  
    Linker flags (Debug):        -Wl,--gc-sections -Wl,--as-needed  
    ccache:                      YES
    Precompiled headers:         NO
    Extra dependencies:          dl m pthread rt
    3rdparty dependencies:

  OpenCV modules:
    To be built:                 calib3d core dnn features2d flann gapi highgui imgcodecs imgproc objdetect photo stitching video
    Disabled:                    java_bindings_generator ml videoio world
    Disabled by dependency:      ts
    Unavailable:                 java js python2 python3
    Applications:                apps
    Documentation:               NO
    Non-free algorithms:         NO

  GUI: 
    QT:                          YES (ver ..)
      QT OpenGL support:         NO
    GTK+:                        NO
    OpenGL support:              NO

  Media I/O: 
    ZLib:                        build (ver 1.2.11)
    JPEG:                        build-libjpeg-turbo (ver 2.0.4-62)
    PNG:                         build (ver 1.6.37)
    JPEG 2000:                   build Jasper (ver 1.900.1)
    HDR:                         YES
    SUNRASTER:                   YES
    PXM:                         YES
    PFM:                         YES

  Video I/O:
    FFMPEG:                      NO
      avcodec:                   NO
      avformat:                  NO
      avutil:                    NO
      swscale:                   NO
      avresample:                NO
    GStreamer:                   NO
    v4l/v4l2:                    YES (linux/videodev2.h)

  Parallel framework:            pthreads

  Trace:                         YES (built-in)

  Other third-party libraries:
    Lapack:                      NO
    Custom HAL:                  NO
    Protobuf:                    build (3.5.1)

  OpenCL:                        YES (no extra features)
    Include path:                /root/opencv/opencv-4.3.0/3rdparty/include/opencl/1.2
    Link libraries:              Dynamic load

  Python (for build):            /usr/bin/python2.7

  Install to:                    /root/opencv/opencv-4.3.0/out
-----------------------------------------------------------------

Configuring done
Generating done

到这里,如果你全部按照上文指示的步骤,完成了所有的工具、路径的依赖问题,那直接执行 make 应该是不会再报错了

cd /root/opencv/opencv-4.3.0/build
make
make install

编译的时间非常久,我用4核CPU make -j4 编译了大约一上午,3个小时吧,也可能是因为我使用到的库比较多。

最终编译成功如图:
opencv_make.png

make install 安装成功如图:

opencv_make_install.png

最终成功生成了ARM平台的二进制文件,并生成了对应的库,如下图:

opencv_cross_succ.png

如上图所示,生成了bin、include、lib、share四个文件夹,这就是OpenCV交叉编译的库,将其导入到Qt的 buildroot文件系统中,再随系统镜像一起打包,即可以在Qt 开发环境中直接调用OpenCV 的API 接口了。


注意:我这里并未列出详细的报错信息,以及解决办法,因为我觉得没必要,每个人的环境,版本可能不一样,报错信息也不一定相同,所以与其浪费篇幅在讲报错信息上,不如把整体的编译思路理清楚,搞清楚编译顺序,相关依赖、变量设置,后面的报错自己一查也能找出来。



以上。

最后修改:2020 年 09 月 08 日
您的支持就是我持续更新的动力!