一个openMP编程处理图像的示例:

从硬盘读入两幅图像,对这两幅图像分别提取特征点,特征点匹配,最后将图像与匹配特征点画出来。理解该例子需要一些图像处理的基本知识,我不在此详细介绍。另外,编译该例需要opencv,我用的版本是2.3.1,关于opencv的安装与配置也不在此介绍。我们首先来看传统串行编程的方式。

 1 #include "opencv2/highgui/highgui.hpp" 2 #include "opencv2/features2d/features2d.hpp" 3 #include <iostream> 4 #include <omp.h> 5 int main( ){ 6     cv::SurfFeatureDetector detector( 400 );     7     cv::SurfDescriptorExtractor extractor; 8     cv::BruteForceMatcher<cv::L2<float> > matcher; 9     std::vector< cv::DMatch > matches;10     cv::Mat im0,im1;11     std::vector<cv::KeyPoint> keypoints0,keypoints1;12     cv::Mat descriptors0, descriptors1;13     double t1 = omp_get_wtime( );14     //先处理第一幅图像15     im0 = cv::imread("rgb0.jpg", CV_LOAD_IMAGE_GRAYSCALE );16     detector.detect( im0, keypoints0);17     extractor.compute( im0,keypoints0,descriptors0);18     std::cout<<"find "<<keypoints0.size()<<"keypoints in im0"<<std::endl;19     //再处理第二幅图像20     im1 = cv::imread("rgb1.jpg", CV_LOAD_IMAGE_GRAYSCALE );21     detector.detect( im1, keypoints1);22     extractor.compute( im1,keypoints1,descriptors1);23     std::cout<<"find "<<keypoints1.size()<<"keypoints in im1"<<std::endl;24     double t2 = omp_get_wtime( );25     std::cout<<"time: "<<t2-t1<<std::endl;26     matcher.match( descriptors0, descriptors1, matches );27     cv::Mat img_matches;28     cv::drawMatches( im0, keypoints0, im1, keypoints1, matches, img_matches ); 29     cv::namedWindow("Matches",CV_WINDOW_AUTOSIZE);30     cv::imshow( "Matches", img_matches );31     cv::waitKey(0);32     return 1;33 }

很明显,读入图像,提取特征点与特征描述子这部分可以改为并行执行,修改如下:

 1 #include "opencv2/highgui/highgui.hpp" 2 #include "opencv2/features2d/features2d.hpp" 3 #include <iostream> 4 #include <vector> 5 #include <omp.h> 6 int main( ){ 7     int imNum = 2; 8     std::vector<cv::Mat> imVec(imNum); 9     std::vector<std::vector<cv::KeyPoint>>keypointVec(imNum);10     std::vector<cv::Mat> descriptorsVec(imNum);11     cv::SurfFeatureDetector detector( 400 );    cv::SurfDescriptorExtractor extractor;12     cv::BruteForceMatcher<cv::L2<float> > matcher;13     std::vector< cv::DMatch > matches;14     char filename[100];15     double t1 = omp_get_wtime( );16 #pragma omp parallel for17     for (int i=0;i<imNum;i++){18         sprintf(filename,"rgb%d.jpg",i);19         imVec[i] = cv::imread( filename, CV_LOAD_IMAGE_GRAYSCALE );20         detector.detect( imVec[i], keypointVec[i] );21         extractor.compute( imVec[i],keypointVec[i],descriptorsVec[i]);22         std::cout<<"find "<<keypointVec[i].size()<<"keypoints in im"<<i<<std::endl;23     }24     double t2 = omp_get_wtime( );25     std::cout<<"time: "<<t2-t1<<std::endl;26     matcher.match( descriptorsVec[0], descriptorsVec[1], matches );27     cv::Mat img_matches;28     cv::drawMatches( imVec[0], keypointVec[0], imVec[1], keypointVec[1], matches, img_matches ); 29     cv::namedWindow("Matches",CV_WINDOW_AUTOSIZE);30     cv::imshow( "Matches", img_matches );31     cv::waitKey(0);32     return 1;33 }

两种执行方式做比较,时间为:2.343秒v.s. 1.2441秒

在上面代码中,为了改成适合#pragma omp parallel for执行的方式,我们用了STL的vector来分别存放两幅图像、特征点与特征描述子,但在某些情况下,变量可能不适合放在vector里,此时应该怎么办呢?这就要用到openMP的另一个工具,section,代码如下:

 1 #include "opencv2/highgui/highgui.hpp" 2 #include "opencv2/features2d/features2d.hpp" 3 #include <iostream> 4 #include <omp.h> 5 int main( ){ 6     cv::SurfFeatureDetector detector( 400 );    cv::SurfDescriptorExtractor extractor; 7     cv::BruteForceMatcher<cv::L2<float> > matcher; 8     std::vector< cv::DMatch > matches; 9     cv::Mat im0,im1;10     std::vector<cv::KeyPoint> keypoints0,keypoints1;11     cv::Mat descriptors0, descriptors1;12     double t1 = omp_get_wtime( );13 #pragma omp parallel sections14     {15 #pragma omp section16         {17             std::cout<<"processing im0"<<std::endl;18             im0 = cv::imread("rgb0.jpg", CV_LOAD_IMAGE_GRAYSCALE );19             detector.detect( im0, keypoints0);20             extractor.compute( im0,keypoints0,descriptors0);21             std::cout<<"find "<<keypoints0.size()<<"keypoints in im0"<<std::endl;22         }23 #pragma omp section24         {25             std::cout<<"processing im1"<<std::endl;26             im1 = cv::imread("rgb1.jpg", CV_LOAD_IMAGE_GRAYSCALE );27             detector.detect( im1, keypoints1);28             extractor.compute( im1,keypoints1,descriptors1);29             std::cout<<"find "<<keypoints1.size()<<"keypoints in im1"<<std::endl;30         }31     }32     double t2 = omp_get_wtime( );33     std::cout<<"time: "<<t2-t1<<std::endl;34     matcher.match( descriptors0, descriptors1, matches );35     cv::Mat img_matches;36     cv::drawMatches( im0, keypoints0, im1, keypoints1, matches, img_matches ); 37     cv::namedWindow("Matches",CV_WINDOW_AUTOSIZE);38     cv::imshow( "Matches", img_matches );39     cv::waitKey(0);40     return 1;41 }

上面代码中,我们首先用#pragma omp parallel sections将要并行执行的内容括起来,在它里面,用了两个#pragma omp section,每个里面执行了图像读取、特征点与特征描述子提取。将其简化为伪代码形式即为:

 1 #pragma omp parallel sections 2 { 3     #pragma omp section 4     { 5         function1(); 6     } 7   #pragma omp section 8     { 9         function2();10     }11 }

意思是:parallel sections里面的内容要并行执行,具体分工上,每个线程执行其中的一个section,如果section数大于线程数,那么就等某线程执行完它的section后,再继续执行剩下的section。在时间上,这种方式与人为用vector构造for循环的方式差不多,但无疑该种方式更方便,而且在单核机器上或没有开启openMP的编译器上,该种方式不需任何改动即可正确编译,并按照单核串行方式执行。

以上分享了这两天关于openMP的一点学习体会,其中难免有错误,欢迎指正。另外的一点疑问是,看到各种openMP教程里经常用到private,shared等来修饰变量,这些修饰符的意义和作用我大致明白,但在我上面所有例子中,不加这些修饰符似乎并不影响运行结果,不知道这里面有哪些讲究。

在写上文的过程中,参考了包括以下两个网址在内的多个地方的资源,不再一 一列出,在此一并表示感谢。

一个openMP编程处理图像的示例相关推荐

  1. OpenMP: OpenMP编程指南

    from: OpenMP: OpenMP编程指南 进入多核时代后,必须使用多线程编写程序才能让各个CPU核得到利用.在单核时代,通常使用操作系统提供的API来创建线程,然而,在多核系统中,情况发生了很 ...

  2. Python机器视觉编程常用数据结构与示例

    Python机器视觉编程常用数据结构与示例 本文总结了使用Python进行机器视觉(图像处理)编程时常用的数据结构,主要包括以下内容: 数据结构 通用序列操作:索引(indexing).分片(slic ...

  3. 计算机网络时延图,计算机网络中网站性能延迟加载图像的示例分析

    计算机网络中网站性能延迟加载图像的示例分析 发布时间:2021-06-09 11:38:56 来源:亿速云 阅读:95 作者:小新 这篇文章给大家分享的是有关计算机网络中网站性能延迟加载图像的示例分析 ...

  4. python的for语句打印金字塔图形_python实现输入任意一个大写字母生成金字塔的示例...

    本文将要为您介绍的是python实现输入任意一个大写字母生成金字塔的示例,具体完成步骤: 输入任意一个大写字母,生成金字塔图形 def GoldTa(input): L = [chr(i) for i ...

  5. java并发编程代码示例_java并发编程之同步器代码示例

    java并发编程之同步器代码示例 发布时间:2020-09-08 16:53:41 来源:脚本之家 阅读:58 作者:Blessing_H 同步器是一些使线程能够等待另一个线程的对象,允许它们协调动作 ...

  6. python画xy轴_python画双y轴图像的示例代码

    很多时候可能需要在一个图中画出多条函数图像,但是可能y轴的物理含义不一样,或是数值范围相差较大,此时就需要双y轴. matplotlib和seaborn都可以画双y轴图像. 一个例子: import ...

  7. python写音乐_你想过用代码来写音乐吗?我用业余时间开发的一个可以编程写音乐的python库(一)...

    最近几个月学业繁忙,但是业余时间自己开发了很多python库,内容包括数学统计,各种游戏,还有音乐等等.其实还有试着写AI方面的,但是目前还是初期进度.今天我想先介绍一下我正在开发中的一个可以编程写音 ...

  8. c语言单片机自动浇花系统,Arduino零基础C语言编程ch5-5.13综合示例–自动浇花系统...

    <Arduino零基础C语言编程ch5-5.13综合示例–自动浇花系统>由会员分享,可在线阅读,更多相关<Arduino零基础C语言编程ch5-5.13综合示例–自动浇花系统(5页珍 ...

  9. HTML5移动的代码,HTML_HTML5实现一个能够移动的小坦克示例代码,复制代码代码如下: !DOCTYPE h - phpStudy...

    HTML5实现一个能够移动的小坦克示例代码 复制代码代码如下: 您的浏览器不支持canvas标签 var canvas1=document.getElementById('tankMap'); var ...

最新文章

  1. 苹果发布首款 Mac 自研芯片 M1,贯通生态快人一步!
  2. 高性能的MySQL(5)索引策略
  3. AndroidStudio常用快捷键及其设置
  4. 无极菜单 php,ThinkPHP菜单无极分类 ThinkPHP菜单无极分类实例讲解
  5. 利用 Flash 远程检测客户端安装的杀软
  6. Http方法:Get请求与Post请求的区别
  7. 【ESSD技术解读-04】ESSD Auto PL规格,引领IO性能弹性新方向
  8. java+什么时候才需要deploy_细思极恐 - 什么才是真正的会写 Java ?
  9. SpringBoot中扩展SpringMVC
  10. AST语法结构树初学者完整教程
  11. 大数据分析平台的功能
  12. 使用 Visual Studio Code 编写 TypeScript
  13. struts2整合spring3整合成功但是spring无法注入
  14. Tomcat7安装步骤
  15. mysql 拼音模糊查询_mysql中文字段转拼音首字母,以及中文拼音模糊查询
  16. SaaSpace:11种最佳免费会计软件工具
  17. https://blog.csdn.net/Darryl_Tang/article/details/80545688
  18. Fantom (FTM) 价格将在未来几天飙升 20%
  19. python爬取微博热搜显示到折线图_Python爬取新浪微博热搜榜-Go语言中文社区
  20. 618年中大促如何选择蓝牙耳机?值得买的蓝牙耳机品牌

热门文章

  1. 46 道阿里巴巴 Java 面试题,你会几道?
  2. PgSQL · 最佳实践 · CPU满问题处理
  3. python-dev 安装错误
  4. 成为人上人,而不是人上人永远的崇拜者
  5. 使用NSKeyedArchiver归档
  6. linux c socket通信
  7. 踩坑rosbag --clock
  8. linux下更换pip源
  9. Jzoj4891 摆书
  10. 201521123078 《Java程序设计》第6周学习总结