Python项目||AI虚拟拖拽演示

项目简介

本项目利用OpenCV和MediaPipe库实现了一个简单的虚拟拖拽演示。通过摄像头捕获手部动作,用户可以通过手指在空中的移动来控制一个方块的位置,从而实现虚拟拖拽的效果。

项目特点

  • 实时性:
    使用OpenCV读取摄像头视频流,实时捕获手部动作,方便用户实时交互。
  • 简单易用: 通过简单的手势,即可实现方块的拖拽,无需额外设备或复杂的操作。
  • 灵活性:
    用户可以根据需要对项目进行功能扩展,如添加更多手势识别、改变方块的形状或颜色等。

实现步骤:

(1)使用OpenCV读取摄像头视频流。
(2)在视频图像上绘制一个方块。
(3)使用MediaPipe库获取手指关节坐标。
(4)判断手指是否在方块上,若是,则方块跟随手指移动。
(5)通过食指和中指指尖距离确定是否激活移动。
(6)在画面显示FPS等信息,提升用户体验。

使用技术:

  • OpenCV: 用于读取摄像头视频流、图像处理和显示。
  • MediaPipe: 提供手部关键点检测功能,用于捕获手部动作。
    适用场景:

教学演示: 可用于展示手部姿势识别和实时交互技术。
产品展示: 可用于展示虚拟拖拽功能,吸引用户关注。
科研探索: 可用于研究手部动作识别和交互技术的实验验证。

项目用途:

教学示例: 可作为深度学习和计算机视觉教学的案例之一,帮助学生理解手部动作识别和交互技术。
科研实验: 可用于验证手部动作识别算法的准确性和实时性,为科研工作者提供实验数据。
娱乐应用: 可作为娱乐应用的基础功能,如虚拟现实游戏中的手部交互等。

使用说明:

运行项目代码,启动摄像头。
根据屏幕中的方块位置,通过手部动作控制方块的移动。
可根据需要进行功能扩展和修改,实现更多交互效果。

项目演示链接:AI虚拟拖拽演示

案例代码:

"""
演示一个简单的虚拟拖拽
步骤:
1、opencv 读取视频流
2、在视频图像上画一个方块
3、通过mediapipe库获取手指关节坐标
4、判断手指是否在方块上
5、是,方块跟着移动
6、完善:通过食指和中指指尖距离确定是否激活移动
7、完善:画面显示FPS等信息
"""

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

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

# 初始化mediapipe的手部检测模块
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))


# 方块初始数组
x = 100
y = 100
w = 200
h = 200

# 初始化手指距离变量
L1 = 0
L2 = 0

# 标记方块是否被按住
on_square = False
# 初始化方块颜色,为绿色
square_color = (0, 255, 0)

# 主循环
while True:
    # 读取一帧
    ret,frame = cap.read()
    # 镜像处理
    frame = cv2.flip(frame,1)
    # 预处理帧,准备进行手部检测
    frame.flags.writeable = False
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)   # BGR-> RGB    
    # 进行手部检测,需要RGB格式的图像
    results = hands.process(frame)
    # 还原帧为可写状态,并进行颜色转换为BGR格式
    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), 10, (0,0,255),-1)

            
            # 判断食指指尖在不在方块上
            if finger_distance < 60:

                # 判断食指指尖坐标是否在方块的X坐标范围 Y坐标范围内
                if (index_finger_x > x and index_finger_x < (x+w)) and (index_finger_y > y and index_finger_y < (y+h)):
                    print('~食指指尖在方块区域内~')
                    # 方块原始颜色未改变,则激活
                    if on_square == False:    
                        L1 = index_finger_x - x      # > 0 < L1 < 200
                        L2 = index_finger_y - y      # > 0 < L2 < 200
                        square_color = (255, 0, 255)
                        on_square = True
                else:
                    print('~食指指尖不在方块区域内~')
            # 食指与中指夹距离大于60,则方块颜色不改变
            else:
                # 解除
                on_square = False
                square_color = (0,255,0)

            # 更新坐标
            if on_square:
                x = index_finger_x - L1      # 方块的左上角坐标随着食指手指移动
                y = index_finger_y - L2      # 方块的左上角坐标随着食指手指移动

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

    # 半透明处理
    overlay = frame.copy()
    cv2.rectangle(frame,(x,y),(x+w,y+h),square_color,-1)
    frame = cv2.addWeighted(overlay, 0.5, frame, 1 - 0.5, 0)
    
    
    
    # 显示画面
    cv2.imshow('demo',frame)

    if cv2.waitKey(10) & 0xFF == 27 :   # 按esc 退出
        break

cap.release()
cv2.destroyAllWindows()





注意事项:
本项目仅为演示用途,未经过完整测试和优化,可能存在一定的局限性和不足之处。
如需商业应用或其他用途,请谨慎使用并自行承担风险。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_763061740

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值