likes
comments
collection
share

用 Python 实现“连字成字” 写作“明天”读作“未来”

作者站长头像
站长
· 阅读数 27

什么是“连字成字“,写作“明天”读作“未来”呢?先来看个示例,一看就明白了,

用 Python 实现“连字成字” 写作“明天”读作“未来”

再比如,

用 Python 实现“连字成字” 写作“明天”读作“未来”

有点意思吧,而且使用 Python 实现这个效果并不难,只需要 4 步,

  1. 将字符串(1 行 m 列的字符数组)转换成白底黑字的图片
  2. 将白底黑字的图片转换成 0、1 的二维数组,字符笔画经过的地方是 1,没有经过的地方是 0
  3. 在二维数组中 1 的位置上填上想要的汉字,0 的位置上填上空白字符,最终得到一个汉字的二维数组
  4. 将这个汉字的二维数组转换为白底黑字的图片

下面我们就来看一看每一步的 Python 代码。

第 1 步

我们先来看看如何将字符串转换为白底黑字的图片。

这一步要用到 Pillow 这个图像处理库。Pillow 派生自 Python Imaging Library(PIL),支持多种格式的图像文件。虽然原始的 PIL 已停止维护,但派生版的 Pillow 不但保留了 PIL 的易用性,还添加了诸多功能。

from PIL import Image, ImageDraw, ImageFont # pip install pillow

# 将字符的二维数组(共 rows 行,每行 cols 个字符)转换成白底黑字的图片
def char_matrix2img(str_matrix, char_size):
    rows = len(str_matrix)
    cols = len(str_matrix[0])

    # 创建白底图片
    img  = Image.new('RGB', (char_size * cols , char_size * rows), 'white')
    # 创建一个 ImageDraw 对象,用于在图像上绘制形状和文本
    draw = ImageDraw.Draw(img)

    # 黑体字
    myfont = ImageFont.truetype("/System/Library/Fonts/STHeiti Medium.ttc", char_size)

    # 逐一将字符“画”到图片上,
    # 每个字符的左上角坐标为 (col * char_size, row * char_size)
    # 颜色为黑色,字体为黑体
    # fill=(0, 0, 0) 表示 RGB(0, 0, 0) 即黑色
    for row in range(rows):
        for col in range(cols):
            char = str_matrix[row][col]
            draw.text((col * char_size, row * char_size), char, fill=(0, 0, 0), font = myfont)
    
    return img

我们定义了一个名为 char_matrix2img() 的函数,执行结果如下,

用 Python 实现“连字成字” 写作“明天”读作“未来”

第 2 步

接下来,我们要将白底黑字的图片转换成 0、1 的二维数组,笔画经过的地方是 1,没有经过的地方是 0。

这一步其实可以很简单,只需要调用 Pillow 库中的 convert() 方法修改图像的模式为二值图像即可。只不过,在二值图像中,每个像素对应的值要么是 0(黑色)要么是 255(白色),而不是 0(没有笔画经过)或 1(有笔画经过)。为了将有无笔画经过和黑白对应起来,我们可以做一个简单的变换。

def img2binary_matrix(img):
  # 将图片转换为二值矩阵
  img = img.convert('1')
  # 读取图片的宽和高
  img_width, img_height = img.size
  print(img_width, 'x', img_height)

  result = []
  for y in range(img_height):
    row = []
    for x in range(img_width):
        row.append(0 if img.getpixel((x, y)) == 255 else 1)
    result.append(row)
  return result

该函数先读取图像的宽度和高度,然后遍历图像的每个像素,将像素值转换为 0 或 1,并存储在结果二维数组 result 中。转换结果如下(为了便于查看,这里将 0 替换成了▫️;将 1 替换成了◼️),

16 x 16
[▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️]
[▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️]
[▫️, ▫️, ◼️, ◼️, ◼️, ◼️, ▫️, ▫️, ◼️, ◼️, ◼️, ◼️, ◼️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ◼️, ▫️, ◼️, ▫️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ◼️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ◼️, ◼️, ◼️, ◼️, ▫️, ◼️, ◼️, ◼️, ◼️, ◼️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ◼️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ◼️, ▫️, ◼️, ◼️, ◼️, ◼️, ◼️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ◼️, ◼️, ◼️, ▫️, ▫️, ◼️, ▫️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ◼️, ◼️, ◼️, ◼️, ▫️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️]
[▫️, ▫️, ◼️, ▫️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️, ▫️, ▫️, ◼️, ◼️, ▫️, ▫️]
[▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ◼️, ◼️, ▫️, ▫️, ▫️, ◼️, ◼️, ◼️, ▫️, ▫️]
[▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ◼️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️, ▫️]

第 3 步

得到了 0、1 的二维数组后,就可以用喜欢的汉字替换其中的 1,并用空白字符替换其中的 0 了。例如,我们反复用“未来”这两个字替换其中的 1,

def binary_matrix2char_matrix(binary_matrix, replace_str):
    result = []
    idx = 0
    for row in binary_matrix:
        char_row = []
        for x in row:
            if x == 0:
                char_row.append(' ')
            else:
                char_row.append(replace_str[idx])
                idx = (idx + 1) % len(replace_str)
        result.append(char_row)
    return result
    
result = binary_matrix2char_matrix(result, '未来')

最后一步

最后一步就很简单了,其实和第一步要解决的问题一模一样,还是将 n 行 m 列(第 1 步中是 1 行 m 列)的字符二维数组转换成白底黑字的图片。所以,只需要再次调用 char_matrix2img() 函数即可,只是这一次需要调小每个字符的大小。

从最初的字符串,到“连字成字”的完整步骤如下,

img = char_matrix2img([['明', '天']], 48)
img.show()

result = img2binary_matrix(img)

result = binary_matrix2char_matrix(result, '未来')
char_matrix2img(result, 16).show()

怎么样,挺有意思的吧。掌握了这个方法,不仅可以“连字成字”,还能“连字成图”,

用 Python 实现“连字成字” 写作“明天”读作“未来”

赶紧发挥你的创意吧!

转载自:https://juejin.cn/post/7399564369229332518
评论
请登录