1. 程式人生 > >opencv學習筆記五十:透視變換綜合例項

opencv學習筆記五十:透視變換綜合例項

案例背景:對下圖發生畸變的影象進行校正

 方案思路:灰度二值化分割,閉操作,尋找輪廓,霍夫直線檢測,直線排序,直線方程,直線交點,透視矩陣,透視變換。

#include<opencv2\opencv.hpp>
using namespace cv;
using namespace std;
int main(int arc, char** argv) { 
	Mat src = imread("1.jpg");
	namedWindow("input", CV_WINDOW_AUTOSIZE);
	imshow("input", src);
	//灰度化
	Mat grayImg;
	cvtColor(src, grayImg, CV_BGR2GRAY);

	//二值化
	Mat binaryImg;
	threshold(grayImg, binaryImg, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);

	//閉操作
	Mat kernel = getStructuringElement(MORPH_RECT,Size(3,3));
	morphologyEx(binaryImg, binaryImg, MORPH_CLOSE,kernel,Point(-1,-1) ,3);
	imshow("output", binaryImg);

	//尋找輪廓
	Mat draw = Mat::zeros(src.size(), CV_8UC3);
	vector<vector<Point>>contours;
	findContours(binaryImg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
	for (int i = 0; i < contours.size(); i++) {
		Rect rect = boundingRect(contours[i]);
		if (rect.width < src.cols / 2 && rect.height < src.rows / 2)continue;
		drawContours(draw, contours, i, Scalar(0, 0, 255), 2);
	}
	imshow("output2", draw);

	//霍夫直線檢測
	vector<Vec4i> lines;
	cvtColor(draw, draw, CV_BGR2GRAY);
	HoughLinesP(draw, lines, 1, CV_PI / 180, src.rows/2,src.rows/2,0);
	Mat draw2 = Mat::zeros(src.size(), CV_8UC3);
	for (int j = 0; j < lines.size(); j++) {
		Vec4i ln = lines[j];
		line(draw2, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 255, 0), 2);		
	}
	printf("number of line:%d\n", lines.size());
	imshow("output3", draw2);

	//尋找與定位直線
	Vec4i topLine,bottomLine,leftLine,rightLine;
	for (int j = 0; j < lines.size(); j++) {
		Vec4i ln = lines[j];
		if (ln[1] < src.rows / 2 && ln[3] < src.rows / 2) {
			topLine = ln;
		}
		if (ln[1] > src.rows / 2 && ln[3] > src.rows / 2) {
			bottomLine = ln;
		}
		if (ln[0] < src.cols / 2 && ln[2] < src.cols / 2) {
			leftLine = ln;
		}
		if (ln[0] > src.cols / 2 && ln[2] > src.cols / 2) {
			rightLine = ln;
		}
	}
	cout << "topLine:p1(x,y)=" << topLine[0] << "," << topLine[1]<<"  " << "p2(x,y)=" << topLine[2] << "," << topLine[3] << endl;
	cout << "bottomLine:p1(x,y)=" << bottomLine[0] << "," << bottomLine[1] << "  " << "p2(x,y)=" << bottomLine[2] << "," << bottomLine[3] << endl;
	cout << "leftLine:p1(x,y)=" << leftLine[0] << "," << leftLine[1] << "  " << "p2(x,y)=" << leftLine[2] << "," << leftLine[3] << endl;
	cout << "rightLine:p1(x,y)=" << rightLine[0] << "," << rightLine[1] << "  " << "p2(x,y)=" << rightLine[2] << "," << rightLine[3] << endl;
	
	//求解直線方程
	float k1, c1;
	k1 = float((topLine[3] - topLine[1])) / float(topLine[2] - topLine[0]);
	c1 = topLine[1] - k1*topLine[0];
	float k2, c2;
	k2 = float((bottomLine[3] - bottomLine[1])) / float(bottomLine[2] - bottomLine[0]);
	c2 = bottomLine[1] - k2*bottomLine[0];
	float k3, c3;
	k3 = float((leftLine[3] - leftLine[1])) / float(leftLine[2] - leftLine[0]);
	c3 = leftLine[1] - k3*leftLine[0];
	float k4, c4;
	k4 = float((rightLine[3] - rightLine[1])) / float(rightLine[2] - rightLine[0]);
	c4 = rightLine[1] - k4*rightLine[0];
	
	//求解直線交點
	Point p1;
	p1.x = (int)((c1 - c3) / (k3 - k1));
	p1.y = (int)(k1*p1.x + c1);
	Point p2;
	p2.x = (int)((c1 - c4) / (k4 - k1));
	p2.y = (int)(k1*p2.x + c1);
	Point p3;
	p3.x = (int)((c2 - c4) / (k4 - k2));
	p3.y = (int)(k2*p3.x + c2);
	Point p4;
	p4.x = (int)((c2 - c3) / (k3 - k2));
	p4.y = (int)(k2*p4.x + c2);
	cout << "左上角:" << p1.x << "," << p1.y << endl;
	cout << "右上角:" << p2.x << "," << p2.y << endl;
	cout << "右下角:" << p3.x << "," << p3.y << endl;
	cout << "左下角:" << p4.x << "," << p4.y << endl;
	
	//畫出交點
	circle(draw2, p1, 2, Scalar(0, 0, 255));
	circle(draw2, p2, 2, Scalar(0, 0, 255));
	circle(draw2, p3, 2, Scalar(0, 0, 255));
	circle(draw2, p4, 2, Scalar(0, 0, 255));
	imshow("output4", draw2);

	//透視變換
	vector<Point2f> srcCorners(4);
	srcCorners[0] = p1;
	srcCorners[1] = p2;
	srcCorners[2] = p3;
	srcCorners[3] = p4;
	vector<Point2f> dstCorners(4);
	dstCorners[0] = Point(0, 0);
	dstCorners[1] = Point(src.cols, 0);
	dstCorners[2] = Point(src.cols, src.rows);
	dstCorners[3] = Point(0, src.rows);	
	Mat warpMartrix = getPerspectiveTransform(srcCorners, dstCorners);//Mat warpMartrix = findHomography(srcCorners, dstCorners);	
	Mat result = Mat::zeros(src.size(), -1);
	warpPerspective(src, result, warpMartrix, result.size(),INTER_LINEAR);
	imshow("output5", result);
	waitKey(0);
	return 0; 
}