我需要用PIL画一个箭头。用户向箭头发送起点坐标和终点坐标。我没有任何想法,如何做到这一点。请帮我吗?
答案 0 :(得分:2)
PIL无法提供简单的绘制箭头的方法,因此建议您将 PIL Image
转换为Numpy
数组并使用 OpenCV < / strong>或 matplotlib 或 Cairo 或 Wand ,在其上绘制箭头,然后转换回 PIL < / strong> 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')
请注意,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')
关键字:Python,图像处理,PIL,Pillow,箭头,箭头,箭头线,OpenCV。