Цветовые пространства: RGB, HSV и оттенки серого

Одно и то же изображение можно описать в разных «системах координат цвета» — и для разных задач удобны разные.

Цветовое пространство — способ закодировать цвет числами. RGB, HSV, grayscale описывают одни и те же пиксели, но в разных осях.

RGB: как хранят и показывают

RGB задаёт цвет тремя интенсивностями: красный, зелёный, синий. Это «родное» пространство экранов и камер. Но у него есть неудобство: чтобы выделить, скажем, «всё красное на фото», нельзя просто посмотреть на канал R — яркий и тёмный красный, красный в тени и на свету дают совершенно разные тройки. Цвет и яркость в RGB перемешаны.

HSV: цвет, насыщенность, яркость отдельно

HSV разделяет то, что в RGB слито воедино:

  • H (Hue, тон) — сам цвет по кругу: 0° красный, 120° зелёный, 240° синий.
  • S (Saturation, насыщенность) — насколько цвет «чистый» против серого.
  • V (Value, яркость) — насколько светлый.

Это удобно для выделения объектов по цвету: «найди всё, у чего тон около красного, независимо от освещённости» — достаточно условия по H, не трогая V. В RGB такое условие пришлось бы выписывать гораздо сложнее. Поэтому в OpenCV для цветовой сегментации (например, поиск красного мяча) почти всегда переходят в HSV.

ПространствоКогда удобно
RGBхранение, отображение, вход нейросети
HSVвыделение объектов по цвету, устойчивость к освещению
Grayscaleкогда важна форма, а не цвет; экономия в 3 раза

Grayscale: когда цвет лишний

Для распознавания границ, текста, форм цвет часто только мешает и утраивает объём данных. Один серый канал — это в три раза меньше чисел и весь акцент на яркости/форме. Классические алгоритмы (Собель, детектор углов) обычно работают по серому.

Простая «цветовая» проверка руками

Не уходя в полноценный перевод в HSV, можно грубо определить доминирующий канал пикселя — это уже даёт ощущение, как «цвет» отделяется от яркости:

pixels = [
    (200,  30,  40),
    ( 20, 180,  60),
    ( 30,  40, 210),
    (200, 200, 200),
]

for (r, g, b) in pixels:
    mx = max(r, g, b)
    if mx == r and r > g + 40 and r > b + 40:
        name = "красноватый"
    elif mx == g and g > r + 40 and g > b + 40:
        name = "зеленоватый"
    elif mx == b and b > r + 40 and b > g + 40:
        name = "синеватый"
    else:
        name = "серый/нейтральный"
    print(f"({r:3},{g:3},{b:3}) -> {name}")

Вывод:

(200, 30, 40) -> красноватый
( 20,180, 60) -> зеленоватый
( 30, 40,210) -> синеватый
(200,200,200) -> серый/нейтральный

Это игрушечная логика, но она показывает идею HSV: «цветность» — это про то, какой канал доминирует и насколько, а не про абсолютную яркость. Настоящий HSV делает это аккуратно и устойчиво.

Итог

  • RGB — для хранения и показа, но смешивает цвет и яркость.
  • HSV разделяет тон, насыщенность и яркость — удобно искать объекты по цвету.
  • Grayscale экономит данные и подходит, когда важна форма.
  • Выбор пространства — это выбор удобных «осей» под конкретную задачу.
Проверьте себя
1. Почему для выделения объекта по цвету (например, красного мяча) удобнее HSV, а не RGB?
AHSV занимает меньше памяти
BВ HSV тон (H) отделён от яркости (V), поэтому условие «красный» проще и устойчивее к освещению
CRGB не поддерживает красный цвет
DHSV всегда точнее
2. В чём практическая выгода перевода в grayscale для классических алгоритмов?
AПоявляются новые цвета
BДанных в 3 раза меньше, а форма/яркость сохраняются — то, что важно для границ и текста
CКартинка становится больше по разрешению
DЭто единственный способ сжать JPEG
3. Что описывает компонента H (Hue) в HSV?
AЯркость пикселя
BСам цвет (тон) по цветовому кругу
CУровень шума
DПрозрачность
Поддержать проект