opencv笔记-SimpleBlobDetector
通用的 Blob 检测方法包括:Laplacian of Gaussian(LoG), Difference of Gaussian(DoG), Derterminant of Hessian(DoH)。
opencv 提供了一种简单的方法实现 Blob 检测:SimpleBlobDetector。所谓 Blob,其实就是图像上一些或亮或暗的小连通区域,该连通区域可以使用特定阈值提取出来。
当分析场景相对简单,使用 SimpleBlobDetector 可以比较准确且高效的定位 Blob 区域,基本思路如下:
1 使用连续阈值对图像进行阈值操作,其阈值参数范围为
,步长为 s;
2 使用 suzuki 算法(findContours)提取每个阈值下形成的区域,findContours 得到的每个边界围成的区域被认为是候选 Blob;
使用 findContours 检测连通区域要比连通区域分析算法更加高效,同时,一次 findContours 可以区分内外边界,外边界对应亮区域,内边界对应暗区域,但 opencv 2.4.10 源码中并未对内外边界区分对待;
3 对 Blob 区域进行筛查,筛查条件包括:
1 CV_PROP_RW bool filterByColor;
2 CV_PROP_RW uchar blobColor;
3
4 CV_PROP_RW bool filterByArea;
5 CV_PROP_RW float minArea, maxArea;
6
7 CV_PROP_RW bool filterByCircularity;
8 CV_PROP_RW float minCircularity, maxCircularity;
9
10 CV_PROP_RW bool filterByInertia;
11 CV_PROP_RW float minInertiaRatio, maxInertiaRatio;
12
13 CV_PROP_RW bool filterByConvexity;
14 CV_PROP_RW float minConvexity, maxConvexity;
1)filterByColor 表示提取亮区域或者暗区域。当 blobColor = 255 时,提取亮区域;当 blobColor = 0 时,提取暗区域;
2)filterByArea 表示是否限制 Blob 面积,其面积范围为一个半开半闭区间 [minArea, maxArea);
3)filterByCircularity 表示是否限制 Blob 圆形度,圆形度公式为
。
当 Blob 为圆形时,
。当 Blob 为一个无限长的椭圆,
。故圆形度范围取值范围为 (0, 1];
4)filterByConvexity 表示 Blob 面积与其凸包面积比,取值范围为 (0, 1);
5)filterByInertia 表示 Blob 区域转动惯量最小值与最大值比值,在 “二值图像的几何性质” 博客中,转动惯量表示为:
,
,
,
,
由于 转动惯量 E 为一个二次型函数,使用系数矩阵
的特征值与特征向量可描述转动惯量特性,其最小值与最大值比为
。
通过以上分析可知,当 Blob 区域为圆形时,比值接近 1。当 Blob 区域为无限长椭圆时,比值接近 0,故取值范围为 (0,1);
4 对于符合筛查条件的 Blob 区域,使用区域边界到中心点距离中值点作为该 Blob 区域半径;
5 将不同阈值下符合条件的候选 Blob 区域组合到一起,使用 minRepeatability 与 minDistBetweenBlobs 筛查出最终有效 Blob 区域;
以下给出 opencv 对候选 Blob 筛查的部分源码:
1 for (size_t contourIdx = 0; contourIdx < contours.size(); contourIdx++)
2 {
3
4 Center center;
5 center.confidence = 1; // 将可信度置1
6
7 // 求轮廓所围成区域零阶矩,一阶矩,二阶矩,用于筛查条件计算
8 Moments moms = moments(Mat(contours[contourIdx]));
9
10 if (params.filterByArea)
11 {
12 // 零阶矩表示区域面积
13 double area = moms.m00;
14 if (area < params.minArea || area >= params.maxArea)
15 continue;
16 }
17
18 if (params.filterByCircularity)
19 {
20 // 求区域面积与区域周长,并使用圆形度公式计算圆形度
21 double area = moms.m00;
22 double perimeter = arcLength(Mat(contours[contourIdx]), true);
23 double ratio = 4 * CV_PI * area / (perimeter * perimeter);
24 if (ratio < params.minCircularity || ratio >= params.maxCircularity)
25 continue;
26 }
27
28 if (params.filterByInertia)
29 {
30 // 使用二阶矩求区域形状
31 double denominator = sqrt(pow(2 * moms.mu11, 2) + pow(moms.mu20 - moms.mu02, 2));
32 const double eps = 1e-2;
33 double ratio;
34 if (denominator > eps)
35 {
36 double cosmin = (moms.mu20 - moms.mu02) / denominator;
37 double sinmin = 2 * moms.mu11 / denominator;
38 double cosmax = -cosmin;
39 double sinmax = -sinmin;
40
41 double imin = 0.5 * (moms.mu20 + moms.mu02) - 0.5 * (moms.mu20 - moms.mu02) * cosmin - moms.mu11 * sinmin;
42 double imax = 0.5 * (moms.mu20 + moms.mu02) - 0.5 * (moms.mu20 - moms.mu02) * cosmax - moms.mu11 * sinmax;
43 ratio = imin / imax;
44 }
45 else
46 {
47 ratio = 1;
48 }
49
50 if (ratio < params.minInertiaRatio || ratio >= params.maxInertiaRatio)
51 continue;
52
53 center.confidence = ratio * ratio;
54 }
55
56 if (params.filterByConvexity)
57 {
58 // 求区域面积与凸包面积之比
59 vector < Point > hull;
60 convexHull(Mat(contours[contourIdx]), hull);
61 double area = contourArea(Mat(contours[contourIdx]));
62 double hullArea = contourArea(Mat(hull));
63 double ratio = area / hullArea;
64 if (ratio < params.minConvexity || ratio >= params.maxConvexity)
65 continue;
66 }
67
68 center.location = Point2d(moms.m10 / moms.m00, moms.m01 / moms.m00);
69
70 if (params.filterByColor)
71 {
72 // 提取亮区域或者暗区域
73 if (binaryImage.at<uchar> (cvRound(center.location.y), cvRound(center.location.x)) != params.blobColor)
74 continue;
75 }
76
77 // 计算 Blob 半径
78 {
79 vector<double> dists;
80 for (size_t pointIdx = 0; pointIdx < contours[contourIdx].size(); pointIdx++)
81 {
82 Point2d pt = contours[contourIdx][pointIdx];
83 dists.push_back(norm(center.location - pt));
84 }
85 std::sort(dists.begin(), dists.end());
86 center.radius = (dists[(dists.size() - 1) / 2] + dists[dists.size() / 2]) / 2.;
87 }
88
89 centers.push_back(center);
90
91 }
参考资料 Learning OpenCV 3 Adrian Kaehler & Gary Bradski
opencv笔记-SimpleBlobDetector的更多相关文章
- OpenCV笔记大集锦(转载)
整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的.如果有好的资源,也欢迎介绍和分享. 1:OpenCV学习笔记 作者:CSDN数量:55篇博文网址: ...
- opencv笔记6:角点检测
time:2015年10月09日 星期五 23时11分58秒 # opencv笔记6:角点检测 update:从角点检测,学习图像的特征,这是后续图像跟踪.图像匹配的基础. 角点检测是什么鬼?前面一篇 ...
- opencv笔记5:频域和空域的一点理解
time:2015年10月06日 星期二 12时14分51秒 # opencv笔记5:频域和空域的一点理解 空间域和频率域 傅立叶变换是f(t)乘以正弦项的展开,正弦项的频率由u(其实是miu)的值决 ...
- opencv笔记4:模板运算和常见滤波操作
time:2015年10月04日 星期日 00时00分27秒 # opencv笔记4:模板运算和常见滤波操作 这一篇主要是学习模板运算,了解各种模板运算的运算过程和分类,理论方面主要参考<图像工 ...
- opencv笔记3:trackbar简单使用
time:2015年 10月 03日 星期六 13:54:17 CST # opencv笔记3:trackbar简单使用 当需要测试某变量的一系列取值取值会产生什么结果时,适合用trackbar.看起 ...
- opencv笔记2:图像ROI
time:2015年 10月 03日 星期六 12:03:45 CST # opencv笔记2:图像ROI ROI ROI意思是Region Of Interests,感兴趣区域,是一个图中的一个子区 ...
- opencv笔记1:opencv的基本模块,以及环境搭建
opencv笔记1:opencv的基本模块,以及环境搭建 安装系统 使用fedora22-workstation-x86_64 安装opencv sudo dnf install opencv-dev ...
- OpenCV基本架构[OpenCV 笔记0]
最近正在系统学习OpenCV,将不定期发布笔记,主要按照毛星云的<OpenCV3编程入门>的顺序学习,会参考官方教程和文档.学习工具是Xcode+CMake,会对书中一部分内容更正,并加入 ...
- 查找并绘制轮廓[OpenCV 笔记XX]
好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...
随机推荐
- mysql自动安装脚本
#!/bin/bashif [ -d /software ] ;then cd /softwareelse mkdir /software && cd /softwarefi #is ...
- [Docker] 在CentOS6.8 安装 Docker
运行docker Linux内核版本需要在3.8以上,针对centos6.5 内核为2.6的系统需要先升级内核.不然会特别卡,退出容器. # 查看当前版本: cat /etc/issue # 导入pu ...
- [网络编程] 自己构建一个cgi.FieldStorage()的对象
问题描述: 通常cgi.FieldStorage()返回一个类似于Python字典的对象. 在cgi框架中必须通过浏览器发送表单过来才能接受消息 那么我该怎么进行本地调试呢? 或者说在没有搭建好一整套 ...
- Go语言系列- http编程和mysql
http编程 一.Http协议 1. 什么是协议? 协议,是指通信的双方,在通信流程或内容格式上,共同遵守的标准. 2. 什么是http协议? http协议,是互联网中最常见的网络通信标准. 3 ...
- 论文翻译:2020_RESIDUAL ACOUSTIC ECHO SUPPRESSION BASED ON EFFICIENT MULTI-TASK CONVOLUTIONAL NEURAL NETWORK
论文翻译:https://arxiv.53yu.com/abs/2009.13931 基于高效多任务卷积神经网络的残余回声抑制 摘要 在语音通信系统中,回声会降低用户体验,需要对其进行彻底抑制.提出了 ...
- PaddleOCRSharp,2022年,你来的晚了些,一款.NET离线使用的高精度OCR
一款免费且离线的.NET使用的OCR,爱你又恨你!恨你来的太晚了. PaddleOCRSharp 本项目是一个基于百度飞桨的PaddleOCR的C++代码修改并封装的.NET的类库.包含文本识别.文本 ...
- [USB波形分析] 全速USB波形数据分析(一)
在之前的文章一次CAN波形分析之旅里,根据示波器采集的波形数据,详细地分析了CAN通信.今天来分析USB数据,还是同样的流程,但是这次使用matplotlib来协助分析. USB基本波形 USB通过一 ...
- 【记录一个问题】用ndk的gcc命令行无法编译C++11的lambda等语法的代码
/Users/ahfu/code/android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_6 ...
- Manacher算法求解回文字符串
Manacher算法可以在\(O(N)\)时间内求解出一个字符串的所有回文子串(正反遍历相同的字串). 注:回文串显然有两种,一种是奇数长度,如abczcba,有一个中心字符z:另外一种是偶数个长度, ...
- VS2017:win32项目与win32控制台应用程序的转换方法
原文:https://www.cnblogs.com/asuser/articles/12297251.html 刚开始使用VS2017新建项目工程时,有时把应用类型的工程建成控制台类型的工程,在编译 ...