Resimde tanınan nesneleri etiketlemek için ML Kit'i kullanabilirsiniz. ML Kit ile birlikte sağlanan varsayılan model, 400'den fazla farklı etiketi destekler.
| Özellik | Paketlenmemiş | Gruplandırılanlar |
|---|---|---|
| Uygulama | Model, Google Play Hizmetleri aracılığıyla dinamik olarak indirilir. | Model, derleme zamanında statik olarak bağlanır. |
| Uygulama boyutu | Boyut yaklaşık 200 KB artar. | Boyutta yaklaşık 5,7 MB artış. |
| Başlatma süresi | İlk kullanımdan önce modelin indirilmesini beklemeniz gerekebilir. | Model hemen kullanılabilir |
Deneyin
- Bu API'nin kullanımına dair bir örnek görmek için örnek uygulamayı inceleyin.
Başlamadan önce
Proje düzeyindeki
build.gradledosyanızda, Google'ın Maven deposunu hembuildscripthem deallprojectsbölümüne eklediğinizden emin olun.ML Kit Android kitaplıklarına ait bağımlılıkları, modülünüzün uygulama düzeyindeki Gradle dosyasına (genellikle
app/build.gradle) ekleyin. İ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' }Google Play Hizmetleri'ndeki modeli kullanmayı tercih ederseniz uygulamanız Play Store'dan yüklendikten sonra modeli otomatik olarak cihaza indirecek şekilde yapılandırabilirsiniz. Bunu yapmak için uygulamanızın
AndroidManifest.xmldosyasına aşağıdaki bildirimi ekleyin:<application ...> ... <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="ica" > <!-- To use multiple models: android:value="ica,model2,model3" --> </application>Modelin kullanılabilirliğini açıkça kontrol edebilir ve Google Play Hizmetleri ModuleInstallClient API aracılığıyla indirme isteğinde bulunabilirsiniz.
Yükleme sırasında model indirmelerini etkinleştirmezseniz veya açıkça indirme isteğinde bulunmazsanız model, etiketleyiciyi ilk kez çalıştırdığınızda indirilir. İndirme tamamlanmadan önce yaptığınız istekler sonuç vermez.
Artık resimleri etiketlemeye hazırsınız.
1. Giriş resmini hazırlama
ResminizdenInputImage nesnesi oluşturun.
Resim etiketleyici, mümkün olduğunda önerilen Bitmap veya camera2 API'yi kullanıyorsanız YUV_420_888 media.Image kullanıldığında en hızlı şekilde çalışır.
Farklı kaynaklardan InputImage nesneleri oluşturabilirsiniz. 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 yakaladığınızda) media.Image nesnesini ve resmin dönüşünü InputImage.fromMediaImage()'e iletin.
CameraX kitaplığını kullanıyorsanız OnImageCapturedListener ve
ImageAnalysis.Analyzer sınıfları, sizin için döndürme değerini 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önüş derecesini veren bir kamera kitaplığı kullanmıyorsanız, cihazın dönüş derecesi ile cihazdaki kamera sensörünün yönünden 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()'ye 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()'ye iletin. Bu, kullanıcıdan galeri uygulamasından bir resim seçmesini istemek için ACTION_GET_CONTENT amacını kullandığınızda yararlı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 öncelikle media.Image girişi için daha önce açıklandığı gibi görüntü döndürme derecesini hesaplayın.
Ardından, arabellek veya diziyle birlikte resmin yüksekliği, genişliği, renk kodlama biçimi ve döndürme derecesiyle 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 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 gösterilir.
2. Görüntü etiketleyicisini yapılandırma ve çalıştırma
Resimdeki nesneleri etiketlemek içinInputImage nesnesini ImageLabeler'nin process yöntemine iletin.
Öncelikle
ImageLabelerörneği alın.Cihaz üzerinde resim etiketleyiciyi kullanmak istiyorsanız aşağıdaki bildirimi 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, görüntüyü
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 alma
Resim etiketleme işlemi başarılı olursaImageLabel nesnelerin listesi başarı dinleyicisine iletilir. Her ImageLabel nesnesi, resimde etiketlenen bir şeyi 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 dizinini 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(); }
Anlık performansı artırmaya yönelik ipuçları
Görüntüleri gerçek zamanlı bir uygulamada etiketlemek istiyorsanız en iyi kare hızlarını elde etmek için aşağıdaki yönergeleri uygulayın:
Cameraveyacamera2API'sini kullanıyorsanız görüntü etiketleyiciye yapılan çağrıları sınırlayın. Görüntü etiketleyici çalışırken yeni bir video karesi kullanılabilir hâle gelirse kareyi bırakın. Örnek için hızlı başlangıç örnek uygulamasındakiVisionProcessorBasesınıfına bakın.CameraXAPI'sini kullanıyorsanız geri basınç stratejisinin varsayılan değerine ayarlandığından emin olunImageAnalysis.STRATEGY_KEEP_ONLY_LATEST. Bu, analiz için aynı anda yalnızca bir resmin gönderilmesini sağlar. Analizör meşgulken daha fazla resim üretilirse bunlar otomatik olarak bırakılır ve teslimat için sıraya alınmaz. Analiz edilen görüntü ImageProxy.close() çağrılarak kapatıldığında en son görüntü teslim edilir.- Giriş resmine grafik yerleştirmek için resim etiketleyicinin çıkışını kullanıyorsanız önce ML Kit'ten sonucu alın, ardından resmi tek adımda oluşturup yerleştirin. Bu, her giriş karesi için yalnızca bir kez görüntüleme yüzeyinde oluşturulur. Örnek için hızlı başlangıç örnek uygulamasındaki
CameraSourcePreviewveGraphicOverlaysınıflarına bakın. - Camera2 API'yi kullanıyorsanız görüntüleri
ImageFormat.YUV_420_888biçiminde çekin. Eski Camera API'yi kullanıyorsanız görüntüleriImageFormat.NV21biçiminde çekin.