Каков наилучший способ усреднить два цвета, которые определяют линейный градиент? - PullRequest
40 голосов
/ 16 марта 2009

Если у меня есть два цвета, определенные их значениями RGB, могу ли я усреднить значения красного, зеленого и синего, а затем объединить, чтобы определить третий цвет, который выглядит как визуальное среднее двух?

т.е. NewColor = (R1 + R2) / 2, (G1 + G2) / 2, (B1 + B2) / 2

РЕДАКТИРОВАТЬ1: Спасибо за все ответы. Для моих текущих потребностей я имею дело только с парами цветов, которые имеют оттенки одного цвета, поэтому я думаю, что их усреднение будет работать. Однако я постараюсь перейти на Lab Space, чтобы убедиться, что это предположение верно и метод будет полезен в будущем.

РЕДАКТИРОВАТЬ2: Вот мои результаты FWIW. Color1 и Color2 - мои два цвета, а два средних столбца - результаты усреднения в пространстве L a b и усреднения RGB соответственно. В этом случае нет большой разницы между этими двумя цветами, и поэтому разница в выходных данных от методов усреднения незначительна.

visual comparison of color averaging techniques

Ответы [ 8 ]

24 голосов
/ 11 апреля 2015

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

Но если вам просто нужен быстрый способ получить среднее из двух цветов, это можно сделать в пространстве RGB. Вы просто должны иметь в виду предостережение: вы должны возвести в квадрат значения RGB перед их усреднением, а затем взять корень результата. (Если вы просто возьмете среднее значение, результат будет слишком темным.)

Как это:

NewColor = sqrt((R1^2+R2^2)/2),sqrt((G1^2+G2^2)/2),sqrt((B1^2+B2^2)/2)

Вот отличный видеоролик, который объясняет, почему этот метод эффективен: https://www.youtube.com/watch?v=LKnqECcg6Gw

22 голосов
/ 16 марта 2009

Посмотрите на ответы на этот вопрос .

По сути, вы хотите преобразовать цвета в нечто, называемое Лабораторное пространство , и найти их среднее значение в этом пространстве.

Лабораторное пространство - это способ представления цветов, когда точки, близкие друг к другу, - это точки, похожие на человеческие.

6 голосов
/ 16 марта 2009

Усреднение по Цветовое пространство HSL может дать лучшие результаты.

6 голосов
/ 16 марта 2009

Я не знаю, является ли взятие простого среднего из компонентов «лучшим» с точки зрения восприятия (это звучит как вопрос для психолога), но вот пара примеров, использующих простое усреднение компонентов.

alt text

Красный-горчично-зеленый уродлив, но интерполяция кажется достаточно разумной.

4 голосов
/ 16 марта 2009

Да. Вы можете усреднить два цвета вместе, как это. Это подход, используемый OpenGL для смешивания цветов (например, при создании MIP-карт для рендеринга удаленных объектов или рендеринга 50% прозрачной текстуры). Это быстро, просто и «достаточно хорошо» для многих ситуаций. Однако это не совсем реалистично и, вероятно, не будет использоваться для изображений фотографического качества.

3 голосов
/ 28 июня 2017

Это сложно. Во-первых, набор значений RGB не определяет цвет. Их необходимо интерпретировать в свете основных цветов, к которым они относятся (цветовое пространство), таких как sRGB, Rec.709, Rec.2020, Adobe RGB (1998) и т. Д.

Кроме того, значения RGB в том виде, в котором мы их обычно встречаем, не пропорциональны линейному свету: они «кодируются» с использованием нелинейной функции (гамма). И иногда (в основном в видеоприложениях) значение «черный» не равно нулю, а смещено от нуля, обычно 16 для 8-битных значений. И «белый» - это не 255, а 235. sRGB и Rec.709 разделяют основные цвета RGB, но их гамма-функции различны.

Преобразование цветового пространства начинается с удаления любого черного смещения, так что черный равен нулю. Если у гамма-функции есть точка останова (как у sRGB и Rec.709), вам нужно будет осторожно масштабировать значения RGB, чтобы «белый» составлял 1,0.

Затем "расшифруйте" гамму, выполнив инверсию исходной гамма-функции. (В одном ответе предлагалось возвести в квадрат значения, что является приближением гамма-декодирования.) Теперь у вас есть линейные значения RGB в некотором цветовом пространстве. На данный момент вы можете конвертировать из этого цветового пространства в пространство Lab. Большинство преобразований из RGB в Lab проходит через промежуточное цветовое пространство, называемое XYZ.

Шаги как вызовы вложенных функций:

Lab = XYZ2Lab (RGB2XYZ (gamma_decode (offset_and_scale (RGB), gammaFunction ), Цветовое пространство RGB ))

(Лабораторное пространство было разработано в 1976 году как попытка создать перцептуально-равномерную деформацию стандартного пространства CIE XYZ. (Luv была еще одной попыткой.) Идея заключается в том, что евклидово (прямолинейное) расстояние между двумя цветами только что заметно отличающиеся (1 "JND") будет одинаковым расстоянием для любых двух цветов. Расстояние между двумя цветами в Lab известно как "delta-E". Простая формула дельта-евклидова расстояния теперь называется dE76. https://en.wikipedia.org/wiki/Color_difference)

В вашем случае вы могли бы усреднить два цвета Lab, чтобы получить новый цвет Lab, а затем обратить все преобразования, чтобы вернуться к RGB в выбранном вами цветовом пространстве.

Это сблизит вас, но не гарантирует, просто потому, что «цвет» - это восприятие человека, а не физическая величина, и его, как известно, трудно надежно охарактеризовать. Лаборатория на самом деле не работала так хорошо, чтобы быть одинаково воспринимаемой. Поэтому вместо исправления Lab они предложили новую, более сложную функцию delta-E с еще одной встроенной функцией деформации: DE94. Это было лучше, но не идеально, поэтому в 2000 году появилось еще одно предложение: DE2000. Также лучше, но не идеально. Смотрите эту страницу вики выше для получения дополнительной информации.

Если DE2000 недостаточно хорош (или слишком сложен!), Вы можете взглянуть на альтернативу Lab под названием ICtCp , которая, как утверждается, более однородна в восприятии, чем Lab.

1 голос
/ 07 сентября 2017

Я думаю, что ответ от arntjw идет в правильном направлении и распознает логарифмическую подстилку, как упомянуто Дэном У. Однако правильное среднее геометрическое значение не равно sqrt ((C1 ^ 2 + C2 ^ 2) / 2) , но sqrt (C1 * C2). Таким образом, средний цвет будет:

NewColor = sqrt(R1*R2),sqrt(G1*G2),sqrt(B1*B2)

Полученные цвета ближе к тому, что мы ожидаем. Вы можете обобщить на большее количество цветов, используя корни более высокого порядка, и взвесить каждый цвет, добавив экспоненту к его компонентам.

0 голосов
/ 14 марта 2013

Там на самом деле гораздо более простой способ.

  • Уменьшите изображение до 1px на 1px.

    Цвет 1px - это средний цвет того, что вы масштабировали

...