七户小站
这里是创客七户社
七户小站

MediaPipe简单的一些手势判断

MediaPipe简单的一些手势判断

首先大家应该需要对于python,opencv和MediaPipe有一定的了解

最近在用MediaPipe Hands试着判断一些简单的手势中有一点小思路,大致如下:
人们判断一只手掌所做出的手势主要是通过观察哪些手指竖直/弯曲,以及观察手指之间是否相接触。比如“OK”手势,就是大拇指与食指指尖相碰,剩余三根手指弯曲。
(放一张MediaPipe手部21个关键点的图)

/wp-content/uploads/2022/06/hand_landmarks.png

通过观察可以发现,对于除大拇指外的四根手指,我们仅需要通过对于它们指尖到指根的距离,一旦小于某个值,便可以认定弯曲。
另外对于大拇指,我们仅需特别判断一下4点与0点的距离是否会小于3点与0点的距离差便可判断其是否弯曲

那这样就可以开始写代码了

主要核心就是这几句,其实就是用勾股定理罢了

判断大拇指是否弯曲

#获得掌根和大拇指中间指节的坐标
three = (int(hand_list.landmark[3].x*w),int(hand_list.landmark[3].y*h))

zero = (int(hand_list.landmark[0].x*w),int(hand_list.landmark[0].y*h))

#勾股定理
length_compare = int(three[0]-zero[0])**2 + int(three[1]-zero[1])**2
length_compare = int(math.sqrt(length_compare))

#对大拇指判断 4-0的距离 

thumb_tip = (int(hand_list.landmark[4].x*w),int(hand_list.landmark[4].y*h))

length_damuzhi = int(thumb_tip[0]-zero[0])**2 + int(thumb_tip[1]-zero[1])**2
length_damuzhi = int(math.sqrt(length_damuzhi))

这样当length_damuzhi < length_compare就能判断大拇指是弯曲的了

对于剩下的四根手指同理

for id in range(0,4) :
     #对于指尖和指根距离判断
     finger_tip = (int(hand_list.landmark[tipsid[id]].x*w),int(hand_list.landmark[tipsid[id]].y*h))
     finger_bottom (int(hand_list.landmark[tipsid[id]-3].x*w),int(hand_list.landmark[tipsid[id]-3].y*h))

     length = int(finger_tip[0]-finger_bottom[0])**2 + int(finger_tip[1]-finger_bottom[1])**2
     length = int(math.sqrt(length))

经过尝试发现当指尖和指根距离差小于50的时候便认为它们弯曲
这样就能判断每根手指的竖直/弯曲情况了

附上一个能判断数字1-5的小程序吧(理论上通过这个思路可以判断相当多的手势)

import mediapipe as mp 
import cv2
import math

cap = cv2.VideoCapture(0)

mpHands = mp.solutions.hands
hand = mpHands.Hands()
mphanddraw = mp.solutions.drawing_utils

tipsid = [8,12,16,20] #除大拇指外每个手指指尖的坐标

while True:
    f , img = cap.read()

    RGBImage = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

    result = hand.process(RGBImage)

    if result.multi_hand_landmarks :

        hands_data = result.multi_hand_landmarks

        fingerlist = []

        for hand_list in hands_data:
            h,w,c = img.shape

            #获得掌根和大拇指中间指节的坐标,来判断手掌的长度
            three = (int(hand_list.landmark[3].x*w),int(hand_list.landmark[3].y*h))

            zero = (int(hand_list.landmark[0].x*w),int(hand_list.landmark[0].y*h))

            #勾股定理
            length_compare = int(three[0]-zero[0])**2 + int(three[1]-zero[1])**2
            length_compare = int(math.sqrt(length_compare))

            #对大拇指判断 4-0的距离

            thumb_tip = (int(hand_list.landmark[4].x*w),int(hand_list.landmark[4].y*h))

            length_damuzhi = int(thumb_tip[0]-zero[0])**2 + int(thumb_tip[1]-zero[1])**2
            length_damuzhi = int(math.sqrt(length_damuzhi))

            #弯曲的话就往列表里记录0
            if length_damuzhi<length_compare :
                fingerlist.append(0)
            else :
                fingerlist.append(1)

            #再用一个循环判断剩余四根手指是否弯曲

            for id in range(0,4) :

                finger_tip = (int(hand_list.landmark[tipsid[id]].x*w),int(hand_list.landmark[tipsid[id]].y*h))
                finger_bottom = (int(hand_list.landmark[tipsid[id]-3].x*w),int(hand_list.landmark[tipsid[id]-3].y*h))

                length = int(finger_tip[0]-finger_bottom[0])**2 + int(finger_tip[1]-finger_bottom[1])**2
                length = int(math.sqrt(length))

                if length<50 :
                        fingerlist.append(0)
                else:
                        fingerlist.append(1)

            totalfinger = fingerlist.count(1) #数有几个手指竖着判断为数字几

            cv2.putText(img,str(totalfinger),(50,50),cv2.FONT_HERSHEY_PLAIN,5,(255,255,255),5)

                # 这个只是绘制手指关节的,可以忽略这段代码
            for id,lm in enumerate(hand_list.landmark):

                    cx,cy = int(lm.x * w),int(lm.y * h)
                    cv2.circle(img,(cx,cy),5,(255,0,255),cv2.FILLED)
                   # cv2.putText(img,str(id),(cx,cy),cv2.FONT_HERSHEY_PLAIN,1,(0,255,255),1)

            mphanddraw.draw_landmarks(img,hand_list,mpHands.HAND_CONNECTIONS,)

    cv2.imshow("Hands",img)

    if(cv2.waitKey(1)==ord("q")):
        break

cap.release()
cv2.destroyAllWindows()
Avatar photo

zyc

文章作者

2023届社长

发表回复

textsms
account_circle
email

七户小站

MediaPipe简单的一些手势判断
使用MediaPipe Hands判断简单手势的一点小思路
扫描二维码继续阅读
2022-06-09