概述: 交叉编译大概的意思是指: 在PC(x86_x64)的机器上编译其他平台如ARM平台的代码,这个过程叫做交叉编译。对于交叉编译,我们首先确定目标平台的架构,RK3566的架构是ARMv8,64位的执行状态。aarch64的介绍可以参考:[https://blog.csdn.net/tanli20090506/article/details/71435777]官方的Linux的SDK中,提供的编译器为:
整个交叉编译工程从大的步骤上讲其实很简单,就是细节的坑有一些,总体步骤:1)下载OpenCV的代码 2) 用CMake-GUI工具配置编译配置 3) 利用gcc-aach64编译代码得到动态库so 4) 编译程序在RK3566开发板运行。
一、下载OpenCV4.5.5代码和OpenCV Contributed代码
OpenCV: 官网下载
OpenCV Contribute : https://github.com/opencv/opencv_contrib/archive/4.5.5.zip
1.2 启动cmke-gui
1.3 配置源代码目录和生成目录Build
点击Config:
配置opencv_contribute目录:
1.4
运行后可以看到代码正在编译:
二、CMake-GUI的配置
三、OpenCV代码的编译
编译OpenCV4.5.5出现的错误:
../../lib/libopencv_world.so.4.5.3: undefined reference to `png_do_expand_palette_rgb8_neon'
../../lib/libopencv_world.so.4.5.3: undefined reference to `png_init_filter_functions_neon'
../../lib/libopencv_world.so.4.5.3: undefined reference to `png_do_expand_palette_rgba8_neon'
../../lib/libopencv_world.so.4.5.3: undefined reference to `png_riffle_palette_neon'
collect2: error: ld returned 1 exit status
apps/model-diagnostics/CMakeFiles/opencv_model_diagnostics.dir/build.make:95: recipe for target 'bin/opencv_model_diagnostics' failed
make[2]: *** [bin/opencv_model_diagnostics] Error 1
CMakeFiles/Makefile2:3183: recipe for target 'apps/model-diagnostics/CMakeFiles/opencv_model_diagnostics.dir/all' failed
make[1]: *** [apps/model-diagnostics/CMakeFiles/opencv_model_diagnostics.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
对应的解决方案:打开opencv源码目录,编辑文件 vim 3rdparty/libpng/pngpriv.h
第130行注释掉, 修改为131行
/* # if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \ */
# if defined(PNG_ARM_NEON) && (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \
defined(PNG_ALIGNED_MEMORY_SUPPORTED)
# define PNG_ARM_NEON_OPT 2
# else
# define PNG_ARM_NEON_OPT 0
# endif
#endif
该解决方案亲测可行,参考博文:https://blog.csdn.net/u010571709/article/details/122103591
四、编译OpenCV的DEMO在板子上运行
创建一个main.c的OpenCV的DEMO程序,实现的功能是将普通的图像转换为黑白二值化的图像。
#include
#include "opencv2/opencv.hpp"
#include "opencv2/calib3d/calib3d.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat imag, result;
imag = imread("mv3.jpg",16);
result = imag.clone();
threshold(imag, result, 100, 250, THRESH_OTSU);
imwrite("huidu.jpg",result);
return 0;
}
直接编写一个简单的命令调用aarch64-g++编译上边的程序:
/home/wzw/rk3566/rk_cross_compile_tool/bin/aarch64-linux-gnu-g++ -g -std=c++11 test.cpp \
-o test_opencv.out \
-I/home/wzw/rk3566/rk3566_opencv/include \
-L/home/wzw/rk3566/rk3566_opencv/lib \
-lopencv_core \
-lopencv_imgcodecs \
-lopencv_imgproc
-I : 指定包含头文件的位置
-L: 指定库文件所在的位置
-l : 指定库的名称。虽然完整的名称是libopencv_core.so 但是我们不写后缀名,也写前边的lib。
五、编译程序在RK3566上的运行
5.1 运行.out 提示: no such file or directory
本次交叉编译编译出.out文件,但是运行的时候提示no such file or directory,最终经过排查怀疑是编译的程序无效(编译器的架构选错), 后续选RK3566 SDK提供的交叉编译工具编译代码没出现这该情况。
5.2 error while loading shared libraries: xxx.so.x
当我解决了5.1的问题后,随之而来的是无法正确加载so库。这是因为我以为linux和windows相同,都会默认加载可执行文件同目录的so文件。实际上linux默认情况下并不会先在当前目录下搜寻so库,从而导致error while loading shared libraries。
可以通过ldd命令查看程序依赖库情况,样例如下所示,由于RK3566开发板不好截图,用其他博客的图[linux加载动态库问题_黄粱一梦-CSDN博客_linux加载动态库]代替:
5.3让Linux在当前目录下调用so库文件
Linux系统在当前目录下调用so文件:默认情况下Linux系统不在会当前系统下寻找程序需要加载的Library文件,这点和windows并不相同,windows会优先从程序的当前目录下搜寻dll并尝试加载。这个有时候并不方便调试代码。一个简单的方式是:Ctrl + Alt + T打开命令行,输入:
# 临时修改,log out之后就失效
export LD_LIBRARY_PATH=./
如果需要任何时候都优先在当前目录搜寻Library,那么按下面的方法:
# 让当前帐号以后都优先加载当前目录的动态库
修改~/.bash_profile在文件末尾加上两行: LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH
# 让所有帐号从此都优先加载当前目录的动态库
修改/etc/profile在文件末尾加上两行: LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH
5.4 链接库的时候,提示load shared libraries error,xxx file too short
经过前面的步骤,终于可以看到系统在尝试记载本地的so库,但是加载库的时候提示库太短了。原因:程序链接的动态库中有软连接,但是软连接没有(l)标识,被识别成了实际的动态库文件,软连接文件又太小,所以就成了too short,解决办法,重新建立软连接。
rm libopencv_core.so libopencv_core.so.405
ln -s libopencv_core.so.4.5.5 libopencv_core.so.405
ln -s libopencv_core.so.405 libopencv_core.so
经过上述的各种问题的处理,终于交叉编译的程序终于在RK3566的板子上正常运行。
六、交叉编译译程序在RK3566上的运行
通过Ubuntu18.04交叉编译的OpenCV库除了opencv_highgui这个库之外,其他库都基本都是正常的。PC的Ubuntu18.04编译的OpenCV库会出现下面的问题:
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.5.5-dev) /home/wzw/opencv4.5.5/modules/highgui/src/window.cpp:1251:
error: (-2:Unspecified error) The function is not implemented. Rebuild the library with
Windows, GTK+ 2.x or Cocoa 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'
这是因为opencv_highgui这个库依赖GTK图形库。而虚拟机的libgtk是x64,RK3566是arm的libgtk。对于这个问题,可以在RK3566通过源码编译opencv_highgui.so这个库,然后替换交叉编译的opencv_highgui.so。
我测试了一下RK3566通过源码的方式安装OpenCV4.5.5 + OpenCV_Contrib4.5.5 大约需要3小时。如果仅选择opencv_core和opencv_highgui等基本库,应该很快就能编译完。