1. 程式人生 > >【OpenCV】透視變換-將影象由不規則四邊形轉換成矩形

【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;
}

執行結果:原影象--目標影象


相關推薦

OpenCV透視變換-影象不規則四邊形轉換矩形

本文是在點選開啟連結基礎上修改而成的,感謝原文博主提供的參考。 程式碼宣告:近期在做身份證影象處理,由於採集問題,採集到的影象存在一定的角度偏差,成為了不規則的四邊形,通過透視變換可將其轉換成矩形,可以更好的進行分割。本文只提供相關函式和相關類。由於博主也是OpenCV新手

OpenCV透視變換矯正

file info 事件 ima 變換 data include imshow spec 演示結果參考: 功能實現:運行程序,會顯示圖片的尺寸,按回車鍵後,依次點擊需矯正的圖片的左上、右上、左下、右下角,結果彈出矯正後的圖片,如圖上的PIC2對話框。按下字符‘q‘後

OpenCV透視變換 Perspective Transformation

透視變換的原理和矩陣求解請參見前一篇《透視變換 Perspective Transformation》。在OpenCV中也實現了透視變換的公式求解和變換函式。 求解變換公式的函式: Mat getPerspectiveTransform(const Po

OpenCV透視變換 Perspective Transformation(續)

求解變換公式的函式:Mat getPerspectiveTransform(const Point2f src[], const Point2f dst[])輸入原始影象和變換之後的影象的對應4個點,便可以得到變換矩陣。之後用求解得到的矩陣輸入perspectiveTrans

轉載PADS Layout匯入DXF,並轉換板框步驟

1、在PADS Layout中選擇 Import... 2、選擇DXF檔案(一般由結構工程師給出),直接點OK即可。 3、匯入後,板框圖一角檢視如下。右鍵選擇 Select Shapes,然後雙擊外框。 4、將線的Type改成Board Outline,確定即可。如果提

OpenCV3透視變換——cv::getPerspectiveTransform()與cv::warpPerspective()詳解

透視變換(Perspective Transformation)是將成像投影到一個新的視平面(Viewing Plane),也稱作投影對映(Projective Mapping)。如圖1,通過透視變換ABC變換到A'B'C'。 圖1 透視變換示意圖

OpenCV分離多通道影象RGB的值

【1】計算影象ROI區域RGB的平均值,cvAvg函式。 【2】通道分離,合併的時候要特別的注意,分離之後的影象時單通道的灰度影象,最後面顯示的彩色影象為方便視覺觀察得到的效果。 但是我感覺還是不對,因為其他的兩個通道的顏色值不變,而想要看的通道的值取零,這樣得到的

OpencvHough變換找直線和圓

目錄 題目 解決方法 完整程式碼 Hough引數詳解 總結 參考 題目 用霍夫變換找出影象中的直線和圓(用彩色直線和圓標記在原圖上)。要求有程式碼,有註釋,有過程、有結果   解決方法 # -*- coding: UTF-8 -*- i

OpenCV3.4.0影象拼接Stitching模組介紹

Images stitching 是opencv3.4.0中的模組之一,使用此模組可以實現對影象的拼接。在此之前需要編譯opencv3.4.0+contrib。具體編譯方法可以點此連結。也可以直接

OpenCVMultiband Blender 用於影象拼縫的平滑

Multiband 融合兩張影象,最直接的方案是在兩張影象的重合區域用一個平滑漸變的權重對二者加權疊加。該方法的效果並不理想,關鍵原因是我們無法兼顧拼縫附近的局域細節和大尺度上兩張圖片的巨集觀特徵(如光照)。當我們希望局域細節能夠完好拼接時,需要用較小的平滑漸

VC++不能引數 1 從“_TCHAR”轉換為“const char* 問題解決

原因:2005預設的"使用 Unicode 字符集",解決:在你建立的解決方案的工程檔案的屬性看到選"配置屬性"的"字符集"請選擇"使用多位元組字符集"就可以了。 2005開啟6.0的檔案時候不會出現的這樣的錯誤,是因為編譯環境在轉換過程中進行了轉換. 這個解決辦法在vs 2008也適用。

131Java把\u開頭的Unicode編碼轉換漢字

最近工作中遇到需要呼叫第三方介面的需求。第三方介面返回的字串中,會把中文轉義成 \u + Unicode 的形式。因此,我需要再把 \u + Unicode 轉換成漢字。 這裡,我們需要認識到 Java 程式碼對於 \u 字元處理的內外有別。如果是編寫程式的時候

OpenCV影象資料YUV格式轉換JPG格式直接使用,而不儲存檔案

解決方法 使用OpenCV影象編碼和解碼函式:imencode、imdecode std::vector data_encode; imencode(“.png”, img_encode, dat

OpenCV影象變換(二)邊緣檢測:梯度運算元、Sobel運算元和Laplace運算元

邊緣 邊緣(edge)是指影象區域性強度變化最顯著的部分。主要存在於目標與目標、目標與背景、區域與區域(包括不同色彩)之間,是影象分割、紋理特徵和形狀特徵等影象分析的重要基礎。 影象強度的顯著變化可分為: •階躍變化函式,即影象強度在不連續處的兩邊的畫

影象處理透視變換 Perspective Transformation

透視變換(Perspective Transformation)是將圖片投影到一個新的視平面(Viewing Plane),也稱作投影對映(Projective Mapping)。通用的變換公式為:u,v是原始圖片左邊,對應得到變換後的圖片座標x,y,其中。變換矩陣可以拆成4

OpenCV圖像增強---灰度變換、直方圖均衡化

test 增強 映射 display 得到 .cpp scalar pic 重要 圖像增強的目的:改善圖像的視覺效果或使圖像更適合於人或機器的分析處理。通過圖像增強,可以減少圖像噪聲,提高目標與背景的對比度,也可以增強或抑制圖像中的某些細節。 -------------

輔助駕駛透視變換(包含鳥瞰圖、俯檢視、正檢視)小結_附仿射變換

一、目的 應用1:實現掃描功能,類似“掃描全能王APP” 應用2:輔助駕駛(行車記錄儀) 二、原理 1、仿射變換  1)定義: 仿射變換是一種二維座標到二維座標之間的線性變換。它保持了二維圖形的“平直性”(直線經過變換之後依然是直線)和“平行性”(二

輔助駕駛透視變換、仿射變換(包含鳥瞰圖、俯檢視、正檢視)[2]——俯檢視

一、效果 二、程式碼實現 1、python程式碼,基於opencv庫和imutils庫 來源:https://blog.csdn.net/qq_34199383/article/details/79571318 from imutils import perspect

學習OpenCV通過DLL實現影象資料從.dat匯入Mat

目的:主要為了將C++的影象處理部分交給C#介面,特此學習怎麼用DLL。 一、生成DLL 1、在vs中建立名為datFile的dll專案,設定包含目錄和庫目錄為opencv路徑 2、編寫datFile類的標頭檔案和實現 datFile.h #ifndef DATFILE_H

opencv影象和輪廓的匹配(hu矩)

影象的hu矩具有平移不變、尺度不變和旋轉不變性。 (1)中心矩:構造平移不變性。利用質心座標構造影象的中心矩。 (2)歸一化中心矩:構造尺度不變性。 (3)hu矩:構造旋轉不變性。 opencv的實現計算hu矩: (1)普通矩和中心矩的計算 void cvMoments(c