基于mediapipe的手势数字识别

基于mediapipe识别手势所对应的数字(一、二、三、四、五)。
mediapipe的官网
总体思路:mediapipe可以识别手掌的关键点,我的思路是识别单根手指是否弯曲,然后根据五根手指的弯曲程度判断手势所对应的数字。

那怎么判断单根手指是否弯曲呢?
我是根据手指的四个关键点的相对位置。比如识别大拇指的弯曲程度,先计算点4和点3的角度a,再计算点2和点1的角度b,最后计算角度a和角度b的差值的绝对值,如果绝对值小于12度,则认为大拇指是伸直的。其他手指同理。

那怎么根据五根手指的弯曲程度判断手势所对应的数字呢?
假设已知五根手指的弯曲程度,若五根手指均伸直,则手势为数字五;若食指、中指、无名指、小指均伸直,而大拇指弯曲,则认为手势是数字四。其它手势同理。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码如下:

import cv2
import mediapipe as mp
import time
import math


# 根据手指四个关节判断手指是否伸直
def get_angleError(point_4,point_3,point_2,point_1):
    try:
        point_4_cx, point_4_cy = int(point_4.x * w), int(point_4.y * h)
        point_3_cx, point_3_cy = int(point_3.x * w), int(point_3.y * h)
        point_2_cx, point_2_cy = int(point_2.x * w), int(point_2.y * h)
        point_1_cx, point_1_cy = int(point_1.x * w), int(point_1.y * h)

        angle_1 = math.degrees(math.atan((point_3_cx - point_4_cx) / (point_3_cy - point_4_cy)))
        angle_2 = math.degrees(math.atan((point_1_cx - point_2_cx) / (point_1_cy - point_2_cy)))
        angle_error = abs(angle_1 - angle_2)
        if angle_error<12:
            isStraight = 1
        else:
            isStraight = 0
    except:
        angle_error = 1000
        isStraight = 0

    return angle_error, isStraight


# 根据五根手指伸直程度识别手势
def getGesture(isStraight_list):
    if isStraight_list[0]==0 and isStraight_list[1]==1 and isStraight_list[2]==0 and isStraight_list[3]==0 and isStraight_list[4]==0:
        gesture = "one"
    elif isStraight_list[0]==0 and isStraight_list[1]==1 and isStraight_list[2]==1 and isStraight_list[3]==0 and isStraight_list[4]==0:
        gesture = "two"
    elif isStraight_list[0]==0 and isStraight_list[1]==0 and isStraight_list[2]==1 and isStraight_list[3]==1 and isStraight_list[4]==1:
        gesture = "three"
    elif isStraight_list[0]==0 and isStraight_list[1]==1 and isStraight_list[2]==1 and isStraight_list[3]==1 and isStraight_list[4]==1:
        gesture = "four"
    elif isStraight_list[0]==1 and isStraight_list[1]==1 and isStraight_list[2]==1 and isStraight_list[3]==1 and isStraight_list[4]==1:
        gesture = "five"
    else:
        gesture = "None"

    return gesture

cap = cv2.VideoCapture(0)
mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,
                      max_num_hands=2,
                      min_detection_confidence=0.5,
                      min_tracking_confidence=0.5)

mpDraw = mp.solutions.drawing_utils
pTime = 0
cTime = 0
while True:
    success, img = cap.read()
    img = cv2.flip(img, 1)
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    results = hands.process(imgRGB)
    #print(results.multi_hand_landmarks)
    if results.multi_hand_landmarks:

        for handLms in results.multi_hand_landmarks:
            for id, lm in enumerate(handLms.landmark):
                #print(id,lm)
                h, w, c = img.shape
                cx, cy = int(lm.x *w), int(lm.y*h)
                # print(cx,cy)
                #if id ==0:
                cv2.circle(img, (cx,cy), 3, (255,0,255), cv2.FILLED)
            mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)

        # 判断拇指手势方向:
        isStraight_list = []
        point_4 = handLms.landmark[4]
        point_3 = handLms.landmark[3]
        point_2 = handLms.landmark[2]
        point_1 = handLms.landmark[1]
        angle_error_1, isStraight_1 = get_angleError(point_4,point_3,point_2,point_1)
        print("isStraight_1:",isStraight_1)
        isStraight_list.append(isStraight_1)

        # 判断食指手势方向:
        point_4 = handLms.landmark[8]
        point_3 = handLms.landmark[7]
        point_2 = handLms.landmark[6]
        point_1 = handLms.landmark[5]
        angle_error_2, isStraight_2 = get_angleError(point_4,point_3,point_2,point_1)
        print("isStraight_2:",isStraight_2)
        isStraight_list.append(isStraight_2)

        # 判断中指手势方向:
        point_4 = handLms.landmark[12]
        point_3 = handLms.landmark[11]
        point_2 = handLms.landmark[10]
        point_1 = handLms.landmark[9]
        angle_error_3, isStraight_3 = get_angleError(point_4,point_3,point_2,point_1)
        print("isStraight_3:",isStraight_3)
        isStraight_list.append(isStraight_3)

        # 判断无名指手势方向:
        point_4 = handLms.landmark[16]
        point_3 = handLms.landmark[15]
        point_2 = handLms.landmark[14]
        point_1 = handLms.landmark[13]
        angle_error_4, isStraight_4 = get_angleError(point_4,point_3,point_2,point_1)
        print("isStraight_4:",isStraight_4)
        isStraight_list.append(isStraight_4)

        # 判断小指手势方向:
        point_4 = handLms.landmark[20]
        point_3 = handLms.landmark[19]
        point_2 = handLms.landmark[18]
        point_1 = handLms.landmark[17]
        angle_error_5, isStraight_5 = get_angleError(point_4,point_3,point_2,point_1)
        print("isStraight_5:",isStraight_5)
        isStraight_list.append(isStraight_5)

        # 根据五根手指的伸直程度判断手势所对应的数字
        gesture  = getGesture(isStraight_list)
        print("gesture:",gesture)

        cv2.putText(img, gesture, (10, 100), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)


    cTime = time.time()
    fps = 1/(cTime-pTime)
    pTime = cTime
    # cv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)
    cv2.imshow("Image", img)
    cv2.waitKey(1)
  • 17
    点赞
  • 118
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值