一.交叉编译opencv库
1.下载opencv源码
OpenCV官方源码下载链接为https://opencv.org/releases/,选择3.4.16版本下载。放在ubuntu系统~/opencv文件夹中,解压缩,opencv文件夹中新建build和install文件夹用于存放编译文件和安装文件:
2. 安装编译工具
- 安装 cmake 和 cmake-gui 工具
sudo apt-get install cmake cmake-qt-gui cmake-curses-gui
- 安装交叉编译器arm-none-linux-gnueabihf,根据自己情况来选择对应交叉编译器
3.安装opencv前安装环境依赖
sudo apt-get install build-essential
sudo apt-get install libopenblas-dev
sudo apt-get install git pkg-config libavcodec-dev libavformat-dev libswscale-dev
处理图像所需的包
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff5-dev libdc1394-22-dev
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev liblapacke-dev
处理视频所需的包
sudo apt-get install libxvidcore-dev libx264-dev
优化opencv功能
sudo apt-get install libatlas-base-dev gfortran
sudo apt-get install ffmpeg
4. 编译
进入build文件夹,执行命令:
cmake-gui
执行完成后会出现图形化工具 cmake-gui,选择源代码目录,buid目录,这里根据自己的路径填写
- 在 CMAKE_EXE_LINKER_FLAGS 处添加上-lpthread -lrt -ldl。添加这些是是指定依赖库的链接
- CMAKE_INSTALL_PREFIX 处指定安装目录,我们在上面已经新建了 install 安装目录。我们直接指定到该目录即可。如果不指定,它会默认安装到 Ubuntu 系统目录/usr/local 下。
- BUILD_TESTS取消勾选,否则会报错测试不通过
- 在源码目录 opencv-3.4.1/3rdparty/protobuf/src/google/protobuf/stubs/common.cc 这个文件下添加**#define HAVE_PTHREAD** 宏定义才可以编译的过。具体原因是 HAVE_PTHREAD 宏定义了 pthread 库。
进入 build 目录下,可以看到 bulid 目录下已经准备了构建文件。我们直接输入 make 构建即可。结束后make install
编译完成如下图,如果有出错,先删除 build 目录下的所有文件,cmake-gui开始重新再来一次!
如果成功安装则会在install目录中出现以下东西
这时可以将这个文件夹中的文件用于程序编写,并和之后生成的可执行文件一同传输至开发板,程序编写参考第二章:
问题汇总:
问题1:
/arm-none-linux-gnueabihf/libc/usr/include/features.h:311:52: error: operator ‘&&’ has no right operand
#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
- 解决1:
在#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64前面 加上
#define _FILE_OFFSET_BITS 64
问题2
make[1]: *** [modules/core/CMakeFiles/opencv_test_core.dir/all] Error 2
Makefile:160: recipe for target ‘all’ failed
make: *** [all] Error 2
- 解决2
configure配置中取消BUILD_TESTS
问题3
usr/lib/gcc-cross/aarch64-linux-gnu/8/…/…/…/…/aarch64-linux-gnu/bin/ld: …/…/lib/libopencv_imgcodecs.so.4.2.0: undefined reference to `png_riffle_palette_neon’
collect2: error: ld returned 1 exit status
make[2]: *** [apps/annotation/CMakeFiles/opencv_annotation.dir/build.make:89:bin/opencv_annotation] 错误 1
make[1]: *** [CMakeFiles/Makefile2:3746:apps/annotation/CMakeFiles/opencv_annotation.dir/all] 错误 2
- 解决3:
./opencv-3.3.1/3rdparty/libpng/pngpriv.h
/*# if (defined(ARM_NEON) || defined(__ARM_NEON)) && */
#if defined(PNG_ARM_NEON) && (defined(ARM_NEON) || defined(__ARM_NEON)) &&
如上所示,把上面的一行注释掉,增加下面一行。删除build文件夹内容,在cmake-gui再次生成文件,再次make即可。
问题4
arm-linux-gnueabihf/bin/ld: …/…/lib/libopencv_imgcodecs.so: undefined reference to png_do_expand_palette_rgb8_neon' ./../../../arm-linux-gnueabihf/bin/ld: ../../lib/libopencv_imgcodecs.so: undefined reference to
png_init_filter_functions_neon’
…/lib/libopencv_imgcodecs.so: undefined reference to `png_init_filter_functions_neon’
- 解决4:
在最上面加上添加如下语句:
SET(ARM 1)
SET(ENABLE_NEON 1)
添加完成后在root权限下重新运行cmake-gui,重新配置和生成。
问题5
想用opencv v4l调用usb/csi摄像头的话,需要cmake-gui中勾选WITH_V4L和WITH_LIBV4L
但是使用常规编译器GCC和G++才会出现上面两个选项,使用交叉编译器不会出现。
- 解决5
这里名字为Linux,L大写即可出现选项,不用v4l随便命名即可
问题6
交叉编译4.9.0版本opencv是,在cmake-gui中出现error in configuration process,project files may be invalid
解决
根据上面的错误定位到libjpeg-turbo的CmakeLists.txt中,${CMAKE_SYSTEM_PROCESSOR} 无输出
在这行之前输入:
set(CMAKE_SYSTEM_NAME Linux) #设置目标系统名字
set(CMAKE_SYSTEM_PROCESSOR arm) #设置目标处理器架构
二.cpp程序编写
1.CMakeList.txt编写
1.库文件
编译完成在install目录中有bin/include/lib等文件夹,其中include存放的头文件,lib存放的libopencv*.so库文件
2.示例程序
在任何位置创建一个文件夹demo,这里就在install目录中新建了,编写测试程序gpio.cpp、CMakeLists.txt、rv1103.cmake,各自代码如下,完成功能:从板内读取一张图片,转为灰度图片并保存。
(1) gpio.cpp:
#include <opencv2/opencv.hpp>
//如果include目录中是opencv4则改成include<opencv4/opencv2/opencv.cpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// 读取图片
cv::Mat image = cv::imread("result.jpg");
// 检查图片是否成功读取
if (image.empty()) {
std::cout << "Could not read the image: " << "path_to_your_image.jpg" << std::endl;
return -1;
}
// 创建灰度图像矩阵
cv::Mat grayImage;
// 将彩色图像转换为灰度图像
cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
cv::imwrite("reshui.jpg",grayImage);
// 等待按键,如果按下'q'键则退出循环
waitKey(1);
return 0;
}
3.CMakeLists.txt:
- 如果lib文件夹中没有cmake文件则自己指定需要哪些so库文件:
cmake_minimum_required(VERSION 3.0)
project(opencv)
set(include_DIR /home/tao/opencv/opencv-rv1103/install/include)# 根据自己include目录设置OpenCV的include路径
set(lib_DIR /home/tao/opencv/opencv-rv1103/install/lib)# 根据自己include目录设置OpenCV的lib路径
include_directories(${include_DIR})# 设置包含的头文件路径
link_directories(${lib_DIR})# 设置库文件路径
add_executable(gpio gpio.cpp)# 将源文件添加到此项目的可执行文件。
file(GLOB LIBRARIES ${lib_DIR}/*.so) #链接 lib 文件夹下所有的库文件 假设是 .so 文件。
#如果只有某一个库则不用上一条命令,直接指定:
#set(ONNX_LIBRARY "/home/tao/linux/rk3568/onnxruntime/lib/libonnxruntime.so") # 根据实际情况修改库文件名
target_link_libraries(gpio ${LIBRARIES})
- 如果有些lib文件夹中除了so库文件还有cmake文件夹则添加opencv库部分时可以改为下面的,不改就完全按照上面的就行:
set(OpenCV_DIR "${CMAKE_CURRENT_SOURCE_DIR}/opencv-mobile-4.9.0-luckfox-pico/lib/cmake/opencv4")#其中有一些*cmake文件
find_package(OpenCV REQUIRED)#自动根据cmake文件查找包
include_directories(${OpenCV_INCLUDE_DIRS})#//include目录
target_link_libraries(main ${LIBS} ${OpenCV_LIBS}) #添加库, OpenCV_INCLUDE_DIRS和OpenCV_LIBS都是根据find_package自动生成的
4.rv1103.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(tools /home/tao/linux/luckfox/luckfox-pico-main/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/)#交叉编译器目录
set(CMAKE_C_COMPILER ${tools}/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-rockchip830-linux-uclibcgnueabihf-g++)
set(CMAKE_AR ${tools}/bin/arm-rockchip830-linux-uclibcgnueabihf-ar)
set(CMAKE_RANLIB ${tools}/bin/arm-rockchip830-linux-uclibcgnueabihf-ranlib)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
在demo文件夹中创建一个空目录build用于存放编译生成文件,并在命令行中进入build文件夹,demo文件夹内容如下,一个三个文件和一个build目录:
3.交叉编译
cd build //进入build目录
cmake -DCMAKE_TOOLCHAIN_FILE=../rv1103.cmake .. //两个..不是三个点... ,两个点是指返回上一级目录找cmakelist.txt文件
make
如果失败,修改问题后需要删除build文件夹内容再cmake指令
4.传输至开发板子
将build文件夹内生成的gpio可执行文件 、最开始opencv编译生成的install文件夹内的东西复制到开发板(可以不在同一个文件夹),如下将其放在同一个文件夹发送至开发板:
5. chmod -r 777 ./*赋予权限
此时运行会报错找不到库,需要指定库路径:export LD_LIBRARY_PATH=/home/root/install/lib:$LD_LIBRARY_PATH指定opencv编译生成的lib文件夹所在开发板中的路径(当前shell有效),不是虚拟机中的位置,也可以修改/etc/ld.so.conf文件永久生效,如果export后仍然报错…/…/lib*so找不到,那就是可执行文件与库的位置与虚拟机中的相对位置不同。
6. ./gpio执行,如果gpio所在文件夹内存放有result.jpg则会读取图片生成灰度图像
问题汇总
有些编译器出现对‘pthread_create’未定义,对‘dladdr’未定义的引用
则CMakeLists.txt最后改为:链接上pthread和dl库
如果想包含多个路径下的头文件和库文件:定义其它路径变量,在include_directories内添加多个变量即可,中间空格隔开。
如果出现cpp程序报错:invalid conversion from ‘void*’ to ‘short unsigned int*’ [-fpermissive]
则可以在CMakeLists.txt中添加编译选项:target_compile_options(gpio PRIVATE -fpermissive)