iT邦幫忙

2022 iThome 鐵人賽

DAY 18
2

這篇教學會使用 MediaPipe 的姿勢偵測模型 ( pose ) 偵測人體姿勢,再透過 OpenCV 讀取攝影鏡頭影像進行辨識,將頭手四肢軀幹標記出對應的節點以及骨架,最後甚至還可透過偵測到的姿勢,作出即時去背的效果。

原文參考:Mediapipe 姿勢偵測 ( Pose )

因為程式使用 Jupyter 搭配 Tensorflow 進行開發,所以請先閱讀「使用 Anaconda」和「使用 MediaPipe」,安裝對應的套件,如果不要使用 Juputer,也可參考「使用 Python 虛擬環境」,建立虛擬環境進行實作。

Python 教學 - Mediapipe 姿勢偵測 ( Pose )

使用 MediaPipe,偵測姿勢並繪製骨架

Mediapipe Pose 模型可以標記出身體共 33 個姿勢節點的位置,甚至可以進一步透過這些節點,將人物與背景分離,做到去背的效果,下圖標示出每個節點的順序和位置 ( 圖片來源 )。

Python 教學 - Mediapipe 姿勢偵測 ( Pose )

下方的程式碼延伸「讀取並播放影片」文章的範例,搭配 mediapipe 姿勢偵測的方法,透過攝影鏡頭獲取影像後,即時標記出身體骨架和動作。

import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils          # mediapipe 繪圖方法
mp_drawing_styles = mp.solutions.drawing_styles  # mediapipe 繪圖樣式
mp_pose = mp.solutions.pose                      # mediapipe 姿勢偵測

cap = cv2.VideoCapture(0)

# 啟用姿勢偵測
with mp_pose.Pose(
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5) as pose:

    if not cap.isOpened():
        print("Cannot open camera")
        exit()
    while True:
        ret, img = cap.read()
        if not ret:
            print("Cannot receive frame")
            break
        img = cv2.resize(img,(520,300))               # 縮小尺寸,加快演算速度
        img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)   # 將 BGR 轉換成 RGB
        results = pose.process(img2)                  # 取得姿勢偵測結果
        # 根據姿勢偵測結果,標記身體節點和骨架
        mp_drawing.draw_landmarks(
            img,
            results.pose_landmarks,
            mp_pose.POSE_CONNECTIONS,
            landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style())

        cv2.imshow('oxxostudio', img)
        if cv2.waitKey(5) == ord('q'):
            break     # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()

Python 教學 - Mediapipe 姿勢偵測 ( Pose )

透過姿勢偵測,進行即時去背

若額外設定 enable_segmentation 參數為 True,則會透過姿勢判斷人體,進一步做到去背的效果,下方的程式碼會將人物背景換成 windows 的經典背景。

import cv2
import mediapipe as mp
import numpy as np
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_pose = mp.solutions.pose

cap = cv2.VideoCapture(0)
bg = cv2.imread('windows-bg.jpg')   # 載入 windows 經典背景

with mp_pose.Pose(
    min_detection_confidence=0.5,
    enable_segmentation=True,       # 額外設定 enable_segmentation 參數
    min_tracking_confidence=0.5) as pose:

    if not cap.isOpened():
        print("Cannot open camera")
        exit()
    while True:
        ret, img = cap.read()
        if not ret:
            print("Cannot receive frame")
            break
        img = cv2.resize(img,(520,300))
        img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        results = pose.process(img2)
        try:
            # 使用 try 避免抓不到姿勢時發生錯誤
            condition = np.stack((results.segmentation_mask,) * 3, axis=-1) > 0.1
            # 如果滿足模型判斷條件 ( 表示要換成背景 ),回傳 True
            img = np.where(condition, img, bg)
            # 將主體與背景合成,如果滿足背景條件,就更換為 bg 的像素,不然維持原本的 img 的像素
        except:
            pass
        mp_drawing.draw_landmarks(
            img,
            results.pose_landmarks,
            mp_pose.POSE_CONNECTIONS,
            landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style())

        cv2.imshow('oxxostudio', img)
        if cv2.waitKey(5) == ord('q'):
            break     # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()

Python 教學 - Mediapipe 姿勢偵測 ( Pose )

參考資料

更多 Python 教學

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我已經寫了超過 400 篇 Python 的教學,有興趣可以參考下方連結呦~ ^_^


上一篇
( Day 17 ) Mediapipe 手掌偵測 ( hands )
下一篇
( Day 19 ) Mediapipe 全身偵測 ( Holistic )
系列文
Python x AI 影像辨識好好玩32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言