Расширение цвета фона для подключенных компонентов (Flood fill) - Обработка изображений - PullRequest
1 голос
/ 12 февраля 2020

застрял, пытаясь понять, как я могу расширить цвет фона внутрь. У меня есть это изображение, которое было сгенерировано с помощью маски после вычитания фонового шума.

enter image description here

Я пытаюсь сделать это следующим образом:

enter image description here

Пока я пытался это сделать, но безрезультатно:

import cv2
from PIL import Image
import numpy as np

Image.open("example_of_misaligned_frame.png") # open poor frame

img_copy = np.asanyarray(img).copy()

contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX) # find contours 

# create bounding box around blob and figure out the row.cols to iterate over
x,y,w,h = cv2.boundingRect(max(contours, key = cv2.contourArea)) 

# flood fill the entire region with back, hoping that off-white region gets filled due to connected components.
for row in range(y, y+h):
    for col in range(x, x+w):
        cv2.floodFill(img_copy, None, seedPoint=(col,row), newVal=0)

В результате получается полностью черное изображение: (

Любая помощь, указывающая мне правильное направление, очень ценится.

Ответы [ 2 ]

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

Вы можете решить эту проблему, дважды нажав floodFill:

  • Первый раз - залейте черные пиксели не совсем белым цветом.
  • Второй раз - закрасить пиксели не совсем белого черным цветом.

По-прежнему существует проблема с поиском значений RGB не совсем белого цвета.
Я нашел импровизированное решение для поиска не совсем белого цвета (я не знаю точных правил какой цвет считается фоновым).

Вот пример рабочего кода:

import cv2
import numpy as np

#Image.open("example_of_misaligned_frame.png") # open poor frame
img = cv2.imread("example_of_misaligned_frame.png")

#img_copy = np.asanyarray(img).copy()
img_copy = img.copy()

#Improvised way to find the Off White color (it's working because the Off White has the maximum color components values).
tmp = cv2.dilate(img, np.ones((50,50), np.uint8), iterations=10)

# Color of Off-White pixel
offwhite = tmp[0, 0, :]

# Convert to tuple
offwhite = tuple((int(offwhite[0]), int(offwhite[1]), int(offwhite[2])))

# Fill black pixels with off-white color
cv2.floodFill(img_copy, None, seedPoint=(0,0), newVal=offwhite)

# Fill off-white pixels with black color
cv2.floodFill(img_copy, None, seedPoint=(0,0), newVal=0, loDiff=(2, 2, 2, 2), upDiff=(2, 2, 2, 2))

cv2.imshow("img_copy", img_copy)
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат cv2.dilate:
enter image description here

Результат первого cv2.floodFill:
enter image description here

Результат второго cv2.floodFill:
enter image description here

1 голос
/ 13 февраля 2020

В Python / OpenCV вы можете просто извлечь двоичную маску из вашего заполненного изображения процесса и стереть эту маску. Затем примените его ко входу или к результату, заполненному потоком.

Вход:

enter image description here

import cv2

# read image
img = cv2.imread("masked_image.png")

# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# make anything not black into white
gray[gray!=0] = 255

# erode mask
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (51,51))
mask = cv2.morphologyEx(gray, cv2.MORPH_ERODE, kernel)

# make mask into 3 channels
mask = cv2.merge([mask,mask,mask])

# apply new mask to img
result = img.copy()
result = cv2.bitwise_and(img, mask)

# write result to disk
cv2.imwrite("masked_image_original_mask.png", gray)
cv2.imwrite("masked_image_eroded_mask.png", mask)
cv2.imwrite("masked_image_eroded_image.png", result)

# display it
cv2.imshow("IMAGE", img)
cv2.imshow("MASK", mask)
cv2.imshow("RESULT", result)
cv2.waitKey(0)


Маска:

enter image description here

Эрозированная маска:

enter image description here

Результат:

enter image description here

Отрегулируйте размер кольцевого (эллиптического) морфологического ядра по желанию для большей или меньшей эрозии.

...