Как заполнить контур круга по краю изображения? - PullRequest
1 голос
/ 07 февраля 2020

enter image description hereenter image description here

На изображении выше я хочу в конечном итоге иметь возможность заполнить контуры цветных кругов. К сожалению, желтый кружок внизу находится прямо на краю изображения, поэтому cv2.findContours() не работает:

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

Кто-нибудь знает, как я могу каким-то образом заполнить контур желтого круга, хотя это на краю изображения? Так как он находится на краю изображения, значение пикселя на нижнем краю изображения не завершает круг, не оценивается в 255, если это имеет смысл.

Я посмотрел онлайн и некоторых людей скажем, можно нарисовать большую рамку вокруг изображения, а затем сделать контуры, но если я это сделаю, то opencv только dr aws большой контур вокруг всего изображения, а не круг.

Любой другой мысли были бы очень признательны!

РЕДАКТИРОВАТЬ: изображение, которое я показываю выше, это только один случай, который я рассматриваю. Я пытаюсь подумать, как я могу сделать это достаточно общим, чтобы для любого контура, который находится на краю границы, я все еще мог заполнить контур с помощью cv2.drawContour ().

Ответы [ 2 ]

2 голосов
/ 07 февраля 2020

Если у вас есть (более или менее) выпуклые многоугольники, вы на самом деле МОЖЕТЕ использовать cv2.findContours. Имея контуры, попробуйте найти центр масс, например, используя cv2.moments, а затем используйте его как начальную точку в cv2.floodFill.

Пожалуйста см. следующий фрагмент кода. Я полагаю, вы можете идентифицировать свои полигоны по цвету. Кроме того, вместо некоторого расширенного нахождения центра масс я просто использовал центральную точку ограничивающего прямоугольника каждого контура. Может быть, этого также достаточно для вашего варианта использования!?

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()

Это ввод:

Input

И это вывод :

Output

Надеюсь, это поможет!

----------------------------------------
System information
----------------------------------------
Platform:    Windows-10-10.0.16299-SP0
Python:      3.8.1
NumPy:       1.18.1
OpenCV:      4.1.2
----------------------------------------
1 голос
/ 07 февраля 2020

Простой способ, возможно, не такой точный, состоит в том, чтобы вычислить выпуклую оболочку для каждого контура и нарисовать внутреннее пространство цветом заливки:

enter image description here enter image description here

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...