質問
RGB 値に基づいて色の明るさを決定するための何らかの式またはアルゴリズムを探しています。RGB 値を加算し、合計が大きいほど明るくなるというような単純なわけにはいかないことはわかっていますが、どこから始めればよいのか迷っています。
解決
明るさのことですか?知覚された明るさ?輝度?
- 輝度(特定のカラースペースの標準):
(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]
他のヒント
あなたが探しているのはRGBだと思います - > ルマ 変換式。
写真/デジタル 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
受け入れられた答えで3つのアルゴリズムを比較しました。サイクルで色を生成しました。そこでは、約400色のみが使用されていました。各色は2x2ピクセルで表され、色は最も暗いものから最も明るいもの(左から右、上から下まで)を並べ替えます。
最初の写真 - 輝度(相対)
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's 答え ここ)
パターンは、1列の色の数に応じて、1番目と2番目の画像で発見される場合があります。 3番目または4番目のアルゴリズムの写真にパターンを見つけたことはありません。
選択しなければならなかった場合、アルゴリズム番号3を使用して、実装がはるかに簡単で、4回目よりも約33%速くなります。
以下は、ブラウザなどで使用される sRGB 画像をグレースケールに変換するための唯一の正しいアルゴリズムです。
内積を計算する前に、色空間のガンマ関数の逆関数を適用する必要があります。次に、減らされた値にガンマ関数を適用します。ガンマ関数を組み込んでいない場合、最大 20% の誤差が発生する可能性があります。
一般的なコンピュータの場合、色空間は sRGB です。sRGB の正しい数値は約 1 です。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)を使用するだけです。つまり、を使用できます 最大 of(r、g、b)hsvのvとして。
私は575ページでチェックしました ハーン&ベイカー これは、それらが「価値」を計算する方法です。
私は見つけました このコード (C#で書かれている)それは、色の「明るさ」を計算する優れた仕事をしている。このシナリオでは、コードは色に白と黒のテキストを配置するかどうかを決定しようとしています。
他のすべてが言ったことを追加するには:
これらのすべての方程式は実際にはちょっとうまく機能しますが、非常に正確である必要がある場合は、最初に色を線形の色空間に変換する必要があります(逆画像ガンマを適用します)。色を表示 - 輝度をモニターガンマに戻します。
イングノリングガンマと適切なガンマを行うことの輝度の違いは、ダークグレーで最大20%です。
ここで言及した式のランダムな選択の中で迷子になるのではなく、W3C標準で推奨される式に行くことをお勧めします。
これが簡単であるが正確なPHP実装です WCAG 2.0 SC 1.4.3 相対輝度 と コントラスト比 式。 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.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);
}
「受け入れられた」答えは間違っていて不完全です
正確な唯一の答えはです @Jive-Dadson と @eddingtonsmonkey 回答、そしてサポート @nils-pipenbrinck. 。他の答え (受け入れられたものを含む) 間違っている、無関係、時代遅れ、または壊れているソースにリンクまたは引用しています。
簡単に言えば:
- SRGBはそうでなければなりません 線形化 係数を適用する前に。
- 輝度(LまたはY)は光と同様に線形です。
- 知覚された軽さ(l*)は、人間の知覚と同様に非線形です。
- HSVとHSLは、知覚の点でリモートで正確でさえありません。
- SRGBのIEC標準は、0.04045のしきい値を指定します いいえ 0.03928(これは時代遅れの初期ドラフトからでした)。
- 便利です (つまり、知覚に関連して), 、ユークリッドの距離には、Cielabなどの知覚的に均一なデカルトベクター空間が必要です。 SRGBは1つではありません。
以下は、正確で完全な答えです:
このスレッドは検索エンジンで高く見えるため、この答えを追加して、主題に関するさまざまな誤解を明確にしています。
輝度 知覚属性であり、直接的な測定値はありません。
認識された軽さ Cielabなどのいくつかのビジョンモデルによって測定されます。 知覚的な軽さ, 、そして、人間の視覚非線形応答曲線に近似するのは非線形です。
輝度 は光の線形尺度であり、通常の視力のためにスペクトル重み付けされていますが、軽さの非線形知覚には調整されていません。
ルマ (Y´ Prime)は、一部のビデオエンコーディングで使用されるエンコードされた加重信号です。線形輝度と混同しないでください。
ガンマ または、トランスファーカーブ(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の電力曲線が必要です。
ここで、v´はSRGBのガンマエンコードR、G、またはBチャネルです。
pseudocode:
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 = (0.2126 * sRGBtoLin(vR) + 0.7152 * sRGBtoLin(vG) + 0.0722 * sRGBtoLin(vB))
知覚された軽さを見つけるために:
ステップ4:
上から輝度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
チャールズ・ポイントンのガンマFAQ
HSVカラースペースはトリックを行う必要があります、 ウィキペディアの記事 あなたが働いている言語に応じて、あなたはライブラリの変換を得るかもしれません。
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に実装されたときに半調整を削除する必要があります。 return int(v*255+.5);半調整が丸みを帯び、これにより、r = g = b ieグレーカラートライアドで値が高すぎる可能性があります。 r = g = bトライアド上のグレースケール変換は、rに等しい値を生成する必要があります。これは、式が有効であることの1つの証拠です。見る 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
私は、明るい赤、明るい緑、明るい青の背景に小さな灰色のバーをすばやく動かし、できるだけ溶けて灰色を調整することでテストを行いました。また、他の色合いでそのテストを繰り返しました。さまざまなディスプレイでテストを繰り返しました。1つでも3.0のガンマ係数が固定されていますが、すべて同じように見えます。さらに、ITU係数は文字通り私の目には間違っています。
そして、はい、私はおそらく通常のカラービジョンを持っています。
明るさを定義してください。色がどれだけ近いかを探しているなら、あなたは使用できます ユークリッド距離 (255、255、255)から
HSVの「V」はおそらくあなたが探しているものです。 MATLABにはRGB2HSV機能があり、以前に引用されたWikipediaの記事は擬似コードでいっぱいです。 RGB2HSV変換が実行不可能な場合、より正確なモデルがグレースケールバージョンの画像になります。
このリンク R、G、Bの値の前にこれらの乗数定数が存在する理由など、すべてを詳細に説明します。
編集:ここでも答えの1つについて説明しています(0.299*r + 0.587*g + 0.114*b)
Rで色の明るさを決定するために、HSVシステムの色でRGBシステムの色を変換します。
私のスクリプトでは、他の理由で以前に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つのシェードオブグレースケール