Saat Anda meneruskan gambar ke ML Kit, API akan mendeteksi hingga lima objek dalam gambar 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 untuk 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 Anda dapat mendownloadnya secara dinamis dari Firebase. Tabel berikut membandingkan dua opsi tersebut.
Model Paket | Model yang Dihosting |
---|---|
Model merupakan bagian dari file .ipa aplikasi Anda, yang
akan memperbesar ukurannya. |
Model bukan bagian dari file .ipa aplikasi Anda. Dihosting dengan mengupload ke Firebase Machine Learning. |
Model akan langsung tersedia, bahkan saat perangkat Android sedang offline | Model didownload sesuai permintaan |
Tidak memerlukan project Firebase | Memerlukan project Firebase |
Anda harus memublikasikan ulang aplikasi untuk memperbarui model | Update model dapat dikirim tanpa memublikasikan ulang aplikasi |
Tidak ada pengujian A/B bawaan | Pengujian A/B yang mudah dengan Firebase Remote Config |
Cobalah
- Lihat aplikasi panduan memulai visi untuk contoh penggunaan model yang dipaketkan dan aplikasi panduan memulai AutoML untuk mengetahui contoh penggunaan model yang dihosting.
- Lihat aplikasi katalog Desain Material untuk implementasi API ini secara menyeluruh.
Sebelum memulai
Sertakan library ML Kit di Podfile Anda:
Untuk memaketkan model dengan aplikasi Anda:
pod 'GoogleMLKit/ObjectDetectionCustom', '3.2.0'
Untuk mendownload model dari Firebase secara dinamis, tambahkan dependensi
LinkFirebase
:pod 'GoogleMLKit/ObjectDetectionCustom', '3.2.0' pod 'GoogleMLKit/LinkFirebase', '3.2.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, 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:
Salin file model (biasanya diakhiri dengan
.tflite
atau.lite
) ke project Xcode dan berhati-hatilah saat memilihCopy bundle resources
ketika 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 Firebase
Untuk menggunakan model yang dihosting dari jarak jauh, buat objek CustomRemoteModel
, dengan menentukan nama yang diberikan kepada model saat dipublikasikan:
Swift
let firebaseModelSource = FirebaseModelSource( name: "your_remote_model") // The name you assigned in // the Firebase console. let remoteModel = CustomRemoteModel(remoteModelSource: firebaseModelSource)
Objective-C
MLKFirebaseModelSource *firebaseModelSource = [[MLKFirebaseModelSource alloc] initWithName:@"your_remote_model"]; // The name you assigned in // the Firebase console. MLKCustomRemoteModel *remoteModel = [[MLKCustomRemoteModel alloc] initWithRemoteModelSource:firebaseModelSource];
Kemudian, mulai tugas download model dengan menentukan kondisi yang Anda inginkan untuk mengizinkan download. Jika model tidak ada di perangkat, atau jika versi model yang lebih baru tersedia, tugas ini akan mendownload model dari Firebase secara asinkron:
Swift
let downloadConditions = ModelDownloadConditions( allowsCellularAccess: true, allowsBackgroundDownloading: true ) let downloadProgress = ModelManager.modelManager().download( remoteModel, conditions: downloadConditions )
Objective-C
MLKModelDownloadConditions *downloadConditions = [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES allowsBackgroundDownloading:YES]; NSProgress *downloadProgress = [[MLKModelManager modelManager] downloadModel:remoteModel conditions:downloadConditions];
Banyak aplikasi memulai tugas download dalam kode inisialisasinya, tetapi Anda dapat melakukannya kapan saja sebelum menggunakan model.
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 5 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 perlu menetapkannya ke |
Nilai minimum keyakinan klasifikasi |
Skor keyakinan minimum label yang terdeteksi. Jika tidak disetel, nilai minimum pengklasifikasi apa pun yang ditentukan oleh metadata model akan digunakan. Jika model tidak berisi metadata apa pun atau metadata tidak menentukan batas pengklasifikasi, nilai minimum default 0,0 akan digunakan. |
Label maksimum per objek |
Jumlah maksimum label per objek yang akan ditampilkan oleh detektor. Jika tidak disetel, nilai default 10 akan digunakan. |
Jika 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. Anda dapat memeriksa status tugas download model menggunakan metode isModelDownloaded(remoteModel:)
pengelola model.
Meskipun Anda hanya perlu mengonfirmasi hal ini sebelum menjalankan detektor objek, jika Anda memiliki model yang dihosting dari jarak jauh dan model yang dipaketkan secara lokal, mungkin ada baiknya untuk melakukan pemeriksaan ini saat membuat instance ObjectDetector
: membuat detektor dari model jarak jauh jika model tersebut telah didownload, dan dari model lokal jika belum didownload.
Swift
var options: CustomObjectDetectorOptions! if (ModelManager.modelManager().isModelDownloaded(remoteModel)) { options = CustomObjectDetectorOptions(remoteModel: remoteModel) } else { 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; if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) { options = [[MLKCustomObjectDetectorOptions alloc] initWithRemoteModel:remoteModel]; } else { options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; } options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3;
Jika Anda hanya memiliki model yang dihosting dari jarak jauh, Anda harus menonaktifkan fungsionalitas terkait model, misalnya membuat sebagian UI berwarna abu-abu atau menyembunyikannya, hingga Anda mengonfirmasi model tersebut telah didownload.
Anda dapat memperoleh status download model dengan menambahkan observer ke
Pusat Notifikasi default. Pastikan untuk menggunakan referensi lemah ke self
di blok observer, karena proses download memerlukan waktu beberapa saat, dan objek asalnya dapat dibebaskan pada saat download selesai. Contoh:
Swift
NotificationCenter.default.addObserver( forName: .mlkitModelDownloadDidSucceed, object: nil, queue: nil ) { [weak self] notification in guard let strongSelf = self, let userInfo = notification.userInfo, let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel, model.name == "your_remote_model" else { return } // The model was downloaded and is available on the device } NotificationCenter.default.addObserver( forName: .mlkitModelDownloadDidFail, object: nil, queue: nil ) { [weak self] notification in guard let strongSelf = self, let userInfo = notification.userInfo, let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel else { return } let error = userInfo[ModelDownloadUserInfoKey.error.rawValue] // ... }
Objective-C
__weak typeof(self) weakSelf = self; [NSNotificationCenter.defaultCenter addObserverForName:MLKModelDownloadDidSucceedNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel]; if ([model.name isEqualToString:@"your_remote_model"]) { // The model was downloaded and is available on the device } }]; [NSNotificationCenter.defaultCenter addObserverForName:MLKModelDownloadDidFailNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError]; }];
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.
- Mendeteksi 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. Persiapkan gambar input
Buat objek VisionImage
menggunakan UIImage
atau CMSampleBuffer
.
Jika Anda menggunakan UIImage
, ikuti langkah-langkah berikut:
- Buat objek
VisionImage
denganUIImage
. Pastikan untuk menentukan.orientation
yang 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
VisionImage
menggunakan objek dan orientasiCMSampleBuffer
: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 detektor:
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 terbaik
Untuk pengalaman pengguna terbaik, ikuti panduan berikut di aplikasi Anda:
- Keberhasilan deteksi objek bergantung pada kompleksitas visual objek. Agar dapat dideteksi, objek dengan sedikit fitur visual mungkin perlu menempati bagian yang lebih besar pada gambar. Anda sebaiknya memberikan panduan kepada pengguna tentang menangkap input yang berfungsi baik dengan jenis objek yang ingin Anda deteksi.
- Saat Anda 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 contoh Desain Material ML Kit][showcase-link]{: .external} 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 kecepatan frame terbaik:Saat Anda menggunakan mode streaming dalam aplikasi real-time, jangan gunakan deteksi beberapa objek, karena sebagian besar perangkat tidak akan dapat menghasilkan frekuensi gambar yang memadai.
- Untuk memproses frame video, gunakan API sinkron
results(in:)
dari detektor. Panggil metode ini dari fungsicaptureOutput(_, didOutput:from:)
AVCaptureVideoDataOutputSampleBufferDelegate
untuk mendapatkan hasil secara sinkron dari frame video yang diberikan. SimpanalwaysDiscardsLateVideoFrames
AVCaptureVideoDataOutput
sebagaitrue
untuk 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 dalam contoh panduan memulai ML Kit untuk mengetahui contohnya.