有很多用字符表示动作、表情的例子,比如
——————/´ ¯/)
—————--/—-/
—————-/—-/
———--/´¯/'--'/´¯`·_
———-/'/--/—-/—--/¨¯
——--('(———- ¯~/'--')
———————-'—--/
———-''————_-·´
———————--(
————-———--
用代码实现起来很简单。
比如首先用画图画一个歪瓜裂枣的心形,然后掏出油漆桶上色。
然后保存,假设文件名是"kkr.png"。
把这张图转换成字符的一种思路如下:
首先读入图片转换为灰度图,然后根据灰度在相应位置选取合适的字符替换(记得换行),最后把总的字符集输出或者写入文件。
但是还有一些细节上的问题。比如图片的尺寸。一个1080*1080的图片难道每行1080个字符吗?这样肯定屏幕上放不下,看起来效果非常差。首先想到的一种解决方法就是缩放,常见的图像库肯定提供这个功能。当然,也有其他思路。比如在神经网络里处理图像时,面对图像信息过多的问题是,使用了卷积神经网络,这里同样可以选用恰当的卷积核进行卷积、池化操作。不过这样其实和缩放差不多(缩放还能更容易保证不失真)。
比如python代码实现:
from PIL import Image
fp=open('kkr.png','rb')
img=Image.open(fp)
img=img.convert("L")
w,h=img.size
k=0.05
img=img.resize((int(k*w),int(k*h)))
w,h=img.size
string=""
for i in range(h):
for j in range(w):
gray=img.getpixel((j,i))
asc=int(gray/255*93)+33
string+=chr(asc)
string+='n'
out=open('out.txt','w')
out.write(string)
out.close()
fp.close()
我的代码里关于灰度和字符的对应是这样选取的:灰度的值为0-255的整数,我选取字符的ASCII码在33-126,然后在[0,255]和[33,126]之间建立均匀的线性映射。
k为缩放比,缩小为原图的0.05倍。
结果如下
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~BBBB~~~~~~~~
~~~~~~~~~~~~~~~BBB~~BBBBBB~~~~~~~
~~~~~~~~~~~~~~BBBBB~BBBBBB~~~~~~~
~~~~~~~~~~~~~BBBBBBBBBBBBB~~~~~~~
~~~~~~~~~~~~~BBBBBBBBBBBBB~~~~~~~
~~~~~~~~~~~~~BBBBBBBBBBBBB~~~~~~~
~~~~~~~~~~~~~BBBBBBBBBBBBB~~~~~~~
~~~~~~~~~~~~~~BBBBBBBBBBBB~~~~~~~
~~~~~~~~~~~~~~BBBBBBBBBBBB~~~~~~~
~~~~~~~~~~~~~~~BBBBBBBBBBB~~~~~~~
~~~~~~~~~~~~~~~!BBBBBBBBB~~~~~~~~
~~~~~~~~~~~~~~~~~BBBBBBB~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这个结果可以看出一个问题:比例失调了。
原因很简单:字符的宽度和高度不相等,再加上行间距和字符间距不相等。
如果在缩放时把图像合理拉宽,或者在word里把这些东西调好之后观察,就可以出现比较好的效果。
如果继续尝试还会发现更多问题。
比如这个算法只适用于背景灰度几乎一致的简单图形,比如如下的结果:
C=D?=<>6B9B77523?451/
<>C>MBD=N8:6198956<'F
<A@;.>FPT97F@=569DF:<
>;=>9C5?DJ`OACU1K:5?
?UGGXYYsXSY]TE?<85D
PR[X`bUdh_UX5C4>17:6
]Z^gaQZZ_QPa_=AW@B9Q
b`^Zh_PnZ^fGUDWAR:A1
aX^ca`ead]jpc@D@B>DG>
]Y_`d]hmgmQWD?NDEB@^
ke_d_bgxslCK>BF?P9_.7
]hfdchjqtQh=ACH;8P@L7
`uic_ndduE?E;3@B3HA=K
ellu|ybSi<7AC*6MT:@6
d_bp{yDHcc.9CJ?CB576?
_Y]ahoH;L@9<>3qL:8B-<
^_`^]A:=4JEBLTFNRJC.
@JoOTNA>DAMELROQ@EH
ME@6VavpZUaP>S^^J?H>
F<7LJ=[NITLO`TXTN178Y
RUMQQSTTCRU[]d`_AA>Q
不妨猜一下这是什么玩意。
谁能猜出来这其实是一只可爱的橘猫?
不过如果对代码稍加改动:
asc=int(gray/255*93)+33 if gray>150 else ord(' ')
其实就是加了个阈值,灰度不超过150的部分用空格替换。
结果是:
`
XYYsX Y]
[X`b dh_ X
]Z^ga ZZ_ a_
b`^Zh_ nZ^f
aX^ca`ead]jpc
]Y_`d]hmgm ^
ke_d_bgxsl _
]hfdchjqt h
`uic_nddu
ellu|yb i
d_bp{y cc
_Y]aho q
^_`^]
o
avpZ a ^^
[ ` X Y
[]d`_
还是能勉强看(naobu)出来有只猫的轮廓的。
针对这种问题,可以考虑的一种解决方法是:不转化为灰度图,直接用rgb图的信息来处理(毕竟这种图转换成灰度图已经看不清了)。然后针对颜色划分类别(比如把色环切分成若干块),每一类是相似的颜色并且对应同一个字符,能够在拓扑信息上较好地还原图像,也就能“看”出原图的效果。
掌握了这个方法就可以自制表情包,此外,也可以用此方法装饰自己的steam自定义信息框展柜。在展柜里放上沙雕表情包或者二次元老婆(划掉)来吸引同好。