Выбор цвета подушки Python HSV;делая это более конкретным - PullRequest
1 голос
/ 02 апреля 2019

Я работаю над веб-приложением, которое позволит вам редактировать изображения с использованием цветов, например, раскрасить черно-белое изображение или переключить цвет автомобиля на цветное изображение.

Мой первый подходВыбор цвета - это выборка цвета в RGB, а затем работа оттуда.Проблема в том, что с rgb цветовая вариация настолько велика, что, выбирая похожие оттенки фиолетового на изображении, вы можете в конечном итоге повторно выбрать несколько раз, и при этом у вас останутся маленькие прямоугольники, в которых вы еще не пробовали его.Например, вот исходное изображение:

enter image description here

С помощью webapp я выбираю небольшую область прямоугольника между изображением для выборки цветов изатем показывая, где цвета совпали ниже

enter image description here

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

Я провел некоторое исследование и обнаружил, что HSV, то есть Hue, Saturation и Value, является более простым способом выбора оттенков цветов.

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

Это код ниже

def get_hsv_positions(image, positions):
    #hsv comes in hue (color of image), saturation and value that's supposed to be how light or dark the color is
    hsv_image = image.convert('HSV')

    values = []

    for pixel in positions:
        values.append(hsv_image.getpixel(tuple(pixel)))

    hues = set([x[0] for x in values])
    hue_matches = []

    width, height = image.size

    img_width, img_height = 0,0

    for _ in range(width * height):
        if img_width == width:
            img_height += 1
            img_width = 0

        pixel = hsv_image.getpixel((img_width, img_height))
        if pixel[0] in hues:
            hue_matches.append((img_width, img_height))

        img_width += 1

    return hue_matches

def get_color_range(request):
    ...

    #this gets the x,y position on the image of interest to sample colors
    cells = []
    for item in selection:
        pos = get_position(item['position']['left'], item['position']['top'], image.width, image.height, width, height)
        item['position']['top'] = pos[1]
        item['position']['left'] = pos[0]

        scale_grid(item, width, height, image.width, image.height)
        cells.extend(get_cells(item))

    image = PILImage.open(image_url)

    if hsv:
        cells = get_hsv_positions(image, cells)

, и именно так он сейчас сэмплирует изображение

enter image description here

лучше но нне идеально, как вы можете сказать здесь

Исходное изображение Выборка Цвет кожи

enter image description here

Выборка с использованием HSV

enter image description here

Сэмплирование без использования HSV

enter image description here

Как вы можете сказать, HSV get - это еще несколько небольших тонов, которыепоявляются на изображении в виде маленьких фигур, но не все из них.

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

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

1 Ответ

1 голос
/ 02 апреля 2019

Решение, которое приходит на ум, - размытие канала оттенка вашего изображения при выборе пикселей в диапазоне. Это должно сгладить резкие изменения оттенка (то есть квадратные артефакты на портрете).

Один из способов сделать это - преобразовать канал оттенка в массив numpy, применить фильтр Гаусса, а затем использовать его для создания маски. Это грубая перезапись вашей функции get_hsv_positions, в которой вместо циклов используются numpy и scipy.

import numpy as np
from scipy.ndimage import gaussian_filter

def get_hsv_positions_smooth(image, positions):
    #hsv comes in hue (color of image), saturation and value that's supposed to be how light or dark the color is
    hsv_image = image.convert('HSV')

    # convert to numpy array
    hsv_image = np.array(hsv_image)
    hue_channel = hsv_image[0, :, :]  # indexed (channel, row, column)

    # get the matching hues
    matching_hues = set()
    for x,y in positions:
        matching_hues.add(hue_channel[x, y])

    # blur hue channel
    SIGMA = 2
    blurred_hue = gaussian_filter(hue_channel, SIGMA)

    # mask the matching values
    mask = np.isin(blurred_hue, matching_hues)

    # get a list of [(x, y), ...] true values in the mask
    xs, ys = np.nonzero(mask)
    return zip(xs, ys)

Стоит отметить, что вы можете исследовать другие виды размытия, которые имеют другие свойства.

Редактировать: Я переместил предыдущее решение, потому что я думаю, что размытие, вероятно, даст вам лучшие результаты.

Одним из решений было бы искусственное сглаживание / расширение списка разрешенных оттенков hues. В данной области интереса выбранные вами оттенки могут быть не непрерывными (например, темно-синий и голубой, но не между ними синим цветом) и могут обрезаться при неестественном пороге.

Я бы предложил превратить hues в np.array, поэтому такие манипуляции немного проще. Если ваш массив hues выглядит примерно как [30, 31, ..., 40, 230, 231, ..., 240], вы можете сгладить его с помощью

import numpy as np

hues = np.array(hues)  # numpy it
blended_hues = np.concatenate([
    hues + 1, hues + 2, ...  # as many points out as you want
    hues - 1, hues - 2, ...
])
all_hues = list(np.unique(np.concatenate([hues, blended_hues])))

И тогда all_hues будет иметь ваши оригинальные оттенки с некоторыми дополнениями.

Другим решением может быть просмотр цветовых пространств CIE . В них обычно X и Y - это оттенки, расширенные до двух измерений, так что вы можете сделать более сложное смешивание цветов.

...