MediaPipe Face Landmarker 工作可讓您在圖片和影片中偵測臉部特徵和表情。您可以使用這項工作來辨識人類臉部表情、套用臉部濾鏡和特效,以及建立虛擬顯示圖片。這項工作會使用機器學習 (ML) 模型,可處理單張圖片、影片或持續傳送的圖片串流。這項工作會輸出 3D 臉部地標、混合形狀分數 (代表臉部表情的係數),以便即時推斷臉部表面的詳細資料,以及轉換矩陣,執行特效算繪所需的轉換。
您可以在 GitHub 上找到這些操作說明中所述的程式碼範例。您可以查看這個網頁示範,瞭解這項工作的實際運作情形。如要進一步瞭解這項工作的功能、模型和設定選項,請參閱總覽。
程式碼範例
MediaPipe Tasks 範例程式碼是 iOS 專用 Face Landmarker 應用程式的基本實作,這個範例會使用實體 iOS 裝置的相機,在持續的影片串流中偵測臉部特徵點。應用程式也可以偵測裝置相片庫中圖片和影片中的臉部特徵點。
您可以將該應用程式做為 iOS 應用程式的起點,也可以在修改現有應用程式時參照這個應用程式。Face 地標 er 程式碼範例於 GitHub 託管。
下載程式碼
以下操作說明說明如何使用 git 指令列工具,建立範例程式碼的本機副本。
下載程式碼範例:
使用下列指令複製 git 存放區:
git clone https://github.com/google-ai-edge/mediapipe-samples
您可以選擇將 Git 例項設定為使用稀疏檢查,這樣就只會取得 Face Landmarker 範例應用程式的檔案:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/face_landmarker/ios
建立範例程式碼的本機版本後,您可以安裝 MediaPipe 工作程式庫、使用 Xcode 開啟專案,然後執行應用程式。如需操作說明,請參閱 iOS 設定指南。
重要元件
下列檔案包含 Face Landmarker 範例應用程式的關鍵程式碼:
- FaceLandmarkerService.swift:初始化 Face Landmarker、處理模型選取作業,並針對輸入資料執行推論。
- CameraViewController.swift:為即時攝影機動態饋給輸入模式實作 UI,並將結果以視覺化方式呈現。
- MediaLibraryViewController.swift:為靜態圖片和影片檔案輸入模式實作 UI,並將結果以視覺化方式呈現。
設定
本節將說明設定開發環境和程式碼專案,以便使用 Face Landmarker 的關鍵步驟。如需使用 MediaPipe 工作設定開發環境的一般資訊 (包括平台版本要求),請參閱 iOS 設定指南。
依附元件
Face Landmarker 會使用 MediaPipeTasksVision
程式庫,必須使用 CocoaPods 安裝。這個程式庫與 Swift 和 Objective-C 應用程式相容,且不需要任何額外的語言專屬設定。
如需在 macOS 上安裝 CocoaPods 的操作說明,請參閱 CocoaPods 安裝指南。如需有關如何為應用程式建立包含必要 Pod 的 Podfile
的操作說明,請參閱「使用 CocoaPods」一文。
使用下列程式碼,在 Podfile
中新增 MediaPipeTasksVision
Pod:
target 'MyFaceLandmarkerApp' do
use_frameworks!
pod 'MediaPipeTasksVision'
end
如果應用程式包含單元測試目標,請參閱「iOS 設定指南」,進一步瞭解如何設定 Podfile
。
型號
MediaPipe Face Landmarker 工作需要經過訓練且與這項工作相容的模型組合。如要進一步瞭解可用於臉部地標的已訓練模型,請參閱工作總覽的「模型」一節。
選取並下載模型,然後使用 Xcode 將模型新增至專案目錄。如需在 Xcode 專案中新增檔案的操作說明,請參閱「管理 Xcode 專案中的檔案和資料夾」。
使用 BaseOptions.modelAssetPath
屬性指定應用程式套件中的模型路徑。如需程式碼範例,請參閱下一節。
建立工作
您可以呼叫其中一個初始化器,建立臉部標記工作。FaceLandmarker(options:)
初始化器可接受設定選項的值。
如果您不需要透過自訂設定選項初始化的臉部地標,可以使用 FaceLandmarker(modelPath:)
初始化器建立含有預設選項的 Face 地標。如要進一步瞭解設定選項,請參閱設定總覽。
Face Landmarker 工作支援 3 種輸入資料類型:靜態圖片、影片檔案和即時影片串流。根據預設,FaceLandmarker(modelPath:)
會初始化靜態圖片的工作。如要初始化工作以處理影片檔案或直播影片串流,請使用 FaceLandmarker(options:)
指定影片或即時串流執行模式。直播模式也需要額外的 faceLandmarkerLiveStreamDelegate
設定選項,讓臉部標記器能夠以非同步方式將臉部標記器結果傳送給委派函式。
請選擇對應於執行模式的分頁,瞭解如何建立工作並執行推論。
Swift
圖片
import MediaPipeTasksVision let modelPath = Bundle.main.path( forResource: "face_landmarker", ofType: "task") let options = FaceLandmarkerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .image options.minFaceDetectionConfidence = minFaceDetectionConfidence options.minFacePresenceConfidence = minFacePresenceConfidence options.minTrackingConfidence = minTrackingConfidence options.numFaces = numFaces let faceLandmarker = try FaceLandmarker(options: options)
影片
import MediaPipeTasksVision let modelPath = Bundle.main.path( forResource: "face_landmarker", ofType: "task") let options = FaceLandmarkerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .video options.minFaceDetectionConfidence = minFaceDetectionConfidence options.minFacePresenceConfidence = minFacePresenceConfidence options.minTrackingConfidence = minTrackingConfidence options.numFaces = numFaces let faceLandmarker = try FaceLandmarker(options: options)
直播
import MediaPipeTasksVision // Class that conforms to the `FaceLandmarkerLiveStreamDelegate` protocol and // implements the method that the face landmarker calls once it finishes // performing face landmark detection in each input frame. class FaceLandmarkerResultProcessor: NSObject, FaceLandmarkerLiveStreamDelegate { func faceLandmarker( _ faceLandmarker: FaceLandmarker, didFinishDetection result: FaceLandmarkerResult?, timestampInMilliseconds: Int, error: Error?) { // Process the face landmarker result or errors here. } } let modelPath = Bundle.main.path( forResource: "face_landmarker", ofType: "task") let options = FaceLandmarkerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .liveStream options.minFaceDetectionConfidence = minFaceDetectionConfidence options.minFacePresenceConfidence = minFacePresenceConfidence options.minTrackingConfidence = minTrackingConfidence options.numFaces = numFaces // Assign an object of the class to the `faceLandmarkerLiveStreamDelegate` // property. let processor = FaceLandmarkerResultProcessor() options.faceLandmarkerLiveStreamDelegate = processor let faceLandmarker = try FaceLandmarker(options: options)
Objective-C
圖片
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"face_landmarker" ofType:@"task"]; MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeImage; options.minFaceDetectionConfidence = minFaceDetectionConfidence; options.minFacePresenceConfidence = minFacePresenceConfidence; options.minTrackingConfidence = minTrackingConfidence; options.numFaces = numFaces; MPPFaceLandmarker *faceLandmarker = [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
影片
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"face_landmarker" ofType:@"task"]; MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeVideo; options.minFaceDetectionConfidence = minFaceDetectionConfidence; options.minFacePresenceConfidence = minFacePresenceConfidence; options.minTrackingConfidence = minTrackingConfidence; options.numFaces = numFaces; MPPFaceLandmarker *faceLandmarker = [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
直播
@import MediaPipeTasksVision; // Class that conforms to the `MPPFaceLandmarkerLiveStreamDelegate` protocol // and implements the method that the face landmarker calls once it finishes // performing face landmark detection in each input frame. @interface APPFaceLandmarkerResultProcessor : NSObject@end @implementation APPFaceLandmarkerResultProcessor - (void)faceLandmarker:(MPPFaceLandmarker *)faceLandmarker didFinishDetectionWithResult:(MPPFaceLandmarkerResult *)faceLandmarkerResult timestampInMilliseconds:(NSInteger)timestampInMilliseconds error:(NSError *)error { // Process the face landmarker result or errors here. } @end NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"face_landmarker" ofType:@"task"]; MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeLiveStream; options.minFaceDetectionConfidence = minFaceDetectionConfidence; options.minFacePresenceConfidence = minFacePresenceConfidence; options.minTrackingConfidence = minTrackingConfidence; options.numFaces = numFaces; // Assign an object of the class to the `faceLandmarkerLiveStreamDelegate` // property. APPFaceLandmarkerResultProcessor *processor = [APPFaceLandmarkerResultProcessor new]; options.faceLandmarkerLiveStreamDelegate = processor; MPPFaceLandmarker *faceLandmarker = [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
注意:如果您使用影片模式或直播模式,Face Landmarker 會使用追蹤功能,避免在每個影格中觸發偵測模型,以便減少延遲時間。
設定選項
此工作包含下列 iOS 應用程式的設定選項:
選項名稱 | 說明 | 值範圍 | 預設值 |
---|---|---|---|
runningMode |
設定任務的執行模式。Face Landmarker 有三種模式:
圖片:單張圖片輸入模式。 影片:影片已解碼影格的模式。 LIVE_STREAM:串流輸入資料 (例如相機) 的模式。 在這個模式中,`faceLandmarkerLiveStreamDelegate` 必須設為實作 `FaceLandmarkerLiveStreamDelegate` 的類別例項,才能以非同步方式接收執行臉部地標偵測的結果。 |
{RunningMode.image, RunningMode.video, RunningMode.liveStream} | {RunningMode.image} |
numFaces |
Face Landmarker 可偵測的臉孔數量上限。只有在 numFaces 設為 1 時才會套用平滑處理。 | 整數 > 0 | 1 |
minFaceDetectionConfidence |
系統判定臉部偵測成功的最低可信度分數。 | 浮點值 [0.0,1.0] | 0.5 |
minFacePresenceConfidence |
臉部地標偵測功能中臉部指標的最低可信度分數。 | 浮點值 [0.0,1.0] | 0.5 |
minTrackingConfidence |
臉部追蹤必須達到的最低可信度分數,才能視為成功。 | 浮點值 [0.0,1.0] | 0.5 |
outputFaceBlendshapes |
FaceLandmarker 是否會輸出臉部混合形狀。臉部混合形狀用於算繪 3D 臉部模型。 | 布林值 | false |
outputFacialTransformationMatrixes |
FaceLandmarker 是否會輸出臉部轉換矩陣。FaceLandmarker 會使用矩陣將臉部標記從標準臉部模型轉換為偵測到的臉部,方便使用者在偵測到的標記上套用效果。 | 布林值 | false |
當跑步模式設為 LIVE_STREAM
時,臉部地標需要額外的 faceLandmarkerLiveStreamDelegate
設定選項,讓臉部地標可以非同步提供臉部地標的偵測結果。委派程式必須實作 faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:)
方法,Face Landmarker 會在處理對每個影格執行臉部地標偵測的結果後呼叫此方法。
選項名稱 | 說明 | 值範圍 | 預設值 |
---|---|---|---|
faceLandmarkerLiveStreamDelegate |
讓 Face Landmarker 在即時串流模式中以非同步方式接收臉部特徵偵測結果。將例項設為此屬性的類別,必須實作 faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) 方法。 |
不適用 | 未設定 |
準備資料
您必須先將輸入圖片或影格轉換為 MPImage
物件,才能將其傳遞至 Face Landmarker。MPImage
支援不同類型的 iOS 圖片格式,可在任何執行中模式使用來推論。如要進一步瞭解 MPImage
,請參閱 MPImage API。
請根據用途和應用程式所需的執行模式,選擇 iOS 圖片格式。MPImage
接受 UIImage
、CVPixelBuffer
和 CMSampleBuffer
iOS 圖片格式。
UIImage
UIImage
格式非常適合下列執行模式:
圖片:應用程式套件、使用者相片庫或檔案系統中的圖片,如果以
UIImage
圖片格式編碼,即可轉換為MPImage
物件。影片:使用 AVAssetImageGenerator 將影片影格擷取為 CGImage 格式,然後轉換為
UIImage
圖片。
Swift
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(uiImage: image)
Objective-C
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
這個範例會使用預設的 UIImage.Orientation.Up 方向初始化 MPImage
。您可以使用任何支援的 UIImage.Orientation 值初始化 MPImage
。臉孔地標不支援鏡像方向,例如 .upMirrored
、.downMirrored
、.leftMirrored
、.rightMirrored
。
如要進一步瞭解 UIImage
,請參閱 UIImage Apple 開發人員說明文件。
CVPixelBuffer
CVPixelBuffer
格式非常適合用於產生影格和使用 iOS CoreImage 架構處理的應用程式。
CVPixelBuffer
格式非常適合下列執行模式:
圖片:如果應用程式在使用 iOS 的
CoreImage
架構進行部分處理後,產生CVPixelBuffer
圖片,則可在圖片執行模式下傳送至 Face Landmarker。影片:可將影片影格轉換為
CVPixelBuffer
格式進行處理,然後以影片模式傳送至 Face Landmarker。直播:使用 iOS 相機產生影格時,應用程式可能會先將影格轉換成
CVPixelBuffer
格式進行處理,再以直播模式傳送至 Face Landmarker。
Swift
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(pixelBuffer: pixelBuffer)
Objective-C
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
如要進一步瞭解 CVPixelBuffer
,請參閱 CVPixelBuffer Apple 開發人員說明文件。
CMSampleBuffer
CMSampleBuffer
格式會儲存統一媒體類型的媒體樣本,非常適合直播執行模式。iOS AVCaptureVideoDataOutput 會以 CMSampleBuffer
格式,以非同步方式傳送 iOS 攝影機的即時影格。
Swift
// Obtain a CMSampleBuffer. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(sampleBuffer: sampleBuffer)
Objective-C
// Obtain a `CMSampleBuffer`. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
如要進一步瞭解 CMSampleBuffer
,請參閱 CMSampleBuffer Apple 開發人員說明文件。
執行工作
如要執行臉部標記器,請使用指派的執行模式專用的 detect()
方法:
- 靜態圖片:
detect(image:)
- 影片:
detect(videoFrame:timestampInMilliseconds:)
- 直播:
detectAsync(image:timestampInMilliseconds:)
以下程式碼範例提供如何在這些不同執行模式下執行 Face Landmarker 的基本範例:
Swift
圖片
let result = try faceLandmarker.detect(image: image)
影片
let result = try faceLandmarker.detect( videoFrame: image, timestampInMilliseconds: timestamp)
直播
try faceLandmarker.detectAsync( image: image, timestampInMilliseconds: timestamp)
Objective-C
圖片
MPPFaceLandmarkerResult *result = [faceLandmarker detectImage:image error:nil];
影片
MPPFaceLandmarkerResult *result = [faceLandmarker detectVideoFrame:image timestampInMilliseconds:timestamp error:nil];
直播
BOOL success = [faceLandmarker detectAsyncImage:image timestampInMilliseconds:timestamp error:nil];
臉部地標程式碼範例會更詳細說明這些模式的實作方式,包括 detect(image:)
、detect(videoFrame:timestampInMilliseconds:)
和 detectAsync(image:timestampInMilliseconds:)
。程式碼範例可讓使用者在處理模式之間切換,但這可能不是您使用情境所需的功能。
注意事項:
在影片模式或直播模式下執行時,您也必須向 Face Landmarker 工作提供輸入影格時間戳記。
在圖片或影片模式下執行時,Face Landmarker 工作會阻斷目前的執行緒,直到處理完輸入圖片或影格為止。為避免阻斷目前執行緒,請使用 iOS Dispatch 或 NSOperation 架構,在背景執行緒中執行處理作業。如果您使用 Swift 建立應用程式,也可以使用 Swift 並行處理執行背景執行緒。
在直播模式下執行時,臉部標記器工作會立即傳回,且不會封鎖目前的執行緒。在處理每個輸入影格後,會使用臉部地標偵測結果呼叫
faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:)
方法。臉部地標程式會在專屬的序列調度佇列中,以非同步方式叫用這個方法。如要在使用者介面上顯示結果,請在處理結果後將結果調度至主佇列。
處理及顯示結果
執行推論時,臉部地標會傳回 FaceLandmarkerResult
,其中包含每個偵測到的臉孔的臉部網格,以及每個臉部地標的座標。或者,結果物件也可以包含表示臉部運算式的混合形狀,以及臉部轉換矩陣,以對偵測到的地標套用臉部特效。
以下是這項工作的輸出資料範例:
FaceLandmarkerResult:
face_landmarks:
NormalizedLandmark #0:
x: 0.5971359014511108
y: 0.485361784696579
z: -0.038440968841314316
NormalizedLandmark #1:
x: 0.3302789330482483
y: 0.29289937019348145
z: -0.09489090740680695
... (478 landmarks for each face)
face_blendshapes:
browDownLeft: 0.8296722769737244
browDownRight: 0.8096957206726074
browInnerUp: 0.00035583582939580083
browOuterUpLeft: 0.00035752105759456754
... (52 blendshapes for each face)
facial_transformation_matrixes:
[9.99158978e-01, -1.23036895e-02, 3.91213447e-02, -3.70770246e-01]
[1.66496094e-02, 9.93480563e-01, -1.12779640e-01, 2.27719707e+01]
...
下圖是工作輸出內容的視覺化呈現:
臉部地標範例程式碼示範如何顯示工作傳回的結果,詳情請參閱 FaceOverlay.swift。