B13 - 图像处理 - Blob 检测与提取
Blob 检测原理以及评估指标
什么是 Blob 检测?
- Blob 在计算机视觉中通常指的是图像中的一块连续区域,这些区域具有某些共同的属性,比如颜色或灰度值。OpenCV 提供了 SimpleBlobDetector 类,它可以用于检测图像中的 blob,并根据不同的特征对它们进行过滤
- Blob 检测指识别和标记 blob 区域,目前有 3 种方法进行斑点检测:高斯拉普拉斯 (LoG)、高斯差分 (DoG) 和黑森行列式 (DoH)
1
2
3
4
5
6
7im = cv2.imread("blob.jpg", cv2.IMREAD_GRAYSCALE)
# 使用默认参数设置检测器.
detector = cv2.SimpleBlobDetector_create()
# 检测blob.
keypoints = detector.detect(im)
# 使用圆形绘制斑点.
im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
Blob 检测的原理?
- (1) 多次二值化:对 minThreshold,maxThreshold) 区间,以 thresholdStep 为间隔,做多次二值化
- (2) 分组: 在每个二进制图像中,连接的白色像素被分组在一起。我们称这些二进制斑点为二进制斑点
- (3) 合并: 计算二进制图像中二进制斑点的中心,并合并比 minDistBetweenBlob 更近的斑点
- (4) 中心及半径计算: 计算并返回新合并的 Blob 的中心和半径
OpenCV 的 Bolo 检测 “颜色 (blobColor)” 设置方法?
- 默认检测黑色点,如果要检测白色的点请设置 blobColor 为 true,并且 color 数值是 255.
OpenCV 的 Bolo 检测 “阈值 (minThreshold/maxThreshold/thresholdStep)” 设置方法?
- 设置二值化阈值区间,其中 thresholdStep 为阈值步进区间,用于生成多个二值图
OpenCV 的 Bolo 检测 “面积 (minArea/maxArea)” 设置方法?
- 基于大小过滤 blob 。例如,设置 minArea = 100 将滤除所有少于 100 个像素的斑点
OpenCV 的 Bolo 检测 “凸性 (minConvexity/maxConvexity)” 设置方法?
- 斑点的面积 / 凸包的面积,取值范围 [0-1]
OpenCV 的 Bolo 检测 “圆度 (minCircularity/maxCircularity)” 设置方法?
- 表示斑点距圆的距离,使用斑点面积与周长的平方之比计算,具有平移、尺度、旋转不变性
- 圆的圆度为 1,正方形的圆度为 0.785
OpenCV 的 Bolo 检测 “惯性比 (minInertiaRatio/maxInertiaRatio)” 设置方法?
- 衡量形状的伸长程度,相当于(短轴 / 长轴),例如对于一个圆,则惯性比是 1,对于椭圆的惯性比在 0 和 1 之间,而对于线是 0; 0≤ minInertiaRatio ≤1 , maxInertiaRatio ≤ 1
OpenCV 的 Bolo 检测的 minDistBetweenBlobs、minRepeatability 参数的含义?
- minDistBetweenBlobs: 最小的斑点距离,不同二值图像的斑点间距离小于该值时,被认为是同一个位置的斑点,否则是不同位置上的斑点,默认 10
- minRepeatability: 重复的最小次数,只有属于灰度图像斑点的那些二值图像斑点数量大于该值时,该灰度图像斑点才被认为是特征点,默认 2
什么是 Blob 提取?
- 连接组件标记(CCL)、连接组件分析(CCA)、Blob 提取、区域标记、斑点发现或区域提取是图论的一种算法应用,其中连接组件的子集基于给定的启发式方法被唯一标记。原理参考如何认识 OpenCV 的线型 lineType
- 通常使用 cv 2. ConnectedComponentsWithStats 来提取图像中的 Blob 区域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19img = cv2.imread("blob.png")
# 中值滤波,去噪
img = cv2.medianBlur(img, 3)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 阈值分割得到二值化图片
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# ret, binary = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY)
# 腐蚀操作
kernel2 = cv2.getStructuringElement(cv2.MORPH_ERODE, (11, 11))
bin_clo = cv2.erode(binary, kernel2, iterations=3)
# 连通域分析
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(bin_clo, connectivity=4)
# 不同的连通域赋予不同的颜色
output = np.zeros((img.shape[0], img.shape[1], 3), np.uint8)
for i in range(1, num_labels):
mask = labels == i
output[:, :, 0][mask] = np.random.randint(0, 255)
output[:, :, 1][mask] = np.random.randint(0, 255)
output[:, :, 2][mask] = np.random.randint(0, 255)