答案 0 :(得分:288)
image files and python source(第1版和第2版)
版本1 这是我的第一次尝试。我会随时更新。
我的SO标识低至300个字符几乎无损。我的技术使用转换为SVG矢量艺术,因此它在线条艺术上效果最佳。它实际上是一个SVG压缩器,它仍然需要原始艺术经历矢量化阶段。
对于我的第一次尝试,我使用了online service作为PNG跟踪,但有许多免费和非免费工具可以处理此部分,包括potrace(开源)。
以下是结果
Original SO Logo http://www.warriorhut.org/graphics/svg_to_unicode/so-logo.png原文 Decoded SO Logo 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现在有资格参赛。变化:
字符: 133
时间:几秒钟
v2 decoded http://www.warriorhut.org/graphics/svg_to_unicode/so-logo-decoded-v2.png编码和解码后(版本2)
正如你所看到的,这次有一些文物。这不是方法的限制,而是我转换中的某个错误。当点超出范围0.0 - 127.0并且我试图约束它们的尝试取得了成功时,工件就会发生。解决方案只是缩小图像,但是我无法缩放实际点而不是画板或组矩阵,现在我太累了。简而言之,如果您的积分在支持的范围内,它通常会起作用。
我认为中间的扭结是由于手柄移动到与其相连的手柄的另一侧。基本上这些点在一开始就太靠近了。在压缩源图像之前对源图像运行简化过滤器应该可以解决这个问题并削减一些不必要的字符。
<强>更新强>: 这种方法适用于简单的对象,因此我需要一种简化复杂路径和降低噪声的方法。我使用Inkscape执行此任务。我有幸运用Inkscape修饰不必要的路径,但没有时间尝试自动化它。我使用Inkscape'Simplify'函数制作了一些示例svgs来减少路径数。
简化工作正常,但这条路可能很慢。
autotrace example 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
这是一些超低分辨率的镜头。虽然也可能需要一些巧妙的路径压缩,但这些更接近140个字符的限制。
groomed 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
ABOVE:使用autotrace的简化路径。
不幸的是我的解析器没有处理autotrace输出,所以我不知道有多少点正在使用或者要简化多远,遗憾的是在截止日期之前没有时间写它。但是,它比inkscape输出更容易解析。
答案 1 :(得分:244)
好的,这是我的nanocrunch.cpp和CMakeLists.txt文件,使用CMake.来构建它。它依赖于Magick++ ImageMagick API进行大部分图像处理。对于字符串编码,它还需要GMP库进行bignum算法。
我的解决方案基于分形图像压缩,有一些独特的曲折。基本思想是拍摄图像,将副本缩小到50%,并查找与原始图像中非重叠块类似的各种方向的片段。这种搜索需要非常强力的方法,但这样可以更容易地引入我的修改。
第一个修改是,我的程序不仅仅考虑90度旋转和翻转,而是考虑45度方向。它是每块一个位,但它极大地帮助了图像质量。
另一个原因是为每个块的每个颜色分量存储对比度/亮度调整太昂贵了。相反,我存储了一个重量化的颜色(调色板只有4 * 4 * 4 = 64种颜色),只是按比例混合。在数学上,这相当于每种颜色的可变亮度和恒定对比度调整。不幸的是,这也意味着翻转颜色没有负面对比。
一旦计算出每个块的位置,方向和颜色,它就会将其编码为UTF-8字符串。首先,它生成一个非常大的bignum来表示块表中的数据和图像大小。这种方法类似于Sam Hocevar的解决方案 - 一种大数字,其基数随位置而变化。
然后它将其转换为任何可用字符集大小的基础。默认情况下,它充分利用分配的unicode字符集,减去小于,大于,&符号,控制,组合,代理和私有字符。它不漂亮,但它的工作原理。您还可以注释掉默认表格并选择可打印的7位ASCII(再次排除&lt;,&gt;和&amp;字符)或CJK Unified Ideographs。可用的字符代码表存储在运行长度编码中,交替运行无效和有效字符。
无论如何,这里有一些图像和时间(在旧的3.0GHz P4上测量),并在上面描述的完整分配的unicode集中压缩为140个字符。总的来说,我对它们的结果非常满意。如果我有更多的时间来处理这个问题,我可能会尝试减少解压缩图像的阻塞。不过,我认为结果非常适合极端压缩比。解压缩的图像是有点印象派的,但我发现相对容易看出位是如何对应于原始的。
Stack Overflow Logo(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一起使用这个问题。这是Mona Lisa的一个版本,压缩到CJK Unified字符集中的139个字符:
http://i43.tinypic.com/2yxgdfk.png 咏璘驞凄脒鵚据蛥鸂拗朐朖辿韩潴鱿歪痫栘璯緍脲蕜抱揎频蓼债鑡嗞靊寞柮嚛嚵籥聚隤慛絖铨馿渫櫰矍昀鰛掾撄粂敽牙粳擎蔍螎葙峬覧绌蹔抆惫冧筇哜搀沄芯譶辍浍垝黟偞媄童竽梀韠镰猳閺狌而膻喙伆杇婣唆鐤諽鷍鸮駫抢毤埙悖萜愿旖鞰萗勹鈱哳垬濅鬒秀瞛洆认気狋异闼籴珵仾氙熜謋繴茴晋髭杍嚖熥勋縿饼珝爸擸萿
我用于此程序顶部的调整参数是:19,19,4,4,3,10,11,1000,1000。我还注释了number_assigned和codes的第一个定义,以及取消注释掉它们的最后定义以选择CJK Unified字符集。
答案 2 :(得分:199)
我的完整解决方案可以在 http://caca.zoy.org/wiki/img2twit找到。它具有以下特点:
http://caca.zoy.org/raw-attachment/wiki/img2twit/so-logo.png http://caca.zoy.org/raw-attachment/wiki/img2twit/twitter4.png
蜥秓鋖筷聝诿缰咱腶漷庯祩皙靊谪獜岨幻寤厎趆脘搇梄踥桻理戂溥欇渹里軱骿苸髙骟市簶璨粭浧鳖捕弫潮衍蚙瀹岚玧霫鏓蓕戏债鼶襋躻弯袮足庭侅旍凼飙驱据嘛掔倾诗籂阉嶹婻椿模墤渽緛赐更当棫武婩缣逡荨璙杯翉珸齸陁颗鳣悯掷舥攩寉鈶兓庭璱篂鰀干丕耓庁铼努樀肝亖弜喆蝞躐葌熲谎蛪曟暙刍镶媏嘝骕慸盂氤缰殾譑
以下是编码过程的概述:
这是解码过程:
我认为该计划最原始的部分是比特流。我没有打包位对齐值(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个字节。
我也有编码器状态演变from a random initial state和from a "good" initial state的小电影。
编辑:以下是压缩方法与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文字。
答案 3 :(得分:45)
以下内容并非正式提交,因为我的软件尚未以任何方式针对指定的任务进行定制。 DLI可以被描述为优化通用有损图像编解码器。它是用于图像压缩的PSNR和MS-SSIM记录保持器,我认为看看它如何针对这个特定任务执行会很有趣。我使用提供的参考Mona Lisa图像并将其缩小到100x150然后使用DLI将其压缩到344字节。
Mona Lisa DLI http://i40.tinypic.com/2md5q4m.png
为了与JPEG和IMG2TWIT压缩样本进行比较,我使用DLI将图像压缩为534字节。 JPEG为536字节,IMG2TWIT为534字节。图像已按比例放大至大致相同的尺寸,以便于比较。 JPEG是左图像,IMG2TWIT是中心,DLI是右图像。
Comparison http://i42.tinypic.com/302yjdg.png
DLI图像设法保留一些面部特征,最着名的是着名的微笑:)。
答案 4 :(得分:21)
我的解决方案的一般概述是:
我知道您要求代码,但我真的不想花时间实际编写代码。我认为有效的设计至少可以激励其他人对其进行编码。
我认为我提出的解决方案的主要好处是它正在重用尽可能多的现有技术。尝试编写一个好的压缩算法可能会很有趣,但保证会有一个更好的算法,很可能是由具有更高数学学位的人编写的。
另一个重要的注意事项是,如果确定utf16是首选编码,那么这个解决方案就会崩溃。压缩到280字节时,jpegs不能正常工作。虽然,对于这个特定的问题陈述,可能有比jpg更好的压缩算法。
答案 5 :(得分:20)
好的,我已经迟到了,但不过我做了我的项目。
这是一种玩具遗传算法,它使用半透明的彩色圆圈来重建初始图像。
特点:
误的feautres:
以下是代表Lena的示例: 犭杨谷杌蒝螦界匘玏扝匮俄归晃客猘摈硰划刀萕码扛斢嘁蜁嚎耂澹簜偾砠偑婊内团揕忈义倨裆凁梡岂掂戆耔攋斘眐奡萛狂昸箆亲嬎廙栃兡塅受橯恰应戞优猫僘莹吱赜卣朸杈腠綍蝘猕屐称悡诟来噩压罍尕熚帤厥虤嫐虲兙罨縨炘排叁抠堃从弅慌螎熰标宑箫柢橙拃丨蜊缩昔傥舭励癳冂囤璟彔榕兠摈侑蒖孂埮槃姠璐哠眛嫡琠枀訜苄暬厇廪焛瀻严啘刱垫仔
代码位于bitbucket.org的Mercurial存储库中。查看http://bitbucket.org/tkadlubo/circles.lua
答案 6 :(得分:19)
以下是我解决问题的方法,我必须承认这是一个非常有趣的项目,它绝对超出了我的正常工作范围,并给了我一些新的东西可供学习。
我背后的基本理念如下:
事实证明这确实有效,但只能在有限的范围内,您可以从下面的示例图片中看到。在输出方面,接下来是一个示例推文,特别是样本中显示的Lena图像。
乤乤万乐唂伂倂倁企侬2企倁3企倁2企伂8企伂3企伂5企倂倃伂倁3企俊企2伂倃5企倁3企倃4企倂企倁企伂2企伂5企倁企伂쥹皗鞟鐾륶䦽阹럆䧜椿籫릹韧욶옷뎷歩㰷歉䴗鑹㞳鞷㬼獴鏙돗鍴祳㭾뤶殒焻乹Ꮛ叇䍼< / p>
正如你所看到的,我确实尝试过限制字符集;但是,在存储图像颜色数据时,我遇到了这样的问题。此外,这种编码方案也倾向于浪费一堆可用于附加图像信息的数据。
就运行时间而言,对于小图像,代码非常快,对于提供的样本图像大约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 Mona Lisa http://code-zen.info/twitterimage/images/mona-lisa.bmp
答案 7 :(得分:15)
Roger Alsing编写的这种遗传算法具有良好的压缩比,但代价是压缩时间长。得到的顶点矢量可以使用有损或无损算法进一步压缩。
http://rogeralsing.com/2008/12/07/genetic-programming-evolution-of-mona-lisa/
这将是一个有趣的计划,但我会错过。
答案 8 :(得分:12)
在原始挑战中,如果您将文本粘贴到文本框中并按“更新”,则大小限制将定义为Twitter仍然允许您发送的内容。正如有些人正确地注意到这与您从移动设备发送的短信息不同。
未明确提及(但我的个人规则是)您应该能够在浏览器中选择推文消息,将其复制到剪贴板并将其粘贴到解码器的文本输入字段中,以便它可以显示它。当然,您也可以将消息保存为文本文件并将其读回或编写一个访问Twitter API的工具,并过滤掉任何看起来像图像代码的消息(任何人都可以使用特殊标记? wink wink )。但规则是,在允许解码之前,消息必须经过Twitter。
祝你好运350字节 - 我怀疑你能否使用它们。
答案 9 :(得分:12)
发布单色或灰度图像应该可以改善可以编码到该空间中的图像的大小,因为您不关心颜色。
可能会增加上传三张图片的挑战,这些图片在重新组合时会为您提供全彩色图像,同时在每张单独的图像中保持单色版本。
在上面添加一些压缩,它可以开始看起来可行......
尼斯!!!现在你们激起了我的兴趣。在一天的剩余时间里不会做任何工作......
答案 10 :(得分:9)
关于此挑战的编码/解码部分。 base16b.org是我尝试指定一种标准方法,用于在更高的Unicode平面中安全有效地编码二进制数据。
一些功能:
对不起,这个答案对于原来的比赛来说太迟了。我独立于这篇文章开始了这个项目,我在其中发现了它。
答案 11 :(得分:8)
存储一堆参考图像的想法很有趣。如果存储25Mb的样本图像并让编码器尝试用这些图像组成图像,那会不会错?有了这么小的管道,两端的机器必然会比通过的数据量大得多,那么25Mb的代码和1Mb的代码和24Mb的图像数据之间有什么区别呢?
(请注意原始指南排除了限制库中已有图像的输入 - 我不建议这样做。)
答案 12 :(得分:8)
愚蠢的想法,但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
答案 13 :(得分:8)
这里压缩很好。
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字节。
答案 14 :(得分:0)
想法:你能用字体作为调色板吗?尝试在一系列向量中打破图像,试图用向量集的组合来描述它们(每个字符本质上是一组向量)。这是使用字体作为字典。例如,我可以使用l表示垂直线,使用 - 表示水平线?只是一个想法。