Défi d'encodage d'images Twitter [fermé]


597

Si une image vaut 1 000 mots, quelle quantité d'image pouvez-vous contenir en 140 caractères?

Remarque : c'est tout! La date limite des primes est arrivée, et après quelques délibérations difficiles, j'ai décidé que l'entrée de Boojum venait à peine de devancer celle de Sam Hocevar . Je publierai des notes plus détaillées une fois que j'aurai eu l'occasion de les rédiger. Bien sûr, tout le monde devrait se sentir libre de continuer à soumettre des solutions et à améliorer les solutions pour que les gens votent. Merci à tous ceux qui ont soumis et participé; Je les ai tous appréciés. Cela a été très amusant pour moi de courir, et j'espère que ça a été amusant pour les participants et les spectateurs.

Je suis tombé sur cet article intéressant sur la compression des images dans un commentaire Twitter, et beaucoup de gens dans ce fil (et un fil sur Reddit ) avaient des suggestions sur différentes façons de le faire. Donc, je pense que ce serait un bon défi de codage; laissez les gens placer leur argent là où se trouve leur bouche et montrez comment leurs idées sur l'encodage peuvent donner plus de détails dans l'espace limité dont vous disposez.

Je vous mets au défi de trouver un système à usage général pour encoder les images en messages Twitter de 140 caractères et les décoder à nouveau en une image. Vous pouvez utiliser des caractères Unicode, vous obtenez donc plus de 8 bits par caractère. Même en autorisant les caractères Unicode, cependant, vous devrez compresser les images dans un très petit espace; ce sera certainement une compression avec perte, et il devra donc y avoir des jugements subjectifs sur la qualité de chaque résultat.

Voici le résultat que l'auteur original, Quasimondo , a obtenu de son encodage (l'image est sous licence Creative Commons Attribution-Noncommercial ): Mona Lisa

Pouvez-vous faire mieux?

Règles

  1. Votre programme doit avoir deux modes: encodage et décodage .
  2. Lors de l' encodage :
    1. Votre programme doit prendre en entrée un graphique dans n'importe quel format graphique matriciel raisonnable de votre choix. Nous dirons que tout format raster pris en charge par ImageMagick compte comme raisonnable.
    2. Votre programme doit générer un message qui peut être représenté en 140 points de code Unicode ou moins; 140 points de code dans l'intervalle U+0000- U+10FFFF, à l' exclusion des non-caractères ( U+FFFE, U+FFFF, U+nFFFE , U+nFFFFn est 1- 10hexadécimal, et la gamme U+FDD0- U+FDEF) et des points de code de substitution ( U+D800- U+DFFF). Il peut être sorti dans n'importe quel encodage raisonnable de votre choix; tout codage pris en charge par GNUiconv sera considéré comme raisonnable, et le codage natif de votre plate-forme ou le codage local serait probablement un bon choix. Voir les notes Unicode ci-dessous pour plus de détails.
  3. Lors du décodage :
    1. Votre programme doit prendre en entrée la sortie de votre mode d' encodage .
    2. Votre programme doit sortir une image dans n'importe quel format raisonnable de votre choix, tel que défini ci-dessus, bien que les formats vectoriels de sortie soient également OK.
    3. La sortie d'image doit être une approximation de l'image d'entrée; plus vous vous rapprochez de l'image d'entrée, mieux c'est.
    4. Le processus de décodage peut n'avoir accès à aucune autre sortie du processus de codage autre que la sortie spécifiée ci-dessus; c'est-à-dire que vous ne pouvez pas télécharger l'image quelque part et sortir l'URL pour le processus de décodage à télécharger, ou quelque chose de stupide comme ça.
  4. Par souci de cohérence dans l'interface utilisateur, votre programme doit se comporter comme suit:

    1. Votre programme doit être un script qui peut être défini sur exécutable sur une plate-forme avec l'interpréteur approprié, ou un programme qui peut être compilé en un exécutable.
    2. Votre programme doit prendre comme premier argument soit encodeou decodede régler le mode.
    3. Votre programme doit prendre des entrées d'une ou plusieurs des manières suivantes (si vous implémentez celui qui prend les noms de fichiers, vous pouvez également lire et écrire à partir de stdin et stdout si les noms de fichiers sont manquants):

      1. Prenez l'entrée de l'entrée standard et produisez la sortie sur la sortie standard.

        my-program encode <input.png >output.txt
        my-program decode <output.txt >output.png
        
      2. Prenez l'entrée d'un fichier nommé dans le deuxième argument et produisez la sortie dans le fichier nommé dans le troisième.

        my-program encode input.png output.txt
        my-program decode output.txt output.png
        
  5. Pour votre solution, veuillez poster:
    1. Votre code, dans son intégralité, et / ou un lien vers celui-ci hébergé ailleurs (s'il est très long, ou nécessite de nombreux fichiers à compiler, ou quelque chose).
    2. Une explication de la façon dont cela fonctionne, si ce n'est pas immédiatement évident d'après le code ou si le code est long et les gens seront intéressés par un résumé.
    3. Une image d'exemple, avec l'image d'origine, le texte vers lequel elle est compressée et l'image décodée.
    4. Si vous construisez sur une idée que quelqu'un d'autre avait, veuillez les attribuer. C'est OK pour essayer d'affiner l'idée de quelqu'un d'autre, mais vous devez les attribuer.

Des lignes directrices

Ce sont essentiellement des règles qui peuvent être brisées, des suggestions ou des critères de notation:

  1. L'esthétique est importante. Je vais juger et suggérer que d'autres personnes jugent, sur la base de:
    1. La qualité de l'image de sortie et son aspect original.
    2. Comme c'est joli le texte. Un charabia complètement aléatoire est OK si vous avez un schéma de compression vraiment intelligent, mais je veux aussi voir des réponses qui transforment les images en poèmes multilingues, ou quelque chose d'intelligent comme ça. Notez que l'auteur de la solution originale a décidé de n'utiliser que des caractères chinois, car cela avait l'air plus agréable de cette façon.
    3. Un code intéressant et des algorithmes intelligents sont toujours bons. J'aime le code court, précis et clair, mais les algorithmes compliqués vraiment intelligents sont aussi OK tant qu'ils produisent de bons résultats.
  2. La vitesse est également importante, mais pas aussi importante que la qualité du travail de compression de l'image que vous faites. Je préfère avoir un programme qui peut convertir une image en un dixième de seconde plutôt que quelque chose qui exécutera des algorithmes génétiques pendant des jours.
  3. Je préférerai des solutions plus courtes à des solutions plus longues, pour autant qu'elles soient raisonnablement comparables en qualité; la concision est une vertu.
  4. Votre programme doit être implémenté dans une langue dont l'implémentation est disponible gratuitement sur Mac OS X, Linux ou Windows. J'aimerais pouvoir exécuter les programmes, mais si vous avez une excellente solution qui ne fonctionne que sous MATLAB ou quelque chose, ça va.
  5. Votre programme doit être aussi général que possible; cela devrait fonctionner pour autant d'images différentes que possible, bien que certaines puissent produire de meilleurs résultats que d'autres. En particulier:
    1. Avoir quelques images intégrées dans le programme auquel il correspond et écrit une référence, puis produit l'image correspondante lors du décodage, est assez boiteux et ne couvrira que quelques images.
    2. Un programme qui peut prendre des images de formes géométriques simples et plates et les décomposer en une primitive vectorielle est assez astucieux, mais s'il échoue sur des images au-delà d'une certaine complexité, il est probablement insuffisamment général.
    3. Un programme qui ne peut prendre que des images d'un rapport d'aspect fixe particulier mais qui fait du bon travail avec elles serait également OK, mais pas idéal.
    4. Vous pouvez constater qu'une image en noir et blanc peut obtenir plus d'informations dans un espace plus petit qu'une image en couleur. D'un autre côté, cela peut limiter les types d'images auxquels elle s'applique; les visages ressortent bien en noir et blanc, mais les motifs abstraits peuvent ne pas être aussi bons.
    5. C'est parfaitement bien si l'image de sortie est plus petite que l'entrée, tout en étant à peu près la même proportion. C'est OK si vous devez redimensionner l'image pour la comparer à l'original; ce qui est important, c'est à quoi ça ressemble.
  6. Votre programme devrait produire une sortie qui pourrait réellement passer par Twitter et sortir indemne. Ce n'est qu'une directive plutôt qu'une règle, car je n'ai trouvé aucune documentation sur l'ensemble précis de caractères pris en charge, mais vous devriez probablement éviter les caractères de contrôle, les caractères de combinaison invisibles géniaux, les caractères à usage privé, etc.

Rubrique de notation

En tant que guide général sur la façon dont je classerai les solutions lors du choix de ma solution acceptée, disons que je vais probablement évaluer les solutions sur une échelle de 25 points (c'est très approximatif, et je ne noterai rien directement, en utilisant simplement ceci comme ligne directrice de base):

  • 15 points pour la façon dont le schéma de codage reproduit une large gamme d'images d'entrée. Il s'agit d'un jugement subjectif et esthétique
    • 0 signifie que cela ne fonctionne pas du tout, il renvoie la même image à chaque fois, ou quelque chose
    • 5 signifie qu'il peut encoder quelques images, bien que la version décodée semble moche et qu'elle ne fonctionne pas du tout sur des images plus compliquées
    • 10 signifie qu'il fonctionne sur une large gamme d'images et produit des images agréables qui peuvent parfois être distinguées
    • 15 signifie qu'il produit des répliques parfaites de certaines images, et même pour des images plus grandes et plus complexes, donne quelque chose qui est reconnaissable. Ou, peut-être que cela ne rend pas les images tout à fait reconnaissables, mais produit de belles images qui sont clairement dérivées de l'original.
  • 3 points pour une utilisation intelligente du jeu de caractères Unicode
    • 0 point pour utiliser simplement l'ensemble des caractères autorisés
    • 1 point pour l'utilisation d'un ensemble limité de caractères pouvant être transférés en toute sécurité sur Twitter ou dans une plus grande variété de situations
    • 2 points pour l'utilisation d'un sous-ensemble thématique de caractères, comme uniquement les idéogrammes Han ou uniquement les caractères de droite à gauche
    • 3 points pour faire quelque chose de vraiment bien, comme générer du texte lisible ou utiliser des caractères qui ressemblent à l'image en question
  • 3 points pour des approches algorithmiques intelligentes et un style de code
    • 0 point pour quelque chose qui représente 1 000 lignes de code uniquement pour réduire l'image, la traiter comme 1 bit par pixel et encoder en base64 qui
    • 1 point pour quelque chose qui utilise une technique d'encodage standard et qui est bien écrit et bref
    • 2 points pour quelque chose qui introduit une technique d'encodage relativement nouvelle, ou qui est étonnamment court et propre
    • 3 points pour une doublure qui produit réellement de bons résultats, ou quelque chose qui innove dans l'encodage graphique (si cela semble être un faible nombre de points pour innover, rappelez-vous qu'un résultat de ce produit aura probablement un score élevé pour l'esthétique ainsi que)
  • 2 points pour la vitesse. Toutes choses étant égales par ailleurs, plus vite c'est mieux, mais les critères ci-dessus sont tous plus importants que la vitesse
  • 1 point pour fonctionner sur un logiciel libre (open source), car je préfère le logiciel libre (notez que C # sera toujours éligible pour ce point tant qu'il fonctionnera en Mono, de même le code MATLAB serait éligible s'il s'exécute sur GNU Octave)
  • 1 point pour avoir suivi toutes les règles. Ces règles sont devenues un peu grosses et compliquées, donc j'accepterai probablement de bonnes réponses qui se trompent un petit détail, mais je donnerai un point supplémentaire à toute solution qui suit réellement toutes les règles

Images de référence

Certaines personnes ont demandé des images de référence. Voici quelques images de référence que vous pouvez essayer; des versions plus petites sont intégrées ici, elles sont toutes liées à des versions plus grandes de l'image si vous en avez besoin:

Lena Mona Lisa Cornell Box Logo StackOverflow

Prix

J'offre une prime de 500 représentants (plus les 50 que StackOverflow entre en jeu) pour la solution que j'aime le mieux, en fonction des critères ci-dessus. Bien sûr, j'encourage tout le monde à voter sur leurs solutions préférées ici également.

Remarque sur la date limite

Ce concours se poursuivra jusqu'à épuisement de la prime, vers 18 h le samedi 30 mai. Je ne peux pas dire l'heure exacte à laquelle il se terminera; il peut être de 17 h à 19 h. Je garantirai que je regarderai toutes les entrées soumises avant 14 heures, et je ferai de mon mieux pour regarder toutes les entrées soumises avant 16 heures; si des solutions sont soumises après cela, je n'aurai peut-être pas la possibilité de leur donner un aperçu juste avant de devoir prendre ma décision. De plus, plus vous soumettez tôt, plus vous aurez de chances de voter pour être en mesure de m'aider à choisir la meilleure solution, alors essayez de soumettre plus tôt plutôt que juste à la date limite.

Notes Unicode

Il y a également eu une certaine confusion sur exactement quels caractères Unicode sont autorisés. La plage de points de code Unicode possibles est U+0000de U+10FFFF. Il existe certains points de code qui ne sont jamais valables pour être utilisés comme caractères Unicode dans tout échange ouvert de données; ce sont les non- caractères et les points de code de substitution . Non - caractères sont définis dans la norme section 5.1.0 Unidode 16,7 comme les valeurs U+FFFE, U+FFFF, U+nFFFE , U+nFFFFn est 1- 10hexadécimal, et la gamme U+FDD0-U+FDEF. Ces valeurs sont destinées à être utilisées pour une utilisation interne spécifique à l'application, et les applications conformes peuvent supprimer ces caractères du texte qu'ils traitent. Les points de code de substitution, définis dans la norme Unicode 5.1.0 section 3.8 as U+D800- U+DFFF, sont utilisés pour coder les caractères au-delà du plan multilingue de base en UTF-16; ainsi, il est impossible de représenter ces points de code directement dans le codage UTF-16, et il n'est pas valide de les coder dans un autre codage. Ainsi, aux fins de ce concours, j'autoriserai tout programme qui code des images dans une séquence de 140 points de code Unicode au maximum de la plage U+0000- U+10FFFF, à l'exclusion de tous les non-caractères et paires de substitution tels que définis ci-dessus.

Je préférerai des solutions qui n'utilisent que des caractères attribués, et encore mieux celles qui utilisent des sous-ensembles intelligents de caractères attribués ou font quelque chose d'intéressant avec le jeu de caractères qu'ils utilisent. Pour une liste des caractères attribués, consultez la base de données de caractères Unicode ; notez que certains caractères sont répertoriés directement, tandis que certains ne sont répertoriés que comme le début et la fin d'une plage. Notez également que les points de code de substitution sont répertoriés dans la base de données, mais interdits comme mentionné ci-dessus. Si vous souhaitez profiter de certaines propriétés des caractères pour rendre le texte que vous sortez plus intéressant, il existe une variété de bases de données d'informations sur les caractères , telles qu'une liste de blocs de code nommés et diverses propriétés de caractères.

Étant donné que Twitter ne spécifie pas le jeu de caractères exact qu'ils prennent en charge, je me montrerai indulgent vis-à-vis des solutions qui ne fonctionnent pas réellement avec Twitter car certains caractères comptent en plus ou certains caractères sont supprimés. Il est préférable, mais non obligatoire, que toutes les sorties codées puissent être transférées indemnes via Twitter ou un autre service de microblogage tel que identi.ca . J'ai vu de la documentation indiquant que Twitter code les entités <,> et &, et les compte donc comme 4, 4 et 5 caractères respectivement, mais je ne l'ai pas testé moi-même, et leur compteur de caractères JavaScript ne semble pas de les compter de cette façon.

Conseils et liens

  • La définition des caractères Unicode valides dans les règles est un peu compliquée. Le choix d'un seul bloc de caractères, comme les idéogrammes unifiés CJC (U + 4E00 – U + 9FCF) peut être plus facile.
  • Vous pouvez utiliser des bibliothèques d'images existantes, comme ImageMagick ou Python Imaging Library , pour votre manipulation d'image.
  • Si vous avez besoin d'aide pour comprendre le jeu de caractères Unicode et ses différents encodages, consultez ce guide rapide ou cette FAQ détaillée sur UTF-8 sous Linux et Unix .
  • Plus tôt vous obtiendrez votre solution, plus je (et les autres personnes votant) devrai y réfléchir. Vous pouvez modifier votre solution si vous l'améliorez; Je baserai ma prime sur la version la plus récente lors de mon dernier examen des solutions.
  • Si vous voulez un format d'image facile à analyser et à écrire (et ne voulez pas simplement utiliser un format existant), je vous suggère d'utiliser le format PPM . Il s'agit d'un format basé sur du texte qui est très facile à utiliser, et vous pouvez utiliser ImageMagick pour convertir vers et depuis celui-ci.

N'hésitez pas à faire des suggestions sur les règles que j'ai écrites dans les commentaires; Je suis certainement prêt à les modifier si les gens pensent qu'ils ont besoin d'éclaircissements ou sont trop sur-spécifiés.
Brian Campbell,

6
Vous devriez probablement dire que télécharger l'image sur un serveur et y poster l'url n'est pas valide.
Shay Erlichmen

2
@Shay N'ai-je pas déjà dit ça? "Le processus de décodage peut ne pas avoir accès à une autre sortie du processus de codage autre que la sortie spécifiée ci-dessus; c'est-à-dire que vous ne pouvez pas télécharger l'image quelque part et sortir l'URL pour le processus de décodage à télécharger, ou quelque chose de stupide comme ça . "
Brian Campbell

1
@Konrad Rudolph Je suis d'accord; Je ne voulais pas dire "idiot" d'un point de vue pratique (clairement, tout ce concours est idiot d'un point de vue pratique), je voulais dire "idiot" dans le contexte de ce concours. L'utilisation d'un URI n'est pas vraiment un algorithme de compression, au sens de la théorie de l'information, car il ne vous permet pas de transférer plus d'informations sans simplement utiliser un canal alternatif. Vous pouvez donner à l'encodeur et au décodeur une grande base de données d'images, et l'appeler compression qui ne fonctionne que sur un ensemble limité d'images, mais j'ai spécifié que vous devez être capable de gérer une image arbitraire.
Brian Campbell,

2
Voici quelques liens que j'ai parcourus qui peuvent aider les gens: azillionmonkeys.com/qed/unicode.html pour une explication de la plage valide de caractères Unicode. Notez que les codages UTF sont ceux qui peuvent coder toute la plage Unicode; UCS-4 est un surensemble de Unicode, et UCS-2 et ASCII sont des sous-ensembles. Et sur le front de la compression, voici une technique similaire à celle du post original, bien qu'il s'autorise 1 Ko plutôt que 350 octets: screamingduck.com/Article.php?ArticleID=46&Show=ABCE
Brian Campbell

Réponses:


244

D'accord, voici le mien: nanocrunch.cpp et le fichier CMakeLists.txt pour le construire en utilisant CMake. Il s'appuie sur l' API Magick ++ ImageMagick pour la plupart de sa gestion d'image. Il nécessite également la bibliothèque GMP pour l'arithmétique bignum pour son codage de chaînes.

J'ai basé ma solution sur la compression d'image fractale, avec quelques rebondissements uniques. L'idée de base est de prendre l'image, de réduire une copie à 50% et de rechercher des pièces dans différentes orientations qui ressemblent à des blocs qui ne se chevauchent pas dans l'image d'origine. Il faut une approche très brutale pour cette recherche, mais cela facilite simplement l'introduction de mes modifications.

La première modification est qu'au lieu de simplement regarder les rotations et les retournements à quatre-vingt-dix degrés, mon programme considère également les orientations à 45 degrés. C'est un bit de plus par bloc, mais cela aide énormément la qualité de l'image.

L'autre chose est que le stockage d'un ajustement de contraste / luminosité pour chacun des composants de couleur de chaque bloc est beaucoup trop cher. Au lieu de cela, je stocke une couleur fortement quantifiée (la palette n'a que 4 * 4 * 4 = 64 couleurs) qui se mélange simplement dans une certaine proportion. Mathématiquement, cela équivaut à un réglage de luminosité variable et de contraste constant pour chaque couleur. Malheureusement, cela signifie également qu'il n'y a pas de contraste négatif pour inverser les couleurs.

Une fois qu'il a calculé la position, l'orientation et la couleur de chaque bloc, il l'encode en une chaîne UTF-8. Tout d'abord, il génère un très grand bignum pour représenter les données dans la table de blocs et la taille de l'image. L'approche est similaire à la solution de Sam Hocevar - une sorte de grand nombre avec un radix qui varie selon la position.

Ensuite, il convertit cela en une base quelle que soit la taille du jeu de caractères disponible. Par défaut, il utilise pleinement le jeu de caractères Unicode attribué, moins le moins que, plus grand que, l'esperluette, le contrôle, la combinaison et les caractères de substitution et privés. Ce n'est pas joli mais ça marche. Vous pouvez également commenter le tableau par défaut et sélectionner à la place des caractères ASCII imprimables 7 bits (à l'exclusion des caractères <,> et &) ou des idéogrammes CJK Unified. Le tableau des codes de caractères disponibles est stocké dans une longueur codée avec des séquences alternées de caractères non valides et valides.

Quoi qu'il en soit, voici quelques images et heures (mesurées sur mon ancien P4 3.0GHz), et compressées à 140 caractères dans l'ensemble unicode assigné décrit ci-dessus. Dans l'ensemble, je suis assez satisfait de la façon dont ils se sont tous déroulés. Si j'avais plus de temps pour travailler là-dessus, j'essaierais probablement de réduire le blocage des images décompressées. Pourtant, je pense que les résultats sont plutôt bons pour le taux de compression extrême. Les images décompressées sont un peu impressionnistes, mais je trouve relativement facile de voir comment les bits correspondent à l'original.

Logo Stack Overflow (8,6 s pour encoder, 7,9 s pour décoder, 485 octets):
http://i44.tinypic.com/2w7lok1.png

Lena (32,8 s pour coder, 13,0 s pour décoder, 477 octets):
http://i42.tinypic.com/2rr49wg.png http://i40.tinypic.com/2rhxxyu.png

Mona Lisa (43,2 s pour coder, 14,5 s pour décoder, 490 octets):
http://i41.tinypic.com/ekgwp3.png http://i43.tinypic.com/ngsxep.png

Edit: CJK Unified Characters

Sam a demandé dans les commentaires sur l'utilisation de ceci avec CJK. Voici une version de Mona Lisa compressée à 139 caractères du jeu de caractères CJK Unified:

http://i43.tinypic.com/2yxgdfk.png 咏 璘 驞 凄 脒 鵚 据 蛥 鸂 拗 朐 朖 辿 韩 瀦 魷 歪 痫 栘 璯 緍 脲 蕜 抱 揎 頻 蓼 債 鑡 嗞 靊 寞 柮 嚛 嚵 籥 聚 聚隤 慛 絖 銓 馿 渫 櫰 矍 昀 鰛 掾 撄 粂 敽 牙 稉 擎 蔍 螎 葙 峬 覧 絀 蹔 抆 惫 冧 笻 哜 搀 澐 芯 譶 辍 澮 垝 黟 偞 媄 童 竽 梀 韠 镰 猳 閺 狌 而 梀伆 杇 婣 唆 鐤 諽 鷍 鴞 駫 搶 毤 埙 誖 萜 愿 旖 鞰 萗 勹 鈱 哳 垬 濅 鬒 秀 瞛 洆 认 気 狋 異 闥 籴 珵 仾 氙 熜 謋 繴 茴 晋 髭 杍 嚖 熥 勳 縿 餅 髭擸 萿

Les paramètres de réglage en haut du programme que j'ai utilisé pour cela étaient: 19, 19, 4, 4, 3, 10, 11, 1000, 1000. J'ai également commenté la première définition de number_assigned et des codes, et je n'ai pas commenté le dernières définitions pour sélectionner le jeu de caractères CJK Unified.


Hou la la! Bon travail. J'étais sceptique quant à la compression d'image fractale pour des images aussi petites, mais cela produit en fait des résultats assez décents. Il était également assez facile à compiler et à exécuter.
Brian Campbell,

1
Merci les gars! Sam, tu veux dire des résultats avec seulement 140 caractères CJK? Si oui, alors oui, vous devrez régler les chiffres en haut. La taille finale en bits est d'environ log2 (steps_in_x steps_in_y steps_in_red steps_in_green steps_in_blue) * blocks_in_x blocks_in_y + log2 (maximum_width maximum_height).
Boojum

Edit: il y a un * 16 dans le premier log2 () que j'ai laissé de côté. Voilà pour les orientations possibles.
Boojum

20
Quelqu'un a-t-il déjà twitter une image en l'utilisant?
dbr

288

fichiers image et source python (versions 1 et 2)

Version 1 Voici ma première tentative. Je mettrai à jour au fur et à mesure.

J'ai le logo SO à 300 caractères presque sans perte. Ma technique utilise la conversion en art vectoriel SVG, donc cela fonctionne mieux en ligne. Il s'agit en fait d'un compresseur SVG, il nécessite encore que l'art original passe par une étape de vectorisation.

Pour ma première tentative, j'ai utilisé un service en ligne pour la trace PNG, mais il existe de nombreux outils gratuits et non gratuits qui peuvent gérer cette partie, y compris Potrace (open-source).

Voici les résultats

Logo SO original http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png Logo SO décodé original http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded.png Après encodage et décodage

Caractères : 300

Temps : non mesuré mais pratiquement instantané (sans les étapes de vectorisation / tramage)

La prochaine étape consistera à incorporer 4 symboles (points et commandes de chemin SVG) par caractère unicode. Pour le moment, ma version python n'a pas de support de caractères large UCS4, ce qui limite ma résolution par caractère. J'ai également limité la plage maximale à l'extrémité inférieure de la plage réservée Unicode 0xD800, mais une fois que j'ai construit une liste de caractères autorisés et un filtre pour les éviter, je peux théoriquement pousser le nombre requis de caractères aussi bas que 70-100 pour le logo ci-dessus.

Une limitation de cette méthode à l'heure actuelle est que la taille de sortie n'est pas fixe. Cela dépend du nombre de nœuds / points vectoriels après vectorisation. L'automatisation de cette limite nécessitera soit une pixellisation de l'image (ce qui supprime le principal avantage des vecteurs), soit une répétition de l'exécution des chemins à travers une étape de simplification jusqu'à ce que le nombre de nœuds souhaité soit atteint (ce que je fais actuellement manuellement dans Inkscape).

Version 2

MISE À JOUR : la v2 est maintenant qualifiée pour concourir. Changements:

  • Entrée / sortie de contrôle de ligne de commande et débogage
  • Utilise l'analyseur XML (lxml) pour gérer SVG au lieu de regex
  • Packs 2 segments de chemin par symbole Unicode
  • Documentation et nettoyage
  • Style de support = "fill: color" et fill = "color"
  • Largeur / hauteur du document regroupées en un seul caractère
  • Couleur du chemin regroupée en un seul caractère
  • La compression des couleurs est obtenue en jetant 4 bits de données de couleur par couleur, puis en les emballant dans un caractère via une conversion hexadécimale.

Caractères : 133

Durée : quelques secondes

v2 décodé http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded-v2.png Après encodage et décodage (version 2)

Comme vous pouvez le voir, il y a cette fois quelques artefacts. Ce n'est pas une limitation de la méthode mais une erreur quelque part dans mes conversions. Les artefacts se produisent lorsque les points sortent de la plage de 0,0 à 127,0 et mes tentatives pour les contraindre ont eu un succès mitigé. La solution consiste simplement à réduire l'image, mais j'ai eu du mal à mettre à l'échelle les points réels plutôt que le plan de travail ou la matrice de groupe et je suis trop fatigué maintenant pour m'en soucier. En bref, si vos points sont dans la plage prise en charge, cela fonctionne généralement.

Je crois que le pli au milieu est dû à une poignée se déplaçant de l'autre côté d'une poignée à laquelle il est lié. Fondamentalement, les points sont trop rapprochés en premier lieu. L'exécution d'un filtre simplifié sur l'image source avant de la compresser devrait résoudre ce problème et raser certains caractères inutiles.

MISE À JOUR : Cette méthode convient aux objets simples, j'avais donc besoin d'un moyen de simplifier les chemins complexes et de réduire le bruit. J'ai utilisé Inkscape pour cette tâche. J'ai eu de la chance avec le nettoyage de chemins inutiles à l'aide d'Inkscape, mais je n'ai pas eu le temps d'essayer de l'automatiser. J'ai fait quelques exemples de svgs en utilisant la fonction 'Simplify' d'Inkscape pour réduire le nombre de chemins.

Simplifier fonctionne bien mais cela peut être lent avec autant de chemins.

exemple d'autotrace 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.war /svg_to_unicode/lena_std_washed_autotrace.png

vignettes tracées http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_autotrace.png

Voici quelques clichés ultra basse résolution. Ceux-ci seraient plus proches de la limite de 140 caractères, bien qu'une compression intelligente du chemin puisse également être nécessaire.

groomed http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_groomed.png Simplifié et moucheté.

trianglulated http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_triangulated.png Simplifié, moucheté et triangulé.

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

CI-DESSUS: Chemins simplifiés utilisant le suivi automatique .

Malheureusement, mon analyseur ne gère pas la sortie de suivi automatique, donc je ne sais pas comment les points peuvent être utilisés ou dans quelle mesure simplifier, malheureusement, il y a peu de temps pour l'écrire avant la date limite. Cependant, il est beaucoup plus facile à analyser que la sortie d'Inkscape.


2
Excellent! Au début, je voulais créer une solution vectorielle hybride avec des arêtes vives et des zones lisses, mais cela s'est avéré beaucoup trop complexe sans utiliser une bibliothèque de traçage (que je ne voulais pas utiliser). J'ai hâte de voir jusqu'où vous pouvez aller avec votre méthode!
sam hocevar

Agréable! J'espérais que nous verrions quelques tentatives d'approches presque sans perte par vectorisation. Cela signifie qu'il a une généralité plus faible, mais une qualité supérieure pour les images qu'il couvre. C'est bien d'utiliser un service en ligne pour la vectorisation. Bonne chance pour réduire encore la taille!
Brian Campbell,

Je considérerais la compression d'image et l'encodage de caractères comme deux étapes différentes - la technique de Sam semble être optimale pour l'encodage, et pourrait facilement être intégrée dans un programme autonome. Vous en aurez plus pour votre argent en vous concentrant sur la partie unique de votre solution (c'est-à-dire la partie de compression) et en sortant simplement une chaîne de bits.
Mark Ransom

70
Sensationnel. Ces images sont vraiment élégantes.
Rinat Abdullin

199

Ma solution complète se trouve sur http://caca.zoy.org/wiki/img2twit . Il présente les caractéristiques suivantes:

  • Temps de compression raisonnable (environ 1 minute pour une haute qualité)
  • Décompression rapide (une fraction de seconde)
  • Conserve la taille originale de l'image (pas seulement le rapport hauteur / largeur)
  • Qualité de reconstruction décente (IMHO)
  • La longueur du message et le jeu de caractères (ASCII, CJK, symboles) peuvent être choisis lors de l'exécution
  • La longueur du message et le jeu de caractères sont détectés automatiquement au moment de la décompression
  • Emballage d'informations très efficace

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

蜥 秓 鋖 筷 聝 诿 缰 偺 腶 漷 庯 祩 皙 靊 谪 獜 岨 幻 寤 厎 趆 脘 搇 梄 踥 桻 理 戂 溥 欇 渹 裏 軱 骿 苸 髙 骟 市 簶 璨 粭 浧 鱉 捕 弫 潮 衍 蚙 浧玧 霫 鏓 蓕 戲 債 鼶 襋 躻 弯 袮 足 庭 侅 旍 凼 飙 驅 據 嘛 掔 倾 诗 籂 阉 嶹 婻 椿 糢 墤 渽 緛 赐 更 儅 棫 武 婩 縑 逡 荨 璙 杯 翉 珸 齸 陁 颗 璙擲 舥 攩 寉 鈶 兓 庭 璱 篂 鰀 乾 丕 耓 庁 錸 努 樀 肝 亖 弜 喆 蝞 躐 葌 熲 谎 蛪 曟 暙 刍 镶 媏 嘝 驌 慸 盂 氤 缰 殾 譑

Voici un aperçu approximatif du processus d'encodage:

  • Le nombre de bits disponibles est calculé à partir de la longueur de message souhaitée et du jeu de caractères utilisable
  • L'image source est segmentée en autant de cellules carrées que le permettent les bits disponibles
  • Un nombre fixe de points (actuellement 2) est affecté à chaque cellule, avec les coordonnées initiales et les valeurs de couleur
  • Ce qui suit est répété jusqu'à ce qu'une condition de qualité soit remplie:
    • Un point est choisi au hasard
    • Une opération est effectuée au hasard sur ce point (le déplacer à l'intérieur de sa cellule, changer sa couleur)
    • Si l'image résultante (voir le processus de décodage ci-dessous) est plus proche de l'image source, l'opération est conservée
  • La taille de l'image et la liste des points sont encodées en UTF-8

Et voici le processus de décodage:

  • La taille et les points de l'image sont lus à partir du flux UTF-8
  • Pour chaque pixel de l'image de destination:
    • La liste des voisins naturels est calculée
    • La couleur finale du pixel est définie comme une moyenne pondérée des couleurs de ses voisins naturels

Ce que je crois être la partie la plus originale du programme, c'est le bitstream. Au lieu d'emballer des valeurs alignées sur les bits ( stream <<= shift; stream |= value), j'emballe des valeurs arbitraires qui ne sont pas dans des plages de puissance de deux ( stream *= range; stream += value). Cela nécessite des calculs de bignum et est bien sûr beaucoup plus lent, mais cela me donne 2009,18 bits au lieu de 1960 lorsque j'utilise les 20902 principaux caractères CJK (c'est trois points de plus que je peux mettre dans les données). Et lorsque j'utilise ASCII, cela me donne 917,64 bits au lieu de 840.

J'ai choisi une méthode pour le calcul initial de l'image qui aurait nécessité des armes lourdes (détection de coin, extraction de caractéristiques, quantification des couleurs ...) car je n'étais pas sûr au début que cela aiderait vraiment. Maintenant, je me rends compte que la convergence est lente (1 minute est acceptable mais elle est néanmoins lente) et je peux essayer de l'améliorer.

La boucle d'ajustement principale est vaguement inspirée de l'algorithme de tramage Direct Binary Seach (où les pixels sont échangés ou inversés de manière aléatoire jusqu'à obtenir une meilleure demi-teinte). Le calcul d'énergie est une simple distance moyenne quadratique, mais j'effectue d'abord un filtre médian 5x5 sur l'image d'origine. Un flou gaussien représenterait probablement mieux le comportement de l'œil humain, mais je ne voulais pas perdre des arêtes vives. J'ai également décidé de ne pas recuire simulé ou d'autres méthodes difficiles à régler car je n'ai pas de mois pour calibrer le processus. Ainsi, l'indicateur "qualité" représente simplement le nombre d'itérations qui sont effectuées sur chaque point avant la fin du codeur.

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

苉 憗 揣 嶕 繠 剳 腏 篮 濕 茝 霮 墧 蒆 棌 杚 蓳 縳 樟 赒 肴 飗 噹 砃 燋 任 朓 峂 釰 靂 陴 貜 犟 掝 喗 讄 荛 砙 矺 敨 鷾 瓔 亨 髎 芟 氲 簵 鸬 嫤 亨激 躙 憮 鄴 甮 槺 骳 佛 愚 猪 駪 惾 嫥 綖 珏 矯 坼 堭 颽 箽 赭 飉 訥 偁 箝 窂 蹻 熛 漧 衆 橼 愀 航 玴 毡 裋 頢 羔 恺 墎 嬔 鑹 楄 瑥 鶼 呍 蕖 抲 鑹苾 绒 酯 嵞 脔 婺 污 囉 酼 俵 菛 琪 棺 则 辩 曚 鸸 職 銛 蒝 礭 鱚 蟺 稿 纡 醾 陴 鳣 尥 蟀 惘 鋁 髚 忩 祤 脤 养 趯 沅 况

Même si toutes les images ne se compressent pas bien, je suis surpris par les résultats et je me demande vraiment quelles autres méthodes existent qui peuvent compresser une image à 250 octets.

J'ai également de petits films sur l'évolution de l' état de l'encodeur à partir d'un état initial aléatoire et d'un "bon" état initial .

Edit : voici comment la méthode de compression se compare au JPEG. À gauche, l'image au-dessus de 536 octets de jamoes. Sur la droite, Mona Lisa compressé à 534 octets en utilisant la méthode décrite ici (les octets mentionnés ici se réfèrent aux octets de données, donc ignorant les bits gaspillés en utilisant des caractères Unicode):

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

Modifier : vient de remplacer le texte CJK par les dernières versions des images.


Je n'ai pas vraiment besoin de pouvoir exécuter le code (j'ai mis la partie sur son exécution dans les directives, à titre de suggestion, pas dans les règles); Je préférerais pouvoir l'exécuter, mais je jugerai cela plus en fonction de la qualité des images que vous générez, du code et des astuces ou algorithmes intéressants. Si je veux l'exécuter et qu'il nécessite des packages que je n'ai pas ou ne veux pas installer sur mon système principal, je peux simplement démarrer une instance Amazon EC2 et l'installer. Tant que vous travaillez avec des bibliothèques regroupées pour l'une des principales distributions, je devrais pouvoir l'exécuter. N'hésitez pas à utiliser CGAL.
Brian Campbell,

2
D'accord, voici ma solution (code source): caca.zoy.org/browser/libpipi/trunk/examples/img2twit.cpp Ma tentative d'explication et quelques exemples se trouvent sur caca.zoy.org/wiki/img2twit
sam hocevar

2
J'aime vraiment ta solution. Vous devriez essayer de réduire le nombre de valeurs attribuées au canal bleu car l'œil humain ne peut pas très bien résoudre le bleu: nfggames.com/games/ntsc/visual.shtm ; cela vous permettra d'avoir plus de détails au détriment de certaines informations de couleur perdues. Ou peut-être l'assigner au vert?
rpetrich

5
Bon point. J'ai essayé quelques variantes de cette idée (voir les commentaires avant la définition de RANGE_X) mais pas très à fond. Comme vous pouvez le voir, l'utilisation de 5 valeurs bleues au lieu de 6 augmentait légèrement moins l'erreur que l'utilisation de 7 valeurs vertes la diminuait. Je n'ai pas essayé de faire les deux par paresse. Un autre problème que j'ai est que je n'ai pas une très bonne fonction d'erreur. J'utilise actuellement ∑ (∆r² + ∆g² + ∆b²) / 3, ce qui fonctionne bien. J'ai essayé ∑ (0,299∆r² + 0,587∆g² + 0,114∆b²), basé (sans justification physique) sur la composante Y de YUV, mais il était trop tolérant avec des erreurs bleues. J'essaierai de trouver des articles sur cette question.
sam hocevar

2
@rpetrich: J'ai modifié le programme pour lui faire augmenter les plages r / g / b dynamiquement tant qu'il y a suffisamment de bits disponibles. Cela garantit que nous ne gaspillons jamais plus de 13 bits dans l'ensemble du flux binaire (mais en pratique, c'est généralement 1 ou 2). Et les images sont légèrement meilleures.
sam hocevar

45

Ce qui suit n'est pas une soumission formelle, car mon logiciel n'a été conçu en aucune façon pour la tâche indiquée. DLI peut être décrit comme un codec d'image avec perte à usage général optimisé. Il s'agit du support d'enregistrement PSNR et MS-SSIM pour la compression d'image, et j'ai pensé qu'il serait intéressant de voir comment il fonctionne pour cette tâche particulière. J'ai utilisé l'image de référence Mona Lisa fournie et je l'ai réduite à 100x150, puis j'ai utilisé DLI pour la compresser à 344 octets.

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

Pour comparer avec les échantillons compressés JPEG et IMG2TWIT, j'ai également utilisé DLI pour compresser l'image à 534 octets. Le JPEG est de 536 octets et IMG2TWIT est de 534 octets. Les images ont été agrandies à environ la même taille pour une comparaison facile. JPEG est l'image de gauche, IMG2TWIT est le centre et DLI est l'image de droite.

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

L'image DLI parvient à conserver certaines des caractéristiques du visage, notamment le célèbre sourire :).


6
Oops. Ce qui précède doit être crédité à Dennis Lee, qui l'a soumis à l'origine. Je viens de le modifier pour intégrer les images en ligne et le lien vers la référence que j'ai trouvée par Google. Et je dois dire, wow, je suis impressionné par la compression. Je vais devoir vérifier la compression DLI.
Brian Campbell,

1
Soit dit en passant, l'auteur de l'IDD mentionne un "long temps de traitement". Comme je ne suis pas en mesure d'exécuter son logiciel, pourriez-vous nous donner des chiffres de temps de compression approximatifs?
sam hocevar

1
En utilisant un AMD Athlon64 2,4 GHz, la compression de l'image 100x150 Mona Lisa prend 38 secondes et la décompression 6 secondes. La compression à un maximum de 251 octets est plus difficile, la qualité de sortie est considérablement réduite. En utilisant l'image de référence Mona Lisa, je l'ai réduite à 60x91, puis j'ai utilisé DLI pour la compresser à 243 octets (la plus proche de 251 sans passer par-dessus). Il s'agit de la sortie i43.tinypic.com/2196m4g.png Le détail n'est pas proche de la DLI de 534 octets même si le débit binaire n'a été réduit que de ~ 50%. La structure de l'image a cependant été assez bien conservée.

1
A décidé de faciliter la comparaison des échantillons compressés de 250 octets. Le DLI de 243 octets a été agrandi et placé à côté de l'échantillon IMG2TWIT. IMG2TWIT à gauche, DLI à droite. Voici l'image i40.tinypic.com/30ndks6.png

1
DLI utilise un paramètre de qualité comme JPEG, donc des essais et erreurs sont nécessaires si une taille de sortie cible est souhaitée.

21

L'aperçu général de ma solution serait:

  1. Je commence par calculer la quantité maximale de données brutes que vous pouvez insérer dans 140 caractères utf8.
    • (Je suppose que utf8, qui est ce que le site Web d' origine prétendait que Twitter avait stocké ses messages. Cela diffère de l'énoncé du problème ci-dessus, qui demande utf16.)
    • En utilisant cette FAQ utf8 , je calcule que le nombre maximum de bits que vous pouvez encoder en un seul caractère utf8 est de 31 bits. Pour ce faire, j'utiliserais tous les caractères qui se trouvent dans la plage U-04000000 - U-7FFFFFFF. (1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx, il y a 31 x, donc je pourrais encoder jusqu'à 31 bits).
    • 31 bits fois 140 caractères équivaut à 4340 bits. Divisez cela par 8 pour obtenir 524,5 et arrondissez-le à 542 octets .
    • (Si nous nous limitons à utf16, nous ne pourrions stocker que 2 octets par caractère, ce qui équivaudrait à 280 octets).
  2. Compressez l'image vers le bas à l'aide de la compression jpg standard.
    • Redimensionnez l'image pour qu'elle soit d'environ 50 x 50 pixels, puis essayez de la compresser à différents niveaux de compression jusqu'à obtenir une image aussi proche de 542 octets que possible sans dépasser.
    • Ceci est un exemple de la mona lisa compressée à 536 octets.
  3. Encodez les bits bruts de l'image compressée en caractères utf-8.
    • Remplacez chaque x dans les octets suivants: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx, avec les bits de l'image.
    • Cette partie serait probablement la partie où la majorité du code devrait être écrite, car il n'y a rien qui existe actuellement qui le fasse.

Je sais que vous demandiez du code, mais je ne veux pas vraiment passer du temps à coder cela. J'ai pensé qu'une conception efficace pourrait au moins inspirer quelqu'un d'autre à coder cela.

Je pense que le principal avantage de ma solution proposée est qu'elle réutilise autant de technologies existantes que possible. Il peut être amusant d'essayer d'écrire un bon algorithme de compression, mais il est garanti qu'il existe un meilleur algorithme, probablement écrit par des personnes qui ont un diplôme en mathématiques supérieures.

Une autre remarque importante est que si l'on décide que utf16 est le codage préféré, alors cette solution s'effondre. les fichiers jpeg ne fonctionnent pas vraiment lorsqu'ils sont compressés à 280 octets. Cependant, il existe peut-être un meilleur algorithme de compression que jpg pour cette déclaration de problème spécifique.


Je suis au travail maintenant, mais je mets définitivement en œuvre cette solution à mon retour.
Paulo Santos

2
D'après mon expérimentation, il semble que UTF-16 soit bien la façon dont Twitter compte les caractères; Les caractères BMP comptent pour 1 et les caractères de niveau supérieur pour 2. Il n'est pas documenté, mais c'est ainsi que leur compteur de caractères JavaScript compte lorsque vous tapez dans la zone de saisie. Il est également mentionné dans les commentaires du fil d'origine. Je n'ai pas essayé de soumettre via l'API pour voir si le compteur est cassé; si c'est le cas, je mettrai à jour le problème pour les contraintes réelles. Cependant, il est peu probable que vous puissiez utiliser UTF-8 arbitraire, car bon nombre de ces séquences plus longues que vous pouvez encoder ne sont pas Unicode valides.
Brian Campbell

4
Après avoir testé avec leur API, il s'avère qu'ils comptent par des caractères Unicode (points de code), pas par des unités de code UTF-16 (c'est le compteur de caractères JavaScript qui compte via UTF-16, puisque c'est apparemment ce que fait la méthode de longueur JavaScript) . Vous pouvez donc y obtenir un peu plus d'informations; les caractères Unicode valides sont compris entre U + 0000 et U + 10FFFF (un peu plus de 20 bits par caractère; 2 ^ 20 + 2 ^ 16 valeurs possibles par caractère). UTF-8 permet d'encoder plus de valeurs que celles autorisées en Unicode, donc si vous vous limitez à Unicode, vous pouvez obtenir environ 350 octets d'espace, pas 542.
Brian Campbell

3
Cette mona lisa de 536 octets a l'air étonnamment bonne, étant donné l'extrême compression!
Chris

3
Nous pouvons actuellement coder 129 775 caractères Unicode différents (attribués, non contrôlés et non privés). Si nous nous limitons à ce sous-ensemble, c'est un total de 2377 bits, ou 297 octets. Code ici: porg.es/blog/what-can-we-fit-in-140-characters
porges

20

D'accord, je suis en retard dans le jeu, mais j'ai quand même fait mon projet.

Il s'agit d'un algorithme génétique jouet qui utilise des cercles colorés translucides pour recréer l'image initiale.

Fonctionnalités:

  • pure Lua. Fonctionne partout où un interprète Lua s'exécute.
  • utilise le format netpbm P3
  • est livré avec une suite complète de tests unitaires
  • conserve la taille originale de l'image

Mis-feautres:

  • lent
  • à ces contraintes d'espace, il ne conserve que le schéma de couleurs de base de l'image initiale et un aperçu général de quelques caractéristiques de celle-ci.

Voici un exemple de twit qui représente Lena: 犭 楊 谷 杌 蒝 螦 界 匘 玏 扝 匮 俄 归 晃 客 猘 摈 硰 划 刀 萕 码 摃 斢 嘁 蜁 嚎 耂 澹 簜 僨 砠 偑 婊 內 團 揕 忈 義 倨 襠 凁 梡岂 掂 戇 耔 攋 斘 眐 奡 萛 狂 昸 箆 亲 嬎 廙 栃 兡 塅 受 橯 恰 应 戞 优 猫 僘 瑩 吱 賾 卣 朸 杈 腠 綍 蝘 猕 屐 稱 悡 ​​詬 來 噩 压 罍 尕 熚 帤 厥 噩虲 兙 罨 縨 炘 排 叁 抠 堃 從 弅 慌 螎 熰 標 宑 簫 柢 橙 拃 丨 蜊 缩 昔 儻 舭 勵 癳 冂 囤 璟 彔 榕 兠 摈 侑 蒖 孂 埮 槃 姠 璐 哠 眛 嫡 琠 枀 訜 璐厇 廩 焛 瀻 严 啘 刱 垫 仔

lena d'origine codé Lena

Le code est dans un référentiel Mercurial sur bitbucket.org. Consultez http://bitbucket.org/tkadlubo/circles.lua


2
Impressionnant! Crée des images soignées et artistiques. Je suis content que les gens y travaillent encore; ça a été très amusant de voir toutes les différentes approches.
Brian Campbell

1
J'aimerais voir cela utilisé comme une superposition transparente sur l'original, donnant quelque chose comme l'effet bokeh.
Nick Radford

19

Ce qui suit est mon approche du problème et je dois admettre que c'était un projet assez intéressant à travailler, il est définitivement en dehors de mon domaine de travail normal et m'a donné quelque chose de nouveau à apprendre.

L'idée de base derrière la mienne est la suivante:

  1. Sous-échantillonner l'échelle de gris de l'image de sorte qu'il y avait un total de 16 nuances différentes
  2. Préformez RLE sur l'image
  3. Emballez les résultats dans les caractères UTF-16
  4. Préformez RLE sur les résultats compressés pour supprimer toute duplication de caractères

Il s'avère que cela fonctionne, mais seulement dans une mesure limitée comme vous pouvez le voir sur les exemples d'images ci-dessous. En termes de sortie, ce qui suit est un exemple de tweet, spécifiquement pour l'image Lena montrée dans les exemples.

乤 乤 万 乐 唂 伂 倂 倁 企 儂 2 企 倁 3 企 倁 2 企 伂 8 企 伂 3 企 伂 5 企 倂 倃 伂 倁 3 企 儁 企 2 伂 倃 5 企 倁 3 企 倃 4 企 倂 企 倁 企 企伂 2 企 伂 5 企 倁 企 伂 쥹 皗 鞹 鐾 륶 䦽 阹 럆 䧜 椿 籫 릹 靭 욶 옷뎷 歩 㰷 歉 䴗 鑹 㞳 鞷 㬼 獴 鏙 돗 鍴 祳 㭾 뤶 殞 焻 乹 Ꮛ 靆 䍼 䍼

Comme vous pouvez le voir, j'ai essayé de contraindre un peu le jeu de caractères; cependant, j'ai rencontré des problèmes lors de l'enregistrement des données de couleur de l'image. En outre, ce schéma de codage a également tendance à gaspiller un tas de bits de données qui pourraient être utilisés pour des informations d'image supplémentaires.

En termes de temps d'exécution, pour les petites images, le code est extrêmement rapide, environ 55 ms pour les exemples d'images fournis, mais le temps augmente avec les images plus grandes. Pour l'image de référence Lena 512x512, le temps de fonctionnement était de 1182 ms. Je dois noter que les chances sont assez bonnes que le code lui-même ne soit pas très optimisé pour les performances (par exemple, tout est travaillé avec un bitmap ), donc les temps pourraient baisser un peu après une refactorisation.

N'hésitez pas à me proposer des suggestions sur ce que j'aurais pu faire de mieux ou ce qui pourrait ne pas être bon avec le code. La liste complète des temps d'exécution et des exemples de sortie se trouve à l'emplacement suivant: http://code-zen.info/twitterimage/

Mettre à jour un

J'ai mis à jour le code RLE utilisé lors de la compression de la chaîne de tweet pour faire un retour en arrière et si c'est le cas, utilisez-le pour la sortie. Cela ne fonctionne que pour les paires de valeurs numériques, mais cela enregistre quelques caractères de données. Le temps d'exécution est plus ou moins le même que la qualité d'image, mais les tweets ont tendance à être un peu plus petits. Je mettrai à jour le tableau sur le site Web au fur et à mesure que je termine les tests. Ce qui suit est l'un des exemples de chaînes de tweet, encore une fois pour la petite version de Lena:

乤 乤 万 乐 唂 伂 倂 倁 企 儂 2 企 倁 3 企 倁 ウ 伂 8 企 伂 エ 伂 5 企 倂 倃 伂 倁 グ 儁 企 2 伂 倃 ガ 倁 ジ 倃 4 企 倂 企 倁 企 伂 ツ 伂 ス 倁企 伂 쥹 皗 鞹 鐾 륶 䦽 阹 럆 䧜 椿 籫 릹 靭 욶 옷뎷 歩 㰷 歉 䴗 鑹 㞳 鞷 㬼 獴 鏙 돗 鍴 祳 㭾 뤶 殞 焻 乹 Ꮛ 靆 䍼

Mettre à jour deux

Une autre petite mise à jour, mais j'ai modifié le code pour regrouper les nuances de couleur en groupes de trois au lieu de quatre, cela utilise un peu plus d'espace, mais à moins que je manque quelque chose, cela devrait signifier que les caractères "étranges" n'apparaissent plus là où la couleur les données sont. De plus, j'ai mis à jour un peu plus la compression pour qu'elle puisse maintenant agir sur la chaîne entière au lieu du bloc de comptage des couleurs. Je teste toujours les temps d'exécution, mais ils semblent être nominalement améliorés; cependant, la qualité d'image est toujours la même. Ce qui suit est la dernière version du tweet de Lena:

2 乤 万 乐 唂 伂 倂 倁 企 儂 2 企 倁 3 企 倁 ウ 伂 8 企 伂 エ 伂 5 企 倂 倃 伂 倁 グ 儁 企 2 伂 倃 ガ 倁 ジ 倃 4 企 倂 企 倁 企 伂 ツ 伂 ス 倁 倁企 伂 坹 坼 坶 坻 刾 啩 容 力 吹 婩 媷 劝 圿 咶 坼 妛 啭 奩 嗆 婣 冷 咛 啫 凃 奉 佶 坍 均 喳 女 媗 决 兴宗 喓 夽 兴 唹 屹 冷 圶 埫 奫 唓 坤 喝 奎 似商 嗉 乃

Logo StackOverflow 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, merci pour l'entrée! Les niveaux de gris fonctionnent en fait assez bien pour la plupart d'entre eux, bien que Lena soit un peu difficile à distinguer. Je cherchais votre source mais j'ai obtenu un 404; pourriez-vous vous assurer que c'est là-haut?
Brian Campbell

Vérifiez-le maintenant, je mettais à jour le site, vous m'avez peut-être surpris entre les mises à jour.
rjzii

Oui, je peux le télécharger maintenant. Maintenant, bien sûr, je dois déterminer si je peux faire en sorte que Mono le compile.
Brian Campbell

Oui! Fonctionne sous Mono, j'ai compilé avec "gmcs -r System.Drawing TwitterImage.cs Program.cs" et je l'ai exécuté avec "mono TwitterImage.exe encode lena.png lena.txt"
Brian Campbell

Cool! J'ai vérifié deux fois pour m'assurer que les bibliothèques que j'utilisais étaient répertoriées pour Mono, mais je n'ai pas encore travaillé avec Mono, donc je ne savais pas si c'était le cas ou non.
rjzii


12

Dans le défi d'origine, la taille limite est définie comme ce que Twitter vous permet toujours d'envoyer si vous collez votre texte dans leur zone de texte et appuyez sur "Mettre à jour". Comme certaines personnes l'ont correctement remarqué, cela est différent de ce que vous pourriez envoyer sous forme de SMS depuis votre mobile.

Ce qui n'est pas explicitement mentionné (mais quelle était ma règle personnelle), c'est que vous devriez pouvoir sélectionner le message tweeté dans votre navigateur, le copier dans le presse-papiers et le coller dans un champ de saisie de texte de votre décodeur afin qu'il puisse l'afficher. Bien sûr, vous êtes également libre d'enregistrer le message sous forme de fichier texte et de le relire ou d'écrire un outil qui accède à l'API Twitter et filtre tout message qui ressemble à un code image (marqueurs spéciaux pour tout le monde? Wink wink ). Mais la règle est que le message doit être passé par Twitter avant d'être autorisé à le décoder.

Bonne chance avec les 350 octets - je doute que vous puissiez les utiliser.


1
Oui, j'ai ajouté une rubrique de notation qui indique que des restrictions plus strictes sur le jeu de caractères sont préférées, mais pas obligatoires. Je voudrais avoir une règle qui exige que les messages passent indemnes sur Twitter, mais cela prendrait beaucoup d'essais et d'erreurs pour comprendre les détails précis de ce qui fonctionne, et je voulais laisser une certaine latitude pour permettre des utilisations créatives de la espace de code. Ainsi, la seule exigence de mon défi est de 140 caractères Unicode valides. Au fait, merci d'être passé! J'aime vraiment votre solution et je veux voir si l'un des kibitzers peut réellement l'améliorer.
Brian Campbell,

12

La publication d'une image monochrome ou en niveaux de gris devrait améliorer la taille de l'image qui peut être encodée dans cet espace car vous ne vous souciez pas de la couleur.

Augmentant éventuellement le défi de télécharger trois images qui, lorsqu'elles sont recombinées, vous donnent une image en couleur tout en conservant une version monochrome dans chaque image distincte.

Ajoutez une compression à ce qui précède et cela pourrait commencer à sembler viable ...

Agréable!!! Maintenant, vous avez piqué mon intérêt. Aucun travail ne sera fait pour le reste de la journée ...


9
s / a atteint un pic / piqué / g
onze81

1
J'aime l'idée de trois images, il devrait être possible de mettre en œuvre une telle idée sur Twitter et le résultat serait plutôt bon.
Makis

9

Concernant la partie encodage / décodage de ce challenge. base16b.org est ma tentative de spécifier une méthode standard pour coder en toute sécurité et efficacement les données binaires dans les plans Unicode supérieurs.

Certaines fonctionnalités :

  • Utilise uniquement les zones utilisateur privées d'Unicode
  • Encode jusqu'à 17 bits par caractère; près de trois fois plus efficace que Base64
  • Une implémentation Javascript de référence d'encodage / décodage est fournie
  • Certains exemples d'encodages sont inclus, y compris Twitter et Wordpress

Désolé, cette réponse arrive beaucoup trop tard pour le concours d'origine. J'ai commencé le projet indépendamment de ce post, que j'ai découvert à mi-chemin.


8

L'idée de stocker un tas d'images de référence est intéressante. Serait-il si mal de stocker, disons, 25 Mo d'échantillons d'images, et que l'encodeur essaie de composer une image en utilisant des bits de ceux-ci? Avec un tuyau aussi minuscule, la machinerie à chaque extrémité va nécessairement être beaucoup plus grande que le volume de données qui la traverse, alors quelle est la différence entre 25 Mo de code et 1 Mo de code et 24 Mo de données d'image?

(notez que les directives originales excluaient de restreindre l'entrée aux images déjà dans la bibliothèque - je ne le suggère pas).


1
Ce serait bien, tant que vous disposez d'une quantité fixe et finie de données sur l'un ou l'autre des terminaux. Bien sûr, vous devrez démontrer qu'il fonctionne avec des images qui ne sont pas dans l'ensemble de formation, comme tout problème de processus de langage naturel statistique. J'adorerais voir quelque chose qui adopte une approche statistique du codage d'image.
Brian Campbell

16
Pour ma part, j'aimerais voir Mona Lisa refaite en utilisant uniquement le fan art de Boba Fett comme source.
Nosredna

Je suis d'accord - l'approche de la photomosaïque semble être dans les règles et serait extrêmement intéressante de voir quelqu'un essayer.
An̲̳̳drew

8

Idée stupide, mais sha1(my_image)qui aboutirait à une représentation "parfaite" de toute image (en ignorant les collisions). Le problème évident est que le processus de décodage nécessite des quantités excessives de forçage brutal.

Le monochrome 1 bit serait un peu plus facile. Chaque pixel devient un 1 ou 0, vous auriez donc 1000 bits de données pour une image de 100 * 100 pixels. Étant donné que le hachage SHA1 est de 41 caractères, nous pouvons en contenir trois dans un seul message, il suffit de forcer brutalement 2 ensembles de 3333 bits et un ensemble de 3334 (bien que même cela soit probablement encore démesuré)

Ce n'est pas exactement pratique. Même avec l'image 1 bit 100 * 100px de longueur fixe, il y a .., en supposant que je ne fais pas de mauvais calculs, 49995000 combinaisons ou 16661667 lorsqu'il est divisé en trois.

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
Le problème avec sha1 (my_image) est que si vous passiez votre temps à le forcer brutalement, vous trouveriez probablement de nombreuses collisions avant de trouver la vraie image; et bien sûr, le forçage brutal sha1 est pratiquement impossible à calculer.
Brian Campbell,

5
Encore mieux que la compression SHA1: mon algorithme de compression "flickr"! Étape 1: téléchargez l'image sur flickr. Étape 2: publiez un lien vers celui-ci sur Twitter. Tadda! Seulement 15 octets utilisent!
niXar

2
niXar: Non, règle 3.4: "Le processus de décodage peut n'avoir accès à aucune autre sortie du processus de codage autre que la sortie spécifiée ci-dessus; autrement dit, vous ne pouvez pas télécharger l'image quelque part et sortir l'URL du processus de décodage vers télécharger, ou quelque chose de stupide comme ça. "
dbr

6
Je sais, j'étais sarcastique.
niXar


0

Idée: pourriez-vous utiliser une police comme palette? Essayez de briser une image dans une série de vecteurs en essayant de les décrire avec une combinaison d'ensembles de vecteurs (chaque caractère est essentiellement un ensemble de vecteurs). Cela utilise la police comme dictionnaire. Je pourrais par exemple utiliser al pour une ligne verticale et a - pour une ligne horizontale? Juste une idée.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.