【问题标题】:Computer Vision: Opencv Counting small circles inside big circle计算机视觉:Opencv 计算大圆圈内的小圆圈
【发布时间】:2020-10-28 19:31:27
【问题描述】:

这是我一直在处理的图像

目标是检测大圆圈内的小圆圈。

目前我所做的是将图像转换为灰度并应用阈值 (cv2.THRESH_OTSU),从而生成此图像

在此之后,我使用我在 stackoverflow 上找到的椭圆形内核应用了 Morph open 的 findcontours 过滤掉了大型对象

结果图是这样的

有人可以指导我正确的做法,以及我哪里出错了。

下面是我一直在研究的附加代码

import cv2
import numpy as np

# Load image, grayscale, Otsu's threshold
image = cv2.imread('01.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
#cv2.imwrite('thresh.jpg', thresh)

# Filter out large non-connecting objects
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    #print(area)
    if area < 200 and area > 0:
        cv2.drawContours(thresh,[c],0,0,-1)

# Morph open using elliptical shaped kernel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

# Find circles 
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area > 20 and area < 50:
        ((x, y), r) = cv2.minEnclosingCircle(c)
        cv2.circle(image, (int(x), int(y)), int(r), (36, 255, 12), 2)

cv2.namedWindow('orig', cv2.WINDOW_NORMAL)
cv2.imshow('orig', thresh)
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', image)
cv2.waitKey()

谢谢!

【问题讨论】:

  • 一个可能有用的想法,如果你得到最大圆的轮廓,那么它里面的所有轮廓都将是你想要的更小的圆。所以,试着找出最大的圆圈。
  • 我猜你可以牺牲几个点来对抗“大圆圈”。然后过滤大小的斑点是一件容易的事。

标签: python opencv image-processing computer-vision opencv-contour


【解决方案1】:

我有一个想法,通过滑动窗口检测小圆圈。当小圆环区域占据滑动窗口面积大于90%(内接圆和正方形),小于100%(避免滑动窗口在大圆环中移动)时。这个位置是一个小圆圈。最大的滑动窗口尺寸是最大的小圆环尺寸。希望有所帮助。

另外,在Piglet的结果上,应用k-means,其中k = 2,可以得到二值图像,然后用findcontours统计小圆。

【讨论】:

    【解决方案2】:

    代码中的主要问题是您在 cv2.findContours() 函数中使用的标志。

    对于这样一个我们必须找到可以出现在另一个轮廓(大圆圈)内的轮廓的问题,我们不应该使用标志 cv2.RETR_EXTERNAL,而是使用 cv2.RETR_TREE。 Click here for detailed info..

    此外,如果内存不是问题,最好使用 cv2.CHAIN_APPROX_NONE 而不是 cv2.CHAIN_APPROX_SIMPLE。 Click here for detailed info.

    因此,下面的简单代码可以用来解决这个问题。

    import cv2
    import numpy as np
    
    Image = cv2.imread("Adg5.jpg")
    GrayImage = cv2.cvtColor(Image, cv2.COLOR_BGR2GRAY)
    
    # Applying Otsu's Thresholding
    Retval, ThreshImage = cv2.threshold(GrayImage, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    
    # Finding Contours in the image
    Contours, Hierarchy = cv2.findContours(ThreshImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    
    # Taking only those contours which have no child contour.
    FinalContours = [Contours[i] for i in range(len(Contours)) if Hierarchy[0][i][2] == -1]
    
    # Drawing contours
    Image = cv2.drawContours(Image, FinalContours, -1, (0, 255, 0), 1)
    
    cv2.imshow("Contours", Image)
    cv2.waitKey(0)
    

    Resulting image 在这种方法中,边界处也会出现大量噪声,但也会检测到所需的橙色点。现在的任务是去除边界噪声。

    另一种很大程度上去除边界噪声的方法类似于@Piglet 的方法。 在这里,我使用 HSV 图像分割出橙色点,然后使用上述方法检测它们。

    import cv2
    import numpy as np
    
    Image = cv2.imread("Adg5.jpg")
    HSV_Image = cv2.cvtColor(Image, cv2.COLOR_BGR2HSV)
    
    # Extracting orange colour using HSV Image.
    ThreshImage = cv2.inRange(HSV_Image, np.array([0, 81, 0]), np.array([41, 255, 255]))
    
    # Finding Contours
    Contours, Hierarchy = cv2.findContours(ThreshImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    
    # Taking only those contours which have no child contour.
    FinalContours = [Contours[i] for i in range(len(Contours)) if Hierarchy[0][i][2] == -1]
    
    # Drawing Contours
    Image = cv2.drawContours(Image, FinalContours, -1, (0, 255, 0), 1)
    
    cv2.imshow("Contours", Image)
    cv2.waitKey(0)
    

    Resultant Image

    【讨论】:

      【解决方案3】:

      将图像转换为灰度会丢掉很多有用的信息。

      为什么不利用您正在寻找的斑点是唯一红色/橙色的事实呢?

      我将饱和通道与红色通道相乘,得到了这个图像:

      现在找到白色斑点变得微不足道了。

      为这些渠道尝试不同的权重,或先应用阈值。有很多方法。尝试不同的照明、不同的背景,直到获得适合图像处理的理想输入。

      【讨论】:

      • 抱歉,我看不到丢失了哪些信息。图像基本上有两种颜色,甚至接近二进制。
      猜你喜欢
      • 2018-05-13
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2014-07-13
      • 2017-07-02
      • 2017-08-26
      相关资源
      最近更新 更多