【问题标题】:Generate an image from arbitrary strings从任意字符串生成图像
【发布时间】:2014-12-25 10:45:07
【问题描述】:

我见过很多图像到 ascii 艺术转换器,但我需要的是更复杂一点。我需要能够使用一组预定义的任意长度的字符串作为我的马赛克图块,而不是从 ascii 字符创建的马赛克图像。

我已经做了很多谷歌搜索,但我什至不确定如何构建我的查询?这样的事情存在吗?如果它不会在其图像生成中使用重复项,则会获得奖励。

【问题讨论】:

    标签: javascript image-processing dynamic-image-generation


    【解决方案1】:

    并不真正适合 Stack Overflow,但仍然是一个有趣的项目。所以我尝试了一下,看看我能走多远。

    我认为归结为:

    1. 计算一组 ASCII 字符的灰度值;
    2. 计算每个字符串的“最佳拟合”;
    3. 重复 2. 直到完成。

    我不认为“没有重复”是可行的,除非你有非常小的图像和大量的候选字符串。这就是我想出的,使用我的头像和我当前的徽章作为字符串列表。 (我排除了我的“c”徽章;不知何故,我的程序认为这是“最适合”大补丁的,这不是很吸引人。注意:不要包含 1 个字符的字符串。)

    QuorumQuorumAutobiographerQuorumQuorumQuorumJongwareQuorumQuorumQuorumQuorumQuor
    umQuorumQuorumAutobiographerQuorumQuorumSupporterQuorumQuorumProofreaderQuorumQu
    orumQuorumAutobiographerQuorumQuorumQuorumQuorumQuorumQuorumAutobiographerQuorum
    QuorumQuorumAutobiographerQuorumQuorumQuorumQuorumQuorumQuorumAutobiographerQuor
    umQuorumQuorumAutobiographerQuorumQuorumQuorumAutobiographerQuorumMortarboardQuo
    rumQuorumAutobiographerQuorumQuorumQuorumQuorumAutobiographerQuorumMortarboardQu
    orumQuorumAutobiographerQuorumQuorumQuorumQuorumJongwareQuorumQuorumCommentatorQ
    uorumQuorumAutobiographerQuorumQuorumQuorumQuorumQuorumQuorumQuorumAutobiographe
    rQuorumQuorumAutobiographerQuorumQuorumProofreaderJongwareQuorumQuorumQuorumQuor
    umQuorumQuorumMortarboardJongwareQuorumProofreaderCommentatorSuffrageQuorumQuoru
    mQuorumQuorumJongwareQuorumAutobiographerSuffrageCommentatorCaucusCriticCleanupQ
    uorumQuorumMortarboardAutobiographerCommentatorQuorumConstituentCriticCriticQuor
    umQuorumQuorumQuorumAutobiographerJongwareCleanupSupporterInvestorCriticCleanupQ
    uorumQuorumQuorumQuorumAutobiographerFanaticCleanupFanaticInvestorCriticCleanupQ
    uorumQuorumQuorumQuorumAutobiographerCriticInformedSupporterCriticCriticInformed
    QuorumQuorumQuorumQuorumAutobiographerCriticQuorumSupporterInvestorFanaticQuorum
    QuorumQuorumQuorumQuorumAutobiographerCriticCleanupCommentatorQuorumDeputyQuorum
    QuorumQuorumQuorumQuorumAutobiographerCriticInvestorCaucusInformedDeputyQuorumQu
    orumQuorumQuorumQuorumQuorumCommentatorCriticCriticCitizen PatrolQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumAutobiographerCriticCriticCitizen PatrolQuorumQuorumQ
    uorumQuorumQuorumQuorumQuorumAutobiographerCriticCriticCitizen PatrolStewardQuor
    umQuorumQuorumQuorumQuorumAutobiographerConstituentCitizen PatrolCaucusQuorumQuo
    rumQuorumQuorumQuorumQuorumAutobiographerInvestorCriticConstituentQuorumQuorumQu
    orumQuorumQuorumQuorumQuorumCommentatorConstituentCleanupCaucusCleanupQuorumQuor
    umQuorumQuorumQuorumQuorumAutobiographerInvestorCleanupSupporterInformedQuorumQu
    orumQuorumQuorumAutobiographerCommentatorCriticInformedJongwareJongwareQuorumQuo
    rumQuorumQuorumAutobiographerCommentatorCriticInvestorJongwareJongwareQuorumQuor
    umQuorumQuorumAutobiographerFanaticInvestorCriticInformedCleanupQuorumQuorumQuor
    umQuorumQuorumQuorumDeputySupporterInvestorConstituentCaucusQuorumQuorumQuorumQu
    orumQuorumQuorumAutobiographerCriticInvestorCriticSupporterQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumAutobiographerInvestorInvestorCleanupQuorumQuorumQuorumQuor
    umQuorumQuorumQuorumQuorumCommentatorInvestorInvestorQuorumQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumCommentatorInvestorInvestorQuorumQuorumQuorumQuorumQu
    orumQuorumQuorumQuorumQuorumCommentatorInvestorCleanupStewardQuorumQuorumQuorumQ
    uorumQuorumQuorumQuorumQuorumCommentatorInvestorJongwareQuorumQuorumQuorumQuorum
    QuorumQuorumQuorumQuorumQuorumAutobiographerCleanupQuorumQuorumQuorumQuorumQuoru
    mQuorumQuorumQuorumQuorumQuorumAutobiographerSuffrageQuorumQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumQuorumAutobiographerDeputyQuorumQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumQuorumQuorumAutobiographerQuorumQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuoru
    

    你必须眯起眼睛;在小尺寸下,它看起来像这样:

    这是我创建它的方式。

    第 1 步:找到合适的图像;

    第二步:转为灰度;

    第 3 步:将灰色转换为极端。此步骤是为了确保输入范围(灰度值)使用 0 到 255 的全范围。

    第 4 步:调整图像大小以获得最佳拟合。我选择了 80x40,并故意将图像压缩了一半。这是因为“文本”通常高于其宽度。不同的字体需要不同的纵横比! 80 是每行的字符数,40 是总行数。

    我在上述步骤中使用了 Photoshop,只是因为我不想为它编写 代码。只要您可以访问原始图像数据,这并不难或其他什么,但它需要大量工作并且并不有趣。

    中间步骤,放大 400% 以便看到像素:

    第 5 步:给自己找一个等宽位图字体。我在“网络”的某个地方找到了一个不错的 8x8。也许更大的尺寸可能效果更好,但只是很小,因为限制因素是你的字符串,而不是字体。

    第 6 步:计算每个 ASCII 字符的“灰色”值。这是黑色像素的数量除以像素的总数。为了更好地传播,我将每个字符的结果除以找到的最大值,所以最小值是0(用于空格),最大值是1(恰好是M,但这取决于字体)。然后我将这些值乘以 255,因此它模拟了灰度值。最后,由于这些值与灰度图像中的值相反,我将它们替换为255-value

    在此期间,我进行了大量测试,以确保我最初的想法仍然合理。这是我的测试图像的转储,使用普通的灰色到字符转换:

    0MMMMMM00000000000RDRRDDDDDDDDDDDDDDR#@RRRRR#00000RRR@RRRRR@RR@RRRRD&44&#00#0000
    MMMMMM000000000000RDRDDDDDDDDDDDDDDDR0####0R&&&&&&DR@RRR@#########RRDDD4@0000000
    MMM000#00000000000RDRRDDDDDDDDDDD&&&R00#000@&DR@####RR@#0000000##0#RD4PP&R@00000
    M000#0000000000000RDDDDDDDDDDD&D&&D&R###0000@#0000#@@##@@@@@##000000R&2FPP4R#000
    00###0000000000000RDDDDDDDDDDDDDD&&&D0000#@##@##00##@RDD&DRRRR#00000@R4FFP4PD@00
    00#000000000000000RDDDDDDDDDD&D&D&&&DRRRRDR@@@##00#R&4&44DDDRRR#0000##R&FPP4PRR@
    00##00#00000000000RDDDDDDDDDDD&&&&&&RDRRRRRRRR##@@RR&F4&RDDRR@@#0000000#&44&&4FD
    000000000000000000DDDDDDD&&&DD&&&D&&R##@RRRRRRRRRRRRD&DRD&44DD&RR@#00000RDDRR4F4
    000000000000000000RDDDDDDDRRDRDDD&DR@###@R&4&4444PP4DRRR&P22FF2FP&DRRRRRRRR@R4FD
    000000000000000000RRRRRRR@00@@R&&DRRRRRR@&P2$33*33*4RRRDP23$*33$$**333*$$2D#@4DR
    000000000000000000RRRRRRR@0000#DDRRRRRD&D4*$$%%ff3F&DRRR2$1%$$%11ff%ll1l;'IRDF&R
    000000000000000000RRR@#0#00000R4444DRRRR&3llf33$32PDRR&3Ii(i%fIlI1Il!ii/' .FF4DR
    0000000#0000000000#@@#0MM0M00#RP22*24DR4$l!!!I%*P4DDP31i===/lf1Illi((ii=;..*F4RR
    000000000000000000#@@##0M00000@F*$%*2PFflilllI1f3*2PF3fIi/=(lf$fIi/======;iF&P4R
    000000000000000000##@##00000000&3f$2F2*1i!ll1$2P4RD&4P*$$%!ii!I!ii/=/=;;;(*&R4FR
    000000000000000000#####00000000D%I3$$fflil!l1$3%3&RD2PP*$%1ll!lI1%f$3fI="1RRRRDR
    000000000000000000#####00000000Rf1f%II1IIl!l!!1%ff$*FFFF*%((lf**F4&D&PPFf2RRRRRR
    00000000000000000M#####0000000003!i11II11l!!!(ilIIl1f$f%I="=1FP4&@#R&DP22&RRR@#@
    0000000000000000000###0000000000#$i/iIIIl!!i=;"";===;""""";i12FFP4&4*4&*FRRRR@@R
    000000000000000000M000000000000000R4FF1l!i(=;"''"""""'...';/i$3$f$$33$$$4DRRRRRR
    000000000000000000000000000M00000000@21l(/ii/=;;=ilI;"'...'=;I%11f$$$ffP@@RR@R#0
    000000000000000000000000000M00000000&11!=/li(i!I%%Ii;... .";"!I!!I1ff$*R0#@#0000
    000000000000000000000000M0000M000000$lli=//=/i!lIi/l%I/""=//'=Iiiil%f$PR@#@00000
    000000000000000000000000M0M0M00000MRl!!!/=;;/l%fl!lI%3233$ff%11II%%f*2PP@##00000
    00000000000000000M000000M0MM00000003=illl!!iI%11%%f%f$32FF22$1%ff$f2DD4PR0000000
    00000000000000000M00M0#RRRRRRRRRRRPi/(lllI1I(=;=iI$2222FPFFP*$fff%FRR2322&R00000
    00000000000000000MM00#RRD&&&&&444*l/(i!ll!i!==/(il%$33*2FFF23$ff*4DDDF33*22&0000
    0000000000000000000000@R@@@@@#&f!((/i!!!lI!i=;;/!l1f32*3$$$ff$2&RR@###@##00##000
    0000000000000000#RRRR@@4F4R0R3!////(iii!!l%Ii=;"=l%f$333$ff%$4############00000#
    0000000000000000000000#@@@#0Di/ii(=/(i!!!lI%%1!(iI%$**$$fffF@0000000000000000000
    00000000000000000000000000000R3l((/((ii!lll!I%$3$f$$$$$3$f20M0000000000000000000
    000000000000000000000000000000#2l///((!!l!!i!!1%f%f$3$f%%fR000000000000000000000
    00000000000000#00000000000000000&l//(i!llllII1%%%1I1ff1I1&000000000000000000#00#
    M00000000000000000000000000000000R3l!!llII111%%%%%%f$$f%2000000000000000000RR00#
    0000#000000000000000000000000000000R*%1II111%%ffff$33fffR000000000000000000##00#
    0####000000000000000000000000000000M0RF3ff$$$fff$$33$ff&00000000000#000000##000R
    #00000000#00000000000000000000000000000R4FFFF22*****3fF00000000000000000000000@&
    00###000000000000000000000000000000000000@RRDD&&&4P*34#00000000000000000000000#R
    00000####000000000000000000000000000000000000##@RRDDR00000000000000M0000000000##
    00000000#000000000000000000000000000000000000000000000000000000000000000000000##
    

    这类似于您的平均图像到 ASCII 艺术转换器的输出。

    第 7 步:找到要使用的字符串列表。

    第 8 步:从左上角开始,针对图像测试每个字符串的覆盖率。打印出最合适的,将位置增加这个字符串的长度,重复直到完成。 (如果您不希望重复,请在此时从池中删除字符串。)

    第 9 步:盈利!


    对于覆盖率测试,我使用每个字符/像素的 (source - dest)² 总和除以字符串的长度:lower = better -- 字符串和目标之间的最小差异。

    我在这里没有考虑漂亮的行尾。如果一个单词恰好填满一行,我尝试给予负奖励,但输出差异很小。它可能仍然适用于更大的字符串集。

    一个可能的改进是测试字符串的序列,也就是说,使用动态编程方法代替这里的贪婪方法,就像 Donald Knuth 设计的决定自动换行文本中的最佳中断.

    【讨论】:

    • 感谢您的回复。不幸的是,我正在进行的项目被废弃了。这是一本很棒的书,我将把它归档在我的记忆库中,希望我能在以后的某个地方尝试一下。
    猜你喜欢
    • 2015-04-30
    • 1970-01-01
    • 2010-10-11
    • 2018-06-23
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多