diff --git a/gesture_recognition.py b/gesture_recognition.py new file mode 100644 index 00000000..d3d3e862 --- /dev/null +++ b/gesture_recognition.py @@ -0,0 +1,141 @@ +import warnings +import threading #导入多线程模块 +import cv2 +import mediapipe as mp +import numpy as np +from tensorflow.keras.models import load_model + +# 禁用特定警告 +warnings.filterwarnings("ignore", category=UserWarning, message='SymbolDatabase.GetPrototype() is deprecated') + +# 初始化 MediaPipe 和 OpenCV +hands = None +mp_draw = mp.solutions.drawing_utils +cap = None +keep_running = False + +# 加载手势识别模型 +model_path = 'D:/hand/hand_gesture_model.h5' +model = load_model(model_path) + +# 定义手势类别 +gesture_classes = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09'] + +def start_recognition(callback=None): + global keep_running, cap, hands + if cap is None or not cap.isOpened(): + cap = cv2.VideoCapture(0) + if hands is None: + hands = mp.solutions.hands.Hands(static_image_mode=False, max_num_hands=2, + model_complexity=1, min_detection_confidence=0.5, + min_tracking_confidence=0.5) + keep_running = True + threading.Thread(target=run_recognition, args=(callback,)).start() + +def run_recognition(callback=None): + global keep_running + last_gesture = None + + while keep_running and cap.isOpened(): + ret, img = cap.read() + if not ret: + break + + img = cv2.flip(img, 1) + img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + results = hands.process(img_rgb) + + total_raised_fingers = 0 + + if results.multi_hand_landmarks: + for handLms in results.multi_hand_landmarks: + mp_draw.draw_landmarks(img, handLms, mp.solutions.hands.HAND_CONNECTIONS) + _, raised_fingers = detect_gesture_and_fingers(handLms) + total_raised_fingers += raised_fingers + + cv2.putText(img, f'Total Raised Fingers: {total_raised_fingers}', (10, 30), + cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2, cv2.LINE_AA,) + + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + if callback: + callback(img) + + stop_recognition() +#停止识别 +def stop_recognition(): + global keep_running, cap + keep_running = False + if cap is not None and cap.isOpened(): + cap.release() + cap = None + cv2.destroyAllWindows() + + + +#释放摄像头资源 +def release_camera(): + global cap + if cap is not None and cap.isOpened(): + cap.release() + cap = None + +def detect_gesture_and_fingers(hand_landmarks): + # 手势识别 + gesture_image = get_hand_image(hand_landmarks) + gesture = predict_gesture(gesture_image) + + # 手指竖起数量检测 + raised_fingers = count_raised_fingers(hand_landmarks) + + return gesture, raised_fingers + +def get_hand_image(hand_landmarks): + # 提取手部区域图像 + # 示例实现,请根据你的需要进行调整 + img = np.zeros((150, 150, 3), dtype=np.uint8) # 示例图像 + return img + +def predict_gesture(img): + img = cv2.resize(img, (150, 150)) + img_array = np.expand_dims(img, axis=0) / 255.0 + predictions = model.predict(img_array) + predicted_class = gesture_classes[np.argmax(predictions)] + return predicted_class + +def count_raised_fingers(hand_landmarks): + fingers_status = [0, 0, 0, 0, 0] + + # 拇指 + thumb_tip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.THUMB_TIP] + thumb_ip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.THUMB_IP] + thumb_mcp = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.THUMB_MCP] + thumb_cmc = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.THUMB_CMC] + + # 计算拇指的角度 + angle_thumb = calculate_angle(thumb_cmc, thumb_mcp, thumb_tip) + if angle_thumb > 160: # 如果拇指的角度大于160度,认为拇指竖起 + fingers_status[0] = 1 + + # 其他手指 + for i, finger_tip_id in enumerate([mp.solutions.hands.HandLandmark.INDEX_FINGER_TIP, + mp.solutions.hands.HandLandmark.MIDDLE_FINGER_TIP, + mp.solutions.hands.HandLandmark.RING_FINGER_TIP, + mp.solutions.hands.HandLandmark.PINKY_TIP]): + finger_tip = hand_landmarks.landmark[finger_tip_id] + finger_pip = hand_landmarks.landmark[finger_tip_id - 2] + finger_mcp = hand_landmarks.landmark[finger_tip_id - 3] + + # 计算手指的角度 + angle_finger = calculate_angle(finger_mcp, finger_pip, finger_tip) + if angle_finger > 160: # 如果手指的角度大于160度,认为手指竖起 + fingers_status[i + 1] = 1 + + return sum(fingers_status) + +def calculate_angle(point1, point2, point3): + # 计算三个点之间的角度 + angle = np.arctan2(point3.y - point2.y, point3.x - point2.x) - np.arctan2(point1.y - point2.y, point1.x - point2.x) + angle = np.abs(angle) + if angle > np.pi: + angle = 2 * np.pi - angle + return angle * 180 / np.pi