前面的博客《OpenCV拉伸图像》介绍了如何利用OpenCV的现成函数实现图像的透视变换。本文受到了《http://blog.csdn.net/xiaowei_cqu/article/details/26471527》的启发,利用OpenMP实现对透视变换的加速。

1)启用OpenMP。openmp的使用很简单,只要是vs2010或以上的环境都可以使用。在需要使用的文件开头包含 <omp.h>,然后在“项目属性>c/c++>语言" 里选择openMP支持:

2)根据http://blog.csdn.net/xiaowei_cqu/article/details/26471527的代码,我做了一些修改,利用宏定义 "#prgma omp parallel for"并行加速。代码的具体含义请参见http://blog.csdn.net/xiaowei_cqu/article/details/26471527。

#include <vector>
#include <omp.h>class PerspectiveTransform
{
public:PerspectiveTransform::PerspectiveTransform(float inA11, float inA21, float inA31, float inA12, float inA22, float inA32, float inA13, float inA23, float inA33);float a11, a21, a31, a12, a22, a32, a13, a23, a33;static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1,float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p,float x3p, float y3p);static PerspectiveTransform squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2,float y2, float x3, float y3);static PerspectiveTransform quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2,float y2, float x3, float y3);PerspectiveTransform buildAdjoint();PerspectiveTransform times(PerspectiveTransform other);void transformPoints(std::vector<float> &points);void pntProjection(unsigned char *pSrc, int iSrcWidth, int iSrcHeight,unsigned char * pDst, int iDstWidth, int iDstHeight);
};
#include "Perspective.h"PerspectiveTransform::PerspectiveTransform(float inA11, float inA21, float inA31, float inA12, float inA22, float inA32, float inA13, float inA23, float inA33) : a11(inA11), a12(inA12), a13(inA13), a21(inA21), a22(inA22), a23(inA23),a31(inA31), a32(inA32), a33(inA33) {}PerspectiveTransform PerspectiveTransform::quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1,float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p,float x3p, float y3p) {PerspectiveTransform qToS = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);PerspectiveTransform sToQ =PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);return sToQ.times(qToS);
}PerspectiveTransform PerspectiveTransform::squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2,float y2, float x3, float y3) {float dx3 = x0 - x1 + x2 - x3;float dy3 = y0 - y1 + y2 - y3;if (dx3 == 0.0f && dy3 == 0.0f) {PerspectiveTransform result(PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f,0.0f, 1.0f));return result;} else {float dx1 = x1 - x2;float dx2 = x3 - x2;float dy1 = y1 - y2;float dy2 = y3 - y2;float denominator = dx1 * dy2 - dx2 * dy1;float a13 = (dx3 * dy2 - dx2 * dy3) / denominator;float a23 = (dx1 * dy3 - dx3 * dy1) / denominator;PerspectiveTransform result(PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0+ a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f));return result;}
}PerspectiveTransform PerspectiveTransform::quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2,float y2, float x3, float y3) {// Here, the adjoint serves as the inverse:return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();
}PerspectiveTransform PerspectiveTransform::buildAdjoint() {// Adjoint is the transpose of the cofactor matrix:PerspectiveTransform result(PerspectiveTransform(a22 * a33 - a23 * a32, a23 * a31 - a21 * a33, a21 * a32- a22 * a31, a13 * a32 - a12 * a33, a11 * a33 - a13 * a31, a12 * a31 - a11 * a32, a12 * a23 - a13 * a22,a13 * a21 - a11 * a23, a11 * a22 - a12 * a21));return result;
}PerspectiveTransform PerspectiveTransform::times(PerspectiveTransform other) {PerspectiveTransform result(PerspectiveTransform(a11 * other.a11 + a21 * other.a12 + a31 * other.a13,a11 * other.a21 + a21 * other.a22 + a31 * other.a23, a11 * other.a31 + a21 * other.a32 + a31* other.a33, a12 * other.a11 + a22 * other.a12 + a32 * other.a13, a12 * other.a21 + a22* other.a22 + a32 * other.a23, a12 * other.a31 + a22 * other.a32 + a32 * other.a33, a13* other.a11 + a23 * other.a12 + a33 * other.a13, a13 * other.a21 + a23 * other.a22 + a33* other.a23, a13 * other.a31 + a23 * other.a32 + a33 * other.a33));return result;
}void PerspectiveTransform::transformPoints(std::vector<float> &points) {int max = points.size();for (int i = 0; i < max; i += 2) {float x = points[i];float y = points[i + 1];float denominator = a13 * x + a23 * y + a33;points[i] = (a11 * x + a21 * y + a31) / denominator;points[i + 1] = (a12 * x + a22 * y + a32) / denominator;}
}void PerspectiveTransform::pntProjection(unsigned char *pSrc, int iSrcWidth, int iSrcHeight,unsigned char * pDst, int iDstWidth, int iDstHeight)
{
#pragma omp parallel forfor(int iX = 0; iX < iSrcWidth; iX++){for(int iY = 0; iY < iSrcHeight; iY++){float denominator = a13 * iX + a23 * iY + a33;int iDstX = (a11 * iX + a21 * iY + a31) / denominator;int iDstY = (a12 * iX + a22 * iY + a32) / denominator;//仅处理映射在目标区域之内的点if(iDstX >= 0 && iDstX < iDstWidth && iDstY >= 0 && iDstY < iDstHeight){pDst[iDstX + iDstY * iDstWidth] = pSrc[iX + iSrcWidth * iY];}}}
}

然后用main.cpp引用以上函数,实现透视变换:

#include "Perspective.h"
#include <opencv2/opencv.hpp>
#include <ctime>
#include <iostream>
#include <Windows.h>
#include <WinBase.h>#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_core249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_imgproc249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_highgui249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_features2d249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_contrib249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_legacy249d.lib")  using namespace cv;
using namespace std;int main()
{SYSTEMTIME start, end;Mat img=imread("E:\\hehe.png");int img_height = img.rows;int img_width = img.cols;Mat img_trans = Mat::zeros(img_height,img_width,CV_8UC1);/*CV_8UC3*/PerspectiveTransform tansform = PerspectiveTransform::quadrilateralToQuadrilateral(/*前面的8个坐标是源图的位置*/0,0,img_width-1,0,0,img_height-1,img_width-1,img_height-1,/*后面8个坐标是目标图的位置*/0,0, // top left670,200, // top right0,300,// bottom left350,440);unsigned char *p1 = img.ptr<unsigned char>(0);unsigned char *p2 = new unsigned char[img_width * img_height];//由于img是rgb三通道的,而我的变换仅限于1通道灰度图,所以变换之前,先从img中提取一个通道for(int i = 0; i < img_width; i++){for(int j =0; j < img_height; j++){p2[j * img_width + i] = p1[j * img_width * 3 + i * 3];}}GetLocalTime(&start);std::cout<<start.wMilliseconds<<"\n";tansform.pntProjection(p2, img_width, img_height,img_trans.ptr<unsigned char>(0), img_width, img_height);GetLocalTime(&end);std::cout<<end.wMilliseconds<<"\n";delete [] p2;std::cin.get();imwrite("E:\\trans.png",img_trans);return 0;
}

源图:

目标图(结果):

由于有一些目标图的像素没有被源图赋值(被拉长的区域肯定有对不上源图的点),导致目标图出现一些黑点。从加速的结果看,效果与#pragma omp parallel for的位置关系很大。目前还在总结规律。

利用OpenMP加速拉伸图像操作相关推荐

  1. 利用python进行png图像的读写操作

    利用python进行png图像的读写操作 最近遇到了对png灰度图像进行读取,并统计图像中众数的需求,现将代码记录如下.ps:适用于单波段图,形如(X,Y). 1.导入需要的包 import matp ...

  2. 【深度学习】万字综述:用于深度神经网络加速的Shift操作

    作者丨科技猛兽 编辑丨极市平台 导读 如何同时满足减少可学习参数的数量以及维持computation/memory access比值?你需要Shift操作.本文将详细介绍shift操作的具体方法.如何 ...

  3. Python计算机视觉编程第一章 基本的图像操作与处理

    基本的图像操作与处理 一.基本介绍 1.1PIL:Python图像处理类库 1.2Matplotlib 1.3Numpy 1.4Scipy 二.例子练习 2.1PIL基础操作 2.1.1 转换图像格式 ...

  4. EGE基础:图像操作篇

    EGE专栏:EGE专栏 目录 一.EGE的图像功能 二.图片读取绘制简单演示 1. 找一张保存在电脑上的图片 2. 查看图片的路径(File path) 3. 读取图像文件并绘制到窗口上 4. 查看运 ...

  5. 利用MONAI加速医学影像学的深度学习研究

    利用MONAI加速医学影像学的深度学习研究 Accelerating Deep Learning Research in Medical Imaging Using MONAI 医学开放式人工智能网络 ...

  6. 利用 GPU 加速人工智能:新型计算模式

    纽约大学本周有一场探讨 "人工智能的未来" 的年度座谈会,Yann LeCun 邀请NVIDIA 联合创始人兼首席执行官黄仁勋 (Jen-Hsun Huang)先生在座谈会上发言. ...

  7. python计算机视觉编程——第一章(基本的图像操作和处理)

    第1章 基本的图像操作和处理 1.1 PIL:Python图像处理类库 1.1.1 转换图像格式--save()函数 1.1.2 创建缩略图 1.1.3 复制并粘贴图像区域 1.1.4 调整尺寸和旋转 ...

  8. python计算机视觉编程——基本的图像操作和处理

    python计算机视觉编程--第一章(基本的图像操作和处理) 第1章 基本的图像操作和处理 1.1 PIL:Python图像处理类库 1.1.1 转换图像格式--save()函数 1.1.2 创建缩略 ...

  9. 【编程语言】利用CImage类对图像像素的处理(图像二值化)

      最近做的课程作业需要用到CImage函数处理图像,其中涉及到读取图像以及对图像像素进行操作,在这里记录一下自己的理解. 首先是CImage类的定义和读取图片 CImage srcImage;CIm ...

最新文章

  1. 开源 SPL 优化报表应用应对没完没了
  2. java下包内继承时编译不过解决方案
  3. ES8新特性_await表达式---JavaScript_ECMAScript_ES6-ES11新特性工作笔记049
  4. node-webkit浏览器插件注册升级方式
  5. Web3D编程入门总结——WebGL与Three.js基础介绍
  6. Python.Algorithms(2nd)pdf
  7. 树莓派LINUX内核移植
  8. php构建的开源的淘宝客cms程序下载地址总结,采集插件小程序等
  9. Hive 3.1.2 国内镜像下载地址
  10. 区块链学习(1) sha256算法 c语言实现
  11. Ubuntu20.04下安装nvidia驱动
  12. 案例分析默写题1__立项管理_可行性研究的内容_可行性研究报告的内容
  13. cast 和convert和concat详解以及mysql和sqlserver兼容问题
  14. 下面最难防范的网络攻击是计算机病毒,求大神们帮帮忙,拜托了,在这先谢过了。...
  15. breakpoint
  16. 听雨小筑---开张纪念
  17. Android摄像头 只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理 底层Surface
  18. asp mysql 查询_ASP基础教程:数据库查询语言(1)
  19. 什么是分布式_什么是分布式存储?分布式云存储有什么优势?
  20. 图解分布式之:最终一致性,一致只会迟到,但绝不缺席

热门文章

  1. linux每40分钟运行一次,【linux】crontab 每 16 分钟运行一次 的执行计划?
  2. macbook proa1708_识别 MacBook Pro 机型
  3. 【计算机网络实验】动态路由协议——华为eNSP(详细实验报告+代码)
  4. Exchange 2010查询用户MAPI会话是否超过了32个session
  5. java服务内存占用过高
  6. DHTML---HTML5
  7. 利用OpenCV读图绘制栅格导航
  8. DNS劫持与路由器DNS劫持漏洞详解(附防护方法)
  9. 2022电动两轮市场格局分化,九号异军突起
  10. 小程序picker标题_微信小程序实现自定义picker选择器弹窗内容