Android'de Firebase ML ile Resim Etiketleme

Bir resimde tanınan nesneleri etiketlemek için Firebase ML ifadesini kullanabilirsiniz. Bkz. genel bakış ile bu API'nin özellikleri hakkında özellikleri.

ziyaret edin.

Başlamadan önce

  1. Henüz yapmadıysanız Firebase'i Android projenize ekleyin.
  2. Modül (uygulama düzeyinde) Gradle dosyanızda (genellikle <project>/<app-module>/build.gradle.kts veya <project>/<app-module>/build.gradle), Android için Firebase ML Vision kitaplığına bağımlılığı ekleyin. Şunu kullanmanızı öneririz: Firebase Android BoM Kitaplık'ta sürüm oluşturmayı kontrol etmek için
    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.3.0"))
    
        // Add the dependency for the Firebase ML Vision library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-vision'
    }

    Firebase Android BoM kullanıldığında, Uygulamanız her zaman Firebase Android kitaplıklarının uyumlu sürümlerini kullanacaktır.

    (Alternatif) Firebase kitaplığı bağımlılıklarını kullanmadanBoM

    Firebase BoM kullanmamayı seçerseniz her Firebase kitaplığı sürümünü belirtmeniz gerekir değerini alır.

    Uygulamanızda birden çok Firebase kitaplığı kullanıyorsanız, kitaplık sürümlerini yönetmek için BoM kullanmanızı öneririz. Bu, tüm sürümlerin uyumlu olduğundan emin olun.

    dependencies {
        // Add the dependency for the Firebase ML Vision library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-vision:24.1.0'
    }
    Kotlin'e özel bir kitaplık modülü mü arıyorsunuz? Başlamak için kalan süre: Ekim 2023 (Firebase BoM 32.5.0), hem Kotlin hem de Java geliştiricileri (ayrıntılar için bkz. Bu girişimle ilgili SSS).
  3. Projeniz için Cloud tabanlı API'leri henüz etkinleştirmediyseniz etkinleştirin şimdi:

    1. Firebase ML Firebase konsolunun API'ler sayfası.
    2. Projenizi daha önce Blaze fiyatlandırma planına yükseltmediyseniz Bunun için yeni sürüme geçin. (Yalnızca emin olun.)

      Bulut tabanlı API'ler yalnızca Blaze düzeyindeki projelerde kullanılabilir.

    3. Cloud tabanlı API'ler henüz etkinleştirilmemişse Bulut tabanlı API'leri etkinleştir'i tıklayın. API'ler.
    ziyaret edin.

Artık görüntüleri etiketlemeye hazırsınız.

1. Giriş resmini hazırlama

Resminizden bir FirebaseVisionImage nesnesi oluşturun. Görüntü etiketleyici, Bitmap kullandığınızda veya Camera2 API'sının JPEG biçiminde bir media.Image olması gerekir. Bu API'nin yapmasını sağlar.

  • Bir FirebaseVisionImage nesnesi oluşturmak için media.Image nesnesi, örneğin bir media.Image nesnesini ve görüntünün FirebaseVisionImage.fromMediaImage() değerine döndürülüyor.

    URL'yi CameraX kitaplığı, OnImageCapturedListener ve ImageAnalysis.Analyzer sınıfları rotasyon değerini hesaplar Bu nedenle, rotasyonu Firebase ML özelliklerinden birine dönüştürmeniz yeterlidir Çağrıdan önce ROTATION_ sabit değer FirebaseVisionImage.fromMediaImage():

    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 Vision API
                // ...
            }
        }
    }

    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 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:

    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
    }

    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;
    }

    Ardından, media.Image nesnesini ve rotasyon değerini FirebaseVisionImage.fromMediaImage() olarak ayarlayın:

    Kotlin+KTX

    val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)

    Java

    FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
  • Dosya URI'sinden bir FirebaseVisionImage nesnesi oluşturmak için uygulama bağlamını ve dosya URI'sini FirebaseVisionImage.fromFilePath(). Bu özellik, kullanıcıdan seçim yapmasını istemek için bir ACTION_GET_CONTENT niyeti kullanın galeri uygulamasından bir resim.

    Kotlin+KTX

    val image: FirebaseVisionImage
    try {
        image = FirebaseVisionImage.fromFilePath(context, uri)
    } catch (e: IOException) {
        e.printStackTrace()
    }

    Java

    FirebaseVisionImage image;
    try {
        image = FirebaseVisionImage.fromFilePath(context, uri);
    } catch (IOException e) {
        e.printStackTrace();
    }
  • Bir FirebaseVisionImage nesnesi oluşturmak için ByteBuffer veya bir bayt dizisi, önce görüntüyü hesaplayın media.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:

    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()

    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();

    Aşağıdakini oluşturmak için arabelleği veya diziyi ve meta veri nesnesini kullanın: FirebaseVisionImage nesne:

    Kotlin+KTX

    val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata)
    // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)

    Java

    FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata);
    // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
  • Bir FirebaseVisionImage nesnesi oluşturmak için Bitmap nesne:

    Kotlin+KTX

    val image = FirebaseVisionImage.fromBitmap(bitmap)

    Java

    FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
    Bitmap nesnesi tarafından temsil edilen resim, dik olmalıdır, ek döndürme gerekmez.

2. Görüntü etiketleyiciyi yapılandırma ve çalıştırma

Bir görüntüdeki nesneleri etiketlemek için FirebaseVisionImage nesnesini FirebaseVisionImageLabeler ürününün processImage yöntemi.

  1. İlk olarak, içe aktarılan FirebaseVisionImageLabeler.

    Kotlin+KTX

    val labeler = FirebaseVision.getInstance().getCloudImageLabeler()
    
    // Or, to set the minimum confidence required:
    // val options = FirebaseVisionCloudImageLabelerOptions.Builder()
    //     .setConfidenceThreshold(0.7f)
    //     .build()
    // val labeler = FirebaseVision.getInstance().getCloudImageLabeler(options)
    

    Java

    FirebaseVisionImageLabeler labeler = FirebaseVision.getInstance()
        .getCloudImageLabeler();
    
    // Or, to set the minimum confidence required:
    // FirebaseVisionCloudImageLabelerOptions options =
    //     new FirebaseVisionCloudImageLabelerOptions.Builder()
    //         .setConfidenceThreshold(0.7f)
    //         .build();
    // FirebaseVisionImageLabeler labeler = FirebaseVision.getInstance()
    //     .getCloudImageLabeler(options);
    

  2. Ardından resmi processImage() yöntemine iletin:

    Kotlin+KTX

    labeler.processImage(image)
        .addOnSuccessListener { labels ->
          // Task completed successfully
          // ...
        }
        .addOnFailureListener { e ->
          // Task failed with an exception
          // ...
        }
    

    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
            // ...
          }
        });
    

3. Etiketli nesneler hakkında bilgi edinme

Görüntü etiketleme işlemi başarılı olursa FirebaseVisionImageLabel nesne yardımcı olmaktır. Her FirebaseVisionImageLabel nesnesi bir şeyi temsil eder bir kod bulun. Her etiket için etiketin metnini alabilirsiniz açıklama, Bilgi Grafiği varlık kimliği (varsa) ve eşleşmenin güven puanı. Örneğin:

Kotlin+KTX

for (label in labels) {
  val text = label.text
  val entityId = label.entityId
  val confidence = label.confidence
}

Java

for (FirebaseVisionImageLabel label: labels) {
  String text = label.getText();
  String entityId = label.getEntityId();
  float confidence = label.getConfidence();
}

Sonraki adımlar