Verwandeln Sie ein Graustufenbild mit Ihrem eigenen Algorithmus in reines Schwarzweiß.
Richtlinien: Sie müssen sich einen eigenen neuen Algorithmus ausdenken. Sie können keine vorhandenen Algorithmen (z. B. Floyd-Steinburg) verwenden, aber Sie können die allgemeine Technik verwenden. Ihr Programm muss in der Lage sein, ein Bild zu lesen und ein Bild derselben Größe zu erstellen. Dies ist ein Beliebtheitswettbewerb, bei dem jeder gewinnt, der die besten (dem Original am nächsten kommenden) und kreativsten (durch Stimmen bestimmten) Ergebnisse erzielt. Bonus, wenn der Code kurz ist, obwohl dies nicht erforderlich ist.
Sie können jedes gewünschte Graustufenbild als Eingabe verwenden. Es sollte größer als 300 x 300 sein. Jedes Dateiformat ist in Ordnung.
Beispiel Eingabe:
Beispielausgabe:
Das ist ein ziemlich guter Job, aber es gibt immer noch sichtbare Linien und Muster.
Antworten:
Fortran
Okay, ich verwende ein obskures Bildformat namens FITS, das für die Astronomie verwendet wird. Dies bedeutet, dass es eine Fortran-Bibliothek zum Lesen und Schreiben solcher Bilder gibt. ImageMagick und Gimp können auch FITS-Bilder lesen / schreiben.
Der von mir verwendete Algorithmus basiert auf "Sierra Lite" -Dithering, jedoch mit zwei Verbesserungen:
a) Ich reduziere den propagierten Fehler um einen Faktor 4/5.
b) Ich füge eine zufällige Variation in die Diffusionsmatrix ein und halte dabei ihre Summe konstant.
Zusammen beseitigen diese fast vollständig die Muster, die in dem Beispiel von OPs zu sehen sind.
Wenn Sie die CFITSIO-Bibliothek installiert haben, kompilieren Sie mit
Die Dateinamen sind fest codiert (wir konnten uns nicht die Mühe machen, dies zu beheben).
Code:
Beispielausgabe für das Welpenbild in OPs post:
OPs Beispielausgabe:
quelle
GraphicsMagick / ImageMagick
Bestellte Dither:
Bevor Sie sich über die Verwendung eines "etablierten Algorithmus" beschweren, lesen Sie bitte das ChangeLog für GraphicsMagick und ImageMagick für April 2003, in dem Sie sehen, dass ich den Algorithmus in diesen Anwendungen implementiert habe. Neu ist auch die Kombination von "-gamma .45455" mit "-ordered-dither".
Das "-gamma .45455" sorgt dafür, dass das Bild zu hell wird. Der Parameter "all" wird nur bei GraphicsMagick benötigt.
Es kommt zu Streifenbildung, da ein 4x4-Bild mit geordnetem Dither nur 17 Graustufen enthält. Das Auftreten von Streifenbildung kann durch Verwendung eines 8x8-Ordered-Dithering mit 65 Stufen reduziert werden.
Hier sind das Originalbild, die geordnete 4 x 4 und 8 x 8-Dither-Ausgabe und die Zufallsschwellenausgabe:
Ich bevorzuge die Ordered-Dither-Version, der Vollständigkeit halber jedoch auch die Random-Threshold-Version.
"10x90%" bedeutet, Pixel mit einer Intensität von unter 10 Prozent als reines Schwarz und über 90 Prozent als reines Weiß wiederzugeben, um zu vermeiden, dass in diesen Bereichen einige einsame Flecken auftreten.
Es ist wahrscheinlich erwähnenswert, dass beide so speichereffizient sind, wie sie nur sein können. Es gibt auch keine Diffusion, daher arbeiten sie pixelweise, auch wenn sie geordnete Dither-Blöcke schreiben, und müssen nichts über die benachbarten Pixel wissen. ImageMagick und GraphicsMagick verarbeiten jeweils eine Zeile, dies ist jedoch für diese Methoden nicht erforderlich. Die geordneten Dither-Konvertierungen dauern auf meinem alten x86_64-Computer weniger als 0,04 Sekunden in Echtzeit.
quelle
Ich entschuldige mich für den Codestil, den ich mithilfe einiger Bibliotheken zusammengefügt habe, die wir gerade in meiner Java-Klasse erstellt haben, und es gibt einen schlimmen Fall von Copy-Paste und magischen Zahlen. Der Algorithmus wählt zufällige Rechtecke im Bild aus und überprüft, ob die durchschnittliche Helligkeit im geditherten Bild oder im Originalbild größer ist. Anschließend wird ein Pixel ein- oder ausgeschaltet, um die Helligkeit näher an die Linie heranzuführen. Dabei werden vorzugsweise Pixel ausgewählt, die sich stärker vom Originalbild unterscheiden. Ich denke, es macht einen besseren Job, wenn dünne Details wie die Haare des Welpen hervorgehoben werden, aber das Bild ist lauter, weil es versucht, Details auch in Bereichen hervorzuheben, in denen keine vorhanden sind.
quelle
Ghostscript (mit etwas Hilfe von ImageMagick)
Weit davon entfernt, mein "eigener neuer Algorithmus" zu sein, aber ich konnte ihm leider nicht widerstehen.
Natürlich funktioniert es besser, ohne die gleiche Größe zu haben.
quelle
JAVA
Hier ist meine Vorlage. Nimmt ein JPG-Bild auf, berechnet die Helligkeit pro Pixel (dank Bonan in dieser SO-Frage) und vergleicht sie mit einem zufälligen Muster, um festzustellen, ob das resultierende Pixel schwarz oder weiß ist. Die dunkelsten Pixel sind immer schwarz und die hellsten Pixel sind immer weiß, um Bilddetails beizubehalten.
Andere Beispiele:
Funktioniert auch mit Farbbildern:
quelle
CJam
95 Bytes :)
Es wird das ASCII-PGM-Format (P2) ohne Kommentarzeile sowohl für die Eingabe als auch für die Ausgabe verwendet.
Die Methode ist sehr einfach: Sie addiert Quadrate von 2 * 2 Pixeln, konvertiert in den Bereich 0..4 und verwendet dann ein entsprechendes Muster von 4 Bits, um 2 * 2 Schwarzweißpixel zu erzeugen.
Das bedeutet auch, dass Breite und Höhe gleichmäßig sein müssen.
Probe:
Und ein Zufallsalgorithmus in nur 27 Bytes:
Es wird das gleiche Dateiformat verwendet.
Probe:
Und schließlich ein gemischter Ansatz: zufälliges Dithering mit einer Tendenz zu einem Schachbrettmuster; 44 Bytes:
Probe:
quelle
Java (1.4+)
Ich bin mir nicht sicher, ob ich das Rad hier neu erfinden werde, aber ich denke, es könnte einzigartig sein ...
Mit begrenzten Zufallsfolgen
Reines zufälliges Dithering
Stadtbild aus Averroes 'Antwort
Der Algorithmus verwendet das Konzept der lokalisierten Helligkeitsenergie und der Normalisierung, um Merkmale beizubehalten. Die ursprüngliche Version verwendete dann einen zufälligen Jitter, um einen geditherten Blick über Bereiche mit ähnlicher Leuchtkraft zu erzeugen. Es war jedoch optisch nicht so ansprechend. Um dem entgegenzuwirken, wird ein begrenzter Satz von begrenzten Zufallssequenzen auf die Helligkeit der rohen Eingangspixel abgebildet, und es werden iterativ und wiederholt Abtastwerte verwendet, um einen zitternd wirkenden Hintergrund zu erhalten.
quelle
Python
Die Idee ist folgende: Das Bild wird in
n x n
Kacheln aufgeteilt. Wir berechnen die durchschnittliche Farbe jeder dieser Kacheln. Dann ordnen wir den Farbbereich dem Bereich0 - 255
zu, der0 - n*n
uns einen neuen Wert gibtv
. Dann färben wir alle Pixel dieser Kachel schwarz und diev
Pixel in dieser Kachel weiß nach dem Zufallsprinzip . Es ist alles andere als optimal, liefert aber dennoch erkennbare Ergebnisse. Abhängig von der Auflösung funktioniert es normalerweise am besten mitn=2
odern=3
. Während inn=2
Sie sich , können Sie bereits Artefakte aus der simulierten Farbtiefe finden, für den Fall, dassn=3
es bereits etwas unscharf werden kann. Ich ging davon aus, dass die Bilder die gleiche Größe haben sollten, aber Sie können natürlich auch diese Methode verwenden und die Größe des generierten Bildes verdoppeln / verdreifachen, um mehr Details zu erhalten.PS: Ich weiß, dass ich ein bisschen zu spät zur Party komme. Ich erinnere mich, dass ich zu Beginn der Herausforderung keine Ideen hatte, aber jetzt nur diese Gehirnwelle hatte =)
Ergebnisse:
n=2:
n=3:
quelle
Definieren wir ein sehr kompaktes, theoretisches Dateiformat für diese Frage, da jedes der vorhandenen Dateiformate zu viel Overhead hat, um eine schnelle Antwort darauf zu schreiben.
Lassen Sie die ersten vier Bytes der Bilddatei die Breite und Höhe des Bildes in Pixel definieren:
gefolgt von
w * h
Graustufen-Bytes von 0 bis 255:Dann können wir ein Stück Code in Python (145 Bytes) definieren, das dieses Bild aufnimmt und Folgendes ausführt:
die "dithert", indem sie Weiß oder Schwarz mit einer Wahrscheinlichkeit zurückgibt, die gleich dem Graustufenwert dieses Pixels ist.
Auf das Beispielbild angewendet, ergibt sich so etwas:
Es ist nicht besonders hübsch, sieht aber in der Vorschau sehr ähnlich aus, und für nur 145 Python-Bytes glaube ich nicht, dass Sie viel besser werden können.
quelle
Kobra
Nimmt eine 24-Bit- oder 32-Bit-PNG / BMP-Datei auf (JPG erzeugt eine Ausgabe mit einigen Grautönen). Es ist auch erweiterbar auf Dateien, die Farbe enthalten.
Es verwendet eine geschwindigkeitsoptimierte ELA, um das Bild in 3-Bit-Farben zu zittern, die bei Eingabe des Testbilds als Schwarz / Weiß ausgegeben werden.
Habe ich schon erwähnt, dass es wirklich schnell ist?
quelle
col
und die Variableimage.setPixel(x,y,col)
bis zum Ende zu belassen, um Wiederholungen zu vermeiden ?Java
Low-Level-Code mit PNGJ und Rauschaddition plus Basisdiffusion . Diese Implementierung erfordert eine Graustufen-8-Bit-PNG-Quelle.
(Fügen Sie dieses Glas Ihrem Erstellungspfad hinzu, wenn Sie es ausprobieren möchten).
Als Bonus: Dies ist äußerst effizient bei der Speichernutzung (es werden nur drei Zeilen gespeichert), sodass es für große Bilder verwendet werden kann.
quelle
Java
Nur ein einfacher RNG-basierter Algorithmus sowie eine Logik für den Umgang mit Farbbildern. Hat die Wahrscheinlichkeit, dass b ein bestimmtes Pixel auf Weiß setzt, setzt es andernfalls auf Schwarz; Dabei ist b die ursprüngliche Helligkeit dieses Pixels.
Hier ist ein mögliches Ergebnis für das Hundebild:
quelle