基于局部极值的分水岭算法的圆斑点检测
来源:互联网 发布:php 下载文件 编辑:程序博客网 时间:2024/06/08 05:58
本次实验利用了基于局部极值的分水岭算法来实现圆斑点的检测。在OPENCV中提供了simpleBlobDetector特征检测器来实现这种斑点检测算法,正如它的名称,该算法使用最简单的方式来检测斑点类的特征点,效果较好,设置较为宽松的参数,就能取得较好的效果。
一 算法的步骤
第一步 多次二值化图像
首先通过一系列连续的阈值把输入的灰度图像转换为一个二值图像的集合,阈值范围为[T1, T2],步长为t,则所有阈值为:
T1,T1+t,T1+2t,T1+3t,……,T2
第二步 确定候选圆点
通过检测每一幅二值图像的边缘的方式提取出每一幅二值图像的连通区域,我们可以认为由边界所围成的不同的连通区域就是该二值图像的斑点。其中,并不是所有的二值图像的连通区域都可以认为是二值图像的斑点,我们通过一些限定条件来得到更准确的斑点。这些限定条件包括颜色,面积和形状,斑点的形状又可以用圆度,偏心率,或凸度来表示,具体参数和计算方法查看参数部分介绍。
第三步 对图像圆点进行分类,确定目标圆点
根据所有二值图像斑点的中心坐标对二值图像斑点进行分类,从而形成灰度图像的斑点,属于一类的那些二值图像斑点最终形成灰度图像的斑点,具体来说就是,灰度图像的斑点是由中心坐标间的距离小于阈值的那些二值图像斑点所组成的,即这些二值图像斑点属于该灰度图像斑点;
二 参数部分
filterByColor斑点颜色。
filterByArea斑点面积。连通区域的面积太大和太小都不是斑 。所以我们需要计算连通区域的面积,只有当该面积在我们所设定的最大面积和最小面积之间时,该连通区域才作为斑点被保留下来。
filterByCircularity 斑点圆度。任意形状的圆度C定义为:
其中,S和p分别表示该形状的面积和周长,当C为1时,表示该形状是一个完美的圆形,而当C为0时,表示该形状是一个逐渐拉长的多边形。
filterByInertia斑点惯性率。偏心率是指某一椭圆轨道与理想圆形的偏离程度,长椭圆轨道的偏心率高,而近于圆形的轨道的偏心率低。圆形的偏心率等于0,椭圆的偏心率介于0和1之间,而偏心率等于1表示的是抛物线。直接计算斑点的偏心率较为复杂,但利用图像矩的概念计算图形的惯性率,再由惯性率计算偏心率较为方便。偏心率E和惯性率I之间的关系为:
因此圆形的惯性率等于1,惯性率越接近1,圆形的程度越高(在实际操作中并没有用到)。
filterByConvexity 表示斑点凸度。在平面中,凸形图指的是图形的所有部分都在由该图形切线所围成的区域的内部。我们可以用凸度来表示斑点凹凸的程度,凸度V的定义为:
其中,H表示该斑点的凸壳面积
minDistBetweenBlobs斑点距离的最小阈值,中心坐标间的距离小于该值就认为为同一个斑点。
三 源码
#include "opencv2/opencv.hpp"#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/features2d/features2d.hpp" using namespace cv;using namespace std;int main(int argc, char* argv[]){ Mat srcImage = imread("pos71_run7_img190.jpg"); Mat srcGrayImage, srcGrayImage1, srcImage1, keyPointImage11, keyPointImage21; if (srcImage.channels() == 3) { cvtColor(srcImage, srcGrayImage, CV_RGB2GRAY); } else { srcImage.copyTo(srcGrayImage); } GaussianBlur(srcGrayImage, srcGrayImage1,Size(11,11),0,0); vector<KeyPoint>detectKeyPoint; Mat keyPointImage1, keyPointImage2; SimpleBlobDetector::Params params; params.filterByArea = true; params.minArea = 15; params.maxArea = 1500; params.thresholdStep = 10; //二值化的阈值步长,即公式1的t params.minThreshold = 50 ; params.maxThreshold = 200; params.filterByCircularity = true; //斑点圆度 params.minCircularity = 0.8; params.maxCircularity = 1; params.filterByConvexity = false; //斑点凸度 params.minConvexity = (float)0.5; params.maxConvexity = 1; params.filterByInertia = false; //斑点惯性率 params.minInertiaRatio = (float)0.4; params.maxInertiaRatio = 1; params.filterByColor = true; params.blobColor = 255;//白色 params.minRepeatability = 2;//重复的最小次数, params.minDistBetweenBlobs = 20; //最小的斑点距离 Ptr<SimpleBlobDetector> sbd = SimpleBlobDetector::create(params); sbd->detect(srcGrayImage1, detectKeyPoint); drawKeypoints(srcImage, detectKeyPoint, keyPointImage1, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS); resize(srcImage, srcImage1, Size(srcImage.cols / 4, srcImage.rows / 4), 0, 0, INTER_LINEAR); imshow("src image", srcImage1); resize(keyPointImage1, keyPointImage11, Size(keyPointImage1.cols /4, keyPointImage1.rows /4), 0, 0, INTER_LINEAR); imshow("keyPoint image1", keyPointImage11); imwrite("spos71_run7_img190.jpg", keyPointImage1); waitKey(0); return 0;}
四 实验结果
![这里写图片描述]
五 补充说明
保存特征点,绘制特征点,在使用中是不透明的,下面做一个简要介绍。
1.KeyPoint特征点类
保存特征点各种信息的KeyPoint类在使用的主要属性:
class KeyPoint{Point2f pt; //特征点坐标float size; //特征点邻域直径float angle; //特征点的方向,值为0~360,负值表示不使用float response; //特征点的响应强度,代表了该点是特征点的程度,可以用于后续处理中特征点排序int octave; //特征点所在的图像金字塔的组int class_id; //用于聚类的id}
主要包含的特征点信息有:位置、邻域直径、特征的方向、响应强度、多尺度信息和分类等。特征点匹配的实现就是通过逐个匹配特征点的这些信息。
2.drawKeypoints特征点绘制
opencv提供了一个快速绘制特征点的函数drawKeypoints,函数原型:
void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, CV_OUT Mat& outImage, const Scalar&color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
第一个参数image:原始图像,可以使三通道或单通道图像;
第二个参数keypoints:特征点向量,向量内每一个元素是一个KeyPoint对象,包含了特征点的各种属性信息;
第三个参数outImage:特征点绘制的画布图像,可以是原图像;
第四个参数color:绘制的特征点的颜色信息,默认绘制的是随机彩色;
第五个参数flags:特征点的绘制模式,其实就是设置特征点的那些信息需要绘制,那些不需要绘制,有以下几种模式可选:
DEFAULT:只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标。
DRAW_OVER_OUTIMG:函数不创建输出的图像,而是直接在输出图像变量空间绘制,要求本身输出图像变量就 是一个初始化好了的,size与type都是已经初始化好的变量
NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制
DRAW_RICH_KEYPOINTS:绘制特征点的时候绘制的是一个个带有方向的圆,这种方法同时显示图像的坐,size,和方向,是最能显示特征的一种绘制方式。
六 参考
http://blog.csdn.net/zhaocj/article/details/44886475
http://blog.csdn.net/dcrmg/article/details/52553513