Frage

Für ein Hobby-Projekt werde ich ein Programm erstellen, dass, wenn ein Bild Bitmap angegeben wird ein Kreuzstich-Muster als PDF erstellen. Ich werde auf einem Mac mit Cocoa / Objective C sein.

Die Quelle Bitmap wird in der Regel ein 24bpp Bild, aber die Millionen von Farben zur Verfügung, nur wenige existieren als Querstichfäden. Themen gibt es in verschiedenen Arten. DMC ist die am weitesten verbreitete und fast ihre gesamte Bereich ist als RGB-Werte von verschiedenen Web-Sites zur Verfügung. Hier ist eine , zum Beispiel.

DMC#  Name               R   G   B
----- ------------------ --- --- ---
blanc White              255 255 255
208   Lavender - vy dk   148  91 128
209   Lavender - dk      206 148 186
210   Lavender - md      236 207 225
211   Lavender - lt      243 218 228
      ...etc...

Mein erstes Problem, wie ich es sehe, ist von einem Startpunkt des RGB von einem Pixel im Bild die nächste Farbe aus dem DMC-Set zur Verfügung zu wählen. Was ist der beste Weg, um die nächste DMC Farbe mathematisch zu finden, und dafür zu sorgen, dass es zu einer engen Passung als Farbe ist?

Obwohl ich Cocoa verwenden werden, können Sie Pseudo-Code zu verwenden (oder sogar Java!) In einem beliebigen Code, den Sie schreiben.

War es hilfreich?

Lösung

Mit dem LAB Farbraum und finden Sie die Farbe mit dem nächsten euklidischen Abstand . Dadurch im RGB-Farbraum wird kontra-intuitive Ergebnisse. (Oder verwenden Sie die HSL Farbraum).

So iterieren nur jedes Pixel über und finden Sie die Farbe mit dem kürzesten Abstand im Farbraum Sie wählen. Beachten Sie, dass der Abstand muss berechnet werden zirkular für einige Farbräume (zum Beispiel jene, die Farbe ).

(Die meisten Farb quanization dreht sich um tatsächlich eine Palette wählen, aber das wurde bereits gesorgt, in Ihrem Fall, so können Sie die populäreren Quantisierungsverfahren nicht verwendet werden.)

Überprüfen Sie auch, diese Frage .

Um den HSB Farbton in Cocoa zu finden, es sieht aus wie Sie die getHue Methode deklariert in NSColor.h

Wenn Sie jedoch nur ein Bild zu einem Kreuzstich Design mit dieser Technik konvertieren, wird es sehr schwer sein, es tatsächlich Stich. Es wird von Single-Pixel-Farbfeldern voll sein, die von Art besiegt den Zweck des Kreuzstiches.

Andere Tipps

Das heißt Farbquantisierung , und es gibt viele Algorithmen zur Verfügung.

Ein sehr einfach ist, nur RGB-Farben als Punkte im Raum zu behandeln, und die guten alten euklidischen Abstand zwischen den Farben verwenden, um herauszufinden, wie „close“ sie sind. Dies hat Nachteile, da das menschliche Auge unterschiedliche Empfindlichkeit an verschiedenen Stellen in diesem Bereich zu erhalten, so dass ein solcher Abstand nicht entsprechen gut, wie Menschen wahrnehmen, die Farben. Sie können verschiedene Gewichtungsschemata verwenden, um diese Situation zu verbessern.

Interresting ...:)

Sie würden nicht nur die nächsten Farben identifizieren, würden Sie auch verwendet, um die Anzahl der Farben reduzieren wollen. Sie wollen nicht mit einem Stichmuster, um am Ende der Hunderte von verschiedenen Farben ...

verwendet

Ich habe einige Code zusammen, der auf einer grundlegenden Ebene tut dies. (Sorry, dass es in C # ist, ich hoffe, dass es trotzdem etwas nützlich sein kann.)

Es gibt einige weitere Optimierungen, die getan werden muss, bevor das Verfahren natürlich auch funktioniert. Die GetDistance Methode gewichtet die Bedeutung von Farbton, Sättigung und Helligkeit gegeneinander, um die beste Balance zwischen denjenigen zu finden, ist natürlich wichtig, um die Farbe zu finden, der am nächsten aussieht.

Es gibt auch eine Menge, die mit dem Verfahren zur Verringerung der Palette durchgeführt werden können. Im Beispiel nahm ich nur die am häufigsten verwendeten Farben, aber Sie wollen wahrscheinlich in gewichten, wie ähnlich die Farben in der Palette sind. Dies kann durch Auswahl der am häufigsten verwendete Farbe, reduziert die Zählung für die restlichen Farben in der Liste durchgeführt werden, abhängig von der Entfernung zur gepflückten Farbe und dann auf die Liste zurückgreifen.

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

public class Hsl {

    public string DmcNumber { get; private set; }
    public Color Color { get; private set; }
    public float Hue { get; private set; }
    public float Saturation { get; private set; }
    public float Brightness { get; private set; }
    public int Count { get; set; }

    public Hsl(Color c) {
        DmcNumber = "unknown";
        Color = c;
        Hue = c.GetHue();
        Saturation = c.GetSaturation();
        Brightness = c.GetBrightness();
        Count = 0;
    }

    public Hsl(string dmc, int r, int g, int b)
        : this(Color.FromArgb(r, g, b))
    {
        DmcNumber = dmc;
    }

    private static float AngleDifference(float a1, float a2) {
        float a = Math.Abs(a1 - a2);
        if (a > 180f) {
            a = 360f - a;
        }
        return a / 180f;
    }

    public float GetDistance(Hsl other) {
        return
            AngleDifference(Hue, other.Hue) * 3.0f +
            Math.Abs(Saturation - other.Saturation) +
            Math.Abs(Brightness - other.Brightness) * 4.0f;
    }

    public Hsl GetNearest(IEnumerable<Hsl> dmcColors) {
        Hsl nearest = null;
        float nearestDistance = float.MaxValue;
        foreach (Hsl dmc in dmcColors) {
            float distance = GetDistance(dmc);
            if (distance < nearestDistance) {
                nearestDistance = distance;
                nearest = dmc;
            }
        }
        return nearest;
    }

}

setzt Dieser Code ein (stark reduziert) Liste der DMC Farben auf, lädt ein Bild, zählt die Farben, die Palette reduziert und wandelt das Bild. Sie würden natürlich wollen auch irgendwo die Informationen aus der reduzierten Palette speichern.

Hsl[] dmcColors = {
    new Hsl("blanc", 255, 255, 255),
    new Hsl("310", 0, 0, 0),
    new Hsl("317", 167, 139, 136),
    new Hsl("318", 197, 198, 190),
    new Hsl("322", 81, 109, 135),
    new Hsl("336", 36, 73, 103),
    new Hsl("413", 109, 95, 95),
    new Hsl("414", 167, 139, 136),
    new Hsl("415", 221, 221, 218),
    new Hsl("451", 179, 151, 143),
    new Hsl("452", 210, 185, 175),
    new Hsl("453", 235, 207, 185),
    new Hsl("503", 195, 206, 183),
    new Hsl("504", 206, 221, 193),
    new Hsl("535", 85, 85, 89)
};

Bitmap image = (Bitmap)Image.FromFile(@"d:\temp\pattern.jpg");

// count colors used
List<Hsl> usage = new List<Hsl>();
for (int y = 0; y < image.Height; y++) {
    for (int x = 0; x < image.Width; x++) {
        Hsl color = new Hsl(image.GetPixel(x, y));
        Hsl nearest = color.GetNearest(dmcColors);
        int index = usage.FindIndex(h => h.Color.Equals(nearest.Color));
        if (index != -1) {
            usage[index].Count++;
        } else {
            nearest.Count = 1;
            usage.Add(nearest);
        }
    }
}

// reduce number of colors by picking the most used
Hsl[] reduced = usage.OrderBy(c => -c.Count).Take(5).ToArray();

// convert image
for (int y = 0; y < image.Height; y++) {
    for (int x = 0; x < image.Width; x++) {
        Hsl color = new Hsl(image.GetPixel(x, y));
        Hsl nearest = color.GetNearest(reduced);
        image.SetPixel(x, y, nearest.Color);
    }
}

image.Save(@"d:\temp\pattern.png", System.Drawing.Imaging.ImageFormat.Png);

erhalten die Quelle für die ppmquant Anwendung aus dem netpbm Reihe von Dienstprogrammen

Andere haben verschiedene Techniken zur Farbquantisierung hingewiesen. Es ist möglich, Techniken wie Markov Zufallsfelder zu verwenden, um zu versuchen, das System zum Schalten Garnfarben Stellen, an benachbarten Pixel zu bestrafen. Es gibt einige allgemeine Multi-Label-MRF-Bibliotheken gibt, einschließlich Boykov des .

eine von diesen zu verwenden, würde die Datenelemente die Eingangsfarben sein, die Etiketten den Satz von Fadenfarben wäre, könnten die Daten Bedingungen so etwas wie die euklidische Distanz in LAB-Raum von bzlm vorgeschlagen sein, und die Nachbarschaft Bedingungen würde bestrafen Fadenfarben umgeschaltet wird.

Je nach Bedeutung der Richtigkeit Ihrer Farboperationen, erinnern Farbraum nehmen s berücksichtigt. Während ich dies etwas studiert haben, aufgrund meiner Fotografie Hobby, ich bin immer noch ein wenig verwirrt über alles.

Aber, wie bereits erwähnt, verwendet LAB so viel wie möglich, weil (afaik) es Farbraum Agnostiker ist, während alle anderen Methoden (RGB / HSL / CMYK) nichts bedeuten (in der Theorie) ohne definierte Farbraum.

RGB, beispielsweise nur drei Prozentwerte (0-255 => 0-100%, mit 8-Bit-Farbtiefe). Also, wenn Sie einen RGB-Tripel (0,255,0) haben, übersetzen sie „nur grün, und so viel wie möglich“. So ist die Frage „wie rot ist?“. Dies ist die Frage, die einen Farbraum Antworten - sRGB 100% -grün nicht so grün ist wie AdobeRGB 100% -grün. Es ist nicht einmal die gleiche Farbton !

Sorry, wenn dies die offtopic Seite der Dinge ging

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top