Farbähnlichkeit - Abstand im Farbraum

OP #6830119
Lesenswert?

Hallo zusammen,

ich betreibe ein ILI9341 an einem STM32F446RE. Bei dieser Kombination 
ist es ja klar, dass ich keinen Framebuffer im RAM halten kann. Ich 
nutze vorwiegend den 16-Bit RGB565-Farbmodus. Auslesen geht bei diesem 
Display-Typ nur als 24-Bit-RGB.

Ich habe ein Grafikelement (man könnte es mit einem klassischen Sprite 
vergleichen), bei dem ich den Hintergrund gegenpuffern muss/will, um 
nicht den kompletten Hintergrund jedes Mal neu aufbauen zu müssen. Also
 - Display-Bereich in 24 Bit-Farben auslesen,
 - umrechnen in 16-Bit RGB565 und puffern.
 - übermalen.

Und später
 - gepufferten Bereich wieder zurückschreiben.

Das Problem: Das Display selbst macht die Umrechnung von RGB565 in RGB24 
ein bisschen anders als ich die Umrechnung in die Gegenrichtung. Wie 
genau kann ich nicht dem Datenblatt entnehmen. Das Ergebnis ist, dass 
der zurückgeschriebene Bereich eine leicht andere Farbe als vorher hat.

Nur ist der komplette Hintergrund einer Palette aus 31 Farben entnommen. 
Fände ich die (indizierte) Farbe, die am dichtesten dran liegt, könnte 
ich daraus die exakte Farbe, wie sie vorher hineingeschrieben wurde, 
rekonstruieren.

Allerdings fehlt mir die geeignete Metrik, die "nächste" Farbe zu 
finden. der naive Ansatz wäre, die Farben auf jeweils 24 Bit zu bringen, 
voneinander komponentenweise abzuziehen und das Ergebnis zu quadrieren. 
Die Summe der Quadrate sollte in 16 Bit passen, lässt sich also für jede 
Farbe speichern. Der Farbindex mit der kleinsten Quadratsumme ist die 
ähnlichste Farbe.

Gibt es eine einfachere Metrik, um ähnliche Farben zu finden? Lässt sich 
evtl. irgendwie eine Fehlerschranke etc. definieren, um bei einer nach 
Häufigkeit sortierten Palette die Suche schon frühzeitig abbrechen zu 
können, ohne für jedes Pixel alle Fehler komplett auszurechnen?
Gast #6830126
Lesenswert?

Walter T. schrieb:
> Fände ich die (indizierte) Farbe, die am dichtesten dran liegt, könnte
> ich daraus die exakte Farbe, wie sie vorher hineingeschrieben wurde,
> rekonstruieren.

Du kannst keine Information wiederherstellen die bei der Umwandlung 
gelöscht wurde. Man kann ja auch aus einem Betrag in ganzen Euro nicht 
den Centbetrag wiederherstellen.

Georg
OP #6830145
Lesenswert?

Okay, manchmal reicht es, das Problem zu formulieren und dann eine Pause 
zu machen.

Wenn das Display die Umrechnung 16Bit -> 24Bit an jeder Stelle gleich 
macht, kann ich die Farbpalette durch Schreiben und Zurücklesen komplett 
konvertieren. Dann brauche ich nur noch auf Gleichheit zu prüfen.

Die Frage ist also nur noch, ob die Prämisse stimmt, oder ob da 
Korrekturfaktoren drin sind, um den gefühlten Kontrast zu erhöhen.

Georg schrieb:
> Du kannst keine Information wiederherstellen die bei der Umwandlung
> gelöscht wurde.

Ich will aber in die andere Richtung rekonstruieren (aus einer Liste 
exakt bekannter Beträge den passenden auswählen, der am besten zum 
gerundeten Betrag passt).
Gast #6830167
Lesenswert?

Walter T. schrieb:

> Das Problem: Das Display selbst macht die Umrechnung von RGB565 in RGB24
> ein bisschen anders als ich die Umrechnung in die Gegenrichtung.

Das ist ja sehr unschön. Aber vermutlich nicht so schwierig zu 
analysieren. Sehr wahrscheinlich wird in eine Richtung abgeschnitten und 
in die andere Richtung (auf-)gerundet. Irgendsowas. Sollte sich 
rausfinden (und dann natürlich entsprechend kompensieren) lassen.

Ist eigentlich ziemlich simpel: du schnappst dir eine der Grundfarben 
schreibst alle möglichen Werte dafür in jeweils ein Pixel, liest dann 
alle diese Pixel wieder aus und vergleichst die Ergebnisse mit dem, was 
du reingeschrieben hast (binär natürlich). Da sollte man sehr leicht das 
Schema erkennen können.

> Allerdings fehlt mir die geeignete Metrik, die "nächste" Farbe zu
> finden. der naive Ansatz wäre, die Farben auf jeweils 24 Bit zu bringen,
> voneinander komponentenweise abzuziehen und das Ergebnis zu quadrieren.

Ja, das geht. Ist aber ziemlich teuer. Und dabei nichtmal wirklich gut, 
denn es berücksichtigt die menschliche Wahrnehmung nicht.

> Gibt es eine einfachere Metrik, um ähnliche Farben zu finden?

Wirklich "einfacher" (im Sinne von: weniger rechenzeitaufwendig) leider 
nicht, aber immerhin besser auf die menschliche Wahrnehmung angepasst.

> Lässt sich
> evtl. irgendwie eine Fehlerschranke etc. definieren, um bei einer nach
> Häufigkeit sortierten Palette die Suche schon frühzeitig abbrechen zu
> können, ohne für jedes Pixel alle Fehler komplett auszurechnen?

Man kann die Sache bitweise erledigen. D.h.: zuerst beschäftigt man sich 
nur mit den höchstwertigen Bits jeder Farbkomponente und steigt dann 
nach Signifikanz ab. Damit kann man erstens den Suchraum in jeder 
Iteration ausdünnen und zweitens die möglichen Zielfarben geeignet 
vorsortieren. Letztlich läuft es auf einen trinären Baum hinaus.
OP #6830237
Lesenswert?

c-hater schrieb:
> Das ist ja sehr unschön. Aber vermutlich nicht so schwierig zu
> analysieren

Das hängt allerdings an der gleichen Prämisse, dass die Zuordnung 16Bit 
-> 24 Bit eindeutig ist. Im Moment sieht es so aus, als müsse ich diese 
fallenlassen - ich suche aber noch nach Fehlern in meinem Aufbau. 
Anscheinend hängt die zurückgelesene Farbe eines Pixels von den 
Nachbarpixeln ab.
Gast #6830269
Lesenswert?

Laut Datenblatt kann der ILI9341 eh nur RGB666.  Für die RGB565 nach 
RGB666 Wandlung gibts ne Lookup-Table (RGBSET-Cmd).  Eine Wandlung nach 
RGB888 beim Lesen macht wohl dein Treiber - der Chip liefert die nicht.
OP #6830280
Lesenswert?

foobar schrieb:
> Eine Wandlung nach
> RGB888 beim Lesen macht wohl dein Treiber - der Chip liefert die nicht.

Ich habe nie behauptet, dass das RGB888 ist. Ich lese nur 24 Bit zurück 
und es ist linksbündig. Aber vielleicht ist das sogar des Rätsels 
Lösung, dass die letzten 2 Bit einfach in der Luft hängen und hier der 
Bus frei herumklingelt. Muß ich gleich mal gucken.

foobar schrieb:
> Für die RGB565 nach
> RGB666 Wandlung gibts ne Lookup-Table (RGBSET-Cmd).

Ich habe die Tabelle auch gefunden - aber ich verstehe sie nicht. Sind 
das irgendwelche Polynome?
Gast #6830283
Lesenswert?

Walter T. schrieb:

> Anscheinend hängt die zurückgelesene Farbe eines Pixels von den
> Nachbarpixeln ab.

Das ist ja ganz fies. Aber durchaus denkbar, bedeuted sogar, dass sich 
die Display-Entwickler richtig Gedanken gemacht haben. Da steckt dann 
nämlich sehr wahrscheinlich ein Dither-Algorithmus dahinter.

Tja, dann bist du tatsächlich bei deinem Ansatz aus dem OT als 
bestmöglicher Lösung (mit den möglichen Optimierungen)

Die einzige Alternative ist: Zu jedem gezeichneten Blob musst du den 
Background, den es überdeckt, im Original verwalten. Das kostet 
natürlich Speicher, aber immerhin sehr viel weniger Speicher als ein 
vollständiger Framebuffer...
Gast #6830316
Lesenswert?

> Ich lese nur 24 Bit zurück und es ist linksbündig.

Bei den seriellen Modi sind da die unteren 2 Bits jeder Farbkomponente 
"don't care".

> Ich habe die Tabelle auch gefunden - aber ich verstehe sie nicht.

Ist einfach eine Tabelle für jede Grundfarbe 5/6 Bit -> 6 Bit.

  red[0..31]   --> 0..63
  green[0..63] --> 0..63
  blue[0..31]  --> 0..63

> Nur ist der komplette Hintergrund einer Palette aus 31 Farben

Wenn du deine eigene Palette und die des Chips abstimmst, könntest du 
(mit ein paar Einschränkungen bei der Farbauswahl) die evtl so aufbauen, 
dass z.B. die unteren 5 Bit des ausgelesenen Blaus gerade dein 
Paletten-Index ist.
Gast #6830385
Lesenswert?

Walter T. schrieb:
> Ich
> nutze vorwiegend den 16-Bit RGB565-Farbmodus. Auslesen geht bei diesem
> Display-Typ nur als 24-Bit-RGB.

Hmm... nun meine ich, daß so ein Grafikchip an der eigentlichen Farbe 
nicht herumändert, sondern lediglich aus den gelieferten 15 Bit 
Farbwerten eine Belegung in 24 Bit macht, indem die niedrigsten Bit 
entweder mit 0 aufgefüllt werden oder die höchsten Bits dorthin kopiert 
werden, um beim hellsten Farbwert auch auf die maximale 
Displayhelligkeit zu kommen.

Aber das ist alles immer gleich, also wenn du zuvor dein Icon oder 
deinen Hintergrund in 565 dort hineingeschrieben hast, dann wird das 
auch nach Auslesen und Zurückschreiben genau so wieder passieren.

Mein Verdacht ist, daß du in deinem Treiber einen Denkfehler hast. Bevor 
du nun dich ergehst in Ähnlichkeitsberechnungen, schau dir deinen Code 
für das Rücklesen und Reduzieren von 24 auf 16 Bit nochmal genau an.

W.S.
OP #6830532
Lesenswert?

Okay. Das ist peinlich. Das Problem war eine kalte Lötstelle.

Die Fehlersuche war ein Krimi - aber ein sehr langweiliger. Die 
Farbabweichungen stellten sich als zu hoher SPI-Takt heraus - wiederum 
bedingt durch eine kalte Lötstelle in der MISO-Leitung, so dass das 
Display die Leitungskapazität nicht mehr treiben konnte. Damit wurde - 
leider sehr reproduzierbar - die High-Bits immer etwas verschmiert, dass 
etwas mehr 1en empfangen als gesendet wurden. Das wiederum äußerte sich 
darin, dass die kräftigen Farben absolut korrekt aussahen, die anderen 
Farben aber tendenziell etwas zu hell.

Darauf gekommen bin ich, weil beim Gegentesten mit einem TFT-Modul mit 
8080-Interface die Farbe immer bis auf winzigste Abweichungen stimmte, 
während die Abweichungen mit dem SPI-Modul deutlich größer waren.

Die winzigen Abweichungen letztendlich ließen sich beseitigen, indem bei 
Rot und Blau jetzt immer aufgerundet wird, wenn das LSB gesetzt ist, 
anstelle abgeschnitten. Mit dem SPI-Takt bin ich jetzt auch etwas 
heruntergegangen. Das Fehlerbild war zwar harmlos, aber man braucht ja 
nicht alles auf Kante genäht.

Was es mit der RGBset-Tabelle auf sich hat, interessiert mich aber immer 
noch.
Angehängte Dateien:
#6831156
Lesenswert?

00000 sind die fünf R-Bits des 5-6-5 RGB-Wertes, den Du reinsteckst. Ans 
Display gehen dann die 6 Bits (R005 bis R000), die Du in die Tabelle als 
Ersetzungswert geschrieben hast. Kommst Du (z.B.) mit einem R-Wert von 
21 (Binär 10101) ums Eck, wird stattdessen der 6-Bit Ersatzwert des 
Tabelleneintrags 22 (R215...R210) ins Display geschrieben.
Gast #6834106
Lesenswert?

P.S.:
Die Problematik der Vorgehensweise ist nachvollziehbar, die des Aufbaus 
ist es nicht. Vielleicht doktort der TO ja am falschen Ende rum, weil 
ihn am anderen Ende ein Wackelkontakt zum Narren hält. Das ist Alles 
nicht greifbar und erzählen kann man viel.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren