OpenCV项目:MediaPipe手部关键点检测详解

MediaPipe 是一款由 Google Research 开发并开源的多媒体机器学习模型应用框架,可以直接调用其API完成目标检测、人脸检测以及关键点检测等。本篇文章介绍其手部21个关键点检测。
在这里插入图片描述

一. 关键函数解释

(1)mediapipe.solutions.hands.Hands(): 手关键点检测

参数:

  • static_image_mode: 默认为 False,将输入图像视为视频流。它将尝试在第一个输入图像中检测手,并在成功检测后进一步定位手的坐标。在随后的图像中,一旦检测到所有 max_num_hands 手并定位了相应的手的坐标,它就会跟踪这些坐标,而不会调用另一个检测,直到它失去对任何一只手的跟踪。这减少了延迟,非常适合处理视频帧。如果设置为 True,则在每个输入图像上运行手部检测,用于处理一批静态的、可能不相关的图像。
  • max_num_hands: 最多检测几只手,默认为2
  • min_detection_confidence: 手部检测模型的最小置信值(0-1之间),超过阈值则检测成功。默认为 0.5
  • min_tracking_confidence: 坐标跟踪模型的最小置信值 (0-1之间),用于将手部坐标视为成功跟踪,不成功则在下一个输入图像上自动调用手部检测。将其设置为更高的值可以提高解决方案的稳健性,但代价是更高的延迟。如果 static_image_mode 为真,则忽略这个参数,手部检测将在每个图像上运行,默认为 0.5

返回值:

  • MULTI_HAND_LANDMARKS: 被检测/跟踪的手的集合,其中每只手被表示为21个手部地标的列表,每个地标由x, y, z组成。x和y分别由图像的宽度和高度归一化为[0,1]。Z表示地标深度。
  • MULTI_HANDEDNESS: 被检测/追踪的手是左手还是右手的集合。每只手由label(标签)和score(分数)组成。 label 是 ‘Left’ 或 ‘Right’ 值的字符串。 score 是预测左右手的估计概率。

(2)mediapipe.solutions.drawing_utils.draw_landmarks(): 绘制手部关键点的连线

参数:

  • image: 需要画图的原始图片
  • landmark_list: 检测到的手部关键点坐标
  • connections: 连接线,需要把那些坐标连接起来
  • landmark_drawing_spec: 坐标的颜色,粗细
  • connection_drawing_spec: 连接线的粗细,颜色等

二. 手部关键点检测并显示伸出的手指数

import cv2
import mediapipe as mp
import cmath

gesture = ["none","one","two","three","four","five","six","seven","eight","nine","ten"]
flag = 0

mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands

hands = mp_hands.Hands(
        static_image_mode=False,
        max_num_hands=2,
        min_detection_confidence=0.75,
        min_tracking_confidence=0.75)

cap = cv2.VideoCapture(0)
while True:
    flag = 0
    ret,frame = cap.read()
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 因为摄像头是镜像的,所以将摄像头水平翻转
    # 不是镜像的可以不翻转
    frame= cv2.flip(frame,1)
    results = hands.process(frame)
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
    
#    if results.multi_handedness:
#        for hand_label in results.multi_handedness:
#            print(hand_label)
            
    if results.multi_hand_landmarks:
        for hand_landmarks in results.multi_hand_landmarks:
            #print('hand_landmarks:', hand_landmarks)
            #计算关键点的距离,用于判断手指是否伸直
            p0_x = hand_landmarks.landmark[0].x
            p0_y = hand_landmarks.landmark[0].y
            p5_x = hand_landmarks.landmark[5].x
            p5_y = hand_landmarks.landmark[5].y
            distance_0_5 = pow(p0_x-p5_x,2)+pow(p0_y-p5_y,2)
            base = distance_0_5 / 0.6
            
            p4_x = hand_landmarks.landmark[4].x
            p4_y = hand_landmarks.landmark[4].y
            distance_5_4 = pow(p5_x-p4_x,2)+pow(p5_y-p4_y,2)
            
            p8_x = hand_landmarks.landmark[8].x
            p8_y = hand_landmarks.landmark[8].y
            distance_0_8 = pow(p0_x-p8_x,2)+pow(p0_y-p8_y,2)
            
            p12_x = hand_landmarks.landmark[12].x
            p12_y = hand_landmarks.landmark[12].y
            distance_0_12 = pow(p0_x-p12_x,2)+pow(p0_y-p12_y,2)
            
            p16_x = hand_landmarks.landmark[16].x
            p16_y = hand_landmarks.landmark[16].y
            distance_0_16 = pow(p0_x-p16_x,2)+pow(p0_y-p16_y,2)
            
            p20_x = hand_landmarks.landmark[20].x
            p20_y = hand_landmarks.landmark[20].y
            distance_0_20 = pow(p0_x-p20_x,2)+pow(p0_y-p20_y,2)
            
            
            if distance_0_8 > base:
                flag += 1
            if distance_0_12 > base:
                flag += 1
            if distance_0_16 > base:
                flag += 1
            if distance_0_20 > base:
                flag += 1
            if distance_5_4 > base*0.3:
                flag += 1
            if flag>=10:
                flag = 10
            # 关键点可视化
            mp_drawing.draw_landmarks(frame, 
                                      hand_landmarks, 
                                      mp_hands.HAND_CONNECTIONS)
            
          
    cv2.putText(frame,gesture[flag],(50,50),0,1.3,(0,0,255),3)
    cv2.imshow('MediaPipe Hands', frame)
    if cv2.waitKey(1) & 0xFF == 27:
        break
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空