由于手语识别需要对手指的位置和动作进行分析,需要对每个手指的位置进行计算并且判断手指的弯曲程度。

首先需要定义一个函数来计算每个手指的弯曲程度:

def finger_bend(finger, landmarks):
    """
    计算手指的弯曲程度
    """
    distal = landmarks[mpHance.HandLandmark[finger.value[0]].value].y
    proximal = landmarks[mpHance.HandLandmark[finger.value[1]].value].y
    intermediate = landmarks[mpHance.HandLandmark[finger.value[2]].value].y
    if distal < proximal and proximal < intermediate:
        return "Straight"
    elif distal > proximal and proximal > intermediate:
        return "Bend"
    else:
        return "Unknown"

接下来定义一个函数来判断手势的类型:

def detect_gesture(hand_landmarks):
    """
    判断手势的类型
    """
    thumb_bend = finger_bend(Finger.THUMB, hand_landmarks.landmark)
    index_bend = finger_bend(Finger.INDEX, hand_landmarks.landmark)
    middle_bend = finger_bend(Finger.MIDDLE, hand_landmarks.landmark)
    ring_bend = finger_bend(Finger.RING, hand_landmarks.landmark)
    pinky_bend = finger_bend(Finger.PINKY, hand_landmarks.landmark)
    if thumb_bend == "Bend" and index_bend == "Bend" and middle_bend == "Bend" and ring_bend == "Bend" and pinky_bend == "Bend":
        return "Fist"
    elif thumb_bend == "Straight" and index_bend == "Bend" and middle_bend == "Bend" and ring_bend == "Bend" and pinky_bend == "Bend":
        return "Point"
    elif thumb_bend == "Bend" and index_bend == "Bend" and middle_bend == "Straight" and ring_bend == "Straight" and pinky_bend == "Straight":
        return "Rock"
    elif thumb_bend == "Straight" and index_bend == "Straight" and middle_bend == "Straight" and ring_bend == "Straight" and pinky_bend == "Straight":
        return "Open"
    else:
        return "Unknown"

最后将以上两个函数加入到主循环中,即可实现手语识别功能:

import mediapipe as mp
import cv2
import time

cap = cv2.VideoCapture(0)
mpHance = mp.solutions.hands  # 选择策略 -- 监测手的模型
mpDraw = mp.solutions.drawing_utils
handLmsStyle=  mpDraw.DrawingSpec(color=(0, 0, 255), thickness=5 )  # 设定点的样式  颜色 粗细,半径
handConStyle=  mpDraw.DrawingSpec(color=(0, 255, 2), thickness=10 )  # 设定线的样式  颜色 粗细,半径
pTime = 0
cTime = 0
hands = mpHance.Hands(static_image_mode=False,      # 影片 false  图片 True
                      max_num_hands=2,              # 最大手识别数量
                      model_complexity=1,           # 模型的复杂度 只能是 0 1 越高越准
                      min_detection_confidence=0.9,     # 识别的精准度
                      min_tracking_confidence=0.5)      # 追踪的严谨度

while True:
    ret, img = cap.read()  # 读取到的图片都是bgr的图片 ,故需要将其转换为RGB的图片

    if ret:
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        result = hands.process(imgRGB)  # 侦测
        # print(result.multi_hand_landmarks)  结果为 三个坐标 XYZ
        imgHeight = img.shape[0] # 获取视窗的高度
        imgWidth = img.shape[1] # 获取视窗的宽度
        if result.multi_hand_landmarks :
            for handLms in result.multi_hand_landmarks :  # 画出所有点和线
                mpDraw.draw_landmarks(img, handLms, mpHance.HAND_CONNECTIONS, handLmsStyle, handConStyle)
                # enumerate函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,常用于for循环中
                for i, lm in enumerate(handLms.landmark):
                    xPos = int(lm.x * imgHeight)
                    yPos = int(lm.y * imgWidth)
                    cv2.putText(img, str(i), (xPos-1, yPos+1), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 200, 50), 1)
                    print(i, xPos, yPos)
                gesture = detect_gesture(handLms)
                cv2.putText(img, gesture, (20, 80), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
        cTime = time.time()
        fps = 1/(cTime - pTime)
        pTime = cTime
        cv2.putText(img, f"FPS : {int(fps)}", (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
        cv2.imshow('img', img)
    if cv2.waitKey(1) == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()
``
import mediapipe as mpimport cv2import timecap = cv2VideoCapture0mpHance = mpsolutionshands # 选择策略 -- 监测手的模型mpDraw = mpsolutionsdrawing_utilshandLmsStyle= mpDrawDrawingSpeccolor=0 0 255 thickness=5

原文地址: https://www.cveoy.top/t/topic/fJwL 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录