【OpenCV】透视变换-将图像由不规则四边形转换成矩形

news/2024/7/21 6:58:42 标签: OpenCV, 透视变换, 图像处理

本文是在点击打开链接基础上修改而成的,感谢原文博主提供的参考。

代码声明:近期在做身份证图像处理,由于采集问题,采集到的图像存在一定的角度偏差,成为了不规则的四边形,通过透视变换可将其转换成矩形,可以更好的进行分割。本文只提供相关函数和相关类。由于博主也是OpenCV新手,函数可能不那么完美,欢迎大家一起讨论。

class CPerspective
{  
private:   
	vector<Vec4i> lines;     
	double deltaRho;  
	double deltaTheta;  
	int minVote;     
	double minLength;     
	double maxGap;  

public:  
	CPerspective() : deltaRho(1), deltaTheta(CV_PI/180), minVote(10), minLength(0.), maxGap(0.) {}  
 
	void setAccResolution(double dRho, double dTheta) 
	{  
		deltaRho= dRho; 
		deltaTheta= dTheta;  
	}  
  
	void setMinVote(int minv) 
	{  
		minVote= minv;  
	}  
 
	void setLineLengthAndGap(double length, double gap) 
	{  
		minLength= length;  
		maxGap= gap;  
	}  

	std::vector<Vec4i> findLines(Mat& binary) 
	{  
		lines.clear();  
		HoughLinesP(binary,lines, deltaRho, deltaTheta, minVote, minLength, maxGap);  
		return lines;   
	}  

	vector<Vec4i> drawVerticalLines(Mat &image, Scalar color=Scalar(0,0,255))
	{  
		vector<Vec4i>::const_iterator iter=lines.begin();  
		vector<Vec4i> verline;

		while (iter!=lines.end()) 
		{  
			Point pt1((*iter)[0],(*iter)[1]);  
			Point pt2((*iter)[2],(*iter)[3]); 

			if(pt1.x == pt2.x || (pt2.y-pt1.y)/(pt2.x-pt1.x)>1 || (pt2.y-pt1.y)/(pt2.x-pt1.x)<-1)  
			{
				//line(image, pt1, pt2, color);  
				verline.push_back(*iter);
				++iter;  
			}
			else
				++iter;
		}  
		
		return verline; 
	}  

	vector<Vec4i> drawHorizontalLines(Mat &image, Scalar color=Scalar(0,0,255))
	{  
		vector<Vec4i>::const_iterator iter1 = lines.begin();
		vector<Vec4i>::const_iterator iter2 = lines.begin();
		vector<Vec4i>::const_iterator top_iter = iter1;
		vector<Vec4i>::const_iterator bottom_iter = iter1;
		vector<Vec4i> horline;

		int miny = (*iter1)[1], maxy = (*iter1)[1];
		while (iter1!=lines.end()) 
		{
			if(miny > (*iter1)[1])
			{
				miny = (*iter1)[1];
			    top_iter = iter1;
				iter1++;  
			}
			else
				iter1++;
		}
		Point pt_top1((*top_iter)[0],(*top_iter)[1]);  
		Point pt_top2((*top_iter)[2],(*top_iter)[3]); 
		//line(image, pt_top1, pt_top2, color);   
		horline.push_back(*top_iter);

		while (iter2!=lines.end()) 
		{
			if(maxy < (*iter2)[1])
			{
				maxy = (*iter2)[1];
			    bottom_iter = iter2;
				iter2++;  
			}
			else
				iter2++;
		}
		Point pt_bottom1((*bottom_iter)[0],(*bottom_iter)[1]);  
		Point pt_bottom2((*bottom_iter)[2],(*bottom_iter)[3]); 
		//line(image, pt_bottom1, pt_bottom2, color); 
		horline.push_back(*bottom_iter);

		return horline;  
	}  

	static CvPoint computeIntersect(Vec4i a, Vec4i b)
	{
		int x1 = a[0], y1 = a[1], x2 = a[2], y2 = a[3];
		int x3 = b[0], y3 = b[1], x4 = b[2], y4 = b[3];

		if (float d = ((float)(x1-x2) * (y3-y4)) - ((y1-y2) * (x3-x4)))
		{
			CvPoint pt;
			pt.x = ((x1*y2 - y1*x2) * (x3-x4) - (x1-x2) * (x3*y4 - y3*x4)) / d;
			pt.y = ((x1*y2 - y1*x2) * (y3-y4) - (y1-y2) * (x3*y4 - y3*x4)) / d;
			return pt;
		}
	}
}; 
IplImage* mycvPerspectiveCorrectionImage(Mat& image)
{ 
    Mat cannyMat;
    Canny (image, cannyMat, 60, 220, 3);
  
    CPerspective findVertex;  
    findVertex.setMinVote (90);  
    findVertex.setLineLengthAndGap (100,80);  
    findVertex.findLines (cannyMat);  
    vector<Vec4i> horline = findVertex.drawVerticalLines (image);  
	vector<Vec4i> verline = findVertex.drawHorizontalLines(image);

	CvPoint2D32f srcVertex[4], dstVertex[4];
	srcVertex[0].x = CPerspective::computeIntersect(horline[1], verline[0]).x; 
	srcVertex[0].y = CPerspective::computeIntersect(horline[1], verline[0]).y;  
	srcVertex[1].x = CPerspective::computeIntersect(horline[0], verline[0]).x;  
	srcVertex[1].y = CPerspective::computeIntersect(horline[0], verline[0]).y;  
	srcVertex[2].x = CPerspective::computeIntersect(horline[1], verline[1]).x;  
	srcVertex[2].y = CPerspective::computeIntersect(horline[1], verline[1]).y;  
	srcVertex[3].x = CPerspective::computeIntersect(horline[0], verline[1]).x;  
	srcVertex[3].y = CPerspective::computeIntersect(horline[0], verline[1]).y; 

	dstVertex[0].x = 0;
	dstVertex[0].y = 0;
	dstVertex[1].x = image.cols-1;
	dstVertex[1].y = 0;
	dstVertex[2].x = 0;
	dstVertex[2].y = image.rows-1;
	dstVertex[3].x = image.cols-1;
	dstVertex[3].y = image.rows-1;

	CvMat* warp_mat = cvCreateMat( 3, 3, CV_32FC1 ); 
	cvGetPerspectiveTransform( srcVertex, dstVertex, warp_mat );  

	IplImage* srcImg = &IplImage(image);
	IplImage* dstImg = cvCloneImage(srcImg);
	cvWarpPerspective(srcImg, dstImg, warp_mat, CV_INTER_LINEAR, cvScalarAll(255));  

	//cvNamedWindow( "Perspective Warp" );  
    //cvShowImage( "Perspective Warp", dstImg );  //最终是输出dst  

	return dstImg;
}

 

运行结果:原图像--目标图像



http://www.niftyadmin.cn/n/781231.html

相关文章

python colorbar xtick locator_Python pyplot.MaxNLocator方法代码示例

本文整理汇总了Python中matplotlib.pyplot.MaxNLocator方法的典型用法代码示例。如果您正苦于以下问题&#xff1a;Python pyplot.MaxNLocator方法的具体用法&#xff1f;Python pyplot.MaxNLocator怎么用&#xff1f;Python pyplot.MaxNLocator使用的例子&#xff1f;那么恭喜…

【C++】C++常见面试题汇总,持续更新中...

1:指针&#xff08;*&#xff09;、引用&#xff08;&&#xff09;、解引用&#xff08;*&#xff09;、取地址&#xff08;&&#xff09;、的概念和区别 概念&#xff1a; 指针指向一块内存&#xff0c;指针保存的是内存的地址&#xff1b;引用是变量的别名&#xff…

mysql 查看用户权限_在Navicat Premium中管理MySQL用户 - 第4部分:权限管理器工具

第4部分&#xff1a;Privilege Manager(权限管理器)工具在本系列教程中&#xff0c;我们一直在探索如何使用Navicat的旗舰产品Navicat Premium执行常见的用户管理任务。在上一篇文章中&#xff0c;我们查看了New User Object选项卡的Server Privileges&#xff0c;Privileges 和…

【C++】static关键字用法总结

C关键字static用法&#xff0c;总结了网络和C Primer的一些重要知识点&#xff0c;可能还有一些遗漏欢迎补充。 C的static有两种用法&#xff1a;面向过程程序设计中的static和面向对象程序设计中的static。前者应用于普通变量和函数&#xff0c;不涉及类&#xff1b;后者主要 …

qt及qt quick开发实战精解_[视频课程更新] 微信天气预报小程序 UI 开发部分

此教程属于开发实战系列视频教程&#xff0c;基于之前发布的 「60 集微信小程序开发视频教程」&#xff0c;更新的第二阶段视频课程。此系列课程将直接进入实战开发部分。此系列视频课程包含&#xff1a;项目初始化页面 UI 开发页面路由逻辑微信小程序云开发平台的使用小程序用…

【C++】const关键字用法总结

C关键字const用法&#xff0c;总结了网络和C Primer的一些重要知识点&#xff0c;可能还有一些遗漏欢迎补充。 CONST是C中常用的类型修饰符,常类型是指使用类型修饰符const说明的类型&#xff0c;常类型的变量或对象的值是不能被更新的。 一、CONST作用 二、CONST的使用 1、定…

华为路由器联动_鸿蒙“基因”很强大,华为新系统比肩iOS,36款手机完成升级...

华为手机这两年受到了很多消费者的青睐&#xff0c;销量和口碑变好的同时&#xff0c;带来的是品牌影响力的提升。在2019年&#xff0c;华为在全球销量上成为第二&#xff0c;华为继续发力&#xff0c;在今年的四五月份连续超越国际巨头三星&#xff0c;成功晋级全球第一大手机…

爬虫python和c语言区别_爬虫概述 - Python教程 - C语言网

网络爬虫(又称为网页蜘蛛&#xff0c;网络机器人&#xff0c;更经常的称为网页追逐者)&#xff0c;它按照一定的规则自动地抓取网络信息。1. 产生背景随着时代的进步&#xff0c;互联网上拥有大量的信息&#xff0c;但是我们该如何高效的获取这些信息成为了一个挑战&#xff0c…