Анализатор CameraX работает не на каждом кадре - PullRequest
0 голосов
/ 26 апреля 2020

Я пытался внедрить анализатор текста MLKit с использованием CameraX, используя Android developer Документация . Я ожидал, что анализатор будет работать на каждом кадре, но он запускается только один раз, когда предварительный просмотр инициализирован. Текст анализируется с помощью MLKit, но анализ выполняется только в том случае, если я поверну экран и перезапущу фрагмент. Почему это происходит?

В XML Я использую <androidx.camera.view.PreviewView .../>.

Во фрагменте:

private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>

private fun startCamera() {
    context?.let { ctx ->
        cameraProviderFuture = ProcessCameraProvider.getInstance(ctx)
        cameraProviderFuture.addListener(Runnable {
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(cameraProvider)
        }, ContextCompat.getMainExecutor(ctx))
    }
}

private fun bindPreview(cameraProvider: ProcessCameraProvider) {
    val preview: Preview = Preview.Builder()
        .build()

    val cameraSelector: CameraSelector = CameraSelector.Builder()
        .requireLensFacing(CameraSelector.LENS_FACING_BACK)
        .build()

    val analyzer = ImageAnalysis.Builder()
        .setTargetResolution(Size(1280, 720))
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
        .build().apply {
            setAnalyzer(Executors.newSingleThreadExecutor(), TextAnalyzer())
        }

    val camera = cameraProvider.bindToLifecycle(viewLifecycleOwner, cameraSelector, analyzer, preview)

    preview.setSurfaceProvider(preview_view.createSurfaceProvider(camera.cameraInfo))
}

Реализация анализатора:

class TextAnalyzer : ImageAnalysis.Analyzer {

val detector = FirebaseVision.getInstance().onDeviceTextRecognizer

@SuppressLint("UnsafeExperimentalUsageError")
override fun analyze(imageProxy: ImageProxy) {
    val mediaImage = imageProxy.image
    val rotation = degreesToFirebaseRotation(imageProxy.imageInfo.rotationDegrees)
    mediaImage?.let { image ->
        val firebaseImage = FirebaseVisionImage.fromMediaImage(image, rotation)
        detector.processImage(firebaseImage)
            .addOnSuccessListener { firebaseVisionText ->
                val text = firebaseVisionText.text
                val textBlock = firebaseVisionText.textBlocks
                Log.i("TEXT_ANALYZER", "success text $text")
                textBlock.forEach {
                    Log.i("TEXT_ANALYZER", "success text BLOCK $it")
                }
            }
            .addOnFailureListener { e ->
                Log.i("TEXT_ANALYZER", "failed ex $e")
            }
    }
}

private fun degreesToFirebaseRotation(degrees: Int): Int = when (degrees) {
    0 -> ROTATION_0
    90 -> ROTATION_90
    180 -> ROTATION_180
    270 -> ROTATION_270
    else -> throw Exception("Rotation must be 0, 90, 180, or 270.")
}
}

1 Ответ

2 голосов
/ 27 апреля 2020

Я понял ответ. Я просто должен был прочитать документы более внимательно, он говорит, что прокси-изображение должно быть закрыто, чтобы не блокировать поток и предварительный просмотр :-)

  override fun analyze(imageProxy: ImageProxy) {
        val mediaImage = imageProxy.image
        val rotation = degreesToFirebaseRotation(imageProxy.imageInfo.rotationDegrees)
        mediaImage?.let { image ->
            val firebaseImage = FirebaseVisionImage.fromMediaImage(image, rotation)
            detector.processImage(firebaseImage)
                .addOnSuccessListener { firebaseVisionText ->
                    val text = firebaseVisionText.text
                    val textBlock = firebaseVisionText.textBlocks
                    // IMPORTANT
                    imageProxy.close()
                }
                .addOnFailureListener { e ->
                    // IMPORTANT
                    imageProxy.close()
                }
        }
    }
...