使用Qt和OpenCV进行交叉编译到树莓派

3

有多种方法可以交叉编译到树莓派,也有针对Qtopencv的交叉编译解决方案。

然而,我找不到任何同时使用Qt和opencv进行交叉编译的解决方案。

我尝试了在64位PC上使用Debian进行以下操作:

我按照这个教程将Qt编译成ARM7的交叉编译器。尽管存在问题,但这里是我的解决方案。现在我可以在树莓派上运行带有图形GUI的Qt程序(虽然只能全屏,但那是一个完全不同的问题)。
我按照官方opencv网站上的指南构建opencv。它失败了,出现错误:No CMAKE_CXX_COMPILER could be found. 通过经验得知(我曾在Windows和Linux上同时使用Qt和opencv),只有当两者都使用相同的编译器进行编译时,Qt和opencv才能一起工作。因此,我尝试使用与我成功编译Qt所使用的相同的交叉编译器来编译opencv:gcc-4.7-linaro-rpi-gnueabihf
我将先前用于编译Qt的gnueabihf指定为编译器:

我创建了目录~/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/

在我最近使用的Qt安装程序自带的g++编译器成功地为x64平台编译opencv时,下载的opencv源代码位于/usr/dev/opencv/。请注意,<user>是当前会话的用户名,以防其他初学者在未来尝试这些方法。

以下错误导致操作失败(其中<user>是我的用户名)

CMake错误,位于/usr/share/cmake-3.0/Modules/CMakeTestCXXCompiler.cmake:54 (message):
C++编译器"/home//opt/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-g++"无法编译简单的测试程序。以下是其输出:
更改目录:/home//temp/CMakeFiles/CMakeTmp
运行构建命令:“/usr/bin/make”“cmTryCompileExec117178613 / fast”
/usr/bin/make -f CMakeFiles / cmTryCompileExec117178613.dir / build.make CMakeFiles / cmTryCompileExec117178613.dir / build
make1:进入目录'/home//temp/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report/home//temp/CMakeFiles/CMakeTmp/CMakeFiles 1
构建CXX对象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:在函数‘int main()’中:
/home//temp/CMakeFiles/CMakeTmp/testCXXCompiler.cxx:4:10:对不起,未实现:Thumb-1 hard-float VFP ABI
CMakeFiles/cmTryCompileExec117178613.dir/build.make:57:目标'CMakeFiles / cmTryCompileExec117178613.dir / testCXXCompiler.cxx.o'的配方失败
make1:*** [CMakeFiles/cmTryCompileExec117178613.dir/testCXXCompiler.cxx.o]错误1
make1:离开目录'/home//temp/CMakeFiles/CMakeTmp'
Makefile:118:目标'cmTryCompileExec117178613 / fast'的配方失败
make:***[cmTryCompileExec117178613/fast]错误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

发现成功:

使用内置规范。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 目标:arm-linux-gnueabihf 配置: /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 线程模型:posix gcc版本4.7.2 20120701(预发布)(crosstool-NG linaro-1.13.1-2012.07-20120720 - Linaro GCC 2012.07)

我该尝试什么? 使用 opencv/platforms/linux/arm-gnueabi.toolchain.cmake 打开cmake的图形用户界面会显示很少的选项(只有ARM_LINUX_SYSROOT、CMAKE_BUILD_TYPE、CMAKE_CONFIGURATION_TYPES、CMAKE_INSTALL_PREFIX、GCC_COMPILER_VERSION和LIBRARY_OUTPUT_PATH_ROOT,但没有BUILD_opencv_xyz选项,这使得我无法禁用单个软件包),比我在x86或x64平台上构建opencv时 情况 更少。

我担心寻找不同的编译器可能会导致Qt出问题,因为据我所知,为了使opencv在Qt中工作,必须使用与用于构建Qt库和构建我的程序相同的编译器对其进行编译。每当我不小心尝试过这样做时,就会遇到奇怪的崩溃,无论是在我包含任何opencv头文件时,还是在我调用任何opencv函数时都会出现。

1个回答

4

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

下载OpenCV 3.0源码后,opencv/platforms/linux/arm-gnueabi.toolchain.cmake文件似乎未能为树莓派充分配置。

配置

访问arm-linux-gnueabihf工具链的创建者的工作组页面,似乎需要向编译器传递以下选项才能支持树莓派中的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

只需在cmake文件的CMAKE_C_FLAGSCMAKE_CXX_FLAGS中添加-fPIC标志,然后再次运行make。

部署

使用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/)复制到树莓派上。使用USB存储设备可能会破坏符号链接,因此建议使用scp命令进行文件复制。

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

因此,您应该将库文件复制到通常用于搜索它们的位置(如/usr/local/bin),或相应地更新您的LD_LIBRARY_PATH

为了进行快速而简单的测试以确认一切正常运行,您可以将库文件复制到与可执行文件部署在同一文件夹中,并使用以下命令运行:

$ LD_LIBRARY_PATH=. ./your_program

测试

现在,在您的树莓派上,Opencv 应该可以在 Qt 程序中工作。

除非我的谷歌搜索技巧非常弱,否则这可能是第一个记录下在树莓派上运行带有 Opencv 的 Qt GUI 应用程序的案例。:)

但是,请注意仍可能存在窗口管理问题。例如,尝试打开 opencv 窗口cv::namedWindow("image"); 可能会失败,并显示以下错误:

OpenCV 错误:未指定错误(函数未实现。 请使用 Windows、GTK+ 2.x 或 Carbon 支持重新构建库。如果您在 Ubuntu 或 Debian 上,请安装 libgtk2.0-dev 和 pkg-config,然后重新运行 cmake 或配置脚本)在cvNamedWindow,文件/usr/dev/opencv/modules/highgui/src/window.cpp,第516行终止 被调用后抛出 'cv::Exception' 实例what():/usr/dev/opencv/modules/highgui/src/window.cpp:516: error:(-2) 函数未实现。请使用 Windows、GTK+ 2.x 或 Carbon 支持重新构建库。如果您在 Ubuntu 或 Debian 上,请安装 libgtk2.0-dev 和 pkg-config,然后重新运行 cmake 或配置脚本 在 cvNamedWindow 函数中

我想我们应该按它说的去做,但是在 Qt GUI 应用程序中,cvNamedWindow并不是非常有用,因为它通常仅用于调试。因此,如果必须在应用程序中显示图像,则将其转换为 QImage 可能比打开独立窗口更好。

但是,除此之外,一切似乎都正常工作,我成功地在树莓派上运行了复杂的图像匹配算法。

(... 如果我找到在窗口中运行 Qt 应用程序并使用 cvNamedWindow 的好方法,我会更新的)


感谢您提供的解决方案。我按照您的建议更改了cmake标志,成功生成了文件! - mtekeli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接