Страницы

Поиск по вопросам

воскресенье, 9 февраля 2020 г.

Определить математически <<средний цвет>> из 2х

#c_sharp #цвета


Имеем 2 цвета, заданы в RGB, по 1 байту на цвет.

Если брать и складывать каждый из цветов, затем делить на 2, то получается на мой
взгляд не совсем верно. Допустим FF0000 и 00FF00 таким образом родят 7F7F00, который
смотрится намного темнее, чем оба его "родителя". Если таким образом считать средний
между FF0000 и FFFF00, то будет FF7F00, который на взгляд явно ближе к FF0000, чем
к FFFF00. На взгляд средний между ними примерно FFAA00.

В каждом пикселе монитора мы имеем 3 субпикселя, питание подаваемое на которые изменяется
от 0 до 255 (некоторых баллов) при данной глубине цвета, если я всё верно понимаю.
Хочу узнать, как можно математически просчитать цвет, который был бы "средним" между
двумя заданными, а именно был бы похож на каждый из них в равной мере, при этом имея
среднюю между ними яркость.
Возможно, есть стандартные библиотеки в средах разработки, которые делают что-то
подобное?



div {
  width: 6em;
  height: 6em;
  display: inline-block;
  font-family: monospace;
  text-indent: -12ch;
  overflow: hidden;
}

div:after {
  content: attr(style);
}



Ответы

Ответ 1



В RGB нельзя высчитать "средний" цвет. Во первых, яркость разных цветов воспринимается глазом по разному - т.е. яркость не "определяется наибольшим значением любого из 3 цветов". В RGB (sRGB) зеленый ярче красного, красный ярче синего. FF0000 по яркости совпадает с 009B00 (справа), а не с вырвиглазным 00FF00 (слева): Во вторых, отсчет яркости не привязан строго к 0, и простое "уполовинивание" значения дает слишком темные цвета. Например, "полуяркий красный" - это, скорее, A60000, а не 7F0000, как можно было бы ожидать. Для правильного смешивания цветов их стоит предварительно перевести в цветовое пространство, отражающее человеческое восприятие, например, Lab color space, и высчитывать среднее уже в этом пространстве. Вот сравнительные результаты для чистых R G и B (сверху - с преобразованием в Lab и усреднением, снизу - с усреднением в RBG). Видно, что усреднение по RGB дает слишком темный результат, а усреднение через Lab - средний по яркости. В C# реализуется достаточно легко, готовые форумы есть по ссылкам на вики выше. Если не хочется вручную вписывать преобразование - возьмите готовую библиотеку: PM> Install-Package ColorMine var color1 = new Rgb() { R = 255 }; var color1Lab = color1.To(); var color2 = new Rgb() { G = 255 }; var color2Lab = color2.To(); var averageLab = new Lab() { L = (color1Lab.L + color2Lab.L) / 2, A = (color1Lab.A + color2Lab.A) / 2, B = (color1Lab.B + color2Lab.B) / 2, }; var averageLabRgb = averageLab.ToRgb();

Ответ 2



Есть две модели смешивания: адитивное и субтрактивное смешение цветов. Можно почитать тут https://creativshik.com/pochemu-vret-monitor/ Адитивное будет так (оно "работает" при световом смешивании лучей, в некоторых графических программах): r = (r1 + r2 ) / 2; g = (b1 + b2 ) / 2; b = (b1 + b2 ) / 2; Cубтрактивное r = // TODO: g = b = Второе "смешивание" цветов похоже на привычное смешивание "акварельных красок" на белом листе. Ещё такое смешивание можно включить в Corel Draw. Адитивное - "приближает" цвета к чёрному. А субтрактивное - к белому. Если стоит задача определить "ближайший" цвет, то используется сумма rgb c коефициентами Q = r * Kr + g* Kg + b*Kb; Где Q- будет "вес" по которому можно определить схожесть. этой формулой переводят изображение в чёрнобелое. Для разных преобразований используют разные коефициенты. Стандартные для ч/б где-то видел - найду запишу. Коефициенты нашёл, вот Y=0.299*R+0.587*G+0.114*B (В.Порев "Компьютерная графика", BHV, 2002г. - страница 41.) Y= 0.2125R + 0.7154G + 0,0721В (Фотошоп ссылка ) При попытке вставить коефициенты - они в формуле сокращаются, т.е. для Y(R=255,G=0,B=0)=76,5 , Y(R=0;G=255;B=0)=150,45. Средний цвет будет (128,128,0), но и средняя яркость будет тоже средней - 113,48. Если вы хотите "поднять" яркость до max(Y(цвет1),Y(цвет2)) то вы можете пересчитать цвет, учитывая формулу приведённую выше. Если у вас задача "не потерять яркость", тогда ставим задачу - сохранить максимальную яркость. Y(Red=255) = 76,5 Y(Green=255) = 150,45, Y=(Red+Green) = 113,48; t = Ymax / Y = 150,45/113,48 = 1,325 Тогда (адитивное смешение): r` = (r1 + r2)*t/2 = (255 + 0)*1,325/2 = 170 g` = (g1 + g2)*t/2 = (0 + 255)*1,325/2 = 170 b` = (b1 + b2)*t/2 = (0 + 0)*1,325 / 2 = 0 Y(R=170,G=170,B=0) = 150,45 Для субтрактивного смешения можно написать аналогичную формулу. Можно так же в цикле прибавлять еденицу - выйдет похожее значение (R=169,G=127,B=42). Внизу пример, сначала R (255,0,0), потом результат "затемнённый" R+G (128,128,0), Потом скорректированый по яркости (170,170,0), потом сделаный инкрементом (169,127,42). Потом зеленый (0,255,0) И последнее, ставьте проверки что б компонента не выходила за пределы [0,255], если меньше 0 то присваивать 0, если более 255 то ставить 255.

Комментариев нет:

Отправить комментарий