Day07 偵測手部是否有拍打的動作
🟡 先看看程式的效果
今天的程式是利用 OpenCV 和 MediaPipe 進行即時手部偵測, 並估算手部與攝影機之間的距離, 當偵測到類似拍打的動作, 手掌的顏色便會由藍色變成綠色。
Today’s program uses OpenCV and MediaPipe for real-time hand detection and estimates the distance between the hand and the camera. When a slapping motion is detected, the color of the palm changes from blue to green.
🟡 學習目標
學習估算手掌的大小, 猜測手掌正在進行的動作。
🟡 程式碼
請先下載 “偵測手部是否有拍打的動作.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 time
# 初始化 MediaPipe 手部偵測模組
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils
# 開啟攝影機
cap = cv2.VideoCapture(0)
def calculate_hand_size(hand_landmarks):
# 簡單估算手部大小,使用手掌根部和中指指尖之間的距離
wrist = hand_landmarks.landmark[mp_hands.HandLandmark.WRIST]
middle_finger_tip = hand_landmarks.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP]
hand_size = ((wrist.x - middle_finger_tip.x) ** 2 + (wrist.y - middle_finger_tip.y) ** 2) ** 0.5
return hand_size
# 儲存上一次的距離和時間
previous_distance = None
previous_time = time.time()
green_start_time = None
while cap.isOpened():
success, image = cap.read()
if not success:
print("忽略空幀")
continue
# 翻轉影像以獲得鏡像效果
image = cv2.flip(image, 1)
# 將影像轉換為 RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 偵測手部
results = hands.process(image_rgb)
current_time = time.time()
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
# 計算手部大小
hand_size = calculate_hand_size(hand_landmarks)
# 假設手的實際大小大約為 20 cm,並估計距離
distance_to_camera = 20 / hand_size if hand_size != 0 else 0
# 比較當前距離和之前的距離
if previous_distance is not None and (current_time - previous_time) >= 0.5:
if previous_distance - distance_to_camera >= 1:
green_start_time = current_time # 記錄開始變綠的時間
# 更新上一次的距離和時間
previous_distance = distance_to_camera
previous_time = current_time
else:
previous_distance = distance_to_camera
# 決定顏色
if green_start_time is not None and (current_time - green_start_time) <= 1:
color = (0, 255, 0) # 綠色
else:
color = (255, 0, 0) # 藍色
# 繪製手部標記
mp_drawing.draw_landmarks(image, hand_landmarks, mp_hands.HAND_CONNECTIONS,
mp_drawing.DrawingSpec(color=color, thickness=2, circle_radius=2),
mp_drawing.DrawingSpec(color=color, thickness=2))
# 顯示手部與攝影機之間的距離
#cv2.putText(image, f'Distance: {distance_to_camera:.2f} cm', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
# 顯示影像
cv2.imshow('Hand Detection', image)
# 按下 ESC 鍵退出
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
🟡 小小挑戰一下
大家可以嘗試進行一些修改或改良喔! 例如:
✌️提高這個程式的辨識準繩度吧
😁 明天見!