Seite 1 von 1

Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 16:03
von Quitte
Hi,

vielleicht kann hier im Python-Forum jemand helfen (obwohl die Frage eher allgemein ist)!

Ich habe zwei Farben im RGB-Format z.B. (255,0,0) , (0,0,255) und möchte Sie auf Ähnlichkeit testen!
Es soll also ein Wert ausgegeben werden, der der augenscheinlichen Ähnlichkeit entspricht (muss nicht perfekt sein)!
D.h. Ich Vergleiche Farbe1 mit Farbe3 und Farbe2 mit Farbe3 und kann dann sagen Farbe1 hat eine höhere Ähnlichkeit zu Farbe3 wie die Farbe2 zur Farbe3 hat!

Die Vergleiche die ich gemacht habe, halten nicht einmal den Grundmischungen (siehe Bild) stand (Vergleich LILA<->Weiss mit GELB<->Weiss bei linearen oder Abstandsquadrat)!
Bild


Hat jemand eine Idee??? Vielleicht ist ein Vergleich im CMYK besser?
ODer vielleicht doch in einem anderen Forum fragen???

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 16:13
von Kebap
Ich schätze, du solltest den RGB-Wert in eine aussagekräftigere Farbskala umrechnen, zB den HSV-Farbraum: http://de.wikipedia.org/wiki/HSV-Farbra ... ahrnehmung
In Fragen der Farbnachstellung wird das HSV-Paradigma gegenüber den Alternativen RGB und CMYK bevorzugt, weil es der menschlichen Farbwahrnehmung ähnelt. So fällt es leichter, die jeweils gewünschte Farbe zu finden

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 16:15
von Quitte
Das klingt schon einmal sehr gut, Gucke mir das mal an!

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 16:31
von Quitte

Code: Alles auswählen

(255, 0, 0) -->     [000, 001, 255]
(0, 255, 0) -->     [120, 001, 255]
(0, 0, 255) -->     [240, 001, 255]
(0, 0, 0) -->       [000, 000, 000]
(0, 255, 255) -->   [180, 001, 255]
(255, 0, 255) -->   [300, 001, 255]
(255, 255, 0) -->   [060, 001, 255]
(255, 255, 255) --> [000, 000, 255]
Und nun?? Wie den Vergleich genau anstellen?
Abstand berechnen mit Interpretation des Farbraum als Zylinder???

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 16:39
von deets
Ja, denn du musst ja fuer hohe V oder S (bzw. niedrige, wie rum auch immer) dafuer Sorge tragen, dass der H-Wert an Signifikanz verliert. An der Oberflaeche des Zylinders ist der wichtig, je mehr zur Spitze bzw. Mittelachse es geht, desto weniger. Da findet sich bestimmt was online...

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 16:49
von Quitte
Das sieht noch besser aus: http://de.wikipedia.org/wiki/Lab-Farbraum
Die Koordinaten des L*a*b*-Farbortes orientieren sich an den physiologischen Eigenschaften der menschlichen Wahrnehmung...
Der wesentliche Vorteil ist die visuelle Gleichabständigkeit: die geometrisch berechenbaren Abstände zweier Farborte im Lab-System entsprechen gut angenähert visuell wahrgenommenen Farbabständen.

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 16:58
von deets
Cool, kannte ich noch gar nicht.

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 17:32
von Quitte
Irgendwo ist noch der Wurm drin!

Code: Alles auswählen

def rgb2xyz(farbe):
    X = 0.4124564*farbe[0] + 0.3575761*farbe[1] + 0.1804375*farbe[2]
    Y = 0.2126729*farbe[0] + 0.7151522*farbe[1] + 0.0721750*farbe[2]
    Z = 0.0193339*farbe[0] + 0.1191920*farbe[1] + 0.9503041*farbe[2]
    return [X,Y,Z]

def xyz2lab(farbe):
    #P/P_n - Werte für große und kleine Bereiche definiert
    werte = farbe[:]
    faks = [0.95,1,1.09]
    for i in range(3):
        werte[i] = float(werte[i])/faks[i]
        if werte[i] * 24389 < 216:
            werte[i] = float(1)/116 * (float(24389)/27 * werte[i] + 16)

    
    l = 116* pow( float(werte[1]) , (1./3) ) - 16
    a = 500* ( pow( float(werte[0])/0.95 , (1./3) ) - pow( float(werte[1]) , (1./3) ) )
    b = 200* ( pow( float(werte[1]) , (1./3) ) - pow( float(werte[2])/1.09 , (1./3) ) )
    return [l,a,b]


def farbabstand(f1,f2):
    f1 = xyz2lab(rgb2xyz(f1))
    f2 = xyz2lab(rgb2xyz(f2))

    erg = 0
    for i in range(3):
        erg += pow(f1[i] - f2[i], 2)

    return int(erg)

print farbabstand([0,0,0],[255,255,255])
print farbabstand([0,0,255],[0,0,0])
Ausgabe:
460208
766287
:K

Wo ist mein Fehler???
http://de.wikipedia.org/wiki/Lab-Farbraum

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 18:55
von anogayales
Musst du da nicht noch die Wurzel ziehen?

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Dienstag 15. November 2011, 19:27
von Quitte
Ich möchte nur Ordinalsskala haben! Ich vergleiche die Farben nur und messe keinen abstand!
Wenn a^2 > b^2 dann ist auch sqrt(a^2) > sqrt(b^2)
Wurzel ziehen ist deshalb beim reinen Vergleich nicht nötig!

Ob da 460208 und 766287 oder 678 und 875 steht ist egal!
Das würde bei beiden bedeuten das Weis<->Schwarz ähnlichere Farben als Blau<->Schwarz sind, was nicht stimmt!

Aber wo ist der Fehler? Ich vermute eher einen Denkfehler!

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Donnerstag 17. November 2011, 01:25
von anogayales
gibt es für sowas keine Referenzimplementierung? Am besten da mal gucken.

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Donnerstag 17. November 2011, 09:28
von BlackJack
Weil mir die ``for i in xrange(3):``-Zeilen nicht gefallen habe ich es mal ohne geschrieben (ungetestet):

Code: Alles auswählen

from itertools import imap, izip


def cube_root(x):
    return pow(x, 1.0 / 3)


def xyz2lab(farbe):
    
    def f(value, factor):
        """P/P_n - Werte für große und kleine Bereiche definiert."""
        result = value / factor
        if result < 216.0 / 24389:
            result = (24289 * result + 432) / 3132.0
        return result
    
    x, y, z = imap(f, farbe, [0.95, 1.0, 1.09])
    
    return (
        116 * cube_root(y) - 16,
        500 * (cube_root(x / 0.95) - cube_root(y)),
        200 * (cube_root(y) - cube_root(z / 1.09))
    )


def rgb2lab(colour):
    return xyz2lab(rgb2xyz(colour))


def farbabstand(f1, f2):
    return int(sum((a - b)**2 for a, b in izip(rgb2lab(f1), rgb2lab(f2))))
Sollte natürlich nichts am Ergebnis ändern.

Re: Farbähnlichkeit (Allgemeine Programmierfrage)

Verfasst: Samstag 19. November 2011, 00:01
von Quitte
So klappt es
(habe das direkt aus einem Javaprogramm Übersetzt)

Code: Alles auswählen

def rgb2lab(farbe):
    R=farbe[0]
    G=farbe[1]
    B=farbe[2]
    
    eps = 216./24389
    k = 24389./27
    Xr = 0.964221
    Yr = 1.0
    Zr = 0.825211

    r = float(R)/255
    g = float(G)/255
    b = float(B)/255
    if r <= 0.04045:
        r = r/12
    else:
        r = pow((r+0.055)/1.055,2.4)

    if g <= 0.04045:
        g = g/12
    else:
        g = pow((g+0.055)/1.055,2.4)

    if b <= 0.04045:
        b = b/12
    else:
        b = pow((b+0.055)/1.055,2.4)

    X =  0.436052025*r     + 0.385081593*g + 0.143087414 *b
    Y =  0.222491598*r     + 0.71688606 *g + 0.060621486 *b
    Z =  0.013929122*r     + 0.097097002*g + 0.71418547  *b
		
    xr = X/Xr
    yr = Y/Yr
    zr = Z/Zr
				
    if xr > eps:
        fx =  pow(xr, 1./3)
    else:
        fx = ((k * xr + 16) / 116)
		 
    if yr > eps:
        fy =  pow(yr, 1./3)
    else:
        fy = ((k * yr + 16) / 116.)

    if zr > eps:
        fz =  pow(zr, 1./3)
    else:
        fz = ((k * zr + 16) / 116)
	
    Lss = ( 116. * fy ) - 16
    ass = 500.*(fx-fy)
    bss = 200.*(fy-fz)
		
    lab = ( 2.55*Lss + .5 , ass + .5 , bss + .5 )
    return lab
Habe damit ein Mosaik-Programm geschrieben! (Großes Bild aus kleinen Bildern erstellen)
Ergebnisse sind deutlich besser bei metapixel und man hat mehr Parameter zum einstellen (insbesondere die Größe der Einzelbilder ohne Verzerrung)
Ich kann mir nun ein paar hundert Einzelfotos bestellen und dann das Mosaikbild per Hand aus einzelnen Bilder erstellen (Programm gibt die Reihenfolge)!
Ist deutlich cooler als einfach ein Poster des Mosaik-Bildes zu bestellen (was mit dem Programm aber natürlich auch geht)

Auf alle Fälle Danke für die Hilfen!