CameraX 分析器不会在每一帧上运行

vrg*_*grg 2 android firebase-mlkit android-camerax

我尝试使用 Android 开发人员文档使用 CameraX 实现 MLKit 文本分析器。我的期望是分析器将在每一帧上运行,但它只运行一次,当预览初始化时。文本由 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))
}
Run Code Online (Sandbox Code Playgroud)

分析器实现:

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.")
}
}
Run Code Online (Sandbox Code Playgroud)

vrg*_*grg 9

我已经想出了答案。我只需要更仔细地阅读文档,它说必须关闭图像代理才能不阻塞线程和预览:-)

  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()
                }
        }
    }
Run Code Online (Sandbox Code Playgroud)