development

RGB 색상의 밝기를 결정하는 공식

big-blog 2020. 2. 28. 19:23
반응형

RGB 색상의 밝기를 결정하는 공식


RGB 값이 주어진 색상의 밝기를 결정하는 일종의 수식이나 알고리즘을 찾고 있습니다. RGB 값을 합산하고 더 높은 합계를 갖는 것이 더 간단 할 수는 없지만 어디서부터 시작 해야할지에 대한 손실이 있습니다.


밝기를 의미합니까? 지각 된 밝기? 휘도?

  • 휘도 (특정 색 공간에 대한 표준) : (0.2126*R + 0.7152*G + 0.0722*B) [1]
  • 휘도 (지각 옵션 1) : (0.299*R + 0.587*G + 0.114*B) [2]
  • 휘도 (옵션 2로 인식, 계산 속도가 느림) : ( @MatthewHerbst 덕분에 ) [3] 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 )

나는 당신이 찾고있는 것이 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

허용 된 답변에서 세 가지 알고리즘을 비교했습니다. 약 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을 사용합니다.

인식 된 밝기 알고리즘 비교


아래는 브라우저 등에서 사용되는 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)
    );
}

흥미롭게도 RGB => HSV에 대한이 공식 은 v = MAX3 (r, g, b) 만 사용합니다. 즉, 최대 (r, g, b)를 HSV의 V로 사용할 수 있습니다 .

나는 Hearn & Baker의 575 페이지에서 이것이 "가치"를 계산하는 방법입니다.

Hearn & Baker pg 319에서


색상의 "밝기"를 계산하는 훌륭한 작업을 수행하는 이 코드 (C #으로 작성)를 찾았습니다 . 이 시나리오에서 코드는 흰색 또는 검은 색 텍스트를 색상 위에 넣을지 여부를 결정하려고합니다.


"허용 된"답변이 잘못되고 불완전합니다

정확한 답변은 @ jive-dadson@EddingtonsMonkey 답변이며 @ nils-pipenbrinck 지원 합니다. 다른 답변 (허용됨 포함) 은 잘못되었거나 관련이 없거나 오래되었거나 파손 된 출처를 연결하거나 인용합니다.

간단히:

  • 계수를 적용하기 전에 sRGB를 LINEARIZED 해야합니다 .
  • 휘도 (L 또는 Y)는 빛과 마찬가지로 선형입니다.
  • 지각 된 밝기 (L *)는 인간의 지각과 마찬가지로 비선형입니다.
  • HSV와 HSL은 인식 측면에서 원격으로 정확하지도 않습니다.
  • sRGB에 대한 IEC 표준은 0.04045의 임계 값을 지정하며 0.03928이 아닙니다 (이전의 초기 초안에서 나온 것임).
  • 유용성 (즉 , 인식에 대한) , 유클리드 거리는 CIELAB와 같이 지각 적으로 균일 한 데카르트 벡터 공간을 필요로합니다. sRGB는 하나가 아닙니다.

다음은 정확하고 완전한 답변입니다.

이 스레드는 검색 엔진에 많이 나타나기 때문에 주제에 대한 다양한 오해를 명확히하기 위해이 답변을 추가하고 있습니다.

밝기 는 지각적인 속성이며 직접 측정 할 수 없습니다.

지각 된 밝기 는 CIELAB과 같은 일부 비전 모델에 의해 측정되며, 여기서 L * (Lstar)는 지각의 밝기 의 측정치이며 인간의 비전 비선형 반응 곡선에 근접하기 위해 비선형입니다.

휘도 는 빛의 선형 측정으로, 보통 시력에 대해서는 스펙트럼 가중치를 적용하지만 밝기에 대한 비선형 인식에는 조정되지 않습니다.

루마 ( Y ' 프라임)는 일부 비디오 인코딩에 사용되는 감마 인코딩 된 가중치 신호입니다. 선형 휘도와 혼동되어서는 안됩니다.

감마 또는 전송 곡선 (TRC)은 종종 지각 곡선과 유사한 곡선이며, 일반적으로 저장 또는 방송을위한 이미지 데이터에 적용되어인지 된 잡음을 줄이고 /거나 데이터 이용률 (및 관련 이유)을 개선합니다.

인식 된 밝기를 결정하려면 먼저 감마 인코딩 된 R´G´B '이미지 값을 선형 휘도 ( L또는 Y) 로 변환 한 다음 비선형 감지 밝기 ( L*)로 변환하십시오.


휘도를 찾기 위해 :

... 어딘가에서 길을 잃었 기 때문에 ...

1 단계 :

모든 sRGB 8 비트 정수 값을 10 진수 0.0-1.0으로 변환

  vR = sR / 255;
  vG = sG / 255;
  vB = sB / 255;

2 단계 :

감마 인코딩 RGB를 선형 값으로 변환합니다. 예를 들어 sRGB (컴퓨터 표준)에는 "정확한"변환이 다음과 같이 약 V ^ 2.2의 전력 곡선이 필요합니다.

sRGB에서 선형으로

여기서 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));
        }
    }

3 단계 :

휘도 (Y)를 찾으려면 sRGB에 대한 표준 계수를 적용하십시오.

계수 적용 Y = R * 0.2126 + G * 0.7152 + B * 0.0722

위 함수를 사용한 의사 코드 :

Y = (0.2126 * sRGBtoLin(vR) + 0.7152 * sRGBtoLin(vG) + 0.0722 * sRGBtoLin(vB))

인식 된 빛을 찾는 방법 :

4 단계 :

위에서 휘도 Y를 가져 와서 L *로 변환

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


다른 사람들이 말한 것을 추가하려면 :

이 모든 방정식은 실제로는 잘 작동하지만 매우 정밀 해야하는 경우 먼저 색상을 선형 색상 공간으로 변환해야하고 (역 이미지 감마 적용) 기본 색상의 가중치 평균을 수행하고 원하는 경우 색상 표시-휘도를 모니터 감마로 다시 가져옵니다.

감마를 무시하고 적절한 감마를 수행하는 것 사이의 휘도 차이는 어두운 회색에서 최대 20 %입니다.


여기에 언급 된 임의의 수식 중에서 손실되는 대신 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.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 <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);
}

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 가지 음영을 참조하십시오 (반 조정 없음).


다음은 감지 된 휘도를 올바르게 계산해야하는 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
}

그 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 계수는 문자 그대로 내 눈에 잘못되었습니다.

그리고 네, 아마도 정상적인 컬러 비전을 가지고 있습니다.


밝기를 정의하십시오. 흰색에 얼마나 가까운 지 찾고 있다면 유클리드 거리사용할 수 있습니다. (255, 255, 255)


HSV의 'V'는 아마도 당신이 찾고있는 것입니다. MATLAB에는 rgb2hsv 함수가 있으며 이전에 인용 된 Wikipedia 기사는 유사 코드로 가득합니다. RGB2HSV 변환이 가능하지 않은 경우 이미지의 회색조 버전이 덜 정확한 모델이됩니다.


이 링크 는 승수 상수가 R, G 및 B 값 앞에 존재하는 이유를 포함하여 모든 것을 자세히 설명합니다.

편집 : 여기에 대한 답변 중 하나에 대한 설명이 있습니다 (0.299 * R + 0.587 * G + 0.114 * B)


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 가지 음영 참조

참고 URL : https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color



반응형