【OpenCV 实战】1.手势虚拟拖拽(双手骨骼点识别)

step:
1.opencv 获取视频流
2.在画面上画一个方块
3.通过mediapipe获取手指关键点坐标
4.判断手指是否在方块上
5.若在方块上,方块跟着手指移动
 

mediapipe网站介绍:Hands - mediapipe (chuoling.github.io)

已上传到GitHub : plumqm/OpenCV-project: 通过20个项目学习计算机视觉(Learn computer vision through 20 projects) (github.com)

"""
author = qian
date = 2024-10-07

step:
1.opencv 获取视频流
2.在画面上画一个方块
3.通过mediapipe获取手指关键点坐标
4.判断手指是否在方块上
5.若在方块上,方块跟着手指移动

"""

import cv2
import numpy as np

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(
    static_image_mode=True,
    max_num_hands=2,
    min_detection_confidence=0.5)

# 1.opencv 获取视频流
cap = cv2.VideoCapture(0)

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

# 方块相关参数
square_x = 100
square_y = 100
square_width = 100
square_color = (255,0,0)
L1 = 0
L2 = 0
on_square = False

while True:

    # 读取每一帧
    ret, frame = cap.read()

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

    # mediapipe处理
    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:

            # 绘制21个关键点
            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())

        # 保存21个x,y坐标
        x_list = [landmark.x for landmark in hand_landmarks.landmark]
        y_list = [landmark.y for landmark in hand_landmarks.landmark]

        # 获取食指指尖
        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_len = np.sqrt((middle_finger_X - index_finger_X)**2 + (middle_finger_Y - index_finger_Y)**2)

        # cv2.circle(frame, (index_finger_X,index_finger_Y)
        # ,20 ,(255,0,255) ,-1)

        # 手指是否在方块上
        if square_x <= x_list[4] <= square_x + square_width and square_y <= y_list[4] <= square_y + square_width:
            square_x += (x_list[4] - square_x) / 10
            square_y += (y_list[4] - square_y) / 10

        # 如果距离小于30算激活
        if finger_len < 30:
            # 判断食指指尖在不在方块上
            if (square_x <= index_finger_X <= square_x + square_width and square_y <= index_finger_Y <= square_y + square_width):
                if on_square == False :
                    L1 = abs(index_finger_X - square_x)
                    L2 = abs(index_finger_Y - square_y)
                    on_square = True
                    square_color = (255,0,255)
            else :
                pass

            if on_square == True:
                square_x = index_finger_X - L1
                square_y = index_finger_Y - L2

        else :
            on_square = False
            square_color = (255,0,0)

    # 2. 在画面上画一个方块
    # cv2.rectangle(frame, (square_x, square_y), (square_x+square_width, square_y+square_width), (255, 0, 0), -1)

    # 画半透明方块
    overlay = frame.copy()
    cv2.rectangle(frame, (square_x, square_y), 
    (square_x+square_width, square_y+square_width), 
    square_color, -1)

    frame = cv2.addWeighted(overlay,0.5,frame,0.5,0)
    # 显示
    cv2.imshow('Virtual drag', frame)

    if cv2.waitKey(10) & 0xFF == 27:
        break 

cap.release()
cv2.destroyAllWindows()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值