web-dev-qa-db-ja.com

RGB色の明るさを決める式

私はRGB値を与えられた色の明るさを決定するためのある種の公式やアルゴリズムを探しています。私はそれがRGB値を一緒に足し合わせて、より高い合計を明るくすることほど単純ではあり得ないことを知っています、しかし私はどこから始めればいいか迷っています。

356
robmerica

明るさを意味しますか?明るさを知覚?輝度?

  • 輝度(特定の色空間の規格):(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]
431
Anonymous

私はあなたが探しているのは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

もしあなたが精度と性能を交換しても構わないと思っているのであれば、これには2つの近似式があります。

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
276
Franci Penov

私は、受け入れられた答えの中で3つのアルゴリズムを比較しました。私は約400色ごとに使われる色を周期的に生成しました。各色は2 x 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列の色数によっては、1枚目と2枚目の絵に模様が付くことがあります。私は、3番目または4番目のアルゴリズムからの絵の上のパターンを決して見つけませんでした。

もし私が選択しなければならないならば、私はそれが実行するのがはるかに簡単でその4番目よりも約33%速いのでアルゴリズム番号3で行くでしょう。

Perceived brightness algorithm comparison

94
Petr Hurtak

以下は、ブラウザなどで使用されている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)
    );
}
42
Jive Dadson

このコード (C#で書かれています)は色の「明るさ」を計算するのに優れた仕事をしています。このシナリオでは、コードは色の上に白または黒のテキストを配置するかどうかを決定しようとしています。

10
sitesbyjoe

興味深いことに、 このRGB => HSV の式は、v = MAX3(r、g、b)を使用するだけです。つまり、HSVではVとして(r、g、b)の最大を使用できます。

私はチェックして、575ページの Hearn&Baker で、これがどのように "値"を計算するかです。

From Hearn&Baker pg 319

10
bobobobo

ここで言及されている式のランダムな選択の中で迷子になるのではなく、私はあなたがW3C規格によって推奨されている式のために行くことを勧めます。

これは WCAG 2.0 PHP 1.4.3の簡単だが正確なSC実装です相対輝度 および コントラスト比 の式。このページのように このページ のように、WCAG準拠に必要な比率を評価するのに適した値を生成します。そのため、あらゆるWebアプリに適しています。他の言語に移植するのは簡単です。

/**
 * 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);
}
8
Synchro

他のすべての人が言ったことを追加するには:

これらの方程式はすべて実際にはうまく機能しますが、非常に正確にする必要がある場合は、まず色を線形色空間に変換し(逆画像ガンマを適用する)、原色の加重平均を行い色を表示する - 輝度をモニタのガンマに戻します。

内部のガンマと適切なガンマを行うこととの間の輝度差は、濃いグレーで最大20%です。

7

「受け入れられた」回答が間違っていて不完全である

正確な回答は、 @ jive-dadson および @ EddingtonsMonkey の回答、およびサポート中の @ nils-pipenbrinck のみです。他の回答(受け入れられたものを含む)は、間違っている、無関係、古い、または壊れているソースへのリンクまたは引用です。

簡単に:

  • sRGBは、係数を適用する前にLINEARIZEDでなければなりません。
  • 輝度(LまたはY)は光と同様に線形です。
  • 知覚明度(L *)は、人間の知覚と同様に非線形です。
  • HSVとHSLは、知覚の観点からもリモートでは正確ではありません。
  • SRGBのIEC規格は、0.04045のしきい値を指定します。これは_ではなく(= /// =)_ 30.03928です(古い初期ドラフトから).
  • 便利な(つまり、知覚に関連する)、ユークリッド距離には、CIELABなどの知覚的に均一なデカルトベクトル空間が必要です。 sRGBは1ではありません。

以下が正しい完全な答えです。

このスレッドは検索エンジンに非常によく登場するため、この回答を追加して、主題に関するさまざまな誤解を明確にします。

明るさは知覚属性であり、直接的な測定値はありません。

知覚明度は、CIELABなどの一部の視覚モデルによって測定されます。ここで、L *(Lstar)は知覚明度の尺度です、および人間の視覚の非線形応答曲線に近似する非線形です。

ルミナンスは、光の線形測定値であり、通常の視覚ではスペクトル的に重み付けされますが、明るさの非線形知覚では調整されません。

Lumaprime)は、一部のビデオエンコーディングで使用されるガンマエンコードされ、重み付けされた信号です。線形輝度と混同しないでください。

ガンマまたは伝達曲線(TRC)は、知覚曲線によく似た曲線であり、一般的に保存または放送用の画像データに適用されて減少します知覚ノイズおよび/またはデータ利用率の向上(および関連する理由)。

知覚される明るさを決定するには、まずガンマエンコードされたR´G´B´画像値を線形輝度に変換します(LまたはY)そして、非線形知覚明度(L*))


輝度を見つけるには:

...明らかにどこかで失われたため...

第一歩:

すべてのsRGB 8ビット整数値を10進数0.0-1.0に変換します

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

ステップ2:

ガンマエンコードされたRGBを線形値に変換します。たとえば、sRGB(コンピューター標準)には約V ^ 2.2のパワーカーブが必要ですが、「正確な」変換は次のとおりです。

sRGB to Linear

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の標準係数を適用します。

Apply coefficients 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 *に変換します

L* from Y equation
擬似コード:

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ゾーンV)。

参照:

IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
チャールズポイントンのガンマFAQ

7
Myndex

HSV色空間はうまくいくはずです。あなたが使っている言語によっては ウィキペディアの記事 を見てくださいあなたにはライブラリ変換があるかもしれません。

Hは色相であり、色の数値(すなわち赤、緑、…)である。

Sは色の彩度、つまりそれがどれほど '強い'かです。

Vは色の「明るさ」です。

1
Ian Hopkinson

RGB輝​​度値= 0.3 R + 0.59 G + 0.11 B

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

色が白にどれだけ近いかを探しているなら、Euclidean Distance from(255、255、255)を使えます

RGB色空間は、L2ユークリッド距離に関して知覚的に不均一です。一様なスペースにはCIE LABとLUVがあります。

1
Gandalf

これは、知覚される輝度を正しく計算するための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
}
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係数は文字通り私の目には間違っています。

はい、私はおそらく普通の色覚を持っています。

1
vortex

Jive Dadsonによる逆ガンマ式は、Javascriptで実装されるときにハーフアジャストを削除する必要があります。つまり、関数gam_sRGBからの戻り値はint(v * 255)の戻り値である必要があります。 intを返さない(v * 255 + .5)。ハーフアジャストは切り上げます、そしてこれはR = G = B、すなわちグレートライアドの上で1より高い値を引き起こす可能性があります。 R = G = Bトライアドのグレースケール変換は、Rと等しい値を生成します。式が有効であることの証明の1つです。実際の式については、 9種類のグレースケール を参照してください(半調整なし)。

1
Dave Collier

明るさを定義してください。色が白にどれだけ近いかを探しているなら、 ユークリッド距離 から(255、255、255)を使うことができます。

0
Ben S

HSVの「V」はおそらくあなたが探しているものです。 MATLABにはrgb2hsv関数があり、以前に引用されたウィキペディアの記事は疑似コードでいっぱいです。 RGB2HSV変換が実行不可能な場合は、精度の低いモデルが画像のグレースケールバージョンになります。

0
Jacob

わかりやすくするために、平方根を使用する式は次のようにする必要があります。

sqrt(coefficient * (colour_value^2))

ではない

sqrt((coefficient * colour_value))^2

これを証明するのは、R = G = BのトライアドをグレースケールRに変換することです。これは、カラー値と係数の二乗ではなく、カラー値を二乗した場合にのみ当てはまります。 9つのグレースケールの色合いを参照してください

0
Dave Collier

Rで色の明るさを決めるために、RGB系の色をHSV系の色に変換します。

私のスクリプトでは、他の理由で以前はHEXシステムコードを使用していましたが、rgb2hsv {grDevices}を使用してRGBシステムコードから始めることもできます。ドキュメントはここ です

これが私のコードのこの部分です。

 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

このリンク は、R、G、Bの値の前にこれらの乗数定数が存在する理由を含め、すべてを詳細に説明しています。

編集:それもここに答えの一つへの説明があります(0.299 * R + 0.587 * G + 0.114 * B)

0
dsignr