Stellen Sie sich einen kontinuierlichen zweidimensionalen Pfad vor, der nur nach links, rechts oder gerade verlaufen kann, sich nicht selbst schneiden kann und ein rechteckiges Raster wie das Pixelraster in einem Bild ausfüllen muss. Wir werden diese Art von Pfad eine Schlange nennen .
Dieses vergrößerte Beispiel zeigt einen Schlangenpfad in einem 10 × 4-Raster, der rot beginnt und bei jedem Schritt den Farbton um etwa 2% erhöht, bis er violett ist. (Die schwarzen Linien sollen nur die Richtung betonen, in die sie weisen.)
Tor
Das Ziel dieses Beliebtheitswettbewerbs ist es, einen Algorithmus zu schreiben, der versucht, ein bestimmtes Bild mit einer einzelnen Schlange wiederherzustellen, deren Farbe sich kontinuierlich in kleinen Mengen ändert.
Ihr Programm muss ein Echtfarbenbild beliebiger Größe sowie einen Gleitkommawert zwischen 0 und 1 einschließlich der Toleranz aufnehmen .
Toleranz definiert den maximalen Betrag, den die Farbe der Schlange in jedem Pixelschritt ändern darf. Wir definieren den Abstand zwischen zwei RGB-Farben als den euklidischen Abstand zwischen den beiden RGB-Punkten, wenn diese auf einem RGB-Farbwürfel angeordnet sind . Der Abstand wird dann normalisiert, sodass der maximale Abstand 1 und der minimale Abstand 0 beträgt.
Farbabstand-Pseudocode: (Angenommen, alle Eingabewerte sind ganze Zahlen im Bereich [0, 255]
; Ausgabe ist normalisiert.)
function ColorDistance(r1, g1, b1, r2, g2, b2)
d = sqrt((r2 - r1)^2 + (g2 - g1)^2 + (b2 - b1)^2)
return d / (255 * sqrt(3))
Wenn das Ergebnis des Aufrufs dieser Funktion für die aktuelle Farbe der Schlange und eine andere Farbe größer als die angegebene Toleranz ist, ändert sich die Schlange möglicherweise nicht in diese andere Farbe.
Wenn Sie es vorziehen, können Sie eine andere Farbabstandsfunktion verwenden. Es muss etwas genaues und gut dokumentiertes sein, wie es unter http://en.wikipedia.org/wiki/Color_difference aufgeführt ist . Du musst es auch normalisieren, um in dir zu sein[0, 1]
, dh die maximal mögliche Entfernung muss 1 und die minimale 0 sein. Teilen Sie uns in Ihrer Antwort mit, ob Sie eine andere Entfernungsmetrik verwenden.
Bilder testen
Sie sollten natürlich Ihre Ausgabebilder veröffentlichen (und sogar Animationen der Schlange, wenn Sie möchten). Ich schlage vor, eine Vielzahl dieser Bilder mit unterschiedlichen niedrigen Toleranzen (etwa 0,005 bis 0,03) zu veröffentlichen.
Gewinnkriterien
Wie gesagt, dies ist ein Beliebtheitswettbewerb. Die am höchsten bewertete Antwort gewinnt. Antworten, die die genaueste und ästhetisch ansprechendste Darstellung der eingegebenen Bilder auf dem "Schlangenpfad" liefern, sollten bewertet werden.
Jeder Benutzer, der in böswilliger Absicht Bilder einsendet, die keine echten Schlangen sind, wird für immer disqualifiziert.
Anmerkungen
- Es darf nur ein Schlangenpfad verwendet werden, der das Bild vollständig ausfüllen muss, ohne dass dasselbe Pixel zweimal berührt wird.
- Die Schlange kann an einer beliebigen Stelle im Bild beginnen und enden.
- Die Schlange kann in jeder Farbe beginnen.
- Die Schlange muss im Bild bleiben. Die Grenzen sind nicht zyklisch.
- Die Schlange kann sich nicht diagonal oder mehr als ein Pixel gleichzeitig bewegen.
quelle
Antworten:
Python
Ich erstelle einen dynamischen Pfad, um die Farbveränderungen auf dem Weg der Schlange zu minimieren. Hier sind einige Bilder:
Toleranz = 0,01
Zyklische Farbpfade für die obigen Bilder (blau bis rot, wird bei Wiederholungen grüner):
Der Pfad wird erzeugt, indem mit einem Anfangspfad begonnen und dann 2x2 Schleifen hinzugefügt werden, bis das Bild gefüllt ist. Der Vorteil dieser Methode ist, dass die Schleifen überall auf dem Pfad hinzugefügt werden können, sodass Sie sich nicht in eine Ecke malen können und mehr Freiheit haben, den gewünschten Pfad zu erstellen. Ich verfolge die möglichen Schleifen neben dem aktuellen Pfad und speichere sie auf einem Haufen, gewichtet durch die Farbänderung entlang der Schleife. Ich löse dann die Schleife mit der geringsten Farbänderung und füge sie dem Pfad hinzu und wiederhole dies, bis das Bild gefüllt ist.
Ich verfolge die Schleifen tatsächlich alleine ('DetourBlock' im Code) und rekonstruiere dann den Pfad. Dies war ein Fehler, da es einige Sonderfälle für ungerade Breite / Höhe gibt und ich mehrere Stunden damit verbracht habe, die Rekonstruktionsmethode zu debuggen. Naja.
Die Metrik für die Pfadgenerierung muss optimiert werden, und ich habe auch eine Idee für eine bessere Einfärbung, aber ich dachte, ich würde dies zuerst herausholen, da es recht gut funktioniert. Abgesehen von diesem, der auf einigen der festgelegten Pfade besser zu sein scheint:
Hier ist der Python-Code, mit Entschuldigungen für meine schrecklichen Codierungsgewohnheiten:
Und noch ein paar Bilder mit einer sehr geringen Toleranz von 0,001 :
Und auch den tollen Wellenweg, weil er ordentlich ist:
BEARBEITEN
Die Pfaderzeugung scheint besser zu sein, wenn der Farbabstand zwischen den Durchschnittsfarben benachbarter Blöcke minimiert wird, als die Summe der Farbabstände zwischen ihren benachbarten Pixeln zu minimieren. Es hat sich außerdem herausgestellt, dass Sie die Farben von zwei toleranzkonformen Schlangenpfaden mitteln und einen anderen toleranzkonformen Schlangenpfad erhalten können. Ich gehe also beide Wege und mittle sie, wodurch viele Artefakte ausgeglichen werden. Zombie Lena und Scary Hands Mona sehen viel besser aus. Endgültige Versionen:
Toleranz 0,01 :
Toleranz 0,001 :
quelle
Java
Mein Programm generiert einen Schlangenpfad für eine bestimmte Breite und Höhe, wobei ein Algorithmus verwendet wird, der dem Algorithmus ähnelt, der die Hilbert-Kurve generiert.
(kleines Spiel: im obigen Bild beginnt die Schlange in der oberen linken Ecke. Kannst du herausfinden, wo sie endet? Viel Glück :)
Hier sind die Ergebnisse für verschiedene Toleranzwerte:
Toleranz = 0,01
Toleranz = 0,05
Toleranz = 0,1
Toleranz = 0,01
Mit 4x4 Pixelblöcken & Pfad sichtbar
Berechnung des Schlangenpfades
Ein Schlangenpfad wird in einem ganzzahligen Array mit doppelter Dimension gespeichert. Die Schlange betritt das Gitter immer an der oberen linken Ecke. Es gibt 4 grundlegende Operationen, die mein Programm auf einem bestimmten Schlangenpfad ausführen kann:
Erstellen Sie einen neuen Schlangenpfad für ein Raster mit der Breite 1 oder Höhe 1. Der Pfad ist nur eine einfache Linie, die je nach Fall von links nach rechts oder von oben nach unten verläuft.
Erhöhen Sie die Gitterhöhe, indem Sie oben einen Schlangenpfad von links nach rechts hinzufügen und dann das Gitter spiegeln (die Schlange muss immer über die obere linke Ecke in das Gitter eintreten).
Erhöhen Sie die Gitterbreite, indem Sie links einen Schlangenpfad von oben nach unten hinzufügen und dann das Gitter umdrehen (die Schlange muss immer durch die obere linke Ecke in das Gitter eintreten).
Verdoppeln Sie die Dimension des Gitters mit einem "Hilbert-Stil" -Algorithmus (siehe Beschreibung unten)
Unter Verwendung einer Reihe dieser atomaren Operationen ist das Programm in der Lage, einen Schlangenpfad beliebiger Größe zu erzeugen.
Der folgende Code berechnet (in umgekehrter Reihenfolge), welche Operationen erforderlich sind, um eine bestimmte Breite und Höhe zu erhalten. Einmal berechnet, werden die Aktionen einzeln ausgeführt, bis wir einen Schlangenpfad der erwarteten Größe erhalten.
Verdoppelung der Schlangenpfadgröße:
Der Algorithmus, der die Größe verdoppelt, funktioniert wie folgt:
Betrachten Sie diesen Knoten, der mit RECHTS und UNTEN verknüpft ist. Ich möchte seine Größe verdoppeln.
Es gibt zwei Möglichkeiten, die Größe zu verdoppeln und die gleichen Ausgänge beizubehalten (rechts und unten):
oder
Um zu bestimmen, welche zu wählen ist, muss ich für jede Knotenrichtung einen "Verschiebungs" -Wert behandeln, der angibt, ob die Ausgangstür nach links / rechts oder oben / unten verschoben ist. Ich folge dem Pfad, wie es die Schlange tun würde, und aktualisiere den Verschiebungswert entlang des Pfades. Der Verschiebungswert bestimmt eindeutig, welchen erweiterten Block ich für den nächsten Schritt verwenden muss.
quelle
Python
Hier ist ein sehr einfacher Algorithmus, mit dem Sie loslegen können. Es beginnt oben links im Bild und dreht sich im Uhrzeigersinn nach innen, um die Farbe so nah wie möglich an der Farbe des nächsten Pixels zu bringen, während die Toleranz eingehalten wird.
Es dauert ein oder zwei Minuten, um die größeren Bilder auszuführen, obwohl ich sicher bin, dass die Spirallogik erheblich optimiert werden könnte.
Ergebnisse
Sie sind interessant, aber nicht wunderschön. Erstaunlicherweise führt eine Toleranz über 0,1 zu ziemlich genau aussehenden Ergebnissen.
Die Große Welle mit einer Toleranz von 0,03:
Mona Lisa bei einer Toleranz von 0,02:
Lena bei einer Toleranz von 0,03, dann 0,01, dann 0,005, dann 0,003:
Verschiedenes mit einer Toleranz von 0,1, dann 0,07, dann 0,04 und dann 0,01:
quelle
Kobra
Füllt das Bild mit einer Schlange wie:
Dies ermöglicht eine viel schnellere Farbanpassung als nur Linien in wechselnden Richtungen, wird jedoch nicht so blockartig wie eine 3-breite Version.
Selbst bei sehr geringen Toleranzen sind die Bildränder noch sichtbar (obwohl bei kleineren Auflösungen der Detailverlust auftritt).
0,01
0,1
0,01
0,01
0,1
0,03
0,005
quelle
C #
Die Schlange beginnt am oberen linken Pixel mit der Farbe Weiß und wechselt von links nach rechts und dann von rechts nach links im Bild.
Ergebnisbildtoleranz = 0,1
quelle