OpenCV库编译移植
创始人
2024-06-03 11:57:50
0

OpenCV 是图像处理中最常用的库,华山派同样对其进行了支持。

1. 编译构建最新版本的 OpenCV(可选)

华山派目前库中自带了 OpenCV 3,如果想使用其他版本的则需自行构建。平头哥针对华山派上的玄铁芯片,对 OpenCV 第三方库进行了一些编译优化,我们去平头哥芯片开放社区下载工具包:

下载完后我们解压得到 OpenCV 源码和 quick start 教程:

在编译时需要选择 C906FDV 芯片的编译指令,默认编译静态链接库,如若要使用动态链接库,需要将编译依赖补全:

cmake .. -DCMAKE_TOOLCHAIN_FILE="../platforms/linux/riscv64-gcc.toolchain.cmake" -DWITH_OPENCL=OFF -DBUILD_opencv_calib3d=ON -DBUILD_ZLIB=ON -DBUILD_PNG=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_WITH_INSTALL_RPATH=1 -DCMAKE_INSTALL_PREFIX=../install -DBUILD_CSI_CV=ON -DWITH_OPENMP=OFF -DWITH_PTHREADS_PF=OFF -DCORE=C906FDV -D BUILD_SHARED_LIBS=ON -D BUILD_opencv_features2d=ON -D BUILD_opencv_apps=OFF -D BUILD_TESTS=OFF -D BUILD_opencv_highgui=OFF -D BUILD_PERF_TESTS=OFF

然后需要在 ../platforms/linux/riscv64-gcc.toolchain.cmake 中指定编译工具链的全局路径:

之后就可以按照 quick start 文档中的构建命令进行编译:

  1. build

  1. make -j32

  1. make install(可选),默认安装在 ../install 下

2. 交叉编译 OpenCV 程序

我们以 OpenCV 的 resize 函数进行测试,测试代码如下:

#include   
#include   
#include   
#include   void test() {  std::string img_path = "./hmbb1280.jpg";  cv::Mat img = cv::imread(img_path);  for (int i = 0; i < 100; i++)  cv::resize(img, img, cv::Size(640, 360), 0, 0, cv::INTER_AREA);  
}  int main(int argc, char **argv) {  clock_t start, end;  start = clock();  test();  end = clock();  std::cout << std::endl << (double) (end - start) / CLOCKS_PER_SEC << std::endl;  return 0;  
}

CMakeLists.txt 编写参考如下,在使用时注意将工具链和库地址进行修改:

cmake_minimum_required(VERSION 3.16.5)  
project(opencv_test_rvv07)  set(CMAKE_CXX_STANDARD 11)  set(CROSS_COMPILE 1) # enable the cross compiler config  IF(CROSS_COMPILE)  set(CMAKE_SYSTEM_NAME Linux)  set(TOOLCHAIN_DIR /home/sophgo/sophpi-huashan/host-tools/gcc/riscv64-linux-musl-x86_64/bin)  # specify the cross compiler  set(CMAKE_C_COMPILER   ${TOOLCHAIN_DIR}/riscv64-unknown-linux-musl-gcc)  set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/riscv64-unknown-linux-musl-g++)  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=rv64imafdcvxthead -mcmodel=medany -mabi=lp64d")  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=rv64imafdcvxthead -mcmodel=medany -mabi=lp64d")  set(OPENCV_FLAG 3)  IF(OPENCV_FLAG EQUAL 0)  set(OPENCV_PATH /home/sophgo/sophpi-huashan/tpu/cvitek_tpu_sdk/opencv)  ELSEIF(OPENCV_FLAG EQUAL 1)  set(OPENCV_PATH /home/sophgo/sophpi-huashan/tpu/OpenCV-V1.0.2/OpenCV/install)  ELSEIF(OPENCV_FLAG EQUAL 2)  set(OPENCV_PATH /home/sophgo/sophpi-huashan/tpu/opencv-4.7.0/install)  ELSE()  set(OPENCV_PATH /home/sophgo/sophpi-huashan/tpu/opencv-install-rv07/install)  ENDIF()  include_directories(${OPENCV_PATH}/include)  link_directories(${OPENCV_PATH}/lib)  set(OPENCV_LIBS ${OPENCV_LIBS} opencv_core opencv_imgcodecs opencv_imgproc)  add_executable(${PROJECT_NAME} main.cpp)  target_link_libraries(${PROJECT_NAME} ${OPENCV_LIBS})  
ELSE()  find_package(OpenCV REQUIRED)  include_directories(${OpenCV_INCLUDE_DIRS})  add_executable(${PROJECT_NAME} main.cpp)  target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBRARIES})  
ENDIF()

然后进行编译,指令如下:

cmake . # 在项目目录下
make # 得到二进制可执行文件

编译成功后,将可执行程序、测试图片和链接库通过 scp 等方式传送到华山派上,并在派上声明环境:

export LD_LIBRARY_PATH=/mnt/data/lib:$LD_LIBRARY_PATH

运行得到测试结果如下:

可以看出,平头哥优化版本的 OpenCV 的确是最快的,其次是 OpenCV-4.7。

3. 移植案例—OpenCV 光流算法

光流是指在连续的两帧图像中由于图像中的物体移动或者摄像头的移动导致的图像中目标像素的移动。OpenCV 库中集成了多种常用的稠密光流算法。本节我们简要介绍两种稠密光流算法在无人机飞行测速中的应用,以及将其移植到华山派上的性能表现。

3.1 OpenCV 光流算法移植

  1. DISOpticalFlow

  • 算法的 创建/计算:

cv::Ptr DISOpticalFlowAlgorithm = cv::DISOpticalFlow::create(cv::DISOpticalFlow::PRESET_MEDIUM); // 可选参数 PRESET_MEDIUM PRESET_FAST PRESET_ULTRAFAST
DISOpticalFlowAlgorithm->calc(prvs, next, flow);
  • 调参:

// 包含了 get set,这边只列出 set 方法
setFinestScale(); // 图像高斯金字塔层数 2
setGradientDescentIterations(); // 最大梯度下降迭代次数 12
setPatchSize(); // Patch 大小 8
setPatchStride(); // Patch 步长 4
setUseMeanNormalization(); // 平均正则化 true
setUseSpatialPropagation(); // true
setVariationalRefinementAlpha(); // 平滑度权重 20.0
setVariationalRefinementDelta(); // 颜色权重 5.0
setVariationalRefinementGamma(); // 梯度权重 10.0
setVariationalRefinementIterations(); // patch 反向搜索中最大梯度迭代次数 0
  • 代码示例:

void cal_DISOpticalFlow(char *prvs_img, char *next_img, double &dx, double &dy) {  cv::Mat frame1 = cv::imread(prvs_img), frame2 = cv::imread(next_img);  int px = frame1.size[0], py = frame1.size[1]; // 行/列cv::Rect rectL((px-r) / 2, (py-r) / 2, r/2,r/2); // 取中间的128x128区域// RGB 转灰度图cv::Mat prvs, next;prvs = frame1(rectL).clone();next = frame2(rectL).clone();cvtColor(prvs, prvs, cv::COLOR_BGR2GRAY);cvtColor(next, next, cv::COLOR_BGR2GRAY);cv::Mat flow(prvs.size(), CV_32FC2);// 创建光流算法调参后计算cv::Ptr DISOpticalFlowAlgorithm = cv::DISOpticalFlow::create(cv::DISOpticalFlow::PRESET_MEDIUM);  DISOpticalFlowAlgorithm->setFinestScale(2);  DISOpticalFlowAlgorithm->setGradientDescentIterations(12);  DISOpticalFlowAlgorithm->setPatchSize(4);  DISOpticalFlowAlgorithm->setPatchStride(2);  DISOpticalFlowAlgorithm->setUseMeanNormalization(true);  DISOpticalFlowAlgorithm->setUseSpatialPropagation(true);  DISOpticalFlowAlgorithm->setVariationalRefinementAlpha(20.0);  DISOpticalFlowAlgorithm->setVariationalRefinementDelta(5.0);  DISOpticalFlowAlgorithm->setVariationalRefinementGamma(10.0);  DISOpticalFlowAlgorithm->setVariationalRefinementIterations(0);  DISOpticalFlowAlgorithm->calc(prvs, next, flow);// 每个通道的均值即为光流计算的偏移量dx = cv::mean(flow)[0];  dy = cv::mean(flow)[1];  
}
  • DIS 光流算法分析:

速度较快,但是面对低纹理场景时效果较差

OpenCV 官方文档 https://docs.opencv.org/master/de/d4f/classcv_1_1DISOpticalFlow.html

  1. FarnebackFlow

FarnbackFlow 光流算法运行速度会略慢于 DIS 光流,但能较好地应对低纹理场景,示例如下:

cv::calcOpticalFlowFarneback(prvs, next, flow, 0.5, 3, 15, 3, 5, 1.2, 0);

OpenCV 官方文档 https://docs.opencv.org/4.7.0/dc/d6b/group__video__track.html

应用到无人机测速,我们往往只需要关注图像中央的 128x128 大小的区域(甚至64x64)即可。这么做一方面可以大大减少计算量,另一方面图像中心区域测定的数据往往比较准确,因为其他区域的像素更容易受到相机畸变的影响。

以上两种算法得到的光流默认是双通道的 cv::Mat,两个通道分别存储每个像素在 x 轴和 y 轴方向的偏移量,求和取平均即可得到两帧图像整体的运动偏移量。

3.2 测试记录

  1. 速度测试

以下分别是 DIS算法(PRESET_MEDIUM 参数)、FB 以及两者混合取平均算法的执行结果,分别打印 dx,dy(偏移量单位:像素)和执行时间(单位:秒)。

  1. 正确性验证

两种算法可以互相验证正确性,也可以打印整个光流 flow Mat,检查是否有异常像素点。

4.参考资料

算丰学院:https://www.sophgo.com/curriculum/index.html

相关内容

热门资讯

小学三年级作文800字(优质... 小学三年级作文800字 篇一我最喜欢的动物我最喜欢的动物是猫。猫有一只灵活的身体,一双亮晶晶的大眼睛...
秋天的变化三年级作文【优选3... 秋天的变化三年级作文 篇一秋天的变化秋天是一个美丽而神奇的季节。在这个季节里,大自然的一切都在发生变...
2018世界杯足球赛作文三年... 2018世界杯足球赛作文三年级 篇一热闹的世界杯足球赛今年的夏天,全世界都沸腾了!因为2018世界杯...
可爱的灰仓鼠三年级优秀作文【... 可爱的灰仓鼠三年级优秀作文 篇一灰仓鼠是一种非常可爱的小动物,它们通常生活在森林或草地中。我非常喜欢...
三年级作文猴子下山【通用6篇... 三年级作文猴子下山 篇一猴子下山的故事,是我们小时候听过的经典故事之一。今天,我要给大家讲一个不同寻...
小学三年级作文我是妈妈的小助... 小学三年级作文我是妈妈的小助手 篇一我是妈妈的小助手我是一个小学三年级的学生,我有一个非常好的妈妈。...
三年级作文我当小家长400字... 三年级作文我当小家长400字作文大全 篇一作为三年级的小学生,我有着当小家长的责任和义务。今天,我要...
谁是我的老师作文三年级49篇... 谁是我的老师作文三年级49篇 篇一我亲爱的老师在我三年级的时候,我遇到了很多不同的老师。有的是我的班...
春节小学三年级作文300字(... 春节小学三年级作文300字 篇一快乐的春节春节是我最喜欢的节日。春节是中国最重要的传统节日,也是全家...
书的字述600字作文(优秀3... 书的字述600字作文 篇一:阅读的魅力阅读是一种独特的体验,它能够带我们进入一个全新的世界,让我们与...
三年级上册写一次游戏活动的作... 三年级上册写一次游戏活动的作文 篇一我最喜欢的游戏——躲猫猫今天,我们班组织了一次非常有趣的游戏活动...
三年级作文400字写大海(最... 三年级作文400字写大海 篇一大海大海,是一个神奇的地方。我喜欢大海,因为它给我带来了无穷的快乐和惊...
快乐的小女孩(推荐4篇) 快乐的小女孩 篇一快乐的小女孩,是一个充满活力和阳光的孩子。她总是带着灿烂的笑容,无论面对什么困难和...
我的好朋友作文三年级300字... 我的好朋友作文三年级300字 篇一我的好朋友我有一个好朋友,他叫小明。我们从小学一年级就是同班同学了...
三年级等我长胡子的时候作文(... 三年级等我长胡子的时候作文 篇一当我还是一个年幼的三年级学生时,我对长大充满了幻想和向往。我时常幻想...
三年级作文250字(精彩6篇... 三年级作文250字 篇一我的暑假生活暑假终于来了!我迫不及待地开始了我美妙的暑假生活。首先,我去了海...
三年级暑假作文300字【优选... 三年级暑假作文300字 篇一我的暑假生活暑假终于来了,我盼望了很久的假期终于到来了。这个暑假,我过得...
三年级难忘的作文不少于250... 篇一:三年级难忘的作文记得那是我三年级的一个阳光明媚的早晨,我正坐在教室里,等待着老师给我们布置作文...
猜猜他是谁三年级作文600字... 猜猜他是谁三年级作文600字9篇 篇一猜猜他是谁我有一个好朋友,他总是戴着一顶红色的帽子,穿着一件蓝...
三年级下册作文文明的一件事(... 三年级下册作文文明的一件事 篇一文明的一件事在我们的日常生活中,有许多小事都可以展现出我们的文明素养...