openCV画箭头函数arrowedLine画出来的很丑,自己写了一个画箭头函数,结果如下
1、OpenCV 画箭头的函数
if __name__ == "__main__":
path = r"D:\cycFeng\Data\tree3.jpg"
img = cv2.imread(path)
StartX = 640
StartY = 528
EndX = 368
EndY = 426
cv2.arrowedLine(img, (StartX, StartX), (EndX, EndY), (255, 0, 0), 2, 9, 0, 0.3) # 画箭头
cv2.imshow('q', img)
cv2.waitKey()
cv2.arrowedLine(img, (StartX, StartX), (EndX, EndY), (255, 0, 0), 2, 9, 0, 0.3) # 画箭头
画出来效果如下,比较丑
2、自己写一个画箭头函数,
给定起始点和终点,以及颜色,先找到箭头的7个点,之后用透明掩膜在原图上画出透明箭头
"""
@Author : XiaoZhou
@Time : 2021/11/22 16:38
@FileName : ArrowDraw.py
@Function :
"""
import numpy as np
import cv2
def GetArrowPoints(StartX, StartY, EndX, EndY, Width, NoseWidth, ArrowSizeL):
"""
这里返回一个箭头的五个点,X坐标水平向右, Y坐标垂直向下
:param StartX: 开始点的X坐标
:param StartY: 开始点Y的坐标
:param EndX: 结束点X的坐标
:param EndY: 结束点Y的坐标
:param Width: 箭头尾部的宽度,这里宽度是一半
:param NoseWidth: 箭头鼻翼的宽度,也是一半
:param ArrowSizeL: 这里是箭头的长度
:return:
"""
xx = EndX - StartX # 水平向右是X 竖直向下是Y
yy = EndY - StartY
if xx == 0: # 找到角度
angle = np.pi/2
else:
angle = np.arctan(abs(yy / xx))
if xx < 0 and yy < 0: # 第二象限
angle = np.pi + angle
elif xx < 0 and yy > 0: # 第三象限
angle = np.pi - angle
elif xx > 0 and yy < 0: # 第一象限
angle = np.pi * 2 - angle
d1 = Width # 这里的宽度表示线条的宽度的一半
# ArrowSizeL = 50 # 表示末端箭头长度
# 通过这五个点,确定一个箭头
d2 = d1 + NoseWidth # 箭头线段宽度+鼻翼宽度 这里鼻翼宽度是一半箭头的鼻翼的宽度
SinAngle = np.sin(angle)
CosAngle = np.cos(angle)
A = [int(StartX + d1 * SinAngle), int(StartY - d1 * CosAngle)]
B = [int(StartX - d1 * SinAngle), int(StartY + d1 * CosAngle)]
EndMid = [int(EndX - ArrowSizeL * CosAngle), int(EndY - ArrowSizeL * SinAngle)]
C = [int(EndMid[0] + d1 * SinAngle), int(EndMid[1] - d1 * CosAngle)]
D = [int(EndMid[0] - d1 * SinAngle), int(EndMid[1] + d1 * CosAngle)]
E = [int(EndMid[0] + d2 * SinAngle), int(EndMid[1] - d2 * CosAngle)]
F = [int(EndMid[0] - d2 * SinAngle), int(EndMid[1] + d2 * CosAngle)]
pts = np.array([A, C, E, [EndX, EndY], F, D, B]) # 这里是有顺序的
return pts
def ArrowDrow(img, StartX, StartY, EndX, EndY, r, g, b):
"""
给一张图像,和箭头的起始点,和颜色,可以在图上对应位置添加对应颜色的箭头, 并且可以调节透明度
:param img:图像
:param StartX:起始点
:param StartY:
:param EndX:
:param EndY:
:param r,g,b: 箭头的颜色
:return:
"""
# 图像的宽高
h = len(img)
w = len(img[0])
# 生成一个同样大小的掩膜图像
mask1 = np.zeros((h, w), dtype=np.uint8)
# 设置箭头的参数
Width = 10 # 没有箭头一端的宽度的一半
NoseWidth = 20 # 箭头鼻翼的宽度
ArrowSizeL = 30 # 箭头的长度
# 得到箭头的五个点
pts = GetArrowPoints(StartX, StartY, EndX, EndY, Width, NoseWidth, ArrowSizeL)
# 在掩膜mask1上用线画箭头
cv2.polylines(mask1, [pts], True, (255, 255, 255)) # 这里表示True是画闭合曲线
# 找到箭头的轮廓,并在原图上画
contours, hierarchyNext10 = cv2.findContours(mask1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 只找外轮廓
# 保存原图
img2 = img.copy()
# 在img原图上添加带颜色的箭头
for cnt in contours:
cv2.fillPoly(img, [cnt], (r, g, b))
# 在图像上覆盖透明膜
alpha = 0.4 # 透明指数 越大颜色越重
img2 = cv2.addWeighted(img, alpha, img2, 1 - alpha, 0)
# # 画起始位置
# img2 = cv2.circle(img2, (StartX, StartY), 5, (0, 0, 255), 1)
# img2 = cv2.circle(img2, (EndX, EndY), 5, (0, 0, 255), 1)
return img2
if __name__ == "__main__":
path = r"D:\tree3.jpg"
img = cv2.imread(path)
StartX = 640
StartY = 528
EndX = 368
EndY = 426
# cv2.arrowedLine(img, (StartX, StartX), (EndX, EndY), (255, 0, 0), 2, 9, 0, 0.3) # 画箭头
img = ArrowDrow(img, StartX, StartY, EndX, EndY, 255, 0, 0)
cv2.imshow('q', img)
cv2.waitKey()
画出来的图像如下: