RGBカラーの明るさを決定する式


387

RGB値を指定して、色の明るさを決定するための何らかの数式またはアルゴリズムを探しています。RGB値を加算して、合計が高くなるほど明るくなることは簡単ではありませんが、どこから始めればよいか途方に暮れています。


8
知覚された明るさは私が探しているものだと思います、ありがとう。
robmerica 2009

2
理論とコード(C#)の両方を含む、色空間とそれらの間の会話についての良い記事(.NETでの色の操作-パート1)があります。回答については、記事の「モデル間の変換」トピックをご覧ください。
2013年

4
私は何年にもわたって会員になっており、これまでにこれまでやったことはありません。答えを確認して、どちらを受け入れるかを考え直すことをお勧めしますか?
Jive Dadson 2017年

回答:


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を使用していることにも注意してください。それらは、あなたがそう思っているように変換されません。
アレックス奇妙な

4
正しくありません。線形変換を適用する前に、まず色空間にガンマ関数の逆関数を適用する必要があります。次に、線形関数を適用した後、ガンマ関数が適用されます。
Jive Dadson、

6
最後の式では、それは(0.299 * R)^ 2ですか、それとも0.299 *(R ^ 2)ですか?
Kaizer Sozay、2015

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

精度とパフォーマンスのトレードオフを喜んで行う場合、これには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

47
正確な値を入力するのが好きですが、「十分に近い」タイプのクイックショートカットも含まれています。+1。
Beska

3
@Jonathan Dumaine-2つの簡単な計算式には両方とも青が含まれます-1つ目は(2 * Red + Blue+ 3 * Green)/ 6、2 つ目は(3 * Red + Blue+ 4 * Green)>> 3です。確かに、どちらのクイック近似でも、Blueは最も低い重みを持っていますが、それでもまだ存在しています。
Franci Penov、

84
@JonathanDumaineそれは人間の目が青に対して最も知覚的ではないからです;-)
クリストファー・オエズベク2012年

4
クイックバージョンは適切に機能します。テストされ、数千人のユーザーがいる実際のアプリに適用すると、すべてが問題なく見えます。
milosmns 2015年

10
クイックバージョンは、次のようにするとさらに高速になりますY = (R<<1+R+G<<2+B)>>3(これは、ARMでのCPUサイクルが3〜4サイクルだけです)。
rjmunro 2015年

105

受け入れられた回答で3つのアルゴリズムを比較しました。サイクルで色を生成し、約400番目の色のみが使用されました。各色は2x2ピクセルで表され、色は最も暗い色から最も明るい色(左から右、上から下)に並べ替えられます。

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を使用します。

知覚された明るさアルゴリズムの比較


3
私にとって、これは最良の答えです。なぜなら、oyuは、同じ輝度で異なる色相がレンダリングされているかどうかを認識できる画像パターンを使用しているからです。私と私の現在のモニターにとって、3番目の画像は「最高の見た目」です。これは、4番目より速く、プラスです
CoffeDeveloper

8
すべての関数に正しい入力を提供しなかったため、比較画像は正しくありません。最初の関数には線形 RGB入力が必要です。非線形(つまり、ガンマ補正)RGBを提供することによってのみ、バンディング効果を再現できます。この問題を修正すると、バンディングアーティファクトがなくなり、1番目の関数が勝者となります。
最大

1
@maxは^2及びsqrt第三の式に含まれるRGB非線形の代わりからRGB線形近似の迅速な方法である^2.2^(1/2.2)それがより正確であろう。残念ながら、線形入力の代わりに非線形入力を使用することは非常に一般的です。
Mark Ransom

53

以下は、ブラウザなどで使用される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
これがsRGBの定義方法です。その理由は、それがゼロに近いいくつかの数値問題を回避するためだと思います。数値を2.2と1 / 2.2の累乗にしただけでは、それほど大きな違いはありません。
Jive Dadson 2013年

8
JMD-視覚認識ラボでの作業の一環として、CRTモニターで直接輝度測定を行い、値の範囲の下部に輝度の線形領域があることを確認できます。
Jerry Federspiel、2014年

2
私はこれが非常に古いことを知っていますが、それでもまだ検索されていません。それは正しいとは思えません。gray(255,255,255)= gray(255,0,0)+ gray(0,255,0)+ gray(0,0,255)にすべきではありませんか?そうではありません。
DCBillen 2015年

2
@DCBillen:いいえ、値は非線形のガンマ補正されたsRGB空間にあるため、単純に合計することはできません。これらを合計する場合は、gam_sRGBを呼び出す前に行う必要があります。
rdb

1
@DCBillen Rdbは正しいです。それらを合計する方法は、関数int gray(int r、int g、int b)に示されています。これは、gam_sRGBを「呼び出し解除」します。4年後、正解が非常に低く評価されるのは私を悩ませています。:-)そうでもない..私はそれを乗り越えます。
Jive Dadson、2016年

45

「受け入れられた」答えは不正確で不完全です

正確な唯一の回答は、@ jive-dadson@EddingtonsMonkeyの回答であり、サポートでは@ nils-pipenbrinckです。その他の回答(承認されたものを含む)は、間違っている、無関係である、時代遅れである、または壊れているソースへのリンクまたは引用です。

簡単に:

  • sRGBは 係数を適用する前に、線形化する。
  • 輝度(LまたはY)は、ライトと同様に線形です。
  • 知覚される明度(L *)は人間の知覚と同様に非線形です。
  • HSVとHSLは、知覚の点でリモートでさえ正確ではありません。
  • sRGBのIEC規格は0.04045のしきい値を指定していますが、そうではありません(これは廃止された初期のドラフトからのものです)。
  • ユークリッド距離は有用です(つまり、知覚と比較して)。CIELABなどの知覚的に均一なデカルトベクトル空間が必要です。sRGBは1つではありません。

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

このスレッドは検索エンジンでよく表示されるため、この回答を追加して、テーマに関するさまざまな誤解を明確にします。

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

知覚される明度は、CIELABなどのいくつかのビジョンモデルによって測定されます。ここで、L *(Lstar)は知覚明度の尺度であり、人間の視覚の非線形応答曲線を近似するために非線形です。

輝度は、通常の視覚に対してスペクトル的に重み付けされた光の線形測定ですが、明度の非線形知覚に対して調整されていません。

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

ガンマまたは伝達曲線(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からリニア

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ゾーンV)を表しています。

参照:

IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
Charles Poyntonのガンマに関するFAQ


@Rotemありがとうございました—奇妙で不完全な発言があり、特にこのスレッドが検索エンジンで上位にランク付けされているため、それを明らかにすることが役立つと感じました。
Myndex

私が作成したデモンストレーション比較BT.601ルマCIE 1976 L *を知覚グレー、いくつかのMATLABコマンドを使用して:Luma=rgb2gray(RGB);LAB=rgb2lab(RGB);LAB(:,:,2:3)=0;PerceptualGray=lab2rgb(LAB);
ロテム

@Myndex私はあなたの式を使用してL *に到達しましたが、使用する式が何であれ、それでも奇妙な結果が得られます...あなたの場合、#d05858のL *は#c51c2aのL *よりも暗いです...これを正しく行う方法は?数式が期待どおりに機能しないのはなぜですか?:(
sjahan

1
@asdfasdfadsはい、L*a*b*多くの心理物理学的属性は考慮されていません。ヘルムホルツコールラウシュ効果は1つですが、他にも多数あります。CIELABは、決して「完全な」画像評価モデルではありません。私の投稿では、非常に深い特徴点に出くわすことなく、基本的な概念をできる限り完全にカバーしようとしていました。ハントモデル、フェアチャイルドモデルなどは、より完全な仕事をしますが、かなり複雑でもあります。
Myndex

1
@Myndex、決して気にしない、私の実装は疲労ベースであり、私の悪い結果はそれからもたらされました:(あなたの助けとあなたの投稿にとても感謝しています!
sjahan

11

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


1
それがまさに私が必要としていたことです。私は古典的な「カラーバー」のデモを行っていて、黒または白の最良の選択で色の上にラベルを付けたかったのです。
RufusVS 2016年

10

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

私がチェックしたところ、Hearn&Bakerの 575ページで、これは彼らが「値」を計算する方法でもあります。

Hearn&Bakerからpg 319


念のためにリンクが死んで、アーカイブ版はこちら- web.archive.org/web/20150906055359/http://...
ピーター・

HSVは知覚的に均一ではありません(そして、それは近くさえありません)。これは、色を調整するための「便利な」方法としてのみ使用されますが、知覚には関係がなく、VはLまたはY(CIE輝度)の真の値とは関係ありません。
Myndex

9

ここで言及されている式のランダムな選択の中で迷うのではなく、W3C標準で推奨されている式を使用することをお勧めします。

これは、WCAG 2.0 SC 1.4.3の 相対輝度コントラスト比の式の単純ですが正確なPHP実装です。このページのように、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 <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ラボ知覚色空間は1976年にさかのぼります。W3C空間はそれほど良くありませんが、計算するのは簡単で実用的な近似です。あなたが提供する建設的なものがあれば、空の批評の代わりにそれを投稿してください。
シンクロ

3
追加/更新のみ:現在、知覚コントラストをより適切にモデル化する置換アルゴリズムを研究しています(Github Issue 695での議論)。ただし、FYIの別の問題として、sRGBのしきい値は0.04045であり、廃止された初期のsRGBドラフトから参照された0.03928ではありません。権威あるIEC stdは0.04045を使用しており、WCAGでこのエラーを修正するためのプルリクエストがまもなくリリースされます。(参照:IEC 61966-2-1:1999)これはGithub issue 360​​にありますが、8ビットでは実際の違いはありません。スレッド360の終わり近くに、8ビットの0.04045 / 0.03928を含むエラーのグラフがあります。
Myndex

8

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

これらの式はすべて実際にはある程度うまく機能しますが、非常に正確にする必要がある場合は、最初に色を線形色空間に変換し(逆イメージガンマを適用)、原色の重み付け平均を行い、必要に応じて色を表示する-輝度をモニターのガンマに戻します。

ガンマを無視することと適切なガンマを実行することの間の輝度差は、暗い灰色で最大20%です。


2

私は今日、JavaScriptで同様のタスクを解決していました。私はこのgetPerceivedLightness(rgb)関数をHEX RGBカラー用に解決しました。輝度補正のためのフェアチャイルドとペロッタの公式を介して、ヘルムホルツコールラウシュ効果を扱います。

/**
 * 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色空間でうまくいくはずです。ウィキペディアの記事を参照してくださいです。作業している言語に応じて、。ライブラリ変換が行われる場合があります。

Hは色の数値である色相です(つまり、赤、緑...)。

Sは色の彩度、つまりどれだけ「濃い」か

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


7
HSV色空間の問題は、黄色の彩度と値は同じでも色相が異なる可能性があることです。黄色は青よりもはるかに明るいです。HSLについても同様です。
Ian Boyd

hsvは、技術的な意味での色の「明るさ」を提供します。知覚的な明るさで
hsvは

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からの戻り値は、int(v * 255)を返す必要があります。int(v * 255 + .5);を返しません。半調整は切り上げます。これにより、R = G = B、つまり灰色のトライアドで値が高すぎる可能性があります。R = G = Bトライアドのグレースケール変換は、Rに等しい値を生成する必要があります。これは、式が有効であることを証明するものの1つです。実際の計算式(半調整なし)については、9つの階調のグレースケールを参照してください。


+0.5を削除しました
Jive Dadson 2017年

私は実験をしました。C ++では+0.5が必要なので、元に戻します。他の言語への翻訳についてのコメントを追加しました。
Jive Dadson 2017年

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

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関数があり、前に引用したウィキペディアの記事には疑似コードが満載です。RGB2HSV変換が実行できない場合、精度の低いモデルは画像のグレースケールバージョンになります。


0

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

編集:ここにも答えの1つに対する説明があります(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 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.