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