RGB 값이 주어진 색상의 밝기를 결정하는 일종의 수식이나 알고리즘을 찾고 있습니다. RGB 값을 합산하고 더 높은 합계를 갖는 것만 큼 간단하지는 않지만 어디서부터 시작 해야할지에 대한 손실이 있습니다.
RGB 값이 주어진 색상의 밝기를 결정하는 일종의 수식이나 알고리즘을 찾고 있습니다. RGB 값을 합산하고 더 높은 합계를 갖는 것만 큼 간단하지는 않지만 어디서부터 시작 해야할지에 대한 손실이 있습니다.
답변:
밝기를 의미합니까? 지각 된 밝기? 휘도?
(0.2126*R + 0.7152*G + 0.0722*B)
[1](0.299*R + 0.587*G + 0.114*B)
[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]0.299*(R^2)
(지수는 곱하기 전에 오기 때문에)
나는 당신이 찾고있는 것이 RGB-> Luma 변환 공식 이라고 생각합니다 .
광도 / 디지털 ITU BT.709 :
Y = 0.2126 R + 0.7152 G + 0.0722 B
디지털 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
Blue
+ 3 * Green) / 6이고, 두 번째는 (3 * Red + Blue
+ 4 * Green) >> 3입니다. 두 가지 근사치 모두에서 Blue의 가중치는 가장 낮지 만 여전히 남아 있습니다.
Y = (R<<1+R+G<<2+B)>>3
(ARM에서 3-4 CPU 사이클 만). 좋은 컴파일러가 그 최적화를 수행 할 것입니다.
허용 된 답변에서 세 가지 알고리즘을 비교했습니다. 약 400 번째 색상 만 사용하는 주기로 색상을 생성했습니다. 각 색상은 2x2 픽셀로 표시되며 가장 어두운 색상부터 가장 밝은 색상 (왼쪽에서 오른쪽, 위에서 아래로)으로 정렬됩니다.
첫 번째 그림- 휘도 (상대)
0.2126 * R + 0.7152 * G + 0.0722 * B
두 번째 사진-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)
네 번째 사진 -WCAG 2.0 SC 1.4.3 상대 휘도 및 명암비 공식 ( @Synchro의 답변은 여기 참조 )
한 행의 색상 수에 따라 첫 번째 및 두 번째 사진에서 패턴이 때때로 표시 될 수 있습니다. 3 번째 또는 4 번째 알고리즘에서 어떤 패턴도 발견하지 못했습니다.
내가 선택해야한다면 구현하기가 훨씬 쉽고 알고리즘보다 약 33 % 더 빠르기 때문에 알고리즘 번호 3을 사용합니다.
^2
및 sqrt
제 식에 포함되는 대신에 RGB의 비 - 선형 RGB에서 선형 근사 빠른 방법 ^2.2
및 ^(1/2.2)
그 더 정확할 것이다. 선형 입력 대신 비선형 입력을 사용하는 것은 불행히도 매우 일반적입니다.
아래는 브라우저 등에서 사용되는 sRGB 이미지를 그레이 스케일로 변환하는 유일한 CORRECT 알고리즘입니다.
내부 제품을 계산하기 전에 색상 공간에 대해 감마 함수의 역을 적용해야합니다. 그런 다음 감마 기능을 감소 된 값에 적용합니다. 감마 기능을 통합하지 않으면 최대 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)
);
}
정확한 답변은 @ jive-dadson 및 @EddingtonsMonkey 답변이며 @ nils-pipenbrinck 지원 합니다. 다른 답변 (허용됨 포함) 은 잘못되었거나 관련이 없거나 쓸모 없거나 고장난 출처를 연결하거나 인용합니다.
이 스레드는 검색 엔진에 많이 나타나기 때문에 주제에 대한 다양한 오해를 명확히하기 위해이 답변을 추가하고 있습니다.
밝기 는 지각적인 속성이며 직접 측정 할 수 없습니다.
인식 된 밝기 는 CIELAB과 같은 일부 비전 모델에 의해 측정되며, 여기서 L * (Lstar)는 지각 밝기 의 측정치이며 인간의 비전 비선형 반응 곡선에 근접하기 위해 비선형입니다.
휘도 는 빛의 선형 측정으로, 보통 시력에 대해서는 스펙트럼 가중치를 적용하지만 밝기에 대한 비선형 인식에는 조정되지 않습니다.
루마 ( Y ' 프라임)는 일부 비디오 인코딩에 사용되는 감마 인코딩 된 가중치 신호입니다. 선형 휘도와 혼동되어서는 안됩니다.
감마 또는 전송 곡선 (TRC)은 종종 지각 곡선과 유사한 곡선이며, 일반적으로 저장 또는 방송을위한 이미지 데이터에 적용되어인지 된 잡음을 감소시키고 / 시키거나 데이터 이용률 (및 관련 이유)을 개선합니다.
인식 된 밝기를 결정하려면 먼저 감마 인코딩 된 R´G´B '이미지 값을 선형 휘도 ( L
또는 Y
) 로 변환 한 다음 비선형 감지 밝기 ( L*
)로 변환하십시오.
... 어딘가에서 길을 잃었 기 때문에 ...
모든 sRGB 8 비트 정수 값을 10 진수 0.0-1.0으로 변환
vR = sR / 255;
vG = sG / 255;
vB = sB / 255;
감마 인코딩 RGB를 선형 값으로 변환합니다. 예를 들어 sRGB (컴퓨터 표준)에는 "정확한"변환이 다음과 같이 약 V ^ 2.2의 전력 곡선이 필요합니다.
여기서 V´는 sRGB의 감마 인코딩 된 R, G 또는 B 채널입니다.
의사 코드 :
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 % 그레이 카드와 같습니다 (Ansel Adams zone V).
IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
Charles Poynton의 감마 FAQ
L*a*b*
많은 심리 물리학 적 속성을 고려하지 않습니다. Helmholtz-Kohlrausch 효과는 하나이지만 다른 것들도 많습니다. CIELAB은 "전체"이미지 평가 모델이 아닙니다. 저는 포스트에서 기본 개념을 가능한 한 완벽하게 다루려고 노력했습니다. 헌트 (Hunt) 모델, 페어차일드 (Fairchild) 모델 등은보다 완전한 작업을 수행하지만 실질적으로 더 복잡합니다.
색상의 "밝기"를 계산하는 훌륭한 작업을 수행하는 이 코드 (C #으로 작성)를 찾았습니다 . 이 시나리오에서 코드는 흰색 또는 검은 색 텍스트를 색상 위에 넣을지 여부를 결정하려고합니다.
흥미롭게도 RGB => HSV에 대한이 공식 은 v = MAX3 (r, g, b) 만 사용합니다. 즉, 최대 (r, g, b)를 HSV의 V로 사용할 수 있습니다 .
나는 Hearn & Baker의 575 페이지에서 이것이 "가치"를 계산하는 방법입니다.
여기에 언급 된 임의의 수식 중에서 길을 잃지 않고 W3C 표준에서 권장하는 수식을 사용하는 것이 좋습니다.
다음은 WCAG 2.0 SC 1.4.3 상대 휘도 및 명암비 공식 의 간단하지만 정확한 PHP 구현입니다 . 이 페이지 와 같이 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 <marcus@synchromedia.co.uk>
*/
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.04045) {
$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 <marcus@synchromedia.co.uk>
*/
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);
}
오늘 자바 스크립트에서 비슷한 작업을 해결하고있었습니다. getPerceivedLightness(rgb)
HEX RGB 색상 에 대해이 기능을 설정했습니다. 휘도 보정을 위해 Fairchild 및 Perrotta 공식을 통해 Helmholtz-Kohlrausch 효과를 처리합니다.
/**
* Converts RGB color to CIE 1931 XYZ color space.
* https://www.image-engineering.de/library/technotes/958-how-to-convert-between-srgb-and-ciexyz
* @param {string} hex
* @return {number[]}
*/
export function rgbToXyz(hex) {
const [r, g, b] = hexToRgb(hex).map(_ => _ / 255).map(sRGBtoLinearRGB)
const X = 0.4124 * r + 0.3576 * g + 0.1805 * b
const Y = 0.2126 * r + 0.7152 * g + 0.0722 * b
const Z = 0.0193 * r + 0.1192 * g + 0.9505 * b
// For some reason, X, Y and Z are multiplied by 100.
return [X, Y, Z].map(_ => _ * 100)
}
/**
* Undoes gamma-correction from an RGB-encoded color.
* https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation
* /programming/596216/formula-to-determine-brightness-of-rgb-color
* @param {number}
* @return {number}
*/
function sRGBtoLinearRGB(color) {
// Send this function a decimal sRGB gamma encoded color value
// between 0.0 and 1.0, and it returns a linearized value.
if (color <= 0.04045) {
return color / 12.92
} else {
return Math.pow((color + 0.055) / 1.055, 2.4)
}
}
/**
* Converts hex color to RGB.
* /programming/5623838/rgb-to-hex-and-hex-to-rgb
* @param {string} hex
* @return {number[]} [rgb]
*/
function hexToRgb(hex) {
const match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
if (match) {
match.shift()
return match.map(_ => parseInt(_, 16))
}
}
/**
* Converts CIE 1931 XYZ colors to CIE L*a*b*.
* The conversion formula comes from <http://www.easyrgb.com/en/math.php>.
* https://github.com/cangoektas/xyz-to-lab/blob/master/src/index.js
* @param {number[]} color The CIE 1931 XYZ color to convert which refers to
* the D65/2° standard illuminant.
* @returns {number[]} The color in the CIE L*a*b* color space.
*/
// X, Y, Z of a "D65" light source.
// "D65" is a standard 6500K Daylight light source.
// https://en.wikipedia.org/wiki/Illuminant_D65
const D65 = [95.047, 100, 108.883]
export function xyzToLab([x, y, z]) {
[x, y, z] = [x, y, z].map((v, i) => {
v = v / D65[i]
return v > 0.008856 ? Math.pow(v, 1 / 3) : v * 7.787 + 16 / 116
})
const l = 116 * y - 16
const a = 500 * (x - y)
const b = 200 * (y - z)
return [l, a, b]
}
/**
* Converts Lab color space to Luminance-Chroma-Hue color space.
* http://www.brucelindbloom.com/index.html?Eqn_Lab_to_LCH.html
* @param {number[]}
* @return {number[]}
*/
export function labToLch([l, a, b]) {
const c = Math.sqrt(a * a + b * b)
const h = abToHue(a, b)
return [l, c, h]
}
/**
* Converts a and b of Lab color space to Hue of LCH color space.
* /programming/53733379/conversion-of-cielab-to-cielchab-not-yielding-correct-result
* @param {number} a
* @param {number} b
* @return {number}
*/
function abToHue(a, b) {
if (a >= 0 && b === 0) {
return 0
}
if (a < 0 && b === 0) {
return 180
}
if (a === 0 && b > 0) {
return 90
}
if (a === 0 && b < 0) {
return 270
}
let xBias
if (a > 0 && b > 0) {
xBias = 0
} else if (a < 0) {
xBias = 180
} else if (a > 0 && b < 0) {
xBias = 360
}
return radiansToDegrees(Math.atan(b / a)) + xBias
}
function radiansToDegrees(radians) {
return radians * (180 / Math.PI)
}
function degreesToRadians(degrees) {
return degrees * Math.PI / 180
}
/**
* Saturated colors appear brighter to human eye.
* That's called Helmholtz-Kohlrausch effect.
* Fairchild and Pirrotta came up with a formula to
* calculate a correction for that effect.
* "Color Quality of Semiconductor and Conventional Light Sources":
* https://books.google.ru/books?id=ptDJDQAAQBAJ&pg=PA45&lpg=PA45&dq=fairchild+pirrotta+correction&source=bl&ots=7gXR2MGJs7&sig=ACfU3U3uIHo0ZUdZB_Cz9F9NldKzBix0oQ&hl=ru&sa=X&ved=2ahUKEwi47LGivOvmAhUHEpoKHU_ICkIQ6AEwAXoECAkQAQ#v=onepage&q=fairchild%20pirrotta%20correction&f=false
* @return {number}
*/
function getLightnessUsingFairchildPirrottaCorrection([l, c, h]) {
const l_ = 2.5 - 0.025 * l
const g = 0.116 * Math.abs(Math.sin(degreesToRadians((h - 90) / 2))) + 0.085
return l + l_ * g * c
}
export function getPerceivedLightness(hex) {
return getLightnessUsingFairchildPirrottaCorrection(labToLch(xyzToLab(rgbToXyz(hex))))
}
HSV 색상 공간은 트릭을 수행해야 합니다. 작업중인 언어에 따라 Wikipedia 기사를 참조하십시오 . 라이브러리 변환이 발생할 수 있습니다.
H는 색상의 수치 인 색조입니다 (예 : 빨강, 초록 ...)
S는 색상의 채도입니다. 즉, '강렬한'정도입니다
V는 색상의 '밝기'입니다.
RGB 휘도 값 = 0.3 R + 0.59 G + 0.11 B
http://www.scantips.com/lumin.html
흰색에 얼마나 가까운 지 찾고 있다면 유클리드 거리를 사용할 수 있습니다 (255, 255, 255)
RGB 색상 공간은 L2의 유클리드 거리와 관련하여 지각 적으로 불균일하다고 생각합니다. 균일 한 공간에는 CIE LAB 및 LUV가 포함됩니다.
Jive Dadson의 역 감마 공식은 Javascript로 구현할 때 반 조정을 제거해야합니다. 즉 함수 gam_sRGB의 리턴은 return int (v * 255) 여야합니다. int (v * 255 + .5)를 반환하지 않습니다. 반 조정은 반올림되며, 이는 R = G = B, 즉 회색 트라이어드에서 너무 높은 값을 유발할 수 있습니다. R = G = B 트라이어드에서 그레이 스케일 변환은 R과 동일한 값을 생성해야합니다. 공식이 유효하다는 증거 중 하나입니다. 작동하는 공식은 반 조정없이 그레이 스케일의 9 가지 음영을 참조하십시오 .
그 RGB 계수가 어떻게 결정되었는지 궁금합니다. 나는 실험을 직접했고 다음과 같이 끝났습니다.
Y = 0.267 R + 0.642 G + 0.091 B
가깝지만 오랫동안 확립 된 ITU 계수와는 분명히 다릅니다. 우리의 눈에는 망막에 서로 다른 양의 원뿔과 막대가있을 수 있으며, 특히 다른 유형의 원뿔 사이의 비율이 다를 수 있기 때문에 이러한 계수가 각각의 관찰자마다 다를 수 있는지 궁금합니다.
참고로 :
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 인 디스플레이조차도 다른 디스플레이에서 테스트를 반복했지만 모두 나에게 동일하게 보입니다. 더욱이, ITU 계수는 문자 그대로 내 눈에 잘못되었습니다.
그리고 네, 아마도 정상적인 컬러 비전을 가지고 있습니다.
인식 된 휘도를 올바르게 계산 해야하는 C 코드가 있습니다.
// 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
}
R로 색상의 밝기를 결정하기 위해 RGB 시스템 색상을 HSV 시스템 색상으로 변환합니다.
필자의 스크립트에서는 다른 이유로 전에 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
명확성을 위해, 제곱근을 사용하는 공식은
sqrt(coefficient * (colour_value^2))
아니
sqrt((coefficient * colour_value))^2
이에 대한 증거는 R = G = B 트라이어드를 그레이 스케일 R로 변환하는 데 있습니다. 이는 색상 값과 계수가 아닌 색상 값을 제곱 한 경우에만 해당됩니다. 그레이 스케일의 9 가지 음영 참조