【CV】计算两个向量的夹角,并使用 OpenCV 可视化弧线

news2025/1/19 14:31:10

背景

基于人体/动物,骨骼点数据,计算关节角度

1. 原理

计算两个向量的夹角,我们已三个点为例,BA 向量和BC向量,求 B 的角度。若为四个点,延长交叉即可。
在这里插入图片描述

2. 效果

效果图如下

请添加图片描述

3. 核心代码

def compute_vector_angle(a, b, c):
    """
    计算两个向量 ba 和 bc 向量的夹角
    @params a , 点 a
    @params b , 点 b
    @params c , 点 c
    """
    # 我这里为了好理解使用三个点数据,也可以用四个点
    triangle_data = [a, b, c]
    # 向量夹角
    ba_angle = math.atan2(a[1] - b[1], a[0] - b[0]) * 180 / math.pi
    bc_angle = math.atan2(c[1] - b[1], c[0] - b[0]) * 180 / math.pi
    b_angle = 0
    if ba_angle * bc_angle >= 0:
        # 第1,4象限
        b_angle = abs(ba_angle - bc_angle)
    else:
        # 第2,3象限
        b_angle = abs(ba_angle) + abs(bc_angle)
        if b_angle > 180:
            b_angle = 360 - b_angle
    print("\nba_angle:", ba_angle, "bc_angle:", bc_angle, "angle:", b_angle)
    start_angle = ba_angle
    end_angle = bc_angle
    return start_angle, end_angle, b_angle, triangle_data

4. 可视化

图像可视化,坐标和圆的坐标系如下,

  • 坐标系,相反
  • 圆坐标系,逆时针,如图所示
    在这里插入图片描述

5. 全部代码

实现 Python 代码,可直接执行,C++ 同理实现

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

"""
@Create  :   2024/01/09 15:03:33
@Author  :   Yuan Mingzhuo
"""

import numpy as np
import cv2
import math


def compute_vector_angle(a, b, c):
    """
    计算两个向量 ba 和 bc 向量的夹角
    @params a , 点 a
    @params b , 点 b
    @params c , 点 c
    """
    # 我这里为了好理解使用三个点数据,也可以用四个点
    triangle_data = [a, b, c]
    # 向量夹角
    ba_angle = math.atan2(a[1] - b[1], a[0] - b[0]) * 180 / math.pi
    bc_angle = math.atan2(c[1] - b[1], c[0] - b[0]) * 180 / math.pi
    b_angle = 0
    if ba_angle * bc_angle >= 0:
        # 第1,4象限
        b_angle = abs(ba_angle - bc_angle)
    else:
        # 第2,3象限
        b_angle = abs(ba_angle) + abs(bc_angle)
        if b_angle > 180:
            b_angle = 360 - b_angle
    print("\nba_angle:", ba_angle, "bc_angle:", bc_angle, "angle:", b_angle)
    start_angle = ba_angle
    end_angle = bc_angle
    return start_angle, end_angle, b_angle, triangle_data


def draw_image_vector_angle(image, triangle_data, start_angle, end_angle, angle):
    """
    可视化显示
    @params image , 图
    @params triangle_data , 向量点数据
    @start_angle , ba 向量角度
    @end_angle   , bc 向量角度
    @angle       , ba 与 bc 向量夹角
    """
    # 点
    point_a = (int(triangle_data[0][0]), int(triangle_data[0][1]))
    point_b = (int(triangle_data[1][0]), int(triangle_data[1][1]))
    point_c = (int(triangle_data[2][0]), int(triangle_data[2][1]))
    for point in triangle_data:
        cv2.circle(
            img=image,
            center=(int(point[0]), int(point[1])),
            radius=2,
            color=(255, 255, 255),
            thickness=1,
            lineType=cv2.LINE_AA,
        )
    # 线
    lines = [(point_b, point_a), (point_b, point_c), (point_a, point_c)]
    for line in lines:
        cv2.line(
            img=image,
            pt1=line[0],
            pt2=line[1],
            color=(0, 0, 255),
            thickness=1,
            lineType=cv2.LINE_AA,
        )
    # 弧线
    startAngle = start_angle
    endAngle = end_angle
    if start_angle * end_angle < 0:
        angle_data = abs(start_angle) + abs(end_angle)
        if angle_data > 180:
            # 取反弧度结束角
            if end_angle > 0:
                endAngle = end_angle - 360
            else:
                endAngle = end_angle + 360

    print("DRAW : ", "startAngle", startAngle, "endAngle", endAngle)
    cv2.ellipse(
        img=image,
        center=point_b,
        axes=(16, 16),
        angle=360,
        startAngle=startAngle,
        endAngle=endAngle,
        color=(255, 255, 255),
        thickness=1,
        lineType=cv2.LINE_AA,
    )
    # 角 B
    angle_b_point = [
        int(((point_a[0] + point_b[0] + point_c[0]) / 3)),
        int(((point_a[1] + point_b[1] + point_c[1]) / 3)),
    ]
    cv2.putText(
        img=image,
        text=f"{int(abs(angle))}",
        org=angle_b_point,
        fontFace=cv2.FONT_HERSHEY_SIMPLEX,
        fontScale=0.3,
        color=(200, 200, 200),
        thickness=1,
        lineType=cv2.LINE_AA,
    )
    return image


if __name__ == "__main__":
    """
    可视化测试
    """
    # 测试点
    a, b, c = (70, 100), (100, 150), (170, 70)
    # 图像
    image = np.full((300, 300, 3), 0, dtype=np.uint8)
    # 计算
    start_angle, end_angle, angle, triangle_data = compute_vector_angle(a, b, c)
    # 绘制
    image = draw_image_vector_angle(
        image=image,
        triangle_data=triangle_data,
        start_angle=start_angle,
        end_angle=end_angle,
        angle=angle,
    )
    # 显示
    cv2.imshow("test", image)
    cv2.waitKey(3000)

6. 应用

骨骼点角度计算和可视化

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1370296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue2源码解析之第一步(对数据进行劫持)

###环境搭建 第一步 创建项目&#xff1a; npm init -y 第二步 安装对应的插件&#xff1a; npm i rollup rollup-plugin-babel babel/core babel/preset-env --save-dev 第三步 全局下创建rollup配置文件 rollup.config.js import babel from rollup-plug…

JVM工作原理与实战(十一):双亲委派机制

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、双亲委派机制 1.双亲委派机制详解 2.父类加载器 3.双亲委派机制的主要作用 二、双亲委派机制常见问题 总结 前言 ​JVM作为Java程序的运行环境&#xff0c;其负责解释和执行字…

CDN的介绍以及加速内容传输原理

目前在公司的开发过程中&#xff0c;发现很多存储在oss的静态资源&#xff08;图片&#xff0c;安装包&#xff09;的链接中域名都使用了cdn域名&#xff0c;后面了解到这个cdn域名的主要作用是加速资源的访问&#xff0c;于是抽空了解了一下CDN加速原理。 目前使用得比较多的是…

【大厂算法面试冲刺班】day0:数据范围反推时间复杂度

常见算法的时间复杂度 规定n是数组的长度/树或图的节点数 二分查找&#xff1a;O(logn) 双指针/滑动窗口&#xff1a;O(n) DFS/BFS&#xff1a;O(n) 构建前缀和&#xff1a;O(n) 查找前缀和&#xff1a;O(1) 一维动态规划&#xff1a;O(n) 二维动态规划&#xff1a;O(n^2) 回溯…

Java后端返回的MySQL日期数据在前端格式错误的解决方法,区分jackson和fastjson

写在前面 在写web项目的时候经常会遇到后端返回的MySQL日期数据(date)类型在前端显示不正确的情况&#xff0c;有的时候会出现一串数字的时间戳&#xff0c;有的时候显示为日期晚了一天。 这是因Json给前端返回数据的时候格式问题造成的 解决方法 其实总结起来就是一句话在…

【Docker】私有仓库

目录 1.搭建 2. 上传镜像 3.拉取镜像 1.搭建 1.拉取私有仓库的镜像 docker pull registry 2.创建私有仓库容器 docker run -id --nameregistry -p 5000:5000 registry 3.打开浏览器,输入地址&#xff08;http:私有仓库服务器ip:5000/v2/_catalog&#xff09; 出现如图表示私…

Python - 深夜数据结构与算法之 Two-Ended BFS

目录 一.引言 二.双向 BFS 简介 1.双向遍历示例 2.搜索模版回顾 三.经典算法实战 1.Word-Ladder [127] 2.Min-Gen-Mutation [433] 四.总结 一.引言 DFS、BFS 是常见的初级搜索方式&#xff0c;为了提高搜索效率&#xff0c;衍生了剪枝、双向 BFS 以及 A* 即启发式搜索…

1.1数算选择题(循环队列、二叉树、查找、堆、顺序表、生成树、哈夫曼树、排序)

循环队列 front&#xff1a;头指针 rear&#xff1a;尾指针 m&#xff1a;循环队列的长度 元素个数&#xff08;rear-frontm&#xff09;%m 19-114048%408 11-194032%4032 二叉树 入度出度&#xff0c;n-1n0n1n2-1n12n2,有n21n0,对于完全二叉树&#xff0c;度为1的节点要…

挑战Transformer的新架构Mamba解析以及Pytorch复现

今天我们来详细研究这篇论文“Mamba:具有选择性状态空间的线性时间序列建模” Mamba一直在人工智能界掀起波澜&#xff0c;被吹捧为Transformer的潜在竞争对手。到底是什么让Mamba在拥挤的序列建中脱颖而出? 在介绍之前先简要回顾一下现有的模型 Transformer:以其注意力机制而…

重学JavaScript高级(八):ES6-ES12新增特性学习

ES6-ES12新增特性学习 ES6–对象字面量增强 属性的简写方法的简写计算属性名 let name "zhangcheng" //我想让sum作为obj的key值 let objKey "sum" let obj {//属性名的简写name//等同于name:name//方法的简写running(){}//等同于running:function()…

RT-DETR 更换骨干网络之 MobileNetV3 | 《搜寻 MobileNetV3》

论文地址:https://arxiv.org/abs/1905.02244 代码地址:https://github.com/xiaolai-sqlai/mobilenetv3 我们展示了基于互补搜索技术和新颖架构设计相结合的下一代 MobileNets。MobileNetV3通过结合硬件感知网络架构搜索(NAS)和 NetAdapt算法对移动设计如何协同工作,利用互…

使用 Open3D 的 3D LiDAR 可视化:用于自动驾驶的 2D KITTI 深度框架-含数据集+源码

3D LiDAR传感器(或)3维 光探测和测距是一种先进的发光仪器,能够像我们人类一样在3维空间中感知现实世界。这项技术尤其彻底改变了地球观测、环境监测、侦察以及现在的自动驾驶领域。它提供准确和详细数据的能力有助于增进我们对环境和自然资源的理解和管理。 在这篇权威研究…

仿stackoverflow名片与b站名片实现(HTML、CSS)

目录 前言一、仿stackoverflow名片HTMLCSS 二、仿b站名片HTMLCSS 素材 前言 学习自ACwing - Web应用课 一、仿stackoverflow名片 HTML <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport&…

【hyperledger-fabric】使用couchDB

简介 本文章主要参考来自于官方文档使用CouchDB以及 https://www.bilibili.com/video/BV1Li4y1f7ex/?spm_id_frompageDriver&vd_source2c5f2831e1c63d3a20045b167ae044e6 B站视频&#xff0c;还是非常感谢up主提供了学习的思路。 为什么要使用couchDB&#xff1f; 原文…

如何将Redis、Zookeeper、Nacos配置为Windows系统的一个服务

说明&#xff1a;当我们在Windows上开发时&#xff0c;不可避免的会用到一些中间件&#xff0c;如Redis、Zookeeper、Nacos等等&#xff0c;当在项目中使用到本地的这些服务器时&#xff0c;我们需要把本地的服务器启动&#xff0c;会开启下面这样的一个窗口。 Redis服务器&am…

vscode使用npm安装element-UI并添加router路由

npm安装vue&#xff0c;添加淘宝镜像-CSDN博客 elementUI安装与配置 安装可以看我上一篇文章 vscode控制台输入指令 npm i element-ui -S 安装完成后在目录结构打开下图文件 可以看到多了一行elementui就代表安装成功了 下面是项目常用的结构 安装完成后需要启用elementU…

稀疏矩阵的三元组表示----(算法详解)

目录 基本算法包括&#xff1a;&#xff08;解释都在代码里&#xff09; 1.创建 2.对三元组元素赋值 3.将三元组元素赋值给变量 4.输出三元组 5.转置&#xff08;附加的有兴趣可以看看&#xff09; 稀疏矩阵的概念&#xff1a;矩阵的非零元素相较零元素非常小时&#xff…

自承载 Self-Host ASP.NET Web API 1 (C#)

本教程介绍如何在控制台应用程序中托管 Web API。 ASP.NET Web API不需要 IIS。 可以在自己的主机进程中自托管 Web API。 创建控制台应用程序项目 启动 Visual Studio&#xff0c;然后从“开始”页中选择“新建项目”。 或者&#xff0c;从“ 文件 ”菜单中选择“ 新建 ”&a…

了解VR虚拟现实的沉浸式效果及其技术特点!

VR虚拟现实体验装置作为近年来人气火爆的科技产品&#xff0c;以其独特的沉浸式体验效果吸引了众多用户&#xff0c;那么&#xff0c;你知道这种VR体验装置是如何实现沉浸式体验效果的吗&#xff1f;它又具备了哪些技术特点呢&#xff1f; 一、真实的场景体验 VR虚拟现实技术通…

html的全选反选

一、实验题目 html实现选择框的全选和反选 二、实验代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>全选和反选</title></head><body><ul>兴趣爱好</ul><input id"all"…