Я ищу какую-то формулу или алгоритм для определения яркости цвета с учетом значений RGB. Я знаю, что это не может быть так просто, как добавление значений RGB вместе, и более высокие суммы будут ярче, но я как бы не понимаю, с чего начать.
Формула для определения яркости цвета RGB
Ответ 1
Вы имеете в виду яркость? Воспринимаемая яркость? Светимость?
- Яркость (стандартная для определенных цветовых пространств):
(0.2126*R + 0.7152*G + 0.0722*B)
[1] - Luminance (воспринимаемый вариант 1):
(0.299*R + 0.587*G + 0.114*B)
[2] - Luminance (воспринимаемый вариант 2, медленнее для вычисления):
sqrt( 0.241*R^2 + 0.691*G^2 + 0.068*B^2 )
sqrt( 0.299*R^2 + 0.587*G^2 + 0.114*B^2 )
(благодаря @MatthewHerbst) [3]
Ответ 2
Я думаю, что вы ищете формулу преобразования RGB → Luma.
Фотометрический/цифровой ITU BT.709:
Y = 0.2126 R + 0.7152 G + 0.0722 B
Digital ITU BT.601 (дает больший вес компонентам R и B):
Y = 0.299 R + 0.587 G + 0.114 B
Если вы хотите торговать точностью для исполнения, для этого есть две формулы приближения:
Y = 0.33 R + 0.5 G + 0.16 B
Y = 0.375 R + 0.5 G + 0.125 B
Это можно быстро вычислить, так как
Y = (R+R+B+G+G+G)/6
Y = (R+R+R+B+G+G+G+G)>>3
Ответ 3
Я сделал сравнение трех алгоритмов в принятом ответе. Я генерировал цвета в цикле, где использовался только каждый 400-й цвет. Каждый цвет представлен размером 2х2 пикселя, цвета сортируются от самых темных к самым светлым (слева направо, сверху вниз).
1-е изображение - Яркость (относительная)
0.2126 * R + 0.7152 * G + 0.0722 * B
2-е изображение - http://www.w3.org/TR/AERT#color-contrast
0.299 * R + 0.587 * G + 0.114 * B
3-е изображение - Цветовая модель HSP
sqrt(0.299 * R^2 + 0.587 * G^2 + 0.114 * B^2)
4-е изображение - WCAG 2.0 SC 1.4.3 относительнаяяркость и коэффициент контрастности (см. @Synchro ответ здесь)
На 1-м и 2-м снимках иногда можно увидеть рисунок в зависимости от количества цветов в одном ряду. Я никогда не замечал никаких паттернов на картинке из 3-го или 4-го алгоритма.
Если бы мне пришлось выбирать, я бы использовал алгоритм № 3, так как его гораздо проще реализовать и он примерно на 33% быстрее, чем 4-й.
Ответ 4
Ниже приведен единственный алгоритм CORRECT для преобразования изображений sRGB, используемых в браузерах и т.д., В оттенки серого.
Перед вычислением скалярного произведения необходимо применить инверсию гамма-функции для цветового пространства. Затем вы применяете гамма-функцию к уменьшенному значению. Невозможность включить гамма-функцию может привести к ошибкам до 20%.
Для типичных компьютерных материалов цветовое пространство sRGB. Правильные номера для sRGB - ок. 0,21, 0,72, 0,07. Гамма для sRGB является составной функцией, которая аппроксимирует возведение в степень на 1/(2.2). Вот в этом все дело в C++.
// sRGB luminance(Y) values
const double rY = 0.212655;
const double gY = 0.715158;
const double bY = 0.072187;
// Inverse of sRGB "gamma" function. (approx 2.2)
double inv_gam_sRGB(int ic) {
double c = ic/255.0;
if ( c <= 0.04045 )
return c/12.92;
else
return pow(((c+0.055)/(1.055)),2.4);
}
// sRGB "gamma" function (approx 2.2)
int gam_sRGB(double v) {
if(v<=0.0031308)
v *= 12.92;
else
v = 1.055*pow(v,1.0/2.4)-0.055;
return int(v*255+0.5); // This is correct in C++. Other languages may not
// require +0.5
}
// GRAY VALUE ("brightness")
int gray(int r, int g, int b) {
return gam_sRGB(
rY*inv_gam_sRGB(r) +
gY*inv_gam_sRGB(g) +
bY*inv_gam_sRGB(b)
);
}
Ответ 5
Я нашел этот код (написанный на С#), который отлично справляется с вычислением "яркости" цвета. В этом случае код пытается определить, следует ли помечать белый или черный текст над цветом.
Ответ 6
Интересно, что эта формулировка для RGB = > HSV использует только v = MAX3 (r, g, b). Другими словами, вы можете использовать максимум (r, g, b) как V в HSV.
Я проверил и на стр. 575 Hearn and Baker это значит, что они также вычисляют значение "Value".
Ответ 7
"Принятый" ответ является неправильным и неполным
Единственными точными ответами являются ответы @jive-dadson и @EddingtonsMonkey и поддержка @nils-pipenbrinck. Другие ответы (в том числе принятые) ссылаются или ссылаются на источники, которые являются либо неправильными, нерелевантными, устаревшими или сломанными.
Кратко:
- Перед применением коэффициентов sRGB необходимо ЛИНЕРИРОВАТЬ.
- Яркость (L или Y) линейна, как и свет.
- Воспринимаемая легкость (L *) нелинейна, как и восприятие человека.
- HSV и HSL даже отдаленно не точны с точки зрения восприятия.
- Стандарт МЭК для sRGB определяет порог 0,04045, это НЕ 0,03928 (это было из устаревшего раннего проекта).
- Полезные (то есть относительно восприятия) евклидовы расстояния требуют перцептуально однородного декартова векторного пространства, такого как CIELAB. sRGB не один.
Ниже приводится правильный и полный ответ:
Поскольку эта тема очень популярна в поисковых системах, я добавляю этот ответ, чтобы прояснить различные неправильные представления по этому вопросу.
Яркость - это атрибут восприятия, он не имеет прямого измерения.
Воспринимаемая легкость измеряется некоторыми моделями зрения, такими как CIELAB, здесь L * (Lstar) является мерой воспринимаемой легкости и нелинейна для аппроксимации кривой нелинейного отклика человеческого зрения.
Яркость - это линейная мера света, спектрально взвешенная для нормального зрения, но не отрегулированная для нелинейного восприятия яркости.
Luma (Y´ prime) - это гамма-кодированный, взвешенный сигнал, используемый в некоторых видео кодировках. Это не следует путать с линейной яркостью.
Гамма или кривая передачи (TRC) - это кривая, которая часто аналогична кривой восприятия и обычно применяется к данным изображения для хранения или передачи для уменьшения воспринимаемого шума и/или улучшения использования данных (и связанных с этим причин).
Чтобы определить воспринимаемую яркость, сначала преобразуйте гамма-кодированные значения изображения R´G´B´ в линейную яркость (L
или Y
), а затем в нелинейную воспринимаемая легкость (L*
)
НАЙТИ ЛЮМИНАНС:
... Потому что, видимо, он где-то был потерян...
Шаг первый:
Преобразовать все 8-битные целочисленные значения sRGB в десятичные 0.0-1.0
vR = sR / 255;
vG = sG / 255;
vB = sB / 255;
Шаг второй:
Преобразовать гамма-кодированный RGB в линейное значение. sRGB (компьютерный стандарт), например, требует кривой мощности приблизительно V ^ 2.2, хотя "точное" преобразование:
Где V´ - канал R, G или B гамма-кодирования sRGB.
Псевдокод:
function sRGBtoLin(colorChannel) {
// Send this function a decimal sRGB gamma encoded color value
// between 0.0 and 1.0, and it returns a linearized value.
if ( colorChannel <= 0.04045 ) {
return colorChannel / 12.92;
} else {
return pow((( colorChannel + 0.055)/1.055),2.4));
}
}
Шаг третий:
Чтобы найти яркость (Y), примените стандартные коэффициенты для sRGB:
Псевдокод с использованием вышеуказанных функций:
Y = (0.2126 * sRGBtoLin(vR) + 0.7152 * sRGBtoLin(vG) + 0.0722 * sRGBtoLin(vB))
НАЙТИ ПЕРСПЕКТИВНОЕ МОЛНИЕ:
Шаг четвертый:
Возьмите яркость Y сверху и преобразуйте в L *
function YtoLstar(Y) {
// Send this function a luminance value between 0.0 and 1.0,
// and it returns L* which is "perceptual lightness"
if ( Y <= (216/24389) { // The CIE standard states 0.008856 but 216/24389 is the intent for 0.008856451679036
return Y * (24389/27); // The CIE standard states 903.3, but 24389/27 is the intent, making 903.296296296296296
} else {
return pow(Y,(1/3)) * 116 - 16;
}
}
L * - это значение от 0 (черный) до 100 (белый), где 50 - перцептуальный "средний серый". L * = 50 является эквивалентом Y = 18,4 или, другими словами, 18% серая карта, представляющая середину фотографической экспозиции (зона V Анселя Адамса).
Ссылки:
IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
Чарльз Пойнтон Гамма FAQ
Ответ 8
Чтобы добавить то, что сказали все остальные:
Все эти уравнения работают на практике хорошо, но если вам нужно быть очень точным, вам нужно сначала преобразовать цвет в линейное цветовое пространство (применить прообразное изображение-гамма), сделать среднюю по весу основные цвета и - если вы хотите отобразить цвет - вернуть яркость обратно в гамму монитора.
Разница яркости между включением гамма и правильной гаммой составляет до 20% в темном серости.
Ответ 9
Вместо того, чтобы потеряться среди случайного выбора формул, упомянутых здесь, я предлагаю вам перейти к формуле, рекомендованной стандартами W3C.
Здесь представлена простая, но точная реализация PHP WCAG 2.0 SC 1.4.3 относительная яркость и коэффициент контрастности. Он создает значения, которые подходят для оценки коэффициентов, необходимых для соответствия WCAG, как на этой странице, и поэтому подходит и подходит для любого веб-приложения. Это тривиально для переноса на другие языки.
/**
* Calculate relative luminance in sRGB colour space for use in WCAG 2.0 compliance
* @link http://www.w3.org/TR/WCAG20/#relativeluminancedef
* @param string $col A 3 or 6-digit hex colour string
* @return float
* @author Marcus Bointon <[email protected]>
*/
function relativeluminance($col) {
//Remove any leading #
$col = trim($col, '#');
//Convert 3-digit to 6-digit
if (strlen($col) == 3) {
$col = $col[0] . $col[0] . $col[1] . $col[1] . $col[2] . $col[2];
}
//Convert hex to 0-1 scale
$components = array(
'r' => hexdec(substr($col, 0, 2)) / 255,
'g' => hexdec(substr($col, 2, 2)) / 255,
'b' => hexdec(substr($col, 4, 2)) / 255
);
//Correct for sRGB
foreach($components as $c => $v) {
if ($v <= 0.03928) {
$components[$c] = $v / 12.92;
} else {
$components[$c] = pow((($v + 0.055) / 1.055), 2.4);
}
}
//Calculate relative luminance using ITU-R BT. 709 coefficients
return ($components['r'] * 0.2126) + ($components['g'] * 0.7152) + ($components['b'] * 0.0722);
}
/**
* Calculate contrast ratio acording to WCAG 2.0 formula
* Will return a value between 1 (no contrast) and 21 (max contrast)
* @link http://www.w3.org/TR/WCAG20/#contrast-ratiodef
* @param string $c1 A 3 or 6-digit hex colour string
* @param string $c2 A 3 or 6-digit hex colour string
* @return float
* @author Marcus Bointon <[email protected]>
*/
function contrastratio($c1, $c2) {
$y1 = relativeluminance($c1);
$y2 = relativeluminance($c2);
//Arrange so $y1 is lightest
if ($y1 < $y2) {
$y3 = $y1;
$y1 = $y2;
$y2 = $y3;
}
return ($y1 + 0.05) / ($y2 + 0.05);
}
Ответ 10
Цветовое пространство HSV должно сделать трюк, см. статья wikipedia в зависимости от языка, на котором вы работаете вы можете получить преобразование в библиотеку.
H - это оттенок, который является числовым значением для цвета (то есть красного, зеленого...)
S - насыщенность цвета, т.е. как "интенсивный" он
V - это "яркость" цвета.
Ответ 11
RGB Значение яркости = 0,3 R + 0,59 G + 0,11 B
http://www.scantips.com/lumin.html
Если вы ищете, как близко к белому цвет, вы можете использовать Euclidean Distance от (255, 255, 255)
Я думаю, что цветовое пространство RGB воспринимается неравномерно по отношению к эвклидовому расстоянию L2. Равномерные пространства включают CIE LAB и LUV.
Ответ 12
Формула обратного гамма Jive Dadson должна иметь половину регулировки при реализации в Javascript, т.е. возврат из функции gam_sRGB должен быть возвращен int (v * 255); не возвращать int (v * 255 +.5); Half-adjust rounds up, и это может вызвать слишком высокое значение на R = G = B, т.е. Серой цветовой триаде. Преобразование оттенков серого в триаде R = G = B должно давать значение, равное R; это одно доказательство правильности формулы. См. Девять оттенков оттенков серого для формулы в действии (без половины регулировки).
Ответ 13
Здесь немного кода С, который должен правильно рассчитать воспринимаемую яркость.
// reverses the rgb gamma
#define inverseGamma(t) (((t) <= 0.0404482362771076) ? ((t)/12.92) : pow(((t) + 0.055)/1.055, 2.4))
//CIE L*a*b* f function (used to convert XYZ to L*a*b*) http://en.wikipedia.org/wiki/Lab_color_space
#define LABF(t) ((t >= 8.85645167903563082e-3) ? powf(t,0.333333333333333) : (841.0/108.0)*(t) + (4.0/29.0))
float
rgbToCIEL(PIXEL p)
{
float y;
float r=p.r/255.0;
float g=p.g/255.0;
float b=p.b/255.0;
r=inverseGamma(r);
g=inverseGamma(g);
b=inverseGamma(b);
//Observer = 2°, Illuminant = D65
y = 0.2125862307855955516*r + 0.7151703037034108499*g + 0.07220049864333622685*b;
// At this point we've done RGBtoXYZ now do XYZ to Lab
// y /= WHITEPOINT_Y; The white point for y in D65 is 1.0
y = LABF(y);
/* This is the "normal conversion which produces values scaled to 100
Lab.L = 116.0*y - 16.0;
*/
return(1.16*y - 0.16); // return values for 0.0 >=L <=1.0
}
Ответ 14
Интересно, как были определены эти коэффициенты rgb. Я сам сделал эксперимент, и я закончил со следующим:
Y = 0.267 R + 0.642 G + 0.091 B
Закрыть, но, очевидно, отличается от давно установленных коэффициентов МСЭ. Интересно, могут ли эти коэффициенты быть разными для каждого наблюдателя, потому что у всех нас может быть разное количество конусов и стержней на сетчатке в наших глазах, и особенно соотношение между различными типами конусов может отличаться.
Для справки:
ITU BT.709:
Y = 0.2126 R + 0.7152 G + 0.0722 B
ITU BT.601:
Y = 0.299 R + 0.587 G + 0.114 B
Я сделал тест, быстро перемещая небольшую серо-полоску на ярко-красном, ярко-зеленом и ярко-синем фоне и настраивая серое до тех пор, пока оно не будет смешано как можно больше. Я также повторил этот тест с другими оттенками. Я повторил тест на разных дисплеях, даже один с фиксированным гамма-коэффициентом 3,0, но все это выглядит одинаково для меня. Более того, коэффициенты МСЭ буквально ошибочны для моих глаз.
И да, я, по-видимому, имею нормальное цветное зрение.
Ответ 15
Определите яркость. Если вы ищете, как близко к белому цвет, вы можете использовать Euclidean Distance от (255, 255, 255)
Ответ 16
"V" HSV - это, вероятно, то, что вы ищете. MATLAB имеет функцию rgb2hsv, а ранее цитированная статья wikipedia полна псевдокода. Если преобразование RGB2HSV невозможно, менее точной моделью будет версия изображения в оттенках серого.
Ответ 17
Эта ссылка объясняет все в глубину, в том числе, почему эти константы множителя существуют до значений R, G и B.
Редактировать: здесь есть объяснение одному из ответов (0.299 * R + 0.587 * G + 0.114 * B)
Ответ 18
Для ясности формулы, которые используют квадратный корень, должны быть
sqrt(coefficient * (colour_value^2))
не
sqrt((coefficient * colour_value))^2
Доказательство этого заключается в преобразовании триады R = G = B в оттенки серого R. Это будет справедливо только в том случае, если вы выберете значение цвета, а не коэффициент времени цветового значения. См. Девять оттенков оттенков серого
Ответ 19
Чтобы определить яркость цвета с помощью R, я преобразую цвет системы RGB в цвет системы HSV.
В моем script я использую системный код HEX раньше по другой причине, но вы также можете запустить с системным кодом RGB с помощью rgb2hsv {grDevices}
. Документация здесь.
Вот эта часть моего кода:
sample <- c("#010101", "#303030", "#A6A4A4", "#020202", "#010100")
hsvc <-rgb2hsv(col2rgb(sample)) # convert HEX to HSV
value <- as.data.frame(hsvc) # create data.frame
value <- value[3,] # extract the information of brightness
order(value) # ordrer the color by brightness
Ответ 20
Когда вы помещаете образ экрана входа в Windows 10 Creators edition с помощью gpo ( "принудительно настройте экран блокировки по умолчанию и изображение входа в систему" ), кажется, что изображение становится темнее, разделив все 3 числа rgb примерно на 1,8 (I пытался сделать его серым):
128 128 128 становится 71 71 71
232 232 232 становится 128 128 128