AI计算机视觉笔记九:基于mediapipe的钢铁侠操作(虚拟拖拽)

简介: 这段代码演示了如何使用OpenCV和MediaPipe库在视频流中实现虚拟物体的拖放功能,模拟了类似钢铁侠电影中的高科技操作界面。具体步骤包括读取视频流、获取手指关键点坐标、计算手指间距离,并判断食指是否位于虚拟方块内。如果手指位于方块内,则更新方块的位置,实现拖放效果。代码提供了详细的实现过程,包括关键点识别、坐标计算及方块绘制等。此外,还提供了半透明效果处理,使视觉效果更加逼真。整个项目基于Mediapipe环境搭建,适合初学者学习计算机视觉应用开发。

一、介绍

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

是使用CVZone方式实现的,代码教程来源https://www.computervision.zone,感兴趣可以测试一下
image.png
根据这个功能,用mediapipe实现了相同的效果。
image.png

二、实现流程

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

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

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

相关文章
|
2月前
|
人工智能 测试技术 API
AI计算机视觉笔记二十 九:yolov10竹签模型,自动数竹签
本文介绍了如何在AutoDL平台上搭建YOLOv10环境并进行竹签检测与计数。首先从官网下载YOLOv10源码并创建虚拟环境,安装依赖库。接着通过官方模型测试环境是否正常工作。然后下载自定义数据集并配置`mycoco128.yaml`文件,使用`yolo detect train`命令或Python代码进行训练。最后,通过命令行或API调用测试训练结果,并展示竹签计数功能。如需转载,请注明原文出处。
|
26天前
|
机器学习/深度学习 人工智能 算法
打造你的超级Agent智能体——在虚拟迷宫中智斗未知,解锁AI进化之谜的惊心动魄之旅!
【10月更文挑战第5天】本文介绍了一个基于强化学习的Agent智能体项目实战,通过控制Agent在迷宫环境中找到出口来完成特定任务。文章详细描述了环境定义、Agent行为及Q-learning算法的实现。使用Python和OpenAI Gym框架搭建迷宫环境,并通过训练得到的Q-table测试Agent表现。此项目展示了构建智能体的基本要素,适合初学者理解Agent概念及其实现方法。
71 9
|
2月前
|
机器学习/深度学习 人工智能 PyTorch
AI计算机视觉笔记三十二:LPRNet车牌识别
LPRNet是一种基于Pytorch的高性能、轻量级车牌识别框架,适用于中国及其他国家的车牌识别。该网络无需对字符进行预分割,采用端到端的轻量化设计,结合了squeezenet和inception的思想。其创新点在于去除了RNN,仅使用CNN与CTC Loss,并通过特定的卷积模块提取上下文信息。环境配置包括使用CPU开发板和Autodl训练环境。训练和测试过程需搭建虚拟环境并安装相关依赖,执行训练和测试脚本时可能遇到若干错误,需相应调整代码以确保正确运行。使用官方模型可获得较高的识别准确率,自行训练时建议增加训练轮数以提升效果。
|
2月前
|
人工智能 开发工具 计算机视觉
AI计算机视觉笔记三十:yolov8_obb旋转框训练
本文介绍了如何使用AUTODL环境搭建YOLOv8-obb的训练流程。首先创建虚拟环境并激活,然后通过指定清华源安装ultralytics库。接着下载YOLOv8源码,并使用指定命令开始训练,过程中可能会下载yolov8n.pt文件。训练完成后,可使用相应命令进行预测测试。
|
2月前
|
人工智能 并行计算 测试技术
AI计算机视觉笔记三十一:基于UNetMultiLane的多车道线等识别
该项目基于开源数据集 VIL100 实现了 UNetMultiLane,用于多车道线及车道线类型的识别。数据集中标注了六个车道的车道线及其类型。项目详细记录了从环境搭建到模型训练与测试的全过程,并提供了在 CPU 上进行训练和 ONNX 转换的代码示例。训练过程约需 4 小时完成 50 个 epoch。此外,还实现了视频检测功能,可在视频中实时识别车道线及其类型。
|
机器学习/深度学习 人工智能 自然语言处理
欧洲科学院院士:中国领先计算机视觉和机器人领域,但AI研究还不足以支撑垂直领域解决方案
如何构建一家伟大的人工智能研究机构?深度学习在自然语言处理方面有怎样的发展?中美欧人工智能市场和技术发展差异?德国人工智能研究中心(DFKI)科学董事,北京深知无限人工智能研究院(AITC)院长兼首席科学家汉斯·乌思克尔特(Hans Uszkoreit)教授,在新智元AI技术峰会上,分享了他的精彩见解。
1561 0
|
4天前
|
机器学习/深度学习 数据采集 人工智能
AI赋能教育:深度学习在个性化学习系统中的应用
【10月更文挑战第26天】随着人工智能的发展,深度学习技术正逐步应用于教育领域,特别是个性化学习系统中。通过分析学生的学习数据,深度学习模型能够精准预测学生的学习表现,并为其推荐合适的学习资源和规划学习路径,从而提供更加高效、有趣和个性化的学习体验。
37 8
|
3天前
|
人工智能 JSON API
阿里云文档智能 & RAG解决方案:提升AI大模型业务理解与应用
阿里云推出的文档智能 & RAG解决方案,旨在通过先进的文档解析技术和检索增强生成(RAG)方法,显著提升人工智能大模型在业务场景中的应用效果。该方案通过文档智能(Document Mind)技术将非结构化文档内容转换为结构化数据,提取文档的层级树、样式和版面信息,并输出为Markdown和Json格式,为RAG提供语义分块策略。这一过程不仅解决了文档内容解析错误和切块丢失语义信息的问题,还优化了输出LLM友好的Markdown信息。方案的优势在于其多格式支持能力,能够处理包括Office文档、PDF、Html、图片在内的主流文件类型,返回文档的样式、版面信息和层级树结构。
23 2
|
3天前
|
人工智能 搜索推荐 安全
AI技术在医疗领域的应用与挑战
【10月更文挑战第27天】 本文探讨了人工智能(AI)在医疗领域的应用,包括疾病诊断、药物研发和患者管理等方面。同时,也分析了AI在医疗领域面临的挑战,如数据隐私、伦理问题和技术局限性等。通过对这些方面的深入分析,我们可以更好地理解AI在医疗领域的潜力和发展方向。
93 59
|
3天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用

热门文章

最新文章