diff --git a/gesture_recognition.py b/gesture_recognition.py index 2fd7c48c..0e38abb7 100644 --- a/gesture_recognition.py +++ b/gesture_recognition.py @@ -6,9 +6,14 @@ import numpy as np from tensorflow.keras.models import load_model from tkinter import Tk, Canvas, Button, Label, LEFT, RIGHT, NW from PIL import Image, ImageTk +import os + +# 设置环境变量以关闭oneDNN自定义操作 +os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' warnings.filterwarnings("ignore", category=UserWarning, message='SymbolDatabase.GetPrototype() is deprecated') +# 初始化全局变量 hands = None mp_draw = mp.solutions.drawing_utils cap = None @@ -16,13 +21,13 @@ keep_running = False paused = False popup_open = 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): +def start_recognition(root, callback=None): global keep_running, cap, hands if cap is None or not cap.isOpened(): cap = cv2.VideoCapture(0) @@ -31,10 +36,9 @@ def start_recognition(callback=None): model_complexity=1, min_detection_confidence=0.5, min_tracking_confidence=0.5) keep_running = True - threading.Thread(target=run_recognition, args=(callback,)).start() + threading.Thread(target=run_recognition, args=(root, callback)).start() - -def run_recognition(callback=None): +def run_recognition(root, callback=None): global keep_running, paused while keep_running and cap.isOpened(): @@ -51,22 +55,18 @@ def run_recognition(callback=None): if results.multi_hand_landmarks: for handLms in results.multi_hand_landmarks: - mp_draw.draw_landmarks(img, handLms, mp.solutions.hands.HAND_CONNECTIONS) + mp_draw.draw_landmarks(img_rgb, handLms, mp.solutions.hands.HAND_CONNECTIONS) gesture, raised_fingers = detect_gesture_and_fingers(handLms) total_raised_fingers += raised_fingers - if gesture == "OK": - handle_ok_gesture() - if total_raised_fingers > 0: handle_finger_detection(total_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, ) + cv2.putText(img_rgb, f'Total Raised Fingers: {total_raised_fingers}', (10, 30), + cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2, cv2.LINE_AA) if callback: - callback(img) - + root.after(0, callback, img_rgb) def stop_recognition(): global keep_running, cap @@ -76,31 +76,24 @@ def stop_recognition(): 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) - if is_ok_gesture(hand_landmarks): - gesture = "OK" - 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 @@ -108,7 +101,6 @@ def predict_gesture(img): predicted_class = gesture_classes[np.argmax(predictions)] return predicted_class - def count_raised_fingers(hand_landmarks): fingers_status = [0, 0, 0, 0, 0] @@ -135,7 +127,6 @@ def count_raised_fingers(hand_landmarks): 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) @@ -143,100 +134,17 @@ def calculate_angle(point1, point2, point3): angle = 2 * np.pi - angle return angle * 180 / np.pi - -def is_ok_gesture(hand_landmarks): - thumb_tip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.THUMB_TIP] - index_tip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.INDEX_FINGER_TIP] - distance = np.linalg.norm(np.array([thumb_tip.x, thumb_tip.y]) - np.array([index_tip.x, index_tip.y])) - - # 检查其他手指是否弯曲 - middle_tip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.MIDDLE_FINGER_TIP] - ring_tip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.RING_FINGER_TIP] - pinky_tip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.PINKY_TIP] - middle_pip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.MIDDLE_FINGER_PIP] - ring_pip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.RING_FINGER_PIP] - pinky_pip = hand_landmarks.landmark[mp.solutions.hands.HandLandmark.PINKY_FINGER_PIP] - - middle_finger_bent = middle_tip.y > middle_pip.y - ring_finger_bent = ring_tip.y > ring_pip.y - pinky_finger_bent = pinky_tip.y > pinky_pip.y - - return distance < 0.05 and middle_finger_bent and ring_finger_bent and pinky_finger_bent # 根据实际情况调整这个阈值 - - -def handle_ok_gesture(): - global paused, popup_open - if not popup_open: - paused = True - popup_open = True - show_ok_window() - - -def show_ok_window(): - def on_continue(): - global paused, popup_open - paused = False - popup_open = False # 关闭弹窗后将标志设置为False - ok_window.destroy() - start_recognition(show_frame) - - ok_window = Tk() - ok_window.title("手势检测") - - label = Label(ok_window, text="检测到OK手势", font=('Helvetica', 24, 'bold')) - label.pack(pady=20) - - continue_button = Button(ok_window, text="继续识别", command=on_continue) - continue_button.pack(pady=10) - - ok_window.protocol("WM_DELETE_WINDOW", on_continue) - ok_window.mainloop() - - def handle_finger_detection(finger_count): global paused, popup_open - if not popup_open: # 只有在没有弹窗打开的情况下才处理手指检测并显示弹窗 - if finger_count == 1: - paused = True - popup_open = True - show_finger_window("您竖起了一根手指") - elif finger_count == 2: - paused = True - popup_open = True - show_finger_window("您竖起了两根手指") - elif finger_count == 3: - paused = True - popup_open = True - show_finger_window("您竖起了三根手指") - elif finger_count == 4: - paused = True - popup_open = True - show_finger_window("您竖起了四根手指") - elif finger_count == 5: + if not popup_open: + if finger_count == 5: paused = True popup_open = True show_stop_recognition_window() - elif finger_count == 6: - paused = True - popup_open = True - show_finger_window("您竖起了六根手指") - elif finger_count == 7: - paused = True - popup_open = True - show_finger_window("您竖起了七根手指") - elif finger_count == 8: - paused = True - popup_open = True - show_finger_window("您竖起了八根手指") - elif finger_count == 9: - paused = True - popup_open = True - show_finger_window("您竖起了九根手指") - elif finger_count == 10: - paused = True - popup_open = True - show_finger_window("您竖起了十根手指") - + # if finger_count == 1: + # paused = True + # popup_open = True + # show_stop_recognition_window() def show_finger_window(message): def on_continue(): @@ -258,7 +166,6 @@ def show_finger_window(message): finger_window.protocol("WM_DELETE_WINDOW", on_continue) finger_window.mainloop() - def show_stop_recognition_window(): def on_continue(): global paused, popup_open @@ -288,13 +195,11 @@ def show_stop_recognition_window(): stop_window.protocol("WM_DELETE_WINDOW", on_continue) stop_window.mainloop() - def show_frame(img=None): - global paused + global paused, canvas if keep_running and cap.isOpened(): if img is not None: - frame = img - frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + frame_rgb = img else: ret, frame = cap.read() if not ret: @@ -314,7 +219,6 @@ def show_frame(img=None): root.update_idletasks() root.update() - if __name__ == "__main__": root = Tk() root.title("手势识别") diff --git a/gui.py b/gui.py index 2c5726fd..c25edbef 100644 --- a/gui.py +++ b/gui.py @@ -7,9 +7,11 @@ from gesture_recognition import start_recognition, stop_recognition, release_cam WINDOW_WIDTH = 800 WINDOW_HEIGHT = 705 + def main(): show_welcome_screen() + def set_window_position(window, width, height): screen_width = window.winfo_screenwidth() screen_height = window.winfo_screenheight() @@ -17,6 +19,7 @@ def set_window_position(window, width, height): y = (screen_height - height) // 2 window.geometry(f'{width}x{height}+{x}+{y}') + def show_welcome_screen(): welcome = Tk() welcome.title("欢迎使用") @@ -33,11 +36,13 @@ def show_welcome_screen(): label = Label(welcome, text="欢迎使用手势识别系统", font=('Helvetica', 24, 'bold'), bg="lightblue", fg="white") label.place(relx=0.5, rely=0.4, anchor=CENTER) - btn_continue = Button(welcome, text="继续", command=lambda: [welcome.destroy(), show_main_screen()], font=('Helvetica', 14), bg="yellow", fg="black", relief=SOLID) + btn_continue = Button(welcome, text="继续", command=lambda: [welcome.destroy(), show_main_screen()], + font=('Helvetica', 14), bg="yellow", fg="black", relief=SOLID) btn_continue.place(relx=0.5, rely=0.6, anchor=CENTER) welcome.mainloop() + def show_main_screen(): global window, canvas window = Tk() @@ -58,7 +63,7 @@ def show_main_screen(): status_label = Label(frame_controls, text="等待开始...", font=('Helvetica', 14), bg='lightgray') status_label.pack(side=LEFT, padx=(10, 20)) - btn_start = ttk.Button(frame_controls, text="开始", command=lambda: start_thread(canvas, status_label)) + btn_start = ttk.Button(frame_controls, text="开始", command=lambda: start_thread(window, canvas, status_label)) btn_start.pack(side=LEFT, padx=10) btn_stop = ttk.Button(frame_controls, text="停止", command=lambda: stop_recognition_with_label(status_label)) @@ -72,22 +77,27 @@ def show_main_screen(): window.mainloop() -def start_thread(canvas, status_label): + +def start_thread(root, canvas, status_label): global keep_running if not keep_running: status_label.config(text="正在识别...") - threading.Thread(target=lambda: start_recognition(callback=lambda img: update_canvas(canvas, img))).start() + threading.Thread( + target=lambda: start_recognition(root, callback=lambda img: update_canvas(canvas, img))).start() + def stop_recognition_with_label(status_label): stop_recognition() status_label.config(text="已停止") + def exit_program(): global window stop_recognition() release_camera() window.destroy() + def update_canvas(canvas, img): img = Image.fromarray(img) imgtk = ImageTk.PhotoImage(image=img) @@ -95,5 +105,6 @@ def update_canvas(canvas, img): canvas.image = imgtk canvas.update() + if __name__ == "__main__": main()