Kendi eğitiminizi tamamladıktan sonra kullanıyorsanız bu modeli uygulamanızda etiketleyerek resim.
Başlamadan önce
- Henüz yapmadıysanız Firebase'i Android projenize ekleyin.
- Modülünüze ML Kit Android kitaplıkları için bağımlılıkları ekleyin
(uygulama düzeyinde) Gradle dosyası (genellikle
app/build.gradle
):apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' dependencies { // ... implementation 'com.google.firebase:firebase-ml-vision:24.0.3' implementation 'com.google.firebase:firebase-ml-vision-automl:18.0.5' }
1. Modeli yükleme
ML Kit, AutoML tarafından oluşturulan modellerinizi cihazda çalıştırır. Ancak, ML Kit'i, modelinizi Firebase'den veya ya da her ikisi birden olabilir.
Modeli Firebase'de barındırarak modeli yayınlamadan güncelleyebilirsiniz. ve Remote Config ve A/B Testing öğelerini kullanarak şunları yapabilirsiniz: Farklı kullanıcı gruplarına dinamik olarak farklı modeller sunar.
Modeli Firebase'de barındırarak değil, yalnızca Firebase'de barındırarak sağlamayı seçerseniz uygulamanızla birlikte paket haline getirirseniz uygulamanızın başlangıçtaki indirme boyutunu küçültebilirsiniz. Bununla birlikte, modelin uygulamanızla birlikte paket halinde olmadığı durumlarda, uygulamanız, uygulamanızı indirene kadar modelle ilgili işlevleri ilk kez devreye giriyor.
Modelinizi uygulamanızla paket haline getirerek uygulamanızın makine öğrenimi özelliklerinin etkin olmasını sağlayabilirsiniz. Firebase tarafından barındırılan model kullanılamadığında çalışmaya devam eder.
Firebase tarafından barındırılan bir model kaynağını yapılandırma
Uzaktan barındırılan modeli kullanmak için bir FirebaseAutoMLRemoteModel
nesnesi oluşturun.
modeli yayınlarken atadığınız adı belirtin:
Java
// Specify the name you assigned in the Firebase console.
FirebaseAutoMLRemoteModel remoteModel =
new FirebaseAutoMLRemoteModel.Builder("your_remote_model").build();
Kotlin+KTX
// Specify the name you assigned in the Firebase console.
val remoteModel = FirebaseAutoMLRemoteModel.Builder("your_remote_model").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:
Java
FirebaseModelDownloadConditions conditions = new FirebaseModelDownloadConditions.Builder()
.requireWifi()
.build();
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
// Success.
}
});
Kotlin+KTX
val conditions = FirebaseModelDownloadConditions.Builder()
.requireWifi()
.build()
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnCompleteListener {
// Success.
}
Birçok uygulama, indirme görevini başlatma kodunda başlatır, ancak bunu, modeli kullanmaya başlamadan önce istediğiniz zaman yapabilirsiniz.
Yerel model kaynağını yapılandırma
Modeli uygulamanızla paket haline getirmek için:
- İndirdiğiniz zip arşivinden modeli ve meta verilerini çıkarın Firebase konsolundan yönetebilirsiniz. Dosyaları indirirken kullanmanızı öneririz (dosya adları dahil) yapılmamalıdır.
-
Modelinizi ve meta veri dosyalarını uygulama paketinize ekleyin:
- Projenizde bir öğe klasörü yoksa şu tarihe kadar bir klasör oluşturun:
app/
klasörünü sağ tıklayıp Yeni > Klasör > Öğeler klasörünü açın. - Öğelerin altında modeli içerecek bir alt klasör oluşturun dosyası olarak da kaydedebilir.
model.tflite
,dict.txt
vemanifest.json
öğesini alt klasöre ekleyin (üç dosyanın tamamı aynı klasör içinde yer alır).
- Projenizde bir öğe klasörü yoksa şu tarihe kadar bir klasör oluşturun:
- Aşağıdakini uygulamanızın
build.gradle
dosyasına ekleyin: Gradle, uygulamayı oluştururken model dosyasını sıkıştırmaz: Model dosyası uygulama paketine dahil edilir ve ML Kit tarafından kullanılabilir işlenmemiş bir öğe olarak görebiliriz.android { // ... aaptOptions { noCompress "tflite" } }
- Model manifestinin yolunu belirterek bir
FirebaseAutoMLLocalModel
nesnesi oluşturun dosya:Java
FirebaseAutoMLLocalModel localModel = new FirebaseAutoMLLocalModel.Builder() .setAssetFilePath("manifest.json") .build();
Kotlin+KTX
val localModel = FirebaseAutoMLLocalModel.Builder() .setAssetFilePath("manifest.json") .build()
Modelinizden görüntü etiketleyici oluşturma
Model kaynaklarınızı yapılandırdıktan sonra bir FirebaseVisionImageLabeler
oluşturun
olabilir.
Yalnızca yerel olarak paketlenmiş bir modeliniz varsa
FirebaseAutoMLLocalModel
nesnesini tanımlayın ve güven puanı eşiğini yapılandırın
(Modelinizi değerlendirme bölümüne bakın):
Java
FirebaseVisionImageLabeler labeler;
try {
FirebaseVisionOnDeviceAutoMLImageLabelerOptions options =
new FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder(localModel)
.setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console
// to determine an appropriate value.
.build();
labeler = FirebaseVision.getInstance().getOnDeviceAutoMLImageLabeler(options);
} catch (FirebaseMLException e) {
// ...
}
Kotlin+KTX
val options = FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder(localModel)
.setConfidenceThreshold(0) // Evaluate your model in the Firebase console
// to determine an appropriate value.
.build()
val labeler = FirebaseVision.getInstance().getOnDeviceAutoMLImageLabeler(options)
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.
Java
FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
.addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean isDownloaded) {
FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder optionsBuilder;
if (isDownloaded) {
optionsBuilder = new FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder(remoteModel);
} else {
optionsBuilder = new FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder(localModel);
}
FirebaseVisionOnDeviceAutoMLImageLabelerOptions options = optionsBuilder
.setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console
// to determine an appropriate threshold.
.build();
FirebaseVisionImageLabeler labeler;
try {
labeler = FirebaseVision.getInstance().getOnDeviceAutoMLImageLabeler(options);
} catch (FirebaseMLException e) {
// Error.
}
}
});
Kotlin+KTX
FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
.addOnSuccessListener { isDownloaded ->
val optionsBuilder =
if (isDownloaded) {
FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder(remoteModel)
} else {
FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder(localModel)
}
// Evaluate your model in the Firebase console to determine an appropriate threshold.
val options = optionsBuilder.setConfidenceThreshold(0.0f).build()
val labeler = FirebaseVision.getInstance().getOnDeviceAutoMLImageLabeler(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:
Java
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@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.
}
});
Kotlin+KTX
FirebaseModelManager.getInstance().download(remoteModel, conditions)
.addOnCompleteListener {
// 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 bir FirebaseVisionImage
nesnesi oluşturun
bu bölümde açıklanan seçeneklerden birini kullanarak videoyu
FirebaseVisionImageLabeler
(sonraki bölümde açıklanmıştır).
media.Image
nesnesinden bir FirebaseVisionImage
nesnesi oluşturabilirsiniz.
bir bayt dizisi veya Bitmap
nesnesindeki gibi:
-
Bir
FirebaseVisionImage
nesnesi oluşturmak içinmedia.Image
nesnesi, örneğin birmedia.Image
nesnesini ve görüntününFirebaseVisionImage.fromMediaImage()
değerine döndürülüyor.URL'yi CameraX kitaplığı,
OnImageCapturedListener
veImageAnalysis.Analyzer
sınıfları rotasyon değerini hesaplar gerekir, bu nedenle rotasyonu ML Kit'lerinden birine veya Çağrıdan önceROTATION_
sabit değerFirebaseVisionImage.fromMediaImage()
:Java
private class YourAnalyzer implements ImageAnalysis.Analyzer { private int degreesToFirebaseRotation(int degrees) { switch (degrees) { case 0: return FirebaseVisionImageMetadata.ROTATION_0; case 90: return FirebaseVisionImageMetadata.ROTATION_90; case 180: return FirebaseVisionImageMetadata.ROTATION_180; case 270: return FirebaseVisionImageMetadata.ROTATION_270; default: throw new IllegalArgumentException( "Rotation must be 0, 90, 180, or 270."); } } @Override public void analyze(ImageProxy imageProxy, int degrees) { if (imageProxy == null || imageProxy.getImage() == null) { return; } Image mediaImage = imageProxy.getImage(); int rotation = degreesToFirebaseRotation(degrees); FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation); // Pass image to an ML Kit Vision API // ... } }
Kotlin+KTX
private class YourImageAnalyzer : ImageAnalysis.Analyzer { private fun degreesToFirebaseRotation(degrees: Int): Int = when(degrees) { 0 -> FirebaseVisionImageMetadata.ROTATION_0 90 -> FirebaseVisionImageMetadata.ROTATION_90 180 -> FirebaseVisionImageMetadata.ROTATION_180 270 -> FirebaseVisionImageMetadata.ROTATION_270 else -> throw Exception("Rotation must be 0, 90, 180, or 270.") } override fun analyze(imageProxy: ImageProxy?, degrees: Int) { val mediaImage = imageProxy?.image val imageRotation = degreesToFirebaseRotation(degrees) if (mediaImage != null) { val image = FirebaseVisionImage.fromMediaImage(mediaImage, imageRotation) // Pass image to an ML Kit Vision API // ... } } }
Resmin döndürmesini sağlayan bir kamera kitaplığı kullanmıyorsanız cihazın dönüşüne ve kameranın yönüne göre hesaplanabilir cihazdaki sensör:
Java
private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 180); } /** * 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, Context context) 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); // On most devices, the sensor orientation is 90 degrees, but for some // devices it is 270 degrees. For devices with a sensor orientation of // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees. CameraManager cameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE); int sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION); rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360; // Return the corresponding FirebaseVisionImageMetadata rotation value. int result; switch (rotationCompensation) { case 0: result = FirebaseVisionImageMetadata.ROTATION_0; break; case 90: result = FirebaseVisionImageMetadata.ROTATION_90; break; case 180: result = FirebaseVisionImageMetadata.ROTATION_180; break; case 270: result = FirebaseVisionImageMetadata.ROTATION_270; break; default: result = FirebaseVisionImageMetadata.ROTATION_0; Log.e(TAG, "Bad rotation value: " + rotationCompensation); } return result; }
Kotlin+KTX
private val ORIENTATIONS = SparseIntArray() init { ORIENTATIONS.append(Surface.ROTATION_0, 90) ORIENTATIONS.append(Surface.ROTATION_90, 0) ORIENTATIONS.append(Surface.ROTATION_180, 270) ORIENTATIONS.append(Surface.ROTATION_270, 180) } /** * 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, context: Context): 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) // On most devices, the sensor orientation is 90 degrees, but for some // devices it is 270 degrees. For devices with a sensor orientation of // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees. val cameraManager = context.getSystemService(CAMERA_SERVICE) as CameraManager val sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION)!! rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360 // Return the corresponding FirebaseVisionImageMetadata rotation value. val result: Int when (rotationCompensation) { 0 -> result = FirebaseVisionImageMetadata.ROTATION_0 90 -> result = FirebaseVisionImageMetadata.ROTATION_90 180 -> result = FirebaseVisionImageMetadata.ROTATION_180 270 -> result = FirebaseVisionImageMetadata.ROTATION_270 else -> { result = FirebaseVisionImageMetadata.ROTATION_0 Log.e(TAG, "Bad rotation value: $rotationCompensation") } } return result }
Ardından,
media.Image
nesnesini ve rotasyon değeriniFirebaseVisionImage.fromMediaImage()
değerine ayarlayın:Java
FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
Kotlin+KTX
val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
- Dosya URI'sinden bir
FirebaseVisionImage
nesnesi oluşturmak için uygulama bağlamını ve dosya URI'siniFirebaseVisionImage.fromFilePath()
. Bu özellik, kullanıcıdan seçim yapmasını istemek için birACTION_GET_CONTENT
niyeti kullanın galeri uygulamasından bir resim.Java
FirebaseVisionImage image; try { image = FirebaseVisionImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
Kotlin+KTX
val image: FirebaseVisionImage try { image = FirebaseVisionImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
- Bir
FirebaseVisionImage
nesnesi oluşturmak içinByteBuffer
veya bir bayt dizisi, önce görüntüyü hesaplayınmedia.Image
girişi için yukarıda açıklandığı gibi döndürülmesini sağlayın.Ardından, bir
FirebaseVisionImageMetadata
nesnesi oluşturun yüksekliğini, genişliğini, renk kodlaması biçimini ve ve rotasyon:Java
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder() .setWidth(480) // 480x360 is typically sufficient for .setHeight(360) // image recognition .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build();
Kotlin+KTX
val metadata = FirebaseVisionImageMetadata.Builder() .setWidth(480) // 480x360 is typically sufficient for .setHeight(360) // image recognition .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build()
Aşağıdakini oluşturmak için arabelleği veya diziyi ve meta veri nesnesini kullanın:
FirebaseVisionImage
nesne:Java
FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata); // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
Kotlin+KTX
val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata) // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
- Bir
FirebaseVisionImage
nesnesi oluşturmak içinBitmap
nesne:Java
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
Kotlin+KTX
val image = FirebaseVisionImage.fromBitmap(bitmap)
Bitmap
nesnesi tarafından temsil edilen resim, dik olmalıdır, ek döndürme gerekmez.
3. Görüntü etiketleyiciyi çalıştırma
Bir görüntüdeki nesneleri etiketlemek için FirebaseVisionImage
nesnesini
FirebaseVisionImageLabeler
ürününün processImage()
yöntemi.
Java
labeler.processImage(image)
.addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionImageLabel>>() {
@Override
public void onSuccess(List<FirebaseVisionImageLabel> labels) {
// Task completed successfully
// ...
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Task failed with an exception
// ...
}
});
Kotlin+KTX
labeler.processImage(image)
.addOnSuccessListener { labels ->
// Task completed successfully
// ...
}
.addOnFailureListener { e ->
// Task failed with an exception
// ...
}
Görüntü etiketleme başarılı olursa FirebaseVisionImageLabel
nesne dizisi
başarıyla dinleyiciye iletilecektir. Her nesneden bu şekilde
resimde tanınan bir özellikle ilgili bilgi verir.
Örneğin:
Java
for (FirebaseVisionImageLabel label: labels) {
String text = label.getText();
float confidence = label.getConfidence();
}
Kotlin+KTX
for (label in labels) {
val text = label.text
val confidence = label.confidence
}
Gerçek zamanlı performansı iyileştirmeye yönelik ipuçları
- Algılayıcıya yapılan çağrıları hızlandırın. Yeni bir video karesi kullanılabilir durumdaysa çerçeveyi bırakın.
- Algılayıcının çıkışını üzerine grafik yerleştirmek için kullanıyorsanı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 şekilde, öğeleri ekran yüzeyinde her giriş karesi için yalnızca bir kez.
-
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.