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

相关内容

热门资讯

六一儿童节活动节目的主持词 六一儿童节活动节目的主持词(精选7篇)  主持词是各种演出活动和集会中主持人串联节目的串联词。在当今...
公司员工的感谢词 公司员工的感谢词3篇  我们虽然是公司的一名员工,其实也是公司的主人,需要有将公司当成家的态度,态度...
毕业晚会的主持稿 毕业晚会的主持稿(精选11篇)  在现在社会,我们很多时候都不得不用到主持稿,主持稿是主持人为节目进...
《加油金三顺》经典台词 《加油金三顺》经典台词  1、回忆是没有任何力量的。(三顺)  2、人都知道会死,但不还是活着吗?(...
升学酒会主持词 升学酒会主持词  借鉴诗词和散文诗是主持词的一种写作手法。在如今这个时代,司仪等是很多场合都需要的角...
秋季开学典礼颁奖主持词 秋季开学典礼颁奖主持词  活动对象的不同,主持词的写作风格也会大不一样。在人们积极参与各种活动的今天...
老人寿宴致辞 老人寿宴致辞(精选7篇)  在我们平凡的日常里,许多人都写过致辞吧,致辞具有“礼仪性”或“仪式化”的...
经典高考升学宴主持词   尊敬的各位领导、各位嘉宾、各位亲朋好友:  大家好!8月,理想赤诚、热爱挚烈,8月,阳光灿烂、收...
中秋晚会主持稿 中秋晚会主持稿(精选5篇)  又到了一个激动人心的好日子!中秋合家团圆,是中华民族的传统习俗。下面是...
男孩满月酒主持词 男孩满月酒主持词  主持词要注意活动对象,针对活动对象写相应的主持词。在各种集会、活动不断增多的社会...
婚礼司仪主持词简短版 婚礼司仪主持词简短版  借鉴诗词和散文诗是主持词的一种写作手法。在人们积极参与各种活动的今天,各种集...
培训主持词 【精华】培训主持词八篇  借鉴诗词和散文诗是主持词的一种写作手法。在当今不断发展的世界,很多晚会、集...
婚礼主持词完整版 2017婚礼主持词(完整版)  无论新人举行什么样形式的婚礼,婚礼主持人是必不能少的。那么婚礼司仪全...
《哈利波特》的经典语录台词 《哈利波特》的经典语录台词  “就看你的了,哈利,要使他们看到,作为一名找球手,单靠一个有钱的爸爸是...
前任2备胎反击战经典台词 前任2备胎反击战经典台词  1、一见钟情太肤浅,日久生情才是真。  2、再深的感情也敌不过缘分的交错...
生日宴会主持词开场白 生日宴会主持词开场白(精选19篇)  【导语】一个好的活动开展,主持人的开场一定要和活动的主题相契合...
大学军训汇报表演主持词 大学军训汇报表演主持词  军训汇演是必不可少的,下面unjs小编整理了大学军训汇报表演主持词,欢迎阅...
闭幕词 闭幕词(通用10篇)  闭幕词,是会议的主要领导人代表会议举办单位,在会议闭幕时的讲话。其内容一般是...
班歌串词 班歌串词尊敬的领导、亲爱的同学们:大家上午好!(合)请全体起来,齐唱《美佛儿校歌》请坐!今天我们隆重...
幼儿园元旦活动主持词开场白   一、主持人开场白:  (亲爱的爸爸妈妈,小朋友们,大家新年好!因为您的孩子,我们走到了一起,形成...