0%

基于QT5编译OpenCV3,支持Python3

[相关链接]github opencv
opencv_contrib
pyenv

安装 pyenv

  • 详细安装参照pyenv README.
1
2
3
4
5
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ exec "$SHELL"
$ pyenv install 3.6.5 # 安装python 3.6.5 版本

编译 OpenCV3

  • 如果要编译extra_modules ,要与 opencv是同版本号,不然会出现奇奇怪怪的编译错误,这里都选3.4.1版本号
1
2
$ wget -c https://github.com/opencv/opencv_contrib/archive/3.4.1.tar.gz
$ tar xvf 3.4.1.tar.gz
  • 或者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
$ git clone https://github.com/opencv/opencv
$ git checout -b 3.4.1 # checkout 一个 Release 版本.
# 或者下载源码包
$ wget -c https://github.com/opencv/opencv/archive/3.4.1.tar.gz
$ cd opencv && mkdir build && cd build
$ cmake
-D CMAKE_PREFIX_PATH=/fullpath/Qt5.7/5.7/gcc_64 # 本机 QT5 的安装位置
-D CMAKE_INSTALL_PREFIX=/fullpath/opencv-build-3.x-qt5-py3
-D WITH_QT=ON # QT 与 GTK 只能二选 一
-D WITH_V4L=ON
-D BUILD_TESTS=OFF
-D WITH_TBB=ON
-D INSTALL_C_EXAMPLES=ON
-D INSTALL_PYTHON_EXAMPLES=ON
-D WITH_OPENMP=ON
-D WITH_OPENEXR=ON
-D WITH_UNICAP=ON
-D BUILD_PYTHON_SUPPORT=ON
-D BUILD_opencv_python3=ON
-D PYTHON_DEFAULT_EXECUTABLE=$HOME/.pyenv/versions/3.6.5/bin/python3.6m
-D PYTHON_INCLUDE_DIRS=$HOME/.pyenv/versions/3.6.5/include/python3.6m
-D PYTHON_EXECUTABLE=$HOME/.pyenv/versions/3.6.5/bin/python3.6
-D PYTHON_LIBRARY=$HOME/.pyenv/versions/3.6.5/lib/libpython3.6m.so.1.0
-D WITH_OPENGL=ON ../

[...]
-- GUI:
-- QT: YES (ver 5.7.0)
-- QT OpenGL support: YES (Qt5::OpenGL 5.7.0)
-- GTK+: NO
-- OpenGL support: YES (/usr/lib/x86_64-linux-gnu/libGLU.so /usr/local/lib/libGL.so)
-- VTK support: YES (ver 6.3.0)
--
-- Media I/O:
-- ZLib: /usr/lib/x86_64-linux-gnu/libz.so (ver 1.2.8)
-- JPEG: /usr/lib/x86_64-linux-gnu/libjpeg.so (ver )
-- WEBP: /usr/lib/x86_64-linux-gnu/libwebp.so (ver encoder: 0x0209)
-- PNG: /usr/lib/x86_64-linux-gnu/libpng.so (ver 1.6.28)
-- TIFF: /usr/lib/x86_64-linux-gnu/libtiff.so (ver 42 / 4.0.8)
-- JPEG 2000: /usr/lib/x86_64-linux-gnu/libjasper.so (ver 1.900.1)
-- OpenEXR: build (ver 1.7.1)
--
-- Video I/O:
-- DC1394: NO
-- FFMPEG: YES
-- avcodec: YES (ver 57.89.100)
-- avformat: YES (ver 57.71.100)
-- avutil: YES (ver 55.58.100)
-- swscale: YES (ver 4.6.100)
-- avresample: YES (ver 3.5.0)
-- GStreamer: NO
-- UniCap: NO
-- UniCap ucil: NO
-- libv4l/libv4l2: NO
-- v4l/v4l2: linux/videodev.h linux/videodev2.h
-- gPhoto2: YES
--
-- Parallel framework: OpenMP
--
-- Trace: YES (with Intel ITT)
--
-- Other third-party libraries:
-- Intel IPP: 2017.0.3 [2017.0.3]
-- at: /fullpath/opencv-3.4.1/build-qt5-py3/3rdparty/ippicv/ippicv_lnx
-- Intel IPP IW: sources (2017.0.3)
-- at: /fullpath/opencv-3.4.1/build-qt5-py3/3rdparty/ippicv/ippiw_lnx
-- Lapack: NO
-- Eigen: YES (ver 3.3.2)
-- Custom HAL: NO
-- Protobuf: build (3.5.1)
--
-- NVIDIA CUDA: NO
--
-- OpenCL: YES (no extra features)
-- Include path: /fullpath/opencv-3.4.1/3rdparty/include/opencl/1.2
-- Link libraries: Dynamic load
--
-- Python 3:
-- Interpreter: /home/michael/.pyenv/shims/python3 (ver 3.6.5)
-- Libraries: /home/michael/.pyenv/versions/3.6.5/lib/libpython3.6m.so.1.0 (ver 3.6.5)
-- numpy: /home/michael/.pyenv/versions/3.6.5/lib/python3.6/site-packages/numpy/core/include (ver 1.14.2)
-- packages path: lib/python3.6/site-packages
--
-- Python (for build): /home/michael/.pyenv/versions/3.6.5/bin/python3.6m
[...]

$ make -j4
$ make install

ERROR

1
2
3
4
CMake Error at /home/michael/3TB-DISK/SOFT-LIBRAR/opencv_contrib/modules/datasets/CMakeLists.txt:5 (ocv_append_source_files_cxx_compiler_options):
Unknown CMake command "ocv_append_source_files_cxx_compiler_options".

-- Configuring incomplete, errors occurred!

QtCreator 创建工程测试

  • 可以创建 qmake 或者 cmake 的工程,这里以 cmake 为例.
  • CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
project(cmake_opencv3)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_subdirectory(utils)
add_executable(${PROJECT_NAME} ${SRC_LIST} utils/multipleimagewindow.cpp)
include_directories(/fullpath/opencv-build-3.x-qt5/include )
link_directories(/fullpath/opencv-build-3.x-qt5/lib )
find_package( OpenCV 3.4.1 HINTS /fullpath/opencv-build-3.x-qt5 )
MESSAGE("OpenCV version : ${OpenCV_VERSION} ")
MESSAGE("source list : ${SRC_LIST} ")
#add_definitions(-DDISABLE_OPENCV_24_COMPATIBILITY)
target_link_libraries(cmake_opencv3 ${OpenCV_LIBS} )
  • main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char *argv[])
{
Mat img = imread("1.jpg");
namedWindow("test");
imshow("test",img);
waitKey(100);
return 1;
}

使用Python3测试OpenCV

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
~$ pyenv global 3.5.6
~$ git clone https://github.com/pyenv/pyenv-virtualenv ~/.pyenv/plugins/pyenv-virtualenv
source ~/.bashrc
~$ mkdir virtual_env
~$ cd virtual_env/
~/virtual_env$ pyenv virtualenv pycv3dev
Using base prefix '/home/michael/.pyenv/versions/3.6.5'
New python executable in /home/michael/.pyenv/versions/3.6.5/envs/pycv3dev/bin/python3.6
Also creating executable in /home/michael/.pyenv/versions/3.6.5/envs/pycv3dev/bin/python
Installing setuptools, pip, wheel...done.
Requirement already satisfied: setuptools in /home/michael/.pyenv/versions/3.6.5/envs/pycv3dev/lib/python3.6/site-packages
Requirement already satisfied: pip in /home/michael/.pyenv/versions/3.6.5/envs/pycv3dev/lib/python3.6/site-packages

~/virtual_env$ pyenv activate pycv3dev
pyenv-virtualenv: prompt changing will be removed from future release. configure `export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
(pycv3dev) ~/virtual_env$ pip install matplotlib jupyter
[...]

(pycv3dev) ~/virtual_env$ jupyter notebook # 使用jupyter 运行一个网页版notebook,不是必须的,也可以用ipython 运行.
[I 10:25:24.424 NotebookApp] Writing notebook server cookie secret to /run/user/1000/jupyter/notebook_cookie_secret
[I 10:25:24.753 NotebookApp] Serving notebooks from local directory: /home/michael
[I 10:25:24.753 NotebookApp] 0 active kernels
[I 10:25:24.753 NotebookApp] The Jupyter Notebook is running at:
[I 10:25:24.753 NotebookApp] http://localhost:8888/?token=7d4657c804326fc3e4bad99509cd69b55cd39b7383c26936
[I 10:25:24.753 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 10:25:24.754 NotebookApp]

Copy/paste this URL into your browser when you connect for the first time,
to login with a token:
http://localhost:8888/?token=7d4657c804326fc3e4bad99509cd69b55cd39b7383c26936
[I 10:25:25.334 NotebookApp] Accepting one-time-token-authenticated connection from ::1
[23504:23541:0428/102525.341812:ERROR:browser_gpu_channel_host_factory.cc(103)] Failed to launch GPU process.
Created new window in existing browser session.

1
2
3
4
5
6
import matplotlib.pyplot as plt
import sys
sys.path.append('/fullpath/opencv-build-3.x-qt5-py3/lib/python3.6/site-packages')
import cv2
img = cv2.imread("1.jpg")
plt.imshow(img)
  • 如果没有出错,会出现一张图片.

交叉编译 QT5.15.2问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
cd ${CACHE}
if test ! -e patches; then
git clone --depth=1 https://github.com/desktop-app/patches.git
fi
if test ! -e qt_${QT}; then
git clone -b ${QT_TAG} --depth=1 https://code.qt.io/qt/qt5.git qt_${QT}
fi

cd qt_${QT}
perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg
git submodule update qtbase qtwayland qtimageformats qtsvg
cd qtbase
find ../../patches/qtbase_${QT} -type f -print0 | sort -z | xargs -r0 git apply
cd ../qtwayland
find ../../patches/qtwayland_${QT} -type f -print0 | sort -z | xargs -r0 git apply
cd ../
# https://gcc.gnu.org/onlinedocs/gcc/MIPS-Options.html
# https://docs.zecwallet.co/setting-up-build-env/
# http://codecepts.de/en/cross-compiling-qt-5-15-with-qtwebengine-for-raspberry-pi-3/
# https://rm5248.com/cross-compile-qt-for-arm/
# https://doc.qt.io/qt-5/linux-requirements.html
mkdir -pv qtbase/mkspecs/linux-mips64el-g++
cat >qtbase/mkspecs/linux-mips64el-g++/qmake.conf<<EOF
#
# qmake configuration for building with mips64el-linux-gnuabi64-g++
#

MAKEFILE_GENERATOR = UNIX
CONFIG += incremental
QMAKE_INCREMENTAL_STYLE = sublib

include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)

# modifications to g++.conf
QMAKE_CC = mips64el-linux-gnuabi64-gcc
QMAKE_CXX = mips64el-linux-gnuabi64-g++
QMAKE_LINK = mips64el-linux-gnuabi64-g++
QMAKE_LINK_SHLIB = mips64el-linux-gnuabi64-g++

QT_QPA_DEFAULT_PLATFORM = xcb

# modifications to linux.conf
QMAKE_AR = mips64el-linux-gnuabi64-ar cqs
QMAKE_OBJCOPY = mips64el-linux-gnuabi64-objcopy
QMAKE_NM = mips64el-linux-gnuabi64-nm -P
QMAKE_STRIP = mips64el-linux-gnuabi64-strip

QMAKE_LFLAGS = -static -static-libgcc -pthread
QMAKE_LIBS_X11 = -lX11-xcb -lXi -lSM -lXau -lX11 -lXfixes -lXext -lxcb -lXau -ldl -lpthread

# QMAKE_LIBS_XCB = \$\$QMAKE_LIBS_X11

LIBS = -L/opt/crossbuild/deps/usr/local/lib \$\$QMAKE_LIBS_X11


load(qt_config)
EOF
cp qtbase/mkspecs/{linux-aarch64-gnu-g++/qplatformdefs.h,linux-mips64el-g++/qplatformdefs.h}
# rm -rf config.* .qmake.stash .config.notes && \
PKG_CONFIG_PATH="${PREFIX}/share/pkgconfig:${PREFIX}/lib/pkgconfig" \
LDFLAGS="-L${PREFIX}/lib -L/usr/mips64el-linux-gnuabi64/lib" \
LD_LIBRARY_PATH="${PREFIX}/lib:/usr/mips64el-linux-gnuabi64/lib" \
./configure -prefix ${PREFIX}/qt5 \
-release \
-opensource \
-confirm-license \
-xplatform linux-mips64el-g++ \
-device-option CROSS_COMPILE=${HOST} \
-nomake tests \
-xkbcommon \
-xcb \
-xcb-xlib \
-static \
-qt-libpng \
-qt-libjpeg \
-qt-harfbuzz \
-qt-pcre \
-qt-zlib \
-qt-freetype \
-no-icu \
-no-gtk \
-no-feature-xcb-sm \
-no-feature-wayland-server \
-dbus-runtime \
-no-opengl \
-I "${PREFIX}/include" \
-I "/usr/mips64el-linux-gnuabi64/include" \
-L "${PREFIX}/lib" \
-L "/usr/mips64el-linux-gnuabi64/lib" \
-openssl-linked \
OPENSSL_LIBS="${PREFIX}/lib/libssl.a ${PREFIX}/lib/libcrypto.a ${PREFIX}/lib/libz.a -ldl -lpthread" \
-plugin-sql-sqlite \
-nomake examples && \
make -j$(nproc) && make install
  • 因为这里是为mips架构静态交叉编译的,而且还需要支持XCB,所以先要把XCB的依赖如:libXau,libX11,libxcb… 先编译完成.
    使用./configure -xcb的方式可能是不能测试过的, 在Qt5.15之前是有一个-qt-xcb选项的,它是为了减少对系统的xcb
    的依赖,后来因为有BUG在该版本后就删除了.错误如下:
1
2
3
4
5
6
7
8
9
10
11
WARNING: Feature xcb-sm is insignificant in this configuration, ignoring related command line option(s).

ERROR: Feature 'xcb' was enabled, but the pre-condition 'features.thread && libs.xcb && tests.xcb_syslibs && features.xkbcommon-x11' failed.

ERROR: Feature 'xcb-xlib' was enabled, but the pre-condition 'features.xlib && libs.xcb_xlib' failed.

Check config.log for details.

# 查看`config.log`,大多数会显示undefined reference
> /usr/lib/gcc-cross/mips64el-linux-gnuabi64/8/../../../../mips64el-linux-gnuabi64/bin/ld: xcb_auth.c:(.text+0xa4c): undefined reference to `XauDisposeAuth'

  • 一. 处理上面的错误,首先是要排查它链接的库中是会真的没有这个函数的要定义,还有链接库的顺先也会出现这种问题,处理这种问题的步骤如下:

    1. 查看库文件是会存在,能被链到.
    2. 查看库文件是否有对应的函数定义.
    3. 调整链接库的顺序,尝试链接.
  • 二. Qt5的configure后会生成config.cache,config.opt,config.tests/目录与文件,先要确定config.log内的测试错误,是可以通过手动编译链接
    成功的.因为我没有找出configure时如何生成config.tests/目录的来源,这里只能通过非正常途径来处理这个问题.第一次configure时会生成上述
    文件与目录,如果删了config.cache就会重新生成config.tests/,否则下一次的configure会根据config.cache的内容来更新.且因为我这里手
    动验证了xcb,xcb_xlib...等库是可以静态编译链接成功的.所以,这里只需要在config.cache里有如下标志:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    grep "cache.xcb.*.result =" volumes/cache/qt_5_15_2/config.cache
    cache.xcb.result = true
    cache.xcb_icccm.result = true
    cache.xcb_util.result = true
    cache.xcb_shm.result = true
    cache.xcb_image.result = true
    cache.xcb_keysyms.result = true
    cache.xcb_randr.result = true
    cache.xcb_render.result = true
    cache.xcb_renderutil.result = true
    cache.xcb_shape.result = true
    cache.xcb_sync.result = true
    cache.xcb_xfixes.result = true
    cache.xcb_xinerama.result = true
    cache.xcb_xkb.result = true
    cache.xcb_syslibs.result = true
    cache.xcb_xlib.result = true


    * 再运行一次configure就可以正常配置完成了.

在Debian下交叉编译Qt_5.15.2-mips64el

  • 安装交叉编译工具链
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

~$ apt-get install -y cpp-8-mips64el-linux-gnuabi64 \
g++-8-mips64el-linux-gnuabi64 \
g++-8-multilib-mips64el-linux-gnuabi64 \
gcc-8-mips64el-linux-gnuabi64 \
gcc-8-mips64el-linux-gnuabi64-base:amd64 \
gcc-8-multilib-mips64el-linux-gnuabi64 \
lib32atomic1-mips64el-cross \
lib32gcc-8-dev-mips64el-cross \
lib32gcc1-mips64el-cross \
lib32gomp1-mips64el-cross \
lib32stdc++-8-dev-mips64el-cross \
lib32stdc++6-mips64el-cross \
libatomic1-mips64el-cross \
libc6-dev-mips32-mips64el-cross \
libc6-dev-mips64el-cross \
libc6-dev-mipsn32-mips64el-cross \
libc6-mips32-mips64el-cross \
libc6-mips64el-cross \
libc6-mipsn32-mips64el-cross \
libgcc-8-dev-mips64el-cross \
libgcc1-mips64el-cross \
libgomp1-mips64el-cross \
libn32atomic1-mips64el-cross \
libn32gcc-8-dev-mips64el-cross \
libn32gcc1-mips64el-cross \
libn32gomp1-mips64el-cross \
libn32stdc++-8-dev-mips64el-cross \
libn32stdc++6-mips64el-cross \
libstdc++-8-dev-mips64el-cross \
libstdc++6-mips64el-cross \
linux-libc-dev-mips64el-cross

  • 使用Multiarch来安装一些依赖的其它库,可以结省大量编译的时间.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

~$ sudo dpkg --add-architecture mips64el

~$ sudo apt-get update -y

~$ apt-get install -y libegl1:mips64el libxkbcommon0:mips64el \
libxkbcommon-x11-0:mips64el \
libegl1-mesa-dev:mips64el \
libssl1.1:mips64el \
zlib1g-dev:mips64el \
libxcb1-dev:mips64el \
libxcb-glx0-dev:mips64el \
libx11-xcb1:mips64el \
libxcb-dri3-dev:mips64el \
libssl-dev:mips64el \
libdrm-dev:mips64el

~$ ls /usr/lib/mips64el-linux-gnuabi64/
~$ ls /usr/mips64el-linux-gnuabi64/
~$ ls /lib/mips64el-linux-gnuabi64
~$ ls /usr/mips64el-linux-gnuabi64/include

~$ ls /usr/lib/mips64el-linux-gnuabi64/pkgconfig/
  • Qt 动态编译
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44

    export HOST='mips64el-linux-gnuabi64'
    export CC=${HOST}-gcc
    export CXX=${HOST}-g++
    export AR=${HOST}-ar
    export LD=${HOST}-ld
    export RANLIB=${HOST}-ranlib
    export STRIP=${HOST}-strip
    export PREFIX=${SYSROOT}/usr/local
    export QT="5_15_2"
    export QT_TAG="v5.15.2"
    export PREFIX="/usr/mips64el-linux-gnuabi64/qt5"

    PKG_CONFIG_LIBDIR="/usr/lib/mips64el-linux-gnuabi64/pkgconfig" \
    ./configure -prefix ${PREFIX} \
    -release \
    -opensource \
    -confirm-license \
    -xplatform linux-mips64el-g++ \
    -device-option CROSS_COMPILE=${HOST} \
    -nomake tests \
    -xkbcommon \
    -opengl es2 \
    -egl \
    -xcb \
    -xcb-xlib \
    -qt-libpng \
    -qt-libjpeg \
    -qt-harfbuzz \
    -qt-pcre \
    -qt-zlib \
    -qt-freetype \
    -no-icu \
    -no-gtk \
    -no-feature-xcb-sm \
    -no-feature-wayland-server \
    -dbus-runtime \
    -openssl-linked \
    -L "/usr/lib/mips64el-linux-gnuabi64" \
    OPENSSL_LIBS="-lssl -lcrypto -lz -ldl -lpthread" \
    -plugin-sql-sqlite \
    -nomake examples


1
OPENSSL_LIBS="/usr/lib/mips64el-linux-gnuabi64/libssl.a /usr/lib/mips64el-linux-gnuabi64/libcrypto.a /usr/lib/mips64el-linux-gnuabi64/libz.a -ldl -lpthread" \

谢谢支持