Twitter Bildcodierungs-Herausforderung [geschlossen]


597

Wenn ein Bild 1000 Wörter wert ist, wie viel von einem Bild können Sie in 140 Zeichen passen?

Hinweis : Das ist es Leute! Die Bounty-Frist ist da, und nach einigen harten Überlegungen habe ich entschieden, dass Boojums Eintrag Sam Hocevars kaum übertrifft . Ich werde detailliertere Notizen veröffentlichen, sobald ich die Gelegenheit hatte, sie aufzuschreiben. Natürlich sollte sich jeder frei fühlen, weiterhin Lösungen einzureichen und Lösungen zu verbessern, über die die Menschen abstimmen können. Vielen Dank an alle, die eingereicht und eingereicht haben; Ich habe sie alle genossen. Das Laufen hat mir sehr viel Spaß gemacht und ich hoffe, es hat sowohl den Teilnehmern als auch den Zuschauern Spaß gemacht.

Ich bin auf diesen interessanten Beitrag gestoßen, in dem versucht wurde, Bilder in einen Twitter-Kommentar zu komprimieren, und viele Leute in diesem Thread (und einem Thread auf Reddit ) hatten Vorschläge, wie Sie dies tun könnten. Ich denke, es wäre eine gute Herausforderung beim Codieren. Lassen Sie die Leute ihr Geld dort einsetzen, wo ihr Mund ist, und zeigen Sie, wie ihre Ideen zur Codierung auf dem begrenzten Platz, den Sie zur Verfügung haben, zu mehr Details führen können.

Ich fordere Sie auf, ein Allzwecksystem zu entwickeln, mit dem Bilder in Twitter-Nachrichten mit 140 Zeichen codiert und erneut in ein Bild decodiert werden können. Sie können Unicode-Zeichen verwenden, sodass Sie mehr als 8 Bit pro Zeichen erhalten. Selbst wenn Sie Unicode-Zeichen zulassen, müssen Sie Bilder auf kleinstem Raum komprimieren. Dies wird sicherlich eine verlustbehaftete Komprimierung sein, und daher muss subjektiv beurteilt werden, wie gut jedes Ergebnis aussieht.

Hier ist das Ergebnis, das der ursprüngliche Autor, Quasimondo , aus seiner Codierung erhalten hat (das Bild ist unter einer Creative Commons Attribution-Noncommercial-Lizenz lizenziert ): Mona Lisa

Kannst du es besser machen?

Regeln

  1. Ihr Programm muss zwei Modi haben: Codierung und Decodierung .
  2. Bei der Codierung :
    1. Ihr Programm muss eine Grafik in einem angemessenen Raster- Grafikformat Ihrer Wahl als Eingabe verwenden . Wir werden sagen, dass jedes von ImageMagick unterstützte Rasterformat als angemessen gilt.
    2. Ihr Programm muss eine Nachricht ausgeben, die in 140 oder weniger Unicode-Codepunkten dargestellt werden kann. 140 Codepunkte im Bereich U+0000- U+10FFFF, ohne nicht-Zeichen ( U+FFFE, U+FFFF, U+nFFFE , U+nFFFF , wo n ist 1- 10hexadezimal, und der Bereich U+FDD0- U+FDEF) sowie Ersatzcodepunkte ( U+D800- U+DFFF). Es kann in einer angemessenen Codierung Ihrer Wahl ausgegeben werden. Jede von GNUiconv unterstützte Codierung wird als angemessen angesehen, und Ihre native Plattform- oder Gebietsschema-Codierung ist wahrscheinlich eine gute Wahl. Weitere Informationen finden Sie in den folgenden Unicode-Hinweisen .
  3. Beim Dekodieren :
    1. Ihr Programm sollte die Ausgabe Ihres Codierungsmodus als Eingabe verwenden .
    2. Ihr Programm muss ein Bild in einem angemessenen Format Ihrer Wahl ausgeben, wie oben definiert, obwohl die Ausgabevektorformate ebenfalls in Ordnung sind.
    3. Die Bildausgabe sollte eine Annäherung an das Eingabebild sein; Je näher Sie dem Eingabebild kommen, desto besser.
    4. Der Decodierungsprozess hat möglicherweise keinen Zugriff auf eine andere Ausgabe des Codierungsprozesses als die oben angegebene Ausgabe. Das heißt, Sie können das Bild nicht irgendwo hochladen und die URL für den Dekodierungsprozess zum Herunterladen oder ähnliches ausgeben.
  4. Aus Gründen der Konsistenz der Benutzeroberfläche muss sich Ihr Programm wie folgt verhalten:

    1. Ihr Programm muss ein Skript sein, das auf einer Plattform mit dem entsprechenden Interpreter als ausführbar festgelegt werden kann, oder ein Programm, das zu einer ausführbaren Datei kompiliert werden kann.
    2. Ihr Programm muss entweder als erstes Argument encodeoder decodezum Festlegen des Modus verwenden.
    3. Ihr Programm muss auf eine oder mehrere der folgenden Arten Eingaben vornehmen (wenn Sie die implementieren, die Dateinamen verwendet, können Sie auch von stdin und stdout lesen und schreiben, wenn Dateinamen fehlen):

      1. Nehmen Sie Eingaben von Standard-In und erzeugen Sie Ausgabe von Standard-Out.

        my-program encode <input.png >output.txt
        my-program decode <output.txt >output.png
        
      2. Nehmen Sie Eingaben aus einer im zweiten Argument genannten Datei und erzeugen Sie Ausgaben in der im dritten Argument genannten Datei.

        my-program encode input.png output.txt
        my-program decode output.txt output.png
        
  5. Für Ihre Lösung schreiben Sie bitte:
    1. Ihr vollständiger Code und / oder ein Link dazu, der an anderer Stelle gehostet wird (wenn er sehr lang ist oder viele Dateien zum Kompilieren benötigt oder so).
    2. Eine Erklärung, wie es funktioniert, wenn es nicht sofort aus dem Code ersichtlich ist oder wenn der Code lang ist und die Leute an einer Zusammenfassung interessiert sind.
    3. Ein Beispielbild mit dem Originalbild, dem zu komprimierenden Text und dem dekodierten Bild.
    4. Wenn Sie auf einer Idee aufbauen, die jemand anderes hatte, schreiben Sie ihn bitte zu. Es ist in Ordnung zu versuchen, die Idee eines anderen zu verfeinern, aber Sie müssen ihn zuschreiben.

Richtlinien

Dies sind im Grunde genommen Regeln, gegen die verstoßen werden kann, Vorschläge oder Bewertungskriterien:

  1. Ästhetik ist wichtig. Ich werde urteilen und vorschlagen, dass andere Leute urteilen, basierend auf:
    1. Wie gut das Ausgabebild aussieht und wie sehr es dem Original ähnelt.
    2. Wie schön der Text aussieht. Völlig zufälliges Gobbledigook ist in Ordnung, wenn Sie ein wirklich cleveres Komprimierungsschema haben, aber ich möchte auch Antworten sehen, die Bilder in mehrsprachige Gedichte verwandeln, oder so etwas Kluges. Beachten Sie, dass der Autor der ursprünglichen Lösung beschlossen hat, nur chinesische Schriftzeichen zu verwenden, da dies so besser aussah.
    3. Interessanter Code und clevere Algorithmen sind immer gut. Ich mag kurzen, präzisen und klaren Code, aber auch wirklich clevere, komplizierte Algorithmen sind in Ordnung, solange sie gute Ergebnisse liefern.
  2. Geschwindigkeit ist ebenfalls wichtig, wenn auch nicht so wichtig wie die Komprimierung des Bildes. Ich hätte lieber ein Programm, das ein Bild in einer Zehntelsekunde konvertieren kann, als etwas, das tagelang genetische Algorithmen ausführt.
  3. Ich werde kürzere Lösungen längeren vorziehen, solange sie in ihrer Qualität einigermaßen vergleichbar sind. Prägnanz ist eine Tugend.
  4. Ihr Programm sollte in einer Sprache implementiert sein, die unter Mac OS X, Linux oder Windows frei verfügbar ist. Ich würde gerne die Programme ausführen können, aber wenn Sie eine großartige Lösung haben, die nur unter MATLAB oder so läuft , ist das in Ordnung.
  5. Ihr Programm sollte so allgemein wie möglich sein. Es sollte für so viele verschiedene Bilder wie möglich funktionieren, obwohl einige möglicherweise bessere Ergebnisse erzielen als andere. Bestimmtes:
    1. Es ist ziemlich lahm, ein paar Bilder in das Programm eingebaut zu haben, mit denen es übereinstimmt und auf die es verweist, und dann beim Entschlüsseln das passende Bild zu erzeugen. Es deckt nur wenige Bilder ab.
    2. Ein Programm, das Bilder von einfachen, flachen, geometrischen Formen aufnehmen und in ein Vektorprimitiv zerlegen kann, ist ziemlich geschickt, aber wenn es bei Bildern ab einer bestimmten Komplexität fehlschlägt, ist es wahrscheinlich nicht allgemein genug.
    3. Ein Programm, das nur Bilder mit einem bestimmten festen Seitenverhältnis aufnehmen kann, aber gute Arbeit damit leistet, wäre ebenfalls in Ordnung, aber nicht ideal.
    4. Möglicherweise stellen Sie fest, dass ein Schwarzweißbild mehr Informationen auf kleinerem Raum als ein Farbbild liefert. Auf der anderen Seite kann dies die Bildtypen einschränken, auf die es anwendbar ist. Gesichter kommen in Schwarz und Weiß gut zur Geltung, aber abstrakte Designs schneiden möglicherweise nicht so gut ab.
    5. Es ist vollkommen in Ordnung, wenn das Ausgabebild kleiner als das Eingabebild ist und ungefähr das gleiche Verhältnis aufweist. Es ist in Ordnung, wenn Sie das Bild vergrößern müssen, um es mit dem Original zu vergleichen. Wichtig ist, wie es aussieht.
  6. Ihr Programm sollte eine Ausgabe produzieren, die tatsächlich über Twitter gesendet werden kann und unversehrt bleibt. Dies ist nur eine Richtlinie und keine Regel, da ich keine Dokumentation zu den genauen unterstützten Zeichensätzen finden konnte, aber Sie sollten wahrscheinlich Steuerzeichen, funky unsichtbare Kombinationszeichen, Zeichen für den privaten Gebrauch und dergleichen vermeiden.

Bewertungsrubrik

Nehmen wir als allgemeinen Leitfaden für die Einstufung von Lösungen bei der Auswahl meiner akzeptierten Lösung an, dass ich wahrscheinlich Lösungen auf einer 25-Punkte-Skala bewerten werde (dies ist sehr grob und ich werde nichts direkt bewerten, nur mit dies als grundlegende Richtlinie):

  • 15 Punkte dafür, wie gut das Codierungsschema eine Vielzahl von Eingabebildern wiedergibt. Dies ist ein subjektives, ästhetisches Urteil
    • 0 bedeutet, dass es überhaupt nicht funktioniert, es gibt jedes Mal das gleiche Bild zurück oder so
    • 5 bedeutet, dass einige Bilder codiert werden können, obwohl die decodierte Version hässlich aussieht und bei komplizierteren Bildern möglicherweise überhaupt nicht funktioniert
    • 10 bedeutet, dass es mit einer Vielzahl von Bildern arbeitet und angenehm aussehende Bilder erzeugt, die gelegentlich unterscheidbar sein können
    • 15 bedeutet, dass es perfekte Nachbildungen einiger Bilder erzeugt und selbst bei größeren und komplexeren Bildern etwas erkennbares ergibt. Oder es macht vielleicht keine Bilder, die gut erkennbar sind, sondern schöne Bilder, die eindeutig vom Original abgeleitet sind.
  • 3 Punkte für die geschickte Verwendung des Unicode-Zeichensatzes
    • 0 Punkte für die einfache Verwendung des gesamten Satzes zulässiger Zeichen
    • 1 Punkt für die Verwendung eines begrenzten Satzes von Zeichen, die für die Übertragung über Twitter oder in einer größeren Vielfalt von Situationen sicher sind
    • 2 Punkte für die Verwendung einer thematischen Teilmenge von Zeichen, z. B. nur Han-Ideogramme oder nur Zeichen von rechts nach links
    • 3 Punkte, um etwas wirklich Ordentliches zu tun, z. B. lesbaren Text zu generieren oder Zeichen zu verwenden, die wie das betreffende Bild aussehen
  • 3 Punkte für clevere algorithmische Ansätze und Codestil
    • 0 Punkte für 1000 Codezeilen, um das Bild zu verkleinern, als 1 Bit pro Pixel zu behandeln und base64 zu codieren
    • 1 Punkt für etwas, das eine Standardcodierungstechnik verwendet und gut geschrieben und kurz ist
    • 2 Punkte für etwas, das eine relativ neuartige Codierungstechnik einführt oder das überraschend kurz und sauber ist
    • 3 Punkte für einen Einzeiler, der tatsächlich gute Ergebnisse liefert, oder etwas, das neue Wege in der Grafikcodierung beschreitet (wenn dies wie eine geringe Anzahl von Punkten für Neuland erscheint, denken Sie daran, dass ein so gutes Ergebnis wahrscheinlich eine hohe Punktzahl für die Ästhetik hat auch)
  • 2 Punkte für Geschwindigkeit. Wenn alles andere gleich ist, ist schneller besser, aber die oben genannten Kriterien sind alle wichtiger als die Geschwindigkeit
  • 1 Punkt für die Ausführung auf freier (Open Source) Software, da ich freie Software bevorzuge (beachten Sie, dass C # für diesen Punkt weiterhin berechtigt ist, solange es auf Mono ausgeführt wird, ebenso wäre MATLAB-Code zulässig, wenn es auf GNU Octave ausgeführt wird).
  • 1 Punkt für die tatsächliche Einhaltung aller Regeln. Diese Regeln sind etwas umfangreich und kompliziert geworden, daher werde ich wahrscheinlich ansonsten gute Antworten akzeptieren, bei denen ein kleines Detail falsch ist, aber ich werde jeder Lösung, die tatsächlich allen Regeln folgt, einen zusätzlichen Punkt geben

Referenzbilder

Einige Leute haben nach Referenzbildern gefragt. Hier sind einige Referenzbilder, die Sie ausprobieren können. Hier sind kleinere Versionen eingebettet, die alle auf größere Versionen des Bildes verweisen, wenn Sie diese benötigen:

Lena Mona Lisa Cornell Box StackOverflow-Logo

Preis

Ich biete eine Prämie von 500 Wiederholungen (plus die 50, die StackOverflow einsetzt) ​​für die Lösung an, die mir am besten gefällt, basierend auf den oben genannten Kriterien. Natürlich ermutige ich alle anderen, auch hier über ihre Lieblingslösungen abzustimmen.

Hinweis zur Frist

Dieser Wettbewerb läuft, bis das Kopfgeld aufgebraucht ist, am Samstag, den 30. Mai, gegen 18 Uhr. Ich kann nicht genau sagen, wann es enden wird. Es kann zwischen 17 und 19 Uhr sein. Ich werde garantieren, dass ich alle bis 14 Uhr eingereichten Beiträge einsehen werde, und ich werde mein Bestes tun, um alle bis 16 Uhr eingereichten Beiträge zu prüfen. Wenn danach Lösungen eingereicht werden, habe ich möglicherweise keine Chance, sie fair zu betrachten, bevor ich meine Entscheidung treffen muss. Je früher Sie einreichen, desto größer ist auch die Chance, dass Sie abstimmen können, um mir bei der Auswahl der besten Lösung zu helfen. Versuchen Sie also, früher als rechtzeitig einzureichen.

Unicode-Notizen

Es gab auch einige Unklarheiten darüber, welche Unicode-Zeichen genau zulässig sind. Der Bereich möglicher Unicode-Codepunkte liegt U+0000bei U+10FFFF. Es gibt einige Codepunkte, deren Verwendung als Unicode-Zeichen in einem offenen Datenaustausch niemals gültig ist. das sind die noncharacters und die Surrogat - Codepunkte . Noncharacters ist in dem definierten Unidode Norm 5.1.0 Abschnitt 16.7 als die Werte U+FFFE, U+FFFF, U+nFFFE , U+nFFFF , wo n ist 1- 10hexadezimal, und der Bereich U+FDD0-U+FDEF. Diese Werte sind für die anwendungsspezifische interne Verwendung vorgesehen, und konforme Anwendungen können diese Zeichen aus dem von ihnen verarbeiteten Text entfernen. Ersatzcodepunkte, die im Unicode Standard 5.1.0 Abschnitt 3.8 als U+D800- definiert sind U+DFFF, werden zum Codieren von Zeichen verwendet, die über die mehrsprachige Grundebene in UTF-16 hinausgehen. Daher ist es unmöglich, diese Codepunkte direkt in der UTF-16-Codierung darzustellen, und es ist ungültig, sie in einer anderen Codierung zu codieren. Für den Zweck dieses Wettbewerbs erlaube ich daher jedem Programm, das Bilder in eine Folge von nicht mehr als 140 Unicode-Codepunkten aus dem Bereich codiert U+0000- U+10FFFFmit Ausnahme aller oben definierten Nichtzeichen und Ersatzpaare.

Ich werde Lösungen bevorzugen , die nur zugewiesene Zeichen verwenden, und noch bessere, die clevere Teilmengen von zugewiesenen Zeichen verwenden oder mit dem von ihnen verwendeten Zeichensatz etwas Interessantes tun. Eine Liste der zugewiesenen Zeichen finden Sie in der Unicode- Zeichendatenbank . Beachten Sie, dass einige Zeichen direkt aufgeführt sind, während andere nur als Anfang und Ende eines Bereichs aufgeführt sind. Beachten Sie auch, dass Ersatzcodepunkte in der Datenbank aufgeführt sind, jedoch wie oben erwähnt verboten sind. Wenn Sie bestimmte Eigenschaften von Zeichen nutzen möchten, um den von Ihnen ausgegebenen Text interessanter zu gestalten, stehen verschiedene Datenbanken mit Zeicheninformationen zur Verfügung, z. B. eine Liste benannter Codeblöcke und verschiedene Zeicheneigenschaften.

Da Twitter nicht den genauen Zeichensatz angibt, den sie unterstützen, werde ich bei Lösungen, die mit Twitter nicht funktionieren, nachsichtig sein, da bestimmte Zeichen zusätzlich zählen oder bestimmte Zeichen entfernt werden. Es wird bevorzugt, aber nicht benötigt, dass alle codierten Ausgaben unbeschadet über Twitter oder einen anderen Microblogging-Dienst wie identi.ca übertragen werden können . Ich habe einige Dokumentationen gesehen, die besagen, dass Twitter-Entitäten <,> und & codieren und diese daher als 4, 4 bzw. 5 Zeichen zählen, aber ich habe das nicht selbst getestet, und ihr JavaScript-Zeichenzähler scheint nicht zu sein um sie so zu zählen.

Tipps & Links

  • Die Definition gültiger Unicode-Zeichen in den Regeln ist etwas kompliziert. Die Auswahl eines einzelnen Zeichenblocks, z. B. CJK Unified Ideographs (U + 4E00 - U + 9FCF), ist möglicherweise einfacher.
  • Sie können vorhandene Bildbibliotheken wie ImageMagick oder Python Imaging Library für Ihre Bildbearbeitung verwenden.
  • Wenn Sie Hilfe zum Verständnis des Unicode-Zeichensatzes und seiner verschiedenen Codierungen benötigen, lesen Sie diese Kurzanleitung oder diese ausführlichen FAQ zu UTF-8 unter Linux und Unix .
  • Je früher Sie Ihre Lösung erhalten, desto mehr Zeit muss ich (und andere abstimmende Personen) damit verbringen. Sie können Ihre Lösung bearbeiten, wenn Sie sie verbessern. Ich werde mein Kopfgeld auf die neueste Version stützen, wenn ich die Lösungen zum letzten Mal durchschaue.
  • Wenn Sie ein einfaches Bildformat zum Parsen und Schreiben wünschen (und nicht nur ein vorhandenes Format verwenden möchten), würde ich die Verwendung des PPM-Formats empfehlen . Es ist ein textbasiertes Format, mit dem man sehr einfach arbeiten kann, und Sie können ImageMagick verwenden , um es zu konvertieren.

Sie können gerne Vorschläge zu den Regeln machen, die ich in den Kommentaren geschrieben habe. Ich bin auf jeden Fall bereit, sie zu optimieren, wenn die Leute das Gefühl haben, dass sie einer Klärung bedürfen oder zu überbestimmt sind.
Brian Campbell

6
Sie sollten wahrscheinlich sagen, dass das Hochladen des Bildes auf einen Server und das Posten der URL nicht gültig ist.
Shay Erlichmen

2
@Shay Habe ich das nicht schon gesagt? "Der Dekodierungsprozess hat möglicherweise keinen Zugriff auf eine andere Ausgabe des Kodierungsprozesses als die oben angegebene. Das heißt, Sie können das Bild nicht irgendwo hochladen und die URL für den Dekodierungsprozess zum Herunterladen oder ähnliches ausgeben . "
Brian Campbell

1
@Konrad Rudolph Ich stimme zu; Ich meinte aus praktischer Sicht nicht "albern" (klar, dieser ganze Wettbewerb ist aus praktischer Sicht albern), ich meinte im Kontext dieses Wettbewerbs "albern". Die Verwendung eines URI ist im Sinne der Informationstheorie kein wirklicher Komprimierungsalgorithmus, da Sie damit keine weiteren Informationen übertragen können, ohne einfach einen alternativen Kanal zu verwenden. Sie könnten dem Codierer und Decodierer eine große Datenbank mit Bildern geben und sie als Komprimierung bezeichnen, die nur für eine begrenzte Anzahl von Bildern funktioniert. Ich habe jedoch angegeben, dass Sie in der Lage sein müssen, ein beliebiges Bild zu verarbeiten.
Brian Campbell

2
Hier sind einige Links, auf die ich gestoßen bin, die den Leuten helfen können: azillionmonkeys.com/qed/unicode.html für eine Erklärung des gültigen Bereichs von Unicode-Zeichen. Beachten Sie, dass die UTF-Codierungen den gesamten Unicode-Bereich codieren können. UCS-4 ist eine Obermenge von Unicode, und UCS-2 und ASCII sind Teilmengen. Und in Bezug auf die Komprimierung ist hier eine ähnliche Technik wie im ursprünglichen Beitrag, obwohl er sich 1 KB statt 350 Byte erlaubt: schreiendeck.com/Article.php?ArticleID=46&Show=ABCE
Brian Campbell

Antworten:


244

Okay, hier ist meine: nanocrunch.cpp und die Datei CMakeLists.txt , um sie mit CMake zu erstellen . Für den größten Teil der Bildverarbeitung wird die Magick ++ ImageMagick-API verwendet. Für die Zeichenfolgencodierung ist außerdem die GMP- Bibliothek für die Bignum-Arithmetik erforderlich .

Ich habe meine Lösung auf der fraktalen Bildkomprimierung mit ein paar einzigartigen Wendungen basiert. Die Grundidee besteht darin, das Bild aufzunehmen, eine Kopie auf 50% zu verkleinern und nach Stücken in verschiedenen Ausrichtungen zu suchen, die nicht überlappenden Blöcken im Originalbild ähneln. Diese Suche erfordert einen sehr brutalen Ansatz, aber das macht es einfacher, meine Modifikationen einzuführen.

Die erste Modifikation ist, dass mein Programm nicht nur 90-Grad-Rotationen und -Flips betrachtet, sondern auch 45-Grad-Orientierungen berücksichtigt. Es ist ein Bit mehr pro Block, aber es verbessert die Bildqualität immens.

Die andere Sache ist, dass das Speichern einer Kontrast- / Helligkeitsanpassung für jede Farbkomponente jedes Blocks viel zu teuer ist. Stattdessen speichere ich eine stark quantisierte Farbe (die Palette hat nur 4 * 4 * 4 = 64 Farben), die einfach in einem bestimmten Verhältnis eingeblendet wird. Mathematisch entspricht dies einer variablen Helligkeit und einer konstanten Kontrastanpassung für jede Farbe. Leider bedeutet dies auch, dass es keinen negativen Kontrast gibt, um die Farben umzudrehen.

Sobald die Position, Ausrichtung und Farbe für jeden Block berechnet wurde, wird diese in eine UTF-8-Zeichenfolge codiert. Zunächst wird ein sehr großes Bignum generiert, um die Daten in der Blocktabelle und die Bildgröße darzustellen. Der Ansatz hierfür ähnelt der Lösung von Sam Hocevar - eine Art große Zahl mit einem Radix, der je nach Position variiert.

Dann wandelt es das in eine Basis um, unabhängig von der Größe des verfügbaren Zeichensatzes. Standardmäßig wird der zugewiesene Unicode-Zeichensatz vollständig verwendet, abzüglich der Zeichen für "kaufmännisches Und", "Steuern", "Kombinieren" sowie "Ersatz" und "Privat". Es ist nicht schön, aber es funktioniert. Sie können auch die Standardtabelle auskommentieren und stattdessen druckbares 7-Bit-ASCII (wiederum ohne <,> und & Zeichen) oder CJK Unified Ideographs auswählen. In der Tabelle, für die Zeichencodes verfügbar sind, wird eine Lauflänge gespeichert, die mit abwechselnden Läufen ungültiger und gültiger Zeichen codiert ist.

Wie auch immer, hier sind einige Bilder und Zeiten (gemessen auf meinem alten 3,0-GHz-P4), die im oben beschriebenen vollständig zugewiesenen Unicode-Satz auf 140 Zeichen komprimiert wurden. Insgesamt bin ich ziemlich zufrieden mit dem Ergebnis. Wenn ich mehr Zeit hätte, um daran zu arbeiten, würde ich wahrscheinlich versuchen, die Blockade der dekomprimierten Bilder zu verringern. Trotzdem denke ich, dass die Ergebnisse für das extreme Kompressionsverhältnis ziemlich gut sind. Die dekomprimierten Bilder sind etwas impressionistisch, aber ich finde es relativ einfach zu sehen, wie Bits dem Original entsprechen.

Stapelüberlauf-Logo (8,6 Sekunden zum Codieren, 7,9 Sekunden zum Decodieren, 485 Byte):
http://i44.tinypic.com/2w7lok1.png

Lena (32,8 Sekunden zum Codieren, 13,0 Sekunden zum Decodieren, 477 Byte):
http://i42.tinypic.com/2rr49wg.png http://i40.tinypic.com/2rhxxyu.png

Mona Lisa (43,2 Sekunden zum Codieren, 14,5 Sekunden zum Decodieren, 490 Byte):
http://i41.tinypic.com/ekgwp3.png http://i43.tinypic.com/ngsxep.png

Bearbeiten: CJK Unified Characters

Sam fragte in den Kommentaren nach der Verwendung mit CJK. Hier ist eine Version der Mona Lisa, die aus dem CJK Unified-Zeichensatz auf 139 Zeichen komprimiert wurde:

http://i43.tinypic.com/2yxgdfk.png 咏 璘 璘 凄 脒 鵚 据 蛥 鸂 拗 朐 朖 辿 韩 瀦 魷 歪隤 慛 絖 銓 馿 渫 櫰 矍 昀 鰛 掾 撄 粂 敽 牙 稉 擎 蔍 螎 葙 覧 絀 蹔 惫 冧 笻 哜 搀 澐伆 杇 婣 唆 鐤 諽 鷍 鴞 駫 搶 毤 埙 誖 萜 愿 旖 鞰 萗 勹 鈱 垬 濅 鬒 瞛 洆 认 気 狋 異擸 萿

Die Abstimmungsparameter oben im Programm, die ich dafür verwendet habe, waren: 19, 19, 4, 4, 3, 10, 11, 1000, 1000. Ich habe auch die erste Definition von number_assigned und Codes auskommentiert und die kommentiert letzte Definitionen von ihnen, um den CJK Unified-Zeichensatz auszuwählen.


Beeindruckend! Gut gemacht. Ich war skeptisch gegenüber der fraktalen Bildkomprimierung für so kleine Bilder, aber sie führt tatsächlich zu ziemlich anständigen Ergebnissen. Es war auch ziemlich einfach zu kompilieren und auszuführen.
Brian Campbell

1
Danke Leute! Sam, meinst du Ergebnisse mit nur 140 CJK-Zeichen? Wenn ja, dann müssen Sie die Zahlen oben einstellen. Die endgültige Größe in Bits liegt bei log2 (Schritte_in_x Schritte_in_y Schritte_in_red Schritte_in_grünen Schritte_in_Blau) * Blocks_in_x Blöcke_in_y + log2 (maximale_Breite maximale_Höhe).
Boojum

Bearbeiten: Es gibt eine * 16 in der ersten log2 (), die ich ausgelassen habe. Das ist für die möglichen Orientierungen.
Boojum

20
Hat jemand schon ein Bild mit diesem Bild getwittert?
dbr

288

Bilddateien und Python-Quelle (Version 1 und 2)

Version 1 Hier ist mein erster Versuch. Ich werde aktualisieren, wenn ich gehe.

Ich habe das SO-Logo auf 300 Zeichen fast verlustfrei reduziert. Meine Technik verwendet die Konvertierung in SVG-Vektorgrafiken, sodass sie am besten für Online-Grafiken funktioniert. Es ist eigentlich ein SVG-Kompressor, es erfordert immer noch, dass die ursprüngliche Kunst eine Vektorisierungsstufe durchläuft.

Für meinen ersten Versuch habe ich einen Onlinedienst für die PNG-Ablaufverfolgung verwendet. Es gibt jedoch VIELE kostenlose und nicht kostenlose Tools, die diesen Teil verarbeiten können, einschließlich Potrace (Open Source).

Hier sind die Ergebnisse

Originales SO-Logo http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png Originales decodiertes SO-Logo http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded.png Nach dem Codieren und Dekodierung

Zeichen : 300

Zeit : Nicht gemessen, aber praktisch sofort (ohne Vektorisierungs- / Rasterisierungsschritte)

In der nächsten Phase werden 4 Symbole (SVG-Pfadpunkte und -Befehle) pro Unicode-Zeichen eingebettet. Im Moment hat mein Python-Build keine breite Zeichenunterstützung UCS4, was meine Auflösung pro Zeichen begrenzt. Ich habe auch den maximalen Bereich auf das untere Ende des reservierten Unicode-Bereichs 0xD800 beschränkt. Sobald ich jedoch eine Liste der zulässigen Zeichen und einen Filter erstellt habe, um sie zu vermeiden, kann ich theoretisch die erforderliche Anzahl von Zeichen auf 70-100 für das verschieben Logo oben.

Eine Einschränkung dieser Methode ist derzeit, dass die Ausgabegröße nicht festgelegt ist. Dies hängt von der Anzahl der Vektorknoten / -punkte nach der Vektorisierung ab. Um diese Grenze zu automatisieren, muss entweder das Bild pixelig gemacht werden (wodurch der Hauptvorteil von Vektoren entfällt) oder die Pfade werden wiederholt durch eine Vereinfachungsstufe geführt, bis die gewünschte Knotenanzahl erreicht ist (was ich derzeit manuell in Inkscape mache).

Version 2

UPDATE : v2 ist jetzt für den Wettbewerb qualifiziert. Änderungen:

  • Eingabe / Ausgabe und Debugging der Befehlszeilensteuerung
  • Verwendet XML-Parser (lxml), um SVG anstelle von Regex zu verarbeiten
  • Packt 2 Pfadsegmente pro Unicode-Symbol
  • Dokumentation und Bereinigung
  • Support style = "fill: color" und fill = "color"
  • Dokumentbreite / -höhe in Einzelzeichen gepackt
  • Pfadfarbe in Einzelzeichen gepackt
  • Die Farbkomprimierung wird erreicht, indem 4 Bit Farbdaten pro Farbe weggeworfen und dann per Hex-Konvertierung in ein Zeichen gepackt werden.

Zeichen : 133

Zeit : Einige Sekunden

v2 decodiert http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded-v2.png Nach dem Codieren und Decodieren (Version 2)

Wie Sie sehen können, gibt es diesmal einige Artefakte. Es ist keine Einschränkung der Methode, sondern ein Fehler irgendwo in meinen Konvertierungen. Die Artefakte treten auf, wenn die Punkte außerhalb des Bereichs von 0,0 bis 127,0 liegen und meine Versuche, sie einzuschränken, gemischten Erfolg hatten. Die Lösung besteht einfach darin, das Bild zu verkleinern. Ich hatte jedoch Probleme, die tatsächlichen Punkte und nicht die Zeichenfläche oder die Gruppenmatrix zu skalieren, und bin jetzt zu müde, um mich darum zu kümmern. Kurz gesagt, wenn Ihre Punkte im unterstützten Bereich liegen, funktioniert dies im Allgemeinen.

Ich glaube, der Knick in der Mitte ist darauf zurückzuführen, dass sich ein Griff auf die andere Seite eines Griffs bewegt, mit dem er verbunden ist. Grundsätzlich sind die Punkte in erster Linie zu nahe beieinander. Wenn Sie vor dem Komprimieren einen Vereinfachungsfilter über dem Quellbild ausführen, sollte dies behoben und einige unnötige Zeichen entfernt werden.

UPDATE : Diese Methode eignet sich gut für einfache Objekte, daher brauchte ich eine Möglichkeit, komplexe Pfade zu vereinfachen und Rauschen zu reduzieren. Ich habe Inkscape für diese Aufgabe verwendet. Ich hatte etwas Glück damit, unnötige Pfade mit Inkscape zu entfernen, hatte aber keine Zeit, sie zu automatisieren. Ich habe einige Beispiel-SVGs mit der Inkscape-Funktion "Vereinfachen" erstellt, um die Anzahl der Pfade zu verringern.

Simplify funktioniert in Ordnung, kann aber bei so vielen Pfaden langsam sein.

Autotrace Beispiel http://www.warriorhut.org/graphics/svg_to_unicode/autotrace_16_color_manual_reduction.png cornell box http://www.warriorhut.com/graphics/svg_to_unicode/cornell_box_simplified.png lena http://www.warriorhut.com/graphics /svg_to_unicode/lena_std_washed_autotrace.png

Thumbnails verfolgt http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_autotrace.png

Hier sind einige Aufnahmen mit extrem niedriger Auflösung. Diese liegen näher an der Beschränkung auf 140 Zeichen, obwohl möglicherweise auch eine clevere Pfadkomprimierung erforderlich ist.

gepflegt http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_groomed.png Vereinfacht und entfleckt.

trianglulated http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_triangulated.png Vereinfacht, entfleckt und trianguliert.

autotrace --output-format svg --output-file cornell_box.svg --despeckle-level 20 --color-count 64 cornell_box.png

OBEN: Vereinfachte Pfade mit Autotrace .

Leider verarbeitet mein Parser die Autotrace-Ausgabe nicht, sodass ich nicht weiß, wie Punkte verwendet werden können oder wie weit sie zu vereinfachen sind. Leider bleibt wenig Zeit, um sie vor Ablauf der Frist zu schreiben. Es ist jedoch viel einfacher zu analysieren als die Inkscape-Ausgabe.


2
Ausgezeichnet! Zuerst wollte ich eine Hybridvektorlösung mit scharfen Kanten und glatten Bereichen erstellen, die sich jedoch als viel zu komplex erwies, ohne eine Ablaufverfolgungsbibliothek zu verwenden (die ich nicht verwenden wollte). Ich freue mich darauf zu sehen, wie weit Sie mit Ihrer Methode kommen können!
Sam Hocevar

Nett! Ich hatte gehofft, wir würden einige Versuche zu nahezu verlustfreien Ansätzen durch Vektorisierung sehen. Dies bedeutet, dass die Allgemeinheit geringer ist, die Qualität der abgedeckten Bilder jedoch höher ist. Es ist in Ordnung, einen Onlinedienst für die Vektorisierung zu verwenden. Viel Glück beim weiteren Verkleinern!
Brian Campbell

Ich würde Bildkomprimierung und Zeichenkodierung als zwei verschiedene Schritte betrachten - Sams Technik scheint für die Kodierung optimal zu sein und könnte leicht in ein eigenständiges Programm eingebaut werden. Sie werden mehr für Ihr Geld bekommen, wenn Sie sich auf den einzigartigen Teil Ihrer Lösung konzentrieren (dh den Komprimierungsteil) und nur eine Folge von Bits ausgeben.
Mark Ransom

70
Beeindruckend. Diese Bilder sehen wirklich stilvoll aus.
Rinat Abdullin

199

Meine vollständige Lösung finden Sie unter http://caca.zoy.org/wiki/img2twit . Es hat die folgenden Funktionen:

  • Angemessene Komprimierungszeit (ca. 1 Minute für hohe Qualität)
  • Schnelle Dekompression (Bruchteil einer Sekunde)
  • Behält die ursprüngliche Bildgröße bei (nicht nur das Seitenverhältnis)
  • Anständige Rekonstruktionsqualität (IMHO)
  • Nachrichtenlänge und Zeichensatz (ASCII, CJK, Symbole) können zur Laufzeit ausgewählt werden
  • Nachrichtenlänge und Zeichensatz werden zur Dekomprimierungszeit automatisch erkannt
  • Sehr effiziente Informationsverpackung

http://caca.zoy.org/raw-attachment/wiki/img2twit/so-logo.png http://caca.zoy.org/raw-attachment/wiki/img2twit/twitter4.png

蜥 秓 鋖 筷 聝 诿 缰 偺 腶 漷 庯 祩 皙 靊 谪 獜 岨 幻 寤 厎 脘 搇 梄 桻 桻 戂 溥 欇 渹 軱 骿 岚 岚 捕 岚 岚 瀹玧 霫 鏓 蓕 戲 債 鼶 襋 躻 弯 袮 足 庭 侅 旍 凼 飙 驅 據 嘛 倾 诗 籂 嶹 嶹 椿 糢 墤 渽 赐 更 憫 憫 翉 憫 憫 鳣擲 舥 攩 寉 鈶 兓 庭 璱 篂 鰀 乾 丕 耓 庁 錸 努 樀 肝 亖 弜 喆 蝞 躐 譑 谎 蛪 曟 暙 刍 镶 媏

Hier ist eine grobe Übersicht über den Kodierungsprozess:

  • Die Anzahl der verfügbaren Bits wird aus der gewünschten Nachrichtenlänge und dem verwendbaren Zeichensatz berechnet
  • Das Quellbild wird in so viele quadratische Zellen segmentiert, wie die verfügbaren Bits zulassen
  • Für jede Zelle ist eine feste Anzahl von Punkten (derzeit 2) mit Anfangskoordinaten und Farbwerten betroffen
  • Folgendes wird wiederholt, bis eine Qualitätsbedingung erfüllt ist:
    • Ein Punkt wird zufällig ausgewählt
    • An diesem Punkt wird zufällig eine Operation ausgeführt (Verschieben in die Zelle, Ändern der Farbe).
    • Wenn das resultierende Bild (siehe Decodierungsprozess unten) näher am Quellbild liegt, wird der Vorgang beibehalten
  • Die Bildgröße und Liste der Punkte ist in UTF-8 codiert

Und das ist der Dekodierungsprozess:

  • Die Bildgröße und die Punkte werden aus dem UTF-8-Stream gelesen
  • Für jedes Pixel im Zielbild:
    • Die Liste der natürlichen Nachbarn wird berechnet
    • Die endgültige Farbe des Pixels wird als gewichteter Durchschnitt der Farben seiner natürlichen Nachbarn festgelegt

Was ich für den originellsten Teil des Programms halte, ist der Bitstream. Anstatt bitausgerichtete Werte ( stream <<= shift; stream |= value) zu packen, packe ich beliebige Werte, die nicht im Zweierpotenzbereich liegen ( stream *= range; stream += value). Dies erfordert Bignum-Berechnungen und ist natürlich viel langsamer, aber es gibt mir 2009,18 Bit anstelle von 1960, wenn ich die 20902-CJK-Hauptzeichen verwende (das sind drei weitere Punkte, die ich in die Daten einfügen kann). Und wenn ich ASCII verwende, bekomme ich 917,64 Bit anstelle von 840.

Ich entschied mich gegen eine Methode für die anfängliche Bildberechnung, die schwere Waffen erfordert hätte (Eckenerkennung, Merkmalsextraktion, Farbquantisierung ...), weil ich zunächst nicht sicher war, ob dies wirklich helfen würde. Jetzt ist mir klar, dass die Konvergenz langsam ist (1 Minute ist akzeptabel, aber dennoch langsam), und ich kann versuchen, dies zu verbessern.

Die Hauptanpassungsschleife ist lose vom Direct Binary Seach-Dithering-Algorithmus inspiriert (bei dem Pixel zufällig vertauscht oder gespiegelt werden, bis ein besserer Halbton erzielt wird). Die Energieberechnung ist ein einfacher quadratischer Mittelwertabstand, aber ich führe zuerst einen 5x5-Medianfilter für das Originalbild durch. Eine Gaußsche Unschärfe würde wahrscheinlich das Verhalten des menschlichen Auges besser darstellen, aber ich wollte keine scharfen Kanten verlieren. Ich habe mich auch gegen simuliertes Tempern oder andere schwer einstellbare Methoden entschieden, da ich keine Monate Zeit habe, um den Prozess zu kalibrieren. Somit repräsentiert das "Qualitäts" -Flag nur die Anzahl der Iterationen, die an jedem Punkt ausgeführt werden, bevor der Codierer endet.

http://caca.zoy.org/raw-attachment/wiki/img2twit/Mona_Lisa_scaled.jpg http://caca.zoy.org/raw-attachment/wiki/img2twit/twitter2.png

苉 憗 揣 嶕 繠 剳 腏 篮 濕 茝 霮 墧 蒆 棌 杚 蓳 縳 樟 赒 肴 噹激 躙 憮 鄴 甮 槺 骳 佛 愚 猪 駪 惾 嫥 綖 珏 矯 坼 堭 颽 箽 飉苾 绒 酯 嵞 脔 婺 污 囉 酼 俵 菛 琪 棺 则 辩 曚 鸸 職 銛 蒝 礭 鱚 蟺 况 醾 陴 陴 尥 尥 蟀 惘 髚 忩 忩 祤 脤 养

Obwohl nicht alle Bilder gut komprimiert werden, bin ich von den Ergebnissen überrascht und frage mich wirklich, welche anderen Methoden es gibt, mit denen ein Bild auf 250 Byte komprimiert werden kann.

Ich habe auch kleine Filme über die Entwicklung des Encoder-Zustands von einem zufälligen Anfangszustand und von einem "guten" Anfangszustand .

Bearbeiten : So wird die Komprimierungsmethode mit JPEG verglichen. Links das über 536-Byte-Bild von Jamoes. Auf der rechten Seite hat Mona Lisa mit der hier beschriebenen Methode auf 534 Bytes komprimiert (die hier genannten Bytes beziehen sich auf Datenbytes und ignorieren daher Bits, die durch die Verwendung von Unicode-Zeichen verschwendet wurden):

http://caca.zoy.org/raw-attachment/wiki/img2twit/minimona.jpg http://caca.zoy.org/raw-attachment/wiki/img2twit/minimona2.png

Bearbeiten : CJK-Text wurde gerade durch die neuesten Versionen der Bilder ersetzt.


Ich muss nicht in der Lage sein, den Code auszuführen (ich habe den Teil über das Ausführen in den Richtlinien als Vorschlag und nicht in die Regeln eingefügt). Ich würde es vorziehen, es ausführen zu können, aber ich werde dies mehr anhand der Qualität der von Ihnen generierten Bilder, des Codes und aller interessanten Tricks oder Algorithmen beurteilen. Wenn ich es ausführen möchte und es Pakete erfordert, die ich nicht auf meinem Hauptsystem habe oder nicht installieren möchte, kann ich einfach eine Amazon EC2-Instanz starten und installieren. Solange Sie mit Bibliotheken arbeiten, die für eine der Hauptdistributionen gepackt sind, sollte ich sie ausführen können. Fühlen Sie sich frei, CGAL zu verwenden.
Brian Campbell

2
Okay, hier ist meine Lösung (Quellcode): caca.zoy.org/browser/libpipi/trunk/examples/img2twit.cpp Mein Erklärungsversuch und einige Beispiele finden Sie unter caca.zoy.org/wiki/img2twit
sam hocevar

2
Ihre Lösung gefällt mir sehr gut. Sie sollten versuchen, die Anzahl der dem blauen Kanal zugewiesenen Werte zu verringern, da das menschliche Auge Blau nicht sehr gut auflösen kann: nfggames.com/games/ntsc/visual.shtm ; Auf diese Weise können Sie auf Kosten des Verlusts einiger Farbinformationen detailliertere Informationen erhalten. Oder vielleicht grün zuordnen?
rpetrich

5
Guter Punkt. Ich habe einige Variationen dieser Idee ausprobiert (siehe die Kommentare vor der RANGE_X-Definition), aber nicht sehr gründlich. Wie Sie sehen können, hat die Verwendung von 5 Blauwerten anstelle von 6 den Fehler etwas weniger erhöht als die Verwendung von 7 Grünwerten. Ich habe nicht versucht, beides aus Faulheit zu tun. Ein weiteres Problem ist, dass ich keine sehr gute Fehlerfunktion habe. Ich benutze derzeit ∑ (∆r² + ∆g² + ∆b²) / 3, was OK funktioniert. Ich habe ∑ (0,299∆r² + 0,587∆g² + 0,114∆b²) versucht, basierend (ohne physikalische Begründung) auf der Y-Komponente von YUV, aber es war zu tolerant gegenüber blauen Fehlern. Ich werde versuchen, Papiere zu diesem Thema zu finden.
Sam Hocevar

2
@rpetrich: Ich habe das Programm so modifiziert, dass es die R / G / B-Bereiche dynamisch erhöht, solange genügend Bits verfügbar sind. Dies stellt sicher, dass niemals mehr als 13 Bits im gesamten Bitstrom verschwendet werden (in der Praxis sind es jedoch normalerweise 1 oder 2). Und die Bilder sehen etwas besser aus.
Sam Hocevar

45

Das Folgende ist keine formelle Einreichung, da meine Software in keiner Weise auf die angegebene Aufgabe zugeschnitten wurde. DLI kann als optimierender verlustbehafteter Allzweck-Bildcodec beschrieben werden. Es ist der PSNR- und MS-SSIM-Datensatzhalter für die Bildkomprimierung, und ich dachte, es wäre interessant zu sehen, wie er für diese bestimmte Aufgabe funktioniert. Ich habe das bereitgestellte Referenzbild von Mona Lisa verwendet und es auf 100 x 150 verkleinert. Dann habe ich DLI verwendet, um es auf 344 Byte zu komprimieren.

Mona Lisa DLI http://i40.tinypic.com/2md5q4m.png

Zum Vergleich mit den komprimierten JPEG- und IMG2TWIT-Samples habe ich DLI verwendet, um das Bild ebenfalls auf 534 Byte zu komprimieren. Das JPEG beträgt 536 Bytes und IMG2TWIT 534 Bytes. Die Bilder wurden zum einfachen Vergleich auf ungefähr die gleiche Größe skaliert. JPEG ist das linke Bild, IMG2TWIT ist die Mitte und DLI ist das rechte Bild.

Vergleich http://i42.tinypic.com/302yjdg.png

Das DLI-Bild schafft es, einige der Gesichtszüge zu bewahren, insbesondere das berühmte Lächeln :).


6
Hoppla. Das oben Genannte sollte Dennis Lee gutgeschrieben werden, der es ursprünglich eingereicht hat. Ich habe es gerade bearbeitet, um die Bilder inline einzubetten und auf die Referenz zu verlinken, die ich von Googling gefunden habe. Und ich muss sagen, wow, ich bin beeindruckt von der Komprimierung. Ich muss die DLI-Komprimierung überprüfen.
Brian Campbell

1
Der DLI-Autor erwähnt übrigens eine "lange Bearbeitungszeit". Können Sie uns grobe Zahlen für die Komprimierungszeit geben, da ich seine Software nicht ausführen kann?
Sam Hocevar

1
Bei Verwendung eines AMD Athlon64 mit 2,4 GHz dauert die Komprimierung des 100 x 150 Mona Lisa-Bildes 38 Sekunden und die Dekomprimierung 6 Sekunden. Das Komprimieren auf maximal 251 Byte ist schwieriger, die Ausgabequalität wird erheblich reduziert. Unter Verwendung des Referenzbilds von Mona Lisa habe ich es auf 60 x 91 verkleinert und es dann mit DLI auf 243 Byte komprimiert (am nächsten an 251, ohne darüber hinwegzugehen). Dies ist die Ausgabe i43.tinypic.com/2196m4g.png Das Detail befindet sich nicht in der Nähe des 534-Byte-DLI, obwohl die Bitrate nur um ~ 50% reduziert wurde. Die Struktur des Bildes wurde jedoch ziemlich gut beibehalten.

1
Beschlossen, um den Vergleich der komprimierten 250-Byte-Samples zu vereinfachen. Der 243-Byte-DLI wurde vergrößert und neben der IMG2TWIT-Probe platziert. IMG2TWIT links, DLI rechts. Hier ist das Bild i40.tinypic.com/30ndks6.png

1
DLI verwendet einen Qualitätsparameter wie JPEG. Daher ist ein Versuch und Irrtum erforderlich, wenn eine Zielausgabegröße gewünscht wird.

21

Der allgemeine Überblick über meine Lösung wäre:

  1. Ich beginne mit der Berechnung der maximalen Menge an Rohdaten, die Sie in 140 utf8-Zeichen einpassen können.
    • (Ich gehe von utf8 aus, was die ursprüngliche Website ist behauptete, Twitter habe seine Nachrichten gespeichert. Dies unterscheidet sich von der obigen Problemstellung, in der utf16 abgefragt wird.)
    • Mit dieser utf8-FAQ berechne ich, dass die maximale Anzahl von Bits, die Sie in einem einzelnen utf8-Zeichen codieren können, 31 Bit beträgt. Zu diesem Zweck würde ich alle Zeichen verwenden, die sich im Bereich U-04000000 - U-7FFFFFFF befinden. (1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx, es gibt 31 x, daher könnte ich bis zu 31 Bit codieren).
    • 31 Bit mal 140 Zeichen entsprechen 4340 Bit. Teilen Sie das durch 8, um 524,5 zu erhalten, und runden Sie es auf 542 Bytes ab .
    • (Wenn wir uns auf utf16 beschränken, können wir nur 2 Bytes pro Zeichen speichern, was 280 Bytes entspricht.)
  2. Komprimieren Sie das Bild mit der Standard-JPG-Komprimierung.
    • Ändern Sie die Größe des Bilds auf ungefähr 50 x 50 Pixel und versuchen Sie dann, es mit verschiedenen Komprimierungsstufen zu komprimieren, bis Sie ein Bild haben, das so nahe wie möglich an 542 Byte liegt, ohne darüber hinauszugehen.
    • Dies ist ein Beispiel für die auf 536 Bytes komprimierte Mona Lisa.
  3. Codieren Sie die Rohbits des komprimierten Bildes in utf-8-Zeichen.
    • Ersetzen Sie jedes x in den folgenden Bytes: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx durch die Bits aus dem Bild.
    • Dieser Teil wäre wahrscheinlich der Teil, in dem der Großteil des Codes geschrieben werden müsste, da derzeit nichts vorhanden ist, das dies tut.

Ich weiß, dass Sie nach Code gefragt haben, aber ich möchte nicht wirklich die Zeit damit verbringen, dies tatsächlich zu codieren. Ich dachte mir, dass ein effizientes Design zumindest jemand anderen dazu inspirieren könnte, dies zu codieren.

Ich denke, der Hauptvorteil meiner vorgeschlagenen Lösung besteht darin, dass so viel vorhandene Technologie wie möglich wiederverwendet wird. Es mag Spaß machen, einen guten Komprimierungsalgorithmus zu schreiben, aber es gibt garantiert einen besseren Algorithmus, der höchstwahrscheinlich von Leuten geschrieben wurde, die einen Abschluss in höherer Mathematik haben.

Ein weiterer wichtiger Hinweis ist jedoch, dass diese Lösung auseinanderfällt, wenn entschieden wird, dass utf16 die bevorzugte Codierung ist. JPEGs funktionieren nicht wirklich, wenn sie auf 280 Bytes komprimiert sind. Vielleicht gibt es für diese spezielle Problemstellung einen besseren Komprimierungsalgorithmus als jpg.


Ich bin jetzt auf der Arbeit, aber ich implementiere diese Lösung definitiv, wenn ich nach Hause komme.
Paulo Santos

2
Aus meinen Experimenten geht hervor, dass UTF-16 tatsächlich die Art und Weise ist, wie Twitter Zeichen zählt. BMP-Zeichen zählen als 1 und Zeichen höherer Ebenen zählen als 2. Es ist nicht dokumentiert, aber so zählt der JavaScript-Zeichenzähler, wenn Sie in das Eingabefeld eingeben. Es wird auch in den Kommentaren im Original-Thread erwähnt. Ich habe nicht versucht, über die API zu senden, um festzustellen, ob der Zähler defekt ist. Wenn dies der Fall ist, aktualisiere ich das Problem für die tatsächlichen Einschränkungen. Es ist jedoch unwahrscheinlich, dass Sie beliebiges UTF-8 verwenden können, da viele dieser längeren Sequenzen, die Sie codieren können, kein gültiger Unicode sind.
Brian Campbell

4
Nach dem Testen mit ihrer API stellt sich heraus, dass sie nach Unicode-Zeichen (Codepunkten) und nicht nach UTF-16-Codeeinheiten zählen (es ist der JavaScript-Zeichenzähler, der über UTF-16 zählt, da dies anscheinend bei der JavaScript-Längenmethode der Fall ist). . So können Sie dort ein bisschen mehr Informationen erhalten; Gültige Unicode-Zeichen liegen im Bereich von U + 0000 bis U + 10FFFF (etwas mehr als 20 Bit pro Zeichen; 2 ^ 20 + 2 ^ 16 mögliche Werte pro Zeichen). UTF-8 ermöglicht die Codierung von mehr Werten als in Unicode zulässig. Wenn Sie sich also auf Unicode beschränken, können Sie ungefähr 350 Byte Speicherplatz erhalten, nicht 542.
Brian Campbell

3
Diese 536-Byte-Mona Lisa sieht angesichts der extremen Komprimierung überraschend gut aus!
Chris

3
Derzeit können 129.775 verschiedene (zugewiesene, nicht kontrollierte, nicht private) Unicode-Zeichen codiert werden. Wenn wir uns auf diese Teilmenge beschränken, sind es insgesamt 2377 Bits oder 297 Bytes. Code hier: porg.es/blog/what-can-we-fit-in-140-characters
porges

20

Okay, ich bin zu spät zum Spiel, aber trotzdem habe ich mein Projekt gemacht.

Es ist ein spielzeuggenetischer Algorithmus, der durchscheinende bunte Kreise verwendet, um das ursprüngliche Bild wiederherzustellen.

Eigenschaften:

  • reine Lua. Läuft überall dort, wo ein Lua-Dolmetscher läuft.
  • Verwendet das Netpbm P3-Format
  • kommt mit einer umfassenden Reihe von Unit-Tests
  • behält die ursprüngliche Bildgröße bei

Fehlfunktionen:

  • langsam
  • Bei diesen Platzbeschränkungen bleiben nur das Grundfarbschema des Ausgangsbildes und ein allgemeiner Umriss einiger Merkmale davon erhalten.

Hier ist ein Beispiel für Lena, das Lena darstellt:岂 掂 戇 耔 攋 斘 眐 奡 萛 狂 昸 箆 亲 嬎 廙 栃 兡 塅 受 橯 应 戞 优 僘 瑩 吱虲 兙 罨 縨 炘 排 叁 抠 堃 從 弅 慌 螎 熰 標 宑 簫 柢 橙 拃 蜊 缩 昔 舭 勵 癳厇 廩 焛 瀻 严 严 刱 刱 垫

Original Lena verschlüsselte Lena

Der Code befindet sich in einem Mercurial-Repository unter bitbucket.org. Schauen Sie sich http://bitbucket.org/tkadlubo/circles.lua an


2
Genial! Erstellt gepflegte, künstlerisch aussehende Bilder. Ich bin froh, dass die Leute noch daran arbeiten. Es hat viel Spaß gemacht, all die verschiedenen Ansätze zu sehen.
Brian Campbell

1
Ich würde gerne sehen, dass dies wie eine transparente Überlagerung des Originals verwendet wird, die so etwas wie den Bokeh-Effekt ergibt.
Nick Radford

19

Das Folgende ist meine Herangehensweise an das Problem und ich muss zugeben, dass dies ein ziemlich interessantes Projekt war, an dem ich arbeiten musste. Es liegt definitiv außerhalb meines normalen Arbeitsbereichs und hat mir etwas Neues gegeben, über das ich lernen kann.

Die Grundidee hinter mir ist wie folgt:

  1. Probieren Sie die Graustufen des Bildes so ab, dass insgesamt 16 verschiedene Schattierungen vorhanden waren
  2. Führen Sie RLE auf dem Bild vor
  3. Packen Sie die Ergebnisse in die UTF-16-Zeichen
  4. Führen Sie RLE für die gepackten Ergebnisse durch, um doppelte Zeichen zu entfernen

Es stellt sich heraus, dass dies funktioniert, jedoch nur in begrenztem Umfang, wie Sie den folgenden Beispielbildern entnehmen können. In Bezug auf die Ausgabe folgt ein Beispiel-Tweet, speziell für das in den Beispielen gezeigte Lena-Bild.

乤 乤 万 乐 唂 伂 倂 倁 企 儂 2 企 倁 3 企 倁 2 企 伂 8 企 伂 3 企 伂 5 企 倂 倃 伂 倁 3 企 儁 企 2 伂 倃 5 企 倁 3 企 倃 4 企 倂 企 倁 企伂 2 企 伂 5 企 倁 企 伂 쥹 皗 鞹 鐾 륶 䦽 阹 럆 䧜 椿 籫 릹 靭 욶 옷뎷 㰷 歉 䴗

Wie Sie sehen können, habe ich versucht, den Zeichensatz ein wenig einzuschränken. Beim Speichern der Bildfarbdaten sind jedoch Probleme aufgetreten. Außerdem neigt dieses Codierungsschema dazu, eine Reihe von Datenbits zu verschwenden, die für zusätzliche Bildinformationen verwendet werden könnten.

In Bezug auf die Laufzeit ist der Code für kleine Bilder extrem schnell, etwa 55 ms für die bereitgestellten Beispielbilder, aber die Zeit nimmt mit größeren Bildern zu. Für das 512 x 512 Lena-Referenzbild betrug die Laufzeit 1182 ms. Ich sollte beachten, dass die Chancen ziemlich gut stehen, dass der Code selbst nicht sehr leistungsoptimiert ist (z. B. wird alles als Bitmap verarbeitet ), sodass die Zeiten nach einigen Umgestaltungen etwas sinken können.

Bitte zögern Sie nicht, mir Vorschläge zu machen, was ich hätte besser machen können oder was mit dem Code falsch sein könnte. Die vollständige Liste der Laufzeiten und der Beispielausgabe finden Sie unter folgendem Speicherort: http://code-zen.info/twitterimage/

Update Eins

Ich habe den RLE-Code aktualisiert, der beim Komprimieren der Tweet-Zeichenfolge verwendet wird, um einen grundlegenden Rückblick zu ermöglichen, und wenn ja, verwenden Sie diesen für die Ausgabe. Dies funktioniert nur für die Zahlenwertpaare, speichert jedoch einige Datenzeichen. Die Laufzeit ist mehr oder weniger gleich wie die Bildqualität, aber die Tweets sind tendenziell etwas kleiner. Ich werde das Diagramm auf der Website aktualisieren, wenn ich die Tests abgeschlossen habe. Was folgt, ist eine der Beispiel-Tweet-Zeichenfolgen, wiederum für die kleine Version von Lena:

乤 乤 万 乐 唂 伂 倂 倁 企 儂 2 企 倁 3 企 倁 ウ 伂 8 企 伂 エ 伂 5 企 倂 倃 伂 倁 グ 儁 企 2 伂 倃 ガ 倁 ジ 倃 4 企 倂 企 倁 企 伂 ツ 伂 ス 倁企 伂 쥹 皗 鞹 鐾 륶 䦽 阹 럆 䧜 椿 籫 릹 靭 욶 옷뎷 歩 㰷 歉 䴗 鑹 㞳

Update Zwei

Ein weiteres kleines Update, aber ich habe den Code geändert, um die Farbtöne in Dreiergruppen anstatt in Vier zu packen. Dies beansprucht etwas mehr Platz. Wenn mir jedoch etwas fehlt, sollte dies bedeuten, dass "ungerade" Zeichen nicht mehr dort erscheinen, wo die Farbe ist Daten sind. Außerdem habe ich die Komprimierung etwas weiter aktualisiert, sodass sie jetzt auf die gesamte Zeichenfolge und nicht nur auf den Farbzählblock angewendet werden kann. Ich teste immer noch die Laufzeiten, aber sie scheinen nominell verbessert zu sein. Die Bildqualität ist jedoch immer noch dieselbe. Was folgt, ist die neueste Version des Lena-Tweets:

2企 伂 坹 坼 坶 坻 刾 啩 容 力 吹 婩 媷 劝 圿 咶 坼 妛 啭 奩 嗆 冷 咛 啫 凃 奉 坍商 嗉 乃

StackOverflow-Logo http://code-zen.info/twitterimage/images/stackoverflow-logo.bmp Cornell Box http://code-zen.info/twitterimage/images/cornell-box.bmp Lena http: // code-zen .info / twitterimage / images / lena.bmp Mona Lisa http://code-zen.info/twitterimage/images/mona-lisa.bmp


1
Super, danke für den Eintrag! Graustufen funktionieren für die meisten von ihnen eigentlich ziemlich gut, obwohl Lena ein bisschen schwer zu erkennen ist. Ich habe nach Ihrer Quelle gesucht, aber eine 404 bekommen; Könntest du sicherstellen, dass es dort oben ist?
Brian Campbell

Überprüfen Sie es jetzt noch einmal. Ich habe die Website aktualisiert, sodass Sie mich möglicherweise zwischen den Aktualisierungen erwischt haben.
rjzii

Ja, ich kann es jetzt herunterladen. Jetzt muss ich natürlich herausfinden, ob ich Mono dazu bringen kann, es zu kompilieren.
Brian Campbell

Ja! Funktioniert unter Mono, habe ich mit "gmcs -r System.Drawing TwitterImage.cs Program.cs" kompiliert und mit "mono TwitterImage.exe encode lena.png lena.txt" ausgeführt
Brian Campbell

Cool! Ich habe noch einmal überprüft, ob die von mir verwendeten Bibliotheken für Mono aufgelistet sind, aber ich habe noch nicht mit Mono gearbeitet, daher war ich mir nicht sicher, ob dies der Fall ist oder nicht.
rjzii


12

In der ursprünglichen Herausforderung ist die Größenbeschränkung als das definiert, was Twitter noch senden kann, wenn Sie Ihren Text in das Textfeld einfügen und auf "Aktualisieren" klicken. Wie einige Leute richtig bemerkt haben, unterscheidet sich dies von dem, was Sie als SMS-Textnachricht von Ihrem Handy aus senden könnten.

Was nicht explizit erwähnt wird (aber was meine persönliche Regel war), ist, dass Sie in der Lage sein sollten, die getwitterte Nachricht in Ihrem Browser auszuwählen, sie in die Zwischenablage zu kopieren und in ein Texteingabefeld Ihres Decoders einzufügen, damit sie angezeigt werden kann. Natürlich können Sie die Nachricht auch als Textdatei speichern und wieder einlesen oder ein Tool schreiben, das auf die Twitter-API zugreift und jede Nachricht herausfiltert, die wie ein Bildcode aussieht (spezielle Markierungen, jemand? Zwinker zwinker ). Die Regel ist jedoch, dass die Nachricht über Twitter gesendet werden muss, bevor Sie sie entschlüsseln dürfen.

Viel Glück mit den 350 Bytes - ich bezweifle, dass Sie sie nutzen können.


1
Ja, ich habe eine Bewertungsrubrik hinzugefügt, die angibt, dass strengere Einschränkungen des Zeichensatzes bevorzugt, aber nicht erforderlich sind. Ich hätte gerne eine Regel, nach der Nachrichten unbeschadet über Twitter gesendet werden müssen, aber das würde viel Versuch und Irrtum erfordern, um die genauen Details der Funktionsweise herauszufinden, und ich wollte einen gewissen Spielraum lassen, um die kreative Nutzung von zu ermöglichen Coderaum. Die einzige Voraussetzung für meine Herausforderung sind 140 gültige Unicode-Zeichen. Übrigens, danke fürs vorbeischauen! Ich mag Ihre Lösung wirklich und möchte sehen, ob einer der Kibitzer sie tatsächlich verbessern kann.
Brian Campbell

12

Durch das Posten eines Schwarzweiß- oder Graustufenbilds sollte die Größe des Bilds verbessert werden, das in diesen Bereich codiert werden kann, da Sie sich nicht für Farbe interessieren.

Möglicherweise wird die Herausforderung, drei Bilder hochzuladen, noch größer. Wenn Sie sie neu kombinieren, erhalten Sie ein Vollfarbbild, während in jedem einzelnen Bild eine monochrome Version beibehalten wird.

Fügen Sie etwas Komprimierung zu dem oben genannten hinzu und es könnte anfangen, brauchbar auszusehen ...

Nett!!! Jetzt habt ihr mein Interesse geweckt. Für den Rest des Tages wird keine Arbeit erledigt ...


9
s /
peaked

1
Ich mag die Idee von drei Bildern, es sollte möglich sein, eine solche Idee auf Twitter zu implementieren und das Ergebnis wäre ziemlich gut.
Makis

9

In Bezug auf den Codierungs- / Decodierungsteil dieser Herausforderung. base16b.org ist mein Versuch, eine Standardmethode für die sichere und effiziente Codierung von Binärdaten in den höheren Unicode-Ebenen anzugeben.

Einige Eigenschaften :

  • Verwendet nur die privaten Benutzerbereiche von Unicode
  • Codiert bis zu 17 Bit pro Zeichen; fast dreimal effizienter als Base64
  • Eine Referenz-Javascript-Implementierung von Codierung / Decodierung wird bereitgestellt
  • Einige Beispielcodierungen sind enthalten, einschließlich Twitter und Wordpress

Entschuldigung, diese Antwort kommt viel zu spät für den ursprünglichen Wettbewerb. Ich habe das Projekt unabhängig von diesem Beitrag gestartet, den ich auf halbem Weg entdeckt habe.


8

Die Idee, eine Reihe von Referenzbildern zu speichern, ist interessant. Wäre es so falsch, beispielsweise 25 MB Beispielbilder zu speichern und den Encoder versuchen zu lassen, ein Bild mit Bits davon zu erstellen? Mit solch einer winzigen Pipe wird die Maschinerie an beiden Enden notwendigerweise viel größer sein als das durchgelassene Datenvolumen. Was ist also der Unterschied zwischen 25 MB Code und 1 MB Code und 24 MB Bilddaten?

(Beachten Sie, dass die ursprünglichen Richtlinien ausgeschlossen haben, dass die Eingabe auf Bilder beschränkt wird, die sich bereits in der Bibliothek befinden - das schlage ich nicht vor).


1
Das wäre in Ordnung, solange Sie an beiden Endpunkten eine feste, endliche Datenmenge haben. Natürlich müssen Sie nachweisen, dass es mit Bildern funktioniert, die nicht im Trainingssatz enthalten sind, genau wie bei jedem statistischen Prozessproblem in natürlicher Sprache. Ich würde gerne etwas sehen, das einen statistischen Ansatz für die Bildcodierung verfolgt.
Brian Campbell

16
Zum einen würde ich gerne sehen, wie Mona Lisa nur mit Boba Fett-Fanart als Quelle überarbeitet wird.
Nosredna

Ich stimme zu - der Photomosaik-Ansatz scheint innerhalb der Regeln zu liegen und wäre äußerst interessant zu sehen, wie jemand einen Stich macht.
An̲̳̳drew

8

Dumme Idee, sha1(my_image)würde aber zu einer "perfekten" Darstellung jedes Bildes führen (Kollisionen ignorieren). Das offensichtliche Problem ist, dass der Dekodierungsprozess übermäßig viel Brute-Forcing erfordert.

1-Bit-Monochrom wäre etwas einfacher. Jedes Pixel wird zu 1 oder 0, sodass Sie 1000 Datenbits für ein 100 * 100-Pixel-Bild haben würden. Da der SHA1-Hash 41 Zeichen hat, können wir drei in eine Nachricht einfügen, müssen nur 2 Sätze von 3333 Bits und einen Satz von 3334 brutal erzwingen (obwohl selbst das wahrscheinlich immer noch unangemessen ist)

Es ist nicht gerade praktisch. Selbst mit dem 1-Bit-100 * 100px-Bild mit fester Länge gibt es .., vorausgesetzt, ich berechne nicht falsch, 49995000 Kombinationen oder 16661667, wenn es in drei geteilt wird.

def fact(maxu):
        ttl=1
        for i in range(1,maxu+1):
                ttl=ttl*i
        return ttl

def combi(setsize, length):
    return fact(length) / (fact(setsize)*fact(length-setsize))

print (combi(2, 3333)*2) + combi(2, 3334)
# 16661667L
print combi(2, 10000)
# 49995000L

10
Das Problem mit sha1 (my_image) ist, dass Sie, wenn Sie Ihre Zeit damit verbringen, es brutal zu erzwingen, wahrscheinlich viele Kollisionen finden würden, bevor Sie das reale Bild gefunden haben. und natürlich ist das brutale Erzwingen von sha1 ziemlich rechenintensiv.
Brian Campbell

5
Noch besser als die SHA1-Komprimierung: mein "flickr" -Komprimierungsalgorithmus! Schritt 1: Bild auf flickr hochladen. Schritt 2: Posten Sie einen Link auf Twitter. Tadda! Nur 15 Bytes verwendet!
NiXar

2
niXar: Nein, Regel 3.4: "Der Dekodierungsprozess hat möglicherweise keinen Zugriff auf eine andere Ausgabe des Kodierungsprozesses als die oben angegebene. Das heißt, Sie können das Bild nicht irgendwo hochladen und die URL für den Dekodierungsprozess an ausgeben herunterladen oder so etwas Dummes. "
dbr

6
Ich weiß, ich war sarkastisch.
NiXar


0

Idee: Könnten Sie eine Schriftart als Palette verwenden? Versuchen Sie, ein Bild in eine Reihe von Vektoren zu unterteilen, um sie mit einer Kombination von Vektorsätzen zu beschreiben (jedes Zeichen ist im Wesentlichen ein Satz von Vektoren). Hierbei wird die Schriftart als Wörterbuch verwendet. Ich könnte zum Beispiel al für eine vertikale Linie und a - für eine horizontale Linie verwenden? Nur eine Idee.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.