AI项目四:基于mediapipe的钢铁侠操作(虚拟拖拽)

news2024/11/14 10:23:17

若该文为原创文章,转载请注明原文出处。

一、介绍

在B站看到使用CVZone进行虚拟物体拖放,模仿钢铁侠电影里的程序操作!_哔哩哔哩_bilibili

是使用CVZone方式实现的,代码教程来源https://www.computervision.zone,感兴趣可以测试一下

 根据这个功能,用mediapipe实现了相同的效果。

 

二、实现流程

1、opencv 读取视频流

cap = cv2.VideoCapture(0)

2、通过mediapipe库获取手指关节坐标

hands = mp_hands.Hands(
    model_complexity=0,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5)
# 识别
results = hands.process(frame)
# 获取食指指尖坐标,坐标位置查看:https://google.github.io/mediapipe/solutions/hands

通过图可以看出,获取8点的坐标和12点的坐标
index_finger_x = int(x_list[8] * width)
index_finger_y = int(y_list[8] * height) 
# 获取中指坐标
middle_finger_x = int(x_list[12] * width)
middle_finger_y = int(y_list[12] * height)

3、计算两指距离

finger_distance = math.hypot((middle_finger_x - index_finger_x),(middle_finger_y - index_finger_y))

4、判断手指是否在方块上

if (index_finger_x > x1 and index_finger_x < (x1+w1)) and (index_finger_y > y1 and index_finger_y < (y1+h1)):

5、在视频上显示方块

cv2.rectangle(frame,(x1,y1),(x1+w1,y1+h1),square_color1,-1)
cv2.rectangle(frame, (x2, y2), (x2 + w2, y2 + h2), square_color1, -1)
cv2.rectangle(frame, (x3, y3), (x3 + w3, y3 + h3), square_color1, -1)
cv2.rectangle(frame, (x4, y4), (x4 + w4, y4 + h4), square_color1, -1)

流程基本就是,获取视频帧,识别手的关键点,获取食指和中指坐标,计算坐标差值,然后更新坐标显示。

三、代码

# 导入opencv
import cv2
import numpy as np
import math

# 导入mediapipe:https://google.github.io/mediapipe/solutions/hands
import mediapipe as mp

mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands

hands = mp_hands.Hands(
    model_complexity=0,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5)

# 读取视频流
cap = cv2.VideoCapture(0)

# 获取画面宽度、高度
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))


# 方块初始数组
x1 = 50
y1 = 50
w1 = 100
h1 = 100

x2 = 160
y2 = 50
w2 = 100
h2 = 100

x3 = 270
y3 = 50
w3 = 100
h3 = 100

x4 = 380
y4 = 50
w4 = 100
h4 = 100

L1 = 0
L2 = 0

on_square1 = False
square_color1 = (0,255,0)

on_square2 = False
on_square3 = False
on_square4 = False

while True:
    ret,frame = cap.read()

    # 镜像
    frame = cv2.flip(frame,1)

    frame.flags.writeable = False
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 识别
    results = hands.process(frame)

    frame.flags.writeable = True
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

    # 如果有结果
    if results.multi_hand_landmarks:

        # 遍历双手
        for hand_landmarks in results.multi_hand_landmarks:
            mp_drawing.draw_landmarks(
                frame,
                hand_landmarks,
                mp_hands.HAND_CONNECTIONS,
                mp_drawing_styles.get_default_hand_landmarks_style(),
                mp_drawing_styles.get_default_hand_connections_style())

            # 使用这两句看一下里面到底是什么?
            # print(type(hand_landmarks))
            # print(hand_landmarks)
            # exit()

            # 21 个关键点的x,y坐标列表
            x_list = []
            y_list = []
            for landmark in hand_landmarks.landmark:
                x_list.append(landmark.x)
                y_list.append(landmark.y)

            # 输出一下长度
            # print(len(x_list))

            # 获取食指指尖坐标,坐标位置查看:https://google.github.io/mediapipe/solutions/hands
            index_finger_x = int(x_list[8] * width)
            index_finger_y = int(y_list[8] * height)

            # 获取中指坐标
            middle_finger_x = int(x_list[12] * width)
            middle_finger_y = int(y_list[12] * height)

            # 计算两指距离
            # finger_distance =math.sqrt( (middle_finger_x - index_finger_x)**2 + (middle_finger_y-index_finger_y)**2)
            finger_distance = math.hypot((middle_finger_x - index_finger_x),(middle_finger_y - index_finger_y))

            # 看一下距离
            # print(finger_distance)

            # 把食指指尖画出来
            cv2.circle(frame,(index_finger_x,index_finger_y),20,(0,0,255),-1)


            # 判断食指指尖在不在方块上

            if finger_distance < 60:

                # X坐标范围 Y坐标范围
                if (index_finger_x > x1 and index_finger_x < (x1+w1)) and (index_finger_y > y1 and index_finger_y < (y1+h1)):
                    if on_square1 == False:
                        print('在')
                        L1 = index_finger_x - x1
                        L2 = index_finger_y - y1
                        square_color1 = (255,0,255)
                        on_square1 = True
                elif (index_finger_x > x2 and index_finger_x < (x2+w2)) and (index_finger_y > y2 and index_finger_y < (y2+h2)):
                    if on_square2 == False:
                        print('在')
                        L1 = index_finger_x - x2
                        L2 = index_finger_y - y2
                        square_color1 = (0,0,255)
                        on_square2 = True
                elif (index_finger_x > x3 and index_finger_x < (x3 + w3)) and (
                        index_finger_y > y3 and index_finger_y < (y3 + h3)):
                    if on_square3 == False:
                        print('在')
                        L1 = index_finger_x - x3
                        L2 = index_finger_y - y3
                        square_color1 = (0, 0, 255)
                        on_square3 = True
                elif (index_finger_x > x4 and index_finger_x < (x4 + w4)) and (
                        index_finger_y > y4 and index_finger_y < (y4 + h4)):
                    if on_square4 == False:
                        print('在')
                        L1 = index_finger_x - x4
                        L2 = index_finger_y - y4
                        square_color1 = (0, 255, 255)
                        on_square4 = True
                else:
                    print('不在')

            else:
                # 解除
                on_square1 = False
                square_color1 = (0,255,0)
                on_square2 = False
                on_square3 = False
                on_square4 = False

            # 更新坐标
            if on_square1:
                x1 = index_finger_x - L1
                y1 = index_finger_y - L2

            if on_square2:
                x2 = index_finger_x - L1
                y2 = index_finger_y - L2

            if on_square3:
                x3 = index_finger_x - L1
                y3 = index_finger_y - L2

            if on_square4:
                x4 = index_finger_x - L1
                y4 = index_finger_y - L2


    # 画一个正方形,需要实心
    # cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),-1)

    # 半透明处理
    overlay = frame.copy()
    cv2.rectangle(frame,(x1,y1),(x1+w1,y1+h1),square_color1,-1)
    cv2.rectangle(frame, (x2, y2), (x2 + w2, y2 + h2), square_color1, -1)
    cv2.rectangle(frame, (x3, y3), (x3 + w3, y3 + h3), square_color1, -1)
    cv2.rectangle(frame, (x4, y4), (x4 + w4, y4 + h4), square_color1, -1)
    frame = cv2.addWeighted(overlay, 0.5, frame, 1 - 0.5, 0)

    # 显示画面
    cv2.imshow('demo',frame)

    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()



代码相对简单,这里不作过多解析,如果有看不懂,可以自行去补充基础知识。

环境使用的是前篇搭建的mediapipe_env环境,请参考博客AI项目一:mediapipe测试_殷忆枫的博客-CSDN博客

如有侵权,或需要完整代码,请及时联系博主。

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

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

相关文章

MathType7.4mac最新版本数学公式编辑器安装教程

MathType7.4中文版是一款功能强大且易于使用的公式编辑器。该软件可与word软件配合使用&#xff0c;有效提高了教学人员的工作效率&#xff0c;避免了一些数学符号和公式无法在word中输入的麻烦。新版MathType7.4启用了全新的LOGO&#xff0c;带来了更多对数学符号和公式的支持…

全国自考02325《计算机系统结构》历年真题试卷及答案 年份:202304

2023 年4 月高等教育自学考试全国统一命题考试 计算机系统结构试题答案及评分参考 &#xff08;课程代码 02325) 一、选择题&#xff1a;本大题共 10小题&#xff0c;每小题1分 1.D 2.B 3.D 4.A 5.B 6.C 7.D 8.D 9. A 10.C 二、填空题&#xff1a;本大题共 10小题&#xff…

如何加入微信群?微信加群教程,如何加更多的群聊?

微信群是人们交流互动的重要平台之一&#xff0c;加入合适的微信群可以拓宽人脉、获取信息和分享经验。下面小编将分享三个方法&#xff0c;帮助你轻松加入心仪的微信群。 方法一&#xff1a;扫描二维码加入 很多微信群会设置专属的二维码&#xff0c;方便他人加入。当你得到某…

Linux操作系统--shell编程(条件判断)

(1).基本的语法 test condition [ condition ] 注意condition前后要有空格;在使用该种表达式的时候,条件非空即为 true,[ hello ]返回 true,[ ] 返回 false。我们可以通过echo $?来判断上一次执行的情况来判断真假(0真1假)。

详解预处理

全文目录 前言预定义符号#define 定义标识符常量#define 定义宏#define 替换规则# 宏参数转换字符串## 宏参数拼接带有副作用的宏参数 宏与函数的对比#undef 移出宏定义命令行定义条件编译#include 文件包含头文件的包含方式头文件的重复包含 前言 前面我们学习了程序的编译和…

【C语言基础】源文件与头文件详解

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

Office Tool Plus 使用与激活

Office Tool Plus 一个强大且实用的 Office 部署工具。 可以免费激活使用office各种版本 体验了一下&#xff0c;觉得很不错&#xff0c;我介绍一下我使用的方式&#xff1a; 1.安装软件 访问官网&#xff1a;Office Tool Plus 选择ZIP的包&#xff0c;下载后解压&#xff0c…

Huggingface托管机器学习模型及API提供

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我想在我的网络和移动应用程序中使用机器学习模型&#xff0c;但要做到这一点&#xff0c;我必须在某个地方托管我的机器学习应用程序。 托管预先训练的 ML 模型称为推理。 我只想添加一些 Python ML 代码并快速获得 REST…

一段简单的汇编语言源程序【2】

此文章主要记录代码的编写&#xff0c;编译&#xff0c;连接&#xff0c;调试过程&#xff0c;相关工具的安装和使用介绍在前面的文章中已提供。 主要功能通过栈实现两个数的交换 源代码如下&#xff1a; assume cs:codesg codesg segmentmov ax,2000Hmov ss,axmov sp,0add s…

国产发力,长存入局|相变存储器PCM是SCM的未来吗?

在去年7月份有一件震惊存储圈的事情&#xff0c;那就是Intel说要放弃Optane产品线&#xff0c;包括PMEM和SSD两个方向都要放弃。存储圈看到听到这个消息也是一脸的茫然。 在Optane产品发布之前&#xff0c;大家针对DRAM和SSD之间的性能gap一直在苦苦找寻合适的产品。SCM存储级内…

深度学习12:胶囊神经网络

目录 研究动机 CNN的缺陷 逆图形法 胶囊网络优点 胶囊网络缺点 研究内容 胶囊是什么 囊间动态路由算法 整体框架 编码器 损失函数 解码器 传统CNN存在着缺陷&#xff08;下面会详细说明&#xff09;&#xff0c;如何解决CNN的不足&#xff0c;Hinton提出了一种对于图…

一篇掌握BFD技术(二):OSPF与BFD联动配置

1. 实验目的 熟悉OSPF与BFD联动的应用场景掌握OSPF与BFD联动的配置方法 想要华为数通配套实验拓扑和配置笔记的朋友们点赞关注&#xff0c;评论区留下邮箱发给你&#xff01; 2. 实验拓扑 3. 实验步骤 1&#xff09;IP地址的配置 AR1的配置 <Huawei>system-view…

Origin软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Origin是一款专业的科学绘图和数据分析软件&#xff0c;由美国OriginLab公司开发。它提供了丰富的数据分析和绘图工具&#xff0c;适用于各种科学领域&#xff0c;如生物学、化学、物理学、医学、地球科学等。Origin软件的主要特…

使用 S3 生命周期精确管理对象生命周期

在亚马逊工作这些年,我发现 S3 的生命周期配置是管理对象生命周期的重要但复杂的工具。在这篇文章中,我将利用实战经验,深入剖析生命周期,从核心概念到实际应用。 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活…

C语言暑假刷题冲刺篇——day5

目录 一、选择题 二、编程题 &#x1f388;个人主页&#xff1a;库库的里昂 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏✨收录专栏&#xff1a;C语言每日一练✨相关专栏&#xff1a;代码小游戏、C语言初阶、C语言进阶&#x1f91d;希望作者…

程序的编译链接【编译链接大概步骤】

全文目录 &#x1f600; 前言&#x1f642; 翻译环境和执行环境&#x1f636; 编译和链接&#x1f635;‍&#x1f4ab; 预编译&#xff08;预处理&#xff09;&#x1f635;‍&#x1f4ab; 编译&#x1f635;‍&#x1f4ab; 汇编&#x1f635;‍&#x1f4ab; 链接 &#x1…

数值类特征

数值类特征 数值类特征是最常见的一种特征类型&#xff0c;数值可以直接喂给算法。 为了提升效果&#xff0c;我们需要对数值特征做一些处理&#xff0c;本文介绍了4种常见的处理方式&#xff1a;缺失值处理、二值化、分桶、缩放。 什么是数值类特征&#xff1f; 数值类特征就是…

腾讯云服务器地域和可用区详细介绍_选择攻略

腾讯云服务器地域有什么区别&#xff1f;怎么选择比较好&#xff1f;地域选择就近原则&#xff0c;距离地域越近网络延迟越低&#xff0c;速度越快。关于地域的选择还有很多因素&#xff0c;地域节点选择还要考虑到网络延迟速度方面、内网连接、是否需要备案、不同地域价格因素…

Redis数据类型全总结【超详细万字总结】

文章目录 前言一、String1、内部实现2、应用场景缓存对象常规计数分布式锁共享 Session 信息 3、常用指令 二、List1、内部实现2、应用场景消息队列List 作为消息队列有什么缺陷 3、常用指令 三、Hash1、内部实现2、应用场景缓存对象购物车 3、常用指令 四、Set1、内部实现2、应…

Linux学习之LNMP环境搭建

LNMP是Linux、Nginx、MySQL和PHP的简称。 Linux参数显示 cat /etc/redhat-release看到操作系统是CentOS Linux release 7.6.1810&#xff0c;uname -r看到内核版本是3.10.0-957.el7.x86_64。 nginx安装 可以参考《Linux学习之CentOS 7源码安装openresty》 安装mariadb数据…