
初探Mediapipe
1. Mediapipe簡介
MediaPipe 是Google於2019年發表的開源專案,此專案針對電腦視覺(Computer vision)提供了跨平台的相關應用。
MediaPipe具有高度整合多種語言以及跨平台的特性,並且在處理性能上也非常快速。從下表我們可以看到上述特性。
並且,MediaPipe也提供了多種成熟的機器學習模組,能夠快速地啟動並使用,不需要太過繁複的安裝過程。
上一篇
下一篇
2. 實作
2.1 安裝python
2.2 選擇IDE
這邊使用的IDE是vscode,但是可以依照個人需求選擇,不一定要相同。
2.3 建立虛擬環境
首先,先移動到想要存放mediapipe相關套件的路徑,並開啟vscode。這時可以發現左側的檔案總管還是空的(取決於你所選的位置)。

開啟vscode後,在終端機輸入以下指令,建立虛擬環境。
python -m venv .venv
完畢後,可以看到左側出現了虛擬環境資料夾,但是此時我們還沒進入虛擬環境之中,需要在終端機輸入以下指令即可進入(activate位置可能因人而異)。
& .\.venv\Scripts\activate

進入虛擬環境後,需要先更新一下pip套件,避免版本過舊,在下載mediapipe的時候出現問題。
python -m pip install -U pip

完成後,輸入以下指令安裝mediapipe
pip install mediapipe

2.4 建立3D物體檢測程式
以下實作可以完成3D物體檢測,但是目前只有支援4種物件(鞋子、杯子、攝影機、椅子),完成效果如下:

建立 object_detec.py 檔案

輸入以下程式碼,完成後執行即可看到效果
import cv2
import mediapipe as mp
import time
# 匯入物件辨識所需權重
mp_objectron = mp.solutions.objectron
# 匯入繪圖風格套件
mp_drawing_styles = mp.solutions.drawing_styles
# 匯入繪圖方法
mp_drawing = mp.solutions.drawing_utils
# 建立鏡頭物件
cap = cv2.VideoCapture(1)
# 建立3D物件辨識的物件
with mp_objectron.Objectron(
static_image_mode=False, # 偵測照片時才需開啟
max_num_objects=5, # 最大物件數量
min_detection_confidence=0.2, # 最小偵測信心程度,小於此值將直接忽略
min_tracking_confidence=0.5, # 最小追蹤信心程度,小於此值將直接忽略
model_name='Shoe' # 要偵測的物件
) as objectron:
# 如果鏡頭開啟,則進入迴圈
while cap.isOpened():
# success -> 使用影片才會用到,用於判斷影片是否結束
# image -> 每一幀影像
success, image = cap.read()
# 若是沒有串流資源,則離開迴圈
if not success:
break
# 每一幀影像開始處理時間
start = time.time()
# 轉換色彩通道順序
# openCV -> BGR,mediapipe偵測使用 RGB,因此需轉換
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 一開始偵測的影像不進行繪圖,提高運算速度
image.flags.writeable = False
# mediapipe 對每一幀影像進行處理
result = objectron.process(image)
# 因為顯示是使用openCV,因此需再將色彩通道轉回來
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
# 因為要看到效果,因此要把繪圖功能打開
image.flags.writeable = True
# 判斷是否有偵測到物件
if result.detected_objects:
# 將偵測到的每一個物件取出
for detected_object in result.detected_objects:
# 畫出地標
mp_drawing.draw_landmarks(
image,
detected_object.landmarks_2d,
mp_objectron.BOX_CONNECTIONS,
)
# 畫出軸
mp_drawing.draw_axis(image, detected_object.rotation, detected_object.translation)
# 每一幀影像處理結束時間
end = time.time()
# 處理每一幀影像時間間隔
total_time = end - start
# 計算fps
fps = 1 / total_time
# 用於將文字顯示在影像上
cv2.putText(image, f'FPS: {int(fps)}', (20,70), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 0, 0), 2)
# 顯示影像
cv2.imshow('3D object detection', image)
# 判斷q是否被按下(不分大小寫)
if cv2.waitKey(5) == ord('q'.casefold()):
# q被按下 -> 離開迴圈
break
# 釋放鏡頭資源
cap.release()
2.5 建立手部追蹤程式
import cv2
import mediapipe as mp
# 匯入繪圖套件
mp_drawing = mp.solutions.drawing_utils
# 匯入繪圖風格套件
mp_drawing_styles = mp.solutions.drawing_styles
# 匯入手部辨識權重
mp_hands = mp.solutions.hands
# 判斷是否有其他鏡頭資源,若沒有的話則使用原本的鏡頭
cap = cv2.VideoCapture(1, cv2.CAP_DSHOW) if cv2.VideoCapture(1).isOpened() else cv2.VideoCapture(0, cv2.CAP_DSHOW)
# 建立手部辨識物件
with mp_hands.Hands(
model_complexity=0, # 模型複雜度,範圍:1~2,越大越複雜,判斷時間越久、但越準確
min_detection_confidence=0.5, # 最小偵測信心程度,小於此值將直接忽略
min_tracking_confidence=0.5 # 最小追蹤信心程度,小於此值將直接忽略
) as hands:
# 如果鏡頭開啟,則進入迴圈
while cap.isOpened():
# success -> 使用影片才會用到,用於判斷影片是否結束
# image -> 每一幀影像
success, image = cap.read()
# 若是沒有串流資源,則離開迴圈
if not success:
break
# 一開始偵測的影像不進行繪圖,提高運算速度
image.flags.writeable = False
# 轉換色彩通道順序
# openCV -> BGR,mediapipe偵測使用 RGB,因此需轉換
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# mediapipe 對每一幀影像進行處理
results = hands.process(image)
# 因為要看到效果,因此要把繪圖功能打開
image.flags.writeable = True
# 因為顯示是使用openCV,因此需再將色彩通道轉回來
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
# 判斷是否有偵測到物件
if results.multi_hand_landmarks:
# 將偵測到的每一個物件取出
for hand_landmarks in results.multi_hand_landmarks:
# 畫出地標
mp_drawing.draw_landmarks(
image,
hand_landmarks,
mp_hands.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style()
)
# 顯示影像
cv2.imshow('MediaPipe Hands', cv2.flip(image, 1))
# 判斷q是否被按下(不分大小寫)
if cv2.waitKey(5) == ord('q'.casefold()):
# q被按下 -> 離開迴圈
break
# 釋放鏡頭資源
cap.release()