Frage

Ich suche nach einer Art Formel oder Algorithmus, um die Helligkeit einer Farbe zu bestimmen, wenn die RGB -Werte angegeben sind. Ich weiß, dass es nicht so einfach sein kann, die RGB -Werte zusammen hinzuzufügen und höhere Summen heller zu haben, aber ich bin nur einen Verlust darüber, wo ich anfangen soll.

War es hilfreich?

Lösung

Meinst du Helligkeit? Wahrgenommene Helligkeit? Luminanz?

  • Luminanz (Standard für bestimmte Farbräume): (0.2126*R + 0.7152*G + 0.0722*B) [1]
  • Luminanz (wahrgenommene Option 1): (0.299*R + 0.587*G + 0.114*B) [2]
  • Luminanz (wahrgenommene Option 2, langsamer zu berechnen): 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 ) (Dank an @Matthewherbst) [3]

Andere Tipps

Ich denke, was Sie suchen, ist die RGB -> Luma Konversionsformel.

Photometrisch/digital ITU BT.709:

Y = 0.2126 R + 0.7152 G + 0.0722 B

Digital ITU BT.601 (gibt den R- und B -Komponenten mehr Gewicht):

Y = 0.299 R + 0.587 G + 0.114 B

Wenn Sie bereit sind, Genauigkeit gegen die Performance zu handeln, gibt es zwei Annäherungsformeln für diese:

Y = 0.33 R + 0.5 G + 0.16 B

Y = 0.375 R + 0.5 G + 0.125 B

Diese können schnell berechnet werden wie

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

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

Ich habe den drei Algorithmen in der akzeptierten Antwort vergleichbar. Ich habe Farben im Zyklus generiert, in dem nur etwa alle 400. Farbe verwendet wurde. Jede Farbe wird durch 2x2 Pixel dargestellt, die Farben werden von dunkel bis hellst (links nach rechts, von oben nach unten) sortiert.

1. Bild - Luminanz (relativ)

0.2126 * R + 0.7152 * G + 0.0722 * B

2. Bild - http://www.w3.org/tr/aert#color-contrast

0.299 * R + 0.587 * G + 0.114 * B

3. Bild - HSP -Farbmodell

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

4. Bild - WCAG 2.0 SC 1.4.3 relative Luminanz und Kontrastverhältnis Formel (siehe @Synchro Antworten hier)

Das Muster kann manchmal auf dem 1. und 2. Bild entdeckt werden, abhängig von der Anzahl der Farben in einer Reihe. Ich habe nie ein Muster auf dem Bild aus dem 3. oder 4. Algorithmus entdeckt.

Wenn ich wählen müsste, würde ich mit Algorithmus Nummer 3 gehen, da es viel einfacher zu implementieren ist und ungefähr 33% schneller als der 4..

Perceived brightness algorithm comparison

Unten ist der einzige korrekte Algorithmus zum Konvertieren von SRGB -Bildern, wie in Browsern usw. in Graustufen verwendet.

Es ist notwendig, eine Umkehrung der Gamma -Funktion für den Farbraum anzuwenden, bevor das innere Produkt berechnet wird. Dann wenden Sie die Gamma -Funktion auf den reduzierten Wert an. Wenn Sie die Gamma -Funktion nicht einbeziehen, kann dies zu Fehlern von bis zu 20%führen.

Für typische Computer -Sachen beträgt der Farbraum SRGB. Die richtigen Zahlen für SRGB sind ca. 0,21, 0,72, 0,07. Gamma für SRGB ist eine zusammengesetzte Funktion, die sich der Exponentiation um 1/(2.2) annähert. Hier ist das Ganze in 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)
    );
}

Interessant, Diese Formulierung für RGB => HSV Verwendet nur v = max3 (r, g, b). Mit anderen Worten, Sie können die verwenden maximal von (r, g, b) als V in HSV.

Ich habe überprüft und auf Seite 575 von Hearn & Baker So berechnen sie auch "Wert".

From Hearn&Baker pg 319

ich fand Dieser Code (geschrieben in C#) Das berechnet die "Helligkeit" einer Farbe hervorragend. In diesem Szenario versucht der Code festzustellen, ob weiß oder schwarzer Text über die Farbe gestellt werden soll.

Um hinzuzufügen, was alle anderen sagten:

Alle diese Gleichungen funktionieren in der Praxis irgendwie gut. Wenn Sie jedoch sehr genau sein müssen Zeigen Sie die Farbe an - Nehmen Sie die Luminanz wieder in den Monitor Gamma.

Der Luminanzunterschied zwischen Gamma in Gamma und der richtigen Gamma beträgt bis zu 20% in den dunklen Grautönen.

Anstatt sich unter der zufälligen Auswahl der hier genannten Formeln zu verlieren, schlage ich vor, dass Sie sich für die nach W3C -Standards empfohlene Formel entscheiden.

Hier ist eine einfache, aber genaue PHP -Implementierung der WCAG 2.0 SC 1.4.3 relative Luminanz und Kontrastverhältnis Formeln. Es erzeugt Werte, die für die Bewertung der für die WCAG -Compliance erforderlichen Verhältnisse geeignet sind, wie auf diese Seite, und als solche ist für jede Web -App geeignet und geeignet. Dies ist trivial, um auf andere Sprachen zu portieren.

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

Die "akzeptierte" Antwort ist falsch und unvollständig

Die einzigen Antworten, die genau sind, sind die @Jive-Dadson und @Eddingtonsmonkey Antworten und zur Unterstützung @Nils-Pipenbrinck. Die anderen Antworten (einschließlich der Akzeptierten) Verknüpfen mit oder zitieren Quellen, die entweder falsch, irrelevant, veraltet oder gebrochen sind.

Knapp:

  • SRGB muss sein Linearisiert Vor dem Anwenden der Koeffizienten.
  • Luminanz (L oder Y) ist linear wie leicht.
  • Die wahrgenommene Leichtigkeit (L*) ist nichtlinear wie die menschliche Wahrnehmung.
  • HSV und HSL sind in Bezug auf die Wahrnehmung nicht einmal aus der Ferne.
  • Der IEC -Standard für SRGB gibt einen Schwellenwert von 0,04045 an NICHT 0,03928 (das war aus einem veralteten frühen Entwurf).
  • Das nützlich sein (dh relativ zur Wahrnehmung), Euklidianische Entfernungen erfordern einen wahrnehmungsuniformierten kartesischen Vektorraum wie Cielab. SRGB ist keiner.

Was folgt, ist eine korrekte und vollständige Antwort:

Da dieser Thread in Suchmaschinen hoch erscheint, füge ich diese Antwort hinzu, um die verschiedenen Missverständnisse zu diesem Thema zu klären.

Helligkeit ist ein Wahrnehmungsattribut, es hat keine direkte Maßnahme.

Wahrgenommene Leichtigkeit wird durch einige Sichtmodelle wie Cielab gemessen, hier L* (LStar) ist ein Maß für Wahrnehmungsleichtigkeit, und ist nichtlinear, um die nichtlineare Reaktionskurve der menschlichen Sicht zu approximieren.

Luminanz ist ein lineares Maß für Licht, spektral gewichtet für normales Sehen, aber nicht für die nichtlineare Wahrnehmung von Leichtigkeit angepasst.

Luma ( Prime) ist ein gamma codiertes, gewichtetes Signal, das in einigen Video -Codierungen verwendet wird. Es ist nicht zu verwechseln mit linearer Leuchtdichte.

Gamma oder Transferkurve (TRC) ist eine Kurve, die häufig der Wahrnehmungskurve ähnelt und häufig auf Bilddaten für die Speicherung oder Sendung angewendet wird, um wahrgenommene Rauschen und/oder die Datenauslastung (und verwandte Gründe) zu verringern.

Wahrgenommene Leichtigkeit bestimmen, zuerst konvertieren Gamma codierte R´g´b´ Bildwerte in lineare Luminanz (L oder Y ) und dann zu nichtlinear wahrgenommener Leichtigkeit (L*)


Luminanz finden:

... weil es anscheinend irgendwo verloren ging ...

Schritt eins:

Konvertieren Sie alle SRGB 8-Bit-Ganzzahlwerte in Decimal 0,0-1.0

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

Schritt zwei:

Konvertieren Sie einen Gamma -codierten RGB in einen linearen Wert. SRGB (Computerstandard) erfordert beispielsweise eine Leistungskurve von ungefähr V^2,2, obwohl die "genaue" Transformation lautet:

sRGB to Linear

Wo V´ der Gamma-kodierte R-, G- oder B-Kanal von SRGB ist.
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));
        }
    }

Schritt drei:

Um Luminance (Y) zu finden, wenden Sie die Standardkoeffizienten für SRGB an:

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

Pseudocode unter Verwendung der oben genannten Funktionen:

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

Wahrgenommene Leichtigkeit finden:

Schritt vier:

Nehmen Sie Luminance Y von oben und transformieren Sie sich zu 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* ist ein Wert von 0 (schwarz) bis 100 (weiß), wobei 50 das Wahrnehmungs "mittlere Grau" ist. L* = 50 ist das Äquivalent von y = 18,4 oder mit anderen Worten eine 18% ige graue Karte, die die Mitte einer fotografischen Belichtung darstellt (Ansel Adams Zone V).

Verweise:

IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
Charles Poyntons Gamma -FAQ

Der HSV -Farbspace sollte den Trick machen, sehen Sie die Wikipedia -Artikel Abhängig von der Sprache, in der Sie arbeiten, erhalten Sie möglicherweise eine Bibliothekskonvertierung.

H ist Farbton, der ein numerischer Wert für die Farbe ist (dh rot, grün ...)

S ist die Sättigung der Farbe, dh wie "intensiv" es ist

V ist die "Helligkeit" der Farbe.

RGB -Luminanzwert = 0,3 r + 0,59 g + 0,11 b

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

Wenn Sie auf der Suche nach der Farbe der Farbe suchen, können Sie den euklidischen Abstand von (255, 255, 255) verwenden.

Ich denke, der RGB-Farbraum ist in Bezug auf die l2-euklidische Entfernung wahrnehmbar ungleichmäßig. Einheitliche Räume umfassen CIE Lab und Luv.

Die Inverse-Gamma-Formel von Jive Dadson muss die halbverschiebende, wenn sie in JavaScript implementiert werden, dh die Rückgabe von function gam_srgb muss int (v*255) zurückgegeben werden. nicht zurückgeben int (v*255+.5); Halbverschiebend rundet sich auf, und dies kann einen Wert auf eine R = G = B-graue Farb-Triade verursachen. Die Grauskala -Umwandlung auf einer R = G = B -Triade sollte einen Wert entsprechen. Es ist ein Beweis dafür, dass die Formel gültig ist. Sehen Neun Graustufen für die Formel in Aktion (ohne halbverhalten).

Hier ist ein bisschen C -Code, der die wahrgenommene Luminanz ordnungsgemäß berechnen sollte.

// 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
}

Ich frage mich, wie diese RGB -Koeffizienten bestimmt wurden. Ich habe selbst ein Experiment durchgeführt und endete mit Folgendem:

Y = 0.267 R + 0.642 G + 0.091 B

Nah, aber offensichtlich anders als die längst etablierten ITU -Koeffizienten. Ich frage mich, ob diese Koeffizienten für jeden Beobachter unterschiedlich sein könnten, da wir alle möglicherweise eine andere Menge an Kegeln und Stäben auf der Netzhaut in unseren Augen haben, und insbesondere das Verhältnis zwischen den verschiedenen Arten von Zapfen kann sich unterscheiden.

Als Referenz:

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

Ich habe den Test durchgeführt, indem ich schnell eine kleine graue Stange auf einen hellroten, hellgrünen und hellblauen Hintergrund bewegte und das Grau einstellte, bis es so weit wie möglich einmischt wurde. Ich wiederholte diesen Test auch mit anderen Farbtönen. Ich wiederholte den Test auf verschiedenen Displays, sogar einen mit einem festen Gamma -Faktor von 3,0, aber alles sieht mir gleich aus. Mehr vorbei, die ITU -Koeffizienten sind buchstäblich falsch für meine Augen.

Und ja, ich habe vermutlich ein normales Farbsehen.

Bitte definieren Sie die Helligkeit. Wenn Sie auf der Suche nach wie nahe an Weiß die Farbe sind, können Sie verwenden Euklidische Entfernung von (255, 255, 255)

Das 'V' von HSV ist wahrscheinlich das, wonach Sie suchen. MATLAB hat eine RGB2HSV -Funktion und der zuvor zitierte Wikipedia -Artikel ist voller Pseudocode. Wenn eine RGB2HSV -Umwandlung nicht möglich ist, wäre ein weniger genaues Modell die Graustufenversion des Bildes.

Dieser Link Erklärt alles ausführlich, einschließlich der Frage, warum diese Multiplikatorkonstanten vor den Werten r, g und b existieren.

Bearbeiten: Es hat auch eine Erklärung zu einer der Antworten hier (0,299*R + 0,587*G + 0,114*B)

Um die Helligkeit einer Farbe mit R zu bestimmen, wandelte ich die Farbe der RGB -Systemfarbe in der HSV -Systemfarbe um.

In meinem Skript verwende ich den HEX -Systemcode bereits aus anderen Gründen, aber Sie können auch mit dem RGB -Systemcode mit beginnen rgb2hsv {grDevices}. Die Dokumentation ist hier.

Hier ist dieser Teil meines Codes:

 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

Für Klarheit müssen die Formeln, die eine Quadratwurzel verwenden, sein

sqrt(coefficient * (colour_value^2))

nicht

sqrt((coefficient * colour_value))^2

Der Beweis dafür liegt in der Umwandlung einer r = g = b -Triade in die Grauskala R. Das wird nur dann wahr sein, wenn Sie den Farbwert und nicht den Koeffizienten der Farbwertzeiten quadratieren. Sehen Neun Graustufen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top