Цветовое сходство / расстояние в цветовом пространстве RGBA - PullRequest
29 голосов
/ 21 января 2011

Как вычислить сходство между двумя цветами в цветовом пространстве RGBA? (где цвет фона, конечно, неизвестен)

Мне нужно переназначить изображение RGBA в палитру цветов RGBA, найдя запись палитры best для каждого пикселя в изображении *.

В цветовом пространстве 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

и я попробовал эту формулу ( edit: См. Ответ ниже для лучшей формулы ):

Δr² + Δg² + Δb² + 3 × Δa²

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

Какая оптимальная формула?


*) для простоты этого вопроса я игнорирую диффузию ошибок, гамму и психовизуальные цветовые пространства.


Немного связано: если вы хотите найти ближайший цвет в этом неевклидовом пространстве RGBA, лучше всего vp-деревья .

Ответы [ 5 ]

12 голосов
/ 10 января 2012

Наконец-то я нашел это!После тщательного тестирования и экспериментов мои выводы таковы:

  • Правильный способ - вычислить максимум возможную разницу между двумя цветами.
    Формулы с любым видом оценкисредняя / типичная разница имела место для несплошностей.

  • Мне не удалось найти рабочую формулу, которая рассчитывает расстояние без смешивания цветов RGBA с некоторыми фонами.

  • Нет необходимости учитывать все возможные цвета фона.Это может быть упрощено до смешивания максимума и минимума отдельно для каждого из каналов R / G / B:

    1. смешайте канал в обоих цветах с channel = 0 в качестве фона,измерить разницу в квадрате
    2. смешать канал в обоих цветах с channel = max в качестве фона, измерить разницу в квадрате
    3. взять выше из двух.

К счастью, смешивание с «белым» и «черным» тривиально, когда вы используете предварительно умноженную альфа (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 голосов
/ 01 декабря 2017

Несколько принципов:

  1. Если два цвета имеют одинаковую альфа, rgbaDistance = rgbDistance * (alpha / 255). Совместим с алгоритмом цветового расстояния RGB, когда оба альфа 255.
  2. Все цвета с очень низким альфа похожи.
  3. rgbaDistance между двумя цветами с одинаковым 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);
}
1 голос
/ 21 января 2011

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

т.е. рассчитать для каждого компонента (используя красный канал в качестве примера здесь)

Интеграл от 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.

1 голос
/ 21 января 2011

Прежде всего, очень интересная проблема:)
У меня нет полного решения (по крайней мере, пока), но есть 2 очевидных крайних случая, которые мы должны рассмотреть:
Когда Δ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) функцию.Не очень математично, но даст достаточно точный ответ

0 голосов
/ 21 января 2011

Я никогда не делал этого, но теория и практика говорят, что преобразование значений RGB на изображении и палитре в яркость-цветность поможет вам найти наилучшие совпадения.Я бы оставил альфа-канал в покое, так как прозрачность не должна иметь ничего общего с «выглядящей лучше» частью.

В этот рождественский вечер я сделал несколько фотографий для подарков, используя программное обеспечение с открытым исходным кодом, которое соответствует фрагментамИсходное изображение в коллекцию изображений.Это кажется более сложной проблемой, чем та, которую вы пытаетесь решить.Одной из таких программ была metapixel .

Наконец, наилучшим вариантом должно быть использование существующей библиотеки для преобразования изображения в формат, такой как PNG, в котором вы можете управлять палитрой.

...