Saat Anda meneruskan gambar ke ML Kit, ML Kit akan mendeteksi hingga lima objek dalam gambar tersebut beserta posisi setiap objek dalam gambar. Saat mendeteksi objek dalam streaming video, setiap objek memiliki ID unik yang dapat Anda gunakan untuk melacak objek dari frame ke frame.
Anda dapat menggunakan model klasifikasi gambar kustom untuk mengklasifikasikan objek yang terdeteksi. Lihat Model kustom dengan ML Kit untuk mendapatkan panduan tentang persyaratan kompatibilitas model, tempat menemukan model terlatih, dan cara melatih model Anda sendiri.
Ada dua cara untuk mengintegrasikan model kustom. Anda dapat memaketkan model dengan memasukkannya ke dalam folder aset aplikasi, atau mendownloadnya secara dinamis dari Cloud Storage. Tabel berikut membandingkan kedua opsi tersebut.
| Model Gabungan | Model yang Dihosting |
|---|---|
Model adalah bagian dari file .ipa aplikasi Anda, yang
meningkatkan ukurannya. |
Model tidak termasuk dalam file .ipa aplikasi Anda. Model dihosting dengan mengupload ke Cloud Storage. Sebaiknya gunakan Cloud Storage for Firebase. |
| Model akan langsung tersedia, bahkan saat perangkat Android sedang offline | Aplikasi Anda harus menyertakan kode untuk mendownload model sesuai permintaan |
| Tidak memerlukan project Firebase | Memerlukan project Firebase (jika menggunakan Cloud Storage for Firebase). |
| Anda harus memublikasikan ulang aplikasi untuk mengupdate model | Update model dapat dikirim tanpa memublikasikan ulang aplikasi |
| Tidak ada pengujian A/B bawaan | Pengujian A/B dengan Firebase Remote Config |
Cobalah
- Lihat aplikasi quickstart vision untuk mengetahui contoh penggunaan model yang dibundel dan aplikasi quickstart automl untuk mengetahui contoh penggunaan model yang dihosting.
- Lihat aplikasi showcase Desain Material untuk mengetahui penerapan API ini secara menyeluruh.
Sebelum memulai
Sertakan library ML Kit di Podfile Anda:
pod 'GoogleMLKit/ObjectDetectionCustom', '8.0.0'Setelah Anda menginstal atau mengupdate Pod project, buka project Xcode menggunakan
.xcworkspace-nya. ML Kit didukung di Xcode versi 13.2.1 atau yang lebih tinggi.Jika ingin mendownload model menggunakan Cloud Storage for Firebase, pastikan Anda menambahkan Firebase ke project iOS, jika belum melakukannya. Langkah ini tidak diperlukan jika Anda memaketkan model.
1. Memuat model
Mengonfigurasi sumber model lokal
Untuk memaketkan model dengan aplikasi Anda:
Salin file model (biasanya diakhiri dengan
.tfliteatau.lite) ke project Xcode, pastikan untuk memilihCopy bundle resourcessaat melakukannya. File model akan disertakan dalam app bundle dan tersedia untuk ML Kit.Buat objek
LocalModel, dengan menentukan jalur ke file model:Swift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
Mengonfigurasi sumber model yang dihosting dari jarak jauh
Untuk menggunakan model yang dihosting dari jarak jauh, Anda harus mendownload file model ke penyimpanan lokal perangkat menggunakan logika aplikasi Anda sendiri, lalu memuatnya sebagai model lokal. Sebaiknya gunakan Cloud Storage for Firebase untuk menghosting model. Untuk mengetahui detail penerapan, lihat panduan migrasi Firebase ML ke Cloud Storage.
2. Mengonfigurasi detektor objek
Setelah mengonfigurasi sumber model, konfigurasikan detektor objek untuk kasus penggunaan Anda dengan objek CustomObjectDetectorOptions. Anda dapat mengubah setelan berikut:
| Setelan Detektor Objek | |
|---|---|
| Mode deteksi |
STREAM_MODE (default) | SINGLE_IMAGE_MODE
Pada Pada |
| Mendeteksi dan melacak beberapa objek |
false (default) | true
Mendeteksi dan melacak hingga lima objek atau hanya objek yang paling tampil beda (default). |
| Mengklasifikasikan objek |
false (default) | true
Mengklasifikasikan objek yang terdeteksi menggunakan model pengklasifikasi kustom yang disediakan atau tidak. Untuk menggunakan model klasifikasi kustom, Anda harus menyetelnya ke |
| Nilai minimum keyakinan klasifikasi |
Skor keyakinan minimum untuk label yang terdeteksi. Jika tidak disetel, nilai batas klasifikasi yang ditentukan oleh metadata model akan digunakan. Jika model tidak berisi metadata atau metadata tidak menentukan nilai batas klasifikasi, nilai batas default 0,0 akan digunakan. |
| Jumlah maksimum label per objek |
Jumlah maksimum label per objek yang akan ditampilkan oleh detektor. Jika tidak disetel, nilai default 10 akan digunakan. |
Jika Anda hanya memiliki model yang dipaketkan secara lokal, cukup buat detektor objek dari objek LocalModel:
Swift
let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3
Objective-C
MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3;
Jika Anda memiliki model yang dihosting dari jarak jauh, Anda harus memeriksa apakah model tersebut sudah didownload sebelum menjalankannya.
Meskipun Anda hanya perlu mengonfirmasi ini sebelum menjalankan detektor objek, jika Anda memiliki model yang dihosting dari jarak jauh dan model yang di-bundle secara lokal, sebaiknya lakukan pemeriksaan ini saat membuat instance ObjectDetector: buat detektor dari model jarak jauh jika telah didownload, dan dari model lokal jika belum.
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 = CustomObjectDetectorOptions(localModel: model) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3 let objectDetector = ObjectDetector.objectDetector(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]; } MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:model]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3; MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
Jika Anda hanya memiliki model yang dihosting dari jarak jauh, Anda harus menonaktifkan fungsi yang terkait dengan model—misalnya, menyamarkan atau menyembunyikan sebagian UI—sampai Anda mengonfirmasi bahwa model telah didownload.
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.initializeDetector(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 detector self.initializeDetector(with: modelURL) } } } func initializeDetector(with modelURL: URL) { let localModel = LocalModel(path: modelURL.path) let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true self.objectDetector = ObjectDetector.objectDetector(options: options) // Enable ML features in UI 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 initializeDetectorWithURL: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 detector [self initializeDetectorWithURL:URL]; } }]; } - (void)initializeDetectorWithURL:(NSURL *)modelURL { MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:modelURL.path]; MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; self.objectDetector = [MLKObjectDetector objectDetectorWithOptions:options]; // Enable ML features in UI [self enableMLFeatures]; }
API deteksi dan pelacakan objek dioptimalkan untuk dua kasus penggunaan inti berikut ini:
- Deteksi langsung dan pelacakan objek paling tampil beda di jendela bidik kamera.
- Deteksi beberapa objek dari gambar statis.
Untuk mengonfigurasi API bagi kasus penggunaan ini:
Swift
// Live detection and tracking let options = CustomObjectDetectorOptions(localModel: localModel) options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3 // Multiple object detection in static images let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3
Objective-C
// Live detection and tracking MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3; // Multiple object detection in static images MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3;
3. Siapkan gambar input
Buat objek VisionImage menggunakan UIImage atau
CMSampleBuffer.
Jika Anda menggunakan UIImage, ikuti langkah-langkah berikut:
- Buat objek
VisionImagedenganUIImage. Pastikan untuk menentukan.orientationyang benar.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Jika Anda menggunakan CMSampleBuffer, ikuti langkah-langkah berikut:
-
Tentukan orientasi data gambar yang terdapat dalam
CMSampleBuffer.Untuk mendapatkan orientasi gambar:
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; } }
- Buat objek
VisionImagemenggunakan objekCMSampleBufferdan orientasi: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];
4. Membuat dan menjalankan detektor objek
Buat detektor objek baru:
Swift
let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
Kemudian, gunakan pendeteksi:
Secara asinkron:
Swift
objectDetector.process(image) { objects, error in guard error == nil, let objects = objects, !objects.isEmpty else { // Handle the error. return } // Show results. }
Objective-C
[objectDetector processImage:image completion:^(NSArray
*_Nullable objects, NSError *_Nullable error) { if (objects.count == 0) { // Handle the error. return; } // Show results. }]; Secara sinkron:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { // Handle the error. return } // Show results.
Objective-C
NSError *error; NSArray
*objects = [objectDetector resultsInImage:image error:&error]; // Show results or handle the error.
5. Mendapatkan informasi tentang objek berlabel
Jika panggilan ke prosesor gambar berhasil, panggilan tersebut akan meneruskan daftar Object ke pengendali penyelesaian atau menampilkan daftar, bergantung pada metode yang digunakan, yaitu asinkron atau sinkron.
Setiap Object berisi properti berikut:
frame |
CGRect yang menunjukkan posisi objek dalam gambar. |
||||||
trackingID |
Bilangan bulat yang mengidentifikasi objek lintas gambar, atau `nil` dalam SINGLE_IMAGE_MODE. | ||||||
labels |
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence), \(label.index)" }.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]; } }
Memastikan pengalaman pengguna yang luar biasa
Untuk mendapatkan pengalaman pengguna terbaik, ikuti pedoman ini dalam aplikasi Anda:
- Keberhasilan deteksi objek bergantung pada kompleksitas visual objek. Agar terdeteksi, objek yang memiliki sedikit fitur visual mungkin perlu menempati bagian yang lebih besar pada gambar. Anda sebaiknya memberikan panduan kepada pengguna tentang pengambilan input yang tepat bagi jenis objek yang ingin Anda deteksi.
- Saat menggunakan klasifikasi, jika ingin mendeteksi objek yang tidak secara jelas termasuk dalam kategori yang didukung, terapkan penanganan khusus untuk objek yang tidak diketahui.
Selain itu, lihat aplikasi showcase Desain Material ML Kit dan koleksi Pola Desain Material untuk fitur yang didukung machine learning.
Meningkatkan performa
Jika ingin menggunakan deteksi objek dalam aplikasi real-time, ikuti pedoman ini untuk mencapai frekuensi frame terbaik:Saat menggunakan mode streaming dalam aplikasi real-time, jangan gunakan deteksi banyak objek, karena sebagian besar perangkat tidak akan dapat menghasilkan frekuensi frame yang memadai.
- Untuk memproses frame video, gunakan
results(in:)API sinkron detektor. Panggil metode ini dari fungsiAVCaptureVideoDataOutputSampleBufferDelegate'scaptureOutput(_, didOutput:from:)untuk mendapatkan hasil secara sinkron dari frame video tertentu. PertahankanAVCaptureVideoDataOutput'salwaysDiscardsLateVideoFramessebagaitrueuntuk membatasi panggilan ke detektor. Jika frame video baru tersedia saat detektor sedang berjalan, frame tersebut akan dihapus. - Jika Anda menggunakan output detektor untuk menempatkan grafis pada gambar input, pertama-tama dapatkan hasilnya dari ML Kit, lalu render gambar dan tempatkan grafis dalam satu langkah. Dengan demikian, Anda hanya merender ke permukaan tampilan sekali untuk setiap frame input yang diproses. Lihat updatePreviewOverlayViewWithLastFrame di contoh quickstart ML Kit untuk mengetahui contohnya.