Python OpenCV简单斑点检测器未检测到所有斑点

Python OpenCV简单斑点检测器未检测到所有斑点,python,opencv,computer-vision,Python,Opencv,Computer Vision,我正在尝试将一个图像分析脚本从Mathematica移植到Python OpenCV,但其中一个函数遇到了问题 我设法对图像进行二值化和分水岭处理,就像在Mathematica中一样。但是,筛选所连接组件的属性的步骤似乎无法正常工作 输入图像如下所示: 但是,我尝试运行以下代码: import cv2 import numpy as np img = cv2.imread('test2.4.png', 1) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY

我正在尝试将一个图像分析脚本从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检测的参数设置为尽可能宽松。然而,大部分斑点未检测到,也未检测到任何流域分割斑点

我已经检查并调整了其中的大部分,除了阈值和(因为图像已经二值化)。为了让函数检测所有存在的BLOB,我是否应该执行任何其他配置


或者,是否有其他最近/更新良好的库能够按组件测量进行过滤?

我知道这已经很久了,但我在这里与您有类似的任务。感兴趣的是如何使用宽度为1的线来分隔那些连接的blob

但是,我使用SimpleBlobDetector玩了一会儿,它所做的只是简单地执行以下步骤(从阅读其源代码开始):

  • 使用不同的阈值(从minThreshold到maxThreshold)和step thresholdStep对图像进行二值化
  • 在每个二值化图像中查找轮廓,在这里应用过滤器,例如面积、颜色、圆度、凸度、惯性等
  • 根据位置组合所有过滤的轮廓,即在两个球之间的距离大于Mindist且不重叠
  • 存储并返回保留的所有斑点(轮廓)的关键点
  • 因此,我使用以下简单代码检查了SimpleBlobDetector的每个步骤,并发现用于分隔连接的斑点的宽度=1的线被发现为单独的轮廓/斑点(在所附图像中,轮廓/斑点显示为红色,轮廓/斑点的中心显示为绿色),特别是对于非水平/垂直线(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或自己使用FindContetors。像这样:

    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内核进行腐蚀,发现的斑点比原始斑点小1~2个像素。我没有对此进行更正(甚至没有尝试去想它)。如果你愿意,我想你可以自己做。希望这有帮助