这可能看起来很简单,我也以为会很简单,但实际上并不是。我花了一个星期尝试让它工作,但我却无法做到。
我需要什么
我需要使用任何手写样式的字体在Python中渲染给定字符串(仅包含标准字符)。必须从TTF文件中加载字体。我还需要能够准确地检测其边界(垂直和水平地获取文本的确切开始和结束位置),最好是在绘制之前。最后,如果输出是一个数组而不是写入磁盘的图像文件,那将使我的生活更加轻松。
我尝试过什么
Imagemagick绑定(即Wand):无法弄清如何在设置图像大小并在其上呈现文本之前获取文本度量。
通过Pycairo绑定的Pango:文档几乎不存在,无法弄清如何从文件中加载TrueType字体。
PIL(Pillow):最有希望的选项。我已经成功地计算出了任何文本的高度(令人惊讶的是,这不仅仅是
这里有一些示例,文本为“Puzzling”:
字体:Lovers Quarrel 结果: 字体:Miss Fajardose 结果: 这是我用来生成图像的代码:
通过Pycairo绑定的Pango:文档几乎不存在,无法弄清如何从文件中加载TrueType字体。
PIL(Pillow):最有希望的选项。我已经成功地计算出了任何文本的高度(令人惊讶的是,这不仅仅是
getsize
返回的高度),但是对于一些字体,宽度似乎有问题。即使让图像足够大,它们也会被裁剪。这里有一些示例,文本为“Puzzling”:
字体:Lovers Quarrel 结果: 字体:Miss Fajardose 结果: 这是我用来生成图像的代码:
from PIL import Image, ImageDraw, ImageFont
import cv2
import numpy as np
import glob
import os
font_size = 75
font_paths = sorted(glob.glob('./fonts/*.ttf'))
text = "Puzzling"
background_color = 180
text_color = 50
color_variance = 60
cv2.namedWindow('display', 0)
for font_path in font_paths:
font = ImageFont.truetype(font_path, font_size)
text_width, text_height = font.getsize(text)
ascent, descent = font.getmetrics()
(width, baseline), (offset_x, offset_y) = font.font.getsize(text)
# +100 added to see that text gets cut off
PIL_image = Image.new('RGB', (text_width-offset_x+100, text_height-offset_y), color=0x888888)
draw = ImageDraw.Draw(PIL_image)
draw.text((-offset_x, -offset_y), text, font=font, fill=0)
cv2.imshow('display', np.array(PIL_image))
k = cv2.waitKey()
if chr(k & 255) == 'q':
break
一些问题
是否字体是问题所在?我的一些同事告诉我可能是这个原因,但我不这样认为,因为通过命令行Imagemagick可以正确渲染它们。
我的代码是否有问题?我是否做错了什么导致文本被截断?
最后,这是PIL的一个错误吗?如果是这种情况,您推荐我使用哪个库来解决我的问题?我应该再试试Pango和Wand吗?