【问题标题】:OpenCV counting overlapping circles using morphological operationOpenCV使用形态学运算计算重叠圆
【发布时间】:2020-01-30 14:50:26
【问题描述】:

这是我试图从中获取圆圈的图像。

我使用灰度图像和侵蚀的差异来获得边界。

img_path= 'input_data/coins.jpg'
img = cv2.imread(img_path)
rgb,gray=getColorSpaces(img)
a,b=0,255
plt.figure(figsize=(12, 12))

erosion_se=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
erosion = cv2.erode(gray,erosion_se,iterations = 1)
boundary=gray-erosion
image, contours, hierarchy = cv2.findContours(boundary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)    
plt.imshow(boundary,'gray')

我可以得到大多数边界相对清晰的圆圈的圆圈。 我想做两件事

  • 获取重叠圆圈的数量。

  • 找到接触图像边界的圆圈。 我可以通过将圆的半径与图像边界进行比较来确定。问题是 2 个特定的 blob 未被检测为圆圈。

    circles = cv2.HoughCircles(boundary, cv2.HOUGH_GRADIENT, 1, 20,
                  param1=30,
                  param2=15,
                  minRadius=5,
                  maxRadius=20)

    if circles is not None: 
        circles = np.uint16(np.around(circles))
        for i in circles[0,:]:
            cv2.circle(img,(i[0],i[2]),i[3],(0,255,0),2)
            cv2.circle(img,(i[0],i[2]),2,(0,0,255),3)

        cv2.imshow('circles', img)

        k = cv2.waitKey(0)
        if k == 27:
            cv2.destroyAllWindows()

下面是圆圈边界图像中 HoughCircles 之后的输出。突出的绿色大圆圈是不受欢迎的。我不确定为什么对于某些重叠区域,没有检测到圆圈。

【问题讨论】:

    标签: python image opencv image-processing image-morphology


    【解决方案1】:

    与其使用要求圆圈是“完美”圆圈并且在连接的斑点上不准确的 HoughCircles,不如使用简单的轮廓过滤方法。以下是主要思想:

    统计重叠圈数

    • 近似单个圆的轮廓区域,即~375
    • 查找轮廓、遍历轮廓并使用轮廓区域进行过滤
    • 对重叠圆圈求和

    为了找到与图像边界接触的圆圈,我们将检测区域限制在图像的外部 10 个像素。我们在这个新图像上找到轮廓,然后使用轮廓区域进行过滤以确定接触圆


    计算重叠圆圈的数量

    在转换为灰度和阈值以获得二值图像后,我们将单个斑点/圆的轮廓区域近似为~375。接下来我们在图像上找到轮廓并使用cv2.contourArea() 进行过滤。为了确定是否存在重叠,我们将每个轮廓的区域除以单个圆形区域,然后使用math.ceil() 找到天花板。如果我们得到一个大于 1 的上限值,这意味着 blob 已连接,我们只需将上限值添加到我们的计数器

    这是检测到的重叠圆圈

    重叠:213

    查找接触图像边界的圆圈

    这个想法是创建一个黑盒来屏蔽不在边界上的图像内部部分。我们可以通过cv2.fillPoly() 做到这一点。从这里我们找到轮廓并使用轮廓区域进行过滤。这个想法是,如果 blob 与某个阈值区域相比相对较大,则意味着 blob 最有可能接触边缘

    这是填充的黑框和检测到的触摸圆圈

    触摸:10

    import cv2
    import numpy as np
    import math
    
    image = cv2.imread('1.jpg')
    black_box = image.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
    
    # Count overlapping circles
    single_area = 375
    overlapping = 0
    
    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)
        blob_area = math.ceil(area/single_area)
        if blob_area > 1:
            overlapping += blob_area
            cv2.drawContours(image, [c], -1, (36,255,12), 2)
    
    # Find circles touching image boundary
    h, w, _ = image.shape
    boundary = 10
    touching = 0
    box = np.array(([boundary,boundary], 
                          [w-boundary,boundary], 
                          [w-boundary, h-boundary], 
                          [boundary, h-boundary]))
    cv2.fillPoly(black_box, [box], [0,0,0])
    
    copy = black_box.copy()
    copy = cv2.cvtColor(copy, cv2.COLOR_BGR2GRAY)
    copy = cv2.threshold(copy, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
    
    cnts = cv2.findContours(copy, 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 > 100:
            touching += 1
            cv2.drawContours(black_box, [c], -1, (36,255,12), 2)
    
    print('Overlapping:', overlapping)
    print('Touching:', touching)
    cv2.imshow('image', image)
    cv2.imshow('black_box', black_box)
    cv2.waitKey()
    

    【讨论】:

    • ,这真是太好了。这正是我正在寻找的。​​span>
    猜你喜欢
    • 2020-07-31
    • 1970-01-01
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    相关资源
    最近更新 更多