Sfida di codifica delle immagini di Twitter [chiuso]


597

Se un'immagine vale 1000 parole, quanto di un'immagine puoi inserire in 140 caratteri?

Nota : è tutto gente! La scadenza di Bounty è arrivata e, dopo alcune difficili deliberazioni, ho deciso che l'ingresso di Boojum ha appena cancellato quello di Sam Hocevar . Pubblicherò note più dettagliate una volta che avrò avuto la possibilità di scriverle. Ovviamente, tutti dovrebbero sentirsi liberi di continuare a presentare soluzioni e migliorare soluzioni su cui le persone possano votare. Grazie a tutti coloro che hanno inviato e iscritto; Mi sono piaciute tutte. È stato molto divertente per me correre e spero sia divertente sia per i partecipanti che per gli spettatori.

Mi sono imbattuto in questo interessante post sul tentativo di comprimere le immagini in un commento su Twitter e molte persone in quel thread (e un thread su Reddit ) avevano suggerimenti su diversi modi in cui potresti farlo. Quindi, immagino che sarebbe una buona sfida per la programmazione; lascia che le persone mettano i loro soldi dov'è la loro bocca e mostra come le loro idee sulla codifica possono portare a maggiori dettagli nello spazio limitato che hai a disposizione.

Ti sfido a inventare un sistema generico per codificare le immagini in messaggi Twitter di 140 caratteri e decodificarle di nuovo in un'immagine. Puoi usare i caratteri Unicode, in modo da ottenere più di 8 bit per carattere. Anche tenendo conto dei caratteri Unicode, tuttavia, dovrai comprimere le immagini in una quantità molto piccola di spazio; questa sarà sicuramente una compressione con perdita di dati, e quindi ci dovranno essere giudizi soggettivi sulla bontà di ogni risultato.

Ecco il risultato che l'autore originale, Quasimondo , ha ottenuto dalla sua codifica (l'immagine è sotto licenza Creative Commons Attribution-Non commercial commercial ): Monna Lisa

Puoi fare di meglio?

Regole

  1. Il tuo programma deve avere due modalità: codifica e decodifica .
  2. Durante la codifica :
    1. Il tuo programma deve prendere come input un elemento grafico in qualsiasi formato grafico raster di tua scelta. Diremo che qualsiasi formato raster supportato da ImageMagick viene considerato ragionevole.
    2. Il programma deve generare un messaggio che può essere rappresentato in 140 o meno punti di codice Unicode; 140 punti di codice nella gamma U+0000- U+10FFFF, esclusi i non-personaggi ( U+FFFE, U+FFFF, U+nFFFE , U+nFFFF dove n è 1- 10esadecimale, e la gamma U+FDD0- U+FDEF) e punti di codice surrogati ( U+D800- U+DFFF). Può essere emesso in qualsiasi codifica ragionevole a tua scelta; qualsiasi codifica supportata da GNUiconv sarà considerata ragionevole e la codifica nativa della piattaforma o la codifica locale sarebbe probabilmente una buona scelta. Vedi le note Unicode di seguito per maggiori dettagli.
  3. Durante la decodifica :
    1. Il tuo programma dovrebbe prendere come input l'output della tua modalità di codifica .
    2. Il tuo programma deve produrre un'immagine in qualsiasi formato ragionevole a tua scelta, come definito sopra, anche se per i formati vettoriali di output è OK.
    3. L'output dell'immagine dovrebbe essere un'approssimazione dell'immagine di input; più ci si avvicina all'immagine in ingresso, meglio è.
    4. Il processo di decodifica potrebbe non avere accesso a nessun altro output del processo di codifica diverso dall'output sopra specificato; vale a dire, non è possibile caricare l'immagine da qualche parte e generare l'URL per il processo di decodifica da scaricare o qualsiasi altra cosa sciocca.
  4. Per motivi di coerenza nell'interfaccia utente, il programma deve comportarsi come segue:

    1. Il programma deve essere uno script che può essere impostato su eseguibile su una piattaforma con l'interprete appropriato o un programma che può essere compilato in un eseguibile.
    2. Il tuo programma deve prendere come primo argomento encodeo decodeper impostare la modalità.
    3. Il programma deve ricevere input in uno o più dei seguenti modi (se si implementa quello che accetta i nomi di file, è anche possibile leggere e scrivere da stdin e stdout se mancano i nomi di file):

      1. Prendi input dallo standard in e produce output allo standard out.

        my-program encode <input.png >output.txt
        my-program decode <output.txt >output.png
        
      2. Prendi l'input da un file chiamato nel secondo argomento e produce output nel file indicato nel terzo.

        my-program encode input.png output.txt
        my-program decode output.txt output.png
        
  5. Per la tua soluzione, inserisci:
    1. Il tuo codice, per intero, e / o un link ad esso ospitato altrove (se è molto lungo, o richiede molti file da compilare, o qualcosa del genere).
    2. Una spiegazione di come funziona, se non è immediatamente evidente dal codice o se il codice è lungo e le persone saranno interessate a un riepilogo.
    3. Un'immagine di esempio, con l'immagine originale, il testo che comprime e l'immagine decodificata.
    4. Se stai sviluppando un'idea che aveva qualcun altro, ti preghiamo di attribuirli. Va bene provare a perfezionare l'idea di qualcun altro, ma devi attribuirli.

Linee guida

Queste sono fondamentalmente regole che possono essere infrante, suggerimenti o criteri di punteggio:

  1. L'estetica è importante. Giudicherò e suggerirò che altre persone giudichino, in base a:
    1. Quanto è buona l'immagine di output e quanto assomiglia all'originale.
    2. Com'è bello il testo. Gobbledigook completamente casuale va bene se hai uno schema di compressione davvero intelligente, ma voglio anche vedere le risposte che trasformano le immagini in poesie multilingue o qualcosa di intelligente. Si noti che l'autore della soluzione originale ha deciso di utilizzare solo caratteri cinesi, poiché sembrava più bello in quel modo.
    3. Il codice interessante e gli algoritmi intelligenti sono sempre buoni. Mi piacciono i codici brevi e chiari, ma gli algoritmi complicati davvero intelligenti vanno bene anche se producono buoni risultati.
  2. Anche la velocità è importante, anche se non tanto quanto la capacità di un lavoro di comprimere l'immagine. Preferirei avere un programma in grado di convertire un'immagine in un decimo di secondo rispetto a qualcosa che eseguirà algoritmi genetici per giorni e giorni.
  3. Preferirò soluzioni più brevi a soluzioni più lunghe, purché ragionevolmente comparabili in termini di qualità; la concisione è una virtù.
  4. Il tuo programma dovrebbe essere implementato in una lingua che ha un'implementazione liberamente disponibile su Mac OS X, Linux o Windows. Mi piacerebbe essere in grado di eseguire i programmi, ma se hai un'ottima soluzione che funziona solo con MATLAB o qualcosa del genere, va bene.
  5. Il tuo programma dovrebbe essere il più generale possibile; dovrebbe funzionare per il maggior numero possibile di immagini diverse, sebbene alcune possano produrre risultati migliori di altre. In particolare:
    1. Avere alcune immagini integrate nel programma a cui corrisponde e scrive un riferimento, e quindi produce l'immagine corrispondente dopo la decodifica, è abbastanza zoppo e coprirà solo alcune immagini.
    2. Un programma che può acquisire immagini di forme geometriche semplici, piatte e geometriche e scomporle in una primitiva vettoriale è piuttosto ingegnoso, ma se fallisce su immagini al di là di una certa complessità probabilmente non è sufficientemente generale.
    3. Un programma che può solo catturare immagini con un particolare formato fisso ma che fa un buon lavoro con loro sarebbe anche OK, ma non ideale.
    4. Potresti scoprire che un'immagine in bianco e nero può ottenere più informazioni in uno spazio più piccolo di un'immagine a colori. D'altra parte, ciò può limitare i tipi di immagine a cui è applicabile; i volti vengono bene in bianco e nero, ma i disegni astratti potrebbero non andare così bene.
    5. Va benissimo se l'immagine in uscita è più piccola dell'input, pur essendo all'incirca la stessa proporzione. Va bene se devi ridimensionare l'immagine per confrontarla con l'originale; l'importante è come appare.
  6. Il tuo programma dovrebbe produrre output che potrebbero effettivamente passare attraverso Twitter e uscirne incolumi. Questa è solo una linea guida piuttosto che una regola, dal momento che non sono riuscito a trovare alcuna documentazione sull'esatto set di caratteri supportati, ma probabilmente dovresti evitare i personaggi di controllo, i funky invisibili che combinano personaggi, i personaggi di uso privato e simili.

Rubrica del punteggio

Come guida generale su come classificherò le soluzioni nella scelta della mia soluzione accettata, supponiamo che probabilmente valuterò le soluzioni su una scala di 25 punti (questo è molto approssimativo e non segnerò nulla direttamente, usando solo questo come linea guida di base):

  • 15 punti per quanto bene lo schema di codifica riproduca una vasta gamma di immagini di input. Questo è un giudizio estetico soggettivo
    • 0 significa che non funziona affatto, restituisce la stessa immagine ogni volta o qualcosa del genere
    • 5 significa che può codificare alcune immagini, anche se la versione decodificata sembra brutta e potrebbe non funzionare affatto su immagini più complicate
    • 10 significa che funziona su una vasta gamma di immagini e produce immagini dall'aspetto piacevole che a volte possono essere distinguibili
    • 15 significa che produce repliche perfette di alcune immagini e anche per immagini più grandi e complesse, dà qualcosa che è riconoscibile. O forse non rende le immagini abbastanza riconoscibili, ma produce bellissime immagini che sono chiaramente derivate dall'originale.
  • 3 punti per un uso intelligente del set di caratteri Unicode
    • 0 punti per usare semplicemente l'intero set di caratteri consentiti
    • 1 punto per l'utilizzo di un set limitato di caratteri sicuri per il trasferimento su Twitter o in una più ampia varietà di situazioni
    • 2 punti per l'utilizzo di un sottoinsieme tematico di personaggi, come solo ideogrammi Han o solo personaggi da destra a sinistra
    • 3 punti per fare qualcosa di veramente pulito, come generare testo leggibile o usare caratteri che sembrano l'immagine in questione
  • 3 punti per approcci algoritmici intelligenti e stile del codice
    • 0 punti per qualcosa che è di 1000 righe di codice solo per ridimensionare l'immagine, trattarla come 1 bit per pixel e base64 codifica che
    • 1 punto per qualcosa che utilizza una tecnica di codifica standard ed è ben scritto e breve
    • 2 punti per qualcosa che introduce una tecnica di codifica relativamente nuova, o che è sorprendentemente breve e pulito
    • 3 punti per un liner che in realtà produce buoni risultati o qualcosa che apre nuovi orizzonti nella codifica grafica (se questo sembra un numero basso di punti per l'apertura di nuovi terreni, ricorda che un risultato così buono avrà probabilmente un punteggio elevato per l'estetica anche)
  • 2 punti per la velocità. A parità di altre condizioni, più veloce è meglio, ma i criteri di cui sopra sono tutti più importanti della velocità
  • 1 punto per l'esecuzione su software libero (open source), perché preferisco il software libero (notare che C # sarà ancora idoneo per questo punto finché funziona su Mono, allo stesso modo il codice MATLAB sarebbe idoneo se funziona su GNU Octave)
  • 1 punto per seguire effettivamente tutte le regole. Queste regole sono diventate un po 'grandi e complicate, quindi probabilmente accetterò altrimenti buone risposte che sbagliano un piccolo dettaglio, ma darò un punto in più a qualsiasi soluzione che segua effettivamente tutte le regole

Immagini di riferimento

Alcune persone hanno chiesto alcune immagini di riferimento. Ecco alcune immagini di riferimento che puoi provare; qui sono incorporate versioni più piccole, tutte collegate a versioni più grandi dell'immagine se ne hai bisogno:

Lena Monna Lisa Scatola Cornell Logo StackOverflow

Premio

Offro una ricompensa di 500 rappresentanti (più i 50 che StackOverflow mette in campo) per la soluzione che mi piace di più, sulla base dei criteri di cui sopra. Ovviamente, incoraggio tutti gli altri a votare anche qui le loro soluzioni preferite.

Nota sulla scadenza

Questo concorso durerà fino allo scadere della taglia, verso le 18:00 di sabato 30 maggio. Non posso dire l'ora esatta in cui finirà; potrebbe essere ovunque dalle 17 alle 19. Garantirò che esaminerò tutte le voci inviate entro le 14:00 e farò del mio meglio per esaminare tutte le voci inviate entro le 16:00; se le soluzioni vengono presentate dopo, potrei non avere la possibilità di dar loro un aspetto corretto prima di dover prendere la mia decisione. Inoltre, prima invii, più possibilità avrai di votare per aiutarmi a scegliere la soluzione migliore, quindi prova a inviare prima piuttosto che alla scadenza.

Note Unicode

C'è stata anche una certa confusione su cosa sono ammessi i caratteri Unicode. La gamma di possibili punti di codice Unicode è U+0000a U+10FFFF. Ci sono alcuni punti di codice che non sono mai validi da usare come caratteri Unicode in uno scambio di dati aperto; questi sono i non caratteri e i punti di codice surrogato . Noncharacters sono definiti nel Unidode standard 5.1.0 sezione 16.7 come i valori U+FFFE, U+FFFF, U+nFFFE , U+nFFFF dove n è 1- 10esadecimale, e la gamma U+FDD0-U+FDEF. Questi valori devono essere utilizzati per un uso interno specifico dell'applicazione e le applicazioni conformi possono rimuovere questi caratteri dal testo elaborato da essi. I punti di codice surrogato, definiti in Unicode Standard 5.1.0 sezione 3.8 come U+D800- U+DFFF, vengono utilizzati per codificare caratteri oltre il piano multilingue di base in UTF-16; pertanto, è impossibile rappresentare questi punti di codice direttamente nella codifica UTF-16 e non è valido codificarli in qualsiasi altra codifica. Pertanto, ai fini di questo concorso, io consentire a qualsiasi programma che codifica le immagini in una sequenza di non più di 140 punti di codice Unicode dalla gamma U+0000- U+10FFFF, escludendo tutti noncharacters e coppie di surrogati come definito sopra.

Io preferisco le soluzioni che utilizzano solo i caratteri assegnati, e quelli ancora migliori che utilizzano sottoinsiemi intelligenti di caratteri assegnati o fare qualcosa di interessante con il set di caratteri che utilizzano. Per un elenco di caratteri assegnati, consultare il database dei caratteri Unicode ; si noti che alcuni caratteri sono elencati direttamente, mentre altri sono elencati solo come l'inizio e la fine di un intervallo. Si noti inoltre che i punti di codice surrogato sono elencati nel database, ma è vietato come indicato sopra. Se desideri sfruttare alcune proprietà dei caratteri per rendere più interessante il testo che hai emesso, ci sono una varietà di database di informazioni sui caratteri disponibili, come un elenco di blocchi di codice con nome e varie proprietà dei caratteri.

Dal momento che Twitter non specifica il set di caratteri esatto che supportano, sarò indulgente riguardo alle soluzioni che in realtà non funzionano con Twitter perché alcuni caratteri contano di più o alcuni caratteri vengono eliminati. Si preferisce, ma non è necessario, che tutti gli output codificati possano essere trasferiti incolumi tramite Twitter o un altro servizio di microblogging come identi.ca . Ho visto alcuni documenti che affermano che Twitter entità codifica <,> e &, e quindi li conteggia rispettivamente come 4, 4 e 5 caratteri, ma non l'ho provato da solo, e il loro contatore di caratteri JavaScript non sembra contarli in quel modo.

Suggerimenti e collegamenti

  • La definizione di caratteri Unicode validi nelle regole è un po 'complicata. La scelta di un singolo blocco di caratteri, come gli Ideografi unificati CJK (U + 4E00 – U + 9FCF), potrebbe essere più semplice.
  • È possibile utilizzare librerie di immagini esistenti, come ImageMagick o Python Imaging Library , per la manipolazione delle immagini.
  • Se hai bisogno di aiuto per comprendere il set di caratteri Unicode e le sue varie codifiche, consulta questa guida rapida o questa FAQ dettagliata su UTF-8 in Linux e Unix .
  • Prima si ottiene la soluzione, più tempo io (e altre persone voteremo) dovrò esaminarla. È possibile modificare la soluzione se la si migliora; Baserò la mia taglia sulla versione più recente quando darò il mio ultimo sguardo alle soluzioni.
  • Se vuoi analizzare e scrivere un semplice formato di immagine (e non vuoi semplicemente usare un formato esistente), ti suggerisco di utilizzare il formato PPM . È un formato basato su testo che è molto facile da lavorare e puoi usare ImageMagick per convertire da e verso di esso.

Sentiti libero di offrire suggerimenti sulle regole che ho scritto nei commenti; Sono certamente disposto a modificarli se le persone sentono di aver bisogno di chiarimenti o sono troppo specificate.
Brian Campbell,

6
Probabilmente dovresti dire che il caricamento dell'immagine su un server e la pubblicazione dell'URL non è valido.
Shay Erlichmen,

2
@Shay Non l'ho già detto? "Il processo di decodifica potrebbe non avere accesso a nessun altro output del processo di codifica diverso dall'output sopra specificato; ovvero, non è possibile caricare l'immagine da qualche parte e generare l'URL per il download del processo di decodifica o qualsiasi altra cosa stupida come quella ".
Brian Campbell,

1
@Konrad Rudolph Sono d'accordo; Non intendevo "sciocco" da un punto di vista pratico (chiaramente, tutto questo concorso è sciocco da un punto di vista pratico), intendevo "sciocco" nel contesto di questo concorso. L'uso di un URI non è in realtà un algoritmo di compressione, nel senso della teoria dell'informazione, in quanto non consente di trasferire ulteriori informazioni senza semplicemente utilizzare un canale alternativo. Potresti dare all'encoder e al decoder un ampio database di immagini e chiamarlo compressione che funziona solo su un set limitato di immagini, ma ho specificato che devi essere in grado di gestire un'immagine arbitraria.
Brian Campbell,

2
Ecco un paio di collegamenti che ho incontrato che potrebbero aiutare la gente: azillionmonkeys.com/qed/unicode.html per una spiegazione della gamma valida di caratteri Unicode. Si noti che le codifiche UTF sono quelle che possono codificare l'intero intervallo Unicode; UCS-4 è un superset di Unicode e UCS-2 e ASCII sono sottoinsiemi. E sul fronte della compressione, ecco una tecnica simile a quella del post originale, sebbene si stia concedendo 1k anziché 350 byte: screamingduck.com/Article.php?ArticleID=46&Show=ABCE
Brian Campbell,

Risposte:


244

Bene, ecco il mio: nanocrunch.cpp e il file CMakeLists.txt per crearlo usando CMake. Si basa sull'API Magick ++ ImageMagick per la maggior parte della sua gestione delle immagini. Richiede anche la libreria GMP per l'aritmetica del bignum per la sua codifica di stringa.

Ho basato la mia soluzione sulla compressione dell'immagine frattale, con alcuni colpi di scena unici. L'idea di base è quella di prendere l'immagine, ridimensionare una copia al 50% e cercare pezzi con vari orientamenti simili ai blocchi non sovrapposti nell'immagine originale. Ci vuole un approccio di forza molto bruta a questa ricerca, ma ciò rende più semplice l'introduzione delle mie modifiche.

La prima modifica è che invece di guardare solo rotazioni e ribaltamenti di novanta gradi, il mio programma considera anche orientamenti di 45 gradi. È un bit in più per blocco, ma aiuta immensamente la qualità dell'immagine.

L'altra cosa è che memorizzare una regolazione del contrasto / luminosità per ciascuno dei componenti di colore di ciascun blocco è troppo costoso. Invece, memorizzo un colore fortemente quantizzato (la tavolozza ha solo 4 * 4 * 4 = 64 colori) che viene semplicemente miscelata in una certa proporzione. Matematicamente, questo equivale a una luminosità variabile e una regolazione costante del contrasto per ciascun colore. Sfortunatamente, significa anche che non c'è contrasto negativo per capovolgere i colori.

Una volta calcolata la posizione, l'orientamento e il colore per ciascun blocco, lo codifica in una stringa UTF-8. Innanzitutto, genera un bignum molto grande per rappresentare i dati nella tabella dei blocchi e le dimensioni dell'immagine. L'approccio a questo è simile alla soluzione di Sam Hocevar: una specie di grande numero con una radice che varia in base alla posizione.

Quindi lo converte in una base qualunque sia la dimensione del set di caratteri disponibile. Per impostazione predefinita, fa pieno uso del set di caratteri unicode assegnato, meno il minore di, maggiore di, e commerciale, controllo, combinazione e caratteri surrogati e privati. Non è carino ma funziona. È inoltre possibile commentare la tabella predefinita e selezionare invece ASCII a 7 bit stampabili (di nuovo esclusi <,> e & caratteri) o Ideografi unificati CJK. La tabella di cui sono disponibili i codici dei caratteri è memorizzata una lunghezza della corsa codificata con corse alternate di caratteri non validi e validi.

Ad ogni modo, ecco alcune immagini e tempi (misurati sul mio vecchio P4 a 3,0 GHz) e compressi a 140 caratteri nel set di unicode completo assegnato sopra descritto. Nel complesso, sono abbastanza soddisfatto di come si sono rivelati tutti. Se avessi più tempo per lavorare su questo, probabilmente proverei a ridurre il blocco delle immagini decompresse. Tuttavia, penso che i risultati siano abbastanza buoni per l'estremo rapporto di compressione. Le immagini decompresse sono un po 'impressioniste, ma trovo relativamente facile vedere come i bit corrispondono all'originale.

Stack Overflow Logo (8.6s per codificare, 7.9s per decodificare, 485 byte):
http://i44.tinypic.com/2w7lok1.png

Lena (32.8s da codificare, 13.0s da decodificare, 477 byte):
http://i42.tinypic.com/2rr49wg.png http://i40.tinypic.com/2rhxxyu.png

Mona Lisa (43.2s da codificare, 14.5s da decodificare, 490 byte):
http://i41.tinypic.com/ekgwp3.png http://i43.tinypic.com/ngsxep.png

Modifica: personaggi unificati CJK

Sam ha chiesto nei commenti sull'uso di questo con CJK. Ecco una versione di Mona Lisa compressa a 139 caratteri dal set di caratteri Unificato CJK:

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

I parametri di ottimizzazione nella parte superiore del programma che ho usato per questo sono stati: 19, 19, 4, 4, 3, 10, 11, 1000, 1000. Ho anche commentato la prima definizione di numero_assegnato e codici e decommentato il ultime definizioni di questi per selezionare il set di caratteri unificato CJK.


Wow! Bel lavoro. Ero scettico sulla compressione dell'immagine frattale per immagini così piccole, ma in realtà produce risultati abbastanza decenti. È stato anche abbastanza facile da compilare ed eseguire.
Brian Campbell,

1
Grazie ragazzi! Sam, vuoi dire risultati con solo 140 caratteri CJK? In tal caso, quindi sì, dovrai sintonizzare i numeri in alto. La dimensione finale in bit è intorno a 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,

Modifica: c'è un * 16 nel primo log2 () che ho lasciato fuori. Questo è per i possibili orientamenti.
Boojum,

20
Qualcuno ha già twitterato un'immagine usando questo?
martedì

288

file immagine e sorgente python (versione 1 e 2)

Versione 1 Ecco il mio primo tentativo. Aggiornerò mentre vado.

Ho il logo SO fino a 300 caratteri quasi senza perdita. La mia tecnica utilizza la conversione in grafica vettoriale SVG, quindi funziona meglio con la grafica in linea. In realtà è un compressore SVG, richiede ancora che l'arte originale passi attraverso una fase di vettorializzazione.

Per il mio primo tentativo ho usato un servizio online per la traccia PNG, tuttavia ci sono MOLTI strumenti gratuiti e non liberi che possono gestire questa parte incluso potrace (open-source).

Ecco i risultati

Logo SO originale http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png Logo SO originale decodificato http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded.png Dopo la codifica e decodifica

Personaggi : 300

Tempo : non misurato ma praticamente istantaneo (esclusi i passaggi di vettorizzazione / rasterizzazione)

La fase successiva sarà incorporare 4 simboli (punti e comandi del percorso SVG) per carattere unicode. Al momento la mia build Python non ha un ampio supporto di caratteri UCS4 che limita la mia risoluzione per personaggio. Ho anche limitato l'intervallo massimo all'estremità inferiore dell'intervallo riservato unicode 0xD800 ma una volta creato un elenco di caratteri consentiti e un filtro per evitarli, posso teoricamente spingere il numero richiesto di caratteri fino a 70-100 per il logo sopra.

Una limitazione di questo metodo al momento è che la dimensione dell'output non è fissa. Dipende dal numero di nodi / punti vettoriali dopo la vettorializzazione. L'automazione di questo limite richiederà la pixelizzazione dell'immagine (che rimuove il vantaggio principale dei vettori) o la ripetuta esecuzione dei percorsi attraverso una fase di semplificazione fino al raggiungimento del conteggio dei nodi desiderato (che attualmente sto eseguendo manualmente in Inkscape).

Versione 2

AGGIORNAMENTO : v2 è ora qualificato per competere. I cambiamenti:

  • Input / output di controllo della riga di comando e debug
  • Utilizza il parser XML (lxml) per gestire SVG anziché regex
  • Comprime 2 segmenti di percorso per simbolo unicode
  • Documentazione e pulizia
  • Support style = "fill: color" e fill = "color"
  • Larghezza / altezza del documento impacchettate in un singolo carattere
  • Colore del percorso racchiuso in un singolo personaggio
  • La compressione del colore viene ottenuta eliminando 4 bit di dati di colore per colore e impacchettandoli in un personaggio tramite conversione esadecimale.

Personaggi : 133

Tempo : pochi secondi

v2 decodificato http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded-v2.png Dopo la codifica e decodifica (versione 2)

Come puoi vedere ci sono alcuni artefatti questa volta. Non è una limitazione del metodo ma un errore da qualche parte nelle mie conversioni. Gli artefatti si verificano quando i punti vanno oltre l'intervallo 0,0 - 127,0 e i miei tentativi di vincolarli hanno avuto un successo misto. La soluzione è semplicemente ridimensionare l'immagine, tuttavia ho avuto problemi a ridimensionare i punti effettivi piuttosto che la tavola da disegno o la matrice di gruppo e ora sono troppo stanco per occuparmene. In breve, se i tuoi punti rientrano nell'intervallo supportato, in genere funziona.

Credo che il nodo nel mezzo sia dovuto a una maniglia che si sposta dall'altra parte di una maniglia a cui è collegata. Fondamentalmente i punti sono troppo vicini tra loro in primo luogo. L'esecuzione di un filtro semplificato sull'immagine di origine prima della compressione dovrebbe risolvere questo problema e radere alcuni caratteri non necessari.

AGGIORNAMENTO : Questo metodo va bene per oggetti semplici, quindi avevo bisogno di un modo per semplificare percorsi complessi e ridurre il rumore. Ho usato Inkscape per questo compito. Ho avuto un po 'di fortuna nel tracciare percorsi superflui usando Inkscape ma non ho avuto il tempo di provare ad automatizzarlo. Ho creato alcuni svg di esempio usando la funzione "Semplifica" di Inkscape per ridurre il numero di percorsi.

Semplificare funziona bene, ma può essere lento con questo molti percorsi.

esempio di 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.warriorhut.com/graphics /svg_to_unicode/lena_std_washed_autotrace.png

miniature tracciate http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_autotrace.png

Ecco alcuni scatti a bassissima risoluzione. Questi sarebbero più vicini al limite di 140 caratteri, anche se potrebbe essere necessaria anche una compressione del percorso intelligente.

groomed http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_groomed.png Semplificato e deselezionato.

trianglulated http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_triangulated.png Semplificato, distrutto e triangolato.

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

SOPRA: Percorsi semplificati utilizzando la funzione di traccia automatica .

Sfortunatamente il mio parser non gestisce l'output di autotrace, quindi non so come possano essere utilizzati i punti o fino a che punto semplificare, purtroppo c'è poco tempo per scriverlo prima della scadenza. Tuttavia è molto più semplice analizzare l'output di inkscape.


2
Eccellente! All'inizio volevo creare una soluzione vettoriale ibrida con entrambi i bordi nitidi e le aree lisce, ma si è rivelata troppo complessa senza utilizzare una libreria di tracciamento (che non volevo usare). Non vedo l'ora di vedere fino a che punto puoi arrivare con il tuo metodo!
sam hocevar,

Bello! Speravo che avremmo visto alcuni tentativi di approcci quasi senza perdita di vettorizzazione. Significa che ha una generalità inferiore, ma una qualità superiore per le immagini che copre. Va bene usare un servizio online per la vettorializzazione. Buona fortuna per ridurre ulteriormente le dimensioni!
Brian Campbell,

Considererei la compressione delle immagini e la codifica dei caratteri come due diversi passaggi: la tecnica di Sam sembra essere ottimale per la codifica e potrebbe essere facilmente integrata in un programma autonomo. Otterrai più denaro per il tuo denaro concentrandoti sulla parte unica della tua soluzione (cioè la parte di compressione) e semplicemente producendo una serie di bit.
Mark Ransom,

70
Wow. Queste immagini sembrano davvero eleganti.
Rinat Abdullin,

199

La mia soluzione completa è disponibile all'indirizzo http://caca.zoy.org/wiki/img2twit . Ha le seguenti caratteristiche:

  • Tempo di compressione ragionevole (circa 1 minuto per alta qualità)
  • Decompressione rapida (una frazione di secondo)
  • Mantiene le dimensioni dell'immagine originale (non solo le proporzioni)
  • Qualità della ricostruzione decente (IMHO)
  • Lunghezza del messaggio e set di caratteri (ASCII, CJK, Simboli) possono essere scelti in fase di esecuzione
  • La lunghezza del messaggio e il set di caratteri vengono rilevati automaticamente al momento della decompressione
  • Imballaggio di informazioni molto efficiente

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

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

Ecco una panoramica generale del processo di codifica:

  • Il numero di bit disponibili viene calcolato dalla lunghezza del messaggio desiderata e dal set di caratteri utilizzabile
  • L'immagine di origine è segmentata in tante celle quadrate quanti i bit disponibili lo consentono
  • Un numero fisso di punti (attualmente 2) è interessato da ogni cella, con coordinate iniziali e valori di colore
  • Quanto segue viene ripetuto fino a quando una condizione di qualità è soddisfatta:
    • Un punto viene scelto a caso
    • Su questo punto viene eseguita un'operazione a caso (spostandola all'interno della sua cella, cambiando colore)
    • Se l'immagine risultante (vedere il processo di decodifica di seguito) è più vicina all'immagine di origine, l'operazione viene mantenuta
  • La dimensione dell'immagine e l'elenco dei punti sono codificati in UTF-8

E questo è il processo di decodifica:

  • Le dimensioni e i punti dell'immagine vengono letti dal flusso UTF-8
  • Per ogni pixel nell'immagine di destinazione:
    • Viene calcolato l'elenco dei neigbours naturali
    • Il colore finale del pixel è impostato come media ponderata dei colori dei suoi vicini naturali

Quello che credo sia la parte più originale del programma è il bitstream. Invece di impacchettare valori allineati a bit ( stream <<= shift; stream |= value), impacco valori arbitrari che non sono in potenze di due intervalli ( stream *= range; stream += value). Ciò richiede calcoli bignum ed è ovviamente molto più lento, ma mi dà 2009.18 bit invece del 1960 quando uso i 20902 caratteri CJK principali (sono altri tre punti che posso inserire nei dati). E quando si usa ASCII, mi dà 917,64 bit invece di 840.

Ho deciso contro un metodo per il calcolo iniziale dell'immagine che avrebbe richiesto armi pesanti (rilevamento degli angoli, estrazione delle caratteristiche, quantizzazione del colore ...) perché all'inizio non ero sicuro che avrebbe davvero aiutato. Ora mi rendo conto che la convergenza è lenta (1 minuto è accettabile ma è comunque lento) e potrei provare a migliorarlo.

Il ciclo di adattamento principale è liberamente ispirato dall'algoritmo di dithering Direct Binary Seach (in cui i pixel vengono scambiati o capovolti in modo casuale fino ad ottenere un semitono migliore). Il calcolo dell'energia è una semplice distanza quadrata medio-radice, ma eseguo prima un filtro mediano 5x5 sull'immagine originale. Una sfocatura gaussiana probabilmente rappresenterebbe meglio il comportamento dell'occhio umano, ma non volevo perdere spigoli vivi. Ho anche deciso di non ricorrere alla simulazione di ricottura o di altri metodi difficili da mettere a punto perché non ho mesi per calibrare il processo. Pertanto, il flag "qualità" rappresenta solo il numero di iterazioni eseguite su ciascun punto prima della fine dell'encoder.

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

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

Anche se non tutte le immagini si comprimono bene, sono sorpreso dai risultati e mi chiedo davvero quali altri metodi esistano che possono comprimere un'immagine a 250 byte.

Ho anche piccoli film sull'evoluzione dello stato dell'encoder da uno stato iniziale casuale e da uno stato iniziale "buono" .

Modifica : ecco come il metodo di compressione si confronta con JPEG. A sinistra, l'immagine di jamoes è superiore a 536 byte. A destra, Mona Lisa compresso fino a 534 byte usando il metodo qui descritto (i byte menzionati qui si riferiscono a byte di dati, ignorando quindi i bit sprecati usando i caratteri Unicode):

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

Modifica : appena sostituito il testo CJK con le versioni più recenti delle immagini.


In realtà non ho bisogno di essere in grado di eseguire il codice (ho inserito la parte relativa all'esecuzione nelle linee guida, come suggerimento, non nelle regole); Preferirei essere in grado di eseguirlo, ma lo giudicherò di più sulla qualità delle immagini che generi, sul codice e su eventuali trucchi o algoritmi interessanti. Se voglio eseguirlo e richiede pacchetti che non ho o non voglio installare sul mio sistema principale, posso semplicemente avviare un'istanza di Amazon EC2 e installarlo. Fintanto che stai lavorando con librerie che sono confezionate per una delle maggiori distribuzioni, dovrei essere in grado di eseguirlo. Sentiti libero di usare CGAL.
Brian Campbell,

2
Ok, ecco la mia soluzione (codice sorgente): caca.zoy.org/browser/libpipi/trunk/examples/img2twit.cpp Il mio tentativo di spiegazione e alcuni esempi sono su caca.zoy.org/wiki/img2twit
sam hocevar

2
Mi piace molto la tua soluzione. Dovresti provare a ridurre il numero di valori assegnati al canale blu poiché l'occhio umano non riesce a risolvere il blu molto bene: nfggames.com/games/ntsc/visual.shtm ; questo ti permetterà di avere maggiori dettagli a scapito della perdita di alcune informazioni sul colore. O forse assegnarlo al verde?
rpetrich,

5
Buon punto. Ho provato alcune varianti di questa idea (vedi i commenti prima della definizione RANGE_X) ma non molto accuratamente. Come puoi vedere, l'uso di 5 valori blu anziché 6 ha aumentato l'errore leggermente meno rispetto all'utilizzo di 7 valori di verde. Non ho provato a fare entrambe le cose per pigrizia. Un altro problema che ho è che non ho una funzione di errore molto buona. Attualmente uso ∑ (∆r² + ∆g² + ∆b²) / 3, che funziona bene. Ho provato ∑ (0,299∆r² + 0,587∆g² + 0,114∆b²), basato (senza giustificazione fisica) sul componente Y di YUV, ma era troppo tollerante con errori blu. Proverò a trovare articoli su questo problema.
sam hocevar,

2
@rpetrich: ho modificato il programma per farlo aumentare dinamicamente le gamme r / g / b purché ci siano abbastanza bit disponibili. Questo assicura che non perdiamo mai più di 13 bit nell'intero flusso di bit (ma in pratica è solitamente 1 o 2). E le immagini sembrano leggermente migliori.
Sam Hocevar,

45

Quanto segue non è un invio formale, poiché il mio software non è stato adattato in alcun modo per l'attività indicata. DLI può essere descritto come un codec di immagine con perdita di dati per scopi generici e ottimizzante. È il detentore del record PSNR e MS-SSIM per la compressione delle immagini e ho pensato che sarebbe stato interessante vedere come si comporta per questo particolare compito. Ho usato l'immagine di riferimento di Mona Lisa fornita e l'ho ridimensionata a 100x150, quindi ho usato DLI per comprimerlo a 344 byte.

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

Per un confronto con i campioni compressi JPEG e IMG2TWIT, ho usato DLI per comprimere anche l'immagine a 534 byte. Il JPEG è 536 byte e IMG2TWIT è 534 byte. Le immagini sono state ridimensionate approssimativamente alla stessa dimensione per un facile confronto. JPEG è l'immagine a sinistra, IMG2TWIT è al centro e DLI è l'immagine a destra.

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

L'immagine DLI riesce a preservare alcune delle caratteristiche del viso, in particolare il famoso sorriso :).


6
Ops. Quanto sopra dovrebbe essere accreditato a Dennis Lee, che lo ha presentato in origine. L'ho appena modificato per incorporare le immagini in linea e il link al riferimento che ho trovato su Google. E devo dire, wow, sono impressionato dalla compressione. Dovrò controllare la compressione DLI.
Brian Campbell,

1
A proposito, l'autore DLI menziona un "lungo tempo di elaborazione". Dato che non sono in grado di eseguire il suo software, potresti darci dei numeri di tempo di compressione approssimativi?
sam hocevar,

1
Utilizzando un AMD Athlon64 2.4 Ghz, la compressione dell'immagine Mona Lisa 100x150 richiede 38 secondi e decompressione 6 secondi. La compressione fino a un massimo di 251 byte è più dura, la qualità dell'output è notevolmente ridotta. Usando l'immagine Mona Lisa di riferimento, l'ho ridimensionata a 60x91, quindi ho usato DLI per comprimerlo a 243 byte (il più vicino a 251 senza andare oltre). Questo è l'output i43.tinypic.com/2196m4g.png Il dettaglio non è vicino al DLI a 534 byte anche se il bitrate è stato ridotto solo del ~ 50%. La struttura dell'immagine è stata mantenuta abbastanza bene comunque.

1
Ha deciso di semplificare il confronto tra i campioni compressi a 250 byte. Il DLI da 243 byte è stato ridimensionato e posizionato accanto al campione IMG2TWIT. IMG2TWIT a sinistra, DLI a destra. Ecco l'immagine i40.tinypic.com/30ndks6.png

1
DLI utilizza un parametro di qualità come JPEG, quindi è necessario tentativi ed errori se si desidera una dimensione di destinazione target.

21

La panoramica generale della mia soluzione sarebbe:

  1. Comincio con il calcolo della massima quantità di dati grezzi che puoi inserire in 140 caratteri utf8.
    • (Sto supponendo utf8, che è ciò in cui il sito Web originale ha affermato che Twitter ha archiviato i suoi messaggi. Questo differisce dalla dichiarazione del problema sopra, che richiede utf16.)
    • Usando questa faq utf8 , calcolo che il numero massimo di bit che puoi codificare in un singolo carattere utf8 è 31 bit. Per fare questo, vorrei usare tutti i personaggi che si trovano nell'intervallo U-04000000 - U-7FFFFFFF. (1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx, ci sono 31 x, quindi ho potuto codificare fino a 31 bit).
    • 31 bit per 140 caratteri equivalgono a 4340 bit. Dividilo per 8 per ottenere 524,5 e arrotondalo per difetto a 542 byte .
    • (Se ci limitiamo a utf16, allora potremmo memorizzare solo 2 byte per carattere, che equivarrebbe a 280 byte).
  2. Comprimi l'immagine usando la compressione jpg standard.
    • Ridimensiona l'immagine in modo che sia circa 50x50px, quindi prova a comprimerla a vari livelli di compressione fino a ottenere un'immagine il più vicino possibile a 542 byte senza andare oltre.
    • Questo è un esempio della mona lisa compressa fino a 536 byte.
  3. Codifica i bit grezzi dell'immagine compressa in caratteri utf-8.
    • Sostituisci ogni x nei seguenti byte: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx, con i bit dell'immagine.
    • Questa parte sarebbe probabilmente la parte in cui la maggior parte del codice dovrebbe essere scritta, perché al momento non esiste nulla che lo faccia.

So che stavi chiedendo il codice, ma non voglio davvero passare il tempo per codificarlo. Ho pensato che un design efficiente potesse almeno ispirare qualcun altro a codificarlo.

Penso che il principale vantaggio della mia soluzione proposta sia che sta riutilizzando quanta più tecnologia possibile. Può essere divertente provare a scrivere un buon algoritmo di compressione, ma c'è sicuramente un algoritmo migliore là fuori, molto probabilmente scritto da persone che hanno una laurea in matematica superiore.

Un'altra nota importante è che se si decide che utf16 è la codifica preferita, questa soluzione non funziona. i jpeg non funzionano davvero se compressi fino a 280 byte. Anche se, forse esiste un algoritmo di compressione migliore di jpg per questa specifica dichiarazione del problema.


Sono al lavoro ora, ma sto implementando definitivamente questa soluzione quando sono tornato a casa.
Paulo Santos,

2
Dalla mia sperimentazione, sembra che UTF-16 sia davvero il modo in cui Twitter conta i personaggi; I caratteri BMP contano come 1 e i caratteri del piano superiore contano come 2. Non è documentato, ma è così che conta il loro contatore di caratteri JavaScript quando si digita nella casella di input. È anche menzionato nei commenti nella discussione originale. Non ho provato a inviare tramite l'API per vedere se il contatore è rotto; in tal caso, aggiornerò il problema per i vincoli effettivi. Tuttavia, non è possibile utilizzare UTF-8 arbitrario, poiché molte di quelle sequenze più lunghe che è possibile codificare non sono Unicode valide.
Brian Campbell,

4
Dopo aver testato con la loro API, si scopre che contano per i caratteri Unicode (punti di codice), non per le unità di codice UTF-16 (è il contatore di caratteri JavaScript che conta tramite UTF-16, poiché apparentemente è quello che fa il metodo di lunghezza JavaScript) . Quindi puoi ottenere un po 'più di informazioni lì dentro; i caratteri Unicode validi sono compresi nell'intervallo da U + 0000 a U + 10FFFF (un po 'più di 20 bit per carattere; 2 ^ 20 + 2 ^ 16 possibili valori per carattere). UTF-8 consente la codifica di più valori di quelli consentiti in Unicode, quindi se ti limiti a Unicode, puoi ottenere circa 350 byte di spazio, non 542.
Brian Campbell,

3
Quella mona lisa da 536 byte sembra sorprendentemente buona, data l'estrema compressione!
Chris,

3
Attualmente possiamo codificare 129.775 caratteri Unicode diversi (assegnati, senza controllo, non privati). Se ci limitiamo a quel sottoinsieme, è un totale di 2377 bit, o 297 byte. Codice qui: porg.es/blog/what-can-we-fit-in-140-characters
porges

20

Ok, sono in ritardo al gioco, ma ho realizzato il mio progetto.

È un algoritmo genetico giocattolo che utilizza cerchi colorati traslucidi per ricreare l'immagine iniziale.

Caratteristiche:

  • pura Lua. Funziona ovunque sia in esecuzione un interprete Lua.
  • utilizza il formato netpbm P3
  • viene fornito con una suite completa di test unitari
  • conserva le dimensioni dell'immagine originale

Mis-feautres:

  • lento
  • a questi limiti di spazio conserva solo la combinazione di colori di base dell'immagine iniziale e un contorno generale di alcune sue caratteristiche.

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

lena originale codificato Lena

Il codice è in un repository Mercurial su bitbucket.org. Dai un'occhiata a http://bitbucket.org/tkadlubo/circles.lua


2
Eccezionale! Crea immagini pulite e dall'aspetto artistico. Sono contento che la gente ci stia ancora lavorando; è stato molto divertente vedere tutti i diversi approcci.
Brian Campbell,

1
Mi piacerebbe vederlo usato come una sovrapposizione trasparente sull'originale, dando qualcosa di simile all'effetto bokeh.
Nick Radford,

19

Quello che segue è il mio approccio al problema e devo ammettere che questo è stato un progetto piuttosto interessante su cui lavorare, è decisamente al di fuori del mio normale regno di lavoro e mi ha dato qualcosa di nuovo da imparare.

L'idea di base dietro la mia è la seguente:

  1. Sottocampiona l'immagine in scala di grigi in modo tale che ci fossero in totale 16 diverse tonalità
  2. Preforma RLE sull'immagine
  3. Comprimi i risultati nei caratteri UTF-16
  4. Preforma RLE sui risultati compressi per rimuovere qualsiasi duplicazione di caratteri

Si scopre che questo funziona, ma solo in misura limitata, come puoi vedere dalle immagini di esempio qui sotto. In termini di output, quello che segue è un tweet di esempio, in particolare per l'immagine di Lena mostrata negli esempi.

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

Come puoi vedere, ho provato a limitare un po 'il set di caratteri; tuttavia, ho riscontrato problemi durante la memorizzazione dei dati relativi al colore dell'immagine. Inoltre, questo schema di codifica tende anche a sprecare un sacco di bit di dati che potrebbero essere utilizzati per ulteriori informazioni sull'immagine.

In termini di tempi di esecuzione, per le immagini di piccole dimensioni il codice è estremamente veloce, circa 55 ms per le immagini di esempio fornite, ma il tempo aumenta con immagini più grandi. Per l'immagine di riferimento Lena 512x512 il tempo di esecuzione era di 1182ms. Dovrei notare che le probabilità sono piuttosto buone che il codice stesso non è molto ottimizzato per le prestazioni (ad esempio, tutto funziona con Bitmap ), quindi i tempi potrebbero diminuire un po 'dopo un po' di refactoring.

Non esitate a offrirmi qualsiasi suggerimento su cosa avrei potuto fare meglio o cosa potrebbe esserci di sbagliato nel codice. L'elenco completo dei tempi di esecuzione e dell'output di esempio è disponibile nel seguente percorso: http://code-zen.info/twitterimage/

Aggiorna uno

Ho aggiornato il codice RLE utilizzato durante la compressione della stringa di tweet per dare un'occhiata di base indietro e, in tal caso, utilizzarlo per l'output. Funziona solo per le coppie di valori numerici, ma salva un paio di caratteri di dati. Il tempo di esecuzione è più o meno lo stesso della qualità dell'immagine, ma i tweet tendono ad essere un po 'più piccoli. Aggiornerò il grafico sul sito Web mentre completerò il test. Quella che segue è una delle stringhe di tweet di esempio, sempre per la versione ridotta di Lena:

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

Aggiornamento due

Un altro piccolo aggiornamento, ma ho modificato il codice per raggruppare le sfumature di colore in gruppi di tre anziché quattro, questo utilizza un po 'più di spazio, ma se non mi manca qualcosa dovrebbe significare che i caratteri "dispari" non compaiono più dove il colore i dati sono. Inoltre, ho aggiornato un po 'di più la compressione in modo che ora possa agire sull'intera stringa anziché sul solo blocco del conteggio dei colori. Sto ancora testando i tempi di esecuzione, ma sembrano essere nominalmente migliorati; tuttavia, la qualità dell'immagine è sempre la stessa. Quella che segue è la versione più recente del tweet di Lena:

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

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


1
Ottimo, grazie per l'ingresso! La scala di grigi in realtà funziona abbastanza bene per la maggior parte di questi, anche se Lena è un po 'difficile da capire. Stavo cercando la tua fonte ma ho ottenuto un 404; potresti assicurarti che sia lassù?
Brian Campbell,

Ricontrolla ora, stavo aggiornando il sito, quindi potresti avermi intercettato tra gli aggiornamenti.
rjzii,

Sì, posso scaricarlo ora. Ora, ovviamente, devo capire se riesco a compilare Mono.
Brian Campbell,

Sì! Funziona con Mono, ho compilato con "gmcs -r System.Drawing TwitterImage.cs Program.cs" ed eseguito con "mono TwitterImage.exe codificare lena.png lena.txt"
Brian Campbell,

Freddo! Ho fatto un doppio controllo per assicurarmi che le librerie che stavo usando fossero elencate per Mono, ma in realtà non ho ancora lavorato con Mono, quindi non ero sicuro che avrebbe funzionato o meno.
rjzii,


12

Nella sfida originale il limite di dimensione è definito come ciò che Twitter ti consente ancora di inviare se incolli il testo nella loro casella di testo e premi "aggiorna". Come alcune persone hanno notato correttamente, questo è diverso da quello che potresti inviare come messaggio SMS dal tuo cellulare.

Ciò che non è esplicitamente menzionato (ma quale era la mia regola personale) è che dovresti essere in grado di selezionare il messaggio twittato nel tuo browser, copiarlo negli appunti e incollarlo in un campo di input di testo del tuo decodificatore in modo che possa visualizzarlo. Naturalmente sei anche libero di salvare il messaggio come file di testo e di rileggerlo o di scrivere uno strumento che accede all'API di Twitter e filtra qualsiasi messaggio che assomiglia a un codice immagine (marcatori speciali di chiunque? Wink wink ). Ma la regola è che il messaggio deve essere passato su Twitter prima che ti sia permesso di decodificarlo.

Buona fortuna con i 350 byte - dubito che sarai in grado di utilizzarli.


1
Sì, ho aggiunto una rubrica di punteggio che indica che le restrizioni più strette sul set di caratteri sono preferite, ma non richieste. Vorrei avere una regola che richieda che i messaggi passino incolumi su Twitter, ma che richiederebbe un sacco di tentativi ed errori per capire i dettagli precisi di ciò che funziona, e volevo lasciare un margine di manovra per consentire usi creativi del spazio del codice. Quindi, l'unico requisito nella mia sfida è 140 caratteri Unicode validi. A proposito, grazie per essere passato! Mi piace molto la tua soluzione e voglio vedere se qualcuno dei kibitzer può davvero migliorarla.
Brian Campbell,

12

Pubblicare un'immagine in bianco e nero o in scala di grigi dovrebbe migliorare la dimensione dell'immagine che può essere codificata in quello spazio poiché non ti interessa il colore.

Forse aumentando la sfida di caricare tre immagini che, se ricombinate, ti danno un'immagine a colori pur mantenendo una versione monocromatica in ogni immagine separata.

Aggiungi un po 'di compressione a quanto sopra e potrebbe iniziare a sembrare fattibile ...

Bello!!! Ora ragazzi avete suscitato il mio interesse. Nessun lavoro verrà svolto per il resto della giornata ...


9
s /
peaked

1
Mi piace l'idea di tre immagini, dovrebbe essere possibile implementare tale idea su Twitter e il risultato sarebbe abbastanza buono.
Makis,

9

Per quanto riguarda la parte di codifica / decodifica di questa sfida. base16b.org è il mio tentativo di specificare un metodo standard per codificare in modo sicuro ed efficiente i dati binari nei piani Unicode superiori.

Alcune caratteristiche:

  • Utilizza solo le aree utente private di Unicode
  • Codifica fino a 17 bit per carattere; quasi tre volte più efficiente di Base64
  • Viene fornita un'implementazione Javascript di riferimento di codifica / decodifica
  • Sono incluse alcune codifiche di esempio, tra cui Twitter e Wordpress

Siamo spiacenti, questa risposta arriva troppo tardi per la competizione originale. Ho iniziato il progetto indipendentemente da questo post, che ho scoperto a metà strada.


8

L'idea di memorizzare un mucchio di immagini di riferimento è interessante. Sarebbe così sbagliato archiviare diciamo 25 Mb di immagini di esempio e fare in modo che l'encoder provasse a comporre un'immagine usando bit di quelle? Con un tubo così minuscolo, il macchinario alle due estremità sarà per necessità molto più grande del volume di dati che passa attraverso, quindi qual è la differenza tra 25 Mb di codice e 1 Mb di codice e 24 Mb di dati immagine?

(nota che le linee guida originali hanno escluso la limitazione dell'input alle immagini già presenti nella libreria - non lo sto suggerendo).


1
Ciò andrebbe bene, purché ci sia una quantità fissa e finita di dati su entrambi gli endpoint. Naturalmente, dovresti dimostrare che funziona con immagini che non sono nel set di formazione, proprio come qualsiasi problema statistico di processo del linguaggio naturale. Mi piacerebbe vedere qualcosa che adotti un approccio statistico alla codifica delle immagini.
Brian Campbell,

16
Io, per esempio, mi piacerebbe vedere Mona Lisa rifatta usando solo la fan art di Boba Fett come fonte.
Nosredna,

Sono d'accordo - l'approccio fotomosaico sembra rientrare nelle regole e sarebbe estremamente interessante vedere qualcuno prendere a pugni.
An̲̳̳drew,

8

Un'idea stupida, ma sha1(my_image)si tradurrebbe in una rappresentazione "perfetta" di qualsiasi immagine (ignorando le collisioni). L'ovvio problema è che il processo di decodifica richiede quantità eccessive di forza bruta.

Il monocromio a 1 bit sarebbe un po 'più semplice .. Ogni pixel diventa 1 o 0, quindi si otterrebbero 1000 bit di dati per un'immagine da 100 * 100 pixel. Poiché l'hash SHA1 è di 41 caratteri, possiamo inserirne tre in un solo messaggio, dobbiamo solo forzare la forza 2 serie di 3333 bit e una serie di 3334 (anche se anche questo è probabilmente ancora eccessivo)

Non è esattamente pratico. Anche con l'immagine a lunghezza fissa a 1 bit 100 * 100 px c'è ..., supponendo che non stia calcolando male, 49995000 combinazioni o 16661667 quando diviso in tre.

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
Il problema con sha1 (my_image) è che se passassi il tuo tempo a forzarlo, probabilmente avresti trovato molte collisioni prima di trovare la vera immagine; e naturalmente forzare brutalmente sha1 è praticamente non calcolabile dal punto di vista computazionale.
Brian Campbell,

5
Ancora meglio della compressione SHA1: il mio algoritmo di compressione "flickr"! Passaggio 1: carica l'immagine su flickr. Passaggio 2: pubblica un link su di esso su Twitter. Tadda! Utilizza solo 15 byte!
niXar,

2
niXar: No, regola 3.4: "Il processo di decodifica potrebbe non avere accesso a nessun altro output del processo di codifica diverso da quello sopra specificato; ovvero, non è possibile caricare l'immagine da qualche parte e inviare l'URL per il processo di decodifica su download o qualsiasi altra cosa sciocca ".
dal

6
Lo so, ero sarcastico.
niXar,


0

Idea: potresti usare un font come tavolozza? Prova a spezzare un'immagine in una serie di vettori cercando di descriverli con una combinazione di set di vettori (ogni personaggio è essenzialmente un set di vettori). Questo sta usando il carattere come dizionario. Potrei ad esempio usare al per una linea verticale e un - per una linea orizzontale? Solo un'idea

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.