再论图像拉伸操作

来源:互联网 发布:java程序员的简历 编辑:程序博客网 时间:2024/06/06 05:19

在前一篇文章《利用OpenMP加速拉伸图像操作》中,我介绍了如何利用自己写的PerspectiveTransform类来拉伸图像。但是我们在那篇博文的最后看到了,拉伸结果并不完美:图中夹杂了一些黑线和黑点。这是因为拉伸操作方式不合理:遍历源图,找到每一个源图像素点对应的目标图像素点,加以赋值。但是映射不是一一对应的,有的目标图的像素点找不到源图的对应,就成为黑点。

解决的办法是反向映射,遍历目标图的所有像素点,然后映射到源图上。把源图像素点的值赋给目标图。

实践这个想法有1个关键点:反向映射矩阵由原矩阵通过buildAdjoint()函数获取。为此,我给PerspectiveTransform类添加了新的方法pntInvProjection()

/*反向变换,遍历目标图的所有像素,获取其在源图的对应点像素值*/void PerspectiveTransform::pntInvProjection(unsigned char *pSrc, int iSrcWidth, int iSrcHeight, unsigned char * pDst, int iDstWidth, int iDstHeight){PerspectiveTransform trans = buildAdjoint();for(int iX = 0; iX < iDstWidth; iX++){for(int iY = 0; iY < iDstHeight; iY++){float denominator = trans.a13 * iX + trans.a23 * iY + trans.a33;int iSrcX = (trans.a11 * iX + trans.a21 * iY + trans.a31) / denominator;int iSrcY = (trans.a12 * iX + trans.a22 * iY + trans.a32) / denominator;if(iSrcX >= 0 && iSrcX < iSrcWidth && iSrcY >= 0 && iSrcY < iSrcHeight){pDst[iX + iY * iDstWidth] = pSrc[iSrcX + iSrcWidth * iSrcY];}}}}

在main函数里用pntInvProjection()取代pntProjection()。

#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);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];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];}}/*tansform.pntProjection(p2, img_width, img_height, img_trans.ptr<unsigned char>(0), img_width, img_height);*/tansform.pntInvProjection(p2, img_width, img_height, img_trans.ptr<unsigned char>(0), img_width, img_height);std::cin.get();imwrite("E:\\trans.png",img_trans);return 0;}

效果:



原创粉丝点击