Day06 計算食指尖與姆指尖之間的距離


🟡 先看看程式的效果

今天的程式是利用 OpenCV 和 MediaPipe 進行即時手部偵測, 並計算食指指尖和拇指指尖之間的距離。

Today’s program uses OpenCV and MediaPipe for real-time hand detection and calculates the distance between the tip of the index finger and the tip of the thumb.


🟡 學習目標

了解 Mediapipe 手部辨識的節點編寫, 以及如果計算兩點之間的距離。


🟡 程式碼

請先下載 “計算食指尖與姆指尖的距離.py”
請按此下載

'''

Python + AI in 21 days
https://jasonworkshop.com/python

Designed by Jason Workshop

[請勿修改以上內容]

---

預備工作:

首先,請確保已安裝 opencv-python, mediapipe 模組
如不確定可直接在 Windows 的 cmd prompt 執行以下指定
pip install opencv-python mediapipe

'''

import cv2
import mediapipe as mp
import math

# 初始化 MediaPipe Hands 模組
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(static_image_mode=False, max_num_hands=2, min_detection_confidence=0.7)
mp_drawing = mp.solutions.drawing_utils  # 繪製工具

# 開啟攝影機
cap = cv2.VideoCapture(0)

def calculate_distance(point1, point2):
    """計算兩點之間的歐幾里得距離"""
    return math.sqrt((point2.x - point1.x) ** 2 + (point2.y - point1.y) ** 2 + (point2.z - point1.z) ** 2)

while cap.isOpened():
    ret, frame = cap.read() # 讀取攝影機畫面
    if not ret:
        print("無法讀取攝影機畫面")
        break

    # 轉換 BGR 圖像到 RGB
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # 偵測手部
    result = hands.process(rgb_frame)

    # 繪製手部關鍵點和連線
    if result.multi_hand_landmarks:
        for hand_landmarks in result.multi_hand_landmarks:
            # 繪製手部關鍵點
            '''
            mp_drawing.draw_landmarks(
                frame,
                hand_landmarks,
                mp_hands.HAND_CONNECTIONS,
                landmark_drawing_spec=mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2, circle_radius=2),
                connection_drawing_spec=mp_drawing.DrawingSpec(color=(255, 255, 255), thickness=1, circle_radius=2)
            )
            '''
            
            # 計算食指指尖和姆指指尖的距離
            # 距離的單位是基於 MediaPipe 的歸一化座標系統,這意味著距離是相對於影像尺寸的比例值,而不是以像素或其他實際世界的單位來表示。
            index_finger_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]
            thumb_tip = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP]
            distance = calculate_distance(index_finger_tip, thumb_tip)
            print(f"食指指尖至姆指指尖的距離: {distance:.2f}")

            # 畫線在食指指尖和姆指指尖之間
            cv2.line(frame, 
                     (int(index_finger_tip.x * frame.shape[1]), int(index_finger_tip.y * frame.shape[0])),
                     (int(thumb_tip.x * frame.shape[1]), int(thumb_tip.y * frame.shape[0])),
                     (255, 255, 255), 2)

            # 顯示距離在左上角
            cv2.putText(frame, f"Distance: {distance:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)

            # 只處理第一隻手
            break

    # 顯示圖像
    cv2.imshow('Hand Landmarks Detection', frame)

    # 按下 ESC 鍵退出
    if cv2.waitKey(1) & 0xFF == 27:
        break

# 釋放攝影機並關閉所有視窗
cap.release()
cv2.destroyAllWindows()

🟡 小小挑戰一下

大家可以嘗試進行一些修改或改良喔! 例如:
✌️嘗試計算左右手食指尖之間的距離吧!

😁 明天見!

按這裏回到 Python + AI 的 21 天挑戰