ML Kit'i kullanarak bir görüntüdeki varlıkları tanıyabilir ve etiketleyebilirsiniz. Bu API, çok çeşitli özel görüntü sınıflandırma modellerini destekler. Lütfen Makine Öğrenimi Kiti ile özel modeller başlıklı makaleyi inceleyin model uyumluluk gereksinimleri, önceden eğitilmiş modellerin ve kendi modellerinizi nasıl eğiteceğinizi öğreneceksiniz.
Görüntü etiketlemeyi özel modellerle entegre etmenin iki yolu vardır: gruplandırma veya ayrı bir ardışık düzen kullanarak Google Play Hizmetleri'nde kullanılabilir. Gruplandırılmamış ardışık düzeni seçerseniz uygulamanız daha küçüktür. Ayrıntılar için aşağıdaki tabloya bakın.
Gruplandırılanlar | Gruplandırılmamış | |
---|---|---|
Kitaplık adı | com.google.mlkit:image-labeling-custom | com.google.android.gms:play-services-mlkit-image-labeling-custom |
Uygulama | Ardışık düzen, derleme sırasında statik olarak uygulamanıza bağlıdır. | Ardışık düzen, Google Play Hizmetleri aracılığıyla dinamik olarak indirilir. |
Uygulama boyutu | Yaklaşık 3,8 MB boyut artışı. | Yaklaşık 200 KB boyut artışı. |
Başlatma süresi | Ardışık düzen hemen kullanılabilir. | İlk kullanımdan önce ardışık düzenin indirilmesini beklemeniz gerekebilir. |
API yaşam döngüsü aşaması | Genel Kullanım (GK) | Beta |
Özel bir modeli entegre etmenin iki yolu vardır: modeli şu ölçüte göre gruplandırma: öğe klasörünün içine yerleştirerek veya dinamik olarak indirerek Firebase'den geliyor. Aşağıdaki tabloda bu iki seçenek karşılaştırılmıştır.
Gruplandırılmış Model | Barındırılan Model |
---|---|
Model, uygulamanızın APK'sının bir parçasıdır ve bu modelin boyutunu artırır. | Model, APK'nızın parçası değil. Şu konuma yükleyerek barındırılır: Firebase Makine Öğrenimi. |
Model, Android cihaz çevrimdışı olsa bile hemen kullanılabilir | Model istek üzerine indirilir |
Firebase projesine gerek yoktur | Firebase projesi gerekir |
Modeli güncellemek için uygulamanızı yeniden yayınlamanız gerekiyor | Uygulamanızı yeniden yayınlamadan model güncellemelerini aktarma |
Yerleşik A/B testi yok | Firebase Remote Config ile kolay A/B testi |
Deneyin
- Vision hızlı başlangıç uygulamasını inceleyin. örneğinin ve automl hızlı başlangıç uygulaması örnek kullanımı.
Başlamadan önce
Proje düzeyindeki
build.gradle
dosyanıza Google'ın Maven deposu hembuildscript
hem deallprojects
bölüm.ML Kit Android kitaplıklarının bağımlılıklarını modülünüze uygulama düzeyinde gradle dosyasıdır. Bu dosya genellikle
app/build.gradle
boyutundadır. Aşağıdakilerden birini seçin: bağımlılıkları belirleyebilirsiniz:Ardışık düzeni uygulamanızla paketlemek için:
dependencies { // ... // Use this dependency to bundle the pipeline with your app implementation 'com.google.mlkit:image-labeling-custom:17.0.3' }
Google Play Hizmetleri'nde ardışık düzeni kullanmak için:
dependencies { // ... // Use this dependency to use the dynamically downloaded pipeline in Google Play Services implementation 'com.google.android.gms:play-services-mlkit-image-labeling-custom:16.0.0-beta5' }
Google Play Hizmetleri'nde ardışık düzeni kullanmayı seçerseniz ardışık düzeni cihaza indirdikten sonra, uygulamanızı Uygulamanızın Play Store'dan yüklendiğinden emin olun. Bunu yapmak için aşağıdakini ekleyin: beyanını uygulamanızın
AndroidManifest.xml
dosyasına ekleyin:<application ...> ... <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="custom_ica" /> <!-- To use multiple downloads: android:value="custom_ica,download2,download3" --> </application>
Ayrıca ardışık düzen kullanılabilirliğini açıkça kontrol edebilir ve Google Play Hizmetleri ModuleLoadClient API'si
Yükleme sırasında ardışık düzen indirmelerini etkinleştirmez veya açık indirme isteğinde bulunmazsanız Ardışık düzen, etiketleyiciyi ilk çalıştırdığınızda indirilir. Yaptığınız istekler hiçbir sonuç döndürmez.
Bir
linkFirebase
modeliniz:Firebase'den dinamik olarak bir model indirmek için
linkFirebase
bağımlılık:dependencies { // ... // Image labeling feature with model downloaded from Firebase implementation 'com.google.mlkit:image-labeling-custom:17.0.3' // Or use the dynamically downloaded pipeline in Google Play Services // implementation 'com.google.android.gms:play-services-mlkit-image-labeling-custom:16.0.0-beta5' implementation 'com.google.mlkit:linkfirebase:17.0.0' }
Bir model indirmek istiyorsanız şunu yaptığınızdan emin olun: Firebase'i Android projenize ekleyin, (onaylamadıysanız). Modeli paket haline getirirken bu işlem gerekli değildir.
1. Modeli yükleme
Yerel model kaynağını yapılandırma
Modeli uygulamanızla paket haline getirmek için:
Model dosyasını (genellikle
.tflite
veya.lite
ile biter) uygulamanızınassets/
klasör. (İlk olarak klasörüapp/
klasörünü sağ tıklayıp Yeni > Klasör > Öğeler Klasörü'nü tıklayın.)Ardından, uygulamanızın
build.gradle
dosyasına şunu ekleyin: Gradle, uygulamayı oluştururken model dosyasını sıkıştırmaz:android { // ... aaptOptions { noCompress "tflite" // or noCompress "lite" } }
Model dosyası uygulama paketine dahil edilir ve ML Kit tarafından kullanılabilir işlenmemiş bir öğe olarak görebiliriz.
Model dosyasının yolunu belirterek
LocalModel
nesnesi oluşturun:Kotlin
val localModel = LocalModel.Builder() .setAssetFilePath("model.tflite") // or .setAbsoluteFilePath(absolute file path to model file) // or .setUri(URI to model file) .build()
Java
LocalModel localModel = new LocalModel.Builder() .setAssetFilePath("model.tflite") // or .setAbsoluteFilePath(absolute file path to model file) // or .setUri(URI to model file) .build();
Firebase tarafından barındırılan bir model kaynağını yapılandırma
Uzaktan barındırılan modeli kullanmak için şu şekilde bir RemoteModel
nesnesi oluşturun:
FirebaseModelSource
, dosyayı açarken modeli atadığınızda
yayınladı:
Kotlin
// Specify the name you assigned in the Firebase console. val remoteModel = CustomRemoteModel .Builder(FirebaseModelSource.Builder("your_model_name").build()) .build()
Java
// Specify the name you assigned in the Firebase console. CustomRemoteModel remoteModel = new CustomRemoteModel .Builder(new FirebaseModelSource.Builder("your_model_name").build()) .build();
Ardından, model indirme görevini başlatmak için model indirme işleminde indirmeye izin vermek istiyorsunuz. Model cihazda yoksa veya sürümü kullanılabiliyorsa görev, yeni bir sürümün yüklü olduğu modeliniz:
Kotlin
val downloadConditions = DownloadConditions.Builder() .requireWifi() .build() RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener { // Success. }
Java
DownloadConditions downloadConditions = new DownloadConditions.Builder() .requireWifi() .build(); RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(@NonNull Task task) { // Success. } });
Birçok uygulama, indirme görevini başlatma kodunda başlatır, ancak bunu, modeli kullanmaya başlamadan önce istediğiniz zaman yapabilirsiniz.
Görüntü etiketleyiciyi yapılandırma
Model kaynaklarınızı yapılandırdıktan sonra şuradan bir ImageLabeler
nesnesi oluşturun:
bunlardan biri olabilir.
Aşağıdaki seçenekler kullanılabilir:
Seçenekler | |
---|---|
confidenceThreshold
|
Algılanan etiketlerin minimum güven puanı. Ayarlanmazsa modelin meta verileri tarafından belirtilen sınıflandırıcı eşiği kullanılır. Model herhangi bir meta veri içermiyorsa veya meta veriler bir sınıflandırıcı eşiği belirtirse 0, 0 varsayılan eşiği kullanılır. |
maxResultCount
|
Döndürülecek maksimum etiket sayısı. Politika ayarlanmazsa 10 kullanılır. |
Yalnızca yerel olarak paketlenmiş bir modeliniz varsa
LocalModel
nesne:
Kotlin
val customImageLabelerOptions = CustomImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0.5f) .setMaxResultCount(5) .build() val labeler = ImageLabeling.getClient(customImageLabelerOptions)
Java
CustomImageLabelerOptions customImageLabelerOptions = new CustomImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0.5f) .setMaxResultCount(5) .build(); ImageLabeler labeler = ImageLabeling.getClient(customImageLabelerOptions);
Uzaktan barındırılan bir modeliniz varsa bu modelin
indiremezsiniz. Model indirme işleminin durumunu kontrol edebilirsiniz.
model yöneticisinin isModelDownloaded()
yöntemini kullanarak görevi tamamlayın.
Etiketleyiciyi çalıştırmadan önce bunu onaylamanız yeterli olsa da hem uzaktan barındırılan hem de yerel olarak paketlenen örneklendirilirken şu kontrolü gerçekleştirmek mantıklıdır: etiketleyici indirilmişse uzak modelden ve yerel modelden modelini kullanmanız gerekir.
Kotlin
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener { isDownloaded -> val optionsBuilder = if (isDownloaded) { CustomImageLabelerOptions.Builder(remoteModel) } else { CustomImageLabelerOptions.Builder(localModel) } val options = optionsBuilder .setConfidenceThreshold(0.5f) .setMaxResultCount(5) .build() val labeler = ImageLabeling.getClient(options) }
Java
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Boolean isDownloaded) { CustomImageLabelerOptions.Builder optionsBuilder; if (isDownloaded) { optionsBuilder = new CustomImageLabelerOptions.Builder(remoteModel); } else { optionsBuilder = new CustomImageLabelerOptions.Builder(localModel); } CustomImageLabelerOptions options = optionsBuilder .setConfidenceThreshold(0.5f) .setMaxResultCount(5) .build(); ImageLabeler labeler = ImageLabeling.getClient(options); } });
Yalnızca uzaktan barındırılan bir modeliniz varsa modelle ilgili ayarını devre dışı bırakmanız gerekir.
(örneğin, kullanıcı arayüzünüzün bir kısmını devre dışı bırakan veya gizleyen)
modelin indirildiğini onaylayın. Bunu bir dinleyici ekleyerek
model yöneticisinin download()
yöntemine:
Kotlin
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener { // Download complete. Depending on your app, you could enable the ML // feature, or switch from the local model to the remote model, etc. }
Java
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void v) { // Download complete. Depending on your app, you could enable // the ML feature, or switch from the local model to the remote // model, etc. } });
2. Giriş resmini hazırlama
Ardından, etiketlemek istediğiniz her görüntü için birInputImage
oluşturun
nesnedir. Bitmap
kullandığınızda görüntü etiketleyici en hızlı şekilde çalışır
veya Camera2 API'sini kullanıyorsanız, YUV_420_888 media.Image
.
önerilir.
InputImage
oluşturabilirsiniz
her biri aşağıda açıklanmıştır.
media.Image
kullanarak
InputImage
oluşturmak için
media.Image
nesnesinden bir nesneden (örneğin,
cihazın kamerasını, media.Image
nesnesini ve resmin
döndürme değeri InputImage.fromMediaImage()
değerine ayarlanır.
URL'yi
CameraX kitaplığı, OnImageCapturedListener
ve
ImageAnalysis.Analyzer
sınıfları rotasyon değerini hesaplar
sizin için.
Kotlin
private class YourImageAnalyzer : ImageAnalysis.Analyzer { override fun analyze(imageProxy: ImageProxy) { val mediaImage = imageProxy.image if (mediaImage != null) { val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) // Pass image to an ML Kit Vision API // ... } } }
Java
private class YourAnalyzer implements ImageAnalysis.Analyzer { @Override public void analyze(ImageProxy imageProxy) { Image mediaImage = imageProxy.getImage(); if (mediaImage != null) { InputImage image = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees()); // Pass image to an ML Kit Vision API // ... } } }
Resmin dönme derecesini sağlayan bir kamera kitaplığı kullanmıyorsanız cihazın dönüş derecesinden ve kameranın yönünden hesaplayabilir cihazdaki sensör:
Kotlin
private val ORIENTATIONS = SparseIntArray() init { ORIENTATIONS.append(Surface.ROTATION_0, 0) ORIENTATIONS.append(Surface.ROTATION_90, 90) ORIENTATIONS.append(Surface.ROTATION_180, 180) ORIENTATIONS.append(Surface.ROTATION_270, 270) } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Throws(CameraAccessException::class) private fun getRotationCompensation(cameraId: String, activity: Activity, isFrontFacing: Boolean): Int { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. val deviceRotation = activity.windowManager.defaultDisplay.rotation var rotationCompensation = ORIENTATIONS.get(deviceRotation) // Get the device's sensor orientation. val cameraManager = activity.getSystemService(CAMERA_SERVICE) as CameraManager val sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION)!! if (isFrontFacing) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360 } else { // back-facing rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360 } return rotationCompensation }
Java
private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0, 0); ORIENTATIONS.append(Surface.ROTATION_90, 90); ORIENTATIONS.append(Surface.ROTATION_180, 180); ORIENTATIONS.append(Surface.ROTATION_270, 270); } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private int getRotationCompensation(String cameraId, Activity activity, boolean isFrontFacing) throws CameraAccessException { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int rotationCompensation = ORIENTATIONS.get(deviceRotation); // Get the device's sensor orientation. CameraManager cameraManager = (CameraManager) activity.getSystemService(CAMERA_SERVICE); int sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION); if (isFrontFacing) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360; } else { // back-facing rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360; } return rotationCompensation; }
Ardından, media.Image
nesnesini ve
döndürme derecesi değerini InputImage.fromMediaImage()
değerine ayarlayın:
Kotlin
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
Dosya URI'si kullanarak
InputImage
oluşturmak için
uygulama bağlamını ve dosya URI'sini
InputImage.fromFilePath()
. Bu özellik,
kullanıcıdan seçim yapmasını istemek için bir ACTION_GET_CONTENT
niyeti kullanın
galeri uygulamasından bir resim.
Kotlin
val image: InputImage try { image = InputImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
Java
InputImage image; try { image = InputImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
ByteBuffer
veya ByteArray
kullanarak
InputImage
oluşturmak için
bir ByteBuffer
veya ByteArray
nesnesinden alıp almayacaksanız önce resmi hesaplayın
media.Image
girişi için daha önce açıklandığı gibi dönme derecesi.
Ardından, arabellek veya diziyle InputImage
nesnesini, bu resmin
yükseklik, genişlik, renk kodlama biçimi ve döndürme derecesi:
Kotlin
val image = InputImage.fromByteBuffer( byteBuffer, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 ) // Or: val image = InputImage.fromByteArray( byteArray, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 )
Java
InputImage image = InputImage.fromByteBuffer(byteBuffer, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 ); // Or: InputImage image = InputImage.fromByteArray( byteArray, /* image width */480, /* image height */360, rotation, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 );
Bitmap
kullanarak
InputImage
oluşturmak için
Bitmap
nesnesindeki şu bildirimi yapın:
Kotlin
val image = InputImage.fromBitmap(bitmap, 0)
Java
InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);
Resim, döndürme dereceleriyle birlikte bir Bitmap
nesnesiyle temsil edilir.
3. Görüntü etiketleyiciyi çalıştırma
Bir görüntüdeki nesneleri etiketlemek için image
nesnesini ImageLabeler
öğesinin
process()
yöntemi.
Kotlin
labeler.process(image) .addOnSuccessListener { labels -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
Java
labeler.process(image) .addOnSuccessListener(new OnSuccessListener<List<ImageLabel>>() { @Override public void onSuccess(List<ImageLabel> labels) { // Task completed successfully // ... } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
4. Etiketli varlıklar hakkında bilgi edinme
Görüntü etiketleme işlemi başarılı olursaImageLabel
listesi
nesneleri başarılı işleyiciye aktarılır. Her ImageLabel
nesnesi, resimde etiketlenen bir şeyi temsil eder. Her etiketin metnini alabilirsiniz
açıklama (TensorFlow Lite model dosyasının meta verilerinde varsa), güven puanı ve dizin. Örneğin:
Kotlin
for (label in labels) { val text = label.text val confidence = label.confidence val index = label.index }
Java
for (ImageLabel label : labels) { String text = label.getText(); float confidence = label.getConfidence(); int index = label.getIndex(); }
Gerçek zamanlı performansı iyileştirmeye yönelik ipuçları
Görüntüleri gerçek zamanlı bir uygulamada etiketlemek isterseniz şu aşağıdaki talimatları uygulayın:
- URL'yi
Camera
veyacamera2
API, çağrıları sınırlamanız gerekir. Yeni bir video çerçeve, resim etiketleyici çalışırken kullanılabilir hale gelirse çerçeveyi bırakın. Bkz. Örnek için hızlı başlangıç örnek uygulamasındakiVisionProcessorBase
sınıfı. CameraX
API'yi kullanıyorsanız karşı baskı stratejisinin varsayılan değerine ayarlandığından emin olunImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
) Bu, aynı anda yalnızca bir resmin analiz için gönderilmesini garanti eder. Daha fazla resim üretilirse analiz aracı meşgulken üretilirse otomatik olarak bırakılır ve teslimat. Analiz edilen resim, çağırarak kapatıldıktan sonra ImageProxy.close(), bir sonraki en son resim yayınlanır.- Grafikleri üzerine bindirmek için görüntü etiketleyicinin çıkışını kullanırsanız
giriş görüntüsünü kullanın, önce ML Kit'ten sonucu alın ve ardından görüntüyü oluşturun
tek bir adımda yapabilirsiniz. Bu, görüntü yüzeyine oluşturulur
her giriş karesi için yalnızca bir kez. Bkz.
CameraSourcePreview
ve Hızlı başlangıç örnek uygulamasındakiGraphicOverlay
sınıflarına göz atın. - Camera2 API'sini kullanıyorsanız görüntüleri şurada yakalayın:
ImageFormat.YUV_420_888
biçimindedir. Eski Kamera API'sini kullanıyorsanız görüntüleri şurada yakalayın:ImageFormat.NV21
biçimindedir.