前面说过,图像特征点检测包括角点和斑点,今天来讲说斑点,斑点是指二维图像中和周围颜色有颜色差别和灰度差别的区域,由于斑点表明的是一个区域,因此其相对于单纯的角点,具备更好的稳定性和更好的抗干扰能力.算法
视觉领域的斑点检测的主要思路是检测出图像中比周围像素灰度打或者比周围区域灰度值小的区域,通常来讲,有两种基本方法函数
1.基于求导的微分方法,这成为微分检测器code
2.基于局部极值的分水岭算法,OPENCV中提供了simpleBlobDetector特征检测器来实现这种基本的斑点检测算法.blog
LOG斑点检测图片
使用高斯拉普拉斯算子检测图像斑点是一种比较常见的办法,对一个二维的高斯函数G(x,y,o),进过规范化的拉普拉斯变换之后,结果在二维图像上呈现为一个圆对称函数,咱们能够用这个函数来检测图像的斑点,而且能够经过改动o的值ci
来检测不一样尺寸的二维斑点.图像以下it
对上面这段话的直观理解是:一个图像和一个二维函数进行卷积运算,实际上就是求取图像和这个函数的类似性,同理,图像与高斯拉普拉斯函数进行卷积,就是求取图像和高斯拉普拉斯函数的类似性,当图像中的斑点尺寸与高斯拉普拉斯函数的形opencv
状趋于一致的时候,图像对应位置的拉普拉斯响应达到最大.class
实际上,lapacian算子自己能够检测图像的极值点,设其为L算子,可是由于L算子并不能消除干扰,图像M中的噪声会影响求取到的结果,因此对图像M进行名为G的高斯滤波去除干扰,获得图像M',公式以下M' = M*G*L=M*(G*L);括号里面就是channel
高斯拉普拉斯算子.
经过上面的那种算法,咱们能够获得斑点,可是没有多尺度的斑点,当高斯协方差o必定的时候,咱们只能检测对应o的半径的斑点,具体的半径经过对标准化的高斯拉普拉斯算子进行求导获得,当o=r/根号2时,响应最大,图像黑白反相时,响应最小,因
此将高斯拉普拉斯算子响应达到峰值的o值,成为特征尺度.
对应二维图像,计算图像在不一样尺度下的离散高斯拉普拉斯响应值,而后检查不一样尺度位置中的每一个值,若是某个尺度下的高斯拉普拉斯响应值,都小于或者大于其余尺度的值,那么该点就是被检测到的图像斑点位置.
2.基于局部极值的分水岭算法斑点检测simpleBlobDetector
这种检测方法分为如下几步
a.对一张图片,设定一个低阈值,设定一个高阈值,在设定一个阈值步进,而后从低阈值到高阈值按照阈值步进取一系列的阈值
b.用每个阈值对图像进行二值化,而后使用findcontours查找边,并计算每个轮廓的中心
c.对应每个图片的轮廓的中心,进行抑制,定义一个最小距离,在这个距离区域内的特征中心被定义为一个blob,获得特征点集合
d.对特征点进行相应的过滤,例如颜色过滤,面积过滤等
API:Ptr<smpleBlobDetector>create(simpleBlobDetector::params 参数集合)
参数集合里面包括 minthreshold 低阈值 maxthreshold 高阈值 thresholdStep 阈值步进 minDistanceBetweenBlob blob分块最小距离 filterColor 颜色过滤 filterArea 面积过滤
filterByCircularrty 圆度过滤 还有两个是边界长度过滤和凸度过滤,这五种过滤方式任选且只能选一种,默认使用黑色颜色过滤
具体使用代码以下
int main(int argc,char* argv[]) { Mat srcImage = imread("F:\\opencv\\OpenCVImage\\FeatureDetectSrc1.jpg"); Mat srcGrayImage; if (srcImage.channels() == 3) { cvtColor(srcImage,srcGrayImage,CV_RGB2GRAY); } else { srcImage.copyTo(srcGrayImage); } vector<KeyPoint>detectKeyPoint; Mat keyPointImage1,keyPointImage2; SimpleBlobDetector::Params params; params.minArea = 10; params.maxArea = 1000; params.filterByCircularity = true; Ptr<SimpleBlobDetector> sbd = SimpleBlobDetector::create(params); sbd->detect(srcGrayImage,detectKeyPoint); drawKeypoints(srcImage,detectKeyPoint,keyPointImage1,Scalar(0,0,255),DrawMatchesFlags::DRAW_RICH_KEYPOINTS); drawKeypoints(srcImage,detectKeyPoint,keyPointImage2,Scalar(0,0,255),DrawMatchesFlags::DEFAULT); imshow("src image",srcImage); imshow("keyPoint image1",keyPointImage1); imshow("keyPoint image2",keyPointImage2); imwrite("F:\\opencv\\OpenCVImage\\FeatureDetectSrc1SimpleBlobDetectorKeyPointImageDefault.jpg",keyPointImage2); waitKey(0); return 0; }