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

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

  1. 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. 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 for
    17 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. 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 sections
    14 {
    15 #pragma omp section
    16 {
    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 section
    24 {
    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. 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简介 openMP是一个编译器指令和库函数的集合,主要是为共享式存储计算机上的并行程序设计使用的. 当计算机升级到多核时,程序中创建的线程数量需要随CPU核数变化,如在CPU核数超过线程数 ...

  2. openMP编程(上篇)之并行程序设计

    openMP简介 openMP是一个编译器指令和库函数的集合,主要是为共享式存储计算机上的并行程序设计使用的. 当计算机升级到多核时,程序中创建的线程数量需要随CPU核数变化,如在CPU核数超过线程数 ...

  3. cesium编程中级(一)添加示例到Sandcastle

    cesium编程中级(一)添加示例到Sandcastle 添加示例到Sandcastle在cesium编程入门(七)3D Tiles,模型旋转中提到过,这里是一份完整的说明 创建例子 开启node服务 ...

  4. 推荐一个算法编程学习中文社区-51NOD【算法分级,支持多语言,可在线编译】

    最近偶尔发现一个算法编程学习的论坛,刚开始有点好奇,也只是注册了一下.最近有时间好好研究了一下,的确非常赞,所以推荐给大家.功能和介绍看下面介绍吧.首页的标题很给劲,很纯粹的Coding社区....虽 ...

  5. 【转】手把手教你把Vim改装成一个IDE编程环境(图文)

    手把手教你把Vim改装成一个IDE编程环境(图文) By: 吴垠 Date: 2007-09-07 Version: 0.5 Email: lazy.fox.wu#gmail.com Homepage ...

  6. openMP编程(下篇)之数据私有与任务调度

    title: openMP编程(下篇)之数据处理子句与任务调度 tags: ["openMP"] notebook: 分布式程序_Linux --- openMP并行编程中数据的共 ...

  7. OpenMP编程总结表

    本文对OpenMP 2.0的全部语法——Macro(宏定义).Environment Variables(环境变量).Data Types(数据类型).Compiler Directives(编译指导 ...

  8. 从一个简单的Java单例示例谈谈并发

    一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static Un ...

  9. 从一个简单的Java单例示例谈谈并发 JMM JUC

    原文: http://www.open-open.com/lib/view/open1462871898428.html 一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这 ...

随机推荐

  1. TensorFlow技术解析与实战学习笔记(15)-----MNIST识别(LSTM)

    一.任务:采用基本的LSTM识别MNIST图片,将其分类成10个数字. 为了使用RNN来分类图片,将每张图片的行看成一个像素序列,因为MNIST图片的大小是28*28像素,所以我们把每一个图像样本看成 ...

  2. 【剑指Offer】47、求1+2+3+4+···+n

      题目描述:   求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C).   解题思路:   本题本身没有太多 ...

  3. 【剑指Offer】41、和为S的连续正数序列

      题目描述:   小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数). ...

  4. Codeforces Round #548 (Div. 2) A. Even Substrings

    You are given a string 

  5. HTTP 状态码 301 和 302 详解及区别——辛酸的探索之路

    转自:http://blog.csdn.net/grandpang/article/details/47448395 一直对http状态码301和302的理解比较模糊,在遇到实际的问题和翻阅各种资料了 ...

  6. 10.01QBXT集训

    a[问题描述]你是能看到第一题的 friends呢.—— hja何大爷对字符串十分有研究,于是天出题虐杀 zhx.何大爷今天为 何大爷今天为 字符串定义了新的权值计算方法.一个由小写母组成,被定义为其 ...

  7. SDOI2017数字表格

    求$\prod_{i=1}^n\prod_{j=1}^n\text{Fib}[\gcd(i,j)]\;\text{mod}\;10^9+7$的值 令$n\leq m$,则有: \begin{align ...

  8. java链接linux服务器,命令操作

    1.本地读取linux文件,即在Windows上链接外部linux package com.common.utils; import java.io.BufferedReader; import ja ...

  9. 用windows远程桌面连接ubuntu

    从Windows 7远程到Windows系统比较简单,只要对方电脑开启远程桌面功能就可以了,但Windows 7远程桌面连接到Ubuntu 14.04比较复杂一点,具体操作步骤如下. Ubuntu 1 ...

  10. 0208MySQL5.7之Group Replication

    转自http://blog.itpub.net/29510932/viewspace-2055679/ MySQL Group Replication: Hello World! 对测试版(on la ...