Twitter图像编码挑战[关闭]


597

如果一张图片的价值为1000字,那么您可以用140个字符容纳多少张图片?

注意:就是这样!赏金的截止日期已经到了,经过一番艰苦的考虑之后,我认为Boojum的入场机会刚好超出Sam Hocevar的入场机会。一旦有机会将它们写下来,我将发布更详细的注释。当然,每个人都应随时继续提交解决方案并改进解决方案以供人们投票。感谢所有提交和输入的人;我都喜欢。对我来说,这很有趣,我希望对参赛者和观众来说都很有趣。

我遇到了一篇有关尝试将图像压缩到Twitter评论中的有趣文章,并且该线程(以及Reddit上的一个线程)中的很多人都提出了有关您可以采用的不同方法的建议。因此,我认为这将是一个很好的编码挑战;让人们把钱花在嘴上,并展示他们的编码思想如何在有限的可用空间内带来更多细节。

我挑战您提出一个通用系统,该系统可将图像编码为140个字符的Twitter消息,然后再次将其解码为图像。您可以使用Unicode字符,因此每个字符可获得8位以上的字符。但是,即使允许使用Unicode字符,您也需要将图像压缩到很小的空间中。这肯定是有损压缩,因此必须对每个结果的外观有主观判断。

这是原始作者Quasimondo从他的编码中获得的结果(图像已获得知识共享署名-非商业许可): 蒙娜丽莎

你能做得更好吗?

规则

  1. 您的程序必须具有两种模式:编码解码
  2. 编码
    1. 您的程序必须以您选择的任何合理的栅格图形格式输入图形。我们将说ImageMagick支持的任何栅格格式都算合理。
    2. 您的程序必须输出一条消息,该消息可以用140个或更少的Unicode代码点表示。在范围140个的代码点U+0000- U+10FFFF,排除非字符(U+FFFEU+FFFFU+ÑFFFEU+ÑFFFF其中Ñ1- 10十六进制和范围U+FDD0- U+FDEF)和替代代码点(U+D800- U+DFFF)。它可能以您选择的任何合理编码输出;GNUiconv支持的任何编码都将被认为是合理的,并且您的平台本机编码或语言环境编码将是一个不错的选择。有关更多详细信息,请参见下面的Unicode注释
  3. 解码
    1. 您的程序应将编码模式的输出作为输入。
    2. 您的程序必须以您选择的任何合理格式输出图像,如上所述,尽管对于输出矢量格式也可以。
    3. 图像输出应该是输入图像的近似值;您离输入图像越近越好。
    4. 除了上面指定的输出,解码过程可能无法访问编码过程的任何其他输出;也就是说,您无法将图像上传到某处并输出URL以供解码过程下载,或者诸如此类的愚蠢行为。
  4. 为了保持用户界面的一致性,您的程序必须具有以下行为:

    1. 您的程序必须是可以在具有适当解释器的平台上设置为可执行文件的脚本,或者是可以编译为可执行文件的程序。
    2. 您的程序必须将第一个参数设为encodedecode设置模式。
    3. 您的程序必须以下列一种或多种方式进行输入(如果实现一种采用文件名的方式,则如果缺少文件名,则也可以从stdin和stdout进行读取和写入):

      1. 从标准输入中获取输入,并在标准输出中生成输出。

        my-program encode <input.png >output.txt
        my-program decode <output.txt >output.png
        
      2. 从第二个参数中命名的文件中获取输入,并在第三个参数中命名的文件中产生输出。

        my-program encode input.png output.txt
        my-program decode output.txt output.png
        
  5. 为您的解决方案,请发布:
    1. 您的代码完整和/或托管在其他地方的链接(如果它很长,或者需要编译许多文件等)。
    2. 如果它在代码中不是立即显而易见的,或者代码很长,人们可能会对摘要感兴趣,请对其进行解释。
    3. 带有原始图像,压缩后的文本和解码图像的示例图像。
    4. 如果您是基于其他人的想法,请归因于他们。可以尝试完善其他人的想法,但是您必须将其归因于。

指导方针

这些基本上是可能被打破的规则,建议或评分标准:

  1. 美学很重要。我将根据以下内容进行判断,并建议其他人进行判断:
    1. 输出图像看起来有多好,看起来像原始图像多少。
    2. 文字看起来不错。如果您有一个非常聪明的压缩方案,则完全随机的gobbledigook可以,但是我还想看到将图像转换为多语言诗歌或类似之类的答案。请注意,原始解决方案的作者决定只使用汉字,因为那样看起来更好。
    3. 有趣的代码和聪明的算法总是好的。我喜欢简短,清晰的代码,但是真正聪明的复杂算法也可以,只要它们能产生良好的结果。
  2. 速度也很重要,尽管不如一项工作对图像的压缩效果那么重要。我宁愿有一个可以在十分之一秒的时间内转换图像的程序,而不是可以连续几天运行遗传算法的程序。
  3. 我会更喜欢较短的解决方案,而不是较长的解决方案,只要它们在质量上具有可比性即可。简洁是一种美德。
  4. 您的程序应使用在Mac OS X,Linux或Windows上可以免费使用的语言来实现。我希望能够运行这些程序,但是如果您有一个仅在MATLAB或其他条件下运行的出色解决方案,那很好。
  5. 您的程序应尽可能通用。它应该适用于尽可能多的不同图像,尽管某些图像可能比其他图像产生更好的结果。特别是:
    1. 在程序中内置一些与之匹配并写入引用的图像,然后在解码时生成匹配图像,这是相当la脚的,将仅覆盖一些图像。
    2. 可以拍摄简单,平坦,几何形状的图像并将其分解为某些矢量基元的程序非常漂亮,但是如果它在超过一定复杂度的图像上失败,则可能不够通用。
    3. 只能拍摄特定固定长宽比的图像但效果很好的程序也可以,但并不理想。
    4. 您可能会发现,与彩色图像相比,黑白图像可以在较小的空间中获取更多信息。另一方面,这可能会限制其适用的图像类型;黑白效果很好,但是抽象的设计可能效果不佳。
    5. 如果输出图像小于输入图像,并且比例大致相同,则完全可以。如果必须放大图像以将其与原始图像进行比较,可以。重要的是外观。
  6. 您的程序应产生实际上可以通过Twitter发出且毫发无损的输出。这只是一个准则,而不是一条规则,因为我找不到支持的精确字符集的任何文档,但是您应该避免使用控制字符,时髦的不可见组合字符,专用字符等。

评分标准

作为有关如何选择接受的解决方案时如何对解决方案进行排名的一般指南,可以说我可能会以25分制来评估解决方案(这很粗糙,我不会直接得分,仅使用这是基本准则):

  • 编码方案可以很好地再现各种输入图像的15分。这是一个主观的审美判断
    • 0表示它根本不起作用,每次都返回相同的图像,或类似的东西
    • 5表示它可以对一些图像进行编码,尽管解码后的版本看起来很难看,而且在更复杂的图像上可能根本不起作用
    • 10表示它可处理各种图像,并产生令人愉悦的图像,有时可能会与众不同
    • 15表示它可以生成某些图像的完美副本,甚至对于更大,更复杂的图像,也可以识别出某些内容。或者,也许它不能产生可识别的图像,但是会产生清晰可见于原始图像的精美图像。
  • 巧妙使用Unicode字符集需要 3分
    • 简单使用整个允许的字符集即可获得0分
    • 使用有限的字符集可以安全地通过Twitter或在各种情况下传输的1分
    • 使用主题字符子集(例如仅汉文字或仅从右到左字符)获得2分
    • 做真正整洁的事情(如生成可读文本或使用看起来像所讨论图像的字符)要3分
  • 聪明的算法方法和代码风格获得 3分
    • 0点代表1000行代码,仅用于缩小图像,将其视为每个像素1位,然后base64对其进行编码
    • 对于使用标准编码技术并且写得很好且简短的内容,要获得1分
    • 引入相对新颖的编码技术的东西,或者令人惊讶的短而干净的东西,只需2分
    • 对于实际上能产生良好结果或在图形编码中取得新突破的衬里,要获得3分(如果这似乎不足以突破新点,请记住,这种良好的结果在美学上可能会获得高分以及
  • 2分的速度。在所有其他条件相同的情况下,速度越快越好,但是上述标准比速度更重要
  • 在自由(开源)软件上运行可获得1分,因为我更喜欢自由软件(请注意,只要C#在Mono上运行,C#仍然有资格获得此积分,同样,如果在GNU Octave上运行,MATLAB代码也将具有资格)
  • 实际遵守所有规则可得1分。这些规则变得有些复杂,因此我可能会接受否则会给出一个小细节错误的好的答案,但我将对实际上遵循所有规则的任何解决方案给予额外的加分

参考图片

有些人要求提供一些参考图像。以下是一些您可以尝试的参考图片;较小的版本嵌入在此处,如果需要,它们都链接到图像的较大版本:

莉娜 蒙娜丽莎 康奈尔盒子 StackOverflow徽标

根据上述标准,我将为我最喜欢的解决方案提供500代表奖金(加上StackOverflow投入的50 奖励)。当然,我也鼓励其他人在这里对自己喜欢的解决方案进行投票。

注意截止日期

这项比赛将一直持续到赏金用完为止,即5月30日(星期六)下午6点左右。可能是下午5点到晚上7点。我将保证我将查看下午2点之前提交的所有条目,并且会尽力查看下午4点之前提交的所有条目;如果在此之后提交解决方案,那么在我必须做出决定之前,我可能没有机会给他们一个公平的外观。另外,您提交的越早,您投票的机会就越多,能够帮助我选择最佳解决方案,因此,请尽早提交,而不是在截止日期之前提交。

Unicode注释

关于允许使用哪些Unicode字符,也存在一些困惑。可能的Unicode代码点范围U+0000U+10FFFF。有些代码点在任何公开的数据交换中都永远无法用作Unicode字符;这些是非字符替代代码点。Noncharacters在所定义的Unidode标准5.1.0节16.7作为值U+FFFEU+FFFFU+ÑFFFEU+ÑFFFF其中Ñ1- 10十六进制和范围U+FDD0-U+FDEF。这些值旨在用于特定于应用程序的内部使用,并且合格的应用程序可能会从这些字符所处理的文本中删除这些字符。替代代码点(在Unicode标准5.1.0第3.8节中定义为U+D800U+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)可能会更容易。
  • 您可以使用现有的图像库(例如ImageMagickPython Imaging Library)进行图像处理。
  • 如果您需要帮助来理解Unicode字符集及其各种编码,请参阅此快速指南有关Linux和Unix中UTF-8的详细FAQ
  • 您越早获得解决方案,我(和其他投票者)就会花更多的时间研究它。如果您改进解决方案,则可以对其进行编辑;当我最后浏览解决方案时,我将以最新版本为基础。
  • 如果您想解析和编写简单的图像格式(并且不想只使用现有格式),建议您使用PPM格式。这是一种基于文本的格式,非常易于使用,您可以使用ImageMagick来回转换。

随意就我在评论中写下的规则提出建议;如果人们感到需要澄清或过于规范,我当然愿意对其进行调整。
布莱恩·坎贝尔

6
您可能应该说,将图像上传到服务器并将URL发布到它是无效的。
Shay Erlichmen,2009年

2
@Shay我不是已经说过吗?“解码过程可能无法访问编码过程的除上述指定输出以外的任何其他输出;也就是说,您无法将图像上传到某处并输出URL以供解码过程下载,或者类似的愚蠢行为”。
布赖恩·坎贝尔

1
@Konrad Rudolph我同意;从实际的角度来看,我并不是说“傻”(显然,从实际的角度来看,整个比赛都是愚蠢的),在这次比赛中,我的意思是“愚蠢”。从信息论的角度来看,使用URI并不是真正的压缩算法,因为它不允许您仅使用备用通道就无法传输更多信息。您可以为编码器和解码器提供一个大型的图像数据库,并将其称为压缩功能,该压缩功能仅适用于有限的一组图像,但我指定您需要能够处理任意图像。
布莱恩·坎贝尔

2
以下是我遇到的一些链接可能会对人们有所帮助:azillionmonkeys.com/qed/unicode.html,以解释Unicode字符的有效范围。请注意,UTF编码是可以编码整个Unicode范围的编码。UCS-4是Unicode的超集,而UCS-2和ASCII是子集。在压缩方面,这是一种与原始帖子类似的技术,尽管他允许自己使用1k而不是350字节:screamingduck.com/Article.php?
Brian Campbell,2009年

Answers:


244

好吧,这是我的:nanocrunch.cppCMakeLists.txt文件,使用CMake进行构建 它的大多数图像处理都依赖于Magick ++ ImageMagick API。它还需要GMP库对字符串进行大数运算。

我的解决方案基于分形图像压缩,但有一些独特之处。基本思想是拍摄图像,将副本缩小到50%,然后寻找与原始图像中的非重叠块相似的各种方向的片段。此搜索采用非常蛮力的方法,但这使引入我的修改更加容易。

第一个修改是,我的程序不仅考虑90度旋转和翻转,还考虑了45度方向。每块多一位,但是它极大地提高了图像质量。

另一件事是,为每个块的每个颜色分量存储对比度/亮度调整过于昂贵。相反,我存储了高度量化的颜色(调色板只有4 * 4 * 4 = 64种颜色),只是按一定比例进行混合。从数学上讲,这等效于每种颜色的可变亮度和恒定对比度调整。不幸的是,这也意味着没有任何反差来翻转颜色。

一旦计算出每个块的位置,方向和颜色,它就会将其编码为UTF-8字符串。首先,它生成一个很大的bignum来表示块表中的数据和图像大小。此方法类似于Sam Hocevar的解决方案-大量基数随位置而变化。

然后,它将其转换为任何可用字符集大小的基础。默认情况下,它充分利用分配的unicode字符集,减去,小于,大于,与号,控制,组合以及代理和私有字符。它不是很漂亮,但是可以。您也可以注释掉默认表并选择可打印的7位ASCII码(同样不包括<,>和&字符)或CJK Unified Ideographs。可用的字符代码表存储了一个行程长度,该行程以无效字符和有效字符交替运行进行编码。

无论如何,这是一些图像和时间(以我的旧版3.0GHz P4测得),并按上述完整分配的unicode集压缩为140个字符。总体而言,我对它们的结果感到非常满意。如果我有更多时间来处理此问题,则可能会尝试减少解压缩图像的块状性。不过,我认为对于极端压缩率而言,结果还是不错的。解压缩后的图像有点印象派,但是我发现比较容易看出位与原始图像的对应关系。

堆栈溢出徽标(编码为8.6s,解码为7.9s,485字节):http ://i44.tinypic.com/2w7lok1.png

Lena(编码32.8秒,解码13.0秒,477字节):
http ://i42.tinypic.com/2rr49wg.png http://i40.tinypic.com/2rhxxyu.png

蒙娜丽莎(43.2s编码,14.5s解码,490字节):
http ://i41.tinypic.com/ekgwp3.png http://i43.tinypic.com/ngsxep.png

编辑:中日韩统一字符

Sam在有关将其与CJK一起使用的评论中询问。这是从CJK Unified字符集中压缩为139个字符的蒙娜丽莎版本:

http://i43.tinypic.com/2yxgdfk.png 咏璘驞凄脒鵚据蛥鸂拗朐朖辿韩潴鱿歪歪栘璯緍养栘璯緍抱揎频蓼债鑡嗞靊孤独柮嚛嚵籥聚隤慛絖铨馿渫櫰矍昀鰛掾撄粂敽牙先前擎蔍螎葙峬覧绌蹔抆平均冧筇哜搀沄芯譶辍浍垝黟偞媄童竽梀韠镰猳閺狌而膻喙伆杇婣唆鐤諽鷍鸮駫抢毤埙悖悖愿愿旖鞰萗勹鈱哳垬濅鬒秀瞛洆认瞛洆异闼籴珵仾自杀熜謋繴茴香晋升杍嚖熥勋杍嚖熥饼珝爸擸萿

我在程序顶部使用的调整参数是:19、19、4、4、3、10、11、1000、1000。我还注释了number_assigned和code的第一个定义,并且未注释掉它们的最后定义选择CJK Unified字符集。


哇!不错的工作。我对这种小图像的分形图像压缩表示怀疑,但实际上确实产生了不错的结果。它也很容易编译和运行。
布赖恩·坎贝尔

1
谢谢你们!Sam,您的意思是仅140个CJK字符的结果吗?如果是这样,那么是的,您需要调整顶部的数字。最终的位大小约为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,2009年

编辑:在我遗漏的第一个log2()中有一个* 16。那是为了可能的方向。
Boojum,2009年

20
有人用这个推特吗?
DBR

288

图像文件和python源(版本1和2)

版本1 这是我的第一次尝试。我会随时更新。

我已经将SO徽标降至300个字符,几乎无损。我的技术使用到SVG矢量艺术的转换,因此在艺术线条上效果最佳。它实际上是SVG压缩机,它仍然需要原始艺术经历矢量化阶段。

我第一次尝试使用在线服务进行PNG跟踪,但是有许多免费和非免费工具可以处理此部分,包括Potrace(开源)。

这是结果

原来如此标志http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png原始 解码,从而标志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)代替regex处理SVG
  • 每个unicode符号打包2个路径段
  • 文档和清理
  • 支持style =“ fill:color”和fill =“ color”
  • 文档宽度/高度打包成单个字符
  • 路径颜色打包成单个字符
  • 通过丢弃每种颜色4位颜色数据,然后通过十六进制转换将其打包为字符,可以实现颜色压缩。

字数133

时间:几秒钟

v2解码http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded-v2.png编码和解码后(版本2)

如您所见,这次有一些工件。这不是方法的限制,而是我转换中的某个错误。当这些点超出0.0-127.0的范围时,就会发生伪影,而我对其进行约束的尝试却取得了不同的成功。解决方案只是将图像按比例缩小,但是我很难按比例缩放实际点,而不是按比例画板或组矩阵,现在我太累了,无法照顾。简而言之,如果您的观点在支持范围内,则通常可以使用。

我相信中间的扭结是由于手柄移动到与其链接的手柄的另一侧。基本上,这些点首先太靠近。在压缩源图像之前对其运行简化过滤器应该可以解决此问题,并剃除一些不必要的字符。

更新:此方法适用于简单对象,因此我需要一种简化复杂路径并减少噪音的方法。我将Inkscape用于此任务。使用Inkscape整理不必要的路径时,我有些运气,但没有时间尝试使其自动化。我使用Inkscape的“简化”功能制作了一些示例svg,以减少路径数量。

简化工作还可以,但是使用这么多路径可能会很慢。

自动跟踪例如http://www.warriorhut.org/graphics/svg_to_unicode/autotrace_16_color_manual_reduction.png 康奈尔框http://www.warriorhut.com/graphics/svg_to_unicode/cornell_box_simplified.png 海伦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 简化和去斑点。

三角化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的简化路径。

不幸的是,我的解析器无法处理自动跟踪输出,因此我不知道可能使用的点数或可简化的程度,可悲的是,在截止日期之前几乎没有时间来编写它。但是,它比inkscape输出更容易解析。


2
优秀的!最初,我想创建一个既具有尖锐边缘又具有光滑区域的混合矢量解决方案,但是事实证明,如果不使用跟踪库(我不想使用它),该方法太复杂了。我期待看到您的方法能达到多大的效果!
sam hocevar,09年

真好!我希望我们能看到一些通过矢量化进行接近无损方法的尝试。这意味着它的通用性较低,但所覆盖图像的质量较高。可以使用在线服务进行矢量化。祝您好运!
布赖恩·坎贝尔

我将图像压缩和字符编码视为两个不同的步骤-Sam的技术似乎是编码的最佳选择,可以轻松地构建到独立程序中。通过专注于解决方案的独特部分(即压缩部分)并仅输出一串比特,您将获得更多收益。
Mark Ransom

70
哇。这些图像看起来非常时尚。
Rinat Abdullin 09年

199

我的完整解决方案可以在以下位置找到 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我没有打包按位对齐的值(),而是打包了不在2的幂范围内的任意值(stream *= range; stream += value)。这需要大数运算,并且速度当然要慢很多,但是使用20902个主要CJK字符时,它提供的是2009.18位而不是1960位(这是我可以在数据中加上的三点)。而当使用ASCII时,它给了我917.64位而不是840位。

我决定反对一种需要大量武器(角落检测,特征提取,颜色量化...)的初始图像计算方法,因为我不确定一开始它是否真的会有所帮助。现在,我意识到收敛很慢(可以接受1分钟,但仍然很慢),我可以尝试对此进行改进。

主要的拟合环从Direct Binary Seach抖动算法(其中像素被随机交换或翻转直到获得更好的半色调)松散地得到启发。能量计算是一个简单的均方根距离,但我首先对原始图像执行了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比较的方式。左边是jamoes的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文本。


我实际上并不需要能够运行代码(我建议将运行代码的部分放在建议中,而不是规则中)。我希望能够运行它,但是我将根据生成的图像的质量,代码以及任何有趣的技巧或算法来进行更多的判断。如果我要运行它,并且它需要我没有或不想在主系统上安装的软件包,则可以启动Amazon EC2实例并安装它。只要您使用的是为主要发行版之一打包的库,我就应该能够运行它。随时使用CGAL。
布赖恩·坎贝尔

2
好的,这是我的解决方案(源代码):caca.zoy.org/browser/libpipi/trunk/examples/img2twit.cpp 我的解释尝试和一些示例在caca.zoy.org/wiki/img2twit
sam hocevar

2
我真的很喜欢您的解决方案。您应该尝试减少分配给蓝色通道的值的数量,因为人眼无法很好地分辨蓝色:nfggames.com/games/ntsc/visual.shtm ; 这将使您获得更多细节,但会丢失一些颜色信息。还是将其分配为绿色?
rpetrich

5
好点子。我确实尝试过这种想法的一些变体(请参阅RANGE_X定义之前的注释),但不是很彻底。如您所见,使用5个蓝色值而不是6个值会增加错误,而使用7个绿色值会减少该错误。我不是出于懒惰而尝试这样做。我遇到的另一个问题是我没有很好的错误功能。我目前使用∑(∆r² + ∆g² + ∆b²)/ 3,效果很好。我尝试了∑(0.299∆r² + 0.587∆g² + 0.114∆b²),但基于物理量没有YUV的Y分量,但是它对蓝色误差的容忍度很高。我将尝试查找有关此问题的论文。
sam hocevar,09年

2
@rpetrich:我修改了程序以使它能够动态增加r / g / b范围,只要有足够的可用位。这样可以确保我们在整个位流中不会浪费超过13位(但实际上通常是1或2)。并且图像看起来更好。
sam hocevar,2009年

45

以下内容不是正式提交的内容,因为我的软件尚未针对指定任务进行任何定制。 DLI可描述为优化的通用有损图像编解码器。它是用于图像压缩的PSNR和MS-SSIM记录保持器,我认为看到它如何执行此特定任务将很有趣。我使用提供的参考《蒙娜丽莎》图像并将其缩放到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图像设法保留了一些面部特征,最著名的是微笑:)。


6
哎呀。以上应归功于最初提交它的Dennis Lee。我只是对其进行编辑以将图像嵌入到行中,并链接到我通过Googling找到的参考。我必须说,哇,压缩给我留下了深刻的印象。我将不得不检查DLI压缩。
布赖恩·坎贝尔

1
顺便说一下,DLI作者提到了“很长的处理时间”。由于我无法运行他的软件,您能给我们大概的压缩时间吗?
sam hocevar,09年

1
使用AMD Athlon64 2.4Ghz,压缩100x150蒙娜丽莎图像的时间为38秒,解压缩时间为6秒。压缩到最大251个字节更加困难,输出质量显着降低。使用参考的《蒙娜丽莎》图像,我将其缩放为60x91,然后使用DLI将其压缩为243个字节(最接近251个字节,而没有进行遍历)。这是输出i43.tinypic.com/2196m4g.png即使比特率仅降低了约50%,细节也不接近534字节DLI。但是,图像的结构保持得很好。

1
决定简化比较250字节压缩样本的过程。243字节的DLI被放大并放置在IMG2TWIT样本旁边。左侧为IMG2TWIT,右侧为DLI。这是图片i40.tinypic.com/30ndks6.png

1
DLI使用JPEG之类的质量参数,因此如果需要目标输出大小,则需要反复试验。

21

我的解决方案的一般概述是:

  1. 我首先计算可以容纳140个utf8字符的最大原始数据量。
    • (我假设是utf8,这是原始网站声称twitter将其消息存储在其中的内容。这与上面的问题声明所要求的utf16不同。)
    • 使用此utf8常见问题解答,我计算出可以在单个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个字节)。
  2. 使用标准jpg压缩将图像压缩。
    • 将图像的大小调整为大约50x50像素,然后尝试以各种压缩级别对其进行压缩,直到获得的图像尽可能接近542字节而不会翻阅。
    • 这是压缩为536字节的mona lisa 的示例
  3. 将压缩图像的原始位编码为utf-8字符。
    • 用以下图像中的位替换以下字节中的每个x:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx。
    • 这部分可能是需要编写大部分代码的部分,因为当前不存在执行此操作的任何内容。

我知道您在要求代码,但是我真的不想花时间来实际编写代码。我认为有效的设计至少可以激发其他人对此进行编码。

我认为我提出的解决方案的主要好处在于,它正在重用尽可能多的现有技术。尝试编写一个好的压缩算法可能很有趣,但是可以保证那里有一个更好的算法,最有可能是由具有较高数学学位的人编写的。

不过,还有一个重要的注意事项是,如果确定utf16是首选编码,则此解决方案将分崩离析。压缩到280个字节时jpeg并不真正起作用。尽管对于这种特定的问题陈述,也许有比jpg更好的压缩算法。


我现在正在上班,但是我回家后一定会实施该解决方案。
Paulo Santos,2009年

2
根据我的实验,似乎UTF-16确实是Twitter计算字符的方式。BMP字符计数为1,高平面字符计数为2。未记录,但这是当您在输入框中键入内容时其JavaScript字符计数器的计数方式。原始线程的注释中也提到了它。我没有尝试通过API提交以查看计数器是否损坏;如果是这样,我将针对实际约束更新问题。但是,您不可能使用任意UTF-8,因为您可以编码的许多较长序列都不是有效的Unicode。
布赖恩·坎贝尔

4
经过对其API的测试后,事实证明它们的确按Unicode字符(代码点)计数,而不是按UTF-16代码单位计数(这是通过UTF-16计数的JavaScript字符计数器,因为显然,这是JavaScript长度方法的作用) 。这样您可以在那里获得更多信息。有效的Unicode字符在U + 0000到U + 10FFFF的范围内(每个字符多于20位;每个字符2 ^ 20 + 2 ^ 16个可能的值)。UTF-8允许多于允许在Unicode的详细值的编码,因此,如果您限制自己的Unicode,就可以了,没有542获得约350个字节的空间
布赖恩·坎贝尔

3
鉴于极端压缩,这536字节的mona lisa看起来非常好!
克里斯,2009年

3
我们目前可以对129,775个不同的(分配的,非控制的,非私有的)Unicode字符进行编码。如果我们将自己限制为该子集,则总共为2377位,即297个字节。代码在这里:porg.es/blog/what-c​​an-we-fit-in-140-characters
porges

20

好的,我迟到了,但是尽管如此,我还是完成了我的项目。

这是一种玩具遗传算法,它使用半透明的彩色圆圈重新创建初始图像。

特征:

  • 纯粹的Lua。在Lua解释器运行的任何地方运行。
  • 使用netpbm P3格式
  • 带有一整套的单元测试
  • 保留原始图像尺寸

错误的功能:

  • 在这种空间限制下,它仅保留初始图像的基本配色方案及其少量特征的总体轮廓。

这是代表莉娜(Lena)的一个例子:岂掂戆耔攋斘眐奡萛狂昸箆亲嬎廙栃兡塅受橯恰应戞优猫僘莹吱赜卣朸破碎赜卣朸猕屐称悡诟来可怕压罍尕熚帤厥虤嫐虲兙罨縨炘排叁抠堃从弅慌螎熰标宑箫柢橙拃丨蜊缩昔傥舭励癳冂囤璟彔榕兠摈侑蒖孂埮槃姠璐哠眛嫡琠枀訜奔驰哠眛嫡琠枀訜厇廪焛瀻严啘刱垫仔

原始的莉娜 编码的莉娜

该代码位于bitbucket.org的Mercurial存储库中。查看http://bitbucket.org/tkadlubo/circles.lua


2
太棒了!创造整洁,美观的图像。我很高兴人们还在为此工作。看到所有不同的方法充满了乐趣。
布莱恩·坎贝尔

1
我希望看到它像在原件上的透明覆盖物一样使用,并提供散景效果。
尼克·拉德福德

19

以下是我解决问题的方法,我必须承认,这是一个非常有趣的项目,肯定超出了我的正常工作范围,并且给了我一些新的知识。

我背后的基本思想如下:

  1. 对图像灰度进行下采样,以便共有16种不同的阴影
  2. 在图像上执行RLE
  3. 将结果打包为UTF-16字符
  4. 在打包结果上执行RLE,以消除所有重复字符

事实证明,这确实有效,但仅在有限的范围内,如您从下面的示例图像中看到的那样。在输出方面,接下来是样本鸣叫,专门针对样本中显示的Lena图像。

唂伂倂倁万乐唂伂倂倁企侬2企倁3企倁2企伂8企伂3企伂5企倂倃伂倁3企俊企2伂倃5企倁3企倃4企倂企倁企伂2企伂5企倁企伂쥹皗鞟鐾륶䦽阹럆䧜椿籫릹韧욶옷뎷歩㰷悔䴗鑹㞳鞷㬼獴鏙돗鍴祳㭾뤶殒焻

如您所见,我确实尝试过限制字符集。但是,在存储图像颜色数据时,这样做会遇到问题。同样,这种编码方案也倾向于浪费一堆数据,这些数据可用于附加的图像信息。

就运行时间而言,对于小图像,代码非常快,对于所提供的示例图像,该代码约为55毫秒,但是对于大图像,时间确实会增加。对于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徽标http://code-zen.info/twitterimage/images/stackoverflow-logo.bmp 康奈尔盒子http://code-zen.info/twitterimage/images/cornell-box.bmp 莉娜http:// code-zen .info / twitterimage / images / lena.bmp 蒙娜丽莎http://code-zen.info/twitterimage/images/mona-lisa.bmp


1
太好了,谢谢您的参与!尽管Lena有点难以辨认,但是灰度对于其中的大多数实际上效果很好。我一直在寻找您的来源,但得到了404。你能确定它在那里吗?
布赖恩·坎贝尔

现在仔细检查一下,我正在更新站点,因此您可能在两次更新之间就被我吸引住了。
rjzii

是的,我现在可以下载它。当然,现在我需要弄清楚是否可以让Mono进行编译。
布赖恩·坎贝尔

是的 在Mono下工作,我使用“ gmcs -r System.Drawing TwitterImage.cs Program.cs”进行编译,并使用“ mono TwitterImage.exe编码lena.png lena.txt”运行
Brian Campbell,2009年

凉!我做了仔细检查,以确保列出了我正在使用的库,但是我实际上还没有使用过Mono,所以我不确定是否可以。
rjzii


12

在最初的挑战中,将大小限制定义为:如果将文本粘贴到其文本框中并按“更新”,Twitter仍然可以发送给您。正如某些人正确注意到的那样,这与您从手机以短信形式发送的内容有所不同。

没有明确提及(但我个人的规则是),您应该能够在浏览器中选择推文,然后将其复制到剪贴板并将其粘贴到解码器的文本输入字段中,以便可以显示它。当然,您也可以将消息另存为文本文件,然后再读回去,或者编写一个工具来访问Twitter API并过滤掉任何看起来像图像代码的消息(特殊标记是所有人吗?眨眼 眨眼)。但是规则是,必须先通过Twitter传递消息,然后才能对消息进行解码。

350字节祝您好运-我怀疑您将能够利用它们。


1
是的,我添加了一个评分标准,该评分标准表示对字符集的更严格限制是优选的,但不是必需的。我想制定一条规则,要求毫不费力地通过Twitter传递消息,但这需要大量的尝试和错误才能弄清有效方法的确切细节,并且我想留出一些余地以允许创造性地使用该消息。代码空间。因此,我的挑战中唯一的要求是140个有效的Unicode字符。顺便说一句,谢谢您的光临!我真的很喜欢您的解决方案,并且想看看是否有任何改进者可以真正改善它。
布赖恩·坎贝尔

12

发布单色或灰度图像应该会改善可以编码到该空间中的图像大小,因为您无需担心颜色。

上载三张图像可能会增加挑战,这些图像重新组合后将为您提供全彩色图像,同时在每个单独的图像中仍保持单色版本。

在上面添加一些压缩,它可能会开始看起来可行...

很好!!! 现在你们激起了我的兴趣。一天的其余时间将不做任何工作。


9
s /
peak

1
我喜欢三张图片的想法,应该有可能将这样的想法应用于Twitter,结果将是非常不错的。
Makis

9

关于此挑战的编码/解码部分。 base16b.org是我尝试指定一种标准方法,用于在较高的Unicode平面中安全有效地编码二进制数据。

一些功能:

  • 仅使用Unicode的专用用户区域
  • 每个字符最多可编码17位;效率是Base64的三倍
  • 提供了编码/解码的参考Javascript实现
  • 包括一些示例编码,包括Twitter和Wordpress

抱歉,这个答案来不及进行原始竞赛。我独立于这篇文章开始了这个项目,而我发现它已经过了一半。


8

存储一堆参考图像的想法很有趣。存储说25Mb的样本图像,并让编码器尝试使用其中的一些比特合成图像,是否会如此错误?使用这样的微型管道,两端的机器必然要比通过的数据量大得多,那么25Mb的代码,1Mb的代码和24Mb的图像数据之间有什么区别?

(请注意,原始准则已排除将输入限制为库中已有的图像-我不建议这样做)。


1
只要两个端点上的数据量都是固定的,就可以了。当然,您需要证明它适用于不在训练集中的图像,就像任何统计自然语言处理问题一样。我希望看到一些采用统计方法进行图像编码的东西。
布赖恩·坎贝尔

16
我希望看到蒙娜丽莎只使用Boba Fett粉丝艺术来重做。
诺斯雷德纳

我同意-光马赛克方法似乎在规则之内,而且看到某人刺中它将会非常有趣。
2009年

8

愚蠢的想法,但sha1(my_image)会导致任何图像的“完美”表示(忽略碰撞)。明显的问题是解码过程需要大量的暴力破解。

1位单色将更容易一些。每个像素变为1或0,因此对于100 * 100像素的图像,您将具有1000位的数据。由于SHA1哈希是41个字符,因此我们可以在一条消息中容纳3个字符,只需要强行强制使用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

10
sha1(my_image)的问题在于,如果您花时间蛮横地强迫它,那么在找到真实图像之前,您可能会发现很多碰撞。当然,强行强制sha1在计算上几乎是不可行的。
布赖恩·坎贝尔

5
甚至比SHA1压缩更好:我的“ flickr”压缩算法!步骤1:将图片上传到flickr。步骤2:在Twitter上发布指向其的链接。塔达!仅使用15个字节!
niXar

2
niXar:否,规则3.4:“解码过程可能无法访问编码过程的任何其他输出,而上述输出除外;也就是说,您无法将图像上传到某处并将解码过程的URL输出到下载或类似的愚蠢内容。”
dbr

6
我知道,我很讽刺。
niXar


0

想法:您可以将字体用作调色板吗?尝试以一系列向量来破坏图像,尝试使用向量集的组合来描述它们(每个字符本质上是向量集)。这是使用字体作为字典。例如,我可以将al用于垂直线,将-用于水平线?只是一个主意。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.