You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
5.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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