【发布时间】:2019-05-16 16:04:43
【问题描述】:
这可能看起来很简单,我也认为会是这样,但显然不是。我一定花了一个星期的时间来完成这项工作,但看在我的爱上,我无法做到。
我需要什么
我需要在 Python 中使用任何给定字体(类似手写)呈现任何给定字符串(仅包含标准字符)。字体必须从 TTF 文件加载。我还需要能够准确地检测它的边界(获得文本的确切开始和结束位置,垂直和水平),最好是在绘制它之前。最后,如果输出是一个我可以继续处理的数组,而不是写入磁盘的图像文件,那真的会让我的生活更轻松。
我的尝试
Imagemagick 绑定(即 Wand):在设置图像大小并在其上渲染文本之前,无法弄清楚如何获取文本指标。
Pango 通过 Pycairo 绑定:几乎不存在文档,无法弄清楚如何从文件中加载 TrueType 字体。
PIL(枕头):最有希望的选择。我已经设法准确地计算出任何文本的高度(令人惊讶的是,这不是 getsize 返回的高度),但对于某些字体来说,宽度似乎有问题。不仅如此,那些宽度有问题的字体也会被错误地渲染。即使图像足够大,它们也会被截断。
这里有一些例子,带有“令人困惑”的文字:
结果:
结果:
这是我用来生成图像的代码:
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 吗?
【问题讨论】:
-
在命令行 ImageMagick 中,您可以在创建文本时使用 -debug annotate 获取字体指标。见imagemagick.org/Usage/text/#font_info。我不知道这在 Wand 中是否可用。但是您可以使用 Python 子进程调用来执行此操作。
-
如果您知道文本需要放入的框,那么stackoverflow.com/a/39557083/740553 可能更符合您的要求。
-
@fmw42 谢谢,我也许可以用它做点什么,尽管在做了一些测试之后,指标似乎也不完全正确,在大多数情况下,PIL 在计算高度方面做得更好。
-
@Mike'Pomax'Kamermans 我需要一个恒定的字体大小,我需要知道它需要多少空间,而不是相反。
-
注意:当我在最新版本的 PIL 中尝试使用最新版本的链接字体时,不再出现这种情况。 PIL 现在可以正确渲染了。
标签: python fonts python-imaging-library text-rendering