Разделить изображение на N изображений, где N — количество цветов, появляющихся на нем.

Я пытаюсь разделить изображение в зависимости от содержащихся в нем цветов.

Мои предыдущие шаги заключались в том, чтобы упростить его до 3 цветов, используя алгоритм KMeans, который предлагает Sklearn, и я получил результат, подобный следующему изображению.

Теперь мне нужно разделить его на 3 изображения по одному для каждого цвета. И получить что-то похожее на это (я сделал это с фотошопом).

Примеры выполнены в черно-белом цвете, потому что на самом деле, если я могу разделить, мне больше не нужны цвета. Но я бы сделал то же самое с 3-х цветными изображениями.

Маска 1:

Маска 2:

Маска 3:

Я нашел этот вопрос, но не могу достичь своей цели.

Я думал о разделении по каналам, но думаю, что это неправильно.

# set green and red channels to 0
blue_img[:, :, 1] = 0
blue_img[:, :, 2] = 0
# set blue and red channels to 0
green_img[:, :, 0] = 0
green_img[:, :, 2] = 0
# set blue and green channels to 0
red_img[:, :, 0] = 0
red_img[:, :, 1] = 0

Я думаю, что ключ в моем алгоритме kmeans, потому что с его помощью я получаю labels и centroids своих цветов, но я действительно не знаю, как это сделать, и я не могу найти никого, кто бы это делал.

Мой алгоритм KMeans:

def get_colors(img, number_of_colors, show_chart, show_segmented_img):
    
    modified_image = img.reshape(img.shape[0]*img.shape[1], 3)
    
    myKMeans = KMeans(n_clusters = number_of_colors)
    
    labels = myKMeans.fit_predict(modified_image)
    
    counts = Counter(labels)
    
    centroids = myKMeans.cluster_centers_
    
    ordered_colors = [centroids[i] for i in counts.keys()]
    
    hex_colors = [RGB2HEX(ordered_colors[i]) for i in counts.keys()]
    
    rgb_colors = [ordered_colors[i] for i in counts.keys()]
    
    if (show_chart):
        plt.figure(figsize = (8, 6))
        plt.pie(counts.values(), labels = hex_colors, colors = hex_colors)
        plt.show()

    if (show_segmented_img):
        centroids = np.uint8(centroids)
        segmented_data = centroids[labels.flatten()]
        segmented_image = segmented_data.reshape(img.shape)
        segmented_image = cv2.cvtColor(segmented_image, cv2.COLOR_RGB2BGR)
        cv2.imwrite('segmentedImg.png', segmented_image)

    return hex_colors, rgb_colors

Может ли кто-нибудь помочь мне, пожалуйста?

Большое спасибо!

Обновлено: Из ответа Хихикомори.

Из ответа Хихикомори я понимаю, что я должен сделать следующее, это основано на вопросе, который я связал ранее, но проблема в том, что я получаю 3 черные маски без какого-либо контура, поэтому я подумал, что это мне не подойдет.

def get_colors(img, number_of_colors, show_chart, show_segmented_img):
    
    modified_image = img.reshape(img.shape[0]*img.shape[1], 3)
    
    myKMeans = KMeans(n_clusters = number_of_colors)
    
    labels = myKMeans.fit_predict(modified_image)
    
    counts = Counter(labels)
    
    centroids = myKMeans.cluster_centers_
    
    ordered_colors = [centroids[i] for i in counts.keys()]
    
    hex_colors = [RGB2HEX(ordered_colors[i]) for i in counts.keys()]
    
    rgb_colors = [ordered_colors[i] for i in counts.keys()]

    # TRYING THE ASNWER
    color1, color2,color3 = rgb_colors
    first_color_indices = np.where(np.all(img == color1, axis=-1))
    second_color_indices = np.where(np.all(img == color2, axis=-1))
    third_color_indices = np.where(np.all(img == color3, axis=-1))

    img1 = np.zeros_like(img)
    img1[first_color_indices]=color1

    img2 = np.zeros_like(img)
    img2[second_color_indices]=color2

    img3 = np.zeros_like(img)
    img3[third_color_indices]=color3

    print('***')
    cv2_imshow(img1)
    print('***')
    cv2_imshow(img2)
    print('***')
    cv2_imshow(img3)
    print('***')
    
    if (show_chart):
        plt.figure(figsize = (8, 6))
        plt.pie(counts.values(), labels = hex_colors, colors = hex_colors)
        plt.show()

    if (show_segmented_img):
        centroids = np.uint8(centroids)
        segmented_data = centroids[labels.flatten()]
        segmented_image = segmented_data.reshape(img.shape)
        segmented_image = cv2.cvtColor(segmented_image, cv2.COLOR_RGB2BGR)
        cv2.imwrite('segmentedImg.png', segmented_image)

    return hex_colors, rgb_colors

Если каждая маска представляет свой цвет, почему у масок есть общие области?

GaneshTata 21.12.2020 06:47

Потому что я ошибся, когда делал пример с фотошопом, извините

Lleims 21.12.2020 10:01

Рассматривали ли вы преобразование изображения в матрицу HLS или HSV? Оттенок означает цвет, например красный зеленый синий cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

Grzegorz Krug 21.12.2020 13:10
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python.
Некоторые методы, о которых вы не знали, что они существуют в Python.
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
377
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

color1 = (0,0,160)
color2 = (0,160,160)
color3 = (160,160,160)
img = np.zeros((640,480,3),np.uint8)

img[100:200,100:200] = color1
img[150:250,150:250] = color2
img[200:300,200:300] = color3

first_color_indices = np.where(np.all(img == color1,axis=-1))
second_color_indices = np.where(np.all(img == color2,axis=-1))
third_color_indices = np.where(np.all(img == color3,axis=-1))

img1 = np.zeros_like(img)
img1[first_color_indices]=color1

img2 = np.zeros_like(img)
img2[second_color_indices]=color2

img3 = np.zeros_like(img)
img3[third_color_indices]=color3

cv2.imshow('origin', img)
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.waitKey(0)

Прежде всего, спасибо! Но с этим кодом я получаю только 3 черные маски. Я отредактировал свой вопрос на случай, если вы увидите ошибку (возможно, глупую).

Lleims 21.12.2020 10:16
Ответ принят как подходящий

Вы можете найти уникальные цвета в своем изображении с помощью np.unique(), а затем перебрать их, установив для каждого пикселя белый или черный цвет в зависимости от того, равен ли он этому цвету или нет:

#!/usr/bin/env python3

import cv2
import numpy as np

# Load image
im = cv2.imread('cheese.png')

# Reshape into a tall column of pixels, each with 3 RGB pixels and get unique rows (colours)
colours  = np.unique(im.reshape(-1,3), axis=0)

# Iterate over the colours we found
for i,colour in enumerate(colours):
    print(f'DEBUG: colour {i}: {colour}')
    res = np.where((im==colour).all(axis=-1),255,0)
    cv2.imwrite(f'colour-{i}.png', res)

Пример вывода

DEBUG: colour 0: [0 0 0]
DEBUG: colour 1: [0 141 196]
DEBUG: colour 2: [1 102 133]

Другие вопросы по теме