คุณใช้ ML Kit เพื่อตรวจหาและติดตามวัตถุในเฟรมวิดีโอต่อเนื่องได้
เมื่อส่งรูปภาพไปยัง ML Kit ระบบจะตรวจจับวัตถุสูงสุด 5 รายการในรูปภาพ พร้อมด้วยตำแหน่งของวัตถุแต่ละชิ้นในรูปภาพ เมื่อตรวจหาวัตถุในสตรีมวิดีโอ แต่ละวัตถุจะมีรหัสที่ไม่ซ้ำกันซึ่งคุณใช้เพื่อติดตามวัตถุจากเฟรมหนึ่งไปยังอีกเฟรมหนึ่งได้ คุณยังเปิดใช้การจัดประเภทออบเจ็กต์แบบคร่าวๆ ได้ด้วย ซึ่งจะติดป้ายกำกับออบเจ็กต์ที่มีคำอธิบายหมวดหมู่แบบกว้าง
ลองเลย
- ลองใช้แอปตัวอย่างเพื่อดูตัวอย่างการใช้งาน API นี้
- ดูแอปโชว์เคสดีไซน์ Material สำหรับการติดตั้งใช้งาน API นี้ตั้งแต่ต้นจนจบ
ก่อนเริ่มต้น
- รวมพ็อด ML Kit ต่อไปนี้ใน Podfile:
pod 'GoogleMLKit/ObjectDetection', '3.2.0'
- หลังจากติดตั้งหรืออัปเดตพ็อดของโปรเจ็กต์แล้ว ให้เปิดโปรเจ็กต์ Xcode โดยใช้
.xcworkspace
ของโปรเจ็กต์นั้น Xcode เวอร์ชัน 12.4 ขึ้นไปรองรับ ML Kit
1. กำหนดค่าตัวตรวจจับออบเจ็กต์
หากต้องการตรวจหาและติดตามออบเจ็กต์ ก่อนอื่นให้สร้างอินสแตนซ์ของ ObjectDetector
และเลือกระบุการตั้งค่าตัวตรวจจับที่คุณต้องการเปลี่ยนจากค่าเริ่มต้น
กำหนดค่าตัวตรวจจับออบเจ็กต์สำหรับ Use Case ของคุณด้วยออบเจ็กต์
ObjectDetectorOptions
คุณสามารถเปลี่ยนการตั้งค่าต่อไปนี้การตั้งค่าตัวตรวจจับออบเจ็กต์ โหมดการตรวจจับ .stream
(ค่าเริ่มต้น) |.singleImage
ในโหมดสตรีม (ค่าเริ่มต้น) ตัวตรวจจับออบเจ็กต์จะทำงานโดยมีเวลาในการตอบสนองต่ำมาก แต่อาจทำให้ได้ผลลัพธ์ไม่สมบูรณ์ (เช่น กรอบหรือหมวดหมู่ที่ไม่ได้ระบุ) ในการเรียกใช้ตัวตรวจจับ 2-3 ครั้งแรก นอกจากนี้ ในโหมดสตรีม ตัวตรวจจับจะกำหนดรหัสติดตามให้กับออบเจ็กต์ ซึ่งคุณสามารถใช้เพื่อติดตามออบเจ็กต์ในเฟรมได้ ใช้โหมดนี้เมื่อคุณต้องการติดตามออบเจ็กต์ หรือเมื่อเวลาในการตอบสนองต่ำเป็นสิ่งสำคัญ เช่น เมื่อประมวลผลสตรีมวิดีโอแบบเรียลไทม์
ในโหมดรูปภาพเดียว ตัวตรวจจับวัตถุจะแสดงผลลัพธ์หลังจากกำหนดกรอบล้อมรอบของวัตถุแล้ว หากคุณเปิดใช้การจัดประเภทด้วย ระบบจะแสดงผลลัพธ์หลังจากทั้งกรอบล้อมรอบและป้ายกำกับหมวดหมู่พร้อมใช้งาน ด้วยเหตุนี้ เวลาในการตอบสนองของการตรวจจับจึงอาจสูงขึ้น นอกจากนี้ ในโหมดภาพเดียว จะไม่มีการกำหนดรหัสติดตาม ใช้โหมดนี้หากเวลาในการตอบสนองไม่สำคัญและคุณไม่ต้องการจัดการกับผลลัพธ์เพียงบางส่วน
ตรวจหาและติดตามออบเจ็กต์หลายรายการ false
(ค่าเริ่มต้น) |true
ไม่ว่าจะตรวจหาและติดตามออบเจ็กต์สูงสุด 5 รายการ หรือเฉพาะออบเจ็กต์ที่โดดเด่นที่สุด (ค่าเริ่มต้น)
จำแนกประเภทวัตถุ false
(ค่าเริ่มต้น) |true
จัดประเภทออบเจ็กต์ที่ตรวจพบเป็นหมวดหมู่คร่าวๆ หรือไม่ เมื่อเปิดใช้ เครื่องมือตรวจจับวัตถุจะจัดประเภทวัตถุเป็นหมวดหมู่ต่อไปนี้ สินค้าแฟชั่น อาหาร ของใช้ในบ้าน สถานที่ และพืช
API การตรวจจับและการติดตามวัตถุได้รับการเพิ่มประสิทธิภาพเพื่อการใช้งานหลักๆ 2 กรณีดังนี้
- การตรวจจับแบบเรียลไทม์และการติดตามวัตถุที่โดดเด่นที่สุดในช่องมองภาพของกล้อง
- การตรวจจับวัตถุหลายรายการในภาพนิ่ง
วิธีกำหนดค่า API สำหรับกรณีการใช้งานเหล่านี้
Swift
// Live detection and tracking let options = ObjectDetectorOptions() options.shouldEnableClassification = true // Multiple object detection in static images let options = ObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true
Objective-C
// Live detection and tracking MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init]; options.shouldEnableClassification = YES; // Multiple object detection in static images MLKObjectDetectorOptions *options = [[MLKOptions alloc] init]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES;
- รับอินสแตนซ์ของ
ObjectDetector
:
Swift
let objectDetector = ObjectDetector.objectDetector() // Or, to change the default settings: let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector]; // Or, to change the default settings: MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
2. เตรียมรูปภาพอินพุต
หากต้องการตรวจหาและติดตามวัตถุ ให้ทำตามขั้นตอนต่อไปนี้กับรูปภาพหรือเฟรมวิดีโอแต่ละเฟรม
หากเปิดใช้โหมดสตรีม คุณต้องสร้างออบเจ็กต์ VisionImage
รายการจาก CMSampleBuffer
สร้างออบเจ็กต์ 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. ประมวลผลภาพ
ส่งผ่านVisionImage
ไปยังวิธีการประมวลผลรูปภาพของตัวตรวจจับวัตถุวิธีหนึ่ง คุณจะใช้เมธอด process(image:)
แบบไม่พร้อมกันหรือเมธอด results()
แบบซิงโครนัสก็ได้
วิธีตรวจหาออบเจ็กต์แบบไม่พร้อมกัน
Swift
objectDetector.process(image) { objects, error in guard error == nil else { // Error. return } guard !objects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
Objective-C
[objectDetector processImage:image completion:^(NSArray* _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here. }];
วิธีตรวจหาวัตถุแบบพร้อมกัน
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard !objects.isEmpty else { print("Object detector returned no results.") return } // Success. Get object info here.
Objective-C
NSError *error; NSArray*objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here.
4. รับข้อมูลเกี่ยวกับออบเจ็กต์ที่ตรวจพบ
หากเรียกตัวประมวลผลภาพสำเร็จ ระบบจะส่งรายการObject
ไปยังตัวแฮนเดิลการเสร็จสมบูรณ์หรือส่งรายการกลับมา โดยขึ้นอยู่กับว่าคุณเรียกเมธอดแบบไม่พร้อมกันหรือซิงโครนัส
Object
แต่ละรายการจะมีพร็อพเพอร์ตี้ต่อไปนี้
frame |
CGRect ระบุตำแหน่งของวัตถุในรูปภาพ |
trackingID |
จำนวนเต็มที่ระบุวัตถุในรูปภาพ หรือ "nil" ในโหมดรูปภาพเดียว |
labels |
อาร์เรย์ของป้ายกำกับที่อธิบายออบเจ็กต์ที่เครื่องมือตรวจจับแสดงผล
พร็อพเพอร์ตี้นี้จะว่างเปล่าหากตั้งค่าตัวเลือกตัวตรวจจับ shouldEnableClassification เป็น false
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID // If classification was enabled: let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence)" }.joined(separator:"\n") }
Objective-C
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (MLKObject *object in objects) { CGRect frame = object.frame; NSNumber *trackingID = object.trackingID; for (MLKObjectLabel *label in object.labels) { NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu", label.text, label.confidence, (unsigned long)label.index]; ... } }
การปรับปรุงการใช้งานและประสิทธิภาพ
เพื่อให้ผู้ใช้ได้รับประสบการณ์ที่ดีที่สุด โปรดปฏิบัติตามหลักเกณฑ์ต่อไปนี้ในแอป
- การตรวจจับวัตถุที่จะประสบความสำเร็จขึ้นอยู่กับความซับซ้อนของภาพของวัตถุ หากต้องการให้ตรวจพบ วัตถุที่มีฟีเจอร์แบบภาพจำนวนเล็กน้อยอาจต้องใช้พื้นที่เก็บรูปภาพส่วนใหญ่ คุณควรให้คำแนะนำแก่ผู้ใช้เกี่ยวกับการบันทึกข้อมูลที่ทำงานได้ดีที่สุดกับประเภทวัตถุที่คุณต้องการตรวจจับ
- เมื่อคุณใช้การแยกประเภท หากต้องการตรวจหาออบเจ็กต์ที่ไม่ตรงกับหมวดหมู่ที่รองรับ ให้ใช้การจัดการพิเศษสำหรับออบเจ็กต์ที่ไม่รู้จัก
นอกจากนี้ ให้ดูคอลเล็กชันรูปแบบสำหรับฟีเจอร์ที่ขับเคลื่อนโดยแมชชีนเลิร์นนิงของดีไซน์ Material
เมื่อคุณใช้โหมดสตรีมมิงในแอปพลิเคชันแบบเรียลไทม์ ให้ทำตามหลักเกณฑ์ต่อไปนี้เพื่อให้ได้อัตราเฟรมที่ดีที่สุด
- อย่าใช้การตรวจจับวัตถุหลายรายการในโหมดสตรีมมิง เนื่องจากอุปกรณ์ส่วนใหญ่จะไม่สามารถสร้างอัตราเฟรมที่เพียงพอได้
- ปิดใช้การแยกประเภทหากไม่ต้องการ
- สำหรับการประมวลผลเฟรมวิดีโอ ให้ใช้ API แบบซิงโครนัส
results(in:)
ของตัวตรวจจับ เรียกใช้เมธอดนี้จากฟังก์ชันcaptureOutput(_, didOutput:from:)
ของAVCaptureVideoDataOutputSampleBufferDelegate
เพื่อรับผลการค้นหาจากเฟรมวิดีโอที่ระบุแบบพร้อมกัน คงalwaysDiscardsLateVideoFrames
ของAVCaptureVideoDataOutput
เป็นtrue
เพื่อควบคุมการโทรไปยังตัวตรวจจับ หากเฟรมวิดีโอใหม่พร้อมใช้งานขณะที่ตัวตรวจจับทำงานอยู่ เฟรมจะหายไป - หากคุณใช้เอาต์พุตจากตัวตรวจจับเพื่อวางซ้อนกราฟิกบนรูปภาพอินพุต ให้รับผลลัพธ์จาก ML Kit ก่อน จากนั้นจึงแสดงผลรูปภาพและการวางซ้อนในขั้นตอนเดียว การทำเช่นนี้จะทำให้คุณแสดงผลบนพื้นผิวแสดงผลเพียงครั้งเดียวต่อเฟรมอินพุตที่ประมวลผลแต่ละเฟรม ดู updatePreviewOverlayViewWithLastFrame ในตัวอย่างการเริ่มใช้งานอย่างรวดเร็วของ ML Kit