Как разделить объекты по их цвету? - PullRequest
1 голос
/ 10 января 2020

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

Изображение, которое необходимо извлечь:

enter image description here

Скриншот кода:

enter image description here

1 Ответ

2 голосов
/ 10 января 2020

Здесь нет необходимости в реальном обнаружении цвета , поскольку обработка выполняется на выходе cv2.watershed. Это «изображение» markers типа np.int32 со значениями 0, 1, 2, 3, ... для одиночных маркеров, обнаруженных cv2.watershed, тогда как 0 является фоном. Таким образом, больше ничего не нужно делать, кроме итерации всех значений маркера (скажем, i), маскировки части, где markers == i, и поиска соответствующих координат ограничивающего прямоугольника, копирования этой части в новое изображение и сохранения в некоторых file.

Вот некоторый код, где cv2.watershed был имитирован с использованием cv2.findContours и cv2.drawContours соответственно ( интересная часть, касающаяся вопроса, является только второй for l oop ):

import cv2
import numpy as np
from matplotlib import pyplot as plt
from skimage import io          # Only needed for web grabbing images

# Load some image with circles from web
image = io.imread('https://www.teachertoolsinc.com/images/detailed/26/TCR77379.png')
plt.figure(1), plt.imshow(image), plt.title('original image'), plt.tight_layout()

# Mimic watershed result using findContours and drawContours
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
gray = cv2.threshold(gray, 16, 255, cv2.THRESH_BINARY)[1]
cnts = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
markers = np.zeros_like(gray).astype(np.int32)
for i, cnt in enumerate(cnts):
    markers = cv2.drawContours(markers, [cnt], -1, i+1, cv2.FILLED)
plt.figure(2), plt.imshow(markers), plt.title('markers'), plt.colorbar(), plt.tight_layout()
plt.show()

# Assuming we only have markers now; iterate all values and crop image part
for i in np.arange(1, np.max(markers[:, :])+1):
    pixels = np.array(np.where(markers == i)).astype(np.int32)
    x1 = np.min(pixels[1, :])
    x2 = np.max(pixels[1, :])
    y1 = np.min(pixels[0, :])
    y2 = np.max(pixels[0, :])
    cv2.imwrite(str(i) + '.png', image[y1:y2, x1:x2, :])

Это входное изображение:

Input

Это имитированное markers "изображение" ( ср. с предоставленным изображением, о котором идет речь):

Markers

И вот два отрезанных круга:

Example 1

Example 2

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

-----------------------
System information
-----------------------
Python:      3.8.1
Matplotlib:  3.2.0rc1
NumPy:       1.18.1
OpenCV:      4.1.2
-----------------------
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...