Draw text on an angle (rotated) in Python

Bug*_*Bug 4 python fonts rotation python-imaging-library python-3.x

我在 Python 中将文本绘制到numpy数组图像上(使用自定义字体)。目前我正在将图像转换为 PIL,绘制文本然后转换回 numpy 数组。

import numpy as np
import cv2

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

char_image = np.zeros((200, 300, 3), np.uint8)

# convert to pillow image
pillowImage = Image.fromarray(char_image)
draw = ImageDraw.Draw(pillowImage)

# add chars to image
font = ImageFont.truetype("arial.ttf", 32)
draw.text((50, 50), 'ABC', (255, 255, 255), font=font)

# convert back to numpy array
char_image = np.array(pillowImage, np.uint8)

# show image on screen
cv2.imshow('myImage', char_image)
cv2.waitKey(0)
Run Code Online (Sandbox Code Playgroud)

无论如何要在给定的角度绘制文本,即。33度?

绘制文本后旋转图像不是一种选择

Ste*_*uch 5

您可以使用 PIL 绘制旋转文本。我建议将文本绘制到空白图像上,旋转该图像,然后将旋转后的图像粘贴到主图像中。就像是:

代码:

def draw_rotated_text(image, angle, xy, text, fill, *args, **kwargs):
    """ Draw text at an angle into an image, takes the same arguments
        as Image.text() except for:

    :param image: Image to write text into
    :param angle: Angle to write text at
    """
    # get the size of our image
    width, height = image.size
    max_dim = max(width, height)

    # build a transparency mask large enough to hold the text
    mask_size = (max_dim * 2, max_dim * 2)
    mask = Image.new('L', mask_size, 0)

    # add text to mask
    draw = ImageDraw.Draw(mask)
    draw.text((max_dim, max_dim), text, 255, *args, **kwargs)

    if angle % 90 == 0:
        # rotate by multiple of 90 deg is easier
        rotated_mask = mask.rotate(angle)
    else:
        # rotate an an enlarged mask to minimize jaggies
        bigger_mask = mask.resize((max_dim*8, max_dim*8),
                                  resample=Image.BICUBIC)
        rotated_mask = bigger_mask.rotate(angle).resize(
            mask_size, resample=Image.LANCZOS)

    # crop the mask to match image
    mask_xy = (max_dim - xy[0], max_dim - xy[1])
    b_box = mask_xy + (mask_xy[0] + width, mask_xy[1] + height)
    mask = rotated_mask.crop(b_box)

    # paste the appropriate color, with the text transparency mask
    color_image = Image.new('RGBA', image.size, fill)
    image.paste(color_image, mask)
Run Code Online (Sandbox Code Playgroud)

它是如何工作的:

  1. 创建一个透明蒙版。
  2. 将文本绘制到蒙版上。
  3. 旋转蒙版,并裁剪到合适的大小。
  4. 使用包含文本的旋转透明蒙版将所需颜色粘贴到图像中。

测试代码:

import numpy as np

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

char_image = np.zeros((100, 150, 3), np.uint8)

# convert to pillow image
pillowImage = Image.fromarray(char_image)

# draw the text
font = ImageFont.truetype("arial.ttf", 32)
draw_rotated_text(pillowImage, 35, (50, 50), 'ABC', (128, 255, 128), font=font)

pillowImage.show()
Run Code Online (Sandbox Code Playgroud)

结果:

结果图片


grg*_*rsr 2

使用 matplotlib,首先可视化数组并在其上绘图,从图中获取原始数据。优点:这两种工具都相当高级,可以让您处理流程的许多细节。ax.annotate()提供了在何处以及如何绘制和设置字体属性的灵活性,并plt.matshow()提供了可让您处理数组可视化各个方面的灵活性。

import matplotlib.pyplot as plt
import scipy as sp

# make Data array to draw in
M = sp.zeros((500,500))

dpi = 300.0

# create a frameless mpl figure
fig, axes = plt.subplots(figsize=(M.shape[0]/dpi,M.shape[1]/dpi),dpi=dpi)
axes.axis('off')
fig.subplots_adjust(bottom=0,top=1.0,left=0,right=1)
axes.matshow(M,cmap='gray')

# set custom font
import matplotlib.font_manager as fm
ttf_fname = '/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf'
prop = fm.FontProperties(fname=ttf_fname)

# annotate something
axes.annotate('ABC',xy=(250,250),rotation=45,fontproperties=prop,color='white')

# get fig image data and read it back to numpy array
fig.canvas.draw()
w,h = fig.canvas.get_width_height()
Imvals = sp.fromstring(fig.canvas.tostring_rgb(),dtype='uint8')
ImArray = Imvals.reshape((w,h,3))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述