web-dev-qa-db-fra.com

Défi d'encodage d'image Twitter

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

Note: C'est ça les gars! La date limite pour les primes est arrivée, et après de longues délibérations, j'ai décidé que entrée de Boojum à peine dépassé celle de Sam Hocevar . Je posterai des notes plus détaillées une fois que j'aurai eu l'occasion de les écrire. Bien sûr, tout le monde devrait pouvoir continuer à soumettre des solutions et à améliorer les solutions sur lesquelles les gens pourront voter. Merci à tous ceux qui ont soumis leur candidature. Je les ai tous appréciés. C’est très amusant pour moi de courir et j’espère que c’est amusant aussi bien pour les participants que pour les spectateurs.

Je suis tombé sur ce post intéressant d'essayer de compresser des images dans un commentaire Twitter, et beaucoup de personnes dans ce fil (et un fil sur Reddit ) avaient des suggestions sur les différentes façons dont vous pourrait le faire. Donc, je pense que cela constituerait un bon défi de codage; laissez les gens placer leur argent là où ils se trouvent 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 mettre au point un système polyvalent permettant d’encoder des images dans des messages Twitter de 140 caractères et de les décoder à nouveau dans une image. Vous pouvez utiliser des caractères Unicode pour obtenir plus de 8 bits par caractère. Même en tenant compte des caractères Unicode, vous devrez toutefois compresser les images dans un espace très restreint. il s'agira certainement d'une compression avec perte, de sorte qu'il faudra faire des jugements subjectifs sur la qualité de chaque résultat.

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

Pouvez-vous faire mieux?

Règles

  1. Votre programme doit avoir deux modes: encoding et decoding.
  2. Quand encodage:
    1. Votre programme doit prendre en entrée un graphique dans n’importe quel format graphique raisonnable raster de votre choix. Nous dirons que tout format de raster pris en charge par ImageMagick est considéré comme raisonnable.
    2. Votre programme doit générer un message pouvant être représenté en 140 points de code Unicode ou moins; 140 points de code dans la plage U+0000U+10FFFF, à l'exclusion des non-caractères (U+FFFE, U+FFFF, U+ n FFFE, U+ n FFFF n est 110 hexadécimal et la plage U+FDD0U+FDEF) et les points de code de substitution (U+D800U+DFFF). Il peut être sorti dans n'importe quel encodage raisonnable de votre choix; tout codage pris en charge par GNU iconv sera considéré comme raisonnable, et le codage natif de votre plate-forme ou le codage des paramètres régionaux sera probablement un bon choix. Voir Notes Unicode ci-dessous pour plus de détails.
  3. Quand décodage:
    1. Votre programme doit prendre en entrée la sortie de votre mode encoding.
    2. Votre programme doit générer une image dans tout format raisonnable de votre choix, tel que défini ci-dessus, bien que les formats de vecteurs de sortie soient également acceptables.
    3. La sortie de l'image doit être une approximation de l'image d'entrée. plus vous pouvez vous rapprocher de l'image d'entrée, mieux c'est.
    4. 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; En d'autres termes, vous ne pouvez pas télécharger l'image quelque part et générer l'URL du processus de décodage à télécharger, ou quelque chose d'aussi idiot que ç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 pouvant être configuré pour être exécutable sur une plate-forme avec l'interpréteur approprié, ou un programme pouvant être compilé en un exécutable.
    2. Votre programme doit prendre comme premier argument soit encode ou decode pour définir le mode.
    3. Votre programme doit accepter les entrées de l’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 de stdout si des 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 une entrée d'un fichier nommé dans le deuxième argument et produisez une 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, en entier, et/ou un lien vers celui-ci hébergé ailleurs (s'il est très long, ou nécessite la compilation de nombreux fichiers, ou quelque chose du genre).
    2. Une explication de la façon dont cela fonctionne, si ce n'est pas immédiatement évident ou si le code est long et que les gens seront intéressés par un résumé.
    3. Un exemple d'image, avec l'image d'origine, le texte compressé et l'image décodée.
    4. Si vous vous appuyez sur une idée que quelqu'un d'autre avait, merci de l'attribuer. C'est bien d'essayer de raffiner l'idée de quelqu'un d'autre, mais vous devez l'attribuez.

Des lignes directrices

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

  1. L'esthétique est importante. Je vais juger et suggérer que les autres jugent, sur la base de:
    1. Qualité de l'image de sortie et qualité de l'image d'origine.
    2. Comme c'est gentil le texte. Si vous avez un schéma de compression vraiment intelligent, vous pouvez utiliser gobbledigook complètement au hasard, 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 d'origine a décidé de n'utiliser que des caractères chinois, car cela lui paraissait plus joli.
    3. Un code intéressant et des algorithmes intelligents sont toujours bons. J'aime les codes courts, précis et clairs, mais des algorithmes compliqués très intelligents sont également acceptables 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. Je préférerais avoir un programme capable de convertir une image en un dixième de seconde plutôt que quelque chose qui utilisera des algorithmes génétiques pendant des jours.
  3. Je préférerai les solutions plus courtes aux solutions plus longues, à condition que leur qualité soit raisonnablement comparable. la concision est une vertu.
  4. Votre programme doit être implémenté dans un langage librement implémenté sous 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 du genre, c'est très bien.
  5. Votre programme devrait ê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 capable de prendre des images de formes géométriques simples, plates et géométriques et de les décomposer en primitives vectorielles est assez astucieux, mais s'il échoue sur des images dépassant une certaine complexité, il est probablement trop peu général.
    3. Un programme qui ne peut prendre que des images ayant un rapport de format déterminé, mais qui fait un bon travail avec ces images serait également OK, mais pas idéal.
    4. Vous constaterez peut-être qu'une image en noir et blanc peut contenir plus d'informations dans un espace plus petit qu'une image en couleur. D'autre part, cela peut limiter les types d'images auxquels il est applicable; les visages sortent très bien en noir et blanc, mais les motifs abstraits ne résistent peut-être pas aussi bien.
    5. Cela convient parfaitement si l’image de sortie est plus petite que l’entrée, tout en ayant à peu près les mêmes proportions. Ce n'est pas grave 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 en réalité passer par Twitter et en ressortir indemne. Il ne s'agit que d'une règle plutôt que d'une règle, car je ne trouvais aucune documentation sur l'ensemble de caractères pris en charge, mais vous devriez probablement éviter les caractères de contrôle, les combinaisons de combinaison invisibles, les caractères d'utilisation privée, etc.

Rubrique de notation

En guise de guide général sur la manière dont je classerai les solutions lors du choix de la 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 marquerai rien directement, simplement en utilisant ceci comme ligne directrice de base):

  • 15 points pour la qualité avec laquelle le schéma de codage reproduit une large gamme d'images d'entrée. C’est un jugement subjectif, esthétique
    • 0 signifie que cela ne fonctionne pas du tout, cela donne la même image à chaque fois, ou quelque chose comme ça
    • 5 signifie qu'il peut encoder quelques images, bien que la version décodée paraisse moche et qu'elle ne fonctionne pas du tout sur des images plus complexes
    • 10 signifie que cela 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 de reconnaissable. Ou peut-être ne crée-t-il pas des images tout à fait reconnaissables, mais de belles images clairement dérivées de l'original.
  • 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 nombre 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, tels que 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 un texte lisible ou utiliser des caractères qui ressemblent à l'image en question
  • points pour les approches algorithmiques intelligentes et le style de code
    • 0 point pour quelque chose qui correspond à 1000 lignes de code uniquement pour réduire l'image, la traiter comme 1 bit par pixel et encoder en base64
    • 1 point pour quelque chose qui utilise une technique de codage standard et qui est bien écrit et bref
    • 2 points pour quelque chose qui introduit une technique de codage relativement nouvelle, ou qui est étonnamment court et net
    • 3 points pour une doublure qui produit de bons résultats, ou quelque chose qui innove en matière d'encodage graphique (si cela semble être un nombre faible de points pour innover, rappelez-vous qu'un résultat qui aura probablement un score élevé en matière d'esthétique ainsi que)
  • 2 points pour la vitesse. Toutes choses étant égales par ailleurs, plus vite est mieux, mais les critères ci-dessus sont tous plus importants que la vitesse.
  • 1 point ​​pour l'exécution 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 fonctionne sur Mono, le code MATLAB le serait aussi si il tourne sur GNU octave)
  • 1 point ​​pour avoir suivi toutes les règles. Ces règles sont devenues un peu volumineuses et compliquées, je vais donc probablement accepter d'autres bonnes réponses qui ne tiennent pas compte d'un petit détail, mais je donnerai un point supplémentaire à toute solution qui respecte 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 incorporées ici, elles sont toutes liées à des versions plus grandes de l'image si vous avez besoin de celles-ci:

LenaMona LisaCornell BoxStackOverflow Logo

Prix

Je propose un prime de 500 représentants (plus les 50 que StackOverflow lance) pour la solution qui me convient le mieux, en fonction des critères ci-dessus. Bien sûr, j'encourage tous les autres à voter sur leurs solutions préférées ici aussi.

Note sur la date limite

Ce concours durera jusqu’à épuisement de la prime, soit environ 6 PM le samedi 30 mai. Je ne peux pas dire exactement quand il se terminera; il peut être n'importe où de 17h à 19h. Je garantirai que je regarderai toutes les inscriptions soumises avant 14 heures et que je ferai de mon mieux pour examiner toutes les entrées soumises avant 16 heures; si des solutions sont présentées par la suite, je n'aurai peut-être pas l'occasion de les examiner de manière juste avant de prendre ma décision. En outre, plus vous soumettez tôt, plus vous aurez de chances de voter pour pouvoir m'aider à choisir la meilleure solution; essayez donc de le soumettre plus tôt plutôt que juste avant la date limite.

Notes Unicode

Il y a également eu une certaine confusion sur les caractères Unicode autorisés. La plage de points de code Unicode possibles va de U+0000 à U+10FFFF. Certains points de code ne peuvent jamais être utilisés comme caractères Unicode dans tout échange de données ouvert; ce sont les non caractères et les points de code de substitution. Les caractères non définis sont définis dans le section 16.7 de la norme Unidode Standard 5.1. comme les valeurs U+FFFE, U+FFFF, U+ n FFFE, U+ n FFFF n est 110 hexadécimal et la plage U+FDD0U+FDEF. Ces valeurs sont destinées à être utilisées pour une utilisation interne spécifique à une application. Les applications conformes peuvent supprimer ces caractères du texte traité par elles. Les points de code de substitution, définis dans le section 3.8 de la norme Unicode 5.1. comme U+D800U+DFFF, servent à coder des caractères au-delà du plan multilingue de base dans 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, pour les besoins de ce concours, je permettrai à tout programme encodant des images dans une séquence ne dépassant pas 140 points de code Unicode de la plage U+0000U+10FFFF, à l'exclusion de tous les non-caractères et paires de substitution. défini ci-dessus.

Je préférerai des solutions qui utilisent uniquement des caractères attribués, et même de meilleures solutions qui utilisent des sous-ensembles astucieux de caractères attribués ou font quelque chose d'intéressant avec le jeu de caractères utilisé. Pour obtenir une liste des caractères attribués, voir le base de données de caractères Unicode ; notez que certains caractères sont listés directement, tandis que d'autres ne sont listés que comme début et fin de plage. Notez également que les points de code de substitution sont répertoriés dans la base de données, mais interdits comme indiqué ci-dessus. Si vous souhaitez tirer parti de certaines propriétés des caractères pour rendre le texte que vous imprimez plus intéressant, il existe un variété de bases de données d'informations sur les caractères disponible, tel qu'un liste de codes nommés blocs et propriétés de caractères différentes .

Étant donné que Twitter ne spécifie pas le jeu de caractères exact qu’ils prennent en charge, je serai indulgent sur les 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 pas obligatoire, que toutes les sorties codées puissent être transférées indemnes via Twitter ou un autre service de micro-blogging tel que identi.ca . J'ai vu de la documentation indiquant que Twitter encode les entités <,>, et &, et compte donc 4, 4 et 5 caractères respectivement, mais je ne l'ai pas testé moi-même et le compteur de caractères JavaScript ne semble pas les compter de cette façon.

Conseils et liens

  • La définition de caractères Unicode valides dans les règles est un peu compliquée. Choisir un seul bloc de caractères, tel que les idéogrammes unifiés CJK (U + 4E00 – U + 9FCF) peut s'avérer plus facile.
  • Vous pouvez utiliser des bibliothèques d’images existantes, telles que ImageMagick ou Bibliothèque d’imagerie Python , pour la manipulation de vos images.
  • Si vous avez besoin d’aide pour comprendre le jeu de caractères Unicode et ses divers codages, voir ce guide rapide ou ce FAQ détaillé sur UTF-8 sous Linux et Unix =.
  • Plus tôt vous obtiendrez votre solution, plus il faudra que je (et d’autres personnes qui votent) y jettent un coup d’œil. Vous pouvez modifier votre solution si vous l'améliorez. Je me baserai 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 que vous ne voulez pas utiliser uniquement un format existant), nous vous suggérons d'utiliser le format format PPM . C'est un format texte très facile à utiliser, et vous pouvez utiliser ImageMagick pour le convertir.
597
Brian Campbell

Bon, voici le mien: nanocrunch.cpp et le fichier CMakeLists.txt pour le construire à l'aide de CMake. Il s'appuie sur le Magick ++ API ImageMagick pour la plupart de sa gestion des images. Elle nécessite également la bibliothèque GMP pour l'arithmétique bignum pour son codage de chaîne.

J'ai basé ma solution sur la compression d'images fractales, avec quelques modifications uniques. L'idée de base est de prendre l'image, de réduire une copie à 50% et de rechercher des morceaux dans différentes orientations qui ressemblent à des blocs ne se chevauchant pas dans l'image d'origine. Cette approche nécessite une approche très brutale, 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 à 90 degrés, mon programme prend également en compte les orientations à 45 degrés. C'est un bit de plus par bloc, mais cela améliore énormément la qualité de l'image.

L'autre chose est que le stockage d'un réglage de contraste/luminosité pour chacune des composantes de couleur de chaque bloc est beaucoup trop coûteux. Au lieu de cela, je stocke une couleur fortement quantifiée (la palette ne contient que 4 * 4 * 4 = 64 couleurs) qui est simplement mélangée dans une certaine proportion. Mathématiquement, cela équivaut à une luminosité variable et à un contraste constant pour chaque couleur. Malheureusement, cela signifie également qu’il n’ya pas de contraste négatif pour inverser les couleurs.

Une fois la position, l’orientation et la couleur calculées pour chaque bloc, il les code dans 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. Cette approche est similaire à la solution de Sam Hocevar: un grand nombre avec une base variable qui varie en fonction de la position.

Ensuite, il convertit cela en une base de la taille du jeu de caractères disponible. Par défaut, il utilise pleinement le jeu de caractères unicode attribué, moins les caractères inférieur à, supérieur à, et commercial, les caractères de contrôle, de combinaison, de substitution et privés. Ce n'est pas joli mais ça marche. Vous pouvez également commenter la table par défaut et sélectionner à la place les ASCII imprimables 7 bits (à nouveau en excluant les caractères <,> et &) ou les idéogrammes unifiés CJK. La table contenant les codes de caractères disponibles est stockée avec une longueur de code codée avec des cycles alternés de caractères non valides et valides.

Quoi qu'il en soit, voici quelques images et moments (mesurés sur mon ancien P4 à 3,0 GHz), compressés à 140 caractères dans le jeu complet Unicode attribué décrit ci-dessus. Dans l’ensemble, je suis assez satisfait de la façon dont ils ont tous évolué. Si j'avais plus de temps pour travailler là-dessus, j'essaierais probablement de réduire le blocage des images décompressées. Néanmoins, 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 qu'il est relativement facile de voir comment les bits correspondent à l'original.

Logo de débordement de pile (8,6 s à coder, 7,9 s à décoder, 485 octets):
http://i44.tinypic.com/2w7lok1.png

Lena (32.8s à encoder, 13.0s à décoder, 477 octets):
http://i42.tinypic.com/2rr49wg.pnghttp://i40.tinypic.com/2rhxxyu.png

Mona Lisa (43.2s à encoder, 14.5s à décoder, 490 octets):
http://i41.tinypic.com/ekgwp3.pnghttp://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 au sommet du programme que j'ai utilisé à cet effet sont: 19, 19, 4, 4, 3, 10, 11, 1000, 1000. J'ai également commenté la première définition de number_assigned et de codes, et décommentée le dernières définitions pour sélectionner le jeu de caractères CJK Unified.

244
Boojum

fichiers image et python source (versions 1 et 2)

Version 1 Voici ma première tentative. Je vais mettre à jour que je vais.

J'ai le logo SO à 300 caractères, presque sans perte. Ma technique utilise la conversion en dessin vectoriel SVG, de sorte que cela fonctionne mieux sur le dessin au trait. C’est en fait un compresseur SVG, il faut 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 BEAUCOUP d’outils gratuits et non-libres pouvant gérer cette partie, notamment potrace (Open source).

Voici les résultats

Original SO Logo http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png Original décodé SO Logo http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded.png après le codage et le décodage

Caractères : 300

Time : non mesuré mais pratiquement instantané (n'incluant pas les étapes de vectorisation/rastérisation)

La prochaine étape consistera à intégrer 4 symboles (points de chemin SVG et commandes) par caractère Unicode. Pour le moment, ma construction python ne prend pas en charge les caractères étendus 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. Cependant, une fois que je construis une liste de caractères autorisés et un filtre pour les éviter, je peux théoriquement indiquer le nombre de caractères requis aussi bas que 70-100 pour le premier. 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 la vectorisation. L'automatisation de cette limite nécessitera soit de pixeliser l'image (ce qui supprime le principal avantage des vecteurs), soit de répéter 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

UPDATE: la v2 est maintenant qualifiée pour concurrencer. Changements:

  • Contrôle en ligne de commande entrée/sortie et débogage
  • Utilise un analyseur XML (lxml) pour gérer SVG au lieu de regex
  • Packs 2 segments de chemin par symbole Unicode
  • Documentation et nettoyage
  • Support style = "fill: color" et fill = "color"
  • Largeur/hauteur du document dans un seul caractère
  • Couleur du chemin intégrée à un seul caractère
  • La compression des couleurs est obtenue en jetant 4 bits de données de couleur par couleur, puis en les intégrant dans un caractère par conversion hexadécimale.

Caractères : 133

Time : quelques secondes

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

Comme vous pouvez le voir, il y a des artefacts cette fois-ci. 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 0,0 - 127,0 et que 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 à réduire les points réels plutôt que la matrice de groupe ou d’artboard et je suis trop fatigué 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 coude au milieu est dû à une poignée qui se déplace de l’autre côté d’une poignée à laquelle elle est liée. Fondamentalement, les points sont trop proches les uns des autres. L'exécution d'un filtre simplifié sur l'image source avant de la compresser devrait résoudre ce problème et éliminer certains caractères inutiles.

UPDATE: Cette méthode convient aux objets simples. Il me fallait donc un moyen de simplifier les chemins complexes et de réduire le bruit. J'ai utilisé Inkscape pour cette tâche. J'ai eu un peu de chance avec la création de chemins inutiles avec Inkscape, mais je n'ai pas eu le temps d'essayer de l'automatiser. J'ai créé 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 de traçage automatique http://www.warriorhut.org/graphics/svg_to_unicode/autotrace_16_color_manual_reduction.pngcornell box http://www.warriorhut.com/ graphics/svg_to_unicode/cornell_box_simplified.pnglena http://www.warriorhut.com/graphics/svg_to_unicode/lena_std_washed_autotrace.png

miniatures suivies http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_autotrace.png

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

soigné http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_groomed.png Simplifié et dépouillé.

trianglulé http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_triangulated.png Simplifié, nettoyé 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 autotrace .

Malheureusement, mon analyseur ne gère pas la sortie de trace automatique, donc je ne sais pas comment les points peuvent être utilisés ni dans quelle mesure ils peuvent être simplifiés. Malheureusement, il reste peu de temps pour l'écrire avant la date limite. Il est cependant beaucoup plus facile d'analyser que la sortie inkscape.

288
SpliFF

Ma solution complète peut être trouvée à http://caca.zoy.org/wiki/img2twit . Il présente les caractéristiques suivantes:

  • Temps de compression raisonnable (environ 1 minute pour une qualité supérieure)
  • Décompression rapide (une fraction de seconde)
  • Conserve la taille de l'image d'origine (pas seulement le format)
  • Qualité de reconstruction décente (IMHO)
  • La longueur du message et le jeu de caractères (ASCII, CJK, symboles) peuvent être choisis au moment 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
  • Information très efficace

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

鋖鏓攩

Voici un aperçu du processus de codage:

  • 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, en changer la 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 codées en UTF-8

Et voici le processus de décodage:

  • La taille de l'image et les points 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 est le bitstream. Au lieu de compresser les valeurs alignées sur les bits (stream <<= shift; stream |= value), je compresse des valeurs arbitraires qui ne sont pas comprises dans la plage de puissance deux (stream *= range; stream += value). Ceci 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 les caractères principaux CJK 20902 sont utilisés (c’est trois points supplémentaires que je peux mettre dans les données). Et lorsque vous utilisez ASCII, cela me donne 917,64 bits au lieu de 840.

J'ai décidé de ne pas utiliser de méthode lourde pour le calcul initial des images (détection des angles, extraction des fonctions, quantification des couleurs, etc.), car je ne savais pas au départ que cela aiderait vraiment. Maintenant, je me rends compte que la convergence est lente (1 minute est acceptable, mais c'est quand même lent) et je pourrais essayer de l'améliorer.

La boucle de réglage principale est vaguement inspirée de l'algorithme de dithering Direct Binary Seach (où les pixels sont échangés ou retournés de manière aléatoire jusqu'à l'obtention d'un meilleur demi-ton). Le calcul de l'énergie est une distance racine-moyenne-carré simple, mais je réalise 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 de contours nets. J'ai également décidé de ne pas appliquer de recuit simulé ni d'autres méthodes difficiles à ajuster, car je ne dispose pas de mois pour calibrer le processus. Ainsi, le drapeau "qualité" représente simplement le nombre d'itérations effectuées sur chaque point avant la fin du codeur.

http://caca.zoy.org/raw-attachment/wiki/img2twit/Mona_Lisa_scaled.jpghttp://caca.zoy.org/raw-attachment/wiki/img2twit/ Twitter2.png

揣憮酯

Même si toutes les images ne se compressent pas bien, les résultats me surprennent et je me demande vraiment quelles sont les autres méthodes permettant de compresser une image à 250 octets.

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

Edit : voici comment la méthode de compression se compare à JPEG. À gauche, l'image de Jamoes est supérieure à 536 octets. À droite, Mona Lisa a compressé jusqu'à 534 octets à l'aide de la méthode décrite ici (les octets mentionnés ici font référence à des octets de données, ignorant ainsi les bits perdus à l'aide de caractères Unicode):

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

Modifier : vient de remplacer le texte CJK par les versions les plus récentes des images.

199
sam hocevar

Ce qui suit n’est pas une soumission formelle, car mon logiciel n’a pas été conçu pour la tâche indiquée. DLI peut être décrit comme un codec d’image optimisé avec pertes d’usage général. Il s’agit du détenteur d’enregistrement PSNR et MS-SSIM pour la compression d’images, et j’ai pensé qu’il serait intéressant de voir comment il se comporterait 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 les échantillons compressés JPEG et IMG2TWIT, j'ai également utilisé DLI pour compresser l'image sur 534 octets. Le format JPEG est de 536 octets et IMG2TWIT de 534 octets. Les images ont été redimensionnées approximativement à la même taille pour faciliter la comparaison. JPEG est l'image de gauche, IMG2TWIT est le centre et DLI est la bonne.

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

L'image de l'IDD parvient à préserver certaines caractéristiques du visage, notamment le célèbre sourire :).

45
Dennis Lee

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 adapter à 140 caractères utf8.
    • (J'assume utf8, ce qui est ce que l'original site web prétend que Twitter stockait ses messages. Cela diffère de l'énoncé du problème ci-dessus, qui demande utf16.)
    • En utilisant this utf8 faq , je calcule que le nombre maximal de bits que vous pouvez coder dans un seul caractère utf8 est de 31 bits. Pour ce faire, j'utiliserais tous les caractères compris 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 à 542 octets .
    • (Si nous nous limitons à utf16, alors nous ne pourrions stocker que 2 octets par caractère, ce qui équivaut à 280 octets).
  2. Compressez l’image en utilisant la compression jpg standard.
    • Redimensionnez l'image à environ 50 x 50 pixels, puis essayez de la compresser à différents niveaux de compression jusqu'à obtenir une image aussi proche que possible de 542 octets sans la 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 aurait besoin d'être écrite, car rien n'existe actuellement qui fait cela.

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

Je pense que le principal avantage de la solution proposée est la réutilisation maximale de la technologie existante. 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 possédant un diplôme supérieur en mathématiques.

Une autre remarque importante est que s’il est décidé que l’utf16 est l’encodage préféré, cette solution tombe en morceaux. Les JPEG ne fonctionnent pas vraiment quand ils sont compressés à 280 octets. Cependant, il existe peut-être un meilleur algorithme de compression que jpg pour cet énoncé de problème spécifique.

21
Stephen McCarthy

D'accord, je suis en retard au jeu, mais j'ai quand même réalisé mon projet.

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

Fonctionnalités:

  • lua pur. S'exécute partout où un interprète Lua s'exécute.
  • utilise le format P3 netpbm
  • livré avec une suite complète de tests unitaires
  • conserve la taille de l'image d'origine

Mésaventures:

  • lent
  • à cette contrainte d'espace, il ne conserve que la palette de couleurs de base de l'image initiale et un aperçu général de ses quelques caractéristiques.

Voici un exemple de twit qui représente Lena:戇罨焛 垫 仔

original lenaencoded Lena

Le code est dans un référentiel Mercurial à l'adresse bitbucket.org. Départ http://bitbucket.org/tkadlubo/circles.lua

20

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

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

  1. Réduisez l’échantillon de gris de l’image, de sorte qu’il existe au total 16 teintes différentes.
  2. Préforme RLE sur l'image
  3. Compressez 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 à partir des exemples d'images ci-dessous. En termes de sortie, voici un exemple de tweet, en particulier pour l’image Lena présentée dans les exemples.

万 乐 唂 2 3 2 8 3 企 5 3 企 2 伂 5 3 企 3 4 2 伂 5

Comme vous pouvez le constater, 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 données pouvant être utilisées pour des informations d'image supplémentaires.

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

N'hésitez pas à me faire part de vos suggestions sur ce que j'aurais pu faire de mieux ou ce qui pourrait ne pas fonctionner avec le code. La liste complète des durées d’exécution et des exemples de résultats est disponible à l’adresse suivante: http://code-zen.info/twitterimage/

Première mise à jour

J'ai mis à jour le code RLE utilisé lors de la compression de la chaîne Tweet pour faire un retour en arrière et, le cas échéant, l'utiliser pour la sortie. Cela ne fonctionne que pour les paires de valeurs numériques, mais enregistre quelques caractères de données. La durée d'exécution est plus ou moins la même chose 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 des tests. Ce qui suit est l’un des exemples de chaînes de tweet, toujours pour la petite version de Lena:

万 乐 唂 4 倃쥹

Mise à jour deux

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

2 乐 唂 乐 2 儂 企 3 4坹商 嗉 乃

Logo StackOverflow http://code-zen.info/twitterimage/images/stackoverflow-logo.bmpCornell Box http://code-zen.info/twitterimage/images/cornell- box.bmpLena http://code-zen.info/twitterimage/images/lena.bmpMona Lisa http://code-zen.info/twitterimage/images /mona-Lisa.bmp

19
rjzii

Cet algorithme génétique écrit par Roger Alsing présente un bon taux de compression, au détriment de temps de compression longs. Le vecteur résultant des sommets pourrait être davantage compressé en utilisant un algorithme avec ou sans perte.

http://rogeralsing.com/2008/12/07/genetic-programming-evolution-of-mona-Lisa/

Ce serait un programme intéressant à mettre en œuvre, mais je vais rater mon coup.

15
CiscoIPPhone

La publication d’une image monochrome ou en niveaux de gris devrait améliorer la taille de l’image pouvant être encodée dans cet espace, dans la mesure où vous ne vous souciez pas de la couleur.

Augmentez éventuellement le défi de télécharger trois images qui, une fois recombinées, vous donnent une image en couleur tout en conservant une version monochrome dans chaque image séparée.

Ajoutez un peu de compression à ce qui précède et cela pourrait commencer à paraître viable ...

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

12
Gineer

Dans le défi initial, la limite de taille est définie par ce que Twitter vous permet toujours d’envoyer si vous collez votre texte dans leur zone de texte et cliquez sur "Mettre à jour". Comme certaines personnes l'ont bien remarqué, cela diffère de ce que vous pourriez envoyer sous forme de message texte SMS à partir de votre téléphone portable.

Ce qui n’est pas explicitement mentionné (mais quelle était ma règle personnelle) est que vous devriez pouvoir sélectionner le message tweeté dans votre navigateur, le copier dans le presse-papier et le coller dans un champ de saisie de texte de votre décodeur pour 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 permettant d’accéder à l’API de Twitter et de filtrer tout message ressemblant à un code image (marqueurs spéciaux, quiconque? clin d'oeilclin d'oeil). Mais la règle est que le message doit être passé par Twitter avant de pouvoir le décoder.

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

12
Quasimondo

Idée stupide, mais sha1(my_image) résulterait en 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 force brute.

Un bit monochrome serait un peu plus facile. Chaque pixel devient 1 ou 0, vous avez donc 1000 bits de données pour une image de 100 * 100 pixels. Puisque le hachage SHA1 est de 41 caractères, nous pouvons en insérer trois dans un message, il suffit de forcer brutalement 2 ensembles de 3333 bits et un ensemble de 3334 (même si cela reste probablement toujours démesuré)

Ce n'est pas vraiment pratique. Même avec l’image 100 * 100px de longueur fixe 1 bit, il ya .., en supposant que je ne me trompe pas de calcul, 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
8
dbr

Ici cette compression est bonne.

http://www.intuac.com/userport/john/apt/

http://img86.imageshack.us/img86/4169/imagey.jpg http://img86.imageshack.us/img86/4169/imagey.jpg

J'ai utilisé le fichier de commandes suivant:

capt mona-Lisa-large.pnm out.cc 20
dapt out.cc image.pnm
Pause

La taille du fichier résultant est de 559 octets.

8
Pieter

L'idée de stocker une série d'images de référence est intéressante. Serait-il si mal de stocker environ 25 Mo d’échantillons d’images et de laisser l’encodeur essayer de composer une image à l’aide de bits? Avec un tuyau aussi minuscule, la machinerie à chaque extrémité va nécessairement être beaucoup plus grande que le volume de données à traverser, alors quelle est la différence entre 25 Mo de code, 1 Mo de code et 24 Mo de données d'image?

(notez que les directives originales excluaient de limiter l'entrée aux images déjà présentes dans la bibliothèque - ce n'est pas ce que je suggère).

8
Steve Bennett

Idée: Pourriez-vous utiliser une police de caractères comme palette? Essayez de casser 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). Ceci utilise la police comme dictionnaire. Je pourrais par exemple utiliser un l pour une ligne verticale et un - pour une ligne horizontale? Juste une idée.

0
Maurits