为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 PIL 绘制箭头?

如何使用 PIL 绘制箭头?

慕慕森 2023-07-05 16:29:15
我需要通过PIL画一个箭头。用户发送箭头的起点坐标和终点坐标。我没有任何想法。我怎样才能做到呢?
查看完整描述

1 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞

PIL 不提供绘制箭头的简单方法,因此我建议将PIL Image转换为NumPy数组,并使用OpenCV、Matplotlib、CairoWand在其上绘制箭头,然后转换回PIL Image

#!/usr/bin/env python3


import cv2

import numpy as np

from PIL import Image


# Create an empty solid blue image

w, h = 640, 480

im = Image.new('RGB', (w,h), (0,0,255))


# Make into Numpy array so we can use OpenCV drawing functions

na = np.array(im)


# Draw arrowed line, from 10,20 to w-40,h-60 in black with thickness 8 pixels

na = cv2.arrowedLine(na, (10,20), (w-40, h-60), (0,0,0), 8)


# Revert back to PIL Image and save

Image.fromarray(na).save('result.png')

//img3.sycdn.imooc.com/64a52a000001fb2406360475.jpg

请注意,OpenCV 使用 BGR 而不是 RGB 排序,因此如果您想要 PIL 中的红线,则需要在 OpenCV 中使用(0, 0, 255) 。


如果您真的非常想使用PIL绘制带有箭头的线,您可以绘制一条线,然后在其末端添加一个三角形,draw.polygon()如下所示:


#!/usr/bin/env python3


import math

import random

from PIL import Image, ImageDraw


def arrowedLine(im, ptA, ptB, width=1, color=(0,255,0)):

    """Draw line from ptA to ptB with arrowhead at ptB"""

    # Get drawing context

    draw = ImageDraw.Draw(im)

    # Draw the line without arrows

    draw.line((ptA,ptB), width=width, fill=color)


    # Now work out the arrowhead

    # = it will be a triangle with one vertex at ptB

    # - it will start at 95% of the length of the line

    # - it will extend 8 pixels either side of the line

    x0, y0 = ptA

    x1, y1 = ptB

    # Now we can work out the x,y coordinates of the bottom of the arrowhead triangle

    xb = 0.95*(x1-x0)+x0

    yb = 0.95*(y1-y0)+y0


    # Work out the other two vertices of the triangle

    # Check if line is vertical

    if x0==x1:

       vtx0 = (xb-5, yb)

       vtx1 = (xb+5, yb)

    # Check if line is horizontal

    elif y0==y1:

       vtx0 = (xb, yb+5)

       vtx1 = (xb, yb-5)

    else:

       alpha = math.atan2(y1-y0,x1-x0)-90*math.pi/180

       a = 8*math.cos(alpha)

       b = 8*math.sin(alpha)

       vtx0 = (xb+a, yb+b)

       vtx1 = (xb-a, yb-b)


    #draw.point((xb,yb), fill=(255,0,0))    # DEBUG: draw point of base in red - comment out draw.polygon() below if using this line

    #im.save('DEBUG-base.png')              # DEBUG: save


    # Now draw the arrowhead triangle

    draw.polygon([vtx0, vtx1, ptB], fill=color)

    return im


# Create an empty solid blue image

w, h = 640, 480

im = Image.new('RGB', (w,h), (0,0,255))


# Get some controlled randomness

random.seed(58)


# Draw some random arrows

for _ in range(10):

    ptA = (random.randint(0,w), random.randint(0,h))

    ptB = (random.randint(0,w), random.randint(0,h))

    im = arrowedLine(im, ptA, ptB)


# Save

im.save('result.png')

//img2.sycdn.imooc.com/64a52a120001dc7e06330477.jpg

关键词:Python、图像处理、PIL、Pillow、箭头、箭头、箭头线、OpenCV。



查看完整回答
反对 回复 2023-07-05
  • 1 回答
  • 0 关注
  • 187 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信