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 | Paket halinde sunulmayan | 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.gradle
dosyanızda, Google'ın Maven deposunu hembuildscript
hem deallprojects
bö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.xml
dosyası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
nesnesi 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 ve cihazdaki kamera sensörünün yönlendirmesinden yararlanarak dönüş derecesini 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 indeksini 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:
Camera
veyacamera2
API'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ı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, 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
CameraSourcePreview
veGraphicOverlay
sınıflarına bakın. - Camera2 API'yi kullanıyorsanız
ImageFormat.YUV_420_888
biçiminde resim çekin. Eski Camera API'yi kullanıyorsanız görüntüleriImageFormat.NV21
biçiminde çekin.