参考python-opencv 图像捕捉多个不规则轮廓,与轮廓内接区域(圆/矩形)思路-持续更新编辑中(会附上详细的思路解释和图片) - Lorzen - 博客园


前言

提示:利用中心延展算法的思想,加入快扩散慢收缩,加快运行速度。由于使用矩来求轮廓的重心,并作为扩散的中心点,所以对u形的区域不友好。


以下是本篇文章正文内容,下面案例可供参考

一、源码

代码如下(示例):

//最大内接矩形,传入单个轮廓
//利用中心延展算法的思想,加入快扩散慢收缩。加快运行速度
bool MaxInnerRect(const vector<Point> &con, Rect &R) {Moments moment = moments(con);//由于使用矩来求轮廓的重心,并作为扩散的中心点,所以对u形的区域不友好,Point midPoint = Point(int(moment.m10 / moment.m00), int(moment.m01 / moment.m00));double Flag = pointPolygonTest(con, midPoint, false);if (Flag <= 0) {R.x = 0;R.y = 0;R.width = 0;R.height = 0;return false;}Rect rect = boundingRect(con);int x1, x2, y1, y2;//中心扩散的四个顶点坐标x1 = midPoint.x - 1;x2 = midPoint.x + 1;y1 = midPoint.y - 1;y2 = midPoint.y + 1;
//*********//int cnt_range, step, radio_x, radio_y;int thre = 4;//由于轮廓并非是很直的线,一个突出点会影响结果,所以要设置敏感值,太小结果不对if (rect.width > rect.height) {// 判断轮廓 X方向更长cnt_range = rect.width;    //获得长边}else {cnt_range = rect.height;}bool flag_x1 = false, flag_x2 = false, flag_y1 = false, flag_y2 = false;//定义标志,标记是否到达边缘radio_x = rect.width / 6;//根据区域的外接矩形边来决定x边扩散的步长radio_y = rect.height / 6;//根据区域的外接矩形边来决定y边扩散的步长step = cnt_range/120;//if (step<1) {   //收缩时步长等于1;step代表每次收缩时,判断点在轮廓外面的步长,必须大于等于1,同时也不能太大,会影响内接矩阵的精度step = 1;}if (step>=3) {step = 2;}//四条边分别求,每条边找到第一次出现在轮廓外的点,然后再收缩,直到找到边界//(此处为了让边不要太敏感,设置出现在轮廓外的点大于thre时,才开始收缩)for (int ix = 1; ix < cnt_range; ++ix) {if (flag_y1 == false) {y1 = y1 - radio_y;//每次扩散radio_y行int numy1 = 0;for (int i = x1; i <= x2;i=i+ step) {double p_x1y1 = pointPolygonTest(con, Point(i, y1), false);if (p_x1y1 < 0) {numy1++;}if (numy1 > thre || y1 <= rect.y) {//开始收缩for (int m = 0; m < radio_y -1 ; ++m) {int numy11 = 0;y1 = y1+ 1;     // 每次收缩1行for (int j = x1; j <= x2; j=j+ step) {double p_jy1 = pointPolygonTest(con, Point(j, y1), false);if (p_jy1 < 0) {numy11++;}if (numy11 > thre)break;//继续收缩}if (numy11 > thre)continue;//继续收缩elsebreak;//找到结果收缩结束}flag_y1 = true;break;//找到结果收缩结束}}}if (flag_x1 == false) {x1 = x1 - radio_x;int numx1 = 0;for (int i = y1; i <= y2; i = i + step) {double p_x1i = pointPolygonTest(con, Point(x1, i), false);if (p_x1i < 0) {numx1++;}if (numx1 > thre || x1<= rect.x) {//开始收缩for (int m = 0; m < radio_x - 1; ++m) {int numx11 = 0;x1 = x1 + 1;    //每次收缩1行for (int j = y1; j <= y2; j = j + step) {double p_x1j = pointPolygonTest(con, Point(x1, j), false);if (p_x1j < 0) {numx11++;}if (numx11 > thre)break;}if (numx11 > thre)continue;elsebreak;}flag_x1 = true;break;}}}if (flag_y2 == false) {y2 = y2 + radio_y;int numy2 = 0;for (int i = x1; i <= x2; i =i + step) {double p_iy2 = pointPolygonTest(con, Point(i, y2), false);if (p_iy2 < 0) {numy2++;}if (numy2 > thre || y2 >= (rect.y+rect.height)) {开始收缩for (int m = 0; m < radio_y - 1; ++m) {int numy22 = 0;y2 = y2 - 1;      //  每次收缩1行for (int j = x1; j <= x2; j = j + step) {double p_jy2 = pointPolygonTest(con, Point(j, y2), false);if (p_jy2 < 0) {numy22++;}if (numy22 > thre)break;}if (numy22 > thre)continue;elsebreak;}flag_y2 = true;break;}}}if (flag_x2 == false) {x2 = x2 + radio_x;int numx2 = 0;for (int i = y1; i <= y2; i = i + step) {double p_x2i = pointPolygonTest(con, Point(x2, i), false);if (p_x2i < 0) {numx2++;}if (numx2 > thre || x2 >= (rect.x + rect.width)) {//开始收缩for (int m = 0; m < radio_x - 1; ++m) {int numx22 = 0;x2 = x2 - 1;    // 每次收缩1行for (int j = y1; j <= y2; j=j+ step) {double p_x2j = pointPolygonTest(con, Point(x2, j), false);if (p_x2j < 0) {numx22++;}if (numx22 > thre)break;}if (numx22 > thre)continue;elsebreak;}flag_x2 = true;break;}}}if (flag_y1 && flag_x1 && flag_y2 && flag_x2) {break;}}R.x = x1;R.y = y1;R.width = x2 - x1;R.height = y2 - y1;return true;
}
//最大内接矩形重载,传入多个轮廓
bool MaxInnerRect(const vector<vector<Point>> &cons, vector<Rect> &R) {Rect r;if (cons.size() == 0) {return false;}for (int i = 0; i < cons.size(); i++) {if (MaxInnerRect(cons[i], r)) {R.push_back(r);}}if (R.size() == 0) {return false;}return true;
}

2.测试

代码如下(示例):

void testInnerRect(int flag) {Mat img = imread("1.png", 1);Mat src;cvtColor(img, src, COLOR_BGR2GRAY);threshold(src, src, 130, 255, THRESH_BINARY);//vector<vector<Point>> contours, SelectContours;findContours(src, contours, RETR_LIST, CHAIN_APPROX_NONE);int jpg = 10000000;int png = 3000;clock_t begin = clock();if (flag == 1) {vector<Rect> R;for (int i = 0; i < contours.size(); i = i + 1) {double area1 = contourArea(contours[i]);if (area1 > png && area1< 500000) {SelectContours.push_back(contours[i]);}}if (MaxInnerRect(SelectContours, R)) {for (int m = 0; m < R.size();m++) {rectangle(img, R[m], Scalar(0, 0, 255), 3);}}}else {for (int i = 0; i < contours.size(); i = i + 1) {//                                                    double area1 = contourArea(contours[i]);if (area1 > jpg) {SelectContours.push_back(contours[i]);}}vector<Point> cons1;Rect R;for (int i = 0; i < SelectContours.size(); i++) {cons1 = SelectContours[i];if (MaxInnerRect(cons1, R)) {rectangle(img, R, Scalar(0, 0, 255), 3);}}}clock_t end = clock();double programTimes = ((double)end - begin) / CLOCKS_PER_SEC;cout << "执行时间: " << programTimes << endl;namedWindow("img", WINDOW_NORMAL);namedWindow("src", WINDOW_NORMAL);imshow("img", img);imshow("src", src);waitKey(0);
}

总结

有改善之处还望提出,共勉!

opencv实现轮廓的内接正矩形相关推荐

  1. opencv 绘制轮廓边框 多边形 圆形 矩形

    如何使用opencv 绘制轮廓边框最小包裹 多边形 圆形 矩形? 函数说明: Rect boundingRect(InputArray points) points:输入信息,可以为包含点的容器(ve ...

  2. java 椭圆拟合,OpenCV画轮廓的外界圆矩形椭圆等

    #include #include #include #include using namespace std; #pragma   comment(lib,"cv.lib") # ...

  3. OpenCV轮廓最大内接矩形(带角度)-计算与绘制(Python / C++源码)

    实现效果 OpenCV获取轮廓/Blob最大内接矩形(带角度) 实现源码 一.C++ OpenCV实现: #include "pch.h" #include <iostrea ...

  4. OPENCV 寻找图形最大内接矩形

      轮廓的最大外接矩形,Opencv有提供的现成的算法,最大内接圆也有提供的算法.但是没有现成的内接矩形的算法.本文使用C++实现了取轮廓最大内接矩形的方式,供大家参考. 实现的基本思路是: 处理图片 ...

  5. Opencv 找轮廓并画出相应的矩形

    找轮廓参考以下大神的,对于里面的方法和结果存储解释的很清楚: http://blog.csdn.net/gubenpeiyuan/article/details/44922413 缺少的是画相应包围矩 ...

  6. opencv findContours()轮廓特征分析大全(求面积、周长、几何矩、质心、凸包、最小外接矩形、最小外接三角形、最小外接椭圆等)

    文章目录 前言 一.效果 二.opencv对应函数介绍 1.轮廓面积 2.轮廓周长 3.轮廓几何矩 4.轮廓的最大外接矩形 5.轮廓的凸包 6.轮廓的最小外接矩形 7.轮廓的最小外接三角形 8.轮廓的 ...

  7. 基于OpenCV的轮廓检测(1)

    1.目标 理解什么叫做轮廓 学习如何寻找轮廓以及可视化轮廓 找出轮廓的不同特征,如面积.周长.质心.边框等 将看到许多与轮廓相关的函数. 2.什么叫做轮廓 轮廓可以简单地解释为连接所有连续点(沿着边界 ...

  8. Python,OpenCV应用轮廓逼近算法,检测对象的形状

    上一篇博客,我们学习了如何利用Python.OpenCV计算轮廓的中心,这一节学习仅运用轮廓的基本属性来检测其形状,三角形,正方形,矩形,五边形,圆. (1)利用轮廓逼近,将曲线上的点数减少为更简单的 ...

  9. 使用Python、OpenCV计算轮廓的中心

    1. 使用Python.OpenCV计算轮廓的中心并标记 2. 使用Python.OpenCV检测轮廓的形状并标记 3. 使用颜色通道统计信息来标记形状的实际颜色并标记 本博客的目标:(1)检测图像中 ...

最新文章

  1. Django(五)模型(model)系统 -- 常用字段和字段参数
  2. 微服务之间调用经过网关吗_微服务网关入门
  3. 人们通常先在线性表尾部临时添加一个_数据结构学习笔记-线性表
  4. 深潜百米,采用半缆通信技术的Gladius水下无人机能够征服海洋吗?
  5. 用 Unity 探究 2D 游戏的打击感
  6. 王兴针对“共同富裕”表态,称其根植于美团基因中
  7. python类与对象做项目_python 类和对象
  8. Spring DI(依赖注入)注解篇
  9. 技术随笔八——仰望夜空 仰望Git
  10. LeedCode Q344 Reverse String(Easy)
  11. 369Cloud控制台、IDE、组件、引擎升级全面解析
  12. 终端SSH工具SecureCRT 9.2.0 for Mac
  13. angular-devextreme treeview 学习笔记
  14. 不念过往,不畏将来:2022年6月我辞职了...
  15. 微信小程序如何实现搜索框的防抖功能
  16. $('.test:hiden');和$('.test :hiden);区别
  17. 计算机英语输入法怎么,电脑为什么输入法总是英文怎么办
  18. 抓取得物数据出现验证码的解析思路
  19. PS和PL共享DDR
  20. 随笔(十一)——在杭州的100天-第十天

热门文章

  1. java用gson转换百度识图api的json
  2. M1支持Windows arm_不讲武德?改变规则?苹果M1处理器 amp; ARM Mac简评
  3. 限制软件试用期的源代码 vc++
  4. 第八章 Hbase专题之架构设计详述(图解)
  5. 山东大学暑期项目实训-基于信用评分卡算法模型的个人信用评级系统的设计与实现-第一周-1(6月28日)
  6. php文字转语音amr,迅捷文字转语音的教程
  7. 关于tf库的问题解决2021-11-05
  8. jquery发送ajax请求_复习之Vue用axios发送ajax请求
  9. 关于部署springboot+jsp项目时打jar包无法访问静态资源的问题
  10. 小米手环(NFC版) 门禁卡模拟 (无需读卡器!)