Cross-compiling 到 Raspberry Pi,使用 Qt 和 opencv

Cross-compiling to Raspberry Pi, using Qt and opencv

有多种方法可以cross-compile to Raspberry Pi, and there are also solutions posted for cross-compiling Qt or opencv

但是,我找不到 cross-compile Qt 程序也使用 opencv 的任何解决方案。

我在 64 位 PC 上使用 debian 尝试了以下方法:

我创建了目录 ~/opt/opencv_build_arm7/ 并在其中尝试了:

sudo cmake -DCMAKE_CXX_COMPILER=/home/<user>/opt/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-g++ -DCMAKE_C_COMPILER=/home/<user>/opt/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-gcc -DCMAKE_TOOLCHAIN_FILE=/usr/dev/opencv/platforms/linux/arm-gnueabi.toolchain.cmake /usr/dev/opencv/

(下载的 opencv 源代码在 /usr/dev/opencv/ 中,我最近成功使用它为 x64 平台编译了 opencv,使用的是我的 Qt 安装附带的 g++ 编译器。)注意, <user> 是当前 session 的用户名,以防其他初学者将来可能会尝试这些方法。

失败并出现以下错误(其中 <user> 是我的用户名)

CMake Error at /usr/share/cmake-3.0/Modules/CMakeTestCXXCompiler.cmake:54 (message): The C++ compiler
"/home//opt/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-g++" is not able to compile a simple test program.

It fails with the following output :

Change Dir: /home//temp/CMakeFiles/CMakeTmp

Run Build Command:"/usr/bin/make" "cmTryCompileExec117178613/fast"

/usr/bin/make -f CMakeFiles/cmTryCompileExec117178613.dir/build.make CMakeFiles/cmTryCompileExec117178613.dir/build

make1: Entering directory '/home//temp/CMakeFiles/CMakeTmp'

/usr/bin/cmake -E cmake_progress_report
/home//temp/CMakeFiles/CMakeTmp/CMakeFiles 1

Building CXX object
CMakeFiles/cmTryCompileExec117178613.dir/testCXXCompiler.cxx.o

/home//opt/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-g++ -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi -o CMakeFiles/cmTryCompileExec117178613.dir/testCXXCompiler.cxx.o -c /home//temp/CMakeFiles/CMakeTmp/testCXXCompiler.cxx

/home//temp/CMakeFiles/CMakeTmp/testCXXCompiler.cxx: In function ‘int main()’:

/home//temp/CMakeFiles/CMakeTmp/testCXXCompiler.cxx:4:10: sorry, unimplemented: Thumb-1 hard-float VFP ABI

CMakeFiles/cmTryCompileExec117178613.dir/build.make:57: recipe for target
'CMakeFiles/cmTryCompileExec117178613.dir/testCXXCompiler.cxx.o' failed

make1: ***
[CMakeFiles/cmTryCompileExec117178613.dir/testCXXCompiler.cxx.o] Error 1

make1: Leaving directory '/home//temp/CMakeFiles/CMakeTmp'

Makefile:118: recipe for target 'cmTryCompileExec117178613/fast' failed

make: *** [cmTryCompileExec117178613/fast] Error 2

我为编译器指定了绝对路径,但即使我不指定它,只是将它添加到我的$PATH中,它仍然有同样的问题。

export PATH=$PATH:/home/<user>/opt/gcc-4.7-linaro-rpi-gnueabihf/bin/

sudo cmake -DCMAKE_TOOLCHAIN_FILE=/usr/dev/opencv/platforms/linux/arm-gnueabi.toolchain.cmake /usr/dev/opencv/

如果我键入

,编译器本身会被正确找到
arm-linux-gnueabihf-g++ -v

找到成功:

Using built-in specs. COLLECT_GCC=./arm-linux-gnueabihf-c++ COLLECT_LTO_WRAPPER=/home/vszabi/opt/gcc-4.7-linaro-rpi-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/4.7.2/lto-wrapper Target: arm-linux-gnueabihf Configured with: /opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/.build/src/gcc-linaro-4.7-2012.07/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-linux-gnueabihf --prefix=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/install --with-sysroot=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/install/arm-linux-gnueabihf/libc --enable-languages=c,c++,fortran --enable-multilib --with-arch=armv6zk --with-tune=arm1176jzf-s --with-fpu=vfp --with-float=hard --with-pkgversion='crosstool-NG linaro-1.13.1-2012.07-20120720 - Linaro GCC 2012.07' --with-bugurl=https://bugs.launchpad.net/gcc-linaro --enable-__cxa_atexit --enable-libmudflap --enable-libgomp --enable-libssp --with-gmp=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-mpfr=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-mpc=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-ppl=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-cloog=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-libelf=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-host-libstdcxx='-L/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static/lib -lpwl' --enable-threads=posix --disable-libstdcxx-pch --enable-linker-build-id --enable-gold --with-local-prefix=/opt/dev/src/crosstool-ng/crosstool-ng-linaro-1.13.1-2012.07-20120720/builds/arm-linux-gnueabihf-linux/install/arm-linux-gnueabihf/libc --enable-c99 --enable-long-long Thread model: posix gcc version 4.7.2 20120701 (prerelease) (crosstool-NG linaro-1.13.1-2012.07-20120720 - Linaro GCC 2012.07)

接下来我可以尝试什么? 使用 opencv/platforms/linux/arm-gnueabi.toolchain.cmake 打开 cmake 的 gui 版本显示很少的选项(仅 ARM_LINUX_SYSROOT、CMAKE_BUILD_TYPE , CMAKE_CONFIGURATION_TYPES, CMAKE_INSTALL_PREFIX, GCC_COMPILER_VERSION 和 LIBRARY_OUTPUT_PATH_ROOT, 但是 BUILD_opencv_xyz 的 none 我可以用它来禁用单个包),比case 当我为 x86 或 x64 平台构建 opencv 时。

恐怕搜索不同的编译器可能会导致 Qt 出现问题,因为据我所知,要使 opencv 在 Qt 中工作,它必须使用与两者所用的相同的编译器进行编译构建 Qt 库并构建我的程序。每当我过去尝试它时,如果不注意这 3 个东西(Qt 库、opencv、我的程序)需要使用相同的编译器进行编译,我总是会在包含任何 opencv header 时遇到奇怪的崩溃,或者每当我从 opencv 调用任何函数时。

http://docs.opencv.org/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.html 上的教程似乎有误或已过时。

正在下载opencv 3.0的源码,opencv/platforms/linux/arm-gnueabi.toolchain.cmake似乎没有为Raspberry Pi配置好。

配置

访问arm-linux-gnueabihf工具链的创建者workgroup page,似乎要支持Raspberry Pi中的ARM7,必须将以下选项传递给编译器:-mcpu=cortex-a7 -mfloat-abi=hard -mfpu=vfpv4

因此,我们必须编辑 opencv/platforms/linux/arm-gnueabi.toolchain.cmake 文件并更改

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=vfpv4")
set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -mthumb -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=vfpv4")

运行再次cmake,配置成功!

制作

构建过程中,如果出现如下错误

CMakeFiles/opencv_core.dir/src/rand.cpp.o: relocation R_ARM_THM_MOVW_ABS_NC against `a local symbol' can not be used when making a shared object; recompile with -fPIC CMakeFiles/opencv_core.dir/src/rand.cpp.o: could not read symbols: Bad value

只需将-fPIC标志添加到cmake文件中的CMAKE_C_FLAGSCMAKE_CXX_FLAGS,然后运行再次制作。

部署

使用 Qt Creator 部署,只需在 .pro 文件中设置头文件和库,例如:

INCLUDEPATH += <your build dir>/install/include/opencv2/
INCLUDEPATH += <your build dir>/install/include/
LIBS += -L  "<your build dir>/install/lib/"
LIBS += -lopencv_calib3d
LIBS += -lopencv_core
#... and so on

您还必须将已编译的库(在 <your build dir>/install/lib/ 中找到)复制到 Raspberry Pi。使用 U 盘可能会弄乱符号链接,因此我建议使用 scp 来复制文件。

如果您对 Linux 比较陌生(就像我自己一样),请不要忘记可执行文件不会像在 Windows 中那样自动查看它们自己的动态库文件夹。

因此,您应该将库复制到通常搜索它们的地方(例如 /usr/local/bin),或者相应地更新您的 LD_LIBRARY_PATH

要进行快速粗略的测试,看看是否一切正常,您可以将库复制到部署可执行文件的同一文件夹中,然后 运行 使用

$ LD_LIBRARY_PATH=. ./your_program

测试

Opencv 现在应该可以在 Raspberry Pi 上的 Qt 程序中运行了。

除非我的 google-fu 很弱,否则这可能是第一个 运行 在 Raspberry Pi 上使用 opencv 创建 Qt GUI 应用程序的记录案例在其中工作。 :)

但是,请注意 window 管理可能仍然存在一些问题。 尝试打开 opencv window,例如 cv::namedWindow("image"); 可能会失败并出现以下错误:

OpenCV Error: Unspecified error (The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script) in cvNamedWindow, file /usr/dev/opencv/modules/highgui/src/window.cpp, line 516 terminate called after throwing an instance of 'cv::Exception' what(): /usr/dev/opencv/modules/highgui/src/window.cpp:516: error: (-2) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function cvNamedWindow

我想我们应该按照它说的去做,但是 cvNamedWindow 在 Qt GUI 应用程序中不是很有用,因为它通常只在调试时需要。因此,如果必须在您的应用程序中显示图像,无论如何将其转换为 QImage 可能比打开一个独立的 window 更好。

然而,其他一切似乎都有效,我设法在 Raspberry Pi.

上成功 运行 复杂的图像匹配算法

(...如果我找到 运行 在 window 中使用 Qt 应用程序并使用 cvNamedWindow 的好的解决方案,将会更新)