博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《图像处理实例》 之 透视变换
阅读量:4287 次
发布时间:2019-05-27

本文共 6429 字,大约阅读时间需要 21 分钟。

目的:将以下的图片转正显示

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
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
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 {  3     SourseImage = imread("1.png");  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
> contours; 19 vector
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
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
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;

void on_AdaptThreshold(int, void*){

  int k = 2 * g_Value + 1;   adaptiveThreshold(MiddleImage, OutputImage, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, k, 0);   imshow("AdaptThreshold", OutputImage);}

参考:贾志刚opencv系列

转载地址:http://bstgi.baihongyu.com/

你可能感兴趣的文章
小程序Canvas隐藏问题处理
查看>>
小程序scroll-view组件使用简介(转)
查看>>
Visual Studio Code设置中文包/配置中文语言
查看>>
Git重置登录密码问题,Git-remote Incorrect username or password ( access token )
查看>>
C#时间点字符串转换为日期,当天时间点判断
查看>>
Visual Studio Code v1.28.2发布
查看>>
js计算时间差示例
查看>>
VSCode中Vue插件使用整理
查看>>
谷歌浏览器如何隐藏控制台的警告内容打印console.warn()
查看>>
Linux小技巧1--利用NFS和Samba在source insight上快速开发应用程序
查看>>
EI(SCI) 收录国外英文期刊(计算机类),A类期刊会议
查看>>
Windows小技巧4——如何取消共享的文件夹
查看>>
跟我一起写 Makefile(一)
查看>>
跟我一起写 Makefile(二)
查看>>
跟我一起写 Makefile(三)
查看>>
双色球笔记2--保存所有双色球号码到MySQL
查看>>
爬虫笔记1--爬取墨迹天气
查看>>
转载1-Python 字符串操作
查看>>
爬虫笔记2--爬取2345网站历史天气
查看>>
C++ 重载、覆盖、隐藏
查看>>