คุณใช้ ML Kit เพื่อตรวจจับใบหน้าในรูปภาพและวิดีโอได้
ลองใช้งาน
- ลองใช้แอปตัวอย่างเพื่อดูตัวอย่างการใช้งาน API นี้
- ลองใช้โค้ดด้วยตนเองโดยใช้ codelab
ข้อควรทราบก่อนที่จะเริ่มต้น
- รวมพ็อด ML Kit ต่อไปนี้ใน Podfile
pod 'GoogleMLKit/FaceDetection', '3.2.0'
- หลังจากติดตั้งหรืออัปเดตพ็อดของโปรเจ็กต์ ให้เปิดโปรเจ็กต์ Xcode โดยใช้
.xcworkspace
XKit เวอร์ชัน 12.4 ขึ้นไปรองรับ ML Kit
หลักเกณฑ์เกี่ยวกับรูปภาพที่ป้อน
สําหรับการจดจําใบหน้า คุณควรใช้รูปภาพที่มีขนาดอย่างน้อย 480x360 พิกเซล เพื่อให้ ML Kit ตรวจจับใบหน้าได้อย่างถูกต้อง รูปภาพอินพุตต้องมีใบหน้าที่แสดงข้อมูลพิกเซลเพียงพอ โดยทั่วไป ใบหน้าแต่ละใบหน้าที่คุณต้องการตรวจจับในรูปภาพควรมีขนาดอย่างน้อย 100x100 พิกเซล หากต้องการตรวจจับการเกิดขึ้นของใบหน้า ML Kit ต้องใช้อินพุตที่มีความละเอียดสูงกว่า นั่นคือแต่ละใบหน้าควรมีขนาดอย่างน้อย 200x200 พิกเซล
หากตรวจพบใบหน้าในแอปพลิเคชันแบบเรียลไทม์ คุณอาจต้องพิจารณาขนาดโดยรวมของรูปภาพที่ป้อนด้วย รูปภาพขนาดเล็กอาจประมวลผลได้เร็วขึ้น ดังนั้นหากต้องการลดเวลาในการตอบสนอง ให้จับภาพที่ความละเอียดต่ําลง แต่อย่าลืมคํานึงถึงข้อกําหนดข้างต้นด้วย และตรวจดูว่าใบหน้าของวัตถุใช้รูปภาพให้มากที่สุดเท่าที่จะทําได้ และดูเคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์
การโฟกัสรูปภาพที่ไม่ดีอาจส่งผลต่อความแม่นยําได้ หากไม่ได้รับผลการค้นหาที่ยอมรับได้ โปรดขอให้ผู้ใช้จับภาพอีกครั้ง
การวางแนวใบหน้าที่สัมพันธ์กับกล้องยังส่งผลต่อฟีเจอร์ใบหน้าซึ่ง ML Kit ตรวจจับได้ด้วย ดูแนวคิดการตรวจจับใบหน้า
1. กําหนดค่าตัวตรวจจับใบหน้า
ก่อนที่จะใช้การตรวจจับใบหน้ากับรูปภาพ หากต้องการเปลี่ยนการตั้งค่าเริ่มต้นของตัวตรวจจับใบหน้า ให้ระบุการตั้งค่าเหล่านั้นด้วยออบเจ็กต์FaceDetectorOptions
คุณสามารถเปลี่ยนการตั้งค่าต่อไปนี้ได้
การตั้งค่า | |
---|---|
performanceMode |
fast (ค่าเริ่มต้น) | accurate
เพิ่มความเร็วหรือความแม่นยําเมื่อตรวจจับใบหน้า |
landmarkMode |
none (ค่าเริ่มต้น) | all
พยายามตรวจจับ "ใบหน้า" ใบหน้า หู หู จมูก แก้ม ปาก จากใบหน้าที่ตรวจพบทั้งหมดหรือไม่ |
contourMode |
none (ค่าเริ่มต้น) | all
จะตรวจหาความผิดเพี้ยนของลักษณะใบหน้าหรือไม่ ระบบตรวจพบรูปร่างรอบตัวคุณเฉพาะสําหรับใบหน้าที่โดดเด่นที่สุดในรูปภาพ |
classificationMode |
none (ค่าเริ่มต้น) | all
แยกประเภทใบหน้าออกเป็นหมวดหมู่ต่างๆ เช่น "ยิ้ม" และ "ลืมตา" หรือไม่ |
minFaceSize |
CGFloat (ค่าเริ่มต้น: 0.1 )
ตั้งค่าขนาดใบหน้าที่ต้องการขนาดเล็กที่สุด ซึ่งแสดงเป็นอัตราส่วนของความกว้างของส่วนหัวต่อความกว้างของรูปภาพ |
isTrackingEnabled |
false (ค่าเริ่มต้น) | true
กําหนดรหัสให้กับใบหน้าหรือไม่ ซึ่งสามารถใช้เพื่อติดตามใบหน้าในรูปภาพต่างๆ ได้ โปรดทราบว่าเมื่อเปิดใช้การตรวจจับใบหน้า ระบบจะตรวจพบเพียงใบหน้าเดียวเท่านั้น การติดตามใบหน้าจึงไม่ได้ให้ผลลัพธ์ที่เป็นประโยชน์ ดังนั้น คุณต้องเปิดใช้ทั้งการตรวจจับด้วยแสงและการติดตามใบหน้าเพื่อปรับปรุงความเร็วการตรวจจับ |
เช่น สร้างออบเจ็กต์ FaceDetectorOptions
ดังตัวอย่างต่อไปนี้
Swift
// High-accuracy landmark detection and face classification let options = FaceDetectorOptions() options.performanceMode = .accurate options.landmarkMode = .all options.classificationMode = .all // Real-time contour detection of multiple faces // options.contourMode = .all
Objective-C
// High-accuracy landmark detection and face classification MLKFaceDetectorOptions *options = [[MLKFaceDetectorOptions alloc] init]; options.performanceMode = MLKFaceDetectorPerformanceModeAccurate; options.landmarkMode = MLKFaceDetectorLandmarkModeAll; options.classificationMode = MLKFaceDetectorClassificationModeAll; // Real-time contour detection of multiple faces // options.contourMode = MLKFaceDetectorContourModeAll;
2. เตรียมรูปภาพอินพุต
หากต้องการตรวจจับใบหน้าในรูปภาพ ให้ส่งรูปภาพเป็นUIImage
หรือ CMSampleBufferRef
ไปยัง FaceDetector
โดยใช้เมธอด process(_:completion:)
หรือ results(in:)
ดังนี้
สร้างออบเจ็กต์ VisionImage
โดยใช้ UIImage
หรือ CMSampleBuffer
หากคุณใช้ UIImage
ให้ทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์
VisionImage
ด้วยUIImage
ตรวจสอบว่าได้ระบุ.orientation
ที่ถูกต้องSwift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
หากคุณใช้ CMSampleBuffer
ให้ทําตามขั้นตอนต่อไปนี้
-
ระบุการวางแนวของข้อมูลรูปภาพที่มีอยู่ใน
CMSampleBuffer
วิธีดูการวางแนวรูปภาพ
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> UIImage.Orientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftMirrored : .right case .landscapeLeft: return cameraPosition == .front ? .downMirrored : .up case .portraitUpsideDown: return cameraPosition == .front ? .rightMirrored : .left case .landscapeRight: return cameraPosition == .front ? .upMirrored : .down case .faceDown, .faceUp, .unknown: return .up } }
Objective-C
- (UIImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- สร้างออบเจ็กต์
VisionImage
โดยใช้ออบเจ็กต์CMSampleBuffer
และการวางแนวดังนี้Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. รับอินสแตนซ์ของ FaceDetector
รับอินสแตนซ์ของ FaceDetector
Swift
let faceDetector = FaceDetector.faceDetector(options: options)
Objective-C
MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
4. ประมวลผลรูปภาพ
จากนั้นส่งรูปภาพไปยังเมธอดprocess()
ดังนี้
Swift
weak var weakSelf = self faceDetector.process(visionImage) { faces, error in guard let strongSelf = weakSelf else { print("Self is nil!") return } guard error == nil, let faces = faces, !faces.isEmpty else { // ... return } // Faces detected // ... }
Objective-C
[faceDetector processImage:image completion:^(NSArray<MLKFace *> *faces, NSError *error) { if (error != nil) { return; } if (faces.count > 0) { // Recognized faces } }];
5. ดูข้อมูลเกี่ยวกับใบหน้าที่ตรวจพบ
หากการดําเนินการตรวจจับใบหน้าสําเร็จ เครื่องมือตรวจจับใบหน้าจะส่งอาร์เรย์ของออบเจ็กต์Face
ไปยังเครื่องจัดการจนเสร็จสมบูรณ์ ออบเจ็กต์ Face
แต่ละรายการแสดงถึงใบหน้าที่ตรวจพบในรูปภาพ สําหรับใบหน้าแต่ละใบหน้า คุณจะเห็นพิกัดที่ล้อมรอบอยู่ในรูปภาพอินพุต รวมถึงข้อมูลอื่นๆ ที่คุณกําหนดค่าตัวตรวจจับใบหน้าให้ค้นหา เช่น
Swift
for face in faces { let frame = face.frame if face.hasHeadEulerAngleX { let rotX = face.headEulerAngleX // Head is rotated to the uptoward rotX degrees } if face.hasHeadEulerAngleY { let rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees } if face.hasHeadEulerAngleZ { let rotZ = face.headEulerAngleZ // Head is tilted sideways 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 (MLKFace *face in faces) { // Boundaries of face in image CGRect frame = face.frame; if (face.hasHeadEulerAngleX) { CGFloat rotX = face.headEulerAngleX; // Head is rotated to the upward rotX degrees } 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): MLKFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar]; if (leftEar != nil) { MLKVisionPoint *leftEarPosition = leftEar.position; } // If contour detection was enabled: MLKFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom]; if (upperLipBottomContour != nil) { NSArray<MLKVisionPoint *> *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; } }
ตัวอย่างโครงสร้างของใบหน้า
เมื่อเปิดใช้การตรวจจับการเกิดขึ้นของใบหน้า คุณจะได้รับรายการคะแนนสําหรับฟีเจอร์ใบหน้าแต่ละรายการที่ตรวจพบ จุดเหล่านี้แสดงถึงรูปร่างของฟีเจอร์ ดูแนวคิดการตรวจจับใบหน้าสําหรับรายละเอียดเกี่ยวกับวิธีแสดงแนวคิด
รูปภาพต่อไปนี้แสดงลักษณะที่จุดเหล่านี้แมปกับใบหน้า คลิกรูปภาพเพื่อขยาย
การตรวจจับใบหน้าแบบเรียลไทม์
หากต้องการใช้การตรวจจับใบหน้าในแอปพลิเคชันแบบเรียลไทม์ ให้ทําตามหลักเกณฑ์ต่อไปนี้เพื่อให้อัตราเฟรมดีที่สุด
กําหนดค่าตัวตรวจจับใบหน้าเพื่อใช้การตรวจจับใบหน้าหรือการแยกประเภทใบหน้าและการตรวจหาจุดสังเกต แต่ไม่ใช่ทั้ง 2 อย่าง
การตรวจจับรอบทิศทาง
การตรวจจับจุดสังเกต
การแยกประเภทและการแยกประเภท
การตรวจจับและการแยกประเภทจุดสังเกต
การตรวจจับรอบทิศทางและการแยกประเภท
การตรวจจับและการแยกประเภท
การตรวจจับรอบทิศทาง การตรวจจับจุดสังเกต และการแยกประเภทเปิดใช้โหมด
fast
(เปิดใช้โดยค่าเริ่มต้น)ลองจับภาพที่ความละเอียดต่ําลง อย่างไรก็ตาม โปรดทราบว่า ข้อกําหนดด้านขนาดรูปภาพของ API นี้
- สําหรับการประมวลผลเฟรมวิดีโอ ให้ใช้
results(in:)
API แบบพร้อมกันของตัวตรวจจับ เรียกวิธีนี้จากฟังก์ชันcaptureOutput(_, didOutput:from:)
ของAVCaptureVideoDataOutputSampleBufferDelegate
เพื่อให้ได้ผลลัพธ์พร้อมกันจากเฟรมวิดีโอที่ระบุ เก็บalwaysDiscardsLateVideoFrames
ของAVCaptureVideoDataOutput
ไว้เป็นtrue
เพื่อควบคุมการโทรไปยังตัวตรวจจับ หาก เฟรมวิดีโอใหม่พร้อมใช้งานระหว่างตัวตรวจจับจะทํางาน เฟรมจะหายไป - หากใช้เอาต์พุตของตัวตรวจจับเพื่อวางซ้อนกราฟิกบนรูปภาพอินพุต ก่อนอื่นให้ดูผลลัพธ์จาก ML Kit จากนั้นแสดงผลรูปภาพและวางซ้อนในขั้นตอนเดียว เมื่อทําเช่นนั้น คุณจะแสดงผลบนพื้นที่แสดงผลเพียงครั้งเดียวสําหรับเฟรมอินพุตแต่ละรายการที่ประมวลผลแล้ว ดูตัวอย่าง update PreviewOverlayViewWithLastFrame ในตัวอย่างคู่มือเริ่มใช้งานฉบับย่อสําหรับ ML Kit