博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用openCV取出图片中的四边形
阅读量:6986 次
发布时间:2019-06-27

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

hot3.png

1、下载Visual Studio2013 : ,直接解压安装;

2、下载openCV:  ;建议下载3.0版本的,3.1以后的版本里面不再有x86,但是vs2013中不支持V14的编译器,所以需要注意vs和opencv的版本对应,负责容易出现未知问题; 此处请参考: 

3、配置vs: 

4、注意: 引用照片时请注意照片路径: 问题基本是图片路径的问题。应将程序相应的图像放置在工程目录下(和cpp源文件同一目录下)。: 

4、截取四边形原理:  

5、截取的具体代码:

////  opencv.cpp//  功能: 图片里取出四边形//  环境搭建: //  参考地址:http://vitrum.github.io/2015/07/28/Opencv-%E5%BA%94%E7%94%A8%EF%BC%8C%E5%9B%BE%E7%89%87%E9%87%8C%E5%8F%96%E5%87%BA%E5%9B%9B%E8%BE%B9%E5%BD%A2/ //  //#include 
#include
#include
using namespace cv;using namespace std;/*** 边缘检测* @param gray - grayscale input image* @param canny - output edge image*/void getCanny(Mat gray, Mat &canny) { Mat thres; double high_thres = threshold(gray, thres, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU), low_thres = high_thres * 0.5; Canny(gray, canny, low_thres, high_thres);}struct Line { Point _p1; Point _p2; Point _center; Line(Point p1, Point p2) { _p1 = p1; _p2 = p2; _center = Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2); }};bool cmp_y(const Line &p1, const Line &p2) { return p1._center.y < p2._center.y;}bool cmp_x(const Line &p1, const Line &p2) { return p1._center.x < p2._center.x;}/*** Compute intersect point of two lines l1 and l2* @param l1* @param l2* @return Intersect Point*/Point2f computeIntersect(Line l1, Line l2) { int x1 = l1._p1.x, x2 = l1._p2.x, y1 = l1._p1.y, y2 = l1._p2.y; int x3 = l2._p1.x, x4 = l2._p2.x, y3 = l2._p1.y, y4 = l2._p2.y; if (float d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)) { Point2f 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; } return Point2f(-1, -1);}void scan(String file, bool debug = false) { // 读入原图 Mat img = imread(file); Mat img_proc; int w = img.size().width, h = img.size().height, min_w = 200; // 计算缩放比例 double scale = min(10.0, w * 1.0 / min_w); int w_proc = w * 1.0 / scale, h_proc = h * 1.0 / scale; // 缩小图片分辨率,提高计算速度 resize(img, img_proc, Size(w_proc, h_proc)); Mat img_dis = img_proc.clone(); /*获取纸的四个边*/ Mat gray, canny; cvtColor(img_proc, gray, CV_BGR2GRAY); // 用canny算子进行边缘检测 getCanny(gray, canny); // w_proc 就是缩小后的画面宽度,20是把间距20以内的线段延长拼接为一条直线 vector
lines; vector
horizontals, verticals; HoughLinesP(canny, lines, 1, CV_PI / 180, w_proc / 3, w_proc / 3, 20); for (size_t i = 0; i < lines.size(); i++) { Vec4i v = lines[i]; double delta_x = v[0] - v[2], delta_y = v[1] - v[3]; Line l(Point(v[0], v[1]), Point(v[2], v[3])); // get horizontal lines and vertical lines respectively if (fabs(delta_x) > fabs(delta_y)) { horizontals.push_back(l); } else { verticals.push_back(l); } // for visualization only if (debug) line(img_proc, Point(v[0], v[1]), Point(v[2], v[3]), Scalar(0, 0, 255), 1, CV_AA); } // 边缘情况下,当没有足够的线检测 if (horizontals.size() < 2) { if (horizontals.size() == 0 || horizontals[0]._center.y > h_proc / 2) { horizontals.push_back(Line(Point(0, 0), Point(w_proc - 1, 0))); } if (horizontals.size() == 0 || horizontals[0]._center.y <= h_proc / 2) { horizontals.push_back(Line(Point(0, h_proc - 1), Point(w_proc - 1, h_proc - 1))); } } if (verticals.size() < 2) { if (verticals.size() == 0 || verticals[0]._center.x > w_proc / 2) { verticals.push_back(Line(Point(0, 0), Point(0, h_proc - 1))); } if (verticals.size() == 0 || verticals[0]._center.x <= w_proc / 2) { verticals.push_back(Line(Point(w_proc - 1, 0), Point(w_proc - 1, h_proc - 1))); } } // 按中心点排序 sort(horizontals.begin(), horizontals.end(), cmp_y); sort(verticals.begin(), verticals.end(), cmp_x); // for visualization only if (debug) { line(img_proc, horizontals[0]._p1, horizontals[0]._p2, Scalar(0, 255, 0), 2, CV_AA); line(img_proc, horizontals[horizontals.size() - 1]._p1, horizontals[horizontals.size() - 1]._p2, Scalar(0, 255, 0), 2, CV_AA); line(img_proc, verticals[0]._p1, verticals[0]._p2, Scalar(255, 0, 0), 2, CV_AA); line(img_proc, verticals[verticals.size() - 1]._p1, verticals[verticals.size() - 1]._p2, Scalar(255, 0, 0), 2, CV_AA); } /* 透视变换 */ // define the destination image size: A4 - 200 PPI int w_a4 = 1654, h_a4 = 2339; //int w_a4 = 595, h_a4 = 842; Mat dst = Mat::zeros(h_a4, w_a4, CV_8UC3); // 求四顶点坐标 corners of destination image with the sequence [tl, tr, bl, br] vector
dst_pts, img_pts; dst_pts.push_back(Point(0, 0)); dst_pts.push_back(Point(w_a4 - 1, 0)); dst_pts.push_back(Point(0, h_a4 - 1)); dst_pts.push_back(Point(w_a4 - 1, h_a4 - 1)); // corners of source image with the sequence [tl, tr, bl, br] img_pts.push_back(computeIntersect(horizontals[0], verticals[0])); img_pts.push_back(computeIntersect(horizontals[0], verticals[verticals.size() - 1])); img_pts.push_back(computeIntersect(horizontals[horizontals.size() - 1], verticals[0])); img_pts.push_back(computeIntersect(horizontals[horizontals.size() - 1], verticals[verticals.size() - 1])); // 转换成原始图像比例尺 for (size_t i = 0; i < img_pts.size(); i++) { // for visualization only if (debug) { circle(img_proc, img_pts[i], 10, Scalar(255, 255, 0), 3); } img_pts[i].x *= scale; img_pts[i].y *= scale; } // 得到的变换矩阵 用getPerspectiveTransform计算转化矩阵,再用warpPerspective调用转化矩阵进行拉伸 Mat transmtx = getPerspectiveTransform(img_pts, dst_pts); // 应用透视变换 warpPerspective(img, dst, transmtx, dst.size()); // 保存照片到本地 imwrite("dst.jpg", dst); // for visualization only if (debug) { namedWindow("dst", CV_WINDOW_KEEPRATIO); imshow("src", img_dis); imshow("canny", canny); imshow("img_proc", img_proc); imshow("dst", dst); waitKey(0); }}int main(int argc, char** argv) { string img_path[] = { "6.jpg", "images/doc2.jpg", "images/doc3.jpg" }; scan(img_path[0]); return 0;}

效果:

原图:

识别结果:

转载于:https://my.oschina.net/freelili/blog/887879

你可能感兴趣的文章
IBATIS中关于iterate"$"与"#"的应用
查看>>
为什么要将对象序列化
查看>>
新增网址/网页 截图api[增加安全防护本接口已停用]源码可下载
查看>>
SpringMVC+Hibernate +MySql+ EasyUI实现POI导出Excel(二)
查看>>
刷leetcode第705题- 设计哈希集合
查看>>
dubbo协议参考
查看>>
SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
查看>>
读《白帽子讲Web安全》之安全意识篇(一)
查看>>
GLSL三种修饰符区别与用途(uniform,attribute和varying)
查看>>
python django django-debug-toolbar 加载缓慢,不能使用。
查看>>
操作系之进程调度及算法详解
查看>>
PHPexcel实列
查看>>
Butterknife 的简单使用 和 配合 Butterknife的插件 Zelezny
查看>>
Magento利用input type=”file”上传图片
查看>>
Android音频开发(4):如何存储和解析wav文件
查看>>
Handler延迟事件使用
查看>>
【DG】Oracle 19c使用dbca来搭建物理DG
查看>>
StringBuilder 、StringBuffer 、 String
查看>>
android studio下NDK开发
查看>>
C#MysqlHelper
查看>>