图像特征提取:斑点检测

1. 什么是斑点

斑点通常是指与周围有着颜色和灰度差别的区域。在实际地图中,往往存在着大量这样的斑点,如一颗树是一个斑点,一块草地是一个斑点,一栋房子也可以是一个斑点。由于斑点代表的是一个区域,相比单纯的角点,它的稳定性要好,抗噪声能力要强,所以它在图像配准上扮演了很重要的角色。

同时有时图像中的斑点也是我们关心的区域,比如在医学与生物领域,我们需要从一些X光照片或细胞显微照片中提取一些具有特殊意义的斑点的位置或数量。

比如下图中天空的飞机、向日葵的花盘、X线断层图像中的两个斑点。

    

在视觉领域,斑点检测的主要思路都是检测出图像中比它周围像素灰度值大或比周围灰度值小的区域。一般有两种方法来实现这一目标:

  1. 基于求导的微分方法,这类的方法称为微分检测器;
  2. 基于局部极值的分水岭算法。

这里我们重点介绍第一种方法,主要检测LOG斑点。而OpenCV中SimpleBlobDetector斑点检测算子就实现了第二种方法,我们这里也会介绍它的接口使用方法。

2. LOG斑点检测

2.1 基本原理

利用高斯拉普通拉斯(Laplace of Gaussian,LOG)算子检测图像斑点是一种十分常用的方法,对于二维高斯函数:

G(x,y;σ)=12πσ2exp(−x2+y22σ2)

它的拉普拉斯变换为:

Δ2g=∂2g∂x2+∂2g∂y2

规范化的高斯拉普变换为:

Δ2norm=σ2Δ2g=σ2(∂2g∂x2+∂2g∂y2)=−12πσ2[1−x2+y2σ2]⋅exp(−x2+y22σ2)

规范化算法子在二维图像上显示是一个圆对称函数,如下图所示。我们可以用这个算子来检测图像中的斑点,并且可以通过改变σ的值,可以检测不同尺寸的二维斑点。

   

2.2 LOG原理解释

其实从更直观的角度去解释为什么LOG算子可以检测图像中的斑点是:

图像与某一个二维函数进行卷积运算实际就是求取图像与这一函数的相似性。同理,图像与高斯拉普拉斯函数的卷积实际就是求取图像与高斯拉普拉斯函数的相似性。当图像中的斑点尺寸与高斯拉普拉斯函数的形状趋近一致时,图像的拉普拉斯响应达到最大。

从概率的角度解释为:假设原图像是一个与位置有关的随机变量X的密度函数,而LOG为随机变量Y的密度函数,则随机变量X+Y的密度分布函数即为两个函数的卷积形式(这一部分的理论,可以参见本博客概率与统计相关文章)。如果想让X+Y能取到最大值,则X与Y能保持步调一致最好,即X上升时,Y也上升,X最大时,Y也最大。

那么LOG算子是怎么被构想出来的呢?

事实上我们知道Laplace可以用来检测图像中的局部极值点,但是对噪声敏感,所以在我们对图像进行Laplace卷积之前,我们用一个高斯低通滤波对图像进行卷积,目标是去除图像中的噪声点。这一过程 可以描述为:

先对图像f(x,y)用方差为σ的高斯核进行高斯滤波,去除图像中的噪点。

L(x,y;σ)=f(x,y)∗G(x,y;σ)

然后对图像的拉普拉斯图像则为:

Δ2=∂2L∂x2+∂2L∂y2

而实际上有下面等式:

Δ2[G(x,y)∗f(x,y)]=Δ2[G(x,y)]∗f(x,y)

所以,我们可以先求高斯核的拉普拉斯算子,再对图像进行卷积。也就是一开始描述的步骤。

2.3 LOG算子的实现

Mat Feat::getHOGKernel(Size& ksize, double sigma) 

    Mat kernel(ksize, CV_64F); 
    Point centPoint = Point((ksize.width -1)/2, ((ksize.height -1)/2)); 
    // first calculate Gaussian 
    for (int i=0; i < kernel.rows; i++) 
    { 
        double* pData = kernel.ptr<double>(i); 
        for (int j = 0; j < kernel.cols; j++) 
        { 
            double param = -((i - centPoint.y) * (i - centPoint.y) + (j - centPoint.x) * (j - centPoint.x)) / (2*sigma*sigma); 
            pData[j] = exp(param); 
        } 
    } 
    double maxValue; 
    minMaxLoc(kernel, NULL, &maxValue); 
    for (int i=0; i < kernel.rows; i++) 
    { 
        double* pData = kernel.ptr<double>(i); 
        for (int j = 0; j < kernel.cols; j++) 
        { 
            if (pData[j] < EPS* maxValue) 
            { 
                pData[j] = 0; 
            } 
        } 
    }

double sumKernel = sum(kernel)[0]; 
    if (sumKernel != 0) 
    { 
        kernel = kernel / sumKernel; 
    } 
    // now calculate Laplacian 
    for (int i=0; i < kernel.rows; i++) 
    { 
        double* pData = kernel.ptr<double>(i); 
        for (int j = 0; j < kernel.cols; j++) 
        { 
            double addition = ((i - centPoint.y) * (i - centPoint.y) + (j - centPoint.x) * (j - centPoint.x) - 2*sigma*sigma)/(sigma*sigma*sigma*sigma); 
            pData[j] *= addition; 
        } 
    } 
    // make the filter sum to zero 
    sumKernel = sum(kernel)[0]; 
    kernel -= (sumKernel/(ksize.width  * ksize.height));

return kernel; 
}

2.4 多尺度检测

我们注意到当σ尺度一定时,只能检测对应半径的斑点,那么检测的是多大半径的斑点呢,我们可以通过对规范化的二维拉普拉斯高斯算子求导:

规范化的高斯拉普拉斯函数为:

Δ2norm=−12πσ2[1−x2+y2σ2]⋅exp(−x2+y22σ2)

求Δ2norm的极点值等价于求取下式:

∂(Δ2norm)∂σ=0

得到:

(x2+y2−2σ2)⋅exp(−(x2+y2)2σ2)

r2−2σ2=0

对于图像中的斑点,在尺度σ=r/2√时,高斯拉普拉斯响应值达到最大。同理,如果图像中的圆形斑点黑白反向,那么,它的高斯拉普拉斯响应值在σ=r/2√时达到最小。将高斯拉普拉斯响应达到峰值时的尺度σ值,称为特征尺度。

那么在多尺度的情况下,同时在空间和尺度上达到最大值(或最小值)的点就是我们所期望的斑点。对于二维图像I(x,y),计算图像在不同尺度下的离散拉普拉斯响应值,然后检查位置空间中的每个点;如果该点的拉普拉斯响应值都大小于或小于其他26个立方空间领域(9+8+9)的值,那么该点就是被检测到的图像斑点。

3 OpenCV进行斑点检测

opencv中检测Blobs的类为SimpleBlobDetector,这个类在opencv中的定义如下:

class SimpleBlobDetector : public FeatureDetector
{
public:
struct Params
{
    Params();
    float thresholdStep;
    float minThreshold;
    float maxThreshold;
    size_t minRepeatability;
    float minDistBetweenBlobs;

    bool filterByColor;
    uchar blobColor;

    bool filterByArea;
    float minArea, maxArea;

    bool filterByCircularity;
    float minCircularity, maxCircularity;

    bool filterByInertia;
    float minInertiaRatio, maxInertiaRatio;

    bool filterByConvexity;
    float minConvexity, maxConvexity;
};

SimpleBlobDetector(const SimpleBlobDetector::Params &parameters = SimpleBlobDetector::Params());

protected:
    ...
};

算法的大致步骤如下:

  1. 对[minThreshold,maxThreshold)区间,以thresholdStep为间隔,做多次二值化。
  2. 对每张二值图片,使用findContours()提取连通域并计算每一个连通域的中心。
  3. 根据2得到的中心,全部放在一起。一些很接近的点[由theminDistBetweenBlobs控制多少才算接近]被归为一个group,对应一个bolb特征..
  4. 从3得到的那些点,估计最后的blob特征和相应半径,并以key points返回。

同时该支持提取特征的方法,一共有5个选项,这里就不多加描述了,默认是提取黑色圆形的Blob特征。下面是一个示例

int main(int argc, char** argv) 

    Mat image = imread(argv[1]); 
    vector<KeyPoint> keyPoints; 
    SimpleBlobDetector::Params params;

SimpleBlobDetector blobDetect(params); 
    blobDetect.create("SimpleBlob"); 
    blobDetect.detect(image, keyPoints); 
    cout << keyPoints.size() << endl; 
    drawKeypoints(image, keyPoints, image, Scalar(255,0,0));

namedWindow("blobs"); 
    imshow("blobs", image); 
    waitKey(); 
    return 0; 
}

  

总体来说,OpenCV的斑点检测效果还算不错,但是在有些图像的效果上明显不如LOG算子检测的检测效果。

4. 扩展阅读

一个与LOG滤波核近似的是高斯差分DOG滤波核,它的定义为:

D(x,y,σ)=(G(x,y,kσ)–G(x,y,σ))∗I(x,y)=L(x,y,kσ)−L(x,y,σ)

其中k为两个相邻尺度间的比例因子。

DOG可以看作为LOG的一个近似,但是它比LOG的效率更高。

前面介绍的微分算子在近圆的斑点检测方面效果很好,但是这些检测算子被限定于只能检测圆形斑点,而且不能估计斑点的方向,因为LOG算子等都是中心对称的。如果我们定义一种二维高斯核的变形,记它在X方向与Y方向上具有不同的方差,则这种算子可以用来检测带有方向的斑点。

G(x,y)=A⋅exp(−[a(ax2+2bxy+cy2)])

a=cos2θ2σ2x+sin2θ2σ2y

b=−sin2θ2σ2x+sin2θ4σ2y

c=sin2θ2σ2x+cos2θ2σ2y

其中A是规一性因子。

5. 参考资料

1. 《现代数字图像 -- 处理技术提高与应用案例详解》

2. 《图像局部不变性特征与描述》

3.  Lindeberg, T. Feature Detection with Automatic Scale Selection

4. Hui Kong. A Generalized Laplacian Of Gaussian Filter for Blob Detection and Its Applications.

5. OpenCV2马拉松第20圈——blob特征检测原理与实现

时间: 2024-10-13 23:00:59

图像特征提取:斑点检测的相关文章

目标检测的图像特征提取之(一)HOG特征(转载)

目标检测的图像特征提取之(一)HOG特征 [email protected] http://blog.csdn.net/zouxy09 1.HOG特征: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和统计图像局部区域的梯度方向直方图来构成特征.Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功.需要提醒的是,HOG+SVM进行行人检测的方法是法

【数字图像处理】目标检测的图像特征提取之HOG特征

1.HOG特征 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和统计图像局部区域的梯度方向直方图来构成特征.Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功.需要提醒的是,HOG+SVM进行行人检测的方法是法国研究人员Dalal在2005的CVPR上提出的,而如今虽然有很多行人检测算法不断提出,但基本都是以HOG+SVM的思路为主. (1)主要

图像特征提取:边缘检测

1. 边缘检测的概念 边缘检测是图像处理与计算机视觉中极为重要的一种分析图像的方法,至少在我做图像分析与识别时,边缘是我最喜欢的图像特征.边缘检测的目的就是找到图像中亮度变化剧烈的像素点构成的集合,表现出来往往是轮廓.在对现实世界的图像采集中,有下面4种情况会表现在图像中时形成一个边缘. 深度的不连续(物体处在不同的物平面上): 表面方向的不连续(如正方体的不同的两个面): 物体材料不同(这样会导致光的反射系数不同): 场景中光照不同(如被树萌投向的地面): 上面的图像是图像中水平方向7个像素点

图像特征提取:SIFT定位算法关键步骤的说明

1. SIFT算法中一些符号的说明 $I(x,y)$表示原图像. $G(x,y,\sigma)$表示高斯滤波器,其中$G(x,y,\sigma) = \frac{1}{2\pi\sigma^2}exp(-(x^2+y^2)/2\sigma^2)$. $L(x,y,\sigma)$表示由一个高斯滤波器与原图像卷积而生成的图像,即$L(x,y,\sigma) = G(x,y,\sigma)\otimes I(x,y)$.一系列的$\sigma_i$,则可以生成一系列的$L(x,y,\sigma_i)

图像局部特征点检测算法综述与应用举例

研究图像特征检测已经有一段时间了,图像特征检测的方法很多,又加上各种算法的变形,所以难以在短时间内全面的了解,只是对主流的特征检测算法的原理进行了学习.总体来说,图像特征可以包括颜色特征.纹理特等.形状特征以及局部特征点等.其中局部特点具有很好的稳定性,不容易受外界环境的干扰,本篇文章也是对这方面知识的一个总结. 本篇文章现在(2015/1/30)只是以初稿的形式,列出了主体的框架,后面还有许多地方需要增加与修改,例如2013年新出现的基于非线性尺度空间的KAZE特征提取方法以及它的改进AKAT

[OpenCV-Python] OpenCV 中图像特征提取与描述 部分 V (一)

部分 V图像特征提取与描述 29 理解图像特征 目标本节我会试着帮你理解什么是图像特征,为什么图像特征很重要,为什么角点很重要等.29.1 解释 我相信你们大多数人都玩过拼图游戏吧.首先你们拿到一张图片的一堆碎片,要做的就是把这些碎片以正确的方式排列起来从而重建这幅图像.问题是,你怎样做到的呢?如果把你做游戏的原理写成计算机程序,那计算机就也会玩拼图游戏了.如果计算机可以玩拼图,我们就可以给计算机一大堆自然图片,然后就可以让计算机把它拼成一张大图了.如果计算机可以自动拼接自然图片,那我们是不是可

斑点检测

1. 什么是斑点 斑点通常是指与周围有着颜色和灰度差别的区域.在实际地图中,往往存在着大量这样的斑点,如一颗树是一个斑点,一块草地是一个斑点,一栋房子也可以是一个斑点.由于斑点代表的是一个区域,相比单纯的角点,它的稳定性要好,抗噪声能力要强,所以它在图像配准上扮演了很重要的角色. 同时有时图像中的斑点也是我们关心的区域,比如在医学与生物领域,我们需要从一些X光照片或细胞显微照片中提取一些具有特殊意义的斑点的位置或数量. 比如下图中天空的飞机.向日葵的花盘.X线断层图像中的两个斑点.      在

斑点检测(LoG,DoG)(下)

斑点检测(LoG,DoG)(下) LoG, DoG, 尺度归一化 上篇文章斑点检测(LoG,DoG)(上)介绍了基于二阶导数过零点的边缘检测方法,现在我们要探讨的是斑点检测.在边缘检测中,寻找的是二阶导数的零点,可是在斑点检测中寻找的是极值点,这是为什么呢?而且在使用二阶导数寻找斑点时不仅在图像上寻找极值点,还要求在尺度空间上也是极值点,又是为什么呢?还有为什么DoG是LoG的简化版本呢?? 这篇文章主要内容就是回答这三个问题. From edges to blobs 对于阶跃信号,其二阶导数在

图像特征提取:Sobel边缘检测

图像特征提取:Sobel边缘检测 前言 点和线是做图像分析时两个最重要的特征,而线条往往反映了物体的轮廓,对图像中边缘线的检测是图像分割与特征提取的基础.文章主要讨论两个实际工程中常用的边缘检测算法:Sobel边缘检测和Canny边缘检测,Canny边缘检测由于算法复杂将在另一篇文章中单独介绍,文章不涉及太多原理,因为大部分的图像处理书籍都有相关内容介绍,文章主要通过Matlab代码,一步一步具体实现两种经典的边缘检测算法. Sobel边缘检测 Soble边缘检测算法比较简,实际应用中效率比ca