【OpenCV】透视变换-将图像由不规则四边形转换成矩形
2015-12-11 17:51
996 查看
本文是在点击打开链接基础上修改而成的,感谢原文博主提供的参考。
代码声明:近期在做身份证图像处理,由于采集问题,采集到的图像存在一定的角度偏差,成为了不规则的四边形,通过透视变换可将其转换成矩形,可以更好的进行分割。本文只提供相关函数和相关类。由于博主也是OpenCV新手,函数可能不那么完美,欢迎大家一起讨论。
运行结果:原图像--目标图像
代码声明:近期在做身份证图像处理,由于采集问题,采集到的图像存在一定的角度偏差,成为了不规则的四边形,通过透视变换可将其转换成矩形,可以更好的进行分割。本文只提供相关函数和相关类。由于博主也是OpenCV新手,函数可能不那么完美,欢迎大家一起讨论。
class CPerspective { private: vector<Vec4i> lines; double deltaRho; double deltaTheta; int minVote; double minLength; double maxGap; public: CPerspective() : deltaRho(1), deltaTheta(CV_PI/180), minVote(10), minLength(0.), maxGap(0.) {} void setAccResolution(double dRho, double dTheta) { deltaRho= dRho; deltaTheta= dTheta; } void setMinVote(int minv) { minVote= minv; } void setLineLengthAndGap(double length, double gap) { minLength= length; maxGap= gap; } std::vector<Vec4i> findLines(Mat& binary) { lines.clear(); HoughLinesP(binary,lines, deltaRho, deltaTheta, minVote, minLength, maxGap); return lines; } vector<Vec4i> drawVerticalLines(Mat &image, Scalar color=Scalar(0,0,255)) { vector<Vec4i>::const_iterator iter=lines.begin(); vector<Vec4i> verline; while (iter!=lines.end()) { Point pt1((*iter)[0],(*iter)[1]); Point pt2((*iter)[2],(*iter)[3]); if(pt1.x == pt2.x || (pt2.y-pt1.y)/(pt2.x-pt1.x)>1 || (pt2.y-pt1.y)/(pt2.x-pt1.x)<-1) { //line(image, pt1, pt2, color); verline.push_back(*iter); ++iter; } else ++iter; } return verline; } vector<Vec4i> drawHorizontalLines(Mat &image, Scalar color=Scalar(0,0,255)) { vector<Vec4i>::const_iterator iter1 = lines.begin(); vector<Vec4i>::const_iterator iter2 = lines.begin(); vector<Vec4i>::const_iterator top_iter = iter1; vector<Vec4i>::const_iterator bottom_iter = iter1; vector<Vec4i> horline; int miny = (*iter1)[1], maxy = (*iter1)[1]; while (iter1!=lines.end()) { if(miny > (*iter1)[1]) { miny = (*iter1)[1]; top_iter = iter1; iter1++; } else iter1++; } Point pt_top1((*top_iter)[0],(*top_iter)[1]); Point pt_top2((*top_iter)[2],(*top_iter)[3]); //line(image, pt_top1, pt_top2, color); horline.push_back(*top_iter); while (iter2!=lines.end()) { if(maxy < (*iter2)[1]) { maxy = (*iter2)[1]; bottom_iter = iter2; iter2++; } else iter2++; } Point pt_bottom1((*bottom_iter)[0],(*bottom_iter)[1]); Point pt_bottom2((*bottom_iter)[2],(*bottom_iter)[3]); //line(image, pt_bottom1, pt_bottom2, color); horline.push_back(*bottom_iter); return horline; } static CvPoint computeIntersect(Vec4i a, Vec4i b) { int x1 = a[0], y1 = a[1], x2 = a[2], y2 = a[3]; int x3 = b[0], y3 = b[1], x4 = b[2], y4 = b[3]; if (float d = ((float)(x1-x2) * (y3-y4)) - ((y1-y2) * (x3-x4))) { CvPoint pt; pt.x = ((x1*y2 - y1*x2) * (x3-x4) - (x1-x2) * (x3*y4 - y3*x4)) / d; pt.y = ((x1*y2 - y1*x2) * (y3-y4) - (y1-y2) * (x3*y4 - y3*x4)) / d; return pt; } } };
IplImage* mycvPerspectiveCorrectionImage(Mat& image) { Mat cannyMat; Canny (image, cannyMat, 60, 220, 3); CPerspective findVertex; findVertex.setMinVote (90); findVertex.setLineLengthAndGap (100,80); findVertex.findLines (cannyMat); vector<Vec4i> horline = findVertex.drawVerticalLines (image); vector<Vec4i> verline = findVertex.drawHorizontalLines(image); CvPoint2D32f srcVertex[4], dstVertex[4]; srcVertex[0].x = CPerspective::computeIntersect(horline[1], verline[0]).x; srcVertex[0].y = CPerspective::computeIntersect(horline[1], verline[0]).y; srcVertex[1].x = CPerspective::computeIntersect(horline[0], verline[0]).x; srcVertex[1].y = CPerspective::computeIntersect(horline[0], verline[0]).y; srcVertex[2].x = CPerspective::computeIntersect(horline[1], verline[1]).x; srcVertex[2].y = CPerspective::computeIntersect(horline[1], verline[1]).y; srcVertex[3].x = CPerspective::computeIntersect(horline[0], verline[1]).x; srcVertex[3].y = CPerspective::computeIntersect(horline[0], verline[1]).y; dstVertex[0].x = 0; dstVertex[0].y = 0; dstVertex[1].x = image.cols-1; dstVertex[1].y = 0; dstVertex[2].x = 0; dstVertex[2].y = image.rows-1; dstVertex[3].x = image.cols-1; dstVertex[3].y = image.rows-1; CvMat* warp_mat = cvCreateMat( 3, 3, CV_32FC1 ); cvGetPerspectiveTransform( srcVertex, dstVertex, warp_mat ); IplImage* srcImg = &IplImage(image); IplImage* dstImg = cvCloneImage(srcImg); cvWarpPerspective(srcImg, dstImg, warp_mat, CV_INTER_LINEAR, cvScalarAll(255)); //cvNamedWindow( "Perspective Warp" ); //cvShowImage( "Perspective Warp", dstImg ); //最终是输出dst return dstImg; }
运行结果:原图像--目标图像
相关文章推荐
- Puppet实现自动化运维
- Nginx1.1 Nginx配置文件详细说明
- Nginxs学习-1安装Nginx 将Nginx作为静态网页服务器
- CentOS安装Samba文件服务器
- Linux如何实现开机启动程序详解
- eclipse使用默认tomcat,运行两次
- Linux网卡高级命令、IP别名及多网卡绑定
- Linux中ping命令的用法
- linux 常用快捷键
- Missing org.apache.maven.archetypes:maven-archetyp
- 推荐一个PHP在线代码运行的网站
- Restful 架构设计
- 一个简单的wifi开关shell脚本实现
- linux下硬盘读写速度测试
- Nginx学习-2 使用Nginx搭建HTML web服务器 实现SSL证书安全访问
- Linux Socket编程(不限Linux)
- 在节点之间导出和导入 DOCKER 镜像
- 控制Linux kernel启动console的打印级别
- Eclipse tomcat server 无法添加项目
- 服务器监控Cacti