Draw text on an angle (rotated) in Python

前端 未结 2 811
日久生厌
日久生厌 2021-01-13 12:27

I am drawing text onto a numpy array image in Python (using a custom font). Currently I am converting the image to PIL, drawing the text and then converting back to a numpy

2条回答
  •  难免孤独
    2021-01-13 12:59

    You can use PIL to draw rotated text. I suggest drawing the text onto a blank image, rotating that image, and then pasting the rotated image into the main image. Something like:

    Code:

    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)
    

    How does it work:

    1. Create a transparency mask.
    2. Draw the text onto the mask.
    3. Rotate the mask, and crop to proper size.
    4. Paste the desired color into the image, using the rotated transparency mask containing the text.

    Test Code:

    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()
    

    Results:

提交回复
热议问题