稍加改进OpenCV的warpPerspective方法

背景知识

OpenCV的例程warpPerspective是用来矫正畸变图像,warpPerspective函数原型为:

CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst,
                                   InputArray M, Size dsize,
                                   int flags = INTER_LINEAR,
                                   int borderMode = BORDER_CONSTANT,

                                   const Scalar& borderValue = Scalar());

函数参数解释如下:

src:输入图像
dst:输出图像,图像的类型须跟原图一致
M:转换矩阵
dsize :输出图像的大小
flags :表示插值方法的组合,线性插值或者最近邻插值;如设置了可选项WARP_INVERSE_MAP(变形插值映射),则会使得转换矩阵M为逆变形
borderMode :像素外推方法

borderValue :边界为常量时使用的值,默认为0

=======

除了正式使用的warpPerspective函数以外,还有一个重要的函数---getPerspectiveTransform,获得透视转换矩阵。只有在得到了转换矩阵之后,才可以使用warpPerspective进行转换,且getPerspectiveTransform的值为warpPerspective函数的第三个参数。(说的有点啰嗦了,待会上代码就明白多了)。

getPerspectiveTransform函数原型为:

CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] );

各个参数含义:

src:输入的原图的四个角点坐标

dst:输出的四个角点坐标,输出图片应是去掉多余的像素,所以四个角点的坐标依次为(0,0),(row,0),(0,col),(row, col);row为输出图像的行数,col为其列数。

========

此代码是在参考原博文https://blog.csdn.net/dcrmg/article/details/52475777的基础上改的,此处手动@-牧野-

代码如下:

#include "core/core.hpp"  
#include "highgui/highgui.hpp"  
#include "imgproc/imgproc.hpp"  

#include <math.h>

using namespace cv;

void onMouse(int event, int x, int y, int flags, void *utsc);
Point2f srcTri[4], dstTri[4];
int clickTimes = 0;  //在图像上单击次数  
Mat image;
Mat imageWarp;
int main(int argc, char *argv[])
{
	image = imread(argv[1]);
	imshow("Source Image", image);
	setMouseCallback("Source Image", onMouse);
	waitKey();
	return 0;
}

float distance(Point2f a, Point2f b)
{
	float y = a.y - b.y;
	float x = a.x - b.x;
	return sqrt(pow(x, 2) + pow(y, 2));
}

void onMouse(int event, int x, int y, int flags, void *utsc)
{
	if (event == CV_EVENT_LBUTTONUP)   //响应鼠标左键抬起事件  
	{
		circle(image, Point(x, y), 2.5, Scalar(0, 0, 255), 2.5);  //标记选中点  
		imshow("Source Image", image);
		srcTri[clickTimes].x = x;
		srcTri[clickTimes].y = y;
		clickTimes++;
	}
	if (clickTimes == 4)
	{
		float disRow = distance(srcTri[0], srcTri[1]);
		float disCol = distance(srcTri[0], srcTri[2]);
		dstTri[0].x = 0;
		dstTri[0].y = 0;
		dstTri[1].x = disRow;
		dstTri[1].y = 0;
		dstTri[2].x = 0;
		dstTri[2].y = disCol;
		dstTri[3].x = disRow;
		dstTri[3].y = disCol;
		Mat transform = Mat::zeros(3, 3, CV_32FC1); //透视变换矩阵  
		transform = getPerspectiveTransform(srcTri, dstTri);  //获取透视变换矩阵         
		warpPerspective(image, imageWarp, transform, Size(disRow, disCol));  //透视变换  
		imshow("After WarpPerspecttive", imageWarp);
	}
}

可以看到,我只是加了一个距离公式算出输出图像的行和列;这样的话使用getPerspectiveTransform函数时会得到较准确的矩阵,也就不必在warpPerspective时自己算出应该减去多少了。

ps:今天属于清明节的第二天假期,在实验室放着音乐,写着第二篇博客,开心。加油吧!

猜你喜欢

转载自blog.csdn.net/qq_35546153/article/details/79837487