OpenCV 斑点检测

  • 2019 年 10 月 7 日
  • 筆記

斑点通常是指与周围有着颜色和灰度差别的区域。有时图像中的斑点也是我们关心的区域,比如在医学影像中或质量检测领域,我们需要从一些X光图片或普通光学照片中提取一些具有特殊意义的斑点的数量和坐标信息。

Opencv中提供了SimpleBlobDetector的特征点检测方法,正如它的名称,该算法使用最简单的方式来检测斑点类的特征点。该算法大致有如下步骤:

1.首先通过一系列连续的阈值把输入的灰度图像转换为一个二值图像的集合。阈值范围为[T1,T2],步长为t,则所有阈值为:

T1,T1+t,T1+2t,T1+3t,……,T2 (1)

2.第二步是利用Suzuki提出的算法通过检测每一幅二值图像的边界的方式提取出每一幅二值图像的连通区域,我们可以认为由边界所围成的不同的连通区域就是该二值图像的斑点。不是所有的二值图像的连通区域都可以认为是二值图像的斑点,我们往往通过一些限定条件来得到更准确的斑点。这些限定条件包括颜色,面积和形状等等。斑点的形状又可以用圆度,偏心率,或凸度来表示。

3.第三步是根据所有二值图像斑点的中心坐标对二值图像斑点进行分类,从而形成灰度图像的斑点,属于一类的那些二值图像斑点最终形成灰度图像的斑点,具体来说就是,灰度图像的斑点是由中心坐标间的距离小于阈值Tb的那些二值图像斑点所组成的,即这些二值图像斑点属于该灰度图像斑点;

4.最后就是确定灰度图像斑点的信息——位置和尺寸。位置是属于该灰度图像斑点的所有二值图像斑点中心坐标的加权和,即公式2,权值q等于该二值图像斑点的惯性率的平方,它的含义是二值图像的斑点的形状越接近圆形,越是我们所希望的斑点,因此对灰度图像斑点位置的贡献就越大。尺寸则是属于该灰度图像斑点的所有二值图像斑点中面积大小居中的半径长度。

(2)

我们以下面的蝌蚪找妈妈图为例来介绍源码的实现。

首先加载图片并进行高斯模糊以降噪。

import cv2  import numpy as np  from matplotlib import pyplot as plt    img0 = cv2.imread("tadpoles.jpg")  gray = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)  gauss = cv2.GaussianBlur(gray, (9,9), 0) #高斯模糊,X,Y 方向的Ksiez分别为9和9

再细化检测参数

params = cv2.SimpleBlobDetector_Params()  #斑点检测的可选参数  #params.minThreshold= 10 #亮度最小阈值控制  #params.maxThreshold = 255 #亮度最大阈值控制  params.thresholdStep = 9 #亮度阈值的步长控制,越小检测出来的斑点越多    params.filterByColor = True #颜色控制  params.blobColor = 0 #只检测黑色斑点  #params.blobColor = 255 #只检测白色色斑点    params.filterByArea = True #像素面积大小控制  params.minArea = 20  #params.maxArea=2000    #params.filterByCircularity = True #圆度控制,圆度的定义是(4π×面积)/(周长的平方)  #params.minCircularity = 0.3    #params.filterByConvexity =True #凸度控制,凸性的定义是(斑点的面积/斑点凸包的面积  #params.minConvexity = 1.0    #params.filterByInertia = True# 惯性率控制  #params.minInertiaRatio = 0.2#圆形的惯性率等于1,惯性率越接近1,圆度越高

然后执行斑点检测:

detector = cv2.SimpleBlobDetector_create(params)#创建斑点检测器  keypoints = detector.detect(gauss) #在哪个图上检测斑点  print("共检测出%d个斑点" %len(keypoints))    #在原图上画出检测到的斑点  im_with_keypoints=cv2.drawKeypoints(img0, keypoints, np.array([]), (0, 0, 255),                                      cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)  print("斑点中心坐标为:")  for (x,y) in keypoints[0].convert(keypoints):      print(x,",", y)      cv2.circle(im_with_keypoints, (x,y), 1, (255,255,255), 1) #以白色标记处斑点中心(以斑点中心为中心画圆)    #绘出检测结果图  plt.subplot(1,1,1)  plt.imshow(cv2.cvtColor(im_with_keypoints, cv2.COLOR_BGR2RGB))  plt.title("OpenCV 斑点检测n之小蝌蚪找妈妈",fontSize =16, color="b")  plt.show()

可以看到,除了全部的蝌蚪都被检测出来了外,青蛙的眼珠也被检测出来了。当然,后者很容易通过斑点面积过滤掉。