斑点检测学习笔记

作者: 开飞机的乔巴 | 来源:发表于2019-08-12 11:06 被阅读5次

    本博客内容来源于网络以及其他书籍,结合自己学习的心得进行重编辑,因为看了很多文章不便一一标注引用,如图片文字等侵权,请告知删除。

    学习笔记目录----->传送门 <-----

    斑点检测简介

    定义斑点

    首先我们来给斑点下个比一个“点”更准确的文字定义,斑点通常指与周围有着颜色和灰度区别的区域(我们也称这种区域叫做奇异区域)。举个例子,一辆汽车可以是一个斑点,车身的轮胎也可以是一个斑点,轮胎上的一个螺丝钉也可以是一个斑点。只要这个区域与周围的区域有着颜色或者灰度的区别,我们就认为它在某个观察维度下就是一个斑点,取决于对物体分析的颗粒度。

    上面我们用比较形象的语言定义了斑点,那么我们怎么用比较数学的语言去描述它呢?斑点就是被边缘完整包围的一块区域。这块区域的像素值与周围区域有这较大的差别。(好像不是很数学。。。。。。)

    斑点检测有什么用途

    斑点检测可以帮我们分割出特定的感兴趣的区域,查找兴趣点,以及在形状的检测中,比如圆形检测,较其他方法有很大辅助。

    检测方法

    斑点检测的思路和上面的描述差不多,就是检测出图像中比周围像素值大或者比周围区域像素值小的区域,一般来说,有两种基本方法

    1. 基于求导的微分方法,即使用滤波核与图像进行卷积,找出与滤波核具有相同特征的区域,例如LoG 算法,DoH算法,DOG算法
    2. 基于局部极值的分水岭算法,例如opencv 中的 SimpleBlobDetector, 分水岭算法的思路比较简单, 假设我们将像素值设置为高度,像素值为0就是地面,然后整幅图像也如一座座山峰,每个山峰的峰顶就是我们的局部极值。局部极值就和我们的斑点的描述是不是很像了,在后面我们详细描述其操作步骤。

    下面我们来描述一下这几种算法


    沉迷学习,日渐消瘦

    LoG斑点检测详述

    LoG全称是:Laplace of Gaussian(高斯拉普拉斯)是一种形态学处理的方法,可以用来进行斑点的检测。

    拉普拉斯感觉很熟悉,哦,对了,在之前的边缘检测中,我们有学习过拉普拉斯算子,它是一个二阶算子,在过0点的地方可认为是边缘。高斯拉普拉斯和拉普拉斯算子是否有关系呢?我们接下来看。

    在想他们是否有关系之前我们先解释一下,高斯拉普拉斯函数为什么能检测斑点。
    首先,我们想一个问题:一个图像与一个二维函数进行卷积操作,直观上的出来的解是什么含义?

    我们应该知道对图像的卷积就是使卷积模板与原图像的像素相对应的位置先做乘法然后把相应位置得到的结果进行求和,最终把求和的结果赋给目标像素。那这实际上就是做了点积操作,点积的操作就是两个向量相应位置相乘然后求和。点积的物理意义是两个向量之间的相似度,推广到二维图像可以说成卷积模板与图像中某一块区域的相似度。如果卷积结果越大,说明图像中的某位置和卷积模板类似,如果卷积结果小,说明图像中某位置和卷积模板的相似度很小。

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

    我们在边缘检测说,二阶微分图中极大值和极小值之间的过 0 点,被认为是边缘。那么极大值和极小值又是什么呢?其实就是我们认为的斑点。

    我们可以看一下高斯拉普拉斯的函数可视化,是不是就是一个斑点。 看起来和拉普拉斯函数的趋势有点像,是的,那高斯是怎么回事?我们知道Laplace算子对噪声比较敏感,所以在我们对图像进行Laplace卷积之前,我们用一个高斯低通滤波对图像进行卷积,目标是去除图像中的噪声点。用公式表示如下: 先对图像用方差σ的高斯核进行高斯滤波: 然后对图像进行拉普拉斯变换: 将两步何在一起即: 所以,我们可以先求高斯核的拉普拉斯算子,再对图像进行卷积。即 当上式的极值点为0时,可以认为是 化简完为 对于半径为r的斑点来说,当方差为如下时

    高斯拉普拉斯响应值达到最大或最小,也就是我们的斑点。

    现在我们基本上解释了,之前的我们的问题。接下来我们看一下具体的操作。

    1. 我们计算出在半径范围内的不同的尺度因子σ(即高斯核方差)的高斯核的拉普拉斯算子
    2. 在图片上进行不同尺度因子LoG
    3. 然后在尺度空间和图像空间上检测都是极值的点,确定为斑点的中心。

    DOH斑点检测

    DOH 全称:Determinant of Hessian,基本方法流程和思路与LoG一样,区别不同的是使用了Hessian矩阵: 对一张图计算xx,yy,xy三个方向的卷积,然后计算其加权行列式:

    理论上,与LOG相比,DOH对细长结构的斑点有较好的抑制作用。

    DOG斑点检测

    DOG实际上对LOG的一种近似,为什么呢?先来看看归一化之后的LoG算子: 而高斯差分算子: 所以:

    因为k-1是常量不影响函数极值点,所以检测归一化的LoG在尺度空间的极值,即近似于检测DoG空间的极值(再具体的过程大家可以自己推导一下)。

    所以DoG进行斑点检测流程:

    1. 首先使用不同尺度的高斯算子对图像进行平滑
    2. 其次计算相邻尺度下平滑图像的差分图像(DoG空间)
    3. 最后在DoG空间寻找极值点

    LoG与DoG相比,明显需要更多的加法运算和乘法运算。虽然DoG需要在每层金字塔多做一次高斯操作(即为了得到S+2张DoG图需要S+3张高斯模糊图),但通过减法取代LoG核的计算过程,显著减少了运算次数,大大节省了运算时间。

    SimpleBlobDetector算法斑点检测详述

    SimpleBlobDetector 算法并没有什么过于复杂的数学计算,正如其名字,简单的斑点检测,我们来看看其大概的几个重要的过程。

    1. 对一张图片,设定一个低阈值,设定一个高阈值,在设定一个阈值步进,然后从低阈值到高阈值按照阈值步进取一系列的阈值,即对[minThreshold,maxThreshold)区间,以thresholdStep为间隔,用每一个阈值对图像进行二值化,得到一系列图像;
    2. 对每张二值图片,使用查找这些图像的边,并计算每一个轮廓的中心;
    3. 根据2得到每一个图片的轮廓的中心点,全部放在一起。定义一个最小距离,在这个距离区域内的特征中心点[由theminDistBetweenBlobs控制多少才算接近]被归为一个group,对应一个斑点特征,得到特征点集合。
    4. 从3得到的那些点,估计最后的斑点特征和相应半径。
    5. 对特征点进行相应的过滤,例如颜色过滤,面积过滤,圆度等。

    opencv 斑点检测(SimpleBlobDetector)效果[代码]

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    
    cv::Mat find_blob(cv::Mat &image)
    {
        cv::Mat view_gray;
        if(image.channels()==3){
            cv::cvtColor(image,view_gray,cv::COLOR_RGB2GRAY);
        }
        else{
            image.copyTo(view_gray);
        }
        cv::SimpleBlobDetector::Params params;
        params.filterByArea = true;
        params.minArea = 50.0f;
        params.maxArea = 100000.0f;
        params.filterByCircularity = true;
        params.minCircularity = (float)0.5;
        params.maxCircularity = std::numeric_limits<float>::max();
        params.filterByConvexity = true;
        params.minConvexity = (float)0.5;
        params.maxConvexity = std::numeric_limits<float>::max();
        params.minThreshold = 50;
        params.maxThreshold = 200;
        params.minDistBetweenBlobs = 0.0f;
    
        cv::Ptr<cv::SimpleBlobDetector> blobDetector =  cv::SimpleBlobDetector::create(params);
        std::vector<cv::KeyPoint> keypoints;
        blobDetector->detect(view_gray ,keypoints,cv::Mat());
        cv::Mat keyimage;
        cv::drawKeypoints(image,keypoints,keyimage,cv::Scalar(0,255,0));
        cv::imshow("blob",keyimage);
        cv::waitKey(0);
        return keyimage;
    }
    int main(int argc, char *argv[])
    {
        cv::Mat  orignal_image = cv::imread (argv[1]);
        cv::Mat image_with_blob = find_blob(orignal_image);
        cv::imwrite("blob_image.png",image_with_blob);
        return 0;
    }
    
    原图 斑点检测后图片,绿圈为检测出斑点

    仅展示SimpleBlobDetector,其他方法日后更新,可以看出来检测的效果还是很好的,基本上苹果和皮卡丘的眼睛嘴巴都检测出来了。

    总结

    1. 通过学习完斑点检测和边缘检测,我们法线LOG和DOG都可以用来进行斑点和边缘检测,区别就是一个算极值点一个算过0点。
    2. 从这片文章的结构也发现,我们大篇幅都在LOG的解释,而其他几种算法却很少。这也反映出我个人的学习进度是我在LOG花了很多的时间,理解了LOG之后在去理解其他的就很简单了,这是不是一种提高呢。不知道大家是不是这样,所以有那么多的知识需要去学,还是不用紧张着急的。

    重要的事情说三遍:

    如果您看到我的文章对您有所帮助,那就点个赞呗 ( * ^ __ ^ * )

    如果您看到我的文章对您有所帮助,那就点个赞呗( * ^ __ ^ * )

    如果您看到我的文章对您有所帮助,那就点个赞呗( * ^ __ ^ * )

    传统2D计算机视觉学习笔记目录传送门
    传统3D计算机视觉学习笔记目录传送门

    任何人或团体、机构全部转载或者部分转载、摘录,请保留本博客链接或标注来源。博客地址:开飞机的乔巴

    作者简介:开飞机的乔巴(WeChat:zhangzheng-thu),现主要从事机器人抓取视觉系统以及三维重建等3D视觉相关方面,另外对slam以及深度学习技术也颇感兴趣,欢迎加我微信或留言交流相关工作。

    相关文章

      网友评论

        本文标题:斑点检测学习笔记

        本文链接:https://www.haomeiwen.com/subject/praidctx.html