Forum: Mikrocontroller und Digitale Elektronik Farbähnlichkeit - Abstand im Farbraum


von Walter T. (nicolas)


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?

von Georg (Gast)


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

von Walter T. (nicolas)


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).

: Bearbeitet durch User
von c-hater (Gast)


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.

von Walter T. (nicolas)


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.

von foobar (Gast)


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.

von Walter T. (nicolas)


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?

von c-hater (Gast)


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...

von Walter T. (nicolas)


Lesenswert?

ielleicht habe ich auch einfach einen dummen Implementierungsfehler 
(Kapitel 7.6.1) drin. Ich gucke gerade.

von foobar (Gast)


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.

von Harry L. (mysth)


Lesenswert?

Das Problem dürfte die Gamma-Kurve sein (die bei der Initialisierung 
festgelegt wird)
Beim Schreiben wird die berücksichtigt - beim lesen nicht.

von W.S. (Gast)


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.

von c-hater (Gast)


Lesenswert?

W.S. schrieb:

> Mein Verdacht ist, daß du in deinem Treiber einen Denkfehler hast.

Das hat er hier:

Beitrag "Re: Farbähnlichkeit - Abstand im Farbraum"

Bereits als Möglichkeit eingeräumt.

Ansonsten wurde alles, was du gesagt hast, bereits zuvor als Möglichkeit 
aufgezeigt.

Nunja, es wurde bereits alles gesagt, bloß noch nicht von jedem...

von Walter T. (nicolas)


Angehängte Dateien:

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.

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

Walter T. schrieb:
> Was es mit der RGBset-Tabelle auf sich hat, interessiert mich aber immer
> noch.

Du treibst das Display mit 16-bit RGB 5-6-5, darstellen kann es aber nur 
18-bit RGB 6-6-6.
Die Lookup-Tabelle bestimmt, wie die 16-Bit "Input"-Farben auf die 
18-Bit "Display"-Farben umgesetzt werden. Da scheint mir nichts 
Geheimnisvolles dran.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Markus F. schrieb:
> Da scheint mir nichts Geheimnisvolles dran.

Wie werden sie denn umgesetzt? Ich sehe nur Indizes.

von Markus F. (mfro)


Lesenswert?

Walter T. schrieb:
> Markus F. schrieb:
>> Da scheint mir nichts Geheimnisvolles dran.
>
> Wie werden sie denn umgesetzt? Ich sehe nur Indizes.

Die Lookup-Tabelle beschreibst Du mit dem "Color Set 2Dh"-Kommando.
Danach wird jeder eingehende 5-6-5 R, G, B-Wert durch den Wert in der 
Tabelle ersetzt, bevor er ins Display-Memory geschrieben wird.

von Walter T. (nicolas)


Lesenswert?

Ich sehe in der Tabelle keinen Wert. Ich sehe nur Indizes. R005, R004, 
R003, R002, R001. Was sind das für Werte? Und was haben die mit 00000 zu 
tun?

von Markus F. (mfro)


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.

von Antoni Stolenkov (Gast)


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.

von Walter T. (nicolas)


Lesenswert?

Als Grundschüler dachte ich immer, schreiben sei schwieriger als lesen. 
Heute weiß ich, dass es andersherum ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.