获取矩形内的圆形轮廓

时间:2018-08-19 19:00:27

标签: python opencv

假设我有一个灰度的,阈值图像,如下所示:

enter image description here

我需要圆圈的轮廓。我该怎么做呢? 我尝试了findContours有多种选择:

  • RETR_EXTERNAL:这仅返回外部矩形的轮廓

  • RETR_TREE:这会返回太多轮廓(外圆和内圆的轮廓)

每个圆只需要1个轮廓。我想在原始圆上绘制另一个色环(绿色或红色)。我预先指定了多少个圆(在本例中为120个圆),但是因为它生成120 * 2 = 240个轮廓(每个圆2个轮廓),所以程序失败。

那么,有没有办法只获得矩形内的圆的轮廓,而每个圆仅获得1个轮廓?

1 个答案:

答案 0 :(得分:1)

假设输入图像名为“ circles.jpg”。

首先,导入所需的库并以灰色格式加载图像。使用Numpy.where()函数可净化图像的前景和背景。然后在该图像上找到所有轮廓:

import cv2
import numpy as np
image_gray = cv2.imread("circles.jpg", 0)
image_gray = np.where(image_gray > 30, 255, image_gray)
image_gray = np.where(image_gray <= 30, 0, image_gray)
image_gray = cv2.adaptiveThreshold(image_gray, 255,
                                   cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                   cv2.THRESH_BINARY, 115, 1)
_, contours, _ = cv2.findContours(image_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

第二,创建一个具有相同宽度和高度的空图像。然后,使用过滤条件在新创建的图像上绘制轮廓-轮廓必须具有圆形形状:

image_copy = np.zeros_like(image_gray)  # create a new emtpy image
for cnt in contours:
    peri = cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, 0.04 * peri, True)
    (x, y, w, h) = cv2.boundingRect(cnt)
    ar = w / float(h)
    if len(approx) > 5 and 0.9 < ar < 1.1:  # filtering condition
        cv2.drawContours(image_copy, [cnt], 0, 255, -1)

第三,您需要将每个轮廓的区域存储到列表中,并删除所有过小的轮廓:

cnt_areas = []
cnt_circles = []
for cnt in contours:
    (x, y, w, h) = cv2.boundingRect(cnt)
    cnt_areas.append(w*h)
    cnt_circles.append(cnt)

import statistics
median_size_limit = statistics.median(cnt_areas) * 0.3
cnt_circles = [cnt for i, cnt in enumerate(cnt_circles)
               if cnt_areas[i] > median_size_limit]

最后,显示并检查结果:

# Draw the result and display
image = cv2.cvtColor(image_gray, cv2.COLOR_GRAY2RGB)
cv2.drawContours(image, cnt_circles, -1, (0, 0,255), 2)
cv2.imshow("Result Preview", image)
cv2.waitKey()

最终结果预览可以在这里查看:

Preview of Result