利用OpenMP加速拉伸图像操作
生活随笔
收集整理的這篇文章主要介紹了
利用OpenMP加速拉伸图像操作
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前面的博客《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加速拉伸图像操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: R:parse函数和eval函数解析字符
- 下一篇: java bean vo_关于JavaB