您可以使用ML Kit來偵測影像和影片中的人臉。
在你開始之前
- 如果您尚未將 Firebase 新增至您的應用程式中,請按照入門指南中的步驟進行操作。
- 在 Podfile 中包含 ML Kit 函式庫:
pod 'Firebase/MLVision', '6.25.0' # If you want to detect face contours (landmark detection and classification # don't require this additional model): pod 'Firebase/MLVisionFaceModel', '6.25.0'
安裝或更新專案的 Pod 後,請務必使用其.xcworkspace
開啟 Xcode 專案。 - 在您的應用程式中,導入 Firebase:
迅速
import Firebase
Objective-C
@import Firebase;
輸入影像指南
為了讓 ML Kit 準確地偵測人臉,輸入影像必須包含由足夠的像素資料表示的人臉。一般來說,您想要在影像中偵測的每張臉應至少為 100x100 像素。如果要偵測人臉輪廓,ML Kit 需要更高解析度的輸入:每張人臉至少應為 200x200 像素。
如果您在即時應用程式中偵測人臉,您可能還需要考慮輸入影像的整體尺寸。較小的影像可以更快地處理,因此為了減少延遲,請以較低的解析度擷取影像(記住上述精度要求)並確保主體的臉部盡可能佔據影像。另請參閱提高即時效能的提示。
影像聚焦不良會影響準確性。如果您沒有獲得可接受的結果,請嘗試要求使用者重新捕捉影像。
臉部相對於相機的方向也會影響 ML Kit 偵測到的臉部特徵。請參閱人臉偵測概念。
1.配置人臉偵測器
在將臉部偵測套用至影像之前,如果要變更任何臉部偵測器的預設設置,請使用VisionFaceDetectorOptions
物件指定這些設定。您可以更改以下設定:設定 | |
---|---|
performanceMode | fast (預設)| accurate 偵測人臉時優先考慮速度或準確性。 |
landmarkMode | none (預設)| all 是否嘗試偵測所有偵測到的臉孔的臉部「地標」(眼睛、耳朵、鼻子、臉頰、嘴巴)。 |
contourMode | none (預設)| all 是否偵測臉部特徵輪廓。僅檢測影像中最突出的臉部的輪廓。 |
classificationMode | none (預設)| all 是否將臉孔分類為「微笑」和「睜開眼睛」等類別。 |
minFaceSize | CGFloat (預設值: 0.1 )要偵測的臉部相對於影像的最小尺寸。 |
isTrackingEnabled | false (預設)| true 是否為人臉分配 ID,可用於跨影像追蹤人臉。 請注意,啟用輪廓偵測後,僅偵測到一張臉部,因此臉部追蹤不會產生有用的結果。因此,為了提高偵測速度,請勿同時啟用輪廓偵測和臉部追蹤。 |
例如,建立一個VisionFaceDetectorOptions
對象,如以下範例之一:
迅速
// High-accuracy landmark detection and face classification let options = VisionFaceDetectorOptions() options.performanceMode = .accurate options.landmarkMode = .all options.classificationMode = .all // Real-time contour detection of multiple faces let options = VisionFaceDetectorOptions() options.contourMode = .all
Objective-C
// High-accuracy landmark detection and face classification FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init]; options.performanceMode = FIRVisionFaceDetectorPerformanceModeAccurate; options.landmarkMode = FIRVisionFaceDetectorLandmarkModeAll; options.classificationMode = FIRVisionFaceDetectorClassificationModeAll; // Real-time contour detection of multiple faces FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init]; options.contourMode = FIRVisionFaceDetectorContourModeAll;
2. 運行人臉偵測器
若要偵測影像中的人臉,請將影像作為UIImage
或CMSampleBufferRef
傳遞給VisionFaceDetector
的detect(in:)
方法:- 取得
VisionFaceDetector
的實例:迅速
lazy var vision = Vision.vision() let faceDetector = vision.faceDetector(options: options)
Objective-C
FIRVision *vision = [FIRVision vision]; FIRVisionFaceDetector *faceDetector = [vision faceDetector]; // Or, to change the default settings: // FIRVisionFaceDetector *faceDetector = // [vision faceDetectorWithOptions:options];
使用
UIImage
或CMSampleBufferRef
建立VisionImage
物件。使用
UIImage
:- 如有必要,旋轉影像,使其
imageOrientation
屬性為.up
。 - 使用正確旋轉的
UIImage
建立VisionImage
物件。不要指定任何旋轉元資料 - 必須使用預設值.topLeft
。迅速
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
使用
CMSampleBufferRef
:建立一個
VisionImageMetadata
對象,該對象指定CMSampleBufferRef
緩衝區中包含的圖像資料的方向。若要取得影像方向:
迅速
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Objective-C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
然後,建立元資料物件:
迅速
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- 使用
CMSampleBufferRef
物件和旋轉元資料建立VisionImage
物件:迅速
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- 如有必要,旋轉影像,使其
- 然後,將圖像傳遞給
detect(in:)
方法:迅速
faceDetector.process(visionImage) { faces, error in guard error == nil, let faces = faces, !faces.isEmpty else { // ... return } // Faces detected // ... }
Objective-C
[faceDetector detectInImage:image completion:^(NSArray<FIRVisionFace *> *faces, NSError *error) { if (error != nil) { return; } else if (faces != nil) { // Recognized faces } }];
3. 取得偵測到的人臉資訊
如果臉部偵測操作成功,臉部偵測器會將VisionFace
物件陣列傳遞給完成處理程序。每個VisionFace
物件代表在影像中偵測到的一張臉。對於每張臉,您都可以獲得其在輸入影像中的邊界座標,以及配置臉部偵測器要尋找的任何其他資訊。例如: 迅速
for face in faces { let frame = face.frame if face.hasHeadEulerAngleY { let rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees } if face.hasHeadEulerAngleZ { let rotZ = face.headEulerAngleZ // Head is rotated upward rotZ degrees } // If landmark detection was enabled (mouth, ears, eyes, cheeks, and // nose available): if let leftEye = face.landmark(ofType: .leftEye) { let leftEyePosition = leftEye.position } // If contour detection was enabled: if let leftEyeContour = face.contour(ofType: .leftEye) { let leftEyePoints = leftEyeContour.points } if let upperLipBottomContour = face.contour(ofType: .upperLipBottom) { let upperLipBottomPoints = upperLipBottomContour.points } // If classification was enabled: if face.hasSmilingProbability { let smileProb = face.smilingProbability } if face.hasRightEyeOpenProbability { let rightEyeOpenProb = face.rightEyeOpenProbability } // If face tracking was enabled: if face.hasTrackingID { let trackingId = face.trackingID } }
Objective-C
for (FIRVisionFace *face in faces) { // Boundaries of face in image CGRect frame = face.frame; if (face.hasHeadEulerAngleY) { CGFloat rotY = face.headEulerAngleY; // Head is rotated to the right rotY degrees } if (face.hasHeadEulerAngleZ) { CGFloat rotZ = face.headEulerAngleZ; // Head is tilted sideways rotZ degrees } // If landmark detection was enabled (mouth, ears, eyes, cheeks, and // nose available): FIRVisionFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar]; if (leftEar != nil) { FIRVisionPoint *leftEarPosition = leftEar.position; } // If contour detection was enabled: FIRVisionFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom]; if (upperLipBottomContour != nil) { NSArray<FIRVisionPoint *> *upperLipBottomPoints = upperLipBottomContour.points; if (upperLipBottomPoints.count > 0) { NSLog("Detected the bottom contour of the subject's upper lip.") } } // If classification was enabled: if (face.hasSmilingProbability) { CGFloat smileProb = face.smilingProbability; } if (face.hasRightEyeOpenProbability) { CGFloat rightEyeOpenProb = face.rightEyeOpenProbability; } // If face tracking was enabled: if (face.hasTrackingID) { NSInteger trackingID = face.trackingID; } }
臉部輪廓範例
啟用臉部輪廓偵測後,您將獲得偵測到的每個臉部特徵的點列表。這些點代表特徵的形狀。有關如何表示輪廓的詳細信息,請參閱人臉檢測概念概述。
下圖說明了這些點如何映射到臉部(點擊圖像放大):
即時人臉偵測
如果您想在即時應用程式中使用人臉偵測,請遵循以下指南以獲得最佳幀速率:
將人臉偵測器配置為使用人臉輪廓偵測或分類和地標偵測,但不能同時使用兩者:
輪廓檢測
地標檢測
分類
地標檢測與分類
輪廓檢測和地標檢測
輪廓檢測和分類
輪廓檢測、地標檢測與分類啟用
fast
模式(預設啟用)。考慮以較低解析度捕捉影像。但是,也要記住此 API 的圖像尺寸要求。
- 對檢測器的節流呼叫。如果偵測器運作時有新的視訊幀可用,則丟棄該幀。
- 如果您使用偵測器的輸出將圖形疊加在輸入影像上,請先從 ML Kit 取得結果,然後一步渲染影像並疊加。透過這樣做,每個輸入幀只需渲染到顯示表面一次。有關範例,請參閱展示範例應用程式中的PreviewOverlayView和FIRDetectionOverlayView類別。