初探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()
				
			
Scroll to Top

hurry up !

軟體工程師培訓

限時免費報名中

藉由與「真實世界軟體專案」相同的技術、工具與開發流程,化簡成與商業機密無關、門檻較低更容易上手的「模擬專案」,讓你有機會在職場前輩的陪伴下,完成真槍實彈的練習,動手解決真實的問題,快速累積個人的經驗與作品,而不只是「學習技術」而已。