python[mediapipe]视觉之戒指随手移动

本文介绍了一位博主利用Mediapipe库创建的手势识别程序,该程序能识别左右手并追踪手指位置。通过右手拇指与食指的距离控制虚拟戒指在屏幕上的移动,而左手中指则可以穿过戒指。虽然目前程序仅实现了一维移动,作者计划通过更复杂的算法来解决戒指形状匹配手部姿势的问题。
摘要由CSDN通过智能技术生成

前几天看见一位博主用mediapipe写的拖动方块,于是我就有了写一个这个代码的想法,我原本要实现的功能是一只手给另一只手带上,但是随着我对里面函数的探索,我发现有点难实现,因为他results.multi_handedness里面可以知道左右手,但是点位在hand_landmarks.landmark这个里面,hand_landmarks.landmark不管你是左手还是右手,只要是手就往里面加点。于是戴戒指这个功能我就分成了两部分,右手拇指和食指达到一定距离后可以移动,左手的中指三个点位分别穿过戒指后,戒指就随左手中指的10号点位移动。

手的点位图:

这个程序目前只可以做到戒指的一维移动,也就是说戒指还只是图片,他只能保持原有的状态直线运动,当手竖起来的时候戒指的形状和手就不匹配了,这就需要通过其他算法完成了,我目前的水平还做不到。

这是戒指图片:

由于我还不会怎么弄动图,就只有放几张截图了

 

import cv2
import time
import math
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)
cap = cv2.VideoCapture(0)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
 
img=cv2.imread("./ring.png")
ring_h,ring_w,ring_ch=img.shape
L1 = 0
L2 = 0
x=100
y=100
on_square = False
mid_12=False
mid_11=False
mid_10=False
while True:
    rec,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:
            if results.multi_handedness:
                for hand in results.multi_handedness: #如果是右手
                    if hand.classification[0].label=='Right':
#                         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())
                        x_list = []
                        y_list = []
                        for landmark in hand_landmarks.landmark:
                            x_list.append(landmark.x)
                            y_list.append(landmark.y)
                        index_finger_x, index_finger_y = int(x_list[8] * width),int(y_list[8] * height)
                        thumb_finger_x,thumb_finger_y = int(x_list[4] * width), int(y_list[4] * height)
                        finger_distance = math.hypot((thumb_finger_x - index_finger_x), (thumb_finger_y - index_finger_y))
                        if finger_distance < 100 :
                            if (index_finger_x > x-10 and index_finger_x < (x + ring_h+10)) and (
                                    index_finger_y > y-10 and index_finger_y < (y + ring_w+10)):
                                if on_square == False:
                                    L1 = index_finger_x - x
                                    L2 = index_finger_y - y
                                    on_square = True
                        else:
                            on_square = False
                        if on_square:
                            x = index_finger_x - L1
                            y = index_finger_y - L2
                    if hand.classification[0].label=='Left': #如果识别为左手,处理左手中指的行为
                        x_list = []
                        y_list = []
                        for landmark in hand_landmarks.landmark:
                            x_list.append(landmark.x)
                            y_list.append(landmark.y)                        
                        mid_finger_12_x,mid_finger_12_y=int(x_list[12]*width),int(y_list[12]*width)
                        mid_finger_11_x,mid_finger_11_y=int(x_list[11]*width),int(y_list[11]*width)
                        mid_finger_10_x,mid_finger_10_y=int(x_list[10]*width),int(y_list[10]*width)
#                         if(mid_finger_12_y<y+ring_w and mid_finger_12_y>y and not mid_10):
#                             mid_12=True
#                         if(mid_finger_11_y<y+ring_w and mid_finger_11_y>y and mid_12 and mid_finger_12_x>x):
#                             mid_11=True
#                         if(mid_finger_10_y<y+ring_w and mid_finger_10_y>y and mid_11):
#                             mid_10=True
#                     if mid_10:          #跟随中指10点位移动
#这里可以先注释了省去戴的过程  
                        x=mid_finger_10_x
                        y=mid_finger_10_y-130
    overlay = frame.copy()
    for i in range(ring_h):#这里是将原图片中接近白色的颜色筛除,只剩余戒指颜色
        for j in range(ring_w):
            px=img[i,j]
            src2_beta=1   
            if(px[0],px[1],px[2])>=(245,245,245):
                continue    
            color=(int(px[0]),int(px[1]),int(px[2]))
            cv2.rectangle(frame, (x+i, y+j), (x+i,y+j),color,-1)
    frame = cv2.addWeighted(overlay, 0.5, frame, src2_beta, 0)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
    
cap.release()
cv2.destroyAllWindows() 
 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值