Anda dapat menggunakan ML Kit untuk mengenali entity dalam gambar dan memberi label pada entity tersebut. API ini mendukung berbagai model klasifikasi gambar kustom. Lihat Model kustom dengan ML Kit untuk mengetahui 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 menempatkannya di dalam folder aset aplikasi, atau Anda dapat mendownloadnya secara dinamis dari Cloud Storage. Tabel berikut membandingkan kedua opsi tersebut.
| Model yang Dipaketkan | Model yang Dihosting |
|---|---|
| Model merupakan bagian dari APK aplikasi, yang meningkatkan ukurannya. | Model bukan bagian dari APK Anda. Model dihosting dengan mengupload ke Cloud Storage. Sebaiknya gunakan Cloud Storage untuk 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 untuk 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 dipaketkan dan aplikasi quickstart automl untuk mengetahui contoh penggunaan model yang dihosting.
Sebelum memulai
Sertakan library ML Kit di Podfile Anda:
pod 'GoogleMLKit/ImageLabelingCustom', '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 Anda ingin mendownload model menggunakan Cloud Storage untuk Firebase, pastikan Anda menambahkan Firebase ke project iOS, jika belum melakukannya. Langkah ini tidak diperlukan jika Anda memaketkan model.
1. Muat model
Mengonfigurasi sumber model lokal
Untuk memaketkan model dengan aplikasi Anda:
Salin file model (biasanya diakhiri dengan
.tfliteatau.lite) ke project Xcode, dan berhati-hatilah saat memilihCopy bundle resourcesketika melakukannya. File model akan disertakan dalam app bundle dan tersedia untuk ML Kit.Buat objek
LocalModel, yang 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 untuk Firebase guna menghosting model. Untuk mengetahui detail penerapan, lihat panduan migrasi Firebase ML ke Cloud Storage.
Mengonfigurasi pemberi label gambar
Setelah mengonfigurasi sumber model, buat objek ImageLabeler dari salah satunya.
Tersedia opsi-opsi berikut:
| Opsi | |
|---|---|
confidenceThreshold
|
Skor keyakinan minimum label yang terdeteksi. Jika tidak ditetapkan, nilai minimum pengklasifikasi yang ditentukan oleh metadata model akan digunakan. Jika model tidak berisi metadata atau metadata tidak menentukan nilai minimum pengklasifikasi, nilai minimum default 0,0 akan digunakan. |
maxResultCount
|
Jumlah maksimum label yang akan ditampilkan. Jika tidak ditetapkan, nilai default 10 akan digunakan. |
Jika hanya memiliki model yang dipaketkan secara lokal, cukup buat pemberi label dari objek 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];
Jika Anda memiliki model yang dihosting dari jarak jauh, Anda harus memeriksa apakah model tersebut sudah didownload sebelum menjalankannya.
Meskipun hanya perlu memastikan hal ini sebelum menjalankan pemberi label, jika Anda memiliki model yang dihosting dari jarak jauh dan model yang dipaketkan secara lokal, mungkin pemeriksaan ini perlu dilakukan saat membuat instance ImageLabeler: buat pemberi label dari model jarak jauh jika model tersebut telah didownload, dan dari model lokal jika belum didownload.
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];
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.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. 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];
3. Jalankan pemberi label gambar
Untuk memberi label pada objek dalam gambar, teruskan objek image ke metode process() ImageLabeler.
Secara asinkron:
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. }];
Secara sinkron:
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. Mendapatkan informasi tentang entity berlabel
Jika operasi pelabelan gambar berhasil, array akan ditampilkanImageLabel. Setiap ImageLabel mewakili sesuatu yang berlabel dalam gambar. Anda dapat memperoleh deskripsi teks setiap label (jika tersedia dalam metadata file model LiteRT), skor keyakinan, dan indeks. Contoh:
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; }
Tips untuk meningkatkan performa real-time
Jika Anda ingin memberikan label pada gambar dalam aplikasi real-time, ikuti panduan ini untuk mencapai frekuensi gambar terbaik:
- Untuk memproses frame video, gunakan API sinkron
results(in:)detektor. Panggil metode ini dari fungsiAVCaptureVideoDataOutputSampleBufferDelegate'scaptureOutput(_, didOutput:from:)untuk mendapatkan hasil secara sinkron dari frame video yang diberikan. 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.