Сходство цвета/расстояние в цветовом пространстве RGBA

StackOverflow https://stackoverflow.com/questions/4754506

Вопрос

Как вычислить сходство между двумя цветами в цветовом пространстве 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, вице-президент являются лучшим.

Это было полезно?

Решение

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

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

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

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

    1. Смешайте канал в обоих цветах с канал= 0 в качестве фона, измерьте разницу в квадрате
    2. Смешайте канал в обоих цветах с канал= максимум как фон, измерьте разницу в квадрате
    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.

Другие советы

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

  1. Когда два цвета имеют одинаковую альфа, rgbadistance = rgbdistance * (альфа / 255). Совместим с алгоритмом цветового расстояния RGB, когда оба альфа - 255.
  2. Все цвета с очень низкой альфой похожи.
  3. RGBADINANCE между двумя цветами с одинаковым RGB линейно зависит от Delta Alpha.
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);
}

Моя идея - это интегрирование по всему возможным цветам фона и усреднение квадратной ошибки.

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

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

Прежде всего, очень интересная проблема :)
У меня нет полного решения (по крайней мере, пока), но есть 2 очевидных крайних случая, которые мы должны рассмотреть:
Когда Δa==0 Проблема относится к пространству RGB
Когда Δa==1 Проблема заключается только в пространстве альфа-1-DIM
Таким образом, формула (которая очень похожа на той, которую вы заявили), которая удовлетворила бы это:
(Δr² + Δg² + Δb²) × (1-(1-Δa)²) + Δa² или же (Δr² + Δg² + Δb²) × (1-Δa²) + Δa²

В любом случае, это, вероятно, будет что -то вроде (Δr² + Δg² + Δb²) × f(Δa) + Δa²

Если бы я был вами, я бы попытался имитировать его с помощью различных пар RGBA и различных цветов фона, чтобы найти лучшее f(Δa) функция Не очень математический, но даст вам достаточно близкий ответ

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top