用MediaPipe快速搭建Hand Tracking

Rice Yang
10 min readApr 12, 2021

--

MediaPipe 是 Google 推出的一款跨平台的推理框架,可以快速的設計機器學習推理 Pipeline 並產出可以 Real-time Demo 的程式。這個框架不負責優化模型訓練與模型推理,而是專注於高速的 Pipeline 搭建

MediaPipe 的優點是說明文件相當的完善,因此可以很簡單的看懂。MediaPipe 也提供了 15 種 Pipeline 方案,並直接提供了輕量化模型開放下載,讓你可以簡單的跑起來任何一種方案並修改,所有方案都是可以在手機跑的 Real-time Demo。

但是,一樣都是跑深度學習模型,為什麼 MediaPipe 更順暢?

本篇文章會先介紹 MediaPipe 的設計原理與基本觀念,並使用 MediaPipe Visualizer 建立一個 Hand Tracking 的簡單 online demo 來做為範例,並說明好的推理 Pipeline 如何影響 App 的執行效率。

MediaPipe Demo。來源:google/mediapipe: Cross-platform, customizable ML solutions for live and streaming media. (github.com)

MediaPipe 的用途與設計

這是因為 MediaPipe 正如其名,是整合 Media 與 Pipeline 的深度學習運行框架。

與 TFLite 有甚麼不同?

TFLite 是 Google 的深度學習推理引擎,但是 TFLite 解決的問題是 CNN 網路的推理加速。將深度學習模型轉換成 TFLite 格式再透過 TFLite 引擎推理,對速度或記憶體都會得到較好的優化效果。

MediaPipe 則是更方便易用的流程設計框架。它使用 TFLite 作為推理引擎,並且把模型推理以外的前後處理全部納入設計考慮,例如:

  • Pipeline 設計
  • 圖片時間戳、短期暫存
  • 圖片翻轉、裁剪
  • NMS
  • 邏輯條件、邏輯處理

舉例來說,一個 Face Detection (web demo) 的 Pipeline 如下:

Face Detection。來源:MediaPipe

上圖就是一個完整的 Pipeline,在 MediaPipe 裡面被稱為 Graph。這張圖中Graph 涵蓋了所有的設定,並且使用者完全不需要寫 Code。對於一張輸入的圖,會由上而下的經過每一個節點 (Node),最後輸出到螢幕上,完成一個簡單的人臉檢測 App。

MediaPipe 基本概念

MediaPipe 包含了 2 個最重要的基本概念:Graph, Calculator。

Calculator

CalculatorMediaPipe 中的最基本的組成單元。Calculator 定義了許多功能,例如:圖片轉換、模型推理、NMS…等等。目前 MediaPipe 支援數百個 Calculator ,可以滿足大多數的應用場景。但如果要自訂 Calculator,也可以靠編寫 C++ 的方式來改寫 Source Code 的方式達成。

每個 Calculator 可以輸入多個 inputs 並輸出多個 outputs。只要其中一個 input 更新時,Calculator 內部的運算就可以被觸發執行,並且產生一個或多個 output。

Graph

Graph 如前文所述,就是透過多個節點相連產生的運算 Pipeline。但除此之外,還有一些細節的設計,讓 MediaPipe 變得更加彈性且高效。

SubGraph

前面說到 Graph 是由多個節點所組成的,而每一個節點可以是一個 Calculator,也可以是由多個 Calculators 組成的一個 SubGraph。透過 SubGraph的設計,使用者可以先定義好各種常用的 SubGraph,再透過這些 SubGraph 組合出完整的 Graph,降低開發時間。

Circles

不同於 TensorFlow、PyTorch 等深度學習框架的 Computation Graph 設計,MediaPipe Graph 可以支援 Circle 的存在。

一個包含 Circle 的簡單 Graph。來源:MediaPipe

上圖是一個最簡單的 Circle 範例。這個範例想要實現的效果是對一個持續輸入的整數變數做持續加總。在這個 Pipeline 中,會依序發生以下事情:

  1. Integer source 給出一個整數變數,稱為 intergers。
  2. Adder 把 integersold_sum(初始化為 0) 相加,並輸出變數 sum
  3. 輸出 sum 做為 Graph 的輸出。
  4. Delay 把 sum 變數的 timestamp 稍微後移,並且輸出成 old_sum
  5. 重複步驟 1,直到 Integer source 沒有輸出

讓 Graph Circle 不會產生無限迴圈的關鍵原因在於 old_sum 變數被標記成 back edge。這個標記讓 Adder 知道 old_sum 有較低的優先級,讓 old_sum 更新時不會觸發 Adder,避免 Circle 的無限循環。

Circle 是讓 MediaPipe 能夠實現複雜邏輯控制的關鍵設計。具體的用法我們可以從下面的範例來理解。

範例 — 從 Hand Landmarks 到 Hand Tracking

Hand Tracking 是一個容易了解 MediaPipe 基本原理以及加速邏輯的教學範例。這個範例的最終效果是要實作 Real-time 的手部關鍵點跟蹤:

Hand Tracking 效果圖。來源:MediaPipe

要實現上圖的效果,我們可以搭建一個基於 Detection + Landmarks 簡單 Graph,下面的定義可以直接貼上 MediaPipe Visualizer 執行:

簡單的 Detection + Landmark 結構

這個 Graph 是先做 Detection 後串接 Landmarks 檢測的簡單 Pipeline。以下先說明兩個比較重要的 SubGraph:

HandDetection

對輸入圖片執行手掌檢測模型,並且輸出類別與位置框

輸入:完整的圖片

輸出

  • DETECTIONS:手的檢測結果
  • NORM_RECT:放大過的手部位置方框

HandLandmark

輸入圖片跟一個位置方框,在位置方框內執行多任務模型(手部關鍵點、左右手分類),並且透過關鍵點的位置修正位置方框後輸出。

輸入

  • NORM_RECT:放大過的手部位置方框
  • IMAGE:完整的圖片

輸出

  • NORM_RECT:根據手掌關鍵點反推的手部位置方框
  • LANDMARKS:手掌關鍵點的 3D 位置
  • PRESENCE:是否為手
  • HANDEDNESS:左右手分類結果

這個 Graph 雖然可以正確執行,但是輸出的 FPS 比較低,在我的電腦上只能跑出 12 FPS 左右的速度,在一般手機上可能會更慢。

Detection + Landmarks 執行結果。來源:自製

Hand Tracking

MediaPipe的官方 demo 給了更順暢的 Graph。沒有修改任何模型,只是加入了一些 Circle 與邏輯條件運算。建構出的 Graph 如下,虛線的部份表示 Circle 中的 back edge:

Hand Tracking Graph。來源:MediaPipe

這個 Graph 的設計概念是 Landmark Tracking:利用 Hand Landmark 的結果來略過 Hand Detection ,進而提升整體的 FPS。

這個原理在於 Hand Landmark 的輸出手掌關鍵點是可以反推回手掌的位置方框的,所以透過單獨的循環呼叫 Hand Landmark 也可以持續更新 NOMR_RECT,而不需要呼叫 Hand Detection。當 Hand Landmark 判斷跟蹤失敗的時候,才需要重新計算 Hand Detection 取得新的 NORM_RECT。

這個實作中,仰賴 3 個關鍵的 Calculator:

  • Previous Lookback Calculator:暫存一個 input,並在運行時直接輸出這個值。
  • Gate Calculator:如果條件不成立,就不執行之後的 Node。
  • Merge Calculator:從多個可能為空 inputs 中,輸出一個不為空的值。

這個 Graph 在 Hand Detection 前後分別加入了 Gate Calculator 與 Merge Calculator。當前一幀的 Hand Landmarks 有檢測到手的時候,Gate 就會關閉並且暫停 Hand Detection的運算。並且在其之後使用 Merge,將上一幀的 NORM_RECT 作為下一幀的 NOMR_RECT 輸入使用。而 Previous Lookback 的作用會確保即使模型還在推理仍然能順暢的跑下面的 Nodes。

最後看一下結果。透過減少 Detection 的推理次數,運行的 FPS 提高到 20 左右,處理時間也從本來的 77.3ms 降低到 47.6ms,減少了 38.5%。重點是效果絲毫未減。

Hand Tracking 執行結果。來源:自製

有興趣的同學,可以上 MediaPipe Visualizer 去搭建看看自己的 Graph:

附上 MediaPipe Visualizer 的使用說明:

結語

其實深度學習不只有模型訓練與推理,前後的資料流處理也是相當重要的一環。這篇文章闡述了一個好的 Pipeline 如何影響程式執行的效率,也示範了如何用 MediaPipe Visualizer 快速完成一個 demo,甚至不需要安裝 IDE 就能使用。

MediaPipe 裡面還有許多相當好的 Graph 與 Calculator,大家可以自行研究。另外,其 Source Code 本身也是一個非常好的示範教材,示範了怎麼寫出一個高耦合低內聚的開發框架。

--

--

Rice Yang
Rice Yang

Written by Rice Yang

A Tech Manager in AI. Experienced in NVIDIA, Alibaba, Pony.ai. Familiar with Deep Learning, Computer Vision, Software Engineering, Autonomous Driving

No responses yet