Görüntüde tanınan nesneleri etiketlemek için ML Kit'i kullanabilirsiniz. ML Kit ile sağlanan varsayılan model, 400'den fazla farklı etiketi destekler.
Öne Çıkarın | Gruplandırılmamış | Gruplandırılanlar |
---|---|---|
Uygulama | Model, Google Play Hizmetleri aracılığıyla dinamik olarak indirilir. | Model, derleme sırasında statik olarak size bağlıdır. |
Uygulama boyutu | Yaklaşık 200 KB boyut artışı. | Yaklaşık 5,7 MB boyut artışı. |
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ıza, hembuildscript
hem deallprojects
bölümlerinize Google'ın Maven deposunu dahil ettiğinizden emin olun.ML Kit Android kitaplıklarının bağımlılıklarını, modülünüzün uygulama düzeyindeki gradle dosyasına ekleyin. Bu dosya genellikle
app/build.gradle
olur. İhtiyaçlarınıza göre aşağıdaki bağımlılıklardan birini seçin:Modeli uygulamanızla gruplandırmak için:
dependencies { // ... // Use this dependency to bundle the model with your app implementation 'com.google.mlkit:image-labeling:17.0.8' }
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ı, 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, model kullanılabilirliğini açıkça kontrol edebilir ve Google Play Hizmetleri ModuleUploadClient API üzerinden indirme isteğinde bulunabilirsiniz.
Yükleme zamanı modelinin indirilmesini etkinleştirmez veya açık indirme isteğinde bulunmazsanız etiketleyiciyi ilk çalıştırdığınızda model indirilir. İndirme işlemi tamamlanmadan önce yaptığınız istekler sonuç vermez.
Artık görüntüleri etiketlemeye hazırsınız.
1. Giriş resmini hazırlama
Resminizden birInputImage
nesnesi oluşturun.
Görüntü etiketleyici, Bitmap
veya kamera2 API'si kullanıyorsanız YUV_420_888 media.Image
(mümkün olduğunda önerilir) kullandığınızda en hızlı şekilde çalışır.
Farklı kaynaklardan InputImage
nesnesi oluşturabilirsiniz. Bu nesnelerin her biri aşağıda açıklanmıştır.
media.Image
kullanarak
media.Image
nesnesinden InputImage
nesnesi oluşturmak için (örneğin, cihaz kamerasından resim çekerken) media.Image
nesnesini ve görüntünün dönüşünü InputImage.fromMediaImage()
yönüne geçirin.
KameraX kitaplığını kullanırsanı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önüş derecesini gösteren bir kamera kitaplığı kullanmıyorsanız cihazın dönüş derecesinden ve 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öndürme derecesi değerini InputImage.fromMediaImage()
öğesine geçirin:
Kotlin
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
Dosya URI'si kullanarak
Dosya URI'sinden bir InputImage
nesnesi oluşturmak için uygulama bağlamını ve dosya URI'sini InputImage.fromFilePath()
öğesine iletin. Bu, kullanıcıdan galeri uygulamasından resim seçmesini istemek için ACTION_GET_CONTENT
niyeti kullandığınızda yararlı olur.
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
ByteBuffer
veya ByteArray
öğesinden InputImage
nesnesi oluşturmak için önce media.Image
girişi için daha önce açıklandığı gibi resim 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 arabellek veya diziyle 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
kullanarak
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 temsil edilir.
2. Görüntü etiketleyiciyi yapılandırma ve çalıştırma
Bir görüntüdeki nesneleri etiketlemek içinInputImage
nesnesini ImageLabeler
öğesinin process
yöntemine iletin.
İlk olarak
ImageLabeler
için bir örnek alın.Cihaz üzerinde görüntü 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. Etiketli nesneler hakkında bilgi edinme
Görüntü etiketleme işlemi başarılı olursaImageLabel
nesnelerinin listesi başarılı işleyiciye iletilir. Her ImageLabel
nesnesi, resimde etiketli olan 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 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ı
Görüntüleri gerçek zamanlı bir uygulamada etiketlemek istiyorsanız en iyi kare hızlarını elde etmek için şu yönergeleri uygulayın:
Camera
veyacamera2
API kullanıyorsanız görüntü etiketleyiciye yapılan çağrıları kısıtlayın. Görüntü etiketleyici çalışırken yeni bir video karesi kullanılabilir hale gelirse kareyi bırakın. Örnek için hızlı başlangıç örnek uygulamasındakiVisionProcessorBase
sınıfına göz atın.CameraX
API'yi kullanıyorsanız karşı basınç stratejisinin varsayılan değerine (ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
) ayarlandığından emin olun. Bu, aynı anda yalnızca bir resmin analiz için gönderilmesini garanti eder. Analiz aracı meşgulken daha fazla görüntü üretilirse bu görüntüler otomatik olarak bırakılır ve teslim edilmek üzere sıraya alınmaz. Analiz edilen resim ImageProxy.close() çağrısı yapılarak kapatıldıktan sonra, bir sonraki son resim yayınlanır.- Giriş görüntüsünün üzerine grafik yerleştirmek için görüntü etiketleyicinin çıkışını kullanırsanız önce ML Kit'ten sonucu alın, ardından görüntüyü ve bindirme tek bir adımda oluşturun. Bu, her bir giriş karesi için görüntü yüzeyinde yalnızca bir kez oluşturulur. Örnek için hızlı başlangıç örnek uygulamasındaki
CameraSourcePreview
veGraphicOverlay
sınıflarına göz atın. - Camera2 API'yi kullanıyorsanız görüntüleri
ImageFormat.YUV_420_888
biçiminde çekin. Eski Kamera API'sini kullanıyorsanız görüntüleriImageFormat.NV21
biçiminde çekin.