简体   繁体   English

如何在图像边缘填充圆形轮廓?

[英]How to fill a circle contour at the edge of an image?

在此处输入图片说明 在此处输入图片说明

In the image above, I want to eventually be able to fill in the contours of the colored circles.在上图中,我希望最终能够填充彩色圆圈的轮廓。 Unfortunately, the yellow circle on the bottom is right at the edge of the image, so cv2.findContours() doesn't work:不幸的是,底部的黄色圆圈正好位于图像的边缘,因此cv2.findContours()不起作用:

_, green_contours, _ = cv2.findContours(green_seg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

Does anyone know how I can somehow fill in the yellow circle contour even though it's at the edge of the image?有谁知道我如何以某种方式填充黄色圆圈轮廓,即使它位于图像的边缘? Since it's at the edge of the image, the pixel value on the bottom edge of the image doesn't complete the circle, isn't valued at 255, if that makes sense.由于它位于图像的边缘,因此图像底部边缘的像素值未完成圆,如果有意义的话,其值不为 255。

I looked online and some people say it's possible to draw a big box around the image and then do the contours, but if I do that, then opencv only draws the big contour around the entire image and not the circle.我在网上查了一下,有人说可以在图像周围画一个大框然后画轮廓,但如果我这样做,那么opencv只会在整个图像周围画大轮廓,而不是圆圈。

Any other thoughts would be greatly appreciated!任何其他想法将不胜感激!

EDIT: The image I show above is just one case I'm considering.编辑:我上面显示的图像只是我正在考虑的一种情况。 I'm trying to think how I can make this general enough such that for any contour that is at the edge of the border, I can still fill in the contour with cv2.drawContour().我正在考虑如何使这个足够通用,以便对于边界边缘的任何轮廓,我仍然可以使用 cv2.drawContour() 填充轮廓。

If you have (more or less) convex polygons, you actually CAN use cv2.findContours .如果你有(或多或少)凸多边形,你实际上可以使用cv2.findContours Having the contours, try to find the center of mass, eg using cv2.moments , and then use this as the seed point in cv2.floodFill .有了轮廓,尝试找到质心,例如使用cv2.moments ,然后将其用作cv2.floodFill的种子点。

Please see the following code snippet.请参阅以下代码片段。 I assume, you can identify your polygons by color.我假设,您可以通过颜色识别多边形。 Also, instead of some advanced finding of the center of mass, I just used the center point of the bounding rectangle of each contour.此外,我只是使用了每个轮廓的边界矩形的中心点,而不是对质心的一些高级查找。 Maybe, that's also sufficient for your use case!?也许,这对您的用例来说也足够了!?

import cv2
import numpy as np

# Set up test image
colors = [(0, 255, 0), (0, 0, 255)]
input = np.zeros((400, 400, 3), np.uint8)
cv2.circle(input, (100, 100), 50, colors[0], 10)
cv2.circle(input, (150, 350), 75, colors[1], 10)
output = input.copy()

# Iterate all colors...
for i, c in enumerate(colors):

    # Mask color
    img = np.all(output == c, axis=2).astype(np.uint8) * 255

    # Find contours with respect to OpenCV version
    cnts = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]

    # Get bounding rectangles; derive seed points for flood filling; flood fill
    rects = [cv2.boundingRect(c) for c in cnts]
    seeds = [(np.int32(r[0] + r[2] / 2), np.int32(r[1] + r[3] / 2)) for r in rects]
    [cv2.floodFill(output, mask=None, seedPoint=s, newVal=c) for s in seeds]

cv2.imshow('input', input)
cv2.imshow('output', output)
cv2.waitKey(0)
cv2.destroyAllWindows()

That's the input:这是输入:

输入

And, that's the output:而且,这就是输出:

输出

Hope that helps!希望有帮助!

----------------------------------------
System information
----------------------------------------
Platform:    Windows-10-10.0.16299-SP0
Python:      3.8.1
NumPy:       1.18.1
OpenCV:      4.1.2
----------------------------------------

A simple way, perhaps not so precise, is to compute the convex hull for each contour and draw the interior with a fill color:一种可能不太精确的简单方法是计算每个轮廓的凸包并用填充颜色绘制内部:

在此处输入图片说明 在此处输入图片说明

import cv2
import numpy as np
import sys

# load input image from the cmd-line
img = cv2.imread('test_images/partial_contour.png')
if (img is None):
    print('!!! Failed imread')
    sys.exit(-1)

output_img = img.copy()

# isolate just the colored drawings
ret, thres_bgr = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY)
thres_bgr[np.where((thres_bgr == [255,255,255]).all(axis=2))] = [0,0,0] # replace white pixels for black

# convert from 3-channels (BGR) to a single channel (gray)
gray_img = cv2.cvtColor(thres_bgr, cv2.COLOR_BGR2GRAY)

# this loop processes all the contours found in the image
contours, hierarchy = cv2.findContours(gray_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contourIdx, cnt in enumerate(contours):
    # compute a convex hull
    hull = cv2.convexHull(cnt)

    # fill the inside with red
    cv2.fillPoly(output_img, pts=[hull], color=(0, 0, 255))

cv2.imshow('output_img', output_img)
cv2.imwrite('fill_partial_cnt_output.png', output_img)
cv2.waitKey(0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM