Wie reduziere ich eine Bitmap auf eine bekannte Menge von RGB-Farben

8

Für ein Hobby-Projekt werde ich ein Programm erstellen, das bei Vorlage eines Bild-Bitmaps ein Kreuzstichmuster als PDF erzeugt. Ich werde Cocoa / Objective C auf einem Mac verwenden.

Die Quell-Bitmap ist normalerweise ein 24-Bit-Bild, aber von den Millionen verfügbaren Farben existieren nur einige als Kreuzstich-Threads. Threads gibt es in verschiedenen Arten. DMC ist die am weitesten verbreitete, und fast ihre gesamte Palette ist als RGB-Werte von verschiedenen Websites verfügbar. Hier ist zum Beispiel ein .

%Vor%

Mein erstes Problem, so wie ich es sehe, ist von einem Startpunkt des RGB von einem Pixel im Bild aus, wobei die nächste verfügbare Farbe aus dem DMC-Set gewählt wird. Was ist der beste Weg, um die nächste DMC-Farbe mathematisch zu finden und sicherzustellen, dass sie auch als Farbe gut passt?

Obwohl ich Cocoa verwenden werde, kannst du Pseudo-Code (oder sogar Java!) in jedem Code verwenden, den du postest.

    
banjollity 07.03.2009, 21:51
quelle

6 Antworten

10

Verwenden Sie den LAB -Farbraum und suchen Sie die Farbe mit dem nächsten euklidische Entfernung . Wenn Sie dies im RGB-Farbraum tun, erhalten Sie kontraintuitive Ergebnisse. (Oder verwenden Sie den HSL -Farbraum.)

So iterieren Sie einfach über jedes Pixel und finden Sie die Farbe mit dem kürzesten Abstand innerhalb des von Ihnen gewählten Farbraums. Beachten Sie, dass die Entfernung für einige Farbräume (z. B. solche mit Farbton ) zirkular berechnet werden muss.

(Bei der meisten Farbquantisierung dreht sich alles um die Auswahl einer Palette, aber das ist in Ihrem Fall schon erledigt, so dass Sie die populäreren Quantisierungstechniken nicht verwenden können.)

Sehen Sie sich auch diese Frage .

Um den HSB-Farbton in Cocoa zu finden, können Sie die Methode getHue in NSColor.h deklariert .

Wenn Sie jedoch ein Bild mit dieser Technik in ein Kreuzstichmuster konvertieren, ist es sehr schwierig, es zu sticken. Es wird voll von einzelnen Pixelfeldern sein, die Art besiegt den Zweck der Kreuzstich.

    
bzlm 07.03.2009, 22:07
quelle
3

Dies wird Farbquantisierung genannt, und es stehen viele Algorithmen zur Verfügung.

Eine sehr einfache Methode besteht darin, RGB-Farben nur als Punkte im Raum zu behandeln und einen einfachen alten euklidischen Abstand zwischen den Farben zu verwenden, um herauszufinden, wie "nahe" sie sind. Dies hat Nachteile, da menschliche Augen an verschiedenen Orten in diesem Raum eine unterschiedliche Empfindlichkeit aufweisen, so dass eine solche Entfernung nicht gut der menschlichen Wahrnehmung der Farben entsprechen würde. Sie können verschiedene Gewichtungsschemata verwenden, um diese Situation zu verbessern.

    
unwind 07.03.2009 22:03
quelle
2

Interessant ...:)

Sie würden nicht nur die nächsten Farben identifizieren, sondern auch die Anzahl der verwendeten Farben reduzieren. Sie wollen nicht mit einem Stickmuster enden, das Hunderte von verschiedenen Farben verwendet ...

Ich habe einen Code zusammengestellt, der das auf einer grundlegenden Ebene tut. (Tut mir leid, dass es in C # ist, ich hoffe, dass es irgendwie nützlich sein kann.)

Es gibt noch weitere Feinabstimmungen, die gemacht werden müssen, bevor die Methode gut funktioniert. Mit der GetDistance-Methode wird die Wichtigkeit von Farbton, Sättigung und Helligkeit gegeneinander gewichtet. Die beste Balance zwischen diesen ist natürlich wichtig, um die Farbe zu finden, die am nächsten kommt.

Es gibt auch eine Menge, die mit der Methode der Reduzierung der Palette getan werden kann. Im Beispiel habe ich nur die am häufigsten verwendeten Farben ausgewählt, aber Sie möchten wahrscheinlich gewichten, wie ähnlich die Farben in der Palette sind. Dazu können Sie die am häufigsten verwendete Farbe auswählen, die Anzahl der verbleibenden Farben in der Liste reduzieren, abhängig von der Entfernung zur gewählten Farbe, und dann die Liste neu sortieren.

Die Hsl-Klasse, die eine DMC-Farbe enthält, kann den Abstand zu einer anderen Farbe berechnen und die nächste Farbe in einer Liste von Farben finden:

%Vor%

Dieser Code richtet eine (stark reduzierte) Liste von DMC-Farben ein, lädt ein Bild, zählt die Farben, verkleinert die Palette und konvertiert das Bild. Sie möchten natürlich auch die Informationen aus der reduzierten Palette speichern.

%Vor%     
Guffa 08.03.2009 02:23
quelle
1

Holen Sie sich die Quelle für die ppmquant -Anwendung aus dem netpbm Dienstprogrammsatz

    
Alnitak 07.03.2009 22:17
quelle
1

Andere haben auf verschiedene Techniken zur Farbquantisierung hingewiesen. Es ist möglich, Techniken wie Markov Random Fields zu verwenden, um zu versuchen, das System zum Wechseln von Fadenfarben an benachbarten Pixelpositionen zu bestrafen. Es gibt einige generische Multi-Label-MRF-Bibliotheken, einschließlich Boykovs .

Um eines davon zu verwenden, wären die Datenelemente die Eingabefarben, die Beschriftungen wären die Garnfarben, die Datenterme könnten etwas wie die von bzlm vorgeschlagene euklidische Distanz im LAB-Raum sein, und die Nachbarschaftsbedingungen würden dies tun bestrafen Sie für das Wechseln der Fadenfarben.

    
Mr Fooz 07.03.2009 22:37
quelle
-1

Denken Sie daran, je nach Relevanz der Korrektheit Ihrer Farbfunktionen den Farbraum zu berücksichtigen. Während ich dies aufgrund meines Fotografie-Hobbys etwas studiert habe, bin ich immer noch etwas verwirrt.

Aber, wie bereits erwähnt, benutze LAB so viel wie möglich, weil (afaik) der Farbraum agnostisch ist, während alle anderen Methoden (RGB / HSL / CMYK) nichts (theoretisch) ohne einen definierten Farbraum bedeuten.

RGB zum Beispiel sind nur drei Prozentwerte (0-255 = & gt; 0-100%, mit einer Farbtiefe von 8 Bit). Wenn Sie also ein RGB-Triplet von (0,255,0) haben, bedeutet das "nur grün und so viel wie möglich". Die Frage ist also: "Wie rot ist rot?". Das ist die Frage, die ein Farbraum beantwortet - sRGB 100% -grün ist nicht so grün wie AdobeRGB 100% -grün. Es ist nicht einmal der gleiche Farbton !

Tut mir leid, wenn das auf die offtopische Seite der Dinge ging

    
Henrik Paul 07.03.2009 22:36
quelle

Tags und Links