OpenCV 画箭头 python

openCV画箭头函数arrowedLine画出来的很丑,自己写了一个画箭头函数,结果如下
OpenCV 画箭头 python_第1张图片

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

画出来的图像如下:

你可能感兴趣的:(python,python,opencv)