Заполнение контуров с помощью OpenCV Python

У меня есть двоичное изображение с полилиниями, созданное с помощью:

cv2.polylines(binaryImage,contours,1, (255,255,255))

Теперь мне нужен эффективный метод заполнения всех полилиний. Я не нашел такой метод в opencv, но, возможно, он существует. В качестве альтернативы, возможно, я мог бы реализовать алгоритм, чтобы сделать работу (но быстрый - у меня есть HD готовые изображения). Пожалуйста, поделитесь своими мыслями..

6 ответов

При использовании функции "cv2.drawContours" отправьте толщина =cv2.FILLED, и все готово.

Я думаю, что вы ищете cv2.fillPoly, который заполняет область, ограниченную одним или несколькими полигонами. Это простой фрагмент, я создаю контур из четырех точек, представляющих вершины квадрата, затем заливаю многоугольник белым цветом.

import numpy as np
import cv2

contours = np.array( [ [50,50], [50,150], [150, 150], [150,50] ] )
img = np.zeros( (200,200) ) # create a single channel 200x200 pixel black image 
cv2.fillPoly(img, pts =[contours], color=(255,255,255))
cv2.imshow(" ", img)
cv2.waitKey()

Вы можете использовать fillPoly или drawContours, если ваш контур замкнут. Собрав вместе @jabaldonedo и @ash-ketchum, ответят:

import cv2
import matplotlib.pyplot as plt
import numpy as np

# Lets first create a contour to use in example
cir = np.zeros((255,255))
cv2.circle(cir,(128,128),10,1)
_, contours, _ = cv2.findContours(cir.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# An open circle; the points are in contours[0]
plt.figure()
plt.imshow(cir)

# Option 1: Using fillPoly
img_pl = np.zeros((255,255))
cv2.fillPoly(img_pl,pts=contours,color=(255,255,255))
plt.figure()
plt.imshow(img_pl)

# Option 2: Using drawContours
img_c = np.zeros((255,255))
cv2.drawContours(img_c, contours, contourIdx=-1, color=(255,255,255),thickness=-1)
plt.figure()
plt.imshow(img_c)

plt.show()

оба img_pl и img_c содержат закрашенный круг из точек контура [0]

Ты можешь использовать drawContours с установленным флагом FILLED:

(код на Java)

Imgproc.drawContours(mat, contours, contourID, COLOR, Core.FILLED);

Вы даете идентификатор желаемого контура и цвет, которым вы хотите его заполнить.

Я знаю, что OP спросил об использовании OpenCV в частности, но я закончил здесь, просто пытаясь заполнить полигоны сегментации, которые у меня были, несмотря на (также, OpenCV был немного проблематичным для моего случая) библиотекой, и я считаю, что многие другие пользователи тоже это сделали, поэтому вот мое решение с использованием scikit imageс polygon функция .

Из документов:

      import matplotlib.pyplot as plt

from skimage.draw import line, polygon, circle, ellipse
import numpy as np


img = np.zeros((500, 500, 3), 'uint8')

# draw line
rr, cc = line(120, 123, 20, 400)
img[rr,cc,0] = 255

# fill polygon
poly = np.array((
    (300, 300),
    (480, 320),
    (380, 430),
    (220, 590),
    (300, 300),
))
rr, cc = polygon(poly[:,0], poly[:,1], img.shape)
img[rr,cc,1] = 255

# fill circle
rr, cc = circle(200, 200, 100, img.shape)
img[rr,cc,:] = (255, 255, 0)

# fill ellipse
rr, cc = ellipse(300, 300, 100, 200, img.shape)
img[rr,cc,2] = 255

plt.imshow(img)
plt.show()

Результат:

Другой способ заполнить контур (фактически заполнить его и показать заполненным)

Найти все контуры
      contours, hierarchy = cv2.findContours(binary_image, cv2.RETR_LIST , cv2.CHAIN_APPROX_TC89_L1)
Чтобы найти подходящий контур (скажем, самую большую площадь)
      if len(contours) == 0:
    print("Empty binary image probably")
else:
    area = 0
    for contour in contours:
        if cv2.contourArea(contour) > area:
            def_contour = contour
            area = cv2.contourArea(contour)

Затем залейте заключительный контур

В final_image может быть binary_image например (или binary_image.copy())

      for i in range(Hight):
    for j in range(Width):
        if cv2.pointPolygonTest(target_contour, (j,i), True) > 0:
            final_image[i,j] = 1 # or 255 (binary image)
        else:
            final_image[i,j] = 0

Наконец, вы можете видеть, что на самом деле он заполнен

      import matplotlib.pyplot as plt
plt.imshow(final_image)
plt.show()
Другие вопросы по тегам