Forum: Mikrocontroller und Digitale Elektronik HSV-RGB/RGB-HSV-Konvertierung ohne Umrechnungsverluste


von Ralf (Gast)


Lesenswert?

Hallo,

ich beschäftige mich grad mit der Umrechnung von HSV nach RGB.
Hier im Forum gibt's ja schon einige Beispiele dazu, u.a. auch eine von 
Benedikt K. verfasste Variante, welche ohne float-Werte zurechtkommt:
Beitrag "Re: HSV RGB Led Dimmer, C Code & Video & Doku"

Recht praktisch, da ich das in ASM auf einem 8051 machen will. 
Allerdings bräuchte ich auch den umgekehrten Weg, das heisst von RGB zu 
HSV. Mir ist klar, dass es natürlich Umrechnungsverluste gibt, wenn man 
nicht mit float o.ä. arbeitet. Diese Umrechnungsverluste an sich spielen 
keine Rolle.

Ich bräuchte aber die beiden Berechnungen so, dass es zwischen den 
Umrechnungen keine Verluste gibt.
Deswegen grübel ich gerade, ob es überhaupt Sinn macht, die Berechnungen 
auf dem Controller durchzuführen und stattdessen eher Tabellen zu 
verwenden (was auch der Geschwindigkeit zugute kommt).

Im Wikipedia-Artikel http://de.wikipedia.org/wiki/HSV-Farbraum ist u.a. 
der Zusammenhang zwischen dem RGB- und dem HSV-Farbraum gezeigt:
http://de.wikipedia.org/w/index.php?title=Datei:HSV-RGB-comparison.svg

Was für mich dort noch nicht ersichtlich ist bzw. wobei ich die Grafik 
unverständlich finde ist der Zusammenhang zwischen Value- und 
Saturation-Wert.

Hue wählt die Farbe an sich, bzw. die anteilige Zusammensetzung aus RGB.
Saturation ist die Intensität der durch Hue gewählten Farbe(n).
Value ist die Intensität gleichmäßig über alle drei Farben.
Ist das so richtig? Bringt mir ja nix, wenn ich's noch nicht exakt 
verstanden habe, vorher brauch ich gar nicht weitermachen :)

Wenn das soweit richtig wäre, dann bringt ein Tabellenansatz 
wahrscheinlich nix, denn das wären ja riesige Tabellen, da muss dann 
doch noch gerechnet werden, aber das wär erst mal nebensächlich. 
Hauptsache ich verstehe das System an sich. Über das verlustfreie 
Umrechnen kann man sich immer noch Gedanken machen.

Ralf

von Karl H. (kbuchegg)


Lesenswert?

Ralf schrieb:

> Was für mich dort noch nicht ersichtlich ist bzw. wobei ich die Grafik
> unverständlich finde ist der Zusammenhang zwischen Value- und
> Saturation-Wert.
>
> Hue wählt die Farbe an sich,

Also einen Wert am oberen Umfang des Kegels

> Saturation ist die Intensität der durch Hue gewählten Farbe(n).

die Farbsättigung.
Was man im Bild nicht (oder nur schlecht) sieht:
In der Mitte, in der Drehachse des Kegels liegen die 'unbunten' Farben. 
Also die Grauwerte, von weiß bis schwarz. Weiß ist oben und schwarz ist 
an der Spitze.
Mit Saturation bestimmst du im Grunde, wie weit dein Farbpunkt von 
dieser Drehachse entfernt ist. Je näher in der Mitte, desto unbunter ist 
deine Farbe und desto mehr hast du keine Farbe mehr, sondern einfach nur 
einen Grauwert.

> Value ist die Intensität gleichmäßig über alle drei Farben.

die Helligkeit der Farbe
Value ist die Höhe in der dein Punkt auf dem Kegel ist. Je weiter oben, 
desto mehr bist du auf deiner echten Farbe (bzw. weiß). Je weiter unten, 
desto näher bist du an Schwarz



Wenn du dich für eine Hue entschieden hast (also die Farbe), dann kann 
man da einen Schnitt durch den Kegel machen und diese Schnittfläche ist 
ein Dreick. zb bei der Hue für Rot

    Rot         <--0 Saturation
      +------------+ weiß
       \           |  o  value
        \          |  |
         \         |  |
          \        |  |
           \       |  |
            \      |  |
             \     |  v
              \    |
               \   |
                \  |
                 \ |
                  \| schwarz

Auf dieser Schnittfläche (also alle Punkte innerhalb des Dreiecks) 
liegen also alle Rot-Werte die es gibt. Von reinem Rot (links oben) bis 
zu allen Nuancen die man in Richtung weiß bzw. in Richtung schwarz 
bilden kann. An der senkrechten Kante rechts sind alle Farben dann nur 
noch Grauschattierungen.

von Karl H. (kbuchegg)


Lesenswert?

Ralf schrieb:

> Wenn das soweit richtig wäre, dann bringt ein Tabellenansatz
> wahrscheinlich nix, denn das wären ja riesige Tabellen, da muss dann
> doch noch gerechnet werden, aber das wär erst mal nebensächlich.
> Hauptsache ich verstehe das System an sich. Über das verlustfreie
> Umrechnen kann man sich immer noch Gedanken machen.

Was genau willst du machen?
Wenn es darum geht einen Farbverlauf durchzudimmen, dann kann man mit 
dem Bild im Wiki-Artikel bei "Zusammenhang HSV-RGB" die Sache deutlich 
vereinfacht machen.

von Frank (Gast)


Lesenswert?

Man kann das HSV-System auch hinsichtlich Spektrum und Wellenlänge 
interpretieren:

- Hue, die Farbe beginnt auf dem Kreis bei 0 Grad Rot (entspricht 700 
nm) und endet bei 270 Grad Blau (entspricht ungefähr 400 nm). Der 
restliche Viertelkreis ist ein Zugeständnis an eine Unzulänglichkeit des 
menschlichen Auges: Magenta. Entsteht als Sinneseindruck durch 
Überlagerung von Rot und Blau, hat aber keine Wellenlänge, weil es 
Magenta nicht als monocrhomatisches Licht gibt.

- Saturation, die Sättigung, wird manchmal auch als "Reinheit" 
interetiert. Stell dir vor, du sollst eine Wellenlänge in ein Spektrum 
von 400-700 nm einzeichenen. Du setzt einen "Nadelimpuls", dann hast du 
eine Saturation von 1, genau die eine Farbe. Machst du die Nadel breiter 
und oben rund, kommen andere Wellenlängen hinzu, die Saturation sinkt. 
Ziehst du eine waagerechte Linie durchs ganze Spektrum, hast du alle 
Farben, also keine Sättigung mehr. Je nach Höhe der Linie (Value) ists 
dann Weiss, Grau oder Schwarz ...

Verständliche Formeln gibts hier: www.easyrgb.com/index.php?X=MATH

von Fabian O. (xfr)


Lesenswert?

Von HSV nach RGB konvertieren und den RGB-Wert wieder zurück zum 
gleichen HSV-Wert geht prinzipbedingt nicht eindeutig. Denn für eine 
bestimmte Graustufe gibt es im RGB-Modell nur eine 
Darstellungsmöglichkeit (rot = grün = blau = Graustufe), im HSV-Modell 
dagegen bei 8 Bit 256 verschiedene (Helligkeit = Graustufe, Sättigung 0, 
Farbton beliebig). Bei der Konvertierung von HSV nach RGB geht bei einer 
Graustufe also die Farbton-Information verloren.

Sag am besten mal, wozu Du das brauchst, es gibt bestimmt eine andere 
Lösung. Zum Beispiel könntest Du zu einer Farbe immer beide 
Repräsentationen speichern und bei Änderungen in einem Modell (z.B. im 
HSV-Modell Farbton + 1) den neuen Wert in das jeweils andere Modell 
(also hier RGB) konvertieren, so dass beide immer "synchron" bleiben. 
Vielleicht ist es aber nicht mal nötig, sondern geht noch viel 
einfacher.

von Falk S. (falkschilling)


Lesenswert?

Hi,
ne Umwandlung von HSI nach RGB für ne Lichtsteuerung findest du auch 
hier,Maklerinnen für AVRs in ASM.

http://falk-land.com/node/14
bzw.
http://rgblightcontrol.sourceforge.net

Auf der angegeben Seite (bzw im SVN) findest du auch ne Excel-Tabelle, 
wo die Konvertierungsfehler dargestellt werden, in dem Fall für ne 
8Bit-PWM.

Mir stellt sich allerdings die Frage, wozu du präzise Umrechnungen 
benötigst. Mit LEDs kannste die Graustufen weitgehend knicken und musst 
aufgrund der nichtlinearen Helligkeitsverteilung von LEDs bzw. der 
niedrigen Quantisierungstiefe bei PWM (im Sinne von Kompromiss zwischen 
hinreichend hoher PWM-Frequenz und Bitanzahl) mit Abstrichen leben.

Soll heißen: ermittle die farbrelevanten Parameter deines Systems und 
entscheide, ob das diese Präzision überhaupt benötigt, sonst isses 
Quatsch. Z.B. Ist die Intensität bei RGB-LEDs nichtlinear - angenommen, 
eine Intensität von 127 sei maximal, dann ist 63 nicht halb so hell! Für 
normale Zwecke reichen aber einfache Approximationen locker aus.

Und auch nicht vergessen, dass du schon alleine im RGB-Farbraum 
allerhand machen kannst, vielleicht kannste dir Farbraum-Umrechnungen 
dann schon komplett klemmen.

von Ralf (Gast)


Lesenswert?

Hallo,

vielen Dank für eure Antworten.

@Karl Heinz Buchegger:
Danke für die Erläuterung. Das heisst eine Sättigung von 0 führt bei 
Value = 1 immer zu weiss, unabhängig vom Hue, richtig? So entnehme ich 
das deinem Kegelschnitt.

> Was genau willst du machen?
> Wenn es darum geht einen Farbverlauf durchzudimmen, dann kann man mit
> dem Bild im Wiki-Artikel bei "Zusammenhang HSV-RGB" die Sache deutlich
> vereinfacht machen.
Der Controller empfängt RGB-Werte und gibt diese per PWM aus. Die Idee 
war jetzt eben noch ein "Klecks Luxus", weil man mit HSV m.E. viel 
schneller zur Wunschfarbe kommt. Der Wunsch nach der "verlustfreien" 
Umrechnung war einfach die Idee, dass man ja auch mal die Werte vom 
Controller abfragen möchte, wenn jemandem eine RGB-Farbe gefällt und man 
die HSV-Werte haben möchte.

@Frank:
Die Erklärung mit Nadeln ist gut, danke! Der Link ist praktisch, da kann 
man super von-nach-Konvertierungsroutinen schreiben! Super Sache!


@Fabian O.:
> Von HSV nach RGB konvertieren und den RGB-Wert wieder zurück zum
> gleichen HSV-Wert geht prinzipbedingt nicht eindeutig.
Okay, hab ich schon befürchtet :)

> Sag am besten mal, wozu Du das brauchst, es gibt bestimmt eine andere
> Lösung.
Wie oben erwähnt, einfach dem User die Möglichkeit geben, zu einem 
RGB/HSV-Farbwert das Pendant herauszufinden.

> Zum Beispiel könntest Du zu einer Farbe immer beide Repräsentationen
> speichern und bei Änderungen in einem Modell (z.B. im
> HSV-Modell Farbton + 1) den neuen Wert in das jeweils andere Modell
> (also hier RGB) konvertieren, so dass beide immer "synchron" bleiben.
Das geht eben nicht, weil man dann die Berechnung schon gemacht hat, 
bevor der Controller die Daten bekommt - für diesen wiederum ist es ja 
nicht nötig, dass er beides kennt.

> Vielleicht ist es aber nicht mal nötig, sondern geht noch viel
> einfacher.
Ja, das geht einfacher - ich kann nämlich auch ganz frech sagen, dass es 
nur entweder-oder gibt. Also dass der Controller die Daten entweder als 
HSV oder RGB interpretiert, aber das jeweilige Pendant nicht 
zurückliefern kann. Intern kann ich ja von HSV nach RGB konvertieren 
(muss ich ja eh).
Ich denke, so werd ich das dann auch machen. Wer dann immer noch 
RGB->HSV braucht kann sich zumindest die groben RGB-Werte über die 
diversen Webseiten oder selbst mithilfe des von Frank genannten Links 
umrechnen.

Ralf

von Ralf (Gast)


Lesenswert?

@Falk:
> ne Umwandlung von HSI nach RGB für ne Lichtsteuerung findest du auch
> hier,Maklerinnen für AVRs in ASM.
Danke, schau ich gleich mal an.

> Auf der angegeben Seite (bzw im SVN) findest du auch ne Excel-Tabelle,
> wo die Konvertierungsfehler dargestellt werden, in dem Fall für ne
> 8Bit-PWM.
Das hört sich gut an, da kann ich ein Feeling für die 
Umrechnungsverluste bekommen.

> Mir stellt sich allerdings die Frage, wozu du präzise Umrechnungen
> benötigst. Mit LEDs kannste die Graustufen weitgehend knicken und musst
> aufgrund der nichtlinearen Helligkeitsverteilung von LEDs bzw. der
> niedrigen Quantisierungstiefe bei PWM (im Sinne von Kompromiss zwischen
> hinreichend hoher PWM-Frequenz und Bitanzahl) mit Abstrichen leben.
Wie gesagt, war einfach deswegen, weil ich ursprünglich eben vorhatte, 
die jeweiligen Pendants ausgeben zu können.
Stimmt, die Abstriche muss man auch noch mit einbeziehen.

> Soll heißen: ermittle die farbrelevanten Parameter deines Systems und
> entscheide, ob das diese Präzision überhaupt benötigt, sonst isses
> Quatsch. Z.B. Ist die Intensität bei RGB-LEDs nichtlinear - angenommen,
> eine Intensität von 127 sei maximal, dann ist 63 nicht halb so hell! Für
> normale Zwecke reichen aber einfache Approximationen locker aus.
Dafür verwende ich einen Ansatz hier aus dem Forum. Den Link kann ich 
mal raussuchen. Hab's grad nicht parat, wenn ich mich recht erinnere 
wird im groben die n-te Wurzel aus der PWM-Auflösung gezogen, wobei n 
die Anzahl der gewünschten Stufen ist.
Der resultierende Wert ist ein Faktor. Stufe 0 ist 0, Stufe 1 ist F^1, 
usw.
Damit hab ich ganz gute Erfahrungen gemacht.

> Und auch nicht vergessen, dass du schon alleine im RGB-Farbraum
> allerhand machen kannst, vielleicht kannste dir Farbraum-Umrechnungen
> dann schon komplett klemmen.
Mir erschien der HSV-Farbraum eben einfacher, wenn man eine bestimmte 
Farbe erzeugen möchte.

Ralf

von Fabian O. (xfr)


Lesenswert?

Ich verstehe jetzt nicht, wo das Problem liegt, den Controller beide 
Umrechungen machen zu lassen. Dann kann er von außen Farben in RGB und 
HSV annehmen und auch jede Farbe als RGB und HSV zurückliefern.

Also im Prinzip so:
1
color_rgb_t led_rgb;
2
color_hsv_t led_hsv;
3
4
void set_rgb(color_rgb_t rgb) {
5
  led_rgb = rgb;
6
  led_hsv = color_rgb_to_hsv(rgb);
7
]
8
9
color_rgb_t get_rgb(void) {
10
  return rgb;
11
}
12
13
void set_hsv(color_hsv_t hsv) {
14
  led_hsv = hsv;
15
  led_rgb = color_hsv_to_rgb(hsv);
16
]
17
18
color_hsv_t get_hsv(void) {
19
  return hsv;
20
}

Kostet drei Byte pro Farbe, die "unnötig" gespeichert sind. Wenn Dich 
das stört, dann eben so:
1
color_rgb_t led_rgb;
2
3
void set_rgb(color_rgb_t rgb) {
4
  led_rgb = rgb;
5
]
6
7
color_rgb_t get_rgb(void) {
8
  return rgb;
9
}
10
11
void set_hsv(color_hsv_t hsv) {
12
  led_rgb = color_hsv_to_rgb(hsv);
13
]
14
15
color_hsv_t get_hsv(void) {
16
  return color_rgb_to_hsv(led_rgb);
17
}

Dann ist aber nicht garantiert, dass man mit get_hsv() genau den mit 
set_hsv() gesetzten Wert zurückbekommt. Wäre in Deinem konkreten 
Anwendungsbeispiel aber ja auch nicht mal schlimm.

von Ralf (Gast)


Lesenswert?

> Ich verstehe jetzt nicht, wo das Problem liegt, den Controller beide
> Umrechungen machen zu lassen.
> Dann ist aber nicht garantiert, dass man mit get_hsv() genau den mit
> set_hsv() gesetzten Wert zurückbekommt. Wäre in Deinem konkreten
> Anwendungsbeispiel aber ja auch nicht mal schlimm.
Schlimm nicht, es dürfte optisch kaum einen Unterschied machen. 
Vielleicht implementier ich's doch noch, mal schauen. Und um Rückfragen 
der Anwender zu unterbinden, warum die Konvertierungen Abweichungen 
voneinander haben kann ich ja auf die Umrechnungen verweisen und 
erläutern, dass es prinzipbedingt Abweichungen gibt.

Ralf

von Fabian O. (xfr)


Lesenswert?

Ralf schrieb:
> Und um Rückfragen
> der Anwender zu unterbinden, warum die Konvertierungen Abweichungen
> voneinander haben kann ich ja auf die Umrechnungen verweisen und
> erläutern, dass es prinzipbedingt Abweichungen gibt.

In der ersten Variante liefert der Controller doch immer genau das 
zurück, was der Anwender vorgegeben hat.

von Karl H. (kbuchegg)


Lesenswert?

Ralf schrieb:

> voneinander haben kann ich ja auf die Umrechnungen verweisen und
> erläutern, dass es prinzipbedingt Abweichungen gibt.

Dann würde ich einfach die jeweilige Vorgabe vom Benutzer auf jeden Fall 
so speichern, wie ich sie kriege.

Kriege ich HSV, dann rechen ich RGB aus
   Will der Benutzer wieder HSV, dann kriegt er die Werte die er mir
   gegeben hat.
   Will er RGB, dann kriegt er eben die errechneten

Kriege ich RGB, dann rechne ich HSV aus
   Will der Benuter HSV, dann kriegt er die errechneten
   Will er aber RGB, dann kriegt er die, die er mir gegeben hat.

Auf die Art ist sichergestellt, dass er auf jeden Fall wieder exakt die 
Werte bekommt, die er mir auch gegeben hat und 'nur' die jeweils anderen 
eine Approximation sind.

von Ralf (Gast)


Lesenswert?

> Dann würde ich einfach die jeweilige Vorgabe vom Benutzer auf jeden Fall
> so speichern, wie ich sie kriege.
Hmmmm... das könnte klappen, die paar Bits RAM, um den Typ der Daten zu 
identifizieren könnte ich noch rausknautschen ;)

Werd ich mal so in Angriff nehmen.

Ralf

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.