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


387

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


8
지각 된 밝기는 내가 생각하는 것입니다. 감사합니다.
robmerica

2
이론과 코드 (C #)를 포함하여 색상 공간과 색상 공간 간의 대화에 대한 좋은 기사 ( .NET에서 색상 조작-1 부 )가 있습니다. 답을 보려면 기사의 모델 간 변환 주제를 참조하십시오.
밑줄

4
나는 오랜 세월 동안 회원이었으며, 전에는 한 번도 해본 적이 없습니다. 답변을 검토 한 후 어느 것을 수락해야하는지 다시 생각해보십시오.
Jive Dadson

답변:


456

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

  • 휘도 (특정 색 공간에 대한 표준) : (0.2126*R + 0.7152*G + 0.0722*B) [1]
  • 휘도 (지각 옵션 1) : (0.299*R + 0.587*G + 0.114*B) [2]
  • 휘도 (옵션 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]

26
이 두 가지 모두 생리적 측면을 강조합니다. 인간의 안구는 녹색 빛에 가장 민감하고, 빨강에서 파랑에 대해 가장 민감하지 않습니다.
Bob Cross

16
이들 모두는 아마도 선형 0-1 RGB에 대한 것이며, 감마 보정 된 0-255 RGB 일 것입니다. 그들은 당신이 생각하는 것처럼 변환되지 않습니다.
alex strange

4
정확하지 않습니다. 선형 변환을 적용하기 전에 먼저 색 공간에 감마 함수의 역을 적용해야합니다. 그런 다음 선형 기능을 적용한 후 감마 기능이 적용됩니다.
Jive Dadson

6
마지막 공식에서 (0.299 * R) ^ 2입니까 아니면 0.299 * (R ^ 2)입니까?
Kaizer Sozay

3
@KaizerSozay 여기에 쓰여진 것처럼 0.299*(R^2)(지수는 곱하기 전에 오기 때문에)
Dantevg

298

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

47
정확한 값을 입력하고 "충분히 근접한"유형 바로 가기도 포함했습니다. +1.
Beska

3
@Jonathan Dumaine-두 ​​가지 빠른 계산 공식은 모두 파란색을 포함합니다. 첫 번째 것은 (2 * Red + Blue+ 3 * Green) / 6이고, 두 번째는 (3 * Red + Blue+ 4 * Green) >> 3입니다. 두 가지 근사치 모두에서 Blue의 가중치는 가장 낮지 만 여전히 남아 있습니다.
Franci Penov

84
@JonathanDumaine 그의 인간의 눈이 ;-) 블루에 적어도 지각 때문에
크리스토퍼 Oezbek

4
빠른 버전이 잘 작동합니다. 수천 명의 사용자를 대상으로 실제 앱에 대한 테스트 및 적용이 완료되었습니다.
milosmns

10
빠른 버전은 다음과 같이하면 훨씬 빠릅니다 Y = (R<<1+R+G<<2+B)>>3(ARM에서 3-4 CPU 사이클 만). 좋은 컴파일러가 그 최적화를 수행 할 것입니다.
rjmunro

105

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

인식 된 밝기 알고리즘 비교


3
oyu는 다른 색조가 동일한 휘도로 렌더링되는지 인식 할 수있는 그림 패턴을 사용하기 때문에 이것이 가장 좋은 대답입니다. 나와 현재 모니터의 경우 3 번째 사진은 "최고의 모습"입니다. 4 번째보다 빠르기 때문입니다.
CoffeDeveloper

8
모든 기능에 올바른 입력을 제공하지 않았기 때문에 비교 이미지가 올바르지 않습니다. 첫 번째 기능에는 선형 RGB 입력이 필요합니다 . 비선형 (예 : 감마 보정) RGB 를 제공하여 밴딩 효과 만 재현 할 수 있습니다 . 이 문제를 해결하면 밴딩 아티팩트가없고 첫 번째 기능이 확실한 승자입니다.
Max

1
를 @Max ^2sqrt제 식에 포함되는 대신에 RGB의 비 - 선형 RGB에서 선형 근사 빠른 방법 ^2.2^(1/2.2)그 더 정확할 것이다. 선형 입력 대신 비선형 입력을 사용하는 것은 불행히도 매우 일반적입니다.
Mark Ransom

53

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

5
이것이 바로 sRGB가 정의 된 방식입니다. 그 이유는 0에 가까운 수치 문제를 피하기 때문이라고 생각합니다. 2.2와 1 / 2.2의 거듭 제곱으로 숫자를 올렸다면 큰 차이가 없습니다.
Jive Dadson

8
JMD-시각 지각 연구소의 작업의 일부로 CRT 모니터에서 직접 휘도 측정을 수행했으며 값 범위의 맨 아래에 선형 휘도 영역이 있음을 확인할 수 있습니다.
Jerry Federspiel

2
나는 이것이 매우 오래되었다는 것을 알고 있지만 여전히 검색해야합니다. 나는 그것이 옳을 것이라고 생각하지 않습니다. 회색 (255,255,255) = 회색 (255,0,0) + 회색 (0,255,0) + 회색 (0,0,255)이 아니어야합니까? 그렇지 않습니다.
DCBillen 15:08에

2
@DCBillen : 아니요, 값은 비선형 감마 보정 sRGB 공간에 있으므로 추가 할 수 없습니다. 추가하려면 gam_sRGB를 호출하기 전에 추가해야합니다.
rdb

1
@DCBillen Rdb가 정확합니다. 그것들을 더하는 방법은 int grey (int r, int g, int b) 함수에 표시되며 gam_sRGB를 "호출하지 않습니다". 4 년 후에 정답이 너무 낮다는 것은 고통 스럽습니다. :-) 정말로 .. 나는 그것을 극복 할 것이다.
Jive Dadson

45

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

정확한 답변은 @ 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


@Rotem 감사합니다. 이상하고 불완전한 진술을 보았는데, 특히이 스레드가 여전히 검색 엔진에서 높은 순위를 차지하기 때문에 문제를 해결하는 것이 도움이 될 것이라고 생각했습니다.
Myndex

MATLAB 명령을 거의 사용하지 않고 BT.601 LumaCIE 1976 L * Perceptual Grey를 비교 하는 데모를 만들었습니다 .Luma=rgb2gray(RGB);LAB=rgb2lab(RGB);LAB(:,:,2:3)=0;PerceptualGray=lab2rgb(LAB);
Rotem

@ Mindex 나는 당신의 공식을 L *에 얻기 위해 사용했지만, 내가 사용하는 공식에 관계없이 여전히 이상한 결과를 얻습니다 ... 당신과 함께, # d05858의 L *는 # c51c2a의 L *보다 어둡습니다 ... 이것을 올바르게 얻는 방법? 수식이 예상대로 작동하지 않는 이유는 무엇입니까? :(
sjahan

1
@asdfasdfads 예, L*a*b*많은 심리 물리학 적 속성을 고려하지 않습니다. Helmholtz-Kohlrausch 효과는 하나이지만 다른 것들도 많습니다. CIELAB은 "전체"이미지 평가 모델이 아닙니다. 저는 포스트에서 기본 개념을 가능한 한 완벽하게 다루려고 노력했습니다. 헌트 (Hunt) 모델, 페어차일드 (Fairchild) 모델 등은보다 완전한 작업을 수행하지만 실질적으로 더 복잡합니다.
Myndex

1
@Myndex, 신경 끄시 고, 내 구현은 피로 기반이었고, 불쌍한 내 결과 :( 큰 가치가 당신의 도움과 게시물에 대한 대단히 감사합니다 그에서 온!
sjahan

11

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


1
바로 내가 필요한 것입니다. 나는 고전적인 "컬러 바"데모를하고 있었고, 최고의 흑백 선택으로 컬러 위에 라벨을 붙이고 싶었다!
RufusVS 2016 년

10

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

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

Hearn & Baker pg 319에서


기록을 위해 링크가 죽었습니다. 여기에서 아카이브 버전 -web.archive.org/web/20150906055359/http://…
Peter

HSV는 지각 적으로 균일하지 않으며 (아직도 가깝지 않습니다). 색상을 조정하는 "편리한"방법으로 만 사용되지만 인식과 관련이 없으며 V는 L 또는 Y (CIE Luminance)의 실제 값과 관련이 없습니다.
Myndex

9

여기에 언급 된 임의의 수식 중에서 길을 잃지 않고 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);
}

왜 W3C 정의를 선호합니까? 개인적으로 저는 CCIR 601과 w3c 권장 사항을 모두 구현했으며 CCIR 601 결과에 훨씬 더 만족했습니다
user151496

1
내가 말했듯이 W3C와 WCAG 모두가 권장하기 때문에?
Synchro

1
W3C 수식이 여러 수준에서 올바르지 않습니다. 인간의 인식을 고려하지 않고, 선형이며 전혀 지각 적으로 균일하지 않은 휘도를 사용하여 "간단한"대비를 사용하고 있습니다. 그중에서도 오늘날 관련이없는 1988 년 이전의 일부 표준 (!!!)을 기반으로 한 것으로 보입니다 (이 표준은 녹색 / 검정과 같은 흑백 모니터를 기반으로하며 온 / 오프의 전체 대비를 나타냄). 그레이 스케일이나 색상을 고려하지 않음).
Myndex

1
그것은 완전한 쓰레기입니다. 루마는 특히 지각 적입니다. 따라서 빨강, 초록, 파랑에 대한 계수가 다릅니다. 나이는 그것과 아무 관련이 없습니다-우수한 CIE Lab 지각 색 공간은 1976 년부터 시작되었습니다. W3C 공간은 좋지 않지만 계산하기 쉬운 실용적인 근사치입니다. 제공 할만한 건설적인 것이 있다면, 빈 비평 대신에 게시하십시오.
Synchro

3
추가 / 업데이트 : 현재 우리는 지각 대비를 더 잘 모델링하는 대체 알고리즘을 연구하고 있습니다 (Github Issue 695에서 논의) . 그러나 별도의 문제로 sRGB의 임계 값은 0.04045 이며, 더 이상 사용되지 않는 초기 sRGB 초안에서 참조 된 0.03928이 아닙니다. 신뢰할 수있는 IEC 표준은 0.04045를 사용하며 WCAG에서이 오류를 수정하기위한 풀 요청이 예정되어 있습니다. (참고 : IEC 61966-2-1 : 1999) 이것은 Github 이슈 360에 있지만 8 비트에는 실제 차이가 없습니다. 스레드 360의 끝 근처에는 8 비트의 0.04045 / 0.03928을 포함한 오류 차트가 있습니다.
Myndex

8

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

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

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


2

오늘 자바 스크립트에서 비슷한 작업을 해결하고있었습니다. 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))))
}

1

HSV 색상 공간은 트릭을 수행해야 합니다. 작업중인 언어에 따라 Wikipedia 기사를 참조하십시오 . 라이브러리 변환이 발생할 수 있습니다.

H는 색상의 수치 인 색조입니다 (예 : 빨강, 초록 ...)

S는 색상의 채도입니다. 즉, '강렬한'정도입니다

V는 색상의 '밝기'입니다.


7
HSV 색 공간의 문제점은 blueyellow에 대해 채도와 값은 동일하지만 색조가 다를 수 있다는 것 입니다. 노랑은 파랑보다 훨씬 밝습니다. HSL도 마찬가지입니다.
Ian Boyd

hsv는 기술적 인 의미에서 색상의 "밝기"를 제공합니다. 지각 밝기 HSV는 정말 실패에
user151496

HSV와 HSL은 지각 적으로 정확하지 않으며 가깝지 않습니다. 그것들은 상대 색상을 조정하기위한 "제어"에 유용하지만 지각 적 밝기의 정확한 예측에는 유용하지 않습니다. 지각 적 밝기를 위해 CIELAB의 L *를 사용하십시오.
Myndex

1

RGB 휘도 값 = 0.3 R + 0.59 G + 0.11 B

http://www.scantips.com/lumin.html

흰색에 얼마나 가까운 지 찾고 있다면 유클리드 거리를 사용할 수 있습니다 (255, 255, 255)

RGB 색상 공간은 L2의 유클리드 거리와 관련하여 지각 적으로 불균일하다고 생각합니다. 균일 한 공간에는 CIE LAB 및 LUV가 포함됩니다.


1

Jive Dadson의 역 감마 공식은 Javascript로 구현할 때 반 조정을 제거해야합니다. 즉 함수 gam_sRGB의 리턴은 return int (v * 255) 여야합니다. int (v * 255 + .5)를 반환하지 않습니다. 반 조정은 반올림되며, 이는 R = G = B, 즉 회색 트라이어드에서 너무 높은 값을 유발할 수 있습니다. R = G = B 트라이어드에서 그레이 스케일 변환은 R과 동일한 값을 생성해야합니다. 공식이 유효하다는 증거 중 하나입니다. 작동하는 공식은 반 조정없이 그레이 스케일의 9 가지 음영을 참조하십시오 .


당신이 당신의 물건을 알고있는 것처럼 들리므로 +0.5를 제거했습니다.
Jive Dadson

나는 실험을했다. C ++에서는 +0.5가 필요하므로 다시 넣습니다. 다른 언어로의 번역에 대한 의견을 추가했습니다.
Jive Dadson 2016 년

1

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

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


실험에서 감마 성분을 먼저 제거하기 위해 선형화 했습니까? 그렇지 않은 경우 결과를 설명 할 수 있습니다. 그러나 계수는 CIE 1931 실험과 관련이 있으며 평균 17 관찰자이므로 결과에 개별 편차가 있습니다.
Myndex 2016 년

1

인식 된 휘도를 올바르게 계산 해야하는 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
}

0

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


1
아니요, sRGB 값 사이에 유클리드 거리를 사용할 수 없으며 sRGB는 지각 적으로 균일 한 데카르트 / 벡터 공간이 아닙니다. 유클리드 거리를 색차의 척도로 사용하려면 최소한 CIELAB로 변환하거나 CIECAM02와 같은 CAM을 사용해야합니다.
Myndex

0

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


0

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

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


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

0

명확성을 위해, 제곱근을 사용하는 공식은

sqrt(coefficient * (colour_value^2))

아니

sqrt((coefficient * colour_value))^2

이에 대한 증거는 R = G = B 트라이어드를 그레이 스케일 R로 변환하는 데 있습니다. 이는 색상 값과 계수가 아닌 색상 값을 제곱 한 경우에만 해당됩니다. 그레이 스케일의 9 가지 음영 참조


5
괄호 미스 매치가 있습니다
log0

사용하는 계수가 올바른 계수의 제곱근이 아닌 한.
RufusVS
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.