Question

Je recherche une sorte de formule ou d'algorithme pour déterminer la luminosité d'une couleur compte tenu des valeurs RVB. Je sais que cela ne peut pas être aussi simple que d'ajouter les valeurs RVB ensemble et d'avoir des sommes plus élevées, mais je suis en quelque sorte à perte de savoir par où commencer.

Était-ce utile?

La solution

Voulez-vous dire luminosité? Luminosité perçue? Luminance?

  • Luminance (standard pour certains espaces de couleurs): (0.2126*R + 0.7152*G + 0.0722*B) [1]
  • Luminance (option perçue 1): (0.299*R + 0.587*G + 0.114*B) [2]
  • Luminance (option perçue 2, plus lente à calculer): 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 ) (grâce à @Matthewherbst) [3]

Autres conseils

Je pense que ce que vous recherchez, c'est le RVB -> Luma formule de conversion.

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 une précision pour la perforation, 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 fait la comparaison des trois algorithmes dans la réponse acceptée. J'ai généré des couleurs dans le cycle où seulement environ la 400e couleur a été utilisée. Chaque couleur est représentée par 2x2 pixels, les couleurs sont triées du plus foncé au plus léger (gauche à droite, de haut en bas).

1ère photo - Luminance (relative)

0.2126 * R + 0.7152 * G + 0.0722 * B

2e image - http://www.w3.org/tr/aert#color-ctrestrast

0.299 * R + 0.587 * G + 0.114 * B

3e photo - Modèle de couleur HSP

sqrt(0.299 * R^2 + 0.587 * G^2 + 0.114 * B^2)

4e image - WCAG 2.0 SC 1.4.3 luminance relative et Rapport de contraste formule (voir @ Synchro réponse ici)

Le motif peut parfois être repéré sur la 1ère et la 2ème image en fonction du nombre de couleurs dans une ligne. Je n'ai jamais repéré de motif sur l'image du 3e ou du 4ème algorithme.

Si je devais choisir, j'irais avec l'algorithme numéro 3 car c'est beaucoup plus facile à mettre en œuvre et c'est environ 33% plus rapidement que le 4e.

Perceived brightness algorithm comparison

Vous trouverez ci-dessous le seul algorithme correct pour convertir des images SRGB, comme utilisé dans les navigateurs, etc., 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 interne. Ensuite, vous appliquez la fonction gamma à la valeur réduite. Le non-incorporation de la fonction gamma peut entraîner des erreurs allant jusqu'à 20%.

Pour des trucs informatiques typiques, l'espace colorimétrique est SRGB. Les bons numéros pour SRGB sont d'env. 0,21, 0,72, 0,07. Le gamma pour le SRGB est une fonction composite qui se rapproche de l'exponentiation par 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)
    );
}

De façon intéressante, Cette formulation pour RVB => HSV utilise simplement v = max3 (r, g, b). En d'autres termes, vous pouvez utiliser le maximum de (r, g, b) comme le V dans HSV.

J'ai vérifié et à la page 575 de Hearn & Baker C'est ainsi qu'ils calculent également la "valeur".

From Hearn&Baker pg 319

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.

Pour ajouter ce que tous les autres ont dit:

Toutes ces équations fonctionnent bien dans la pratique, mais si vous devez être très précise, vous devez d'abord convertir la couleur en espace colorimétrique linéaire (appliquez l'image inverse-gamma), faites la moyenne de poids des couleurs primaires et - si vous voulez Afficher la couleur - ramenez la luminance dans le moniteur Gamma.

La différence de luminance entre le gamma gamma et le gamma approprié est jusqu'à 20% dans les gris sombres.

Plutôt que de se perdre parmi la sélection aléatoire des formules mentionnées ici, je vous suggère de choisir la formule recommandée par les normes W3C.

Voici une implémentation PHP simple mais exacte du WCAG 2.0 SC 1.4.3 luminance relative et Rapport de contraste formules. Il produit des valeurs appropriées pour évaluer les ratios requis pour la conformité WCAG, comme sur cette page, et en tant que tel est approprié et approprié pour toute application Web. Ceci est trivial pour le port dans 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 <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);
}

La réponse "acceptée" est incorrecte et incomplète

Les seules réponses qui sont exactes sont les @ jive-dadson et @Eddingtonsmonkey Réponses et en soutien @ nils-pipenbrinck. Les autres réponses (y compris les acceptés) lient ou citons des sources qui sont erronées, non pertinentes, obsolètes ou cassées.

Brièvement:

  • SRGB doit être Linéarisé Avant d'appliquer les coefficients.
  • La luminance (L ou Y) est linéaire comme la lumière.
  • La légèreté perçue (l *) est non linéaire, tout comme la perception humaine.
  • HSV et HSL ne sont même pas précis à distance en termes de perception.
  • La norme IEC pour SRGB spécifie un seuil de 0,04045 il est NE PAS 0,03928 (c'était d'un premier projet obsolète).
  • Être utile (c'est-à-dire par rapport à la perception), Les distances euclidiennes nécessitent un espace vectoriel cartésien perceptuellement uniforme tel que le CIELAB. SRGB n'en est pas un.

Ce qui suit est une réponse correcte et complète:

Parce que ce fil apparaît fortement dans les moteurs de recherche, j'ajoute cette réponse pour clarifier les différentes idées fausses sur le sujet.

Luminosité est un attribut perceptuel, il n'a pas de mesure directe.

Légèreté perçue est mesuré par certains modèles de vision tels que le cielab, ici l * (lstar) est une mesure de légèreté perceptuelle, et est non linéaire pour approximer la courbe de réponse non linéaire de la vision humaine.

Luminance est une mesure linéaire de la lumière, pondérée spectrale pour une vision normale mais non ajustée pour la perception non linéaire de la légèreté.

Luma ( prime) est un signal pondéré en codé gamma utilisé dans certains codages vidéo. Il ne doit pas être confondu avec la luminance linéaire.

Gamma ou la courbe de transfert (TRC) est une courbe qui est souvent similaire à la courbe perceptuelle, et est généralement appliquée aux données d'image pour le stockage ou la diffusion pour réduire le bruit perçu et / ou améliorer l'utilisation des données (et des raisons connexes).

Pour déterminer la légèreté perçue, convertissez d'abord les valeurs d'image en codés gamma en r´g´b en en luminance linéaire (L ou Y ) puis à la légèreté perçue non linéaire (L*)


Pour trouver la luminance:

... parce que, apparemment, il a été perdu quelque part ...

La première étape:

Convertir toutes les valeurs entières SRGB 8 bits en décimal 0,0-1.0

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

Deuxième étape:

Convertissez 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:

sRGB to Linear

Où V´ est le canal R, G ou B codé 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));
        }
    }

Troisième étape:

Pour trouver la luminance (Y), appliquez les coefficients standard pour SRGB:

Apply coefficients Y = R * 0.2126 + G * 0.7152 + B *  0.0722

Pseudocode utilisant les fonctions ci-dessus:

Y = (0.2126 * sRGBtoLin(vR) + 0.7152 * sRGBtoLin(vG) + 0.0722 * sRGBtoLin(vB))

Pour trouver la légèreté perçue:

Quatrième étape:

Prenez la luminance y d'en haut et transformez en l *

L* from Y equation
Pseudocode:

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) où 50 est le "gris moyen" perceptuel. L * = 50 est l'équivalent de y = 18,4, ou en d'autres termes une carte grise de 18%, représentant le milieu d'une exposition photographique (Zone Adams Adams V).

Références:

IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
FAQ GAMMA de Charles Poynton

L'espace de couleurs HSV doit faire l'affaire, voir le Article Wikipedia Selon la langue dans laquelle vous travaillez, vous pouvez obtenir une conversion de bibliothèque.

H est Hue qui est une valeur numérique pour la couleur (c'est-à-dire rouge, 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 la couleur est proche de la couleur, vous pouvez utiliser la distance euclidienne de (255, 255, 255)

Je pense que l'espace colorimétrique RVB est perceptivement non uniforme par rapport à la distance euclidienne L2. Les espaces uniformes incluent CIE Lab et LUV.

La formule gamma inverse par Jive Dadson doit faire supprimer la moitié de réajustement lorsqu'elle est implémentée dans JavaScript, c'est-à-dire que le retour de la fonction GAM_SRGB doit être retourné int (v * 255); pas retour int (v * 255 + .5); À moitié réduit, et cela peut provoquer une valeur trop élevée sur un r = g = b ie gris couleur gris. La conversion de niveaux de gris sur une triade r = g = b devrait produire une valeur égale à r; C'est une preuve que la formule est valide. Voir Neuf nuances de greyscale pour la formule en action (sans le demi-ajustement).

Voici un peu de code C qui devrait bien calculer 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 RVB ont été déterminés. J'ai moi-même fait une expérience et je me suis retrouvé avec ce qui suit:

Y = 0.267 R + 0.642 G + 0.091 B

Close mais évidemment différent des coefficients de l'UIT établi depuis longtemps. Je me demande si ces coefficients pourraient être différents pour chaque observateur, car nous pouvons tous avoir une quantité différente de cônes et de tiges sur la rétine dans nos yeux, et en particulier le rapport entre les différents types de cônes peut différer.

Pour référence:

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

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 mélange 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 un avec un facteur gamma fixe de 3.0, mais tout me ressemble. De plus, les coefficients de l'UIT ont littéralement tort pour mes yeux.

Et oui, j'ai vraisemblablement une vision des couleurs normale.

Veuillez définir la luminosité. Si vous cherchez à quel point la couleur est proche de la couleur, vous pouvez utiliser Distance euclidienne à partir de (255, 255, 255)

Le «V» de HSV est probablement ce que vous recherchez. MATLAB a une fonction RGB2HSV et l'article Wikipedia précédemment cité est plein de pseudocode. Si une conversion RGB2HSV n'est pas possible, un modèle moins précis serait la version en niveaux de gris de l'image.

Ce lien Explique tout ce qui est en profondeur, y compris pourquoi ces constantes multiplicateurs existent avant les valeurs R, G et B.

Edit: il a une explication à l'une des réponses ici (0,299 * R + 0,587 * G + 0,114 * B)

Pour déterminer la luminosité d'une couleur avec R, je convertisse la couleur du système RVB dans la couleur du système HSV.

Dans mon script, j'utilise le code système hexadécial avant pour une autre raison, mais vous pouvez également démarrer 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

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 de cela réside dans la conversion d'une triade r = g = b en niveaux de greys R. Ce ne sera vrai que si vous carré la valeur de la couleur, pas le coefficient de temps de valeur de couleur. Voir Neuf nuances de greyscale

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top