Bir resimde tanınan nesneleri etiketlemek için ML Kit'i kullanabilirsiniz. ML Kit ile sağlanan varsayılan model 400'den fazla farklı etiketi destekler.
Özellik | Paketsiz | Gruplandırılanlar |
---|---|---|
Uygulama | Model, Google Play Hizmetleri aracılığıyla dinamik olarak indirilir. | Model, derleme sırasında statik olarak bağlanır. |
Uygulama boyutu | Boyut yaklaşık 200 KB artar. | Boyut yaklaşık 5,7 MB artar. |
Başlatma süresi | İlk kullanımdan önce modelin indirilmesini beklemeniz gerekebilir. | Model hemen kullanılabilir |
Deneyin
- Bu API'nin örnek kullanımını görmek için örnek uygulamayı inceleyin.
Başlamadan önce
Proje düzeyindeki
build.gradle
dosyanızda, Google'ın Maven deposunu hembuildscript
hem deallprojects
bölümlerinize eklediğinizden emin olun.ML Kit Android kitaplıklarının bağımlılıkları, modülünüzün uygulama düzeyindeki Gradle dosyasına (genellikle
app/build.gradle
) eklenmelidir. İhtiyaçlarınıza göre aşağıdaki bağımlılıklardan birini seçin:Modeli uygulamanızla paketlemek için:
dependencies { // ... // Use this dependency to bundle the model with your app implementation 'com.google.mlkit:image-labeling:17.0.9' }
Modeli Google Play Hizmetleri'nde kullanmak için:
dependencies { // ... // Use this dependency to use the dynamically downloaded model in Google Play Services implementation 'com.google.android.gms:play-services-mlkit-image-labeling:16.0.8' }
Modeli Google Play Hizmetleri'nde kullanmayı seçerseniz uygulamanızı, Play Store'dan yüklendikten sonra modeli cihaza otomatik olarak indirecek şekilde yapılandırabilirsiniz. Bunu yapmak için uygulamanızın
AndroidManifest.xml
dosyasına aşağıdaki beyanı ekleyin:<application ...> ... <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="ica" > <!-- To use multiple models: android:value="ica,model2,model3" --> </application>
Ayrıca Google Play Hizmetleri ModuleInstallClient API aracılığıyla modelin kullanılabilirliğini açıkça kontrol edebilir ve indirme isteğinde bulunabilirsiniz.
Yükleme sırasında model indirmelerini etkinleştirmezseniz veya açık indirme isteğinde bulunmazsanız model, etiketleyiciyi ilk kez çalıştırdığınızda indirilir. İndirme tamamlanmadan önce gönderdiğiniz istekler sonuç vermez.
Artık görselleri etiketlemeye hazırsınız.
1. Giriş resmini hazırlama
Resminizden birInputImage
nesnesi oluşturun.
Resim etiketleyici, Bitmap
veya camera2 API'yi kullanıyorsanız mümkün olduğunda önerilen YUV_420_888 media.Image
kullanıldığında en hızlı şekilde çalışır.
Farklı kaynaklardan InputImage
nesnesi oluşturabilirsiniz. Bunların her biri aşağıda açıklanmıştır.
media.Image
kullanma
Bir media.Image
nesnesinden InputImage
nesnesi oluşturmak için (ör. bir cihazın kamerasından resim çekerken) media.Image
nesnesini ve resmin dönme açısını InputImage.fromMediaImage()
'e iletin.
CameraX kitaplığını kullanıyorsanız OnImageCapturedListener
ve ImageAnalysis.Analyzer
sınıfları rotasyon değerini sizin için hesaplar.
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 gösteren bir kamera kitaplığı kullanmıyorsanız bunu cihazın dönme derecesinden ve cihazdaki kamera sensörünün yöneliminden hesaplayabilirsiniz:
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önüş derecesi değerini InputImage.fromMediaImage()
'e iletin:
Kotlin
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
Dosya URI'si kullanma
Dosya URI'sinden InputImage
nesnesi oluşturmak için uygulama bağlamını ve dosya URI'sini InputImage.fromFilePath()
'a iletin. Bu, kullanıcıdan galeri uygulamasından bir resim seçmesini istemek için ACTION_GET_CONTENT
intent'i kullandığınızda kullanışlıdır.
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
kullanma
ByteBuffer
veya ByteArray
öğesinden InputImage
nesnesi oluşturmak için önce, media.Image
girişi için daha önce açıklandığı gibi görüntünün döndürme derecesini hesaplayın.
Ardından, resmin yüksekliği, genişliği, renk kodlama biçimi ve döndürme derecesiyle birlikte arabelleği veya diziyi kullanarak InputImage
nesnesini oluşturun:
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
kullanma
Bitmap
nesnesinden InputImage
nesnesi oluşturmak için aşağıdaki beyanı yapın:
Kotlin
val image = InputImage.fromBitmap(bitmap, 0)
Java
InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);
Resim, döndürme dereceleriyle birlikte bir Bitmap
nesnesi ile temsil edilir.
2. Resim etiketleyiciyi yapılandırma ve çalıştırma
Bir resimdeki nesneleri etiketlemek içinInputImage
nesnesini ImageLabeler
'un process
yöntemine iletin.
Öncelikle
ImageLabeler
örneği alın.Cihaz üzerinde resim etiketleyiciyi kullanmak istiyorsanız aşağıdaki beyanı yapın:
Kotlin
// To use default options: val labeler = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS) // Or, to set the minimum confidence required: // val options = ImageLabelerOptions.Builder() // .setConfidenceThreshold(0.7f) // .build() // val labeler = ImageLabeling.getClient(options)
Java
// To use default options: ImageLabeler labeler = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS); // Or, to set the minimum confidence required: // ImageLabelerOptions options = // new ImageLabelerOptions.Builder() // .setConfidenceThreshold(0.7f) // .build(); // ImageLabeler labeler = ImageLabeling.getClient(options);
- Ardından, resmi
process()
yöntemine iletin:
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 // ... } });
3. Etiketlenmiş nesneler hakkında bilgi edinme
Görüntü etiketleme işlemi başarılı olursa başarı dinleyicisine birImageLabel
nesnesi listesi iletilir. Her ImageLabel
nesnesi, resimde etiketlenmiş bir nesneyi temsil eder. Temel model 400'den fazla farklı etiketi destekler.
Her etiketin metin açıklamasını, model tarafından desteklenen tüm etiketler arasındaki dizini ve eşleşmenin güven puanını alabilirsiniz. Ö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ı
Gerçek zamanlı bir uygulamada resimleri etiketlemek istiyorsanız en iyi kare hızlarına ulaşmak için aşağıdaki yönergeleri uygulayın:
Camera
veyacamera2
API'yi kullanıyorsanız resim etiketleyiciye yapılan çağrıları sınırlandırın. Resim etiketleyici çalışırken yeni bir video karesi kullanılabilir hale gelirse kareyi bırakın. Örnek olarak hızlı başlangıç kılavuzu örnek uygulamasındakiVisionProcessorBase
sınıfına bakın.CameraX
API'sini kullanıyorsanız geri basınç stratejisinin varsayılan değerine ayarlandığından emin olunImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
. Bu sayede, aynı anda analiz için yalnızca bir resim gönderilir. Analizör meşgulken daha fazla görüntü oluşturulursa bu görüntüler otomatik olarak bırakılır ve yayınlama için sıraya alınmaz. Analiz edilen resim, ImageProxy.close() çağrısı yapılarak kapatıldıktan sonra bir sonraki en yeni resim yayınlanır.- Giriş resmine grafik yerleştirmek için resim etiketleyicinin çıkışını kullanıyorsanız önce ML Kit'ten sonucu alın, ardından resmi ve yer paylaşımını tek bir adımda oluşturun. Bu, her giriş karesi için yalnızca bir kez görüntü yüzeyinde oluşturulur. Örnek olarak, hızlı başlangıç kılavuzundaki örnek uygulamadaki
CameraSourcePreview
veGraphicOverlay
sınıflarına bakın. - Camera2 API'yi kullanıyorsanız resimleri
ImageFormat.YUV_420_888
biçiminde kaydedin. Eski Camera API'yi kullanıyorsanız resimleriImageFormat.NV21
biçiminde çekin.