OpenCV4学习笔记(49)——Blob特征分析算法
今天要整理记录的笔记是关于图像Blob特征分析算法的内容。计算机视觉中的Blob(斑点)是指图像中的一块连通区域,Blob分析就是对前景、背景分离后的二值图像,进行连通域提取和标记。标记完成的每一个Blob都代表一个前景目标,然后就可以计算Blob的一些相关特征。
也可以称Blob(斑点)是指二维图像中和周围像素点存在颜色差异和灰度差异的特征区域,针对这些特征区域所提取出某些具有区域代表性的信息,就被称为Blob特征。由于Blob特征代表的是一个区域,所以相比单纯的角点,它的稳定性要更好,抗噪声能力也更强,所以它在图像配准上扮演了很重要的角色。例如在opencv::ccalib模块中,进行双目相机的三维重建时需要先利用两张分别由不同相机拍摄出的图像来进行立体匹配从而得到深度图,而深度图表现出来就是具有多个Blob的灰度图像,而进行立体匹配过程也会在两张图像之间寻找相似的区域特征。
同时有时图像中的Blob也是我们关心的区域,比如在医学与生物领域,我们需要从一些X光照片或细胞显微照片中提取一些具有特殊意义的斑点的位置或数量。
Blob特征分析算法使用相对简单的方式来检测斑点类的特征,OpenCV提供了一种方便的APISimpleBlobDetector
来检测斑点并根据不同的特征对其进行过滤。
其步骤为:
(1)对于一幅图像在阈值区间 [ minthresh, maxthresh ]内以某个阈值步长进行多次二值分割,得到多张二值图像;
(2)再对多张二值图像分别获取连通域的轮廓及轮廓中心;
(3)将距离小于某个阈值minDistBetweenBlob
的Blob中心点归为一类,对应的连通域也视为同个区域,再经过条件筛选对连通域进行过滤后留下来的就是斑点特征。
SimpleBlobDetector
可以实现对各种常见的Blob对象进行检测与分离。使用该检测器的时候,可以根据需要来输入不同的条件参数,得到的结果跟输入的参数息息相关。首先,创建BLOB特征参数设置器SimpleBlobDetector::Params params;
,然后就可以根据需求设置不同参数。
例如可以设置二值化阈值区间:
//二值化阈值区间
params.minThreshold = 0;
params.maxThreshold = 255;
选择是否通过颜色或灰度值进行过滤:
//根据灰度或颜色值过滤
params.filterByColor = true;
blobColor = 0 //以选择较暗的blob,将 blobColor = 255设置为较亮的blob。
// params.filterByColor = false;
选择是否根据BLOB面积进行过滤:
params.filterByArea = true;
params.minArea = 200;
选择是否根据BLOB的圆度进行过滤:
//根据圆度过滤;圆度表示斑点距圆的距离,例如圆的圆度为1,正方形的圆度为0.785
params.filterByCircularity = true;
params.minCircularity = 0.3;
选择是否根据BLOB的惯性比进行过滤:
//根据惯性比过滤;衡量形状的伸长程度,相当于(短轴 / 长轴),例如对于一个圆,则惯性比是1,对于椭圆的惯性比在0和1之间,而对于线是0; 0≤ minInertiaRatio ≤1 , maxInertiaRatio ≤ 1
params.filterByInertia = true;
params.minInertiaRatio = 0.5;
选择是否根据凹凸性进行过滤:
//根据凹凸性进行过滤;凸度定义为:斑点的面积/该斑点的凸包面积;凸度小于等于1,越接近1表示该斑点凸性越强
params.filterByConvexity = true;
params.minConvexity = 0.1;
上面是常用的参数设置,当设置好所需的参数后,就可以通过auto blob = SimpleBlobDetector::create(params);
来创建Blob特征检测器,其中传入的就是我们已经设置好了的参数设置器。
接着就可以利用Blob特征检测器来对图像进行Blob特征检测了,代码演示如下:
Mat test_image = imread("D:\\opencv_c++\\opencv_tutorial\\data\\images\\zhifang_ball.png");
Mat gray_image;
cvtColor(test_image, gray_image, COLOR_BGR2GRAY);
SimpleBlobDetector::Params params;
//二值化阈值区间
params.minThreshold = 0;
params.maxThreshold = 255;
//根据灰度或颜色值过滤
//blobColor = 0以选择较暗的blob,将 blobColor = 255设置为较亮的blob。
params.filterByColor = false;
//根据BLOB面积过滤
params.filterByArea = true;
params.minArea = 200;
//根据圆度过滤;圆度表示斑点距圆的距离,例如圆的圆度为1,正方形的圆度为0.785
params.filterByCircularity = true;
params.minCircularity = 0.3;
//根据惯性比过滤;衡量形状的伸长程度,相当于(短轴 / 长轴),例如对于一个圆,则惯性比是1,对于椭圆的惯性比在0和1之间,而对于线是0; 0≤ minInertiaRatio ≤1 , maxInertiaRatio ≤ 1
params.filterByInertia = true;
params.minInertiaRatio = 0.5;
//根据凹凸性进行过滤;凸度定义为:斑点的面积/该斑点的凸包面积;凸度小于等于1,越接近1表示该斑点凸性越强
params.filterByConvexity = true;
params.minConvexity = 0.1;
auto blob = SimpleBlobDetector::create(params);
vector<KeyPoint>keyPoints;
blob->detect(gray_image, keyPoints, Mat()); //必须使用灰度图进行检测
drawKeypoints(test_image, keyPoints, test_image, Scalar(0,255,0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imshow("test_image", test_image);
这里使用的输入图像为下图:
我们通过过滤blob特征,来筛选其中最接近圆形的、比较明显的区域,效果如下:
这里找到的特征点,其实就是每一个特征Blob的轮廓点,所以当我们使用特征点绘制的时候,就把检测到的每一个blob给标记了出来。
可见Blob特征分析能够帮助我们根据目标物体的形状特征来进行区域提取,但是这就很考验我们对其各种参数设置的调试能力了,只有找到适合我们需求的参数,Blob特征分析算法才能发挥其最大的优点。
好了今天的笔记到此结束。刚刚收到通知说本学期不回校了,烦是真的烦,看来我的暑假实习要泡汤了。。。等回校,莫名其妙就大四了。。。啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!!!!!!!!!!!!!!!!!!!!!!!!!!!
PS:本人的注释比较杂,既有自己的心得体会也有网上查阅资料时摘抄下的知识内容,所以如有雷同,纯属我向前辈学习的致敬,如果有前辈觉得我的笔记内容侵犯了您的知识产权,请和我联系,我会将涉及到的博文内容删除,谢谢!