Se uma imagem vale mais que 1000 palavras, quanto da imagem você pode caber em 140 caracteres?
Nota : É isso aí pessoal! Chegou o prazo da recompensa e, após algumas deliberações difíceis, decidi que a entrada de Boojum mal superava a de Sam Hocevar . Vou postar notas mais detalhadas assim que tiver a chance de escrevê-las. Obviamente, todos devem se sentir à vontade para continuar enviando soluções e aprimorando soluções para as pessoas votarem. Obrigado a todos que enviaram e inscrevem-se; Eu gostei de todos eles. Isso foi muito divertido para mim, e espero que tenha sido divertido tanto para os participantes quanto para os espectadores.
Me deparei com este post interessante sobre como tentar compactar imagens em um comentário no Twitter, e muitas pessoas nesse tópico (e um tópico no Reddit ) tinham sugestões sobre diferentes maneiras de fazer isso. Então, acho que seria um bom desafio de codificação; permita que as pessoas coloquem seu dinheiro onde estão, e mostre como suas idéias sobre codificação podem levar a mais detalhes no espaço limitado disponível.
Desafio você a criar um sistema de uso geral para codificar imagens em mensagens do Twitter com 140 caracteres e decodificá-las em uma imagem novamente. Você pode usar caracteres Unicode para obter mais de 8 bits por caractere. Mesmo permitindo caracteres Unicode, no entanto, você precisará compactar imagens em uma quantidade muito pequena de espaço; isso certamente será uma compactação com perdas e, portanto, terá que haver julgamentos subjetivos sobre a qualidade de cada resultado.
Aqui está o resultado que o autor original, Quasimondo , obteve de sua codificação (a imagem é licenciada sob uma licença Creative Commons Attribution-Noncommercial ):
Você pode fazer melhor?
Regras
- Seu programa deve ter dois modos: codificação e decodificação .
- Ao codificar :
- Seu programa deve ter como entrada um gráfico em qualquer formato gráfico de varredura razoável de sua escolha. Diremos que qualquer formato raster suportado pelo ImageMagick conta como razoável.
- Seu programa deve gerar uma mensagem que possa ser representada em 140 ou menos pontos de código Unicode; 140 pontos de código no intervalo
U+0000
-U+10FFFF
, excluindo não caracteres (U+FFFE
,U+FFFF
,U+
nFFFE
,U+
nFFFF
, onde n é1
-10
hexadecimal, e a gamaU+FDD0
-U+FDEF
) e pontos de código substituto (U+D800
-U+DFFF
). Pode ser produzido em qualquer codificação razoável de sua escolha; qualquer codificação suportada pelo GNUiconv
será considerada razoável, e a codificação nativa ou local de sua plataforma provavelmente será uma boa opção. Veja as notas Unicode abaixo para mais detalhes.
- Ao decodificar :
- Seu programa deve ter como entrada a saída do seu modo de codificação .
- Seu programa deve gerar uma imagem em qualquer formato razoável de sua escolha, conforme definido acima, embora os formatos vetoriais de saída também sejam aceitáveis.
- A saída da imagem deve ser uma aproximação da imagem de entrada; quanto mais perto você estiver da imagem de entrada, melhor.
- O processo de decodificação pode não ter acesso a nenhuma outra saída do processo de codificação além da saída especificada acima; ou seja, você não pode fazer upload da imagem em algum lugar e gerar o URL para o processo de decodificação baixar, ou algo parecido.
Por uma questão de consistência na interface do usuário, seu programa deve se comportar da seguinte maneira:
- Seu programa deve ser um script que possa ser definido como executável em uma plataforma com o intérprete apropriado ou um programa que possa ser compilado em um executável.
- Seu programa deve tomar como seu primeiro argumento
encode
oudecode
para definir o modo. Seu programa deve receber entradas de uma ou mais das seguintes maneiras (se você implementar a que aceita nomes de arquivos, também poderá ler e gravar a partir de stdin e stdout se houver nomes ausentes):
Capte a entrada da entrada padrão e produza saída com saída padrão.
my-program encode <input.png >output.txt my-program decode <output.txt >output.png
Pegue a entrada de um arquivo nomeado no segundo argumento e produza saída no arquivo nomeado no terceiro.
my-program encode input.png output.txt my-program decode output.txt output.png
- Para sua solução, poste:
- Seu código, na íntegra, e / ou um link para ele hospedado em outro local (se for muito longo ou exigir muitos arquivos para compilar, ou algo assim).
- Uma explicação de como funciona, se não for imediatamente óbvio no código ou se o código for longo e as pessoas se interessarem em um resumo.
- Uma imagem de exemplo, com a imagem original, o texto compactado e a imagem decodificada.
- Se você está construindo uma ideia que alguém teve, atribua-a. Não há problema em tentar refinar a ideia de outra pessoa, mas você deve atribuí-la.
Diretrizes
Estas são basicamente regras que podem ser quebradas, sugestões ou critérios de pontuação:
- A estética é importante. Vou julgar e sugerir que outras pessoas julguem, com base em:
- Qual a aparência da imagem de saída e a aparência da original.
- Que bom o texto parece. O gobbledigook completamente aleatório é bom se você tiver um esquema de compactação realmente inteligente, mas também quero ver respostas que transformam imagens em poemas multilíngües ou algo assim. Observe que o autor da solução original decidiu usar apenas caracteres chineses, pois parecia melhor assim.
- Código interessante e algoritmos inteligentes são sempre bons. Gosto de códigos curtos, diretos e claros, mas algoritmos complicados muito inteligentes são bons demais desde que produzam bons resultados.
- A velocidade também é importante, embora não seja tão importante quanto a qualidade de um trabalho para compactar a imagem que você faz. Prefiro ter um programa que possa converter uma imagem em um décimo de segundo do que algo que estará executando algoritmos genéticos por dias a fio.
- Prefiro soluções mais curtas a soluções mais longas, desde que sejam razoavelmente comparáveis em qualidade; concisão é uma virtude.
- Seu programa deve ser implementado em um idioma que tenha uma implementação disponível gratuitamente no Mac OS X, Linux ou Windows. Eu gostaria de poder executar os programas, mas se você tem uma ótima solução que roda apenas no MATLAB ou algo assim, tudo bem.
- Seu programa deve ser o mais geral possível; deve funcionar com tantas imagens diferentes quanto possível, embora algumas possam produzir melhores resultados do que outras. Em particular:
- Ter algumas imagens integradas no programa às quais corresponde e gravar uma referência e depois produz a imagem correspondente após a decodificação é bastante ruim e cobrirá apenas algumas imagens.
- Um programa que pode capturar imagens de formas simples, planas e geométricas e decompô-las em algum vetor primitivo é bastante bacana, mas se falhar nas imagens além de uma certa complexidade, provavelmente será insuficientemente geral.
- Um programa que só pode capturar imagens de uma determinada proporção fixa, mas faz um bom trabalho com elas também seria bom, mas não ideal.
- Você pode achar que uma imagem em preto e branco pode obter mais informações em um espaço menor que uma imagem colorida. Por outro lado, isso pode limitar os tipos de imagem aos quais é aplicável; os rostos saem bem em preto e branco, mas os desenhos abstratos podem não se sair tão bem.
- É perfeitamente adequado se a imagem de saída for menor que a entrada, enquanto estiver aproximadamente na mesma proporção. Tudo bem se você precisar ampliar a imagem para compará-la ao original; o importante é como fica.
- Seu programa deve produzir resultados que possam realmente passar pelo Twitter e sair ilesos. Isso é apenas uma diretriz e não uma regra, já que não consegui encontrar nenhuma documentação sobre o conjunto preciso de caracteres suportados, mas você provavelmente deve evitar caracteres de controle, caracteres combinados invisíveis e funky, caracteres de uso privado e similares.
Rubrica de pontuação
Como um guia geral de como classificarei as soluções ao escolher minha solução aceita, digamos que provavelmente avaliarei soluções em uma escala de 25 pontos (isso é muito difícil e não pontuarei nada diretamente, apenas usando como orientação básica):
- 15 pontos sobre o quão bem o esquema de codificação reproduz uma ampla gama de imagens de entrada. Este é um julgamento subjetivo, estético
- 0 significa que não funciona, devolve a mesma imagem sempre, ou algo assim
- 5 significa que ele pode codificar algumas imagens, embora a versão decodificada pareça feia e possa não funcionar em imagens mais complicadas
- 10 significa que ele funciona em uma ampla variedade de imagens e produz imagens de aparência agradável que podem ocasionalmente ser distinguíveis
- 15 significa que produz réplicas perfeitas de algumas imagens e, mesmo para imagens maiores e mais complexas, fornece algo que é reconhecível. Ou talvez não faça imagens que sejam bastante reconhecíveis, mas produz imagens bonitas que são claramente derivadas do original.
- 3 pontos para o uso inteligente do conjunto de caracteres Unicode
- 0 pontos por simplesmente usar todo o conjunto de caracteres permitidos
- 1 ponto para usar um conjunto limitado de caracteres que são seguros para transferência pelo Twitter ou em uma variedade maior de situações
- 2 pontos para usar um subconjunto temático de caracteres, como apenas ideogramas Han ou apenas caracteres da direita para a esquerda
- 3 pontos para fazer algo realmente interessante, como gerar texto legível ou usar caracteres que se parecem com a imagem em questão
- 3 pontos para abordagens algorítmicas inteligentes e estilo de código
- 0 pontos para algo que é de 1000 linhas de código apenas para reduzir a imagem, tratá-la como 1 bit por pixel e codificar base64 que
- 1 ponto para algo que usa uma técnica de codificação padrão e é bem escrito e breve
- 2 pontos para algo que introduz uma técnica de codificação relativamente nova ou que é surpreendentemente curta e limpa
- 3 pontos para um liner que realmente produz bons resultados, ou algo que abre novos caminhos na codificação gráfica (se isso parecer um número baixo de pontos para abrir novos caminhos, lembre-se de que um resultado desse bom provavelmente terá uma pontuação alta em estética também)
- 2 pontos por velocidade. Tudo o resto é igual, mais rápido é melhor, mas os critérios acima são todos mais importantes que a velocidade
- 1 ponto para execução no software livre (código aberto), porque eu prefiro o software livre (observe que o C # ainda será elegível para esse ponto enquanto for executado no Mono, da mesma forma o código MATLAB seria elegível se for executado no GNU Octave)
- 1 ponto para realmente seguir todas as regras. Essas regras ficaram um pouco grandes e complicadas, então provavelmente aceitarei boas respostas que apresentem um pequeno detalhe errado, mas darei um ponto extra a qualquer solução que realmente siga todas as regras
Imagens de referência
Algumas pessoas pediram algumas imagens de referência. Aqui estão algumas imagens de referência que você pode tentar; versões menores são incorporadas aqui, todas elas se vinculam a versões maiores da imagem, se você precisar delas:
Prêmio
Estou oferecendo uma recompensa de 500 representantes (mais os 50 que o StackOverflow oferece ) para a solução que eu mais gosto, com base nos critérios acima. Obviamente, incentivo todos os outros a votarem em suas soluções favoritas aqui também.
Nota sobre prazo
Este concurso será realizado até que a recompensa acabe, cerca das 18h no sábado, 30 de maio. Não sei dizer a hora exata em que terminará; pode estar entre as 17 e as 19h. Garantirei que examinarei todas as entradas enviadas até as 14h e farei o possível para ver todas as entradas enviadas até as 16h; se as soluções forem enviadas depois disso, talvez eu não tenha chance de dar uma olhada justa antes de tomar minha decisão. Além disso, quanto mais cedo você enviar, mais chances terá de votar para poder me ajudar a escolher a melhor solução. Portanto, tente enviá-lo mais cedo do que no prazo.
Notas Unicode
Também houve alguma confusão sobre exatamente quais caracteres Unicode são permitidos. O intervalo de possíveis pontos de código Unicode é U+0000
para U+10FFFF
. Existem alguns pontos de código que nunca são válidos para uso como caracteres Unicode em qualquer intercâmbio aberto de dados; esses são os não caracteres e os pontos de código substitutos . Noncharacters são definidos no 5.1.0 secção Unidode Norma 16.7 como os valores U+FFFE
, U+FFFF
, U+
nFFFE
, U+
nFFFF
, onde n é 1
- 10
hexadecimal, e a gama U+FDD0
-U+FDEF
. Esses valores devem ser usados para uso interno específico do aplicativo, e os aplicativos em conformidade podem retirar esses caracteres do texto processado por eles. Pontos de código substitutos, definidos na seção 3.8.0 do Unicode Standard 3.8 como U+D800
- U+DFFF
, são usados para codificar caracteres além do Plano Multilíngue Básico em UTF-16; portanto, é impossível representar esses pontos de código diretamente na codificação UTF-16 e é inválido codificá-los em qualquer outra codificação. Assim, para os fins deste concurso, permitirei que qualquer programa que codifique imagens em uma sequência de no máximo 140 pontos de código Unicode do intervalo U+0000
- U+10FFFF
excluindo todos os não caracteres e pares substitutos, conforme definido acima.
Vou preferir soluções que usam apenas caracteres atribuídos, e melhor ainda aqueles que usam subconjuntos inteligentes de caracteres atribuídos ou fazer algo interessante com o conjunto de caracteres que eles usam. Para obter uma lista dos caracteres atribuídos, consulte o banco de dados de caracteres Unicode ; observe que alguns caracteres são listados diretamente, enquanto outros são listados apenas como o início e o fim de um intervalo. Observe também que os pontos de código substitutos estão listados no banco de dados, mas são proibidos conforme mencionado acima. Se você quiser tirar proveito de certas propriedades dos caracteres para tornar o texto que você produz mais interessante, há uma variedade de bancos de dados com informações sobre caracteres , como uma lista de blocos de código nomeados e várias propriedades de caracteres.
Como o Twitter não especifica exatamente o conjunto de caracteres que eles suportam, serei indulgente com soluções que não funcionam com o Twitter porque certos caracteres contam caracteres extras ou extra. É preferível, mas não obrigatório, que todas as saídas codificadas possam ser transferidas ilesas via Twitter ou outro serviço de microblog, como o identi.ca . Eu vi alguma documentação declarando que o Twitter codifica a entidade <,> e &, e, portanto, conta esses caracteres como 4, 4 e 5, respectivamente, mas eu não testei isso sozinho, e o contador de caracteres JavaScript não parece contá-los dessa maneira.
Dicas e Links
- A definição de caracteres Unicode válidos nas regras é um pouco complicada. A escolha de um único bloco de caracteres, como os Ideógrafos Unificados CJK (U + 4E00 – U + 9FCF), pode ser mais fácil.
- Você pode usar bibliotecas de imagens existentes, como ImageMagick ou Python Imaging Library , para sua manipulação de imagens.
- Se você precisar de ajuda para entender o conjunto de caracteres Unicode e suas várias codificações, consulte este guia rápido ou esta FAQ detalhada sobre UTF-8 no Linux e Unix .
- Quanto mais cedo você encontrar sua solução, mais tempo eu (e outras pessoas votando) terei de analisá-la. Você pode editar sua solução se a melhorar; Baseará minha recompensa na versão mais recente quando der minha última olhada nas soluções.
- Se você deseja que um formato de imagem fácil seja analisado e gravado (e não queira usar apenas um formato existente), sugiro usar o formato PPM . É um formato baseado em texto muito fácil de trabalhar, e você pode usar o ImageMagick para converter para e a partir dele.
fonte
Respostas:
Tudo bem, aqui está o meu: nanocrunch.cpp e o arquivo CMakeLists.txt para construí-lo usando o CMake. Ele se baseia na API Magick ++ ImageMagick para a maior parte de seu tratamento de imagens. Também requer que a biblioteca GMP seja aritmética de bignum para sua codificação de string.
Baseei minha solução na compressão de imagem fractal, com algumas reviravoltas únicas. A idéia básica é obter a imagem, redimensionar uma cópia para 50% e procurar peças em várias orientações semelhantes a blocos não sobrepostos na imagem original. É necessária uma abordagem de força muito bruta para essa pesquisa, mas isso facilita a introdução de minhas modificações.
A primeira modificação é que, em vez de apenas olhar para rotações e inversões de noventa graus, meu programa também considera orientações de 45 graus. É mais um bit por bloco, mas ajuda imensamente a qualidade da imagem.
A outra coisa é que armazenar um ajuste de contraste / brilho para cada componente de cor de cada bloco é muito caro. Em vez disso, armazeno uma cor fortemente quantizada (a paleta tem apenas 4 * 4 * 4 = 64 cores) que simplesmente se mistura em alguma proporção. Matematicamente, isso é equivalente a um brilho variável e a um ajuste constante de contraste para cada cor. Infelizmente, isso também significa que não há contraste negativo para mudar as cores.
Uma vez calculada a posição, orientação e cor de cada bloco, ele codifica isso em uma string UTF-8. Primeiro, ele gera um bignum muito grande para representar os dados na tabela de blocos e o tamanho da imagem. A abordagem para isso é semelhante à solução de Sam Hocevar - tipo de número grande, com um raio que varia de acordo com a posição.
Em seguida, ele converte isso em uma base, independentemente do tamanho do conjunto de caracteres disponível. Por padrão, ele faz uso total do conjunto de caracteres unicode atribuído, menos os caracteres menor que, maior que e comercial, controle, combinação e substituto e privado. Não é bonito, mas funciona. Você também pode comentar a tabela padrão e selecionar ASCII de 7 bits imprimível (excluindo novamente caracteres <,> e &) ou Ideógrafos unificados CJK. A tabela com os códigos de caracteres disponíveis é armazenada com um comprimento de execução codificado com execuções alternadas de caracteres inválidos e válidos.
De qualquer forma, aqui estão algumas imagens e horários (conforme medido no meu antigo P4 de 3,0 GHz) e compactados para 140 caracteres no conjunto unicode designado completo descrito acima. No geral, estou bastante satisfeito com o resultado. Se eu tivesse mais tempo para trabalhar nisso, provavelmente tentaria reduzir o bloqueio das imagens descomprimidas. Ainda assim, acho que os resultados são bons para a taxa de compressão extrema. As imagens descompactadas são um pouco impressionistas, mas acho relativamente fácil ver como os bits correspondem ao original.
Logotipo do estouro de pilha (8.6s para codificar, 7.9s para decodificar, 485 bytes):
http://i44.tinypic.com/2w7lok1.png
Lena (32,8s para codificar, 13,0s para decodificar, 477 bytes):
http://i42.tinypic.com/2rr49wg.png http://i40.tinypic.com/2rhxxyu.png
Mona Lisa (43,2 segundos para codificar, 14,5 segundos para decodificar, 490 bytes):
http://i41.tinypic.com/ekgwp3.png http://i43.tinypic.com/ngsxep.png
Editar: CJK caracteres unificados
Sam perguntou nos comentários sobre como usar isso com o CJK. Aqui está uma versão da Mona Lisa compactada para 139 caracteres do conjunto de caracteres CJK Unified:
http://i43.tinypic.com/2yxgdfk.png Clique para ampliar Clique para ampliar Clique para ampliar Clique para ampliar Clique para ampliar Clique para ampliar Clique para ampliar Clique para ampliar隤 慛 絖 銓 馿 掾 撄 粂 敽 稉 擎 蔍 螎 葙 峬 覧 絀 蹔 抆 惫 笻 笻 哜 搀 澐 芯 辍 辍 辍 垝 而 辍 猳 閺 而 猳 猳 猳 而 猳 猳 猳 猳 猳伆 杇 婣 唆 鐤 毤 埙 誖 萜 旖 鞰 萗 勹 鈱 哳 垬 濅 鬒 秀 瞛 认 认 気 狋 異 闥 珵 珵 珵 氙 餅 珵 熥 勳 餅 熥 熥 熥 餅 熥 熥 熥 熥 熥擸 萿
Os parâmetros de ajuste na parte superior do programa que usei para isso foram: 19, 19, 4, 4, 3, 10, 11, 1000, 1000. Também comentei a primeira definição de number_assigned e codes e descomentei o últimas definições para selecionar o conjunto de caracteres CJK Unified.
fonte
arquivos de imagem e fonte python (versões 1 e 2)
Versão 1 Aqui está minha primeira tentativa. Vou atualizar conforme for.
Eu tenho o logotipo SO até 300 caracteres quase sem perdas. Minha técnica usa a conversão para arte vetorial SVG, para que funcione melhor na arte de linha. Na verdade, é um compressor SVG, ainda exige que a arte original passe por um estágio de vetorização.
Na minha primeira tentativa, usei um serviço on - line para o rastreamento PNG, no entanto, existem MUITAS ferramentas gratuitas e não gratuitas que podem lidar com essa parte, incluindo potrace (código aberto).
Aqui estão os resultados
Logo SO original http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png Logo SO original decodificado http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded.png Após a codificação e decodificação
Personagens : 300
Tempo : não medido, mas praticamente instantâneo (sem incluir etapas de vetorização / rasterização)
O próximo estágio será incorporar 4 símbolos (pontos e comandos do caminho SVG) por caractere unicode. No momento, minha compilação python não possui suporte amplo a caracteres UCS4, o que limita minha resolução por caractere. Também limitei o intervalo máximo para a extremidade inferior do intervalo reservado unicode 0xD800; no entanto, depois de criar uma lista de caracteres permitidos e um filtro para evitá-los, teoricamente posso empurrar o número necessário de caracteres para 70-100 para o logo acima.
Uma limitação deste método no momento é que o tamanho da saída não é fixo. Depende do número de nós / pontos do vetor após a vetorização. A automação desse limite exigirá pixelização da imagem (que remove os principais benefícios dos vetores) ou execução repetida dos caminhos por um estágio de simplificação até que a contagem de nós desejada seja alcançada (o que atualmente estou fazendo manualmente no Inkscape).
Versão 2
ATUALIZAÇÃO : a v2 agora está qualificada para competir. Alterar:
Personagens : 133
Tempo : alguns segundos
v2 decoded http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded-v2.png Após codificação e decodificação (versão 2)
Como você pode ver, existem alguns artefatos dessa vez. Não é uma limitação do método, mas um erro em algum lugar das minhas conversões. Os artefatos acontecem quando os pontos ultrapassam o intervalo de 0,0 a 127,0 e minhas tentativas de restringi-los tiveram um sucesso misto. A solução é simplesmente reduzir a imagem, no entanto, tive problemas para dimensionar os pontos reais em vez da prancheta ou da matriz do grupo e agora estou cansado demais para me importar. Em resumo, se seus pontos estão no intervalo suportado, geralmente funciona.
Acredito que a torção no meio se deve a uma alça que se move para o outro lado de uma alça à qual está ligada. Basicamente, os pontos estão muito próximos em primeiro lugar. A execução de um filtro simplificado sobre a imagem de origem antes da compactação deve corrigir isso e eliminar alguns caracteres desnecessários.
ATUALIZAÇÃO : Este método é adequado para objetos simples, então eu precisava de uma maneira de simplificar caminhos complexos e reduzir o ruído. Eu usei o Inkscape para esta tarefa. Tive alguma sorte em preparar caminhos desnecessários usando o Inkscape, mas não tive tempo para tentar automatizá-lo. Fiz alguns exemplos de svgs usando a função 'Simplificar' do Inkscape para reduzir o número de caminhos.
Simplificar funciona ok, mas pode ser lento com muitos caminhos.
exemplo de autotrace http://www.warriorhut.org/graphics/svg_to_unicode/autotrace_16_color_manual_reduction.png caixa cornell 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
miniaturas rastreadas http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_autotrace.png
Aqui estão algumas fotos de ultra baixa resolução. Eles estariam mais próximos do limite de 140 caracteres, embora também seja necessária alguma compactação de caminho inteligente.
groomed http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_groomed.png Simplificado e despeckled.
trianglulated http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_triangulated.png simplificado, manchas retiradas e triangulada.
ACIMA: Caminhos simplificados usando rastreamento automático .
Infelizmente, meu analisador não lida com a saída de rastreamento automático, então não sei como os pontos estão em uso ou até que ponto simplificar. Infelizmente, há pouco tempo para escrevê-lo antes do prazo. É muito mais fácil analisar do que a saída do inkscape.
fonte
Minha solução completa pode ser encontrada em http://caca.zoy.org/wiki/img2twit . Possui os seguintes recursos:
Aqui está uma visão geral do processo de codificação:
E este é o processo de decodificação:
O que acredito ser a parte mais original do programa é o fluxo de bits. Em vez de empacotar valores alinhados por bits (
stream <<= shift; stream |= value
), compacto valores arbitrários que não estão na faixa de dois potências (stream *= range; stream += value
). Isso requer cálculos bignum e, é claro, é muito mais lento, mas me dá 2009,18 bits em vez de 1960 ao usar os caracteres CJK principais do 20902 (são mais três pontos que posso colocar nos dados). E ao usar ASCII, ele me fornece 917,64 bits em vez de 840.Decidi contra um método para o cálculo inicial da imagem que exigiria armas pesadas (detecção de canto, extração de recursos, quantização de cores ...) porque não tinha certeza no início que realmente ajudaria. Agora percebo que a convergência é lenta (1 minuto é aceitável, mas é lento, no entanto) e posso tentar melhorar isso.
O loop de ajuste principal é pouco inspirado no algoritmo de pontilhamento Direct Binary Seach (em que os pixels são trocados ou invertidos aleatoriamente até obter um meio-tom melhor). O cálculo da energia é uma distância quadrática média quadrática simples, mas realizo primeiro um filtro mediano de 5x5 na imagem original. Um borrão gaussiano provavelmente representaria melhor o comportamento do olho humano, mas eu não queria perder arestas vivas. Também decidi contra o recozimento simulado ou outros métodos difíceis de ajustar, porque não tenho meses para calibrar o processo. Portanto, o sinalizador "qualidade" representa apenas o número de iterações que são executadas em cada ponto antes do final do codificador.
Embora nem todas as imagens sejam compactadas bem, estou surpreso com os resultados e realmente me pergunto quais outros métodos existem que podem compactar uma imagem para 250 bytes.
Eu também tenho pequenos filmes da evolução do estado do codificador a partir de um estado inicial aleatório e de um estado inicial "bom" .
Editar : aqui está como o método de compactação se compara ao JPEG. À esquerda, o jamoes está acima da imagem de 536 bytes. À direita, a Mona Lisa compactou até 534 bytes usando o método descrito aqui (os bytes mencionados aqui se referem a bytes de dados, portanto, ignorando os bits desperdiçados usando caracteres Unicode):
Editar : acabou de substituir o texto CJK pelas versões mais recentes das imagens.
fonte
O seguinte não é um envio formal, pois meu software não foi adaptado de forma alguma para a tarefa indicada. O DLI pode ser descrito como um codec de imagem com perda de propósito geral otimizado. É o detentor do registro PSNR e MS-SSIM para compactação de imagem, e pensei que seria interessante ver o desempenho dessa tarefa em particular. Usei a imagem de referência da Mona Lisa fornecida e a reduzi para 100x150, depois usei o DLI para compactá-la para 344 bytes.
Mona Lisa DLI http://i40.tinypic.com/2md5q4m.png
Para comparação com as amostras compactadas JPEG e IMG2TWIT, usei o DLI para compactar a imagem em 534 bytes também. O JPEG tem 536 bytes e IMG2TWIT é 534 bytes. As imagens foram dimensionadas para aproximadamente o mesmo tamanho para facilitar a comparação. JPEG é a imagem da esquerda, IMG2TWIT é o centro e DLI é a imagem da direita.
Comparação http://i42.tinypic.com/302yjdg.png
A imagem DLI consegue preservar algumas das características faciais, principalmente o famoso sorriso :).
fonte
A visão geral da minha solução seria:
Sei que você estava pedindo código, mas não quero gastar muito tempo para codificá-lo. Imaginei que um design eficiente pudesse pelo menos inspirar alguém a codificar isso.
Eu acho que o principal benefício da minha solução proposta é que ela está reutilizando o máximo de tecnologia existente possível. Pode ser divertido tentar escrever um bom algoritmo de compactação, mas é garantido que existe um algoritmo melhor por aí, provavelmente escrito por pessoas com um diploma em matemática mais alta.
Uma outra observação importante é que, se for decidido que utf16 é a codificação preferida, essa solução se desfaz. JPEGs realmente não funcionam quando compactados até 280 bytes. Embora, talvez exista um algoritmo de compactação melhor que o jpg para esta declaração de problema específica.
fonte
Ok, estou atrasado para o jogo, mas mesmo assim fiz o meu projeto.
É um algoritmo genético de brinquedo que usa círculos coloridos translúcidos para recriar a imagem inicial.
Recursos:
Mis-feautres:
Aqui está um exemplo de twit que representa Lena: 犭 楊 谷 杌 螦 扝 俄 归 晃 客 猘 摈 硰 划 刀 萕 码 摃 斢 斢 蜁 划 摃 斢 嘁 蜁 簜 摃 斢 蜁 澹 簜 斢 嘁 蜁 簜 僨 斢 團 澹岂 掂 戇 耔 攋 昸 箆 亲 嬎 栃 兡 塅 受 橯 恰 应 戞 优 猫 僘 吱 吱 賾 卣 朸 杈 綍 綍 綍 猕 厥 綍 尕 熚 厥 尕 尕 尕 厥 尕 尕 尕 尕 尕虲 兙 罨 縨 炘 弅 慌 螎 熰 宑 簫 柢 橙 拃 丨 蜊 缩 昔 儻 舭 癳 癳 冂 囤 璟 彔 兠 兠 兠 侑 訜 兠 嫡 琠 訜 嫡 嫡 嫡 訜 嫡 嫡 嫡 嫡 嫡厇 廩 焛 瀻 严 刱 垫 仔
O código está em um repositório Mercurial em bitbucket.org. Confira http://bitbucket.org/tkadlubo/circles.lua
fonte
A seguir, é minha abordagem do problema e devo admitir que este foi um projeto bastante interessante de se trabalhar, está definitivamente fora do meu domínio normal de trabalho e me deu algo novo para aprender.
A idéia básica por trás da minha é a seguinte:
Acontece que isso funciona, mas apenas em uma extensão limitada, como você pode ver nas imagens de exemplo abaixo. Em termos de saída, o que se segue é um exemplo de tweet, especificamente para a imagem Lena mostrada nas amostras.
Como você pode ver, tentei restringir um pouco o conjunto de caracteres; no entanto, tive problemas ao armazenar os dados de cores da imagem. Além disso, esse esquema de codificação também tende a desperdiçar vários bits de dados que podem ser usados para obter informações adicionais sobre a imagem.
Em termos de tempo de execução, para imagens pequenas, o código é extremamente rápido, cerca de 55ms para as imagens de amostra fornecidas, mas o tempo aumenta com imagens maiores. Para a imagem de referência Lena de 512x512, o tempo de execução foi de 1182ms. Devo observar que as probabilidades são muito boas de que o código em si não seja muito otimizado para o desempenho (por exemplo, tudo é trabalhado como um bitmap ) para que os tempos possam diminuir um pouco após alguma refatoração.
Sinta-se à vontade para me oferecer sugestões sobre o que eu poderia ter feito melhor ou o que pode estar errado com o código. A lista completa dos tempos de execução e da amostra de saída pode ser encontrada no seguinte local: http://code-zen.info/twitterimage/
Update One
Atualizei o código RLE usado ao compactar a string do tweet para fazer uma retrospectiva básica e, se sim, use isso para a saída. Isso funciona apenas para os pares de valores numéricos, mas salva alguns caracteres de dados. O tempo de execução é mais ou menos o mesmo, assim como a qualidade da imagem, mas os tweets tendem a ser um pouco menores. Vou atualizar o gráfico no site à medida que concluir o teste. O que se segue é uma das seqüências de exemplo de tweet, novamente para a versão pequena do Lena:
Atualização dois
Outra pequena atualização, mas modifiquei o código para agrupar os tons de cores em grupos de três, em vez de quatro, isso usa mais espaço, mas, a menos que eu esteja perdendo alguma coisa, isso significa que caracteres "estranhos" não aparecem mais onde a cor dados são. Além disso, atualizei a compactação um pouco mais para que agora ela possa atuar sobre toda a cadeia, em vez de apenas o bloco de contagem de cores. Ainda estou testando os tempos de execução, mas eles parecem ter melhorado nominalmente; no entanto, a qualidade da imagem ainda é a mesma. O que se segue é a versão mais recente do tweet de Lena:
Logotipo StackOverflow http://code-zen.info/twitterimage/images/stackoverflow-logo.bmp Cornell Box http://code-zen.info/twitterimage/images/cornell-box.bmp Lena http: // code-zen .info / twitterimage / images / lena.bmp Mona Lisa http://code-zen.info/twitterimage/images/mona-lisa.bmp
fonte
Esse algoritmo genético que Roger Alsing escreveu possui uma boa taxa de compressão, à custa de longos tempos de compressão. O vetor resultante de vértices pode ser ainda mais compactado usando um algoritmo com ou sem perdas.
http://rogeralsing.com/2008/12/07/genetic-programming-evolution-of-mona-lisa/
Seria um programa interessante para implementar, mas vou sentir falta.
fonte
No desafio original, o limite de tamanho é definido como o que o Twitter ainda permite enviar se você colar o texto na caixa de texto e pressionar "atualizar". Como algumas pessoas perceberam corretamente, isso é diferente do que você pode enviar como uma mensagem de texto SMS do seu celular.
O que não é mencionado explicitamente (mas qual era minha regra pessoal) é que você deve poder selecionar a mensagem tweetada no seu navegador, copiá-la na área de transferência e colá-la em um campo de entrada de texto do seu decodificador para que ele possa ser exibido. É claro que você também pode salvar a mensagem como um arquivo de texto e lê-la novamente ou escrever uma ferramenta que acessa a API do Twitter e filtra qualquer mensagem que se pareça com um código de imagem (marcadores especiais alguém? Wink wink ). Mas a regra é que a mensagem deve ter passado pelo Twitter antes que você possa decodificá-la.
Boa sorte com os 350 bytes - duvido que você possa usá-los.
fonte
A publicação de uma imagem monocromática ou em escala de cinza deve melhorar o tamanho da imagem que pode ser codificada nesse espaço, pois você não se importa com cores.
Possivelmente aumentando o desafio de fazer o upload de três imagens que, quando recombinadas, fornecem uma imagem em cores, mantendo uma versão monocromática em cada imagem separada.
Adicione um pouco de compressão ao acima e ele pode começar a parecer viável ...
Agradável!!! Agora vocês despertaram meu interesse. Nenhum trabalho será feito pelo resto do dia ...
fonte
Em relação à parte de codificação / decodificação deste desafio. base16b.org é minha tentativa de especificar um método padrão para codificar com segurança e eficiência dados binários nos planos Unicode superiores.
Algumas funcionalidades :
Desculpe, esta resposta chega muito tarde para a competição original. Comecei o projeto independentemente deste post, que descobri no meio do caminho.
fonte
A idéia de armazenar várias imagens de referência é interessante. Seria tão errado armazenar, digamos, 25Mb de imagens de amostra, e pedir ao codificador para compor uma imagem usando bits dessas? Com uma tubulação tão minúscula, a maquinaria de cada extremidade é necessariamente maior do que o volume de dados que passa, então qual é a diferença entre 25Mb de código e 1Mb de código e 24Mb de dados de imagem?
(observe que as diretrizes originais descartaram restringir a entrada a imagens já existentes na biblioteca - não estou sugerindo isso).
fonte
Idéia estúpida, mas
sha1(my_image)
resultaria em uma representação "perfeita" de qualquer imagem (ignorando colisões). O problema óbvio é que o processo de decodificação requer quantidades excessivas de força bruta.Monocromático de 1 bit seria um pouco mais fácil. Cada pixel se torna 1 ou 0, para que você tenha 1000 bits de dados para uma imagem de 100 * 100 pixels. Como o hash SHA1 possui 41 caracteres, podemos encaixar três em uma mensagem, apenas para força bruta 2 conjuntos de 3333 bits e um conjunto de 3334 (embora mesmo isso provavelmente ainda seja desordenado)
Não é exatamente prático. Mesmo com a imagem 100 * 100px de 1 bit de comprimento fixo, existe .., supondo que eu não esteja calculando mal as combinações 49995000 ou 16661667 quando dividido em três.
fonte
Aqui essa compressão é boa.
http://www.intuac.com/userport/john/apt/
http://img86.imageshack.us/img86/4169/imagey.jpg http://img86.imageshack.us/img86/4169/imagey.jpg
Eu usei o seguinte arquivo em lotes:
O tamanho do arquivo resultante é 559 bytes.
fonte
Idéia: você poderia usar uma fonte como paleta? Tente quebrar uma imagem em uma série de vetores, tentando descrevê-los com uma combinação de conjuntos de vetores (cada caractere é essencialmente um conjunto de vetores). Isso está usando a fonte como um dicionário. Eu poderia, por exemplo, usar al para uma linha vertical e um - para uma linha horizontal? Apenas uma ideia.
fonte