2022年 11月 5日

Python字符画生成详解

Python字符画生成详解

  • 字符画的原理
  • 方案设计
    •  设计思路
    •  整体流程
  • 代码实现
  • 成品展示
  • 提示

字符画的原理

  顾名思义,字符画就是由字符组成的画
  日常我们在网上看到的彩色图片一般有3个颜色通道:R(红)、G(绿)、B(蓝)。你没看错,就是初中物理你学过的那个“色光三原色,以此构成颜色鲜明的图片。
这是一张可爱的喵喵
  而当绘图的颜色只有一种的情况下,如素描的时候,则通过线条颜色的密集程度不同进行明暗区分,即灰度值区分。
这是一张素描的可爱猫猫
  同理,对于字符画,我们也可以根据字符笔画的密集程度进行字符画的明暗区分,以此实现对字符画各部分的灰度区分。
一张喵喵的字符画

方案设计

 设计思路

  首先,每个字符中线条的密集程度进行排序,用于生成字符画时的明暗区分。这里我采用的字符是“MNHQ$OC?7>!:-; “,各位可以更具自己的需求进行更改。
  基础的字符画是单色画,既然如此,我们则没必要针对彩色图片进行方案设计,可以将图片将图片整体修改为灰色,根据灰色图片中每个像素点的灰度值将对应像素替换成对应字符。
  考虑到一般情况下,一个字符的高度大于它的宽度,并且每行字符之间都会有固定的间隙,为了保证最终成品的与原图的宽高比,可以将转换后的灰图的宽度进行拉伸,用于抵消由于字符宽高不一致和行间间隙造成的误差。

在这里插入图片描述

  然后,生成一个和灰图相同的数组
pixels,遍历
pixels每个像素,根据该像素的灰度获取对应字符并进行拼接,最后返回拼接后字符串。

 整体流程

  1. 设置字符串chars用于区分不同灰度。
  2. 通过PIL(需安装pillow)的Image包读取img并进行图片宽度拉伸。
  3. 将img转换为灰图。
  4. 使用numpy生成与img相同的数组pixels。
  5. 定义空串result。
  6. 循环遍历pixels像素点,获取该像素灰度在chars中对应的字符,并将该字符拼接至result,一行遍历完成后拼接换行符。
  7. 返回result。

代码实现

import numpy as np
from PIL import Image


def chars_image(path, result_path, widen, chars):
    img = Image.open(path)  # 获取图片
    img_width, img_height = img.size  # 获取图片原始宽高
    # img_width, img_height = img_width // 10, img_height // 10 #根据需求进行压缩
    img_width = int(img_width * widen)  # 图片宽度拉伸,拉伸程度根据图片大小自行修改
    img = img.resize((img_width, img_height), Image.ANTIALIAS)  # 修改图片尺寸
    img = img.convert("L")  # 将图片转换为灰图
    pixels = np.array(img)  # 生成img的copy数组pixels
    N = len(chars)
    step = 256 // N
    result = ""
    for i in range(img_height):
        for j in range(img_width):
            index1 = pixels[i][j] // step  # 获取灰度对应字符
            result += chars[index1]  # 字符拼接
        result += "\n"  # 一层遍历完成后添加换行符

    with open(result_path, "w", encoding="utf-8") as f:
        f.write(result)


if __name__ == '__main__':
    chars_image(path="./img.png", result_path="./result.txt", widen=1.8, chars="MNHQ$OC?7>!:-; ")

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

成品展示

原图
原图
成品图
在这里插入图片描述

提示

如果遇到以下这种由于字符宽度不一致导致成品效果差的情况。
在这里插入图片描述

将显示字体修改为Courier或Courier New后缩小即可。
显示字体修改
修改后在这里插入图片描述