OpenCV找圆系列(1)SimpleBlobDetector源码,凸度和圆度等检测原理
Blob是指图像中的一块连通区域,Blob分析就是对前景/背景分离后的二值图像,进行连通域提取和标记。知识点就是SimpleBlobDetector的使用,blob(斑点)筛选条件:斑点颜色、面积、圆度、惯性率、凸度。
void blobDetector()
{Mat img = imread("d:\\11.jpg");SimpleBlobDetector::Params params;params.thresholdStep = 10; //二值化的阈值步长params.minThreshold = 20;params.maxThreshold = 200;params.filterByArea = true;params.minArea = 10;params.maxArea = 80000;params.filterByCircularity = true;params.minCircularity = 0.5;Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);vector<KeyPoint> key_points;detector->detect(img, key_points);Mat output_img;drawKeypoints(img, key_points, output_img, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);namedWindow("SimpleBlobDetector", WINDOW_NORMAL);imshow("SimpleBlobDetector", output_img);waitKey(0);
}
- 阈值:通过使用以minThreshold开始的阈值对源图像进行阈值处理,将源图像转换为多个二进制图像。这些阈值以thresholdStep递增,直到maxThreshold。因此,第一个阈值为minThreshold,第二个阈值为minThreshold + thresholdStep,第三个阈值为minThreshold + 2 x thresholdStep,依此类推;
- 按大小:可以通过设置参数filterByArea = 1以及minArea和maxArea的适当值来基于大小过滤blob。例如。设置minArea = 100将滤除所有少于100个像素的斑点。
- 按圆度:这只是测量斑点距圆的距离。例如。正六边形的圆度比正方形高。要按圆度过滤,请设置filterByCircularity =1。然后为minCircularity和maxCircularity设置适当的值。圆度定义为(
)。圆的为圆度为1,正方形的圆度为PI/4,依此类推。
以下给出 opencv 对候选 Blob 筛查的部分源码:
https://github.com/opencv/opencv/blob/4.2.0/modules/features2d/src/feature2d.cpp
https://github.com/opencv/opencv/blob/4.2.0/modules/features2d/src/blobdetector.cpp
SimplerBlobDetector/SimplerBlobDetector.cpp at master · joostvanstuijvenberg/SimplerBlobDetector · GitHub
//image为输入的灰度图像
//binaryImage为二值图像
//centers表示该二值图像的斑点
void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryImage, vector<Center> ¢ers) const
{(void)image;centers.clear(); //斑点变量清零vector < vector<Point> > contours; //定义二值图像的斑点的边界像素变量Mat tmpBinaryImage = binaryImage.clone(); //复制二值图像//调用findContours函数,找到当前二值图像的所有斑点的边界findContours(tmpBinaryImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);#ifdef DEBUG_BLOB_DETECTOR// Mat keypointsImage;// cvtColor( binaryImage, keypointsImage, CV_GRAY2RGB );//// Mat contoursImage;// cvtColor( binaryImage, contoursImage, CV_GRAY2RGB );// drawContours( contoursImage, contours, -1, Scalar(0,255,0) );// imshow("contours", contoursImage );
#endif//遍历当前二值图像的所有斑点for (size_t contourIdx = 0; contourIdx < contours.size(); contourIdx++){//结构类型Center代表着斑点,它包括斑点的中心位置,半径和权值Center center; //斑点变量//初始化斑点中心的置信度,也就是该斑点的权值center.confidence = 1;//调用moments函数,得到当前斑点的矩Moments moms = moments(Mat(contours[contourIdx]));if (params.filterByArea) //斑点面积的限制{double area = moms.m00; //零阶矩即为二值图像的面积//如果面积超出了设定的范围,则不再考虑该斑点if (area < params.minArea || area >= params.maxArea)continue;}if (params.filterByCircularity) //斑点圆度的限制{double area = moms.m00; //得到斑点的面积//计算斑点的周长double perimeter = arcLength(Mat(contours[contourIdx]), true);//由公式3得到斑点的圆度double ratio = 4 * CV_PI * area / (perimeter * perimeter);//如果圆度超出了设定的范围,则不再考虑该斑点if (ratio < params.minCircularity || ratio >= params.maxCircularity)continue;}if (params.filterByInertia) //斑点惯性率的限制{//计算公式13中最右侧等式中的开根号的值double denominator = sqrt(pow(2 * moms.mu11, 2) + pow(moms.mu20 - moms.mu02, 2));const double eps = 1e-2; //定义一个极小值double ratio;if (denominator > eps){//cosmin和sinmin用于计算图像协方差矩阵中较小的那个特征值λ2double cosmin = (moms.mu20 - moms.mu02) / denominator;double sinmin = 2 * moms.mu11 / denominator;//cosmin和sinmin用于计算图像协方差矩阵中较大的那个特征值λ1double cosmax = -cosmin;double sinmax = -sinmin;//imin为λ2乘以零阶中心矩μ00double imin = 0.5 * (moms.mu20 + moms.mu02) - 0.5 * (moms.mu20 - moms.mu02) * cosmin - moms.mu11 * sinmin;//imax为λ1乘以零阶中心矩μ00double imax = 0.5 * (moms.mu20 + moms.mu02) - 0.5 * (moms.mu20 - moms.mu02) * cosmax - moms.mu11 * sinmax;ratio = imin / imax; //得到斑点的惯性率}else{ratio = 1; //直接设置为1,即为圆}//如果惯性率超出了设定的范围,则不再考虑该斑点if (ratio < params.minInertiaRatio || ratio >= params.maxInertiaRatio)continue;//斑点中心的权值定义为惯性率的平方center.confidence = ratio * ratio;}if (params.filterByConvexity) //斑点凸度的限制{vector < Point > hull; //定义凸壳变量//调用convexHull函数,得到该斑点的凸壳convexHull(Mat(contours[contourIdx]), hull);//分别得到斑点和凸壳的面积,contourArea函数本质上也是求图像的零阶矩double area = contourArea(Mat(contours[contourIdx]));double hullArea = contourArea(Mat(hull));double ratio = area / hullArea; //公式5,计算斑点的凸度//如果凸度超出了设定的范围,则不再考虑该斑点if (ratio < params.minConvexity || ratio >= params.maxConvexity)continue;}//根据公式7,计算斑点的质心center.location = Point2d(moms.m10 / moms.m00, moms.m01 / moms.m00);if (params.filterByColor) //斑点颜色的限制{//判断一下斑点的颜色是否正确if (binaryImage.at<uchar> (cvRound(center.location.y), cvRound(center.location.x)) != params.blobColor)continue;}//compute blob radius{vector<double> dists; //定义距离队列//遍历该斑点边界上的所有像素for (size_t pointIdx = 0; pointIdx < contours[contourIdx].size(); pointIdx++){Point2d pt = contours[contourIdx][pointIdx]; //得到边界像素坐标//计算该点坐标与斑点中心的距离,并放入距离队列中dists.push_back(norm(center.location - pt));}std::sort(dists.begin(), dists.end()); //距离队列排序//计算斑点的半径,它等于距离队列中中间两个距离的平均值center.radius = (dists[(dists.size() - 1) / 2] + dists[dists.size() / 2]) / 2.;}centers.push_back(center); //把center变量压入centers队列中#ifdef DEBUG_BLOB_DETECTOR// circle( keypointsImage, center.location, 1, Scalar(0,0,255), 1 );
#endif}
#ifdef DEBUG_BLOB_DETECTOR// imshow("bk", keypointsImage );// waitKey();
#endif
}
---
参考文献
OpenCV图像处理中“找圆技术”的使用
https://www.cnblogs.com/jsxyhelu/p/14117304.htmlhttps://www.cnblogs.com/jsxyhelu/p/14117304.html
OpenCV 常用检测算法_DaGongJiGuoMaLu09的博客-CSDN博客_cv算法一、直线检测1、直线检测cv.HoughLines:使用标准霍夫变换,找到二值图像中的直线lines = cv.HoughLines( image, # 8-bit、单通道的二值图像 rho, # 累加器的距离分辨率,以像素为单位 theta, # 累加器的角度分辨率,以弧度为单位 threshold, # 累加器的阈值参数,太大会过滤大部分直线,太小则误检测会很多 lines, # srn, # 对于多尺度霍夫变换,https://blog.csdn.net/DaGongJiGuoMaLu09/article/details/109123980
OpenCV找圆系列(1)SimpleBlobDetector源码,凸度和圆度等检测原理相关推荐
- matlab中调用histeq函数命令,根据MATLAB的histeq函数改写的运行在OpenCV下的直方图规定化源码!...
据说,图像的直方图规定化比直方图均衡化用得更多,但是很奇怪的是OpenCV居然没有图像直方图规定化的源码!所以,我就有必要在OpenCV下写一个图像直方图规定化处理的函数,以方便将来使用. 我在网上找 ...
- 死磕 java同步系列之ReentrantReadWriteLock源码解析
问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...
- SequoiaDB 系列之六 :源码分析之coord节点
好久不见. 在上一篇SequoiaDB 系列之五 :源码分析之main函数,有讲述进程开始运行时,会根据自身的角色,来初始化不同的CB(控制块,control block). 在之前的一篇Sequ ...
- 飞翔的圆(Flappy Bird)游戏源码完整版
2019独角兽企业重金招聘Python工程师标准>>> 这个源码是一个不错的休闲类的游戏源码,飞翔的圆(Flappy Bird)游戏源码V1.0,本项目是一个仿Flappy Bird ...
- Python基于OpenCV的人脸表情识别系统[源码&部署教程]
1.项目背景 人脸表情识别是模式识别中一个非常重要却十分复杂的课题.首先对计算机人脸表情识别技术的研究背景及发展历程作了简单回顾.然后对近期人脸表情识别的方法进行了分类综述.通过对各种识别方法的分析与 ...
- [darknet源码系列-2] darknet源码中的cfg解析
[darknet源码系列-2] darknet源码中的cfg解析 FesianXu 20201118 at UESTC 前言 笔者在[1]一文中简单介绍了在darknet中常见的数据结构,本文继续上文 ...
- 【Linux后台开发系列】Nginx源码从模块开发开始,不再对nginx源码陌生丨源码分析
Nginx源码从模块开发开始,不再对nginx源码发怵,值得学习,认真听完. 1. nginx的conf配置,cmd解析 2. nginx模块的八股文 3. nginx开发的细枝末节 [Linu ...
- 找茬微信小程序源码完整版
最新找茬微信小程序源码+搭建教程+全套素材+前端源码,测试完美运行.内有所有有些的素材,导入即可. 不错的引流和流量主程序,带后端添加与管理! [完整源码链接] 找茬小程序完美运营版.zip资 ...
- paho架构_MQTT系列最终章-Paho源码分析(三)-心跳与重连机制
写在前面 通过之前MQTT系列-Eclipse.Paho源码分析(二)-消息的发送与接收的介绍,相信仔细阅读过的小伙伴已经对Eclipse.Paho内部发送和订阅消息的流程有了一个较为清晰的认识,今天 ...
- 【Spring 源码阅读】Spring IoC、AOP 原理小总结
Spring IoC.AOP 原理小总结 前言 版本约定 正文 Spring BeanFactory 容器初始化过程 IoC 的过程 bean 完整的创建流程如下 AOP 的过程 Annotation ...
最新文章
- 魅族的android m l,Android M 外部存储剖析
- SQL Server 备份还原造成孤立用户的问题
- c语言中void delay0.5(),单片机彩灯是怎样点亮
- Linux 如何获取PAGE size的大小?
- python如何读取数据保存为新格式_Python Numpy中数据的常用保存与读取方法
- 域名解析是否生效实时检测(阿里云DNS检测)
- 在C ++ STL中使用string :: to_string()将数字转换为字符串
- Spark入门必读:核心概念介绍及常用RDD操作
- 直播预告丨Oracle 12C~19C统计信息的最佳实践
- 米斯特白帽培训讲义 工具篇 AWVS
- 依赖注入原理,作用,注入方式——Spring IOC/DI(二)
- 源码安装mysql初始化报错_源码安装MySQL5.6.39后,修改配置文件启动报错
- opencms9.0安装
- linux下木马程序病原体的制作和运行
- mysql int_mysql中int(10)代表什么意思?
- 利用机器学习算法挖掘群控网络黑产设备
- 网络安全中接口测试的解决方案
- A Prompting-based Approach for Adversarial Example Generation andRobustness Enhancement
- NTP DDoS反射放大攻击实验
- Java反射机制的学习(3)
热门文章
- CENTOS 配置串口连接
- 惠普179fnw打印机使用说明_|惠普HP Color Laser MFP 179fnw一体机驱动下载v1.10官方版 - 欧普软件下载...
- docker-compose idea CreateProcess error=2, 系统找不到指定的文件
- 毕业论文系列-公式编号
- unity c#斗地主算法计算牌型
- 大气压计BMP280+BME280+BMP180 在ESP8266 (RTOS3.2)上初调的兼容驱动
- 软件测试02_软件生命周期软件测试流程
- html视频怎么改大小,对视频大小、比例进行修改
- 北京邮电计算机课程表,北邮通信工程本科专业课程表
- OBJ 模型文件与MTL材质文件 介绍