施勢帆老師的教學網站

 找回密碼
 立即註冊
搜索
熱搜: 活動 交友 discuz
查看: 65|回復: 0

Mediapipe 手掌特徵點偵測 ( Hand Landmark Detection )

[複製鏈接]

710

主題

721

帖子

3449

積分

管理員

Rank: 9Rank: 9Rank: 9

積分
3449
發表於 2025-4-24 14:44:59 | 顯示全部樓層 |閱讀模式
import cv2
import mediapipe as mp
import numpy as np

# 初始化 MediaPipe Hand Landmarker
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles

# 設定手部偵測模型(提高信心閾值減少誤判)
hands = mp_hands.Hands(
    static_image_mode=False,
    max_num_hands=2,
    min_detection_confidence=0.8,
    min_tracking_confidence=0.8
)

# 開啟攝像頭
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("❌ 錯誤:無法開啟相機")
    exit()

try:
    while True:
        ret, frame = cap.read()
        if not ret:
            print("❌ 錯誤:無法讀取畫面")
            break

        # 鏡像翻轉畫面(讓左右判斷更直覺)
        frame = cv2.flip(frame, 1)
        h, w, _ = frame.shape

        # 轉換為 RGB(MediaPipe 需要 RGB 格式)
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        # 偵測手部關鍵點
        results = hands.process(frame_rgb)

        if results.multi_hand_landmarks:
            for hand_landmarks, handedness in zip(
                results.multi_hand_landmarks,
                results.multi_handedness
            ):
                # 繪製手部關鍵點和連接線
                mp_drawing.draw_landmarks(
                    frame,
                    hand_landmarks,
                    mp_hands.HAND_CONNECTIONS,
                    mp_drawing_styles.get_default_hand_landmarks_style(),
                    mp_drawing_styles.get_default_hand_connections_style()
                )

                # 取得手部資訊
                hand_type = handedness.classification[0].label  # Left or Right
                confidence = handedness.classification[0].score  # 信心分數

                # 計算手部邊界框(Bounding Box)
                landmark_array = np.array([[lm.x * w, lm.y * h] for lm in hand_landmarks.landmark])
                x_min, y_min = np.min(landmark_array, axis=0).astype(int)
                x_max, y_max = np.max(landmark_array, axis=0).astype(int)

                # 繪製邊界框
                cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2)

                # 顯示手部類別和信心分數
                cv2.putText(
                    frame, f"{hand_type} Hand (Conf: {confidence:.2f})",
                    (x_min, y_min - 10),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.6,
                    (0, 255, 0), 2
                )

                # 顯示所有 21 個關鍵點座標(可選:只顯示特定關鍵點)
                for idx, landmark in enumerate(hand_landmarks.landmark):
                    cx, cy = int(landmark.x * w), int(landmark.y * h)
                    cv2.putText(
                        frame, f"{idx}{cx},{cy})",
                        (cx + 10, cy),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.4,
                        (255, 255, 255), 1
                    )

        # 顯示畫面
        cv2.imshow('Hand Tracking with Full Info', frame)

        # 按 'q' 退出
        if cv2.waitKey(1) == ord('q'):
            break

finally:
    cap.release()
    cv2.destroyAllWindows()
    hands.close()

本帖子中包含更多資源

您需要 登錄 才可以下載或查看,沒有帳號?立即註冊

x
回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

Archiver|手機版|小黑屋|施勢帆老師的教學網站

GMT+8, 2025-5-10 03:16 , Processed in 0.061170 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回復 返回頂部 返回列表