四、SLAM学习笔记—— Ubuntu18.04交叉编译OpenCV4.5.5至ARM64位平台firefly-RK3566

概述: 交叉编译大概的意思是指: 在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

运行后可以看到代码正在编译:

四、SLAM学习笔记—— Ubuntu18.04交叉编译OpenCV4.5.5至ARM64位平台firefly-RK3566_第1张图片

二、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加载动态库]代替:

四、SLAM学习笔记—— Ubuntu18.04交叉编译OpenCV4.5.5至ARM64位平台firefly-RK3566_第2张图片

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等基本库,应该很快就能编译完。

你可能感兴趣的:(Ubuntu,arm,opencv,arm开发)