image - tono - valor del color




Fórmula para determinar el brillo del color RGB. (12)

Estoy buscando algún tipo de fórmula o algoritmo para determinar el brillo de un color dados los valores RGB. Sé que no puede ser tan simple como sumar los valores RGB y tener sumas más altas sea más brillante, pero no sé por dónde empezar.


¿Te refieres al brillo? ¿Brillo percibido? Luminancia?

  • Luminancia (estándar para ciertos espacios de color): (0.2126*R + 0.7152*G + 0.0722*B) [1]
  • Luminancia (opción percibida 1): (0.299*R + 0.587*G + 0.114*B) [2]
  • Luminancia (opción percibida 2, más lenta de calcular): 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 ) (gracias a @MatthewHerbst ) [3]

A continuación se muestra el único algoritmo CORRECTO para convertir imágenes sRGB, como se usa en navegadores, etc., a escala de grises.

Es necesario aplicar una inversa de la función gamma para el espacio de color antes de calcular el producto interno. Luego aplicas la función gamma al valor reducido. Si no se incorpora la función gamma, se pueden producir errores de hasta el 20%.

Para cosas típicas de la computadora, el espacio de color es sRGB. Los números correctos para sRGB son aprox. 0,21, 0,72, 0,07. Gamma para sRGB es una función compuesta que se aproxima a la exponenciación en 1 / (2.2). Aquí está todo 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)
    );
}

Creo que lo que está buscando es la fórmula de conversión RGB -> Luma .

Fotométrica / digital ITU BT.709 :

Y = 0.2126 R + 0.7152 G + 0.0722 B

Digital ITU BT.601 (le da más peso a los componentes R y B):

Y = 0.299 R + 0.587 G + 0.114 B

Si está dispuesto a intercambiar precisión por desempeño, hay dos fórmulas de aproximación para esta:

Y = 0.33 R + 0.5 G + 0.16 B

Y = 0.375 R + 0.5 G + 0.125 B

Estos pueden ser calculados rápidamente como

Y = (R+R+B+G+G+G)/6

Y = (R+R+R+B+G+G+G+G)>>3


En lugar de perderse entre la selección aleatoria de fórmulas que se mencionan aquí, le sugiero que busque la fórmula recomendada por los estándares de W3C.

Aquí hay una implementación PHP simple pero exacta de las fórmulas de relación de luminancia relativa y contraste WCAG 2.0 SC 1.4.3 . Produce valores que son apropiados para evaluar las relaciones requeridas para el cumplimiento de WCAG, como en esta página , y como tal, es adecuado y apropiado para cualquier aplicación web. Esto es trivial para portar a otros idiomas.

/**
 * 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);
}

Encontré este código (escrito en C #) que hace un excelente trabajo de cálculo del "brillo" de un color. En este escenario, el código está tratando de determinar si se debe colocar texto blanco o negro sobre el color.


La 'V' de HSV es probablemente lo que estás buscando. MATLAB tiene una función rgb2hsv y el artículo de wikipedia previamente citado está lleno de pseudocódigo. Si una conversión RGB2HSV no es factible, un modelo menos preciso sería la versión en escala de grises de la imagen.


La fórmula de gamma inversa de Jive Dadson debe tener eliminado el medio ajuste cuando se implementa en Javascript, es decir, el retorno de la función gam_sRGB debe devolverse int (v * 255); no devuelve int (v * 255 + .5); La mitad del ajuste se redondea, y esto puede causar un valor demasiado alto en R = G = B, es decir, tríada de color gris. La conversión a escala de grises en una tríada R = G = B debe producir un valor igual a R; Es una prueba de que la fórmula es válida. Consulte Nine Shades of Greyscale para ver la fórmula en acción (sin el medio ajuste).


Para agregar lo que todos los demás dijeron:

Todas estas ecuaciones funcionan bastante bien en la práctica, pero si necesita ser muy preciso, primero debe convertir el color en espacio de color lineal (aplicar imagen inversa-gamma), hacer el promedio de los colores primarios y, si lo desea, mostrar el color: vuelva a colocar la luminancia en el monitor gamma.

La diferencia de luminancia entre ingnoring gamma y hacer gamma adecuada es de hasta el 20% en los grises oscuros.


Para determinar el brillo de un color con R, convierto el color del sistema RGB al color del sistema HSV.

En mi script, uso el código del sistema HEX antes por otra razón, pero también puede comenzar con el código del sistema RGB con rgb2hsv {grDevices} . La documentación está here .

Aquí está esta parte de mi código:

 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

Por favor define el brillo. Si está buscando qué tan cerca del blanco está el color, puede usar la Distancia euclidiana desde (255, 255, 255)


Valor de luminancia RGB = 0.3 R + 0.59 G + 0.11 B

http://www.scantips.com/lumin.html

Si está buscando qué tan cerca del blanco está el color, puede usar la Distancia euclidiana desde (255, 255, 255)

Creo que el espacio de color RGB es perceptivamente no uniforme con respecto a la distancia euclidiana L2. Los espacios uniformes incluyen CIE LAB y LUV.





rgb