Цветное сходство/расстояние в цветовом пространстве RGBA
Как вычислить сходство между двумя цветами в цветовом пространстве RGBA? (где цвет фона неизвестен конечно)
Мне нужно переназначить изображение RGBA в палитру цветов RGBA, найдя лучшую запись палитры для каждого пикселя в изображении *.
В цветовом пространстве RGB можно предположить, что наиболее сходным цветом является цвет с наименьшим евклидовым расстоянием. Однако этот подход не работает в RGBA, например, евклидово расстояние от rgba(0,0,0,0)
до rgba(0,0,0,50%)
меньше, чем до rgba(100%,100%,100%,1%)
, но последний выглядит намного лучше.
Я использую предварительно умноженное цветовое пространство RGBA:
r = r×a
g = g×a
b = b×a
и я попробовал эту формулу (изменение: см. ответ ниже для лучшей формулы):
Δr² + Δg² + Δb² + 3 × Δa²
но это не выглядит оптимальным - на изображениях с полупрозрачными градиентами он находит неправильные цвета, которые вызывают разрывы/острые края. Линейные пропорции между непрозрачными цветами и альфой кажутся подозрительными.
Какая оптимальная формула?
*) для простоты этого вопроса я игнорирую диффузию ошибок, гамму и психовизуальные цветовые пространства.
Немного связано: если вы хотите найти ближайший цвет в этом неевклидовом пространстве RGBA, vp-деревья являются лучшими.
Ответы
Ответ 1
Наконец-то я нашел это! После тщательного тестирования и экспериментов мои выводы таковы:
-
Правильный способ - рассчитать максимально возможную разницу между двумя цветами.
Формулы с любой оценкой средней/типичной разницы имели место для разрывов.
-
Мне не удалось найти рабочую формулу, которая рассчитывает расстояние, не смешивая цвета RGBA с некоторыми фонами.
-
Нет необходимости учитывать все возможные цвета фона. Это может быть упрощено до смешивания максимума и минимума отдельно для каждого из каналов R/G/B:
- смешать канал в обоих цветах с channel = 0 в качестве фона, измерить разницу в квадрате
- смешайте канал в обоих цветах с channel = max в качестве фона, измерьте квадратичную разницу
- взять выше из двух.
К счастью, смешивание с "белым" и "черным" тривиально, когда вы используете предварительно умноженную альфа (r = r×a
).
Полная формула:
max((r₁-r₂)², (r₁-r₂ - a₁+a₂)²) +
max((g₁-g₂)², (g₁-g₂ - a₁+a₂)²) +
max((b₁-b₂)², (b₁-b₂ - a₁+a₂)²)
C Источник, включая реализацию SSE2.
Ответ 2
Несколько принципов:
- Когда два цвета имеют одинаковый альфа, rgbaDistance = rgbDistance * (альфа/255). Совместим с алгоритмом цветового расстояния RGB, когда альфа составляет 255.
- Все цвета с очень низкой альфаю похожи.
- Сопротивление rgba между двумя цветами с одинаковым RGB линейно зависит от дельта-альфа.
double DistanceSquared(Color a, Color b)
{
int deltaR = a.R - b.R;
int deltaG = a.G - b.G;
int deltaB = a.B - b.B;
int deltaAlpha = a.A - B.A;
double rgbDistanceSquared = (deltaR * deltaR + deltaG * deltaG + deltaB * deltaB) / 3;
return deltaAlpha * deltaAlpha / 2.0 + rgbDistanceSquared * a.A * b.A / (255 * 255);
}
Ответ 3
Моя идея интегрируется один раз поверх всех возможных цветов фона и усредняет квадратную ошибку.
то есть. для вычисления каждого компонента (используя здесь красный канал)
Интеграл от 0 до 1 ((r1 * a1 + rB * (1-a1)) - (r2 * a2 + rB * (1-a2))) ^ 2 * drB
который, если я правильно вычисляю, вычисляет:
dA=a1-a2
dRA=r1*a1-r2*a2
errorR=dRA^2+dA*dRA+dA^2/3
И затем суммируем их по R, G и B.
Ответ 4
Прежде всего, очень интересная проблема:)
У меня нет полного решения (по крайней мере, пока нет), но есть два очевидных крайних случая, которые мы должны рассмотреть:
Когда Δa==0
проблема аналогична пространству RGB
При Δa==1
проблема заключается только в альфа-1-мерном пространстве
Таким образом, формула (которая очень похожа на ту, которую вы указали), которая удовлетворит это:
(Δr² + Δg² + Δb²) × (1-(1-Δa)²) + Δa²
или (Δr² + Δg² + Δb²) × (1-Δa²) + Δa²
В любом случае, вероятно, это будет что-то вроде (Δr² + Δg² + Δb²) × f(Δa) + Δa²
Если бы я был вами, я попытался бы имитировать его различными парами RGBA и различными цветами фона, чтобы найти лучшую функцию f(Δa)
. Не очень математический, но даст вам достаточно близкий ответ.
Ответ 5
Я никогда этого не делал, но теория и практика говорят, что преобразование значений RGB в изображении и палитру в яркость-цветность будет помогут вам найти лучшие матчи. Я оставил бы альфа-канал в покое, поскольку прозрачность должна иметь мало общего с "лучшей" частью.
Этот xmass я сделал некоторые фотомозаики для подарков, используя программное обеспечение с открытым исходным кодом, которое соответствует фрагментам исходного изображения в коллекции изображений. Это кажется более сложной проблемой, чем проблема, которую вы пытаетесь решить. Одна из них была metapixel.
Наконец, лучшим вариантом является использование существующей библиотеки для преобразования изображения в формат, например PNG, в котором вы можете управлять палитрой.