คุณใช้ ML Kit เพื่อจดจำเอนทิตีในรูปภาพและติดป้ายกำกับได้ API นี้รองรับโมเดลการแยกประเภทรูปภาพที่กำหนดเองหลากหลายประเภท ดูคำแนะนำเกี่ยวกับ ข้อกำหนดด้านความเข้ากันได้ของโมเดล ตำแหน่งที่จะค้นหาโมเดลที่ฝึกไว้ล่วงหน้า และวิธีฝึกโมเดลของคุณเองได้ที่โมเดลที่กำหนดเองด้วย ML Kit
การผสานรวมโมเดลที่กำหนดเองทำได้ 2 วิธี คุณสามารถรวมโมเดลได้โดย วางไว้ในโฟลเดอร์ชิ้นงานของแอป หรือจะดาวน์โหลดแบบไดนามิก จาก Cloud Storage ก็ได้ ตารางต่อไปนี้เปรียบเทียบตัวเลือกทั้ง 2 รายการ
| โมเดลแบบแพ็กเกจ | โมเดลที่โฮสต์ |
|---|---|
| โมเดลเป็นส่วนหนึ่งของ APK ของแอป ซึ่งจะเพิ่มขนาดของ APK | โมเดลไม่ได้เป็นส่วนหนึ่งของ APK โดยการอัปโหลดไปยัง Cloud Storage เราขอแนะนำให้ใช้ Cloud Storage สำหรับ Firebase |
| โมเดลพร้อมใช้งานทันทีแม้ว่าอุปกรณ์ Android จะออฟไลน์อยู่ก็ตาม | แอปของคุณต้องมีโค้ดเพื่อดาวน์โหลดโมเดลตามต้องการ |
| ไม่จำเป็นต้องมีโปรเจ็กต์ Firebase | ต้องมีโปรเจ็กต์ Firebase (หากใช้ Cloud Storage for Firebase) |
| คุณต้องเผยแพร่แอปอีกครั้งเพื่ออัปเดตโมเดล | อัปเดตโมเดลแบบพุชโดยไม่ต้องเผยแพร่แอปอีกครั้ง |
| ไม่มีการทดสอบ A/B ในตัว | การทดสอบ A/B ด้วยการกำหนดค่าระยะไกลของ Firebase |
ลองเลย
- ดูตัวอย่างการใช้งานโมเดลที่รวมไว้ในแอปเริ่มต้นใช้งาน Vision และดูตัวอย่างการใช้งานโมเดลที่โฮสต์ไว้ในแอปเริ่มต้นใช้งาน AutoML
ก่อนเริ่มต้น
ใส่ไลบรารี ML Kit ใน Podfile ดังนี้
pod 'GoogleMLKit/ImageLabelingCustom', '8.0.0'หลังจากติดตั้งหรืออัปเดต Pod ของโปรเจ็กต์แล้ว ให้เปิดโปรเจ็กต์ Xcode โดยใช้
.xcworkspaceML Kit รองรับ Xcode เวอร์ชัน 13.2.1 ขึ้นไปหากต้องการดาวน์โหลดโมเดลโดยใช้ Cloud Storage สำหรับ Firebase โปรดตรวจสอบว่าคุณได้เพิ่ม Firebase ลงในโปรเจ็กต์ iOS แล้ว หากยังไม่ได้ดำเนินการ การดำเนินการนี้ไม่จำเป็นเมื่อคุณรวมโมเดล
1. โหลดโมเดล
กำหนดค่าแหล่งที่มาของโมเดลในเครื่อง
วิธีรวมโมเดลกับแอป
คัดลอกไฟล์โมเดล (โดยปกติจะลงท้ายด้วย
.tfliteหรือ.lite) ไปยังโปรเจ็กต์ Xcode โดยอย่าลืมเลือกCopy bundle resourcesเมื่อดำเนินการ ไฟล์โมเดลจะรวมอยู่ใน App Bundle และพร้อมใช้งานกับ ML Kitสร้างออบเจ็กต์
LocalModelโดยระบุเส้นทางไปยังไฟล์โมเดลSwift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
กำหนดค่าแหล่งที่มาของโมเดลที่โฮสต์จากระยะไกล
หากต้องการใช้โมเดลที่โฮสต์จากระยะไกล คุณต้องดาวน์โหลดไฟล์โมเดลไปยังพื้นที่เก็บข้อมูลภายในเครื่องของอุปกรณ์โดยใช้ตรรกะของแอปของคุณเอง แล้วโหลดเป็นโมเดลในเครื่อง เราขอแนะนำให้ใช้ Cloud Storage for Firebase เพื่อโฮสต์โมเดล ดูรายละเอียดการติดตั้งใช้งานได้ที่คำแนะนำในการย้ายข้อมูลจาก Firebase ML ไปยัง Cloud Storage
กำหนดค่าเครื่องมือติดป้ายกำกับรูปภาพ
หลังจากกำหนดค่าแหล่งที่มาของโมเดลแล้ว ให้สร้างออบเจ็กต์ ImageLabeler จากแหล่งที่มาใดแหล่งที่มาหนึ่ง
โดยมีตัวเลือกดังต่อไปนี้
| ตัวเลือก | |
|---|---|
confidenceThreshold
|
คะแนนความเชื่อมั่นขั้นต่ำของป้ายกำกับที่ตรวจพบ หากไม่ได้ตั้งค่าไว้ ระบบจะใช้เกณฑ์ตัวแยกประเภทใดก็ตามที่ข้อมูลเมตาของโมเดลระบุ หากโมเดลไม่มีข้อมูลเมตาหรือข้อมูลเมตาไม่ได้ ระบุเกณฑ์ตัวแยกประเภท ระบบจะใช้เกณฑ์เริ่มต้นที่ 0.0 |
maxResultCount
|
จำนวนป้ายกำกับสูงสุดที่จะแสดง หากไม่ได้ตั้งค่า ระบบจะใช้ค่าเริ่มต้นเป็น 10 |
หากมีโมเดลที่รวมไว้ในเครื่องเท่านั้น ให้สร้างเครื่องมือติดป้ายกำกับจากออบเจ็กต์ LocalModel ดังนี้
Swift
let options = CustomImageLabelerOptions(localModel: localModel) options.confidenceThreshold = NSNumber(value: 0.0) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; options.confidenceThreshold = @(0.0); MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
หากมีโมเดลที่โฮสต์จากระยะไกล คุณจะต้องตรวจสอบว่าได้ดาวน์โหลดโมเดลแล้วก่อนที่จะดำเนินการ
แม้ว่าคุณจะต้องยืนยันเรื่องนี้ก่อนเรียกใช้โปรแกรมติดป้ายกำกับ แต่หากมีทั้งโมเดลที่โฮสต์จากระยะไกลและโมเดลที่รวมไว้ในเครื่อง คุณอาจต้องทำการตรวจสอบนี้เมื่อสร้างอินสแตนซ์ของ ImageLabeler: สร้างโปรแกรมติดป้ายกำกับจากโมเดลระยะไกลหากดาวน์โหลดแล้ว และจากโมเดลในเครื่องหากยังไม่ได้ดาวน์โหลด
Swift
// Path where your download logic saves the model let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let localModelURL = documentDirectory.appendingPathComponent("my_remote_model.tflite") let model: LocalModel if FileManager.default.fileExists(atPath: localModelURL.path) { // Use the downloaded model model = LocalModel(path: localModelURL.path) } else { // Fall back to bundled model guard let bundledModelPath = Bundle.main.path(forResource: "model", ofType: "tflite") else { return } model = LocalModel(path: bundledModelPath) } let options = CustomImageLabelerOptions(localModel: model) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *localModelPath = [documentsDirectory stringByAppendingPathComponent:@"my_remote_model.tflite"]; MLKLocalModel *model; if ([NSFileManager.defaultManager fileExistsAtPath:localModelPath]) { // Use the downloaded model model = [[MLKLocalModel alloc] initWithPath:localModelPath]; } else { // Fall back to bundled model NSString *bundledModelPath = [NSBundle.mainBundle pathForResource:@"model" ofType:@"tflite"]; model = [[MLKLocalModel alloc] initWithPath:bundledModelPath]; } MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:model]; MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
หากมีเฉพาะโมเดลที่โฮสต์จากระยะไกล คุณควรปิดใช้ฟังก์ชันการทำงานที่เกี่ยวข้องกับโมเดล เช่น ทำให้ส่วนหนึ่งของ UI เป็นสีเทาหรือซ่อนไว้ จนกว่าคุณจะยืนยันว่าดาวน์โหลดโมเดลแล้ว
Swift
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let localModelURL = documentDirectory.appendingPathComponent("my_remote_model.tflite") if FileManager.default.fileExists(atPath: localModelURL.path) { // Model is already cached, initialize immediately self.initializeLabeler(with: localModelURL) } else { // Model is not yet available, show loading UI and start download self.showLoadingUI() let storage = Storage.storage() let modelRef = storage.reference(forURL: "gs://YOUR_BUCKET/path/to/model.tflite") modelRef.write(toFile: localModelURL) { url, error in self.hideLoadingUI() if let error = error { // Handle download error self.showErrorUI() } else if let modelURL = url { // Download success, initialize labeler self.initializeLabeler(with: modelURL) } } } func initializeLabeler(with modelURL: URL) { let localModel = LocalModel(path: modelURL.path) let options = CustomImageLabelerOptions(localModel: localModel) self.imageLabeler = ImageLabeler.imageLabeler(options: options) // Enable ML-related UI features here self.enableMLFeatures() }
Objective-C
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *localModelPath = [documentsDirectory stringByAppendingPathComponent:@"my_remote_model.tflite"]; NSURL *localModelURL = [NSURL fileURLWithPath:localModelPath]; if ([NSFileManager.defaultManager fileExistsAtPath:localModelPath]) { // Model is already cached, initialize immediately [self initializeLabelerWithURL:localModelURL]; } else { // Model is not yet available, show loading UI and start download [self showLoadingUI]; FIRStorage *storage = [FIRStorage storage]; FIRStorageReference *modelRef = [storage referenceForURL:@"gs://YOUR_BUCKET/path/to/model.tflite"]; [modelRef writeToFile:localModelURL completion:^(NSURL * _Nullable URL, NSError * _Nullable error) { [self hideLoadingUI]; if (error != nil) { // Handle download error [self showErrorUI]; } else { // Download success, initialize labeler [self initializeLabelerWithURL:URL]; } }]; } - (void)initializeLabelerWithURL:(NSURL *)modelURL { MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:modelURL.path]; MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; self.imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options]; // Enable ML-related UI features here [self enableMLFeatures]; }
2. เตรียมรูปภาพอินพุต
สร้างออบเจ็กต์ 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. เรียกใช้เครื่องมือติดป้ายกำกับรูปภาพ
หากต้องการติดป้ายกำกับวัตถุในรูปภาพ ให้ส่งimageออบเจ็กต์ไปยังเมธอด ImageLabeler's
process()
แบบอะซิงโครนัส
Swift
imageLabeler.process(image) { labels, error in guard error == nil, let labels = labels, !labels.isEmpty else { // Handle the error. return } // Show results. }
Objective-C
[imageLabeler processImage:image completion:^(NSArray*_Nullable labels, NSError *_Nullable error) { if (label.count == 0) { // Handle the error. return; } // Show results. }];
แบบซิงโครนัส
Swift
var labels: [ImageLabel] do { labels = try imageLabeler.results(in: image) } catch let error { // Handle the error. return } // Show results.
Objective-C
NSError *error; NSArray*labels = [imageLabeler resultsInImage:image error:&error]; // Show results or handle the error.
4. ดูข้อมูลเกี่ยวกับเอนทิตีที่ติดป้ายกำกับ
หากการดำเนินการติดป้ายกำกับรูปภาพสำเร็จ ระบบจะแสดงผลอาร์เรย์ของImageLabel ImageLabel แต่ละรายการแสดงถึงสิ่งที่ได้รับการ
ติดป้ายกำกับในรูปภาพ คุณจะได้รับคำอธิบายข้อความของแต่ละป้ายกำกับ (หากมีใน
ข้อมูลเมตาของไฟล์โมเดล LiteRT) คะแนนความเชื่อมั่น และดัชนี เช่น
Swift
for label in labels { let labelText = label.text let confidence = label.confidence let index = label.index }
Objective-C
for (MLKImageLabel *label in labels) { NSString *labelText = label.text; float confidence = label.confidence; NSInteger index = label.index; }
เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์
หากต้องการติดป้ายกำกับรูปภาพในแอปพลิเคชันแบบเรียลไทม์ ให้ทำตามหลักเกณฑ์ต่อไปนี้เพื่อให้ได้อัตราเฟรมที่ดีที่สุด
- หากต้องการประมวลผลเฟรมวิดีโอ ให้ใช้
results(in:)API แบบซิงโครนัสของเครื่องตรวจจับ เรียกใช้ เมธอดนี้จากฟังก์ชันAVCaptureVideoDataOutputSampleBufferDelegatecaptureOutput(_, didOutput:from:)เพื่อรับผลลัพธ์จากเฟรมวิดีโอที่ระบุแบบพร้อมกัน เก็บAVCaptureVideoDataOutputของalwaysDiscardsLateVideoFramesเป็นtrueเพื่อควบคุมการโทรไปยังเครื่องตรวจจับ หากมีวิดีโอเฟรมใหม่ ขณะที่เครื่องตรวจจับทำงานอยู่ ระบบจะทิ้งเฟรมนั้น - หากใช้เอาต์พุตของเครื่องตรวจจับเพื่อซ้อนทับกราฟิกบน รูปภาพอินพุต ให้รับผลลัพธ์จาก ML Kit ก่อน จากนั้นจึงแสดงรูปภาพ และซ้อนทับในขั้นตอนเดียว การทำเช่นนี้จะทำให้คุณแสดงผลไปยังพื้นผิวการแสดงผล เพียงครั้งเดียวสำหรับแต่ละเฟรมอินพุตที่ประมวลผลแล้ว ดูตัวอย่างได้ที่ updatePreviewOverlayViewWithLastFrame ในตัวอย่างการเริ่มต้นอย่างรวดเร็วของ ML Kit