1

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

 2 years ago
source link: https://blog.51cto.com/cnca/5612616
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Table of Contents

⛳️ 实战场景

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

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

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

这是最简单的说明,但是每个像素点都有一种颜色,而且该颜色是由红绿蓝三色组成,红绿蓝即 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 库操作下述图片,将其转换为字符图:

你看过字符画吗?用 Python 自己实现一个吧_灰度值_02

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

  • 颜色越浅,字符留白越多,当颜色为白时,使用空格字符;
  • 颜色越深,使用的字符笔画越多,例如黑色,可以使用 @ 这样的符号;

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

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


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

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

你看过字符画吗?用 Python 自己实现一个吧_灰度值_03

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

from PIL import Image

def img_to_char(path):
    img = Image.open(path)
    # 原图的宽和高
    ow, oh = img.size
    print(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_img
s = img_to_char('1.png')
print(s)

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

你看过字符画吗?用 Python 自己实现一个吧_灰度值_04

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

@#$%&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 += char
        char_img = char_img + s + '\n'
    return char_img

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

你看过字符画吗?用 Python 自己实现一个吧_灰度值_05

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

def img_to_char(path):
    img = Image.open(path)
    # 原图的宽和高
    ow, oh = img.size
    print(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 += char
        char_img = char_img + s + '\n'
    return char_img

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

你看过字符画吗?用 Python 自己实现一个吧_像素点_06

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

# 缩小高度和宽度
w = int(ow * 0.3)
h = int(oh * 0.3)

h = h // 2
# 调整图片大小
img = img.resize((w, h))
img = img.convert('L')

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

你看过字符画吗?用 Python 自己实现一个吧_像素点_07

📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 <font color=red>711</font> 篇原创博客


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK