我正在尝试将我的一个图像分析脚本从Mathematica移植到Python OpenCV,但是我遇到了其中一个函数的问题。
我设法对图像进行二值化和分水岭,就像在Mathematica中一样。但是,过滤连接组件属性的步骤似乎无法正常工作。
输入图片如下:
但是,我尝试运行以下代码:
import cv2
import numpy as np
img = cv2.imread('test2.4.png', 1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Set up the detector and configure its params.
params = cv2.SimpleBlobDetector_Params()
params.minDistBetweenBlobs = 0
params.filterByColor = True
params.blobColor = 255
params.filterByArea = True
params.minArea = 10
params.maxArea = 300000
params.filterByCircularity = False
params.filterByConvexity = False
params.filterByInertia = True
params.minInertiaRatio = 0.01
params.maxInertiaRatio = 1
detector = cv2.SimpleBlobDetector_create(params)
# Detect blobs.
keypointsb = detector.detect(img)
# Draw detected blobs as red circles.
im_with_keypoints = cv2.drawKeypoints(img, keypointsb, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# Show keypoints
cv2.imwrite('test3.png',im_with_keypoints)
如代码所示,我已将blob检测的参数设置为尽可能宽松。然而,没有检测到大部分斑点,也没有检测到任何分水岭裂缝斑点。
我检查过documentation for the function并调整了大部分内容,但阈值和repeatability除外(因为图片已经被二元化)。是否有任何其他配置我应该执行以便函数检测所有存在的blob?
或者,是否有其他最近/更新的库能够通过组件测量进行过滤?
答案 0 :(得分:2)
我知道它很长,但我在这里和你有类似的任务。对如何使用width = 1行分隔这些连接的blob感兴趣。
但是,我使用SimpleBlobDetector玩了一会儿,它的作用简要介绍了以下步骤(从阅读源代码):
因此,我使用以下简单代码检查了SimpleBlobDetector的每一步,并发现用于分隔连接的blob的width = 1行被发现为单独的轮廓/ blob(轮廓/ blob显示为红色和轮廓/斑点的中心在附图中显示为绿色,特别是对于非水平/垂直线(1像素轮廓)。那些小轮廓然后被minArea或blobColor = 255过滤掉。这就是为什么你的分裂斑点被检测为更大的斑点。
import cv2
import numpy as np
img = cv2.imread('test3.png', 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, bin_img = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
out_img = img
temp_bin_img = bin_img.copy()
ret, contours = cv2.findContours(temp_bin_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
M = cv2.moments(contours[i])
if(M['m00'] == 0.0):
continue
x, y = int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])
out_img = cv2.drawContours(out_img, contours, i, (0,0,255), 1)
cv2.circle(out_img, (x, y), 1, (0,255,0), -1)
cv2.imwrite('test3-contours.png', out_img)
要改进,可能首先尝试侵蚀以增加边界的宽度,然后使用SimpleBlobDetector或自己使用findContours。像这样:
import cv2
import numpy as np
img = cv2.imread('YUSAQ.png', 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, bin_img = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((3,3),np.uint8)
erosion = cv2.erode(bin_img, kernel, iterations = 1)
out_img = img
temp_bin_img = erosion.copy()
ret, contours = cv2.findContours(temp_bin_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
M = cv2.moments(contours[i])
if(M['m00'] == 0.0):
continue
x, y = int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])
out_img = cv2.drawContours(out_img, contours, i, (0,0,255), 1)
cv2.circle(out_img, (x, y), 1, (0,255,0), -1)
cv2.imwrite('test3-erosion.png', out_img)
使用3x3内核进行侵蚀导致找到的blob比原始blob小1~2像素。我没有对此进行修正(甚至没有想到它)。如果你愿意,我想你可以自己做。希望这会有所帮助。