## 《图像处理实例》 之 透视变换

opencv自带的函数“透视变换”，但是有一点，四个交点的值我们是不知道的，有几种办法：

1.直接用鼠标去Image watch去查看四个交点的值。

2.用角点检测算法。。。我现在还没学到。

3.使用数学知识，求四条直线然后进行求取。

 1 Point p1; // 左上角
2     p1.x = 13;
3     p1.y = 65;
4     Point p2; // 右上角
5     p2.x = 474;
6     p2.y = 58;
7     Point p3; // 左下角
8     p3.x = 48;
9     p3.y = 310;
10     Point p4; // 右下角
11     p4.x = 461;
12     p4.y = 317;
13
14     // 透视变换
15     vector<Point2f> src_corners(4);
16     src_corners[0] = p1;
17     src_corners[1] = p2;
18     src_corners[2] = p3;
19     src_corners[3] = p4;
20     int width, height;
21     width = SourseImage.cols;
22     height = SourseImage.rows;
23
24     vector<Point2f> dst_corners(4);
25     dst_corners[0] = Point(0, 0);
26     dst_corners[1] = Point(width, 0);
27     dst_corners[2] = Point(0, height);
28     dst_corners[3] = Point(width, height);
29
30     // 获取透视变换矩阵
31     Mat warpmatrix = getPerspectiveTransform(src_corners, dst_corners);
32     warpPerspective(SourseImage, OutputImage, warpmatrix, SourseImage.size(), INTER_LINEAR);
33     imshow("123", SourseImage);

效果图如下：就是手工输入有点牵强~~

高斯滤波-->>灰度-->>二值化

直线检测：（这个参数得适当的调整，不然效果很差）

代码：

  1 int main(int argc, char** argv)
2 {
4     if (SourseImage.empty()) return -1;
5     imshow("sourse", SourseImage);
6     //-------------------预处理----------------------//
7     GaussianBlur(SourseImage, MiddleImage, Size(3, 3), 3, 3);
8     cvtColor(MiddleImage, MiddleImage, CV_BGR2GRAY);
9     threshold(MiddleImage, MiddleImage, 0, 255, THRESH_BINARY | THRESH_OTSU);
10     imshow("threImage", MiddleImage);
11     //-------------------形态学操作-----------------//
12     Mat kernel = getStructuringElement(MORPH_RECT, Size(27, 27));
13     morphologyEx(MiddleImage, MiddleImage, MORPH_OPEN, kernel);
14     morphologyEx(MiddleImage, MiddleImage, MORPH_OPEN, kernel);
15     bitwise_not(MiddleImage, MiddleImage, Mat());
16     imshow("morphology", MiddleImage);
17     //----------------------边缘检测-----------------------------//
18     vector<vector<Point>> contours;
19     vector<Vec4i> hierarchy;
20     Mat testImage = Mat::zeros(MiddleImage.size(), MiddleImage.type());
21     findContours(MiddleImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
22     for (size_t i = 0; i < contours.size(); i++)
23     {
24         drawContours(testImage, contours, i, Scalar(255, 255, 255), 1);
25     }
26     imshow("contours", testImage);
27
28     int width = SourseImage.cols;
29     int height = SourseImage.rows;
30     //--------------------------霍夫直线检测------------------------//
31     vector<Vec4i> lines;
32     int accu = min(width*0.3, height*0.3);
33     HoughLinesP(testImage, lines, 1, CV_PI / 360, accu, accu, 40);//参数最好用图片的长宽变换来的，容易移植
34     Mat lineImage = Mat::zeros(MiddleImage.size(), MiddleImage.type());
35     for (size_t i = 0; i < lines.size(); i++)
36     {
37         line(lineImage, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(255, 255, 255), 1, 8, 0);
38     }
39     imshow("lines", lineImage);
40     //-----------------查找线段对应的矩形边界------------------//
41     Vec4i topline, bottomline, leftline, rightline;
42     for (size_t i = 0; i < lines.size(); i++)
43     {
44         double roti = abs(lines[i][3] - lines[i][1]);
45         //判断是平行X轴还是平行Y轴-->>|y2-y1|
46         if (roti < SourseImage.cols / 3)//平行X轴（上下两条边）
47         {
48             if (lines[i][1] < SourseImage.rows / 2 && lines[i][3] < SourseImage.rows / 2) topline = lines[i];
49             else bottomline = lines[i];
50         }
51         else//左右两条边
52         {
53             if (lines[i][0] < SourseImage.cols / 2 && lines[i][2] < SourseImage.cols / 2) leftline = lines[i];
54             else rightline = lines[i];
55         }
56     }
57     //--------------------计算四条线段的交点-----------------------//
58     double b_top, b_bot, b_rit, b_lef;
59     double k_top, k_bot, k_rit, k_lef;
60     Point lef_top, rit_top, lef_bot, rit_bot;
61     //直线斜率
62     k_top = (topline[3] - topline[1]) / (topline[2] - topline[0]);
63     k_bot = (bottomline[3] - bottomline[1]) / (bottomline[2] - bottomline[0]);
64     k_rit = (rightline[3] - rightline[1]) / (rightline[2] - rightline[0]);
65     k_lef = (leftline[3] - leftline[1]) / (leftline[2] - leftline[0]);
66     //直线表达式因子，推到一遍就知道了
67     b_top = topline[3] - k_top*topline[2];
68     b_bot = bottomline[3] - k_bot*bottomline[2];
69     b_rit = rightline[3] - k_rit*rightline[2];
70     b_lef = leftline[3] - k_lef*leftline[2];
71     //计算交点值
72     lef_top.x = abs((b_top - b_lef) / (k_top - k_lef));
73     rit_top.x = abs((b_top - b_rit) / (k_top - k_rit));
74     lef_bot.x = abs((b_bot - b_lef) / (k_bot - k_lef));
75     rit_bot.x = abs((b_bot - b_rit) / (k_bot - k_rit));
76
77     lef_top.y = abs(k_top*lef_top.x + b_top);
78     rit_top.y = abs(k_top*rit_top.x + b_top);
79     lef_bot.y = abs(k_bot*lef_bot.x + b_bot);
80     rit_bot.y = abs(k_bot*rit_bot.x + b_bot);
81     //画出交点
82     Mat lastImage = Mat::zeros(MiddleImage.size(), CV_8UC3);
83     circle(lastImage, lef_top, 5, Scalar(0, 0, 255));
84     circle(lastImage, rit_top, 5, Scalar(0, 0, 255));
85     circle(lastImage, lef_bot, 5, Scalar(0, 0, 255));
86     circle(lastImage, rit_bot, 5, Scalar(0, 0, 255));
87     imshow("circle", lastImage);
88     //-------------------------透视变换------------------------//
89     //存储需要变换的四点
90     vector<Point2f> srcPoint(4), dstPoint(4);
91     srcPoint[0] = lef_top;
92     srcPoint[1] = rit_top;
93     srcPoint[2] = lef_bot;
94     srcPoint[3] = rit_bot;
95
96     dstPoint[0] = Point2f(0, 0);
97     dstPoint[1] = Point2f(SourseImage.cols, 0);
98     dstPoint[2] = Point2f(0, SourseImage.rows);
99     dstPoint[3] = Point2f(SourseImage.cols, SourseImage.rows);
100
101     Mat Change = getPerspectiveTransform(srcPoint,dstPoint);
102     warpPerspective(SourseImage, OutputImage, Change, OutputImage.size());
103     imshow("test",OutputImage);
104     waitKey(0);
105     return 0;
106 }

g_Value =95；

{
int k = 2 * g_Value + 1;