Цветовые пространства: 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 экономит данные и подходит, когда важна форма.
- Выбор пространства — это выбор удобных «осей» под конкретную задачу.