Mediapipe 姿势侦测
这篇教学会使用 MediaPipe 的姿势侦测模型 ( pose ) 侦测人体姿势,再透过 OpenCV 读取摄影镜头图像进行辨识,将头手四肢躯干标记出对应的节点以及骨架,最后甚至还可透过侦测到的姿势,作出即时去背的效果。
快速导览:
因为程序使用 Jupyter 搭配 Tensorflow 进行开发,所以请先阅读“使用 Anaconda”和“使用 MediaPipe”,安装对应的软件包,如果不要使用 Juputer,也可参考“使用 Python 虚拟环境”,建立虚拟环境进行实作。
使用 MediaPipe,侦测姿势并绘制骨架
Mediapipe Pose 模型可以标记出身体共 33 个姿势节点的位置,甚至可以进一步透过这些节点,将人物与背景分离,做到去背的效果,下图标示出每个节点的顺序和位置 ( 图片来源 )。
下方的程序码延伸“读取并播放影片”文章的范例,搭配 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()
透过姿势侦测,进行即时去背
若额外设定 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()
微信扫码关注
抖音扫码关注