Каков наилучший способ усреднения двух цветов, определяющих линейный градиент?

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

  •  19-08-2019
  •  | 
  •  

Вопрос

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

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

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

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

visual comparison of color averaging techniques

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

Решение

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

Как правило, вы хотите преобразовать цвета в нечто, называемое лабораторное пространство , и найти их средний в этом пространстве.

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

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

В нескольких ответах предлагается преобразовать в цветовое пространство 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

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

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

alt text

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

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

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

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

Преобразование цветового пространства начинается с удаления любого черного смещения, так что черный становится нулевым. Если гамма-функция имеет точку останова (как это делают sRGB и Rec.709), вам нужно будет тщательно масштабировать значения RGB, чтобы & Quot; white & Quot; это 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 в выбранном вами цветовом пространстве.

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

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

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

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

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

На самом деле есть гораздо более простой способ.

  • Уменьшите изображение до размера 1 на 1 пиксель.

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

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