Je recherche une formule ou un algorithme pour déterminer la luminosité d'une couleur en fonction des valeurs RVB. Je sais que ce ne peut pas être aussi simple que d’additionner les valeurs RVB et d’avoir des sommes plus élevées plus brillantes, mais je ne sais pas trop par où commencer.
Voulez-vous dire la luminosité? Luminosité perçue? Luminance?
(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 )
(merci à @ MatthewHerbst ) [3]Je pense que vous recherchez la formule de conversion RVB -> Luma .
Photométrique/numérique ITU BT.709 :
Y = 0.2126 R + 0.7152 G + 0.0722 B
Numérique ITU BT.601 (donne plus de poids aux composants R et B):
Y = 0.299 R + 0.587 G + 0.114 B
Si vous êtes prêt à échanger l'exactitude contre la performance, il existe deux formules d'approximation pour celle-ci:
Y = 0.33 R + 0.5 G + 0.16 B
Y = 0.375 R + 0.5 G + 0.125 B
Ceux-ci peuvent être calculés rapidement comme
Y = (R+R+B+G+G+G)/6
Y = (R+R+R+B+G+G+G+G)>>3
J'ai comparé les trois algorithmes dans la réponse acceptée. J'ai généré des couleurs dans un cycle où seulement environ 400 couleurs étaient utilisées. Chaque couleur est représentée par 2x2 pixels, les couleurs sont triées du plus foncé au plus clair (de gauche à droite, de haut en bas).
1ère image - Luminance (relative)
0.2126 * R + 0.7152 * G + 0.0722 * B
2ème image - http://www.w3.org/TR/AERT#color-contrast
0.299 * R + 0.587 * G + 0.114 * B
3ème image - Modèle couleur HSP
sqrt(0.299 * R^2 + 0.587 * G^2 + 0.114 * B^2)
4ème image - WCAG 2.0 SC 1.4.luminance relative et taux de contraste formule (voir @ Synchro's répondre ici )
Les motifs peuvent parfois être repérés sur les 1ère et 2ème images en fonction du nombre de couleurs d'une rangée. Je n'ai jamais repéré aucun motif sur l'image du 3ème ou 4ème algorithme.
Si je devais choisir, je choisirais l'algorithme 3, car il est beaucoup plus facile à mettre en œuvre et environ 33% plus rapide que le 4ème.
Vous trouverez ci-dessous le seul algorithme CORRECT permettant de convertir les images sRVB, telles qu’elles sont utilisées dans les navigateurs, en niveaux de gris.
Il est nécessaire d'appliquer un inverse de la fonction gamma pour l'espace colorimétrique avant de calculer le produit intérieur. Ensuite, vous appliquez la fonction gamma à la valeur réduite. Ne pas incorporer la fonction gamma peut entraîner des erreurs allant jusqu'à 20%.
Pour les tâches informatiques typiques, l’espace colorimétrique est sRGB. Les bons chiffres pour sRGB sont env. 0,21, 0,72, 0,07. Gamma pour sRGB est une fonction composite qui approxime l'exponentiation de 1/(2.2). Voici le tout en 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)
);
}
J'ai trouvé ce code (écrit en C #) qui fait un excellent travail de calcul de la "luminosité" d'une couleur. Dans ce scénario, le code essaie de déterminer s'il faut mettre du texte blanc ou noir sur la couleur.
Fait intéressant, cette formulation pour RGB => HSV utilise seulement v = MAX3 (r, g, b). En d'autres termes, vous pouvez utiliser le maximum de (r, g, b) comme V dans HSV.
J'ai vérifié et à la page 575 de Hearn & Baker c'est ainsi qu'ils calculent la "valeur" également.
Plutôt que de vous perdre dans la sélection aléatoire des formules mentionnées ici, je vous suggère d’opter pour la formule recommandée par les normes W3C.
Voici une implémentation PHP simple mais exacte de WCAG 2.0 SC 1.4.luminance relative et rapport de contraste formules. Il génère des valeurs appropriées pour évaluer les ratios requis pour la conformité WCAG, comme sur cette page , et en tant que telles, convient à toutes les applications Web. Ceci est trivial pour porter à d'autres langues.
/**
* 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);
}
Pour ajouter ce que tous les autres ont dit:
Toutes ces équations fonctionnent assez bien dans la pratique, mais si vous devez être très précis, vous devez d’abord convertir la couleur en un espace colorimétrique linéaire (appliquez l’image inverse du gamma), effectuez la moyenne pondérée des couleurs primaires et - si vous le souhaitez. afficher la couleur - ramenez la luminance dans le gamma du moniteur.
La différence de luminance entre maîtriser le gamma et réaliser le gamma approprié va jusqu'à 20% chez les gris sombres.
Les seules réponses qui soient exactes sont les réponses @ jive-dadson et @ EddingtonsMonkey , et à l'appui @ nils-pipenbrinck . Les autres réponses (y compris les acceptées) renvoient à ou citent des sources erronées, non pertinentes, obsolètes ou endommagées.
Étant donné que ce fil de discussion apparaît fortement dans les moteurs de recherche, j'ajoute cette réponse pour clarifier les différentes idées fausses sur le sujet.
La luminosité est un attribut perceptuel, elle n'a pas de mesure directe.
La légèreté perçue est mesurée par certains modèles de vision tels que CIELAB, ici L * (Lstar) est une mesure de légèreté perceptuelle , et est non linéaire pour se rapprocher de la courbe de réponse non linéaire de la vision humaine.
La luminance est une mesure linéaire de la lumière pondérée spectralement pour une vision normale mais non ajustée pour une perception non linéaire de la luminosité.
Luma ( Y´ prime) est un signal pondéré gamma utilisé dans certains codages vidéo. Il ne faut pas le confondre avec la luminance linéaire.
Le gamma ou courbe de transfert (TRC) est une courbe souvent similaire à la courbe de perception, et est couramment appliquée aux données d'image pour le stockage ou la diffusion afin de réduire bruit perçu et/ou améliorer l'utilisation des données (et les raisons connexes).
Pour déterminer la luminosité perçue , convertissez d’abord les valeurs d’image R´G´B´ encodées en gamma en luminance linéaire (L
ou Y
), puis à une luminosité perçue non linéaire (L*
)
... Parce qu'apparemment il a été perdu quelque part ...
Convertir toutes les valeurs sRGB sur 8 bits en valeurs décimales 0.0-1.0
_ vR = sR / 255;
vG = sG / 255;
vB = sB / 255;
_
Convertit un RVB codé gamma en une valeur linéaire. sRGB (standard informatique), par exemple, nécessite une courbe de puissance d'environ V ^ 2,2, bien que la transformation "précise" soit:
Où V´ est le canal R, G ou B codé en gamma de sRGB.
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));
}
}
_
Pour trouver la luminance (Y), appliquez les coefficients standard pour sRGB:
Pseudocode utilisant les fonctions ci-dessus:
_Y = (0.2126 * sRGBtoLin(vR) + 0.7152 * sRGBtoLin(vG) + 0.0722 * sRGBtoLin(vB))
_
Prendre la luminance Y d'en haut et la transformer en 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 * est une valeur de 0 (noir) à 100 (blanc), 50 étant le "gris moyen" perceptuel. L * = 50 est l'équivalent de Y = 18,4 ou, en d'autres termes, une carte grise à 18% représentant le milieu d'une exposition photographique (zone V d'Ansel Adams).
IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
FAQ Gamma de Charles Poynton
L’espace colorimétrique HSV devrait faire l'affaire, voir l'article de wikipedia , selon la langue dans laquelle vous travaillez, vous risquez d'obtenir un conversion de bibliothèque.
H est la teinte qui est une valeur numérique pour la couleur (c'est-à-dire le rouge, le vert ...)
S est la saturation de la couleur, c’est-à-dire à quel point elle est "intense"
V est la "luminosité" de la couleur.
Valeur de luminance RVB = 0,3 R + 0,59 G + 0,11 B
http://www.scantips.com/lumin.html
Si vous cherchez à quel point le blanc est proche de la couleur, vous pouvez utiliser Distance euclidienne à partir de (255, 255, 255).
Je pense que l’espace colorimétrique RVB est non uniforme du point de vue de la perception de la distance euclidienne L2. Les espaces uniformes incluent CIE LAB et LUV.
Voici un peu de code C qui devrait calculer correctement la luminance perçue.
// 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
}
Je me demande comment ces coefficients RGB ont été déterminés. J'ai fait une expérience moi-même et je me suis retrouvé avec ce qui suit:
Y = 0.267 R + 0.642 G + 0.091 B
Proche mais évidemment différent des coefficients de l’ITU établis depuis longtemps. Je me demande si ces coefficients pourraient être différents pour chaque observateur, car nous pourrions tous avoir une quantité différente de cônes et de bâtonnets sur la rétine de nos yeux, et en particulier le rapport entre les différents types de cônes pourrait être différent.
Pour référence:
UIT 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
J'ai fait le test en déplaçant rapidement une petite barre grise sur un fond rouge vif, vert vif et bleu vif, et en ajustant le gris jusqu'à ce qu'il se confonde autant que possible. J'ai également répété ce test avec d'autres nuances. J'ai répété le test sur différents écrans, même avec un facteur gamma de 3,0, mais cela me semble identique. De plus, les coefficients de l'UIT sont littéralement faux pour mes yeux.
Et oui, je suppose que ma vision des couleurs est normale.
La formule gamma inverse de Jive Dadson doit supprimer le demi-ajustement lorsqu’elle est implémentée en Javascript, c’est-à-dire que le retour de la fonction gam_sRGB doit être return int (v * 255); ne retourne pas int (v * 255 + .5); Ajustez les arrondis à moitié, ce qui peut entraîner une valeur 1 trop élevée sur un trièdre de couleur R = G = B, c'est-à-dire gris. La conversion en niveaux de gris sur un trièdre R = G = B devrait produire une valeur égale à R; c'est une preuve que la formule est valide. Voir Neuf nuances de gris pour la formule en action (sans le demi-réglage).
S'il vous plaît définir la luminosité. Si vous cherchez à quel point la couleur est proche du blanc, vous pouvez utiliser Distance euclidienne à partir de (255, 255, 255)
Le "V" du HSV est probablement ce que vous recherchez. MATLAB a une fonction rgb2hsv et l'article de Wikipédia précédemment cité est rempli de pseudocodes. Si une conversion RGB2HSV n'est pas possible, un modèle moins précis serait la version en niveaux de gris de l'image.
Pour plus de clarté, les formules qui utilisent une racine carrée doivent être
sqrt(coefficient * (colour_value^2))
ne pas
sqrt((coefficient * colour_value))^2
La preuve en est la conversion d'un trièdre R = G = B en niveaux de gris R. Cela ne sera vrai que si vous égalisez la valeur de la couleur, et non la valeur de la couleur par son coefficient. Voir Neuf nuances de gris
Pour déterminer la luminosité d'une couleur avec R, je convertis la couleur système RVB en couleur système HSV.
Dans mon script, j'utilise le code système HEX auparavant pour une autre raison, mais vous pouvez également commencer avec le code système RVB avec rgb2hsv {grDevices}
. La documentation est ici .
Voici cette partie de mon code:
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
Ce lien explique tout en profondeur, y compris pourquoi ces constantes de multiplicateur existent avant les valeurs R, G et B.
Edit: Il y a une explication à l’une des réponses ici aussi (0.299 * R + 0.587 * G + 0.114 * B)