BLOB是图像中灰度块的一种专业称呼,更加变通一点的可以说它跟我们前面二值图像分析的联通组件类似,通过特征提取实现常见的各种灰度BLOB对象组件检测与分离。使用该检测器的时候,可以根据需要输入不同参数,得到的结果跟输入的参数息息相关。
OpenCV中的Blob分析函数为SimpleBlobDetector,OpenCV中支持实现常见的BLOB分析过滤,如下所示:
- 根据BLOB面积过滤
- 根据灰度/颜色值过滤
- 根据圆度过滤
- 根据长轴与短轴过滤
- 根据凹凸进行过滤
对应的参数列表如下:
SimpleBlobDetector::Params::Params()
bool filterByArea
bool filterByCircularity
bool filterByColor
bool filterByConvexity
bool filterByInertia
float maxArea
float maxCircularity
float maxConvexity
float maxInertiaRatio
float maxThreshold
float minArea
float minCircularity
float minConvexity
float minDistBetweenBlobs
float minInertiaRatio
OpenCV中Blob检测示例代码如下:
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// 加载图像
Mat src = imread("D:/lena.jpg");
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
cv::imshow("输入图像", src);
// 初始化参数设置
SimpleBlobDetector::Params params;
params.minThreshold = 10;
params.maxThreshold = 240;
params.filterByArea = true;
params.minArea = 50;
params.filterByCircularity = true;
params.minCircularity = 0.1;
params.filterByConvexity = true;
params.minConvexity = 0.5;
params.filterByInertia = true;
params.minInertiaRatio = 0.5;
// 创建BLOB Detetor
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
// BLOB分析与显示
Mat result;
vector<KeyPoint> keypoints;
detector->detect(gray, keypoints);
for (auto kpt : keypoints) {
std::cout << "key point radius: " << kpt.size << std::endl;
cv::circle(src, kpt.pt, 2, cv::Scalar(0, 255, 0), 2, 8, 0);
cv::circle(src, kpt.pt, kpt.size/2, cv::Scalar(255, 0, 255), 3, 8, 0);
}
imshow("Blob检测-OpenCV学堂", src);
waitKey(0);
}
演示效果如下:
SimpleBlobDetector 函数有两个很诡异的地方。
第一个是实现的默认参数支持与参数检查
OpenCV中SimpleBlobDetector函数默认的参数值如下:
thresholdStep = 10;
minThreshold = 50;
maxThreshold = 220;
minRepeatability = 2;
minDistBetweenBlobs = 10;
filterByColor = true;
blobColor = 0;
filterByArea = true;
minArea = 25;
maxArea = 5000;
filterByCircularity = false;
minCircularity = 0.8f;
maxCircularity = std::numeric_limits<float>::max();
filterByInertia = true;
//minInertiaRatio = 0.6;
minInertiaRatio = 0.1f;
maxInertiaRatio = std::numeric_limits<float>::max();
filterByConvexity = true;
//minConvexity = 0.8;
minConvexity = 0.95f;
maxConvexity = std::numeric_limits<float>::max();
collectContours = false;
每次执行之前都会进行断言检查,但是OpenCV中同时提供了是否启用Blob各种过滤开关选项,但是无论开关选项是否启用,这个断言检查都是检查全部属性值,这个就导致你设置选项为false的时候,必须填写对应选项的选项值,否则就无法执行Blob检测函数。对应的源码文件 blobdetector.cpp 发现了这段代码作为佐证:
static void validateParameters(const SimpleBlobDetector::Params& p)
{
if (p.thresholdStep <= 0)
CV_Error(Error::StsBadArg, "thresholdStep>0");
if (p.minThreshold > p.maxThreshold || p.minThreshold < 0)
CV_Error(Error::StsBadArg, "0<=minThreshold<=maxThreshold");
if (p.minDistBetweenBlobs <=0 )
CV_Error(Error::StsBadArg, "minDistBetweenBlobs>0");
if (p.minArea > p.maxArea || p.minArea <=0)
CV_Error(Error::StsBadArg, "0<minArea<=maxArea");
if (p.minCircularity > p.maxCircularity || p.minCircularity <= 0)
CV_Error(Error::StsBadArg, "0<minCircularity<=maxCircularity");
if (p.minInertiaRatio > p.maxInertiaRatio || p.minInertiaRatio <= 0)
CV_Error(Error::StsBadArg, "0<minInertiaRatio<=maxInertiaRatio");
if (p.minConvexity > p.maxConvexity || p.minConvexity <= 0)
CV_Error(Error::StsBadArg, "0<minConvexity<=maxConvexity");
}
第二个是现实的默认输入图像的背景必须是白色
如果是黑色背景图像输入,Blob检测所有的参数就直接失效了,但是官方开发教程示例代码与函数文档都没有说明这点,导致很多新手小白不明所以就直接掉坑了,然后就放弃使用这个函数了。
学习《OpenCV应用开发:入门、进阶与工程化实践》一书
做真正的OpenCV开发者,从入门到入职,一步到位!
全书共计16个章节,重点聚焦OpenCV开发常用模块详解与工程化开发实践,提升OpenCV应用开发能力,助力读者成为OpenCV开发者,同时包含深度学习模型训练与部署加速等知识,帮助OpenCV开发者进一步拓展技能地图,满足工业项目落地所需技能提升。请点下面查看本书目录
学习课程有专属答疑群
读者专属QQ群 :657875553
进群暗号:OpenCV4读者