opencv透视变换

对于不同的图片,图片预处理可能需要修改,比如滤波,形态学处理等; 

#include<opencv2/opencv.hpp>
#include<highgui/highgui.hpp>
using namespace std;
using namespace cv;

int main() {
	Mat src = imread("1.jpg");
	imshow("input", src);
	Mat src_clone = src.clone();
	cvtColor(src, src, CV_BGR2GRAY);
	//GaussianBlur(src, src, Size(5, 5), 0, 0);
	int height = src.rows;
	int width = src.cols;
	adaptiveThreshold(src, src, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV, 25, 10);

	Mat kernel = getStructuringElement(MORPH_RECT, Size(5,5), Point(-1, -1));
	morphologyEx(src, src, MORPH_CLOSE, kernel, Point(-1, -1), 2);
	imshow("1", src);
	Mat drawImg = Mat::zeros(src.size(), CV_8UC3);
	vector<vector<Point>> contours;
	vector<Vec4i> hearichy;
	Rect rect;
	findContours(src, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
		for (size_t t = 0; t < contours.size(); t++) {
		//最大外接矩形,透视变换使用
		rect = boundingRect(contours[(int)t]);
		drawContours(drawImg, contours, (int)t, Scalar(0,0,255), 2, 8, hearichy);
		//rectangle(drawImg, rect, Scalar(255,0,0), 1, 8);
	}
	imshow("contours", drawImg);
	vector<Vec4i> lines;
	Mat contourImg;
	//霍夫直线检测需要灰度图
	cvtColor(drawImg, contourImg, COLOR_BGR2GRAY);
	int accu = min(src.rows * 0.5, src.cols * 0.5);
	HoughLinesP(contourImg, lines, 1, CV_PI / 180.0, accu, accu, 0);
	Mat lineImg = Mat::zeros(src.size(), CV_8UC3);
	for (size_t t = 0; t < lines.size(); t++) {
		Vec4i ln = lines[t];
		line(lineImg, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(255, 0, 0), 2, 8, 0);

	}
	cout << "lines number:" << lines.size() << endl;
	imshow("lines", lineImg);

	//寻找上下左右四条线
	int deltah = 0;
	Vec4i top, bottom;
	Vec4i left, right;
	for (int i = 0; i < lines.size(); i++) {
		Vec4i ln = lines[i];
		deltah = abs(ln[3] - ln[1]);
		if (ln[3] < height * 0.5 && ln[1] < height * 0.5 ) {
			top = ln;
			line(lineImg, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 255, 0), 2, 8, 0);
		}
		if (ln[3] > height * 0.5 && ln[1] > height * 0.5) {
			bottom = ln;
			line(lineImg, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(255, 255, 0), 2, 8, 0);
		}
		if (ln[0] > height * 0.5 && ln[2] > height * 0.5) {
			right = ln;
			line(lineImg, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 255, 255), 2, 8, 0);
		}
		if (ln[0] < height * 0.5 && ln[2] < height * 0.5) {
			left = ln;
			line(lineImg, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(255, 0, 255), 2, 8, 0);
		}
	}

	imshow("find four lines", lineImg);


	//拟合四条直线方程 y=kx+c
	//top
	float k1, c1;
	k1 = float(top[3] - top[1]) / float(top[2] - top[0]);
	c1 = top[1] - k1 * top[0];
	cout << "top: y = " << k1 << "x + " << c1 << endl;

	//bottom
	float k2, c2;
	k2 = float(bottom[3] - bottom[1]) / float(bottom[2] - bottom[0]);
	c2 = bottom[1] - k2 * bottom[0];
	cout << "bottom: y = " << k2 << "x + " << c2 << endl;
	
	//right
	float k3, c3;
	k3 = float(right[3] - right[1]) / float(right[2] - right[0]);
	c3 = right[1] - k3 * right[0];
	cout << "right: y = " << k3 << "x + " << c3 << endl;

	//left
	float k4, c4;
	k4 = float(left[3] - left[1]) / float(left[2] - left[0]);
	c4 = left[1] - k4 * left[0];
	cout << "left: y = " << k4 << "x + " << c4 << endl;

	//求四条线交点 y=k1x+c1;y=k2x+c2; x = (c1-c2)/(k2-k1)
	//top,left
	Point top_left;
	top_left.x = static_cast<int>((c1 - c4) / (k4 - k1));
	top_left.y = static_cast<int>(k1 * top_left.x + c1);
	cout << "左上角:p<x,Y>=<" << top_left.x << "," << top_left.y << ">" << endl;
	//top,right
	Point top_right;
	top_right.x = static_cast<int>((c1 - c3) / (k3 - k1));
	top_right.y = static_cast<int>(k1 * top_right.x + c1);
	cout << "右上角:p<x,Y>=<" << top_right.x << "," << top_right.y << ">" << endl;
	//bottom,left
	Point bottom_left;
	bottom_left.x = static_cast<int>((c2 - c4) / (k4 - k2));
	bottom_left.y = static_cast<int>(k2 * bottom_left.x + c2);
	cout << "左下角:p<x,Y>=<" << bottom_left.x << "," << bottom_left.y << ">" << endl;
	//bottom,right
	Point bottom_right;
	bottom_right.x = static_cast<int>((c2 - c3) / (k3 - k2));
	bottom_right.y = static_cast<int>(k2 * bottom_right.x + c2);
	cout << "右下角:p<x,Y>=<" << bottom_right.x << "," << bottom_right.y << ">" << endl;

	//画出四个点
	Mat pointImg = Mat::zeros(src.size(), CV_8UC3);
	circle(pointImg, top_left, 2, Scalar(0, 0, 255), 2, 8);
	circle(pointImg, top_right, 2, Scalar(0, 0, 255), 2, 8);
	circle(pointImg, bottom_left, 2, Scalar(0, 0, 255), 2, 8);
	circle(pointImg, bottom_right, 2, Scalar(0, 0, 255), 2, 8);
	imshow("find four points", pointImg);

	//透视变换
	vector<Point2f> src_comers(4);
	src_comers[0] = top_left;
	src_comers[1] = top_right;
	src_comers[2] = bottom_right;
	src_comers[3] = bottom_left;

	vector <Point2f> dst_comers(4);
	dst_comers[0] = Point(0, 0);
	dst_comers[1] = Point(rect.width, 0);
	dst_comers[2] = Point(rect.width, rect.height);
	dst_comers[3] = Point(0, rect.height);
	
	//获取变换矩阵
	Mat warpmatrix = getPerspectiveTransform(src_comers, dst_comers);
	Mat result = Mat::zeros(Size(rect.width, rect.height), src_clone.type());
	warpPerspective(src_clone, result, warpmatrix, result.size(), INTER_LINEAR);
	imshow("result", result);
	waitKey();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40238526/article/details/89709042