Android'de özel bir sınıflandırma modeliyle nesneleri algılama, izleme ve sınıflandırma

Art arda gelen video karelerindeki nesneleri algılamak ve takip etmek için ML Kit'i kullanabilirsiniz.

Bir resmi ML Kit'e ilettiğinizde, resimdeki beşe kadar nesneyi algılar konumla birlikte resimdeki her bir nesnenin konumunu da içerir. Şu yolda nesneleri algılarken: her nesnenin, nesneyi izlemek için kullanabileceğiniz benzersiz bir kimliği vardır her kareden kareye geçelim.

Gösterilen nesneleri sınıflandırmak için özel bir görüntü sınıflandırma modeli algılandı. Ayrıntılı bilgi için Makine Öğrenimi Kiti ile özel modeller başlıklı makaleyi inceleyin. model uyumluluk gereksinimleri hakkında rehberlik, önceden eğitilmiş modellerin nerede ve kendi modellerinizi nasıl eğiteceğinizi öğreneceksiniz.

Özel bir modeli entegre etmenin iki yolu vardır. Modeli şu şekilde gruplandırabilirsiniz: bunu uygulamanızın öğe klasörüne yerleştirebilir veya kendiniz dinamik olarak indirebilirsiniz. Firebase'den geliyor. Aşağıdaki tabloda iki seçenek karşılaştırılmıştır.

Gruplandırılmış Model Barındırılan Model
Model, uygulamanızın APK'sının bir parçasıdır ve bu modelin boyutunu artırır. Model, APK'nızın parçası değil. Şu konuma yükleyerek barındırılır: Firebase Makine Öğrenimi.
Model, Android cihaz çevrimdışı olsa bile hemen kullanılabilir Model istek üzerine indirilir
Firebase projesine gerek yoktur Firebase projesi gerekir
Modeli güncellemek için uygulamanızı yeniden yayınlamanız gerekiyor Uygulamanızı yeniden yayınlamadan model güncellemelerini aktarma
Yerleşik A/B testi yok Firebase Remote Config ile kolay A/B testi

Deneyin

Başlamadan önce

  1. Proje düzeyindeki build.gradle dosyanıza Google'ın Maven deposu hem buildscript hem de allprojects bölüm.

  2. ML Kit Android kitaplıklarının bağımlılıklarını modülünüze uygulama düzeyinde gradle dosyası vardır. Bu genellikle app/build.gradle olan:

    Bir modeli uygulamanızla paketlemek için:

    dependencies {
      // ...
      // Object detection & tracking feature with custom bundled model
      implementation 'com.google.mlkit:object-detection-custom:17.0.2'
    }
    

    Firebase'den dinamik olarak model indirmek için linkFirebase bağımlılık:

    dependencies {
      // ...
      // Object detection & tracking feature with model downloaded
      // from firebase
      implementation 'com.google.mlkit:object-detection-custom:17.0.2'
      implementation 'com.google.mlkit:linkfirebase:17.0.0'
    }
    
  3. Bir model indirmek istiyorsanız şunu yaptığınızdan emin olun: Firebase'i Android projenize ekleyin, (ücretsizdir) . Modeli paket haline getirirken bu işlem gerekli değildir.

1. Modeli yükleme

Yerel model kaynağını yapılandırma

Modeli uygulamanızla paket haline getirmek için:

  1. Model dosyasını (genellikle .tflite veya .lite ile biter) uygulamanızın assets/ klasör. (İlk olarak klasörü app/ klasörünü sağ tıklayıp Yeni > Klasör > Öğeler Klasörü'nü tıklayın.)

  2. Ardından, uygulamanızın build.gradle dosyasına şunu ekleyin: Gradle, uygulamayı oluştururken model dosyasını sıkıştırmaz:

    android {
        // ...
        aaptOptions {
            noCompress "tflite"
            // or noCompress "lite"
        }
    }
    

    Model dosyası uygulama paketine dahil edilir ve ML Kit tarafından kullanılabilir işlenmemiş bir öğe olarak görebiliriz.

  3. Model dosyasının yolunu belirterek LocalModel nesnesi oluşturun:

    Kotlin

    val localModel = LocalModel.Builder()
            .setAssetFilePath("model.tflite")
            // or .setAbsoluteFilePath(absolute file path to model file)
            // or .setUri(URI to model file)
            .build()

    Java

    LocalModel localModel =
        new LocalModel.Builder()
            .setAssetFilePath("model.tflite")
            // or .setAbsoluteFilePath(absolute file path to model file)
            // or .setUri(URI to model file)
            .build();

Firebase tarafından barındırılan bir model kaynağını yapılandırma

Uzaktan barındırılan modeli kullanmak için şu şekilde bir CustomRemoteModel nesnesi oluşturun: FirebaseModelSource, dosyayı açarken modeli atadığınızda yayınladı:

Kotlin

// Specify the name you assigned in the Firebase console.
val remoteModel =
    CustomRemoteModel
        .Builder(FirebaseModelSource.Builder("your_model_name").build())
        .build()

Java

// Specify the name you assigned in the Firebase console.
CustomRemoteModel remoteModel =
    new CustomRemoteModel
        .Builder(new FirebaseModelSource.Builder("your_model_name").build())
        .build();

Ardından, model indirme görevini başlatmak için model indirme görevinizi 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:

Kotlin

val downloadConditions = DownloadConditions.Builder()
    .requireWifi()
    .build()
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
    .addOnSuccessListener {
        // Success.
    }

Java

DownloadConditions downloadConditions = new DownloadConditions.Builder()
        .requireWifi()
        .build();
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
        .addOnSuccessListener(new OnSuccessListener() {
            @Override
            public void onSuccess(@NonNull Task task) {
                // Success.
            }
        });

Birçok uygulama, indirme görevini başlatma kodunda başlatır, ancak bunu, modeli kullanmaya başlamadan önce istediğiniz zaman yapabilirsiniz.

2. Nesne algılayıcıyı yapılandırma

Model kaynaklarınızı yapılandırdıktan sonra bir CustomObjectDetectorOptions nesnesidir. Bu ayarı değiştirmek için şu ayarları kullanın:

Nesne Algılayıcı Ayarları
Algılama modu STREAM_MODE (varsayılan) | SINGLE_IMAGE_MODE

STREAM_MODE ürününde (varsayılan) nesne algılayıcısı çalışır düşük gecikme süresi vardır, ancak eksik sonuçlar oluşturabilir (ör. (belirtilmemiş sınırlayıcı kutular veya kategori etiketleri) yer alır. çağrılarına karşılık gelir. Ayrıca STREAM_MODE içinde, algılayıcı, nesnelere izleme kimlikleri atar. Bu kimlikleri çerçevelerde nesneleri izler. YouTube TV'yi izlemek istediğinizde veya veri işleme sırasında olduğu gibi düşük gecikmenin gerçek zamanlı video akışı sağlar.

SINGLE_IMAGE_MODE işlevinde, nesne algılayıcısı nesnenin sınırlayıcı kutusu belirlendikten sonra sonuç elde edilir. Şu durumda: sınıflandırmayı da etkinleştirdiğinde sınırlayıcıdan sonra sonucu döndürür kutu ve kategori etiketi kullanılabilir. Sonuç olarak algılama gecikmesi potansiyel olarak daha yüksektir. Ayrıca, SINGLE_IMAGE_MODE, izleme kimlikleri atanmadı. Tekliflerinizi otomatikleştirmek ve optimize etmek için bu modu kullanırsanız ve gecikmeyle uğraşmak istemezseniz kısmi sonuçlar sağlar.

Birden çok nesneyi algılama ve izleme false (varsayılan) | true

Beş adede kadar veya yalnızca en fazla nesne algılayıp takip etme belirgin nesne (varsayılan).

Nesneleri sınıflandırma false (varsayılan) | true

Sağlanan veriler kullanılarak algılanan nesnelerin sınıflandırılması özel sınıflandırıcı modeli. Özel sınıflandırmanızı kullanmak için: modeli için bunu true olarak ayarlamanız gerekir.

Sınıflandırma güven eşiği

Algılanan etiketlerin minimum güven puanı. Ayarlanmazsa modelin meta verileri tarafından belirtilen sınıflandırıcı eşiği kullanılır. Model herhangi bir meta veri içermiyorsa veya meta veriler sınıflandırıcı eşiği ile başladığından, 0,0 varsayılan eşiği kullanılır.

Nesne başına maksimum etiket

Algılayıcının nesne başına maksimum etiket sayısı dön. Politika ayarlanmazsa varsayılan değer olan 10 kullanılır.

Nesne algılama ve izleme API'si, bu iki temel kullanım için optimize edilmiştir vakalar:

  • Kameradaki en belirgin nesnenin canlı algılanması ve takip edilmesi vizör.
  • Statik görüntüden birden fazla nesnenin algılanması.

API'yi bu kullanım alanları için yapılandırmak üzere yerel olarak paketlenmiş bir model kullanarak:

Kotlin

// Live detection and tracking
val customObjectDetectorOptions =
        CustomObjectDetectorOptions.Builder(localModel)
        .setDetectorMode(CustomObjectDetectorOptions.STREAM_MODE)
        .enableClassification()
        .setClassificationConfidenceThreshold(0.5f)
        .setMaxPerObjectLabelCount(3)
        .build()

// Multiple object detection in static images
val customObjectDetectorOptions =
        CustomObjectDetectorOptions.Builder(localModel)
        .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
        .enableMultipleObjects()
        .enableClassification()
        .setClassificationConfidenceThreshold(0.5f)
        .setMaxPerObjectLabelCount(3)
        .build()

val objectDetector =
        ObjectDetection.getClient(customObjectDetectorOptions)

Java

// Live detection and tracking
CustomObjectDetectorOptions customObjectDetectorOptions =
        new CustomObjectDetectorOptions.Builder(localModel)
                .setDetectorMode(CustomObjectDetectorOptions.STREAM_MODE)
                .enableClassification()
                .setClassificationConfidenceThreshold(0.5f)
                .setMaxPerObjectLabelCount(3)
                .build();

// Multiple object detection in static images
CustomObjectDetectorOptions customObjectDetectorOptions =
        new CustomObjectDetectorOptions.Builder(localModel)
                .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
                .enableMultipleObjects()
                .enableClassification()
                .setClassificationConfidenceThreshold(0.5f)
                .setMaxPerObjectLabelCount(3)
                .build();

ObjectDetector objectDetector =
    ObjectDetection.getClient(customObjectDetectorOptions);

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.

Algılayıcıyı çalıştırmadan önce bunu onaylamanız gerekse de hem uzaktan barındırılan hem de yerel olarak paketlenen resim dedektörünü örneklendirirken şu kontrolü gerçekleştirmek mantıklıdır: dedektörden, indirilmişse uzak modelden, yerel modelden ise modelini kullanmanız gerekir.

Kotlin

RemoteModelManager.getInstance().isModelDownloaded(remoteModel)
    .addOnSuccessListener { isDownloaded ->
    val optionsBuilder =
        if (isDownloaded) {
            CustomObjectDetectorOptions.Builder(remoteModel)
        } else {
            CustomObjectDetectorOptions.Builder(localModel)
        }
    val customObjectDetectorOptions = optionsBuilder
            .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
            .enableClassification()
            .setClassificationConfidenceThreshold(0.5f)
            .setMaxPerObjectLabelCount(3)
            .build()
    val objectDetector =
        ObjectDetection.getClient(customObjectDetectorOptions)
}

Java

RemoteModelManager.getInstance().isModelDownloaded(remoteModel)
    .addOnSuccessListener(new OnSuccessListener() {
        @Override
        public void onSuccess(Boolean isDownloaded) {
            CustomObjectDetectorOptions.Builder optionsBuilder;
            if (isDownloaded) {
                optionsBuilder = new CustomObjectDetectorOptions.Builder(remoteModel);
            } else {
                optionsBuilder = new CustomObjectDetectorOptions.Builder(localModel);
            }
            CustomObjectDetectorOptions customObjectDetectorOptions = optionsBuilder
                .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
                .enableClassification()
                .setClassificationConfidenceThreshold(0.5f)
                .setMaxPerObjectLabelCount(3)
                .build();
            ObjectDetector objectDetector =
                ObjectDetection.getClient(customObjectDetectorOptions);
        }
});

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:

Kotlin

RemoteModelManager.getInstance().download(remoteModel, conditions)
    .addOnSuccessListener {
        // Download complete. Depending on your app, you could enable the ML
        // feature, or switch from the local model to the remote model, etc.
    }

Java

RemoteModelManager.getInstance().download(remoteModel, conditions)
        .addOnSuccessListener(new OnSuccessListener() {
            @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.
            }
        });

3. Giriş resmini hazırlama

Resminizden bir InputImage nesnesi oluşturun. Nesne algılayıcı, doğrudan bir Bitmap, NV21 ByteBuffer veya YUV_420_888 media.Image. Bu kaynaklardan bir InputImage oluşturmak bu uygulamalardan birine doğrudan erişiminiz varsa önerilir. Bir Diğer kaynaklardan InputImage, dönüşümü dahili olarak ele alacağız. ve daha az verim olabilir.

InputImage oluşturabilirsiniz her biri aşağıda açıklanmıştır.

media.Image kullanarak

InputImage oluşturmak için media.Image nesnesinden bir nesneden (örneğin, cihazın kamerasını, media.Image nesnesini ve resmin döndürme değeri InputImage.fromMediaImage() değerine ayarlanır.

URL'yi CameraX kitaplığı, OnImageCapturedListener ve ImageAnalysis.Analyzer sınıfları rotasyon değerini hesaplar sizin için.

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önme derecesini sağlayan bir kamera kitaplığı kullanmıyorsanız cihazın dönüş derecesinden ve kameranın yönünden hesaplayabilir cihazdaki sensör:

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() değerine ayarlayın:

Kotlin

val image = InputImage.fromMediaImage(mediaImage, rotation)

Java

InputImage image = InputImage.fromMediaImage(mediaImage, rotation);

Dosya URI'si kullanarak

InputImage oluşturmak için uygulama bağlamını ve dosya URI'sini InputImage.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

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

InputImage oluşturmak için bir ByteBuffer veya ByteArray nesnesinden alıp almayacaksanız önce resmi hesaplayın media.Image girişi için daha önce açıklandığı gibi dönme derecesi. Ardından, arabellek veya diziyle InputImage nesnesini, bu resmin yükseklik, genişlik, renk kodlama biçimi ve döndürme derecesi:

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

InputImage oluşturmak için Bitmap nesnesindeki şu 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.

4. Nesne algılayıcıyı çalıştırma

Kotlin

objectDetector
    .process(image)
    .addOnFailureListener(e -> {...})
    .addOnSuccessListener(results -> {
        for (detectedObject in results) {
          // ...
        }
    });

Java

objectDetector
    .process(image)
    .addOnFailureListener(e -> {...})
    .addOnSuccessListener(results -> {
        for (DetectedObject detectedObject : results) {
          // ...
        }
    });

5. Etiketli nesneler hakkında bilgi edinme

process() çağrısı başarılı olursa DetectedObject içeren bir liste yardımcı olur.

Her DetectedObject aşağıdaki özellikleri içerir:

Sınırlayıcı kutu NesneninRect görüntüsüdür.
İzleme Kimliği Nesneyi resimler arasında tanımlayan bir tam sayı. Boş değer: TEK_IMAGE_MODE.
Etiketler
Etiket açıklaması Etiketin metin açıklaması. Yalnızca TensorFlow Lite modelinin meta verileri etiket açıklamaları içeriyor.
Etiket dizini Desteklenen tüm etiketler arasından etiketin dizini sınıflandırıcıyı kullanın.
Etiket güveni Nesne sınıflandırmasının güven değeri.

Kotlin

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (detectedObject in results) {
    val boundingBox = detectedObject.boundingBox
    val trackingId = detectedObject.trackingId
    for (label in detectedObject.labels) {
      val text = label.text
      val index = label.index
      val confidence = label.confidence
    }
}

Java

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (DetectedObject detectedObject : results) {
  Rect boundingBox = detectedObject.getBoundingBox();
  Integer trackingId = detectedObject.getTrackingId();
  for (Label label : detectedObject.getLabels()) {
    String text = label.getText();
    int index = label.getIndex();
    float confidence = label.getConfidence();
  }
}

Mükemmel bir kullanıcı deneyimi sağlama

En iyi kullanıcı deneyimi için uygulamanızda aşağıdaki yönergelere uyun:

  • Nesne algılama işleminin başarılı olması, nesnenin görsel karmaşıklığına bağlıdır. İçinde az sayıda görsel özelliği olan nesnelerin algılanması için kaplamaya başlar. Kullanıcılara şu konularda yol göstermeniz gerekir: algılamak istediğiniz tür nesnelerde iyi çalışan bir giriş yakalamanızı sağlar.
  • Sınıflandırma kullanırken, düşmeyen nesneleri tespit etmek isterseniz desteklenen kategorilere ayırarak, bilinmeyen kullanıcılar için nesneler'i tıklayın.

Ayrıca, ML Kit Material Design vitrin uygulaması ve Materyal Tasarım Makine öğrenimi destekli özellikler koleksiyonu için kalıplar.

Performansı artırma

Nesne algılamayı gerçek zamanlı bir uygulamada kullanmak isterseniz aşağıdaki talimatları uygulayın:

  • Akış modunu gerçek zamanlı bir uygulamada kullanırken birden fazla nesne algılama özelliği vardır. Bunun nedeni, çoğu cihaz yeterli kare hızı üretememesidir.

  • URL'yi Camera veya camera2 API, algılayıcıya yapılan çağrıları kısıtlamaz. Yeni bir video çerçeve, algılayıcı çalışırken kullanılabilir hale gelirse çerçeveyi bırakın. Bkz. Örnek için hızlı başlangıç örnek uygulamasındaki VisionProcessorBase sınıfı.
  • CameraX API'yi kullanıyorsanız karşı baskı stratejisinin varsayılan değerine ayarlandığından emin olun ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) Bu, aynı anda yalnızca bir resmin analiz için gönderilmesini garanti eder. Daha fazla resim üretilirse analiz aracı meşgulken üretilirse otomatik olarak bırakılır ve teslimat. Analiz edilen resim, çağırarak kapatıldıktan sonra ImageProxy.close(), bir sonraki en son resim gönderilir.
  • Algılayıcının çıkışını, üzerine grafik yerleştirmek için 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, görüntü yüzeyine oluşturulur her giriş karesi için yalnızca bir kez. Bkz. CameraSourcePreview ve Hızlı başlangıç örnek uygulamasındaki GraphicOverlay sınıflarına göz atın.
  • 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.