Bild in ASCII-Kunst-Konvertierung - Stapelüberlauf

Wie Bitmap-Bild in ASCII-Technik unter Verwendung von C ++ konvertieren?

  • Graustufenbilder
  • Verwendung von mono-beabstandeten fonts
  • Halte es einfach (nicht zu weit fortgeschritten Sachen für Anfänger Programmierer verwenden)

Es gibt mehr Ansätze für Bild in ASCII-Art-Umwandlung, die zur Verwendung von Mono-Abstand meist basierten Schriftarten für Einfachheit ich nur zu den Wurzeln bleiben:







Pixel / Flächenintensität basiert (Shading)

Dieser Ansatz behandelt jedes Pixel des Pixelbereiches als einzelner Punkt. Die Idee ist, die durchschnittliche Grauskalaintensität dieses Punktes zu berechnen und sie dann mit nahe genug Intensität auf den berechneten einem mit Zeichen ersetzen. Dafür brauchen wir eine Liste der verwendbaren Zeichen jeweils mit vorberechneten Intensität nennen es lassen Charakter Karte. So wählen Sie schneller, welches Zeichen ist das beste für die Intensität gibt es zwei Möglichkeiten:

linear verteilte Intensitätszeichenübersicht

So verwenden wir nur Zeichen, die Intensitätsdifferenz mit dem gleichen Schritt haben. Mit anderen Worten, wenn aufsteigend sortiert dann:

Auch wenn unser Charakter Karte sortiert wird, dann können wir den Charakter direkt aus der Intensität berechnen (keine Suche erforderlich)

willkürlich verteilte Intensitätszeichenübersicht

So haben wir Reihe von verwendbaren Zeichen und die Intensitäten. Wir müssen also wieder Intensität am nächsten an der intensity_of (dot) finden, wenn wir die Karte sortiert [] wir sonst binäre Suche verwenden können wir O benötigen (n) Mindestabstand Schleife oder O (1) Wörterbuch suchen. Manchmal Einfachheit halber die Zeichenübersicht [] kann als linear geringe Gamma-Verzerrung in der Regel unsichtbar im Ergebnis verteilt behandelt werden verursacht, wenn Sie wissen, was zu suchen.

Intensität basierte Konvertierung ist groß auch für Graustufenbilder (nicht nur schwarz und weiß). Wenn Sie den Punkt als ein einzelnes Pixel wählen wird das Ergebnis groß (1 Pixel -> Zeichen) so größere Bilder ein Bereich (multiplizieren der Schriftgröße) anstelle Aspekt ausgewählt Verhältnis zu erhalten und nicht zu viel vergrößern.

  1. so gleichmäßig Bild zu unterteilen (Grauskala) Pixel oder (rechteckig) Bereiche Dot ‚s
  2. Berechnen der Intensität jedes Pixels / Gebiet
  3. ersetzen Sie es durch Zeichen aus der Zeichentabelle mit der nächsten Intensität

Als Zeichen ordnen Sie alle Zeichen verwenden können, aber das Ergebnis wird besser, wenn der Charakter Pixel gleichmäßig entlang der Zeichenbereich verteilt hat. Für den Anfang können Sie:

absteigend sortiert und so tun, linear verteilt werden.

Also, wenn Intensität der Pixel / Bereich i = <0-255> dann wird das Ersatzzeichen sein

wenn i == 0, dann ist das Pixel / Bereich schwarz ist, wenn ich 127 == dann das Pixel / Bereich ist grau, und wenn ich 255 == dann das Pixel / Bereich ist weiß. Sie können mit verschiedenen Zeichen in der Karte experimentieren [].

Hier altes Beispiel von mir in C ++ und VCL:

Sie müssen VCL Sachen ersetzen / ignorieren, wenn Sie Borland / Embarcadero-Umgebung verwenden

  • mm_log memo ist, wo der Text ausgegeben wird,
  • BMP ist Eingabe-Bitmap
  • Ansi ist VCL type string indexierter Form 1 nicht von 0 als char *.

Auf der linken Seite ist ASCII-Art-Ausgang (Schriftgröße 5px), und auf der rechten Eingangsbild Gezoomte einige Male. Wie Sie die Ausgabe größer Pixel sehen -> Charakter. wenn Sie größere Flächen anstelle von Pixeln dann ist der Zoom kleinen, aber natürlich ist der Ausgang optisch weniger ansprechend. Dieser Ansatz ist sehr einfach und schnell zu Code / Prozess.

Wenn Sie erweiterte Dinge hinzufügen:

  • automatisierte Karte Berechnungen
  • automatische Pixel / Bereichsgröße-Auswahl
  • Seitenverhältnis Korrekturen

Dann können Sie komplexere Bilder mit besseren Ergebnissen verarbeiten:

Ergeben sich hier in 1: 1-Verhältnis (zoomen, um die Zeichen zu sehen):

Bild in ASCII-Kunst-Konvertierung - Stapelüberlauf

Natürlich für Bereich verlieren Abtasten Sie die kleinen Details. Dies ist Bild der gleichen Größe wie das erste Beispiel mit Bereichen abgetastet:







Wie Sie sehen können, ist dies besser geeignet für größere Bilder

Charakterstück (Hybrid zwischen Shading und Solid ASCII Art)

Dieser Ansatz versucht Bereich (nicht mehr einzelne Bildpunkte) mit Zeichen mit ähnlicher Intensität und Form zu ersetzen. Dies führt zu besseren Ergebnissen auch bei größeren Schriftart im Vergleich zu früherem Ansatz auf der anderen Seite diesen Ansatz verwendet wird, ist ein wenig langsamer natürlich. Es gibt mehr Möglichkeiten, dies zu tun, aber die Grundidee ist es, die Differenz (Abstand) zwischen Bildbereich (Punkt) und ausgelassene Zeichen zu berechnen. Sie können mit dem naiven Summe von abs Differenz zwischen den Pixeln beginnen, aber das wird nicht sehr guten Ergebnissen führen, weil sogar eine 1-Pixel-Verschiebung wird der Abstand groß machen, sondern können Korrelation oder verschiedene Metriken verwenden. Der Gesamtalgorithmus ist fast die gleiche wie in früheren Ansatz:

  1. so gleichmäßig Bild zu unterteilen (Grauskala) rechteckige Bereiche Dot ‚s
    • idealerweise mit dem gleichen Seitenverhältnis wie gerendert Schriftzeichen (es wird Seitenverhältnis zu erhalten, vergessen Sie nicht, dass die Zeichen in der Regel ein wenig in x-Achse überlappen)
  2. Berechnen der Intensität von jedem Bereich (Punkt)
  3. ersetzen sie für Zeichen aus der Zeichentabelle mit der engsten Intensität / -form

Wie Abstand zwischen Zeichen und Punkt zu berechnen? Das ist der schwierigste Teil dieses Ansatzes. Während des Experimentieren entwickeln ich diesen Kompromiss zwischen Geschwindigkeit, Qualität und Einfachheit:

Dividieren Zeichenbereich zu den Zonen

Bild in ASCII-Kunst-Konvertierung - Stapelüberlauf

  • berechnet getrennte Intensität für links, rechts, oben, unten, und die Mittelzone der einzelnen Zeichen aus dem Alphabet Umwandlung (Karte)
  • normalisieren alle Intensitäten, so dass sie auf Größe Bereich unabhängig sind i = (i * 256) / (xs * ys)
  • Prozess Quellbild in Bereichen Rechtecks

    • (Mit dem gleichen Seitenverhältnis wie Zielfont)
    • für jede Flächenintensität in der gleichen Weise berechnen, wie in Punkt 1
    • findet die beste Übereinstimmung von Intensitäten in Umwandlung Alphabet
    • Ausgang ausgestattet Zeichen
  • Dies ist Ergebnis für font size = 7px

    Bild in ASCII-Kunst-Konvertierung - Stapelüberlauf

    Wie Sie die Ausgabe optisch ansprechend sehen können sogar mit größerer Schriftgröße verwendet (das bisherige Ansatz Beispiel war mit Größe 5px Schrift). Der Ausgang ist in etwa die gleiche Größe wie Eingangsbild (kein Zoom). Die besseren Ergebnisse erzielt werden, da die Zeichen näher an Originalbild nicht nur durch die Intensität, sondern auch durch allgemeine Form und daher können Sie größere Schriftarten verwenden und nach wie vor die Erhaltung Details (bis zu einem Punkt von groben).

    Hier vollständiger Code für die VCL basierte Konvertierung App:

    Es ist einfache Form app (Form1) mit einzelnen TMemo mm_txt drin. Es lädt Bild „pic.bmp“. dann nach Auflösung zu wählen, welchem ​​Ansatz konvertiert zu verwenden, um Text, der auf „pic.txt“ und an Memo zu visualisieren gespeichert wird. Für diejenigen ohne VCL ignorieren die VCL Sachen und ersetzen mit jedem String-Typ Ansistring Sie haben, und auch die Graphics :: TBitmap mit einem beliebigen Bitmap oder Bildklasse Ihnen zur Verfügung mit Pixelzugriffsfähigkeit haben.

    Sehr wichtiger Hinweis ist, dass diese die Einstellungen von mm_txt- verwendet> Font so stellen Sie sicher, dass Sie Folgendes einstellen:

    • Font-> Pitch = fpFixed
    • Font-> charset = OEM_CHARSET
    • Font-> Name = "System"

    zu machen, wird diese Arbeit richtig sonst die Schrift nicht als Mono-Abstand gehandhabt werden. Mausrad ändert nur die Schriftgröße nach oben / unten die Ergebnisse auf verschiedenen Schriftgrößen zu sehen

    • siehe Word-Portraits Visualisierung
    • Sprache verwenden, mit Bitmap / Dateizugriff und Textausgabefunktionen
    • dringend empfohlen, mit dem ersten Ansatz zu beginnen, da es sehr einfach, Straße nach vorn und einfach ist, und erst dann in den zweiten bewegen (die als Modifikation der ersten getan werden kann, so dass die meisten des Code bleiben, wie sowieso)
    • Es ist eine gute Idee, mit invertierten Intensität zu berechnen (schwarze Pixel ist der höchste Wert), da Standard-Text-Vorschau auf weißem Hintergrund ist damit zu viel besseren Ergebnissen führt.
    • Sie können mit der Größe, Zählung und Anordnung der Unterteilungszonen experimentieren oder eine Raster wie 3x3 stattdessen verwenden.

    Schließlich ist hier ein Vergleich zwischen den beiden Ansätzen am selben Eingang:

    Bild in ASCII-Kunst-Konvertierung - Stapelüberlauf

    Während heutige neue Fragen zu lesen bekam ich eine Idee von einem kühlen App, die Region von Desktop ausgewählt packt und es kontinuierlich Konverter asciiart füttern und das Ergebnis anzuzeigen. Nach einer Stunde Codierung es getan, und ich bin so zufrieden mit dem Ergebnis, dass ich einfach habe es hier hinzufügen.

    OK die App bestehen aus nur zwei Fenstern. Das erste Master-Fenster ist im Grunde mein altes Konverter Fenster ohne die Bildauswahl und Vorschau (alle das Zeug oben drin ist). Es hat nur die ASCII-Vorschau und Konvertierungseinstellungen. Das zweite Fenster ist leere Form mit transparentem innen für die erregende Bereichsauswahl (keine Funktionalität auch immer).

    Jetzt auf Timer packe ich nur den ausgewählten Bereich durch Auswahlformular, übergeben Sie es zur Umkehr und die asciiart Vorschau.

    So Sie Bereich einschließen möchten, dass Sie durch das Auswahlfenster und sehen das Ergebnis im Master-Fenster konvertieren. Es kann ein Spiel, Zuschauer sein. Es sieht aus wie das:

    Bild in ASCII-Kunst-Konvertierung - Stapelüberlauf

    So, jetzt kann ich sogar Videos in asciiart für Spaß beobachten. Einige sind wirklich schön :).

    Wenn Sie wollen versuchen, dies in GLSL zu sehen, dies zu implementieren:







    In Verbindung stehende Artikel