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博客

相关文章
|
25天前
|
人工智能 测试技术 API
AI计算机视觉笔记二十 九:yolov10竹签模型,自动数竹签
本文介绍了如何在AutoDL平台上搭建YOLOv10环境并进行竹签检测与计数。首先从官网下载YOLOv10源码并创建虚拟环境,安装依赖库。接着通过官方模型测试环境是否正常工作。然后下载自定义数据集并配置`mycoco128.yaml`文件,使用`yolo detect train`命令或Python代码进行训练。最后,通过命令行或API调用测试训练结果,并展示竹签计数功能。如需转载,请注明原文出处。
|
25天前
|
机器学习/深度学习 人工智能 PyTorch
AI计算机视觉笔记三十二:LPRNet车牌识别
LPRNet是一种基于Pytorch的高性能、轻量级车牌识别框架,适用于中国及其他国家的车牌识别。该网络无需对字符进行预分割,采用端到端的轻量化设计,结合了squeezenet和inception的思想。其创新点在于去除了RNN,仅使用CNN与CTC Loss,并通过特定的卷积模块提取上下文信息。环境配置包括使用CPU开发板和Autodl训练环境。训练和测试过程需搭建虚拟环境并安装相关依赖,执行训练和测试脚本时可能遇到若干错误,需相应调整代码以确保正确运行。使用官方模型可获得较高的识别准确率,自行训练时建议增加训练轮数以提升效果。
|
25天前
|
人工智能 开发工具 计算机视觉
AI计算机视觉笔记三十:yolov8_obb旋转框训练
本文介绍了如何使用AUTODL环境搭建YOLOv8-obb的训练流程。首先创建虚拟环境并激活,然后通过指定清华源安装ultralytics库。接着下载YOLOv8源码,并使用指定命令开始训练,过程中可能会下载yolov8n.pt文件。训练完成后,可使用相应命令进行预测测试。
|
25天前
|
人工智能 并行计算 测试技术
AI计算机视觉笔记三十一:基于UNetMultiLane的多车道线等识别
该项目基于开源数据集 VIL100 实现了 UNetMultiLane,用于多车道线及车道线类型的识别。数据集中标注了六个车道的车道线及其类型。项目详细记录了从环境搭建到模型训练与测试的全过程,并提供了在 CPU 上进行训练和 ONNX 转换的代码示例。训练过程约需 4 小时完成 50 个 epoch。此外,还实现了视频检测功能,可在视频中实时识别车道线及其类型。
|
5月前
|
机器学习/深度学习 计算机视觉
AIGC核心技术——计算机视觉(CV)预训练大模型
【1月更文挑战第13天】AIGC核心技术——计算机视觉(CV)预训练大模型
558 3
AIGC核心技术——计算机视觉(CV)预训练大模型
|
10月前
|
机器学习/深度学习 PyTorch 算法框架/工具
Azure 机器学习 - 使用 ONNX 对来自 AutoML 的计算机视觉模型进行预测
Azure 机器学习 - 使用 ONNX 对来自 AutoML 的计算机视觉模型进行预测
112 0
|
25天前
|
人工智能 测试技术 PyTorch
AI计算机视觉笔记二十四:YOLOP 训练+测试+模型评估
本文介绍了通过正点原子的ATK-3568了解并实现YOLOP(You Only Look Once for Panoptic Driving Perception)的过程,包括训练、测试、转换为ONNX格式及在ONNX Runtime上的部署。YOLOP由华中科技大学团队于2021年发布,可在Jetson TX2上达到23FPS,实现了目标检测、可行驶区域分割和车道线检测的多任务学习。文章详细记录了环境搭建、训练数据准备、模型转换和测试等步骤,并解决了ONNX转换过程中的问题。
|
3月前
|
自然语言处理 监控 自动驾驶
大模型在自然语言处理(NLP)、计算机视觉(CV)和多模态模型等领域应用最广
【7月更文挑战第26天】大模型在自然语言处理(NLP)、计算机视觉(CV)和多模态模型等领域应用最广
73 11
|
4月前
|
编解码 机器人 测试技术
2024年6月计算机视觉论文推荐:扩散模型、视觉语言模型、视频生成等
6月还有一周就要结束了,我们今天来总结2024年6月上半月发表的最重要的论文,重点介绍了计算机视觉领域的最新研究和进展。
121 8
|
5月前
|
机器学习/深度学习 编解码 人工智能
Vision Mamba:将Mamba应用于计算机视觉任务的新模型
Mamba是LLM的一种新架构,与Transformers等传统模型相比,它能够更有效地处理长序列。就像VIT一样现在已经有人将他应用到了计算机视觉领域,让我们来看看最近的这篇论文“Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Models,”
509 7

热门文章

最新文章

下一篇
无影云桌面