python-opencv 标注图片角度值

python-opencv 标注图片角度值

实现功能

通过在打开的图片中使用鼠标选取角的三个点,然后计算其角度并且标记在图片中

CV2函数

# 读取图片,返回numpy.ndarray对象
img = cv2.imread("image_path")
# 图片显示, 显示与操作的窗口
cv2.imshow("win_name", img)
# 鼠标事件监听
cv2.setMouseCallback("win_name", calback_function)
# 绘制直线
cv2.line(img, point1, point2, color, thickness=None)
# 绘制点
cv2.circle(img, center, radius, color, thickness=None, lineType=None, shift=None)

标注示例

示例图片:
在这里插入图片描述
角度标注释:
在这里插入图片描述

代码

from cv2 import cv2
import math

win_name = "measuring angle"
img_path = "angle.jpg"
img = cv2.imread(img_path)
img_cp = img.copy()  # 拷贝一份数据

points = []  # 存储选择的点


def mouse_point(event, x, y, *args):
    """
    鼠标左键点击事件回调函数
    :param event:
    :param x:
    :param y: y 是图片上到下的方向的坐标轴,不是常规的坐标,
    相当于对常规坐标沿X周做了翻转,但是对于角度来说,做翻转不会影响角度大小,所以坐标不需要转换。
    :param args: flags, params
    :return:
    """
    thickness = 2
    color = (0, 0, 255)
    # print("args", args)
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(img, (x, y), 2, (0, 0, 255),
                   thickness=thickness)  # circle(img, center, radius, color, thickness=None, lineType=None, shift=None)
        points.append((x, y))
        print(x, y)

        # 计算角度
        if points and len(points) % 3 == 0:  # 每三个点组成一个角度
            o_point = points[-2]  # 角顶点
            a = get_angle_by_cos(*points[-3:])
            angle = round(math.degrees(a), 2)
            print(f"弧度:{a}, 角度:{angle}")

            # 绘制角的边
            cv2.line(img, o_point, points[-1], color,
                     thickness=thickness)  # def line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
            # def line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
            cv2.line(img, o_point, points[-3], color, thickness=thickness)
            mark_point = o_point[0] + 20, o_point[1] - 10

            # 绘制角度值到图片中
            cv2.putText(img, str(angle), mark_point, cv2.FONT_HERSHEY_COMPLEX, 0.6, color)


def get_angle_by_cos(p0, p1, p2):
    """
    使用向量的点乘公式计算角度值
    :param p0:
    :param p1: 角的顶点
    :param p2:
    :return: 弧度
    """
    # print(p0, p1, p2)
    l1 = p0[0] - p1[0], p0[1] - p1[1]
    l2 = p2[0] - p1[0], p2[1] - p1[1]
    # print(l1, l2)
    m = math.sqrt(l1[0] ** 2 + l1[1] ** 2) * math.sqrt(l2[0] ** 2 + l2[1] ** 2)
    if m == 0:
        return 0
    cos = (l1[0] * l2[0] + l1[1] * l2[1]) / m
    # print(cos)
    return math.acos(cos)


def window():
    # 函数对全局变量赋值,需要使用 global关键字
    global img
    global points

    while True:
        cv2.imshow(win_name, img)
        cv2.setMouseCallback(win_name, mouse_point)
        if (cv2.waitKey(1) & 0xFF) == ord("q"): # cv2.waitKey(1) & 0xFF 是为了截取低8位,不用也可以
            # 键盘输入 q时 保存当前图片以及刷新图片为初始图片
        # if cv2.waitKey(1) == ord("q"):
            points = []
            cv2.imwrite("measuring.jpg", img)
            # img = cv2.imread(img_path)  # 重新载入图片
            img = img_cp.copy()  # 重新载入图片


if __name__ == "__main__":
    window()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值