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)!
Hat jemand eine Idee??? Vielleicht ist ein Vergleich im CMYK besser?
ODer vielleicht doch in einem anderen Forum fragen???
Farbähnlichkeit (Allgemeine Programmierfrage)
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
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
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]
Abstand berechnen mit Interpretation des Farbraum als Zylinder???
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...
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.
Irgendwo ist noch der Wurm drin!
Ausgabe:
460208
766287
:K
Wo ist mein Fehler???
http://de.wikipedia.org/wiki/Lab-Farbraum
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])
460208
766287
:K
Wo ist mein Fehler???
http://de.wikipedia.org/wiki/Lab-Farbraum
-
- User
- Beiträge: 456
- Registriert: Mittwoch 15. April 2009, 14:11
Musst du da nicht noch die Wurzel ziehen?
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!
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!
-
- User
- Beiträge: 456
- Registriert: Mittwoch 15. April 2009, 14:11
gibt es für sowas keine Referenzimplementierung? Am besten da mal gucken.
Weil mir die ``for i in xrange(3):``-Zeilen nicht gefallen habe ich es mal ohne geschrieben (ungetestet):
Sollte natürlich nichts am Ergebnis ändern.
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))))
So klappt es
(habe das direkt aus einem Javaprogramm Übersetzt)
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!
(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
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!