如果一张图片价值1000字,你可以在140个字符中放入多少图片?
注意:那就是大家!赏金的最后期限就在这里,经过一番艰难的考虑后,我认为Boojum的进入只是勉强淘汰Sam Hocevar的.一旦我有机会写出来,我会发布更详细的笔记.当然,每个人都应该随时继续提交解决方案并改进人们投票的解决方案.感谢所有提交和参赛的人; 我很喜欢他们.这对我来说非常有趣,我希望这对参赛者和观众来说都很有趣.
我遇到了一篇关于尝试将图像压缩成Twitter评论的有趣帖子,该线程中的很多人(以及Reddit上的一个帖子)都提出了有关不同方法的建议.所以,我认为这将是一个很好的编码挑战; 让人们将钱放在嘴边,并展示他们对编码的看法如何在有限的空间中提供更多细节.
我挑战你想出一个通用系统,用于将图像编码成140个字符的Twitter消息,并将它们再次解码为图像.您可以使用Unicode字符,因此每个字符的字符数超过8位.但是,即使允许使用Unicode字符,也需要将图像压缩到非常小的空间内; 这肯定会是一种有损压缩,因此必须对每种结果的好看进行主观判断.
以下是原作者Quasimondo从他的编码中获得的结果(图片根据知识共享署名 - 非商业许可证授权):
你能做得更好吗?
您的程序必须有两种模式:编码和解码.
当编码:
您的程序必须以您选择的任何合理光栅图形格式输入图形作为输入.我们会说ImageMagick支持的任何栅格格式都算合理.
您的程序必须输出一条消息,该消息可以用140个或更少的Unicode代码点表示; 在范围140个的代码点U+0000
- U+10FFFF
,排除非字符(U+FFFE
,U+FFFF
,U+
ÑFFFE
,U+
ÑFFFF
其中Ñ是1
- 10
十六进制和范围U+FDD0
- U+FDEF
)和替代代码点(U+D800
- U+DFFF
).它可以以您选择的任何合理编码输出; GNUiconv
支持的任何编码都被认为是合理的,您的平台本机编码或区域编码可能是一个不错的选择.有关详细信息,请参阅下面的Unicode注释
当解码:
您的程序应该将编码模式的输出作为输入.
您的程序必须以您选择的任何合理格式输出图像,如上所述,但输出矢量格式也可以.
图像输出应该是输入图像的近似值; 越接近输入图像越好.
除了上面指定的输出之外,解码过程可能无法访问编码过程的任何其他输出; 也就是说,你不能在某处上传图像并输出用于下载的解码过程的URL,或任何类似的傻事.
为了用户界面的一致性,您的程序必须按如下方式运行:
您的程序必须是可以在具有相应解释器的平台上设置为可执行的脚本,或者可以编译为可执行文件的程序.
您的程序必须作为其第一个参数encode
或decode
设置模式.
您的程序必须通过以下一种或多种方式获取输入(如果您实现了带文件名的方法,如果文件名丢失,您也可以从stdin和stdout读取和写入):
从标准输入获取输入并在标准输出上产生输出.
my-program encodeoutput.txt my-program decode output.png
从第二个参数中指定的文件中获取输入,并在第三个参数中指定的文件中生成输出.
my-program encode input.png output.txt my-program decode output.txt output.png
对于您的解决方案,请发布:
你的代码,完整的,和/或在其他地方托管的链接(如果它很长,或者需要很多文件来编译,或者其他东西).
解释它是如何工作的,如果代码中不是很明显,或者代码很长,人们会对摘要感兴趣.
示例图像,包含原始图像,压缩到的文本以及解码图像.
如果您的想法是基于其他人的想法,请归因于他们.尝试改进别人的想法是可以的,但你必须归因于他们.
这些基本上是可能被破坏的规则,建议或评分标准:
美学很重要.我将评判,并建议其他人判断,基于:
输出图像看起来有多好,它看起来像原始图像.
文字看起来有多好看.如果你有一个非常聪明的压缩方案,完全随机的gobbledigook是好的,但我也希望看到将图像变成多语言的答案,或者像这样聪明的东西.请注意,原始解决方案的作者决定只使用中文字符,因为它看起来更好.
有趣的代码和聪明的算法总是很好.我喜欢简短,重点和清晰的代码,但只要它们产生良好的结果,真正聪明的复杂算法也可以.
速度也很重要,但不如压缩你做的图像的工作有多重要.我宁愿有一个程序可以在十分之一秒内转换图像,而不是几天运行遗传算法的图像.
我会更喜欢较短的解决方案,只要它们在质量上具有相当的可比性; 简洁是一种美德.
您的程序应该使用在Mac OS X,Linux或Windows上具有可自由实现的实现的语言来实现.我希望能够运行这些程序,但如果你有一个只能在MATLAB下运行的优秀解决方案,那很好.
你的计划应该尽可能一般; 它应该适用于尽可能多的不同图像,尽管有些图像可能比其他图像产生更好的结果.特别是:
将一些内置于程序中的图像与其匹配并写入引用,然后在解码时生成匹配图像,相当蹩脚,并且仅覆盖少量图像.
一个可以拍摄简单,平面,几何形状的图像并将它们分解成一些矢量图形的程序非常漂亮,但是如果它在超出一定复杂度的图像上失败则可能不够通用.
一个程序只能拍摄特定固定宽高比的图像,但能很好地使用它们也可以,但不理想.
您可能会发现黑白图像可以在比彩色图像更小的空间中获得更多信息.另一方面,这可能会限制它适用的图像类型; 黑色和白色的面孔很好,但抽象的设计可能不会那么好.
如果输出图像小于输入,则完全没有问题,而大致相同的比例.如果您必须将图像缩放以将其与原始图像进行比较,则可以.重要的是它的外观.
你的程序应该产生的输出实际上可以通过Twitter并且毫发无伤.这只是一个指导而不是规则,因为我找不到任何支持的精确字符集的文档,但你应该避免控制字符,时髦的隐形组合字符,私人使用字符等.
作为我在选择我接受的解决方案时如何对解决方案进行排名的一般指南,让我说我可能会以25分的比例评估解决方案(这非常粗糙,我不会直接评分任何东西,只是使用这是一个基本准则):
15点表示编码方案如何再现各种输入图像.这是一种主观的审美判断
0表示它根本不起作用,每次都会返回相同的图像,或者其他东西
5意味着它可以编码一些图像,虽然解码版本看起来很丑,但在更复杂的图像上它可能根本不起作用
10意味着它适用于各种图像,并产生令人愉悦的图像,偶尔可以区分
15意味着它可以生成一些图像的完美复制品,即使对于更大和更复杂的图像,它也能提供可识别的东西.或者,它可能不会使图像具有很强的识别性,但会产生明显来自原始图像的精美图像.
聪明地使用Unicode字符集 3分
简单地使用整组允许的字符为0分
1点使用一组有限的字符,这些字符可以安全地通过Twitter或更广泛的情况进行传输
使用主题字符子集的2分,例如仅汉字表意文字或仅从右到左字符
做一些非常整洁的事情需要3分,例如生成可读文本或使用看起来像有问题的图像的字符
聪明的算法方法和代码风格有 3个点
只有1000行代码的0分才能缩小图像,将其视为每像素1位,而base64编码为
对于使用标准编码技术并且写得很好并且简短的东西的1分
对于引入相对新颖的编码技术或者令人惊讶的短而干净的东西的2分
实际上可以产生良好效果的一个衬垫有3个点,或者在图形编码方面突破新领域的东西(如果这看起来像是一个很少的分数用于突破新的领域,请记住,这个优点可能会对美学产生高分以及)
2分的速度.在其他条件相同的情况下,速度越快越好,但上述标准都比速度更重要
在免费(开源)软件上运行1分,因为我更喜欢免费软件(请注意,只要它在Mono上运行,C#仍然符合此要求,如果在GNU Octave上运行,MATLAB代码也是合格的)
实际遵守所有规则的1分.这些规则变得有点大而复杂,所以我可能会接受其他好的答案,这会让一个小细节错误,但我会给任何实际遵循所有规则的解决方案额外的一点
有些人要求提供一些参考图像.以下是一些您可以尝试的参考图像; 这里嵌入了较小的版本,如果您需要,它们都链接到更大版本的图像:
根据上述标准,我提供了500个代表奖金(加上StackOverflow推出的50个奖励),用于我最喜欢的解决方案.当然,我也鼓励其他人在这里投票选出他们最喜欢的解决方案.
这场比赛将持续到赏金用完,即5月30日星期六下午6点左右.我不能说它将结束的确切时间; 它可能是从下午5点到7点.我保证我会查看下午2点提交的所有参赛作品,我会尽力查看下午4点提交的所有参赛作品; 如果在此之后提交解决方案,我可能没有机会在我做出决定之前给他们一个公平的看法.此外,您提交的越早,您投票的机会就越大,能够帮助我选择最佳解决方案,因此请尽早提交,而不是在截止日期前提交.
究竟是什么允许Unicode字符也存在一些混淆.可能的Unicode代码点的范围是U+0000
到U+10FFFF
.在任何开放的数据交换中,有一些代码点永远无法用作Unicode字符; 这些都是noncharacters和代理代码点.Noncharacters在所定义的Unidode标准5.1.0节16.7作为值U+FFFE
,U+FFFF
,U+
ÑFFFE
,U+
ÑFFFF
其中Ñ是1
- 10
十六进制和范围U+FDD0
- U+FDEF
.这些值旨在用于特定于应用程序的内部使用,并且符合要求的应用程序可能会将这些字符从它们处理的文本中删除.替代代码点,在所定义的Unicode标准5.1.0节3.8如U+D800
- U+DFFF
,被用于在UTF-16编码以外的基本多语种平面字符; 因此,不可能直接在UTF-16编码中表示这些代码点,并且在任何其他编码中对它们进行编码是无效的.因此,为了本次比赛的目的,我将允许任何编码图像的程序从该范围内不超过140个Unicode代码点的序列U+0000
- U+10FFFF
不包括上面定义的所有非字符和代理对.
我更喜欢只使用指定字符的解决方案,甚至更喜欢使用指定字符的聪明子集或使用他们使用的字符集做一些有趣事情的解决方案.有关指定字符的列表,请参阅Unicode字符数据库 ; 请注意,某些字符是直接列出的,而有些字符仅列为范围的开头和结尾.另请注意,代理代码点列在数据库中,但如上所述是禁止的.如果您希望利用字符的某些属性来使输出的文本更有趣,则可以使用各种字符信息数据库,例如命名代码块列表和各种字符属性.
由于Twitter没有指定他们支持的确切字符集,因此我会对那些实际上不适用于Twitter的解决方案感到宽容,因为某些字符会计算额外的或某些字符被剥离.优选但不要求所有编码输出应该能够通过Twitter或其他微博服务(例如identi.ca)无损地传输.我已经看到一些文档声明Twitter实体编码<,>和&,因此分别计算为4个,4个和5个字符,但我没有自己测试过,他们的JavaScript字符计数器似乎没有以那种方式来统计他们.
规则中有效Unicode字符的定义有点复杂.选择单个字符块,例如CJK统一表意文字(U + 4E00-U + 9FCF)可能更容易.
您可以使用现有的图像库(如ImageMagick或Python Imaging Library)进行图像处理.
如果您需要一些帮助来理解Unicode字符集及其各种编码,请参阅本快速指南或有关Linux和Unix中UTF-8的详细常见问题解答.
越早获得解决方案,我(以及其他人投票)就必须有更多时间来查看它.如果您改进了解,您可以编辑解决方案; 当我最后一次查看解决方案时,我将以最新版本为基础.
如果你想要一个简单的图像格式来解析和写(并且不想只使用现有的格式),我建议使用PPM格式.它是一种基于文本的格式,非常易于使用,您可以使用ImageMagick进行转换.
SpliFF.. 288
图像文件和python源(版本1和2)
版本1 这是我的第一次尝试.我会随时更新.
我的SO标识低至300个字符几乎无损.我的技术使用转换为SVG矢量艺术,因此它在线条艺术上效果最佳.它实际上是一个SVG压缩器,它仍然需要原始艺术经历矢量化阶段.
对于我的第一次尝试,我使用了PNG跟踪的在线服务,但是有许多免费和非免费的工具可以处理这个部分,包括potrace(开源).
结果如下
原创SO徽标http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png原始 解码SO徽标http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded.png编码后解码
人物:300
时间:未测量但实际上是即时的(不包括矢量化/光栅化步骤)
下一阶段将是每个unicode字符嵌入4个符号(SVG路径点和命令).目前我的python构建没有广泛的字符支持UCS4,这限制了我的每个字符的分辨率.我还将最大范围限制在unicode保留范围0xD800的下端,但是一旦我构建了一个允许字符列表和一个避免它们的过滤器,理论上我可以将所需的字符数推低到70-100.上面的标志.
目前该方法的局限性在于输出大小不固定.它取决于矢量化后矢量节点/点的数量.自动化此限制将要求对图像进行像素化(这会消除向量的主要优点)或重复运行路径直到达到所需的节点数(我目前在Inkscape中手动执行).
版本2
更新:v2现在有资格参加比赛.变化:
命令行控制输入/输出和调试
使用XML解析器(lxml)来处理SVG而不是正则表达式
每个unicode符号包含2个路径段
文档和清理
支持样式="填充:颜色"和填充="颜色"
文档宽度/高度打包成单个字符
路径颜色打包成单个字符
通过每种颜色丢弃4位颜色数据然后通过十六进制转换将其打包成字符来实现颜色压缩.
人物:133
时间:几秒钟
v2解码http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded-v2.png编码和解码后(版本2)
如你所见,这次有一些文物.这不是方法的限制,而是我转换中的某个错误.当点超出范围0.0 - 127.0并且我试图限制它们的尝试取得了成功时,工件就会发生.解决方案只是缩小图像,但是我无法缩放实际点而不是画板或组矩阵,现在我太累了.简而言之,如果您的积分在支持的范围内,它通常会起作用.
我相信中间的扭结是由于手柄移动到它所连接的手柄的另一侧.基本上这些点在一开始就太靠近了.在压缩源图像之前对源图像运行简化过滤器应该解决这个问题并削减一些不必要的字符.
更新:此方法适用于简单对象,因此我需要一种简化复杂路径和降低噪音的方法.我使用Inkscape完成这项任务.我有幸运用Inkscape修饰不必要的路径,但没有时间尝试自动化它.我使用Inkscape'Simplify'函数制作了一些示例svgs来减少路径数量.
简化工作正常但是这条路径很慢.
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
跟踪缩略图http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_autotrace.png
这是一些超低分辨率的镜头.虽然也可能需要一些巧妙的路径压缩,但它们更接近140个字符的限制.
修饰http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_groomed.png 简化和去斑点.
trianglulated http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_triangulated.png 简化,去斑和三角化.
autotrace --output-format svg --output-file cornell_box.svg --despeckle-level 20 --color-count 64 cornell_box.png
上图:使用autotrace的简化路径.
不幸的是我的解析器没有处理autotrace输出,所以我不知道可能有多少点正在使用或者有多远可以简化,遗憾的是在截止日期之前没有时间编写它.然而,它比inkscape输出更容易解析.
图像文件和python源(版本1和2)
版本1 这是我的第一次尝试.我会随时更新.
我的SO标识低至300个字符几乎无损.我的技术使用转换为SVG矢量艺术,因此它在线条艺术上效果最佳.它实际上是一个SVG压缩器,它仍然需要原始艺术经历矢量化阶段.
对于我的第一次尝试,我使用了PNG跟踪的在线服务,但是有许多免费和非免费的工具可以处理这个部分,包括potrace(开源).
结果如下
原创SO徽标http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png原始 解码SO徽标http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded.png编码后解码
人物:300
时间:未测量但实际上是即时的(不包括矢量化/光栅化步骤)
下一阶段将是每个unicode字符嵌入4个符号(SVG路径点和命令).目前我的python构建没有广泛的字符支持UCS4,这限制了我的每个字符的分辨率.我还将最大范围限制在unicode保留范围0xD800的下端,但是一旦我构建了一个允许字符列表和一个避免它们的过滤器,理论上我可以将所需的字符数推低到70-100.上面的标志.
目前该方法的局限性在于输出大小不固定.它取决于矢量化后矢量节点/点的数量.自动化此限制将要求对图像进行像素化(这会消除向量的主要优点)或重复运行路径直到达到所需的节点数(我目前在Inkscape中手动执行).
版本2
更新:v2现在有资格参加比赛.变化:
命令行控制输入/输出和调试
使用XML解析器(lxml)来处理SVG而不是正则表达式
每个unicode符号包含2个路径段
文档和清理
支持样式="填充:颜色"和填充="颜色"
文档宽度/高度打包成单个字符
路径颜色打包成单个字符
通过每种颜色丢弃4位颜色数据然后通过十六进制转换将其打包成字符来实现颜色压缩.
人物:133
时间:几秒钟
v2解码http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded-v2.png编码和解码后(版本2)
如你所见,这次有一些文物.这不是方法的限制,而是我转换中的某个错误.当点超出范围0.0 - 127.0并且我试图限制它们的尝试取得了成功时,工件就会发生.解决方案只是缩小图像,但是我无法缩放实际点而不是画板或组矩阵,现在我太累了.简而言之,如果您的积分在支持的范围内,它通常会起作用.
我相信中间的扭结是由于手柄移动到它所连接的手柄的另一侧.基本上这些点在一开始就太靠近了.在压缩源图像之前对源图像运行简化过滤器应该解决这个问题并削减一些不必要的字符.
更新:此方法适用于简单对象,因此我需要一种简化复杂路径和降低噪音的方法.我使用Inkscape完成这项任务.我有幸运用Inkscape修饰不必要的路径,但没有时间尝试自动化它.我使用Inkscape'Simplify'函数制作了一些示例svgs来减少路径数量.
简化工作正常但是这条路径很慢.
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
跟踪缩略图http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_autotrace.png
这是一些超低分辨率的镜头.虽然也可能需要一些巧妙的路径压缩,但它们更接近140个字符的限制.
修饰http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_groomed.png 简化和去斑点.
trianglulated http://www.warriorhut.org/graphics/svg_to_unicode/competition_thumbnails_triangulated.png 简化,去斑和三角化.
autotrace --output-format svg --output-file cornell_box.svg --despeckle-level 20 --color-count 64 cornell_box.png
上图:使用autotrace的简化路径.
不幸的是我的解析器没有处理autotrace输出,所以我不知道可能有多少点正在使用或者有多远可以简化,遗憾的是在截止日期之前没有时间编写它.然而,它比inkscape输出更容易解析.
好吧,这是我的:nanocrunch.cpp和CMakeLists.txt文件,使用CMake构建它. 它依赖于Magick ++ ImageMagick API来处理大部分图像.它还需要GMP库用于其字符串编码的bignum算法.
我的解决方案基于分形图像压缩,有一些独特的扭曲.基本思想是拍摄图像,将副本缩小到50%,并查找与原始图像中非重叠块类似的各种方向的片段.这种搜索需要一种非常强力的方法,但这样可以更容易地引入我的修改.
第一个修改是,我的程序还考虑了45度方向,而不只是看90度旋转和翻转.每块只有一点,但它极大地帮助了图像质量.
另一方面,为每个块的每个颜色分量存储对比度/亮度调整太昂贵了.相反,我存储了一个重量化的颜色(调色板只有4*4*4 = 64种颜色),只是按比例混合.在数学上,这相当于每种颜色的可变亮度和恒定对比度调整.不幸的是,这也意味着翻转颜色没有负面对比.
一旦计算出每个块的位置,方向和颜色,它就会将其编码为UTF-8字符串.首先,它生成一个非常大的bignum来表示块表中的数据和图像大小.这种方法类似于Sam Hocevar的解决方案 - 一种大数字,其基数随位置而变化.
然后它将它转换为任何可用字符集大小的基数.默认情况下,它充分利用分配的unicode字符集,减去小于,大于,&符号,控制,组合,代理和私有字符.它不漂亮,但它的工作原理.您也可以注释掉默认表并选择可打印的7位ASCII(再次排除<,>和&字符)或CJK Unified Ideographs.可用的字符代码表存储在运行长度编码中,其中交替运行无效和有效字符.
无论如何,这里是一些图像和时间(在我的旧3.0GHz P4上测量),并在上面描述的完整分配的unicode集中压缩到140个字符.总的来说,我对它们的结果非常满意.如果我有更多的时间来处理这个问题,我可能会尝试减少解压缩图像的阻塞.不过,我认为结果非常适合极端压缩比.解压缩的图像有点印象派,但我发现相对容易看出位是如何与原始位置相对应的.
Stack Overflow徽标(8.6s进行编码,7.9s进行解码,485字节):
http://i44.tinypic.com/2w7lok1.png
Lena(32.8s编码,13.0s解码,477字节):
http ://i42.tinypic.com/2rr49wg.png http://i40.tinypic.com/2rhxxyu.png
蒙娜丽莎(编码43.2秒,解码14.5秒,490字节):
http ://i41.tinypic.com/ekgwp3.png http://i43.tinypic.com/ngsxep.png
编辑:CJK统一角色
Sam在评论中询问了如何与CJK一起使用.这是从CJK Unified字符集压缩到139个字符的Mona Lisa版本:
http://i43.tinypic.com/2yxgdfk.png 咏璘驞凄脒鵚据蛥鸂拗朐朖辿韩潴鱿歪痫栘璯緍脲蕜抱揎频蓼债鑡嗞靊寞柮嚛嚵籥聚隤慛絖铨馿渫櫰矍昀鰛掾撄粂敽牙粳擎蔍螎葙峬覧绌蹔抆惫冧筇哜搀沄芯譶辍浍垝黟偞媄童竽梀韠镰猳閺狌而膻喙伆杇婣唆鐤諽鷍鸮駫抢毤埙悖萜愿旖鞰萗勹鈱哳垬濅鬒秀瞛洆认気狋异闼籴珵仾氙熜謋繴茴晋髭杍嚖熥勋縿饼珝爸擸萿
我用于此程序顶部的调整参数是:19,19,4,4,3,10,11,1000,1000.我还注释了number_assigned和代码的第一个定义,并且未注释掉最后定义它们以选择CJK Unified字符集.
我的完整解决方案可以在 http://caca.zoy.org/wiki/img2twit.它具有以下功能:
合理的压缩时间(高质量约1分钟)
快速减压(几分之一秒)
保持原始图像大小(不仅仅是宽高比)
体面重建质量(恕我直言)
可以在运行时选择消息长度和字符集(ASCII,CJK,符号)
消息长度和字符集在解压缩时自动检测
非常有效的信息包装
http://caca.zoy.org/raw-attachment/wiki/img2twit/so-logo.png http://caca.zoy.org/raw-attachment/wiki/img2twit/twitter4.png
蜥秓鋖筷聝诿缰咱腶漷庯祩皙靊谪獜岨幻寤厎趆脘搇梄踥桻理戂溥欇渹里軱骿苸髙骟市簶璨粭浧鳖捕弫潮衍蚙瀹岚玧霫鏓蓕戏债鼶襋躻弯袮足庭侅旍凼飙驱据嘛掔倾诗籂阉嶹婻椿模墤渽緛赐更当棫武婩缣逡荨璙杯翉珸齸陁颗鳣悯掷舥攩寉鈶兓庭璱篂鰀干丕耓庁铼努樀肝亖弜喆蝞躐葌熲谎蛪曟暙刍镶媏嘝骕慸盂氤缰殾譑
以下是编码过程的概述:
可用位数由所需的消息长度和可用的字符集计算得出
源图像被分割成与可用位允许的一样多的方形单元
使用初始坐标和颜色值对每个单元格影响固定数量的点(当前为2)
重复以下步骤,直到满足质量条件:
随机选择一个点
在该点上随机执行操作(在其单元内移动,改变其颜色)
如果得到的图像(参见下面的解码过程)更接近源图像,则保持操作
图像大小和点列表以UTF-8编码
这是解码过程:
从UTF-8流中读取图像大小和点
对于目标图像中的每个像素:
计算自然邻域列表
像素的最终颜色设置为其自然邻居颜色的加权平均值
我认为该程序最原始的部分是比特流.stream <<= shift; stream |= value
我没有打包位对齐值(),而是打包不在两个幂范围内的任意值(stream *= range; stream += value
).这需要bignum计算,当然要慢得多,但是当使用20902个主要CJK字符时,它给了我2009.18位而不是1960位(这是我可以在数据中添加的三个点).当使用ASCII时,它给出了917.64位而不是840位.
我决定采用一种初始图像计算的方法,这种方法需要重型武器(角点检测,特征提取,颜色量化......),因为我一开始并不确定它真的有用.现在我意识到收敛很慢(1分钟是可以接受的,但它仍然很慢)我可能会尝试改进.
主拟合循环从直接二进制搜索抖动算法(其中像素被随机交换或翻转直到获得更好的半色调)中松散地启发.能量计算是一个简单的均方根距离,但我首先在原始图像上执行5x5中值滤波.高斯模糊可能更好地代表人眼行为,但我不想失去锋利的边缘.我还决定不使用模拟退火或其他难以调整的方法,因为我没有几个月的时间来校准过程.因此,"质量"标志仅表示在编码器结束之前对每个点执行的迭代次数.
http://caca.zoy.org/raw-attachment/wiki/img2twit/Mona_Lisa_scaled.jpg http://caca.zoy.org/raw-attachment/wiki/img2twit/twitter2.png
苉憗揣嶕繠剳腏篮湿茝霮墧蒆棌杚蓳缚樟赒肴飗当砃燋任朓峂釰雳陴貜犟掝喗讄荛砙矺敨鷾璎亨髎芟氲簵鸬嫤铰俇激躙怃邺甮槺骳佛愚猪駪惾嫥綖珏矫坼堭颽箽赭飉讷偁钳窂蹻熛漧众橼愀航玴毡裋頢羔恺墎嬔鑹楄瑥鹣呍蕖抲鹂秓苾绒酯嵞脔婺污啰酼俵菛琪棺则辩曚鸸职铦蒝礭鱚蟺稿纡醾陴鳣尥蟀惘铝髚忩祤脤养趯沅况
即使并非所有图像都能很好地压缩,我对结果感到惊讶,我真的很想知道还有哪些方法可以将图像压缩到250个字节.
我也有编码器状态从随机初始状态和"良好"初始状态演变的小电影.
编辑:这是压缩方法与JPEG比较的方式.在左边,jamos是536字节以上的图片.在右边,Mona Lisa使用此处描述的方法压缩到534字节(此处提到的字节指的是数据字节,因此忽略使用Unicode字符浪费的位):
http://caca.zoy.org/raw-attachment/wiki/img2twit/minimona.jpg http://caca.zoy.org/raw-attachment/wiki/img2twit/minimona2.png
编辑:刚刚用最新版本的图像替换了CJK文本.
以下不是正式提交,因为我的软件没有以任何方式为指定的任务量身定制. DLI可以被描述为优化通用有损图像编解码器.它是用于图像压缩的PSNR和MS-SSIM记录保持器,我认为看看它如何针对这个特定任务执行会很有趣.我使用提供的参考Mona Lisa图像并将其缩小到100x150然后使用DLI将其压缩到344字节.
蒙娜丽莎DLI http://i40.tinypic.com/2md5q4m.png
为了与JPEG和IMG2TWIT压缩样本进行比较,我使用DLI将图像压缩为534字节.JPEG为536字节,IMG2TWIT为534字节.图像已按比例放大至大致相同的尺寸,以便于比较.JPEG是左图像,IMG2TWIT是中心,DLI是右图像.
比较http://i42.tinypic.com/302yjdg.png
DLI图像设法保留一些面部特征,最着名的是着名的微笑:).
我的解决方案的一般概述是:
我首先计算可以容纳140个utf8字符的最大原始数据量.
(我假设utf8,这是原始网站声称twitter存储它的消息.这不同于上面的问题陈述,它要求utf16.)
使用这个utf8 faq,我计算出你可以在一个utf8字符中编码的最大位数是31位.为此,我将使用U-04000000-U-7FFFFFFF范围内的所有字符.(1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx,有31 x,因此我可以编码最多31位).
31位乘以140个字符等于4340位.将其除以8得到524.5,然后将其舍入为542字节.
(如果我们将自己限制为utf16,那么我们每个字符只能存储2个字节,这相当于280个字节).
使用标准jpg压缩缩小图像.
将图像大小调整为大约50x50px,然后尝试以各种压缩级别压缩它,直到您有一个尽可能接近542字节的图像而不会过去.
这是 mona lisa压缩到536字节的一个例子.
将压缩图像的原始位编码为utf-8字符.
将以下字节中的每个x替换为:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx,以及图像中的位.
这部分可能是需要编写大部分代码的部分,因为目前没有任何代码可以执行此操作.
我知道你要求代码,但我真的不想花时间来实际编写代码.我认为有效的设计可能至少会激励其他人对其进行编码.
我认为我提出的解决方案的主要好处是它正在尽可能多地重用现有技术.尝试编写一个好的压缩算法可能很有趣,但确保有更好的算法,很可能是由拥有更高数学学位的人编写的.
另一个重要的注意事项是,如果确定utf16是首选编码,那么这个解决方案就会崩溃.压缩到280字节时,jpegs不能正常工作.虽然,对于这个特定的问题陈述,可能有比jpg更好的压缩算法.
好吧,我已经迟到了,但不过我做了我的项目.
这是一种玩具遗传算法,它使用半透明的彩色圆圈来重建初始图像.
特征:
纯净的Lua.运行Lua解释器运行的任何地方.
使用netpbm P3格式
附带一套全面的单元测试
保留原始图像大小
误的feautres:
慢
在该空间限制下,它仅保留初始图像的基本颜色方案和其几个特征的一般轮廓.
下面是代表莉娜为例TWIT:犭杨谷杌蒝螦界匘玏扝匮俄归晃客猘摈硰划刀萕码扛斢嘁蜁嚎耂澹簜偾砠偑婊内团揕忈义倨裆凁梡岂掂戆耔攋斘眐奡萛狂昸箆亲嬎廙栃兡塅受橯恰应戞优猫僘莹吱赜卣朸杈腠綍蝘猕屐称悡诟来噩压罍尕熚帤厥虤嫐虲兙罨縨炘排叁抠堃从弅慌螎熰标宑箫柢橙拃丨蜊缩昔傥舭励癳冂囤璟彔榕兠摈侑蒖孂埮槃姠璐哠眛嫡琠枀訜苄暬厇廪焛瀻严啘刱垫仔
该代码位于bitbucket.org的Mercurial存储库中.退房http://bitbucket.org/tkadlubo/circles.lua
以下是我解决问题的方法,我必须承认这是一个非常有趣的项目,它绝对超出了我的正常工作范围,并且给了我一些新的东西可供学习.
我背后的基本思想如下:
对图像进行灰度下采样,使得总共有16种不同的阴影
在图像上预成型RLE
将结果打包为UTF-16字符
在打包结果上预先形成RLE以删除任何重复的字符
事实证明,这确实有效,但只能在有限的范围内,您可以从下面的示例图像中看到.在输出方面,接下来是一个示例推文,特别是样本中显示的Lena图像.
乤乤万乐唂伂倂倁企侬2企倁3企倁2企伂8企伂3企伂5企倂倃伂倁3企俊企2伂倃5企倁3企倃4企倂企倁企伂2企伂5企倁企伂쥹皗鞟鐾륶䦽阹럆䧜椿籫릹韧욶옷뎷歩㰷歉䴗鑹㞳鞷㬼獴鏙돗鍴祳㭾뤶殒焻乹Ꮛ叇䍼
正如你所看到的,我确实尝试过限制字符集; 但是,在存储图像颜色数据时,我遇到了这样的问题.此外,该编码方案还倾向于浪费可用于附加图像信息的一堆数据.
就运行时而言,对于小图像,代码非常快,对于提供的样本图像大约55ms,但是随着图像变大,时间确实增加.对于512x512 Lena参考图像,运行时间为1182ms.我应该注意,代码本身并没有针对性能进行非常优化(例如,所有内容都作为Bitmap使用)的可能性非常大,所以在重构之后时间可能会有所下降.
请随时向我提供有关我可以做得更好或代码可能出错的建议.可以在以下位置找到运行时和样本输出的完整列表:http://code-zen.info/twitterimage/
更新一
我已经更新了压缩推文字符串时使用的RLE代码以进行基本回顾,如果是这样,那么将其用于输出.这仅适用于数值对,但它确实保存了几个字符的数据.运行时间或多或少与图像质量相同,但推文往往略小.我将在完成测试时更新网站上的图表.以下是一个示例推文字符串,同样适用于小版本的Lena:
乤乤万乐唂伂倂倁企侬2企倁3企倁ウ伂8企伂エ伂5企倂倃伂倁グ俊企2伂倃ガ倁ジ倃4企倂企倁企伂ツ伂ス倁企伂쥹皗鞟鐾륶䦽阹럆䧜椿籫릹韧욶옷뎷歩㰷歉䴗鑹㞳鞷㬼獴鏙돗鍴祳㭾뤶殒焻乹Ꮛ叇䍼
更新二
另一个小更新,但我修改了代码将颜色阴影打包成三个一组而不是四个,这使用了一些更多的空间,但除非我遗漏了一些东西,否则它应该意味着"奇数"字符不再出现在颜色的地方数据是.此外,我更新了压缩,因此它现在可以作用于整个字符串,而不仅仅是颜色计数块.我还在测试运行时间,但它们似乎在名义上得到改善; 但是,图像质量仍然相同.以下是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 蒙娜丽莎http://code-zen.info/twitterimage/images/mona-lisa.bmp
Roger Alsing编写的这种遗传算法具有良好的压缩比,但代价是压缩时间长.可以使用有损或无损算法进一步压缩所得到的顶点矢量.
http://rogeralsing.com/2008/12/07/genetic-programming-evolution-of-mona-lisa/
将是一个有趣的计划实施,但我会错过.
在原始挑战中,大小限制被定义为如果您将文本粘贴到文本框中并按"更新",Twitter仍允许您发送的内容.有些人正确地注意到这与您从移动设备发送的短信息不同.
没有明确提到的(但我的个人规则是)你应该能够在浏览器中选择推文消息,将其复制到剪贴板并将其粘贴到解码器的文本输入字段中,以便显示它.当然,您也可以自由地将消息保存为文本文件并将其读回或编写一个访问Twitter API的工具,并过滤掉任何看起来像图像代码的消息(特殊标记是谁?wink wink).但规则是,在允许解码之前,消息必须通过Twitter.
祝你好运350字节 - 我怀疑你能否利用它们.
发布单色或灰度图像应该可以改善可以编码到该空间中的图像的大小,因为您不关心颜色.
可能会增加上传三张图像的挑战,这些图像在重新组合时会为您提供全彩色图像,同时仍然在每个单独的图像中保持单色版本.
添加一些压缩到上面,它可能开始看起来可行...
尼斯!现在你们激起了我的兴趣.一天剩下的时间里都不会做任何工作......
关于此挑战的编码/解码部分. base16b.org是我尝试指定一种标准方法,用于在更高的Unicode平面中安全有效地编码二进制数据.
一些功能:
仅使用Unicode的私有用户区
每个字符最多可编码17位; 效率几乎是Base64的三倍
提供了编码/解码的参考Javascript实现
包括一些示例编码,包括Twitter和Wordpress
对不起,这个答案对于原始比赛来说太晚了.我独立于这篇文章开始了这个项目,我在其中发现了一半.
存储一堆参考图像的想法很有趣.如果存储25Mb的样本图像并让编码器尝试用这些图像组成图像,那会不会错?有了这么小的管道,两端的机器必然会比通过的数据量大得多,那么25Mb的代码和1Mb的代码和24Mb的图像数据之间有什么区别呢?
(注意原始指南排除了限制图书馆中已有图像的输入 - 我不是这么说的).
愚蠢的想法,但sha1(my_image)
会导致任何图像的"完美"表示(忽略碰撞).显而易见的问题是解码过程需要过多的暴力破解.
1位单色将更容易..每个像素变为1或0,因此对于100*100像素图像,您将拥有1000位数据.由于SHA1散列是41个字符,我们可以将三个合为一个消息,只需要暴力破解2组3333位和一组3334(尽管即使这可能仍然是过度的)
这不太准确.即使使用固定长度的1位100*100px图像,也有..,假设我没有错误计算,49995000组合,或16661667分成三个.
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
这种压缩很好.
http://www.intuac.com/userport/john/apt/
http://img86.imageshack.us/img86/4169/imagey.jpg http://img86.imageshack.us/img86/4169/imagey.jpg
我使用了以下批处理文件:
capt mona-lisa-large.pnm out.cc 20 dapt out.cc image.pnm Pause
生成的文件大小为559个字节.