ฉันกำลังมองหาสูตรหรืออัลกอริทึมบางอย่างเพื่อกำหนดความสว่างของสีที่ให้ค่า RGB ฉันรู้ว่ามันไม่ง่ายเหมือนการเพิ่มค่า RGB เข้าด้วยกันและการมีผลรวมที่สูงกว่านั้นจะสว่างกว่า แต่ฉันก็รู้สึกว่าจะเริ่มต้นตรงไหน
ฉันกำลังมองหาสูตรหรืออัลกอริทึมบางอย่างเพื่อกำหนดความสว่างของสีที่ให้ค่า RGB ฉันรู้ว่ามันไม่ง่ายเหมือนการเพิ่มค่า RGB เข้าด้วยกันและการมีผลรวมที่สูงกว่านั้นจะสว่างกว่า แต่ฉันก็รู้สึกว่าจะเริ่มต้นตรงไหน
คำตอบ:
คุณหมายถึงความสว่างหรือไม่ การรับรู้ความสว่าง? สว่าง?
(0.2126*R + 0.7152*G + 0.0722*B)
[1](0.299*R + 0.587*G + 0.114*B)
[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]0.299*(R^2)
(เพราะการยกกำลังไปก่อนคูณ)
ฉันคิดว่าสิ่งที่คุณกำลังมองหาคือสูตรการแปลงRGB -> Luma
แสง / ดิจิตอลITU BT.709 :
Y = 0.2126 R + 0.7152 G + 0.0722 B
Digital 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
Blue
+ 3 * สีเขียว) / 6, อันที่สองคือ (3 * สีแดง + Blue
+ 4 * สีเขียว) >> 3 ได้รับทั้งในการประมาณอย่างรวดเร็ว Blue มีน้ำหนักต่ำสุด แต่ก็ยังอยู่ที่นั่น
Y = (R<<1+R+G<<2+B)>>3
(นั่นเป็นเพียงรอบ CPU 3-4 รอบบน ARM) แต่ฉันคิดว่าคอมไพเลอร์ที่ดีจะทำการเพิ่มประสิทธิภาพนั้นสำหรับคุณ
ฉันทำการเปรียบเทียบอัลกอริทึมทั้งสามในคำตอบที่ยอมรับแล้ว ฉันสร้างสีในวงรอบซึ่งมีการใช้สีเพียงประมาณ 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 ความสว่างสัมพัทธ์และสูตรอัตราส่วนคอนทราสต์ (ดูที่@คำตอบของซิงโครที่นี่ )
รูปแบบสามารถมองเห็นได้บางครั้งในภาพที่ 1 และ 2 ขึ้นอยู่กับจำนวนของสีในแถวเดียว ฉันไม่เคยเห็นลวดลายบนรูปภาพจากอัลกอริธึมที่ 3 หรือ 4
ถ้าฉันต้องเลือกฉันจะใช้อัลกอริธึมหมายเลข 3 เนื่องจากง่ายต่อการใช้งานมากและเร็วกว่าอันดับ 4 ประมาณ 33%
^2
และsqrt
รวมอยู่ในสูตรที่สามเป็นวิธีที่เร็วใกล้เคียงกับเส้นตรงจาก RGB ที่ไม่ใช่เชิงเส้น RGB แทน^2.2
และ^(1/2.2)
ที่จะถูกต้องมากขึ้น การใช้อินพุตที่ไม่ใช่เชิงเส้นแทนที่จะเป็นลิเนียร์นั้นเป็นเรื่องปกติ
ด้านล่างเป็นอัลกอริทึมที่ถูกต้องเพียงอย่างเดียวสำหรับการแปลงภาพ 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)
);
}
คำตอบเดียวที่มีความถูกต้องเป็น@ Jive-dadsonและ@EddingtonsMonkeyคำตอบและในการสนับสนุน@ Nils-Pipenbrinck คำตอบอื่น ๆ(รวมถึงคำตอบที่ยอมรับ)กำลังเชื่อมโยงหรืออ้างถึงแหล่งข้อมูลที่ไม่ถูกต้องไม่เกี่ยวข้องล้าสมัยหรือแตกหัก
เนื่องจากหัวข้อนี้ปรากฏอย่างสูงในเครื่องมือค้นหาฉันจึงเพิ่มคำตอบนี้เพื่อชี้แจงความเข้าใจที่คลาดเคลื่อนในเรื่องต่างๆ
ความสว่างเป็นคุณสมบัติการรับรู้มันไม่มีการวัดโดยตรง
การรับรู้ความสว่างถูกวัดโดยแบบจำลองการมองเห็นบางอย่างเช่น CIELAB ที่นี่ L * (Lstar) เป็นการวัดการรับรู้แสงและไม่ตรงกับเส้นโค้งโดยประมาณสำหรับการมองเห็นของมนุษย์
ความส่องสว่างเป็นตัวชี้วัดเชิงเส้นของแสงซึ่งมีน้ำหนักเชิงสเปกตรัมสำหรับการมองเห็นปกติ แต่ไม่ได้ปรับสำหรับการรับรู้ที่ไม่ใช่เชิงเส้นของความสว่าง
Luma ( Y´prime ) คือสัญญาณแกมม่าที่เข้ารหัสแล้วและมีน้ำหนักถ่วงน้ำหนักที่ใช้ในการเข้ารหัสวิดีโอบางรายการ เพื่อไม่ให้สับสนกับความส่องสว่างเชิงเส้น
แกมมาหรือการถ่ายโอนโค้ง (TRC) เป็นโค้งที่มักจะคล้ายกับการรับรู้โค้งและมักจะใช้กับข้อมูลภาพสำหรับการจัดเก็บหรือออกอากาศเพื่อลดเสียงที่รับรู้และ / หรือปรับปรุงการใช้ข้อมูล (และเหตุผลที่เกี่ยวข้อง)
ในการพิจารณาความสว่างที่รับรู้อันดับแรกให้แปลงค่าภาพแกมม่าที่เข้ารหัส R´G´B´ เป็นความส่องสว่างเชิงเส้น ( L
หรือY
) จากนั้นเป็นความสว่างที่มองไม่เห็นเชิงเส้น ( L*
)
... เพราะเห็นได้ชัดว่ามันหายไปที่ไหนสักแห่ง ...
แปลงค่าจำนวนเต็ม sRGB 8 บิตทั้งหมดเป็นทศนิยม 0.0-1.0
vR = sR / 255;
vG = sG / 255;
vB = sB / 255;
แปลง RGB ที่เข้ารหัสแกมม่าเป็นค่าเชิงเส้น ตัวอย่างเช่น sRGB (มาตรฐานคอมพิวเตอร์) ต้องใช้ power curve ประมาณ V ^ 2.2 แม้ว่าการแปลง "ถูกต้อง" จะเป็น:
โดยที่ V´เป็นช่องสัญญาณ s, RGB, 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));
}
}
หากต้องการค้นหา Luminance (Y) ให้ใช้ค่าสัมประสิทธิ์มาตรฐานสำหรับ sRGB:
Pseudocode โดยใช้ฟังก์ชั่นด้านบน:
Y = (0.2126 * sRGBtoLin(vR) + 0.7152 * sRGBtoLin(vG) + 0.0722 * sRGBtoLin(vB))
ใช้ความส่องสว่าง 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
L*a*b*
ไม่คำนึงถึงคุณลักษณะทางจิตวิทยาจำนวนมาก Helmholtz-Kohlrausch effect เป็นหนึ่งเดียว แต่ก็มีอีกหลายอย่าง CIELAB ไม่ใช่รูปแบบการประเมินภาพ "เต็ม" ไม่ว่าด้วยวิธีใด ในโพสต์ของฉันฉันพยายามที่จะครอบคลุมแนวคิดพื้นฐานอย่างสมบูรณ์ที่สุดโดยไม่ต้องเข้าไปใน minutiae ลึกมาก โมเดล Hunt, โมเดลของ Fairchild และอื่น ๆ ทำงานได้อย่างสมบูรณ์มากขึ้น แต่ก็มีความซับซ้อนมากขึ้น
น่าสนใจสูตรนี้สำหรับ RGB => HSVใช้เพียง v = MAX3 (r, g, b) คุณสามารถใช้จำนวนสูงสุดได้ (r, g, b) เป็น V ใน HSV
ฉันตรวจสอบและในหน้า 575 ของHearn & Bakerนี่คือวิธีที่พวกเขาคำนวณ "คุณค่า" เช่นกัน
แทนที่จะหลงทางในการเลือกสูตรที่กล่าวถึงในที่นี้ฉันขอแนะนำให้คุณลองสูตรที่แนะนำโดยมาตรฐาน W3C
นี่คือตรงไปตรงมา แต่แน่นอนการดำเนิน PHP ของWCAG 2.0 SC 1.4.3 ญาติความสว่างและความคมชัดอัตราส่วนสูตร มันสร้างค่าที่เหมาะสมสำหรับการประเมินอัตราส่วนที่จำเป็นสำหรับการปฏิบัติตาม 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);
}
ในการเพิ่มสิ่งที่คนอื่นพูด:
สมการทั้งหมดนี้ทำงานได้ดีในทางปฏิบัติ แต่ถ้าคุณต้องการแม่นยำมากคุณต้องแปลงสีให้เป็นพื้นที่สีเชิงเส้นก่อน (ใช้ภาพผกผัน - แกมม่า) ทำค่าเฉลี่ยน้ำหนักของสีหลักและ - ถ้าคุณต้องการ แสดงสี - นำความสว่างกลับเข้าไปในแกมม่าของจอภาพ
ความแตกต่างของความส่องสว่างระหว่างการฝังแกมม่ากับการทำแกมม่าที่เหมาะสมนั้นสูงถึง 20% ในสีเทาเข้ม
ฉันกำลังแก้ไขงานที่คล้ายกันในวันนี้ด้วยจาวาสคริปต์ ฉันgetPerceivedLightness(rgb)
ใช้ฟังก์ชันนี้เป็นสี HEX RGB มันเกี่ยวข้องกับเอฟเฟ็กต์ Helmholtz-Kohlrausch ผ่านสูตร Fairchild และ Perrotta สำหรับการแก้ไขความสว่าง
/**
* 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))))
}
HSV colourspace ควรทำตามเคล็ดลับดูบทความ wikipediaขึ้นอยู่กับภาษาที่คุณใช้ในการทำงานคุณอาจได้รับการแปลงห้องสมุด
H คือสีซึ่งเป็นค่าตัวเลขสำหรับสี (เช่นสีแดงสีเขียว ... )
S คือความอิ่มตัวของสีนั่นคือ 'รุนแรง' อย่างไร
V คือ 'ความสว่าง' ของสี
ค่าความส่องสว่าง RGB = 0.3 R + 0.59 G + 0.11 B
http://www.scantips.com/lumin.html
หากคุณกำลังมองหาว่าสีใกล้เคียงกับสีขาวมากแค่ไหนคุณสามารถใช้ Euclidean Distance ได้ตั้งแต่ (255, 255, 255)
ฉันคิดว่าพื้นที่สีของ RGB นั้นดูไม่สม่ำเสมอเมื่อเทียบกับระยะทางยูคอนลิเดียน L2 พื้นที่ที่สม่ำเสมอรวมถึง CIE LAB และ LUV
สูตรผกผัน - แกมม่าโดย Jive Dadson จำเป็นต้องลบการปรับครึ่งเมื่อใช้งานใน Javascript นั่นคือการกลับมาจากฟังก์ชั่น gam_sRGB จะต้องกลับ int (v * 255); ไม่คืนค่า int (v * 255 + .5); ปรับครึ่งรอบขึ้นและอาจทำให้ค่าหนึ่งสูงเกินไปใน R = G = B เช่นสีเทาสามกลุ่ม การแปลง Greyscale บน R = G = B สามควรสร้างมูลค่าเท่ากับ R; มันเป็นข้อพิสูจน์ว่าสูตรนั้นถูกต้อง ดูNine Shades of Greyscaleสำหรับสูตรที่ใช้งาน (โดยไม่ต้องปรับครึ่ง)
ฉันสงสัยว่าสัมประสิทธิ์ 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 นั้นไม่ถูกต้องสำหรับสายตาของฉัน
และใช่ฉันน่าจะมีการมองเห็นสีปกติ
นี่คือรหัส 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
}
กรุณากำหนดความสว่าง หากคุณกำลังมองหาว่าสีใกล้เคียงกับสีขาวมากแค่ไหนคุณสามารถใช้Euclidean Distance ได้ตั้งแต่ (255, 255, 255)
'V' ของ HSV อาจเป็นสิ่งที่คุณกำลังมองหา MATLAB มีฟังก์ชั่น rgb2hsv และบทความ wikipedia ที่อ้างถึงก่อนหน้านี้เต็มไปด้วย pseudocode หากการแปลง RGB2HSV เป็นไปไม่ได้แบบจำลองที่แม่นยำน้อยกว่าจะเป็นรูปภาพระดับสีเทา
ลิงค์นี้จะอธิบายทุกอย่างในเชิงลึกรวมถึงสาเหตุที่ค่าคงที่ตัวคูณเหล่านั้นมีอยู่ก่อนค่า R, G และ B
แก้ไข: มันมีคำอธิบายหนึ่งในคำตอบที่นี่ด้วย (0.299 * R + 0.587 * G + 0.114 * B)
ในการพิจารณาความสว่างของสีด้วย 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
เพื่อความชัดเจนสูตรที่ใช้รากที่สองจะต้องเป็น
sqrt(coefficient * (colour_value^2))
ไม่
sqrt((coefficient * colour_value))^2
การพิสูจน์เรื่องนี้อยู่ในการแปลงค่า R = G = B สามเป็น greyscale R ซึ่งจะเป็นจริงถ้าคุณกำหนดค่าสีเป็นสองเท่าไม่ใช่ค่าสีคูณค่าสัมประสิทธิ์ ดูNine Shades of Greyscale