写点什么

你看过字符画吗?用 Python 自己实现一个吧

作者:梦想橡皮擦
  • 2022 年 9 月 27 日
    河北
  • 本文字数:1549 字

    阅读完需:约 5 分钟

⛳️ 实战场景


如果你是一名程序员,你肯定在网上的代码中看到过下述注释,那有没有想过自己实现一个呢?



先说原理:图片由像素点构成,然后将每个像素点替换成一个字符,就可以将图片转换成字符画。


这是最简单的说明,但是每个像素点都有一种颜色,而且该颜色是由红绿蓝三色组成,红绿蓝即 RBG 值,如果将所有颜色与字符替换,那存在 256 x 256 x 256 = 1638400 中颜色,完全与字符替换是不可能的,此时就需要降低替换数量,这里就引入了灰度值,每个颜色值都可以转换成灰度值,而且灰度值的范围是 0-255,这样大幅降低了待替换数量,并且在 Python 中有现成的将图片转换为灰度图的库,实现起来就更加便捷了。


这里存在一个 RGB 转灰度值的公式:


gray = 0.2126 * r + 0.7152 * g + 0.0722 * b

也可以使用下述公式,含义一致。

gray = (2126 * r + 7152 * g + 722 * b) / 10000


提前安装 pillow 库,用于将图片转换为灰度图。


⛳️ pillow 转灰度图


使用 pillow 库操作下述图片,将其转换为字符图:



由于需要进行字符串替换,所以需要了解一些基本规则:


颜色越浅,字符留白越多,当颜色为白时,使用空格字符;


颜色越深,使用的字符笔画越多,例如黑色,可以使用 @ 这样的符号;


接下来我们就把图片转换成灰度值:


def img_to_char(path):img = Image.open(path)# 原图的宽和高 ow, oh = img.sizeprint(ow, oh)img = img.convert('L')img.show()


s = img_to_char('1.png')print(s)


此时运行代码,就会得到一张灰色图片,效果如下:


接下来将图片中每个像素点的灰度值都提取出来,做后一步计算。


from PIL import Image


def img_to_char(path):img = Image.open(path)# 原图的宽和高 ow, oh = img.sizeprint(ow, oh)img = img.convert('L')# img.show()char_img = ""for y in range(oh):s = ''for x in range(ow):# 取灰度值 gray = img.getpixel((x, y))# char = gray_to_char(gray)s += str(gray)char_img = char_img + s + '\n'return char_imgs = img_to_char('1.png')print(s)


此时会得到下图效果,一堆数字,在数字中还是可以发现部分差异的。


数字有了,接下来就是数字转换为字符了,你可以依据前文提及的【黑白】程度进行排列,例如下述内容:


@#$%&MNBEFRWYLIkbtj?*984532menocvzst{}[]1|()<>=+~-;:i^"'.


数量和内容都可以自行控制,最后放置一个空格,用来替换白色。

将灰度值转换成对应的字符

def gray_to_char(gray):all_char = """@#$%&MNBEFRWYLIkbtj?*984532menocvzst{}[]1|()<>=+~-;:i^"'. """char = all_char[int(len(all_char) * gray / 256)]return char


然后把前文数字拼接的位置,替换成该函数。


char_img = ""for y in range(oh):s = ''for x in range(ow):# 取灰度值 gray = img.getpixel((x, y))char = gray_to_char(gray)s += charchar_img = char_img + s + '\n'return char_img


此时在运行代码,就可以得到一张超大的字符图,下图是表情包眼睛区域。


接下来对图片进行一下优化,降低大小。


def img_to_char(path):img = Image.open(path)# 原图的宽和高 ow, oh = img.sizeprint(ow, oh)# 缩小高度和宽度 w = int(ow * 0.3)h = int(oh * 0.3)# 调整图片大小 img = img.resize((w, h))img = img.convert('L')# img.show()char_img = ""for y in range(h):s = ''for x in range(w):# 取灰度值 gray = img.getpixel((x, y))char = gray_to_char(gray)s += charchar_img = char_img + s + '\n'return char_img


等比例压缩之后,发现图片被拉伸了,原因是像素转换成文本,行与行之间有间隔,要缩小高度才能得到较好效果。


高度缩小到原来的二分之一,代码如下所示:

缩小高度和宽度

w = int(ow * 0.3)h = int(oh * 0.3)


h = h // 2

调整图片大小

img = img.resize((w, h))img = img.convert('L')


此时就可以得到一个比较合理大小的图片了,是不是一模一样!


发布于: 刚刚阅读数: 3
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
你看过字符画吗?用 Python 自己实现一个吧_9月月更_梦想橡皮擦_InfoQ写作社区