1赞

回答

收藏

【BPI-M2 Berry试用】opencv性能小测试(vs树莓派、nanopi)

其他 其他 4997 人阅读 | 0 人回复 | 2017-10-15

本帖最后由 ky123 于 2017-10-16 09:39 编辑

楼主申请该款开发板的目标很明确,一个是舵机控制、另一个是opencv。都说arm跑opencv是个笑话,跟别人提起想法的时候总是被笑话,但不稍微试一下又怎么知道呢。于是楼主花两三天对手头各款开发板的环境配置了一下,然后挑选了三个比较常用的图像操作函数、以及本人一个项目中的算法进行测试。
至于楼主为什么唯独让香蕉派使用2.4.9版本,在另一张吐槽贴中会提到。

(一)环境搭建
关于opencv安装问题会在另一张试用贴中提到。
qt的安装这里只需要运行
  1. sudo apt-get install qt5-default
复制代码

(二)编译过程中一些问题

问题描述一:
  1. QtOpenCV: error while loading shared libraries: libopencv_core.so.3.2: cannot open shared object file: No such file or directory
复制代码
解决方法:
问题是由于系统不知道libopencv_core.so.3.2放在哪里,只需要在OpenCV.conf中说明就好:
在这个路径中:
  1. cd /etc/ld.so.conf.d
复制代码
创建文件:
  1. mkdir OpenCV.conf
复制代码
在文件中写入库的安装路径(根据你编译时的路径填写,具体情况可以看我别的试用贴):
  1. /etc/local/lib
复制代码
启动:
  1. sudo ldconfig
复制代码
问题描述二:
  1. EOF in backquote substitution
复制代码
解决方法:
这是pro文件里面有个`的字符,一开始看起来好像是屏幕的脏点,结果怎么都编译不了。


(三)编译文件搭建
本人一般是利用qt的console,方便快捷,不用搞麻烦到极点的qmake
先创建工程文件:
  1. mkdir blur.cpp
复制代码
输入代码
执行qmake
  1. qmake
复制代码
修改生成的.pro文件:
  1. QT += core
  2. QT -= gui

  3. TARGET = blur
  4. CONFIG += console
  5. CONFIG -= app_bundle

  6. TEMPLATE = app

  7. SOURCES += blur.cpp

  8. INCLUDEPATH += /usr/include \
  9. /usr/include/opencv \
  10. /usr/include/opencv2

  11. LIBS += /usr/lib/arm-linux-gnueabihf/libopencv_highgui.so \
  12. /usr/lib/arm-linux-gnueabihf/libopencv_core.so \
  13. /usr/lib/arm-linux-gnueabihf/libopencv_video.so
复制代码
其中,TARGET是生成可执行文件的文件名;
SOURCES是编译文件的文件名;
INCLUDEPATH是头文件位置,这个取决于你安装的位置,具体情况可以看我上一篇试用贴
LIBS是函数库位置,这里罗列的是一些常用的,并非全部,需要可以随时加上,这个也取决于你安装的位置,具体情况可以看我上一篇试用贴
执行编译:
  1. make
复制代码
运行:
  1. ./blur
复制代码
(四)测试源码
blur滤波:
  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <time.h>
  4. #include <stdlib.h>
  5. #include "opencv2/highgui/highgui.hpp"
  6. #include "opencv2/imgproc/imgproc.hpp"
  7. using namespace cv;

  8. int main( )
  9. {
  10. struct timespec tpstart;
  11. struct timespec tpmiddle;
  12. struct timespec tpend;
  13. long timedif;
  14. clock_gettime(CLOCK_MONOTONIC, &tpstart);

  15. //【1】载入原始图
  16. Mat srcImage = imread("/home/qt/qt_for_opencv/28.jpg");

  17. //【2】测试时间
  18. clock_gettime(CLOCK_MONOTONIC, &tpmiddle);

  19. //【3】进行均值滤波操作
  20. Mat dstImage;
  21. blur( srcImage, dstImage, Size(7, 7));

  22. //【4】显示时间
  23. clock_gettime(CLOCK_MONOTONIC, &tpend);
  24. timedif = 1000000*(tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_nsec-tpstart.tv_nsec)/1000;
  25. fprintf(stdout, "all took %ld microseconds\n", timedif);
  26. timedif = 1000000 * (tpend.tv_sec - tpmiddle.tv_sec) + (tpend.tv_nsec - tpmiddle.tv_nsec) / 1000;
  27. fprintf(stdout, "process took %ld microseconds\n", timedif);

  28. return 0;
  29. }
复制代码
canny算子:
  1. #include <opencv2/opencv.hpp>
  2. #include<opencv2/highgui/highgui.hpp>
  3. #include<opencv2/imgproc/imgproc.hpp>
  4. using namespace cv;

  5. int main()
  6. {
  7.         struct timespec tpstart;
  8.         struct timespec tpmiddle;
  9.         struct timespec tpend;
  10.         long timedif;
  11.         clock_gettime(CLOCK_MONOTONIC, &tpstart);

  12.         //载入原始图
  13.         Mat srcImage = imread("/home/qt/qt_for_opencv/28.jpg",1);  //工程目录下应该有一张名为1.jpg的素材图
  14.         Mat srcImage1 = srcImage.clone();

  15.         clock_gettime(CLOCK_MONOTONIC, &tpmiddle);

  16.         Mat dstImage, edge, grayImage;

  17.         // 【1】创建与src同类型和大小的矩阵(dst)
  18.         dstImage.create(srcImage1.size(), srcImage1.type());

  19.         // 【2】将原图像转换为灰度图像
  20.         cvtColor(srcImage1, grayImage, CV_BGR2GRAY);

  21.         // 【3】先用使用 3x3内核来降噪
  22.         blur(grayImage, edge, Size(3, 3));

  23.         // 【4】运行Canny算子
  24.         Canny(edge, edge, 3, 9, 3);

  25.         //【5】将g_dstImage内的所有元素设置为0
  26.         dstImage = Scalar::all(0);

  27.         //【6】使用Canny算子输出的边缘图g_cannyDetectedEdges作为掩码,来将原图g_srcImage拷到目标图g_dstImage中
  28.         srcImage1.copyTo(dstImage, edge);

  29.         clock_gettime(CLOCK_MONOTONIC, &tpend);
  30.         timedif = 1000000 * (tpend.tv_sec - tpstart.tv_sec) + (tpend.tv_nsec - tpstart.tv_nsec) / 1000;
  31.         fprintf(stdout, "it took %ld microseconds\n", timedif);
  32.         timedif = 1000000 * (tpend.tv_sec - tpmiddle.tv_sec) + (tpend.tv_nsec - tpmiddle.tv_nsec) / 1000;
  33.         fprintf(stdout, "it took %ld microseconds\n", timedif);

  34.         waitKey(0);

  35.         return 0;
  36. }
复制代码
contours轮廓:
  1. #include <opencv2/opencv.hpp>
  2. #include "opencv2/highgui/highgui.hpp"
  3. #include "opencv2/imgproc/imgproc.hpp"
  4. using namespace cv;
  5. using namespace std;

  6. int main()
  7. {

  8.         struct timespec tpstart;
  9.         struct timespec tpmiddle;
  10.         struct timespec tpend;
  11.         long timedif;
  12.         clock_gettime(CLOCK_MONOTONIC, &tpstart);

  13.         // 【1】载入原始图,且必须以二值图模式载入
  14.         Mat srcImage = imread("/home/qt/qt_for_opencv/28.jpg", 0);
  15.         clock_gettime(CLOCK_MONOTONIC, &tpmiddle);

  16.         //【2】初始化结果图
  17.         Mat dstImage = Mat::zeros(srcImage.rows, srcImage.cols, CV_8UC3);

  18.         //【3】srcImage取大于阈值119的那部分
  19.         srcImage = srcImage > 119;

  20.         //【4】定义轮廓和层次结构
  21.         vector<vector<Point> > contours;
  22.         vector<Vec4i> hierarchy;

  23.         //【5】查找轮廓
  24.         //此句代码的OpenCV2版为:
  25. findContours( srcImage, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
  26.         //此句代码的OpenCV3版为:
  27. //findContours(srcImage, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);

  28.         // 【6】遍历所有顶层的轮廓, 以随机颜色绘制出每个连接组件颜色
  29.         int index = 0;
  30.         for (; index >= 0; index = hierarchy[index][0])
  31.         {
  32.                 Scalar color(rand() & 255, rand() & 255, rand() & 255);
  33.                 //此句代码的OpenCV2版为:
  34. drawContours( dstImage, contours, index, color, CV_FILLED, 8, hierarchy );
  35.                 //此句代码的OpenCV3版为:
  36. //drawContours(dstImage, contours, index, color, FILLED, 8, hierarchy);
  37.         }

  38.         //【7】显示最后的轮廓图
  39.         //imshow( "轮廓图", dstImage );

  40.         clock_gettime(CLOCK_MONOTONIC, &tpend);
  41.         timedif = 1000000 * (tpend.tv_sec - tpstart.tv_sec) + (tpend.tv_nsec - tpstart.tv_nsec) / 1000;
  42.         fprintf(stdout, "it took %ld microseconds\n", timedif);
  43.         timedif = 1000000 * (tpend.tv_sec - tpmiddle.tv_sec) + (tpend.tv_nsec - tpmiddle.tv_nsec) / 1000;
  44.         fprintf(stdout, "process took %ld microseconds\n", timedif);

  45.         waitKey(0);

  46. }
复制代码
这里使用的计时是clock_gettime,可以精确到nm级别(十亿分之一秒),出于对数据读取能力差异的担忧,这里特地进行了两次测量,第一次是测总的运行时间,第二次是测单纯的图像处理时间。

(五)测试结果
一些截图:





测试平台数据:


测试结果:


这个结果也是让我有点迷糊,对于canny,竟然比512M的nano还渣?contours却稳胜了树莓派!猜测可能是由于其他都是3.3.0版本,唯独香蕉派用了2.4.9的原因。至于为什么这么做,其他的帖子会提到。以后有机会也会安装ubuntu serve编译一下3.3.0版本再进行一次测试。

关注下面的标签,发现更多相似文章
分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条