首页 > 解决方案 > 为什么在我的应用程序使用 ML-Kit 扫描它看到的第一个文本后,相机会关闭并且屏幕变黑?

问题描述

我正在使用 CameraX 和 ML-Kit 的 Android 文本识别 API 来制作文本识别应用程序。相机工作正常,直到我指向一个单词并识别它。然后屏幕变黑,我看到那里写着这个词(这就是我的想法,但我希望这个词在相机预览仍然打开时出现)。我原本以为这个词可能有一些背景颜色导致了这种情况,所以我将背景颜色设置为透明,但这并没有改变任何东西。我试过搜索 Stack Overflow,但在这里没有找到任何东西。MLKit 和 Camera X 文档也没有提及这一点。

这是我的 activity_main.xml 文件,这可能是原因。

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">


<androidx.camera.view.PreviewView
    android:id="@+id/cameraPreviewView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintTop_toTopOf="parent">
</androidx.camera.view.PreviewView>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fontFamily="sans-serif-black"
    android:textColor="@color/white"
    android:textSize="20sp"
    android:textStyle="bold"
    app:layout_constraintBottom_toTopOf="@+id/cameraPreviewView"
    app:layout_constraintTop_toTopOf="parent"
    android:id="@+id/Result"
    android:gravity="bottom"/>

这是我唯一的 Kotlin 文件。


import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.media.Image
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import android.widget.Toast
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.myapplication3.databinding.ActivityMainBinding
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.TextRecognition
import java.io.IOException
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        if (allPermissionsGranted()) {
            startCamera()
        } else {
            requestPermissions()
        }
    }

    private val cameraExecutor: ExecutorService by lazy { Executors.newSingleThreadExecutor() }

    override fun onDestroy() {
        super.onDestroy()
        cameraExecutor.shutdown()
    }
    private companion object {
        val TAG: String = MainActivity::class.java.simpleName
        const val REQUEST_CODE_PERMISSIONS = 10
        val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
    }
    private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
    }

    private fun requestPermissions() {
        ActivityCompat.requestPermissions(
            this,
            REQUIRED_PERMISSIONS,
            REQUEST_CODE_PERMISSIONS
        )
    }
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                startCamera()
            } else {
                Toast.makeText(
                    this,
                    "Permissions not granted.",
                    Toast.LENGTH_SHORT
                ).show()
                finish()
            }
        }
    }
    class TextReaderAnalyzer(
        private val textFoundListener: (String) -> Unit
    ) : ImageAnalysis.Analyzer {


        @SuppressLint("UnsafeOptInUsageError")
        override fun analyze(imageProxy: ImageProxy) {
            imageProxy.image?.let {process(it, imageProxy) }
        }
        private fun process(image: Image, imageProxy: ImageProxy) {
            try {
                readTextFromImage(InputImage.fromMediaImage(image, 90), imageProxy)
            } catch (e: IOException) {
                Log.d(TAG, "Failed to load the image")
                e.printStackTrace()
            }
        }

        @SuppressLint("UnsafeOptInUsageError")
        private fun readTextFromImage(image: InputImage, imageProxy: ImageProxy) {
            TextRecognition.getClient()
                .process(image)
                .addOnSuccessListener { visionText ->
                    processTextFromImage(visionText)
                }
                .addOnFailureListener { error ->
                    Log.d(TAG, "Failed to process the image")
                    error.printStackTrace()
                    imageProxy.close()
                }
        }
        private fun processTextFromImage(visionText: Text) {
            for (block in visionText.textBlocks) {
                // You can access whole block of text using block.text
                for (line in block.lines) {
                    // You can access whole line of text using line.text
                    for (element in line.elements) {
                        textFoundListener(element.text)
                    }
                }
            }
        }
    }
    private val imageAnalyzer by lazy {
        ImageAnalysis.Builder()
            .setTargetAspectRatio(AspectRatio.RATIO_16_9)
            .build()
            .also {
                it.setAnalyzer(
                    cameraExecutor,
                    TextReaderAnalyzer(::onTextFound)
                )
            }
    }

    private fun onTextFound(foundText: String)  {
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val textView: TextView = binding.Result
        textView.text = foundText
    }

    private fun startCamera() {
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener(
            {
                val preview = Preview.Builder()
                    .build()
                    .also { it.setSurfaceProvider(binding.cameraPreviewView.surfaceProvider) }
                cameraProviderFuture.get().bind(preview, imageAnalyzer)
            },
            ContextCompat.getMainExecutor(this)
        )
    }

    private fun ProcessCameraProvider.bind(
        preview: Preview,
        imageAnalyzer: ImageAnalysis
    ) = try {
        unbindAll()
        bindToLifecycle(
            this@MainActivity,
            CameraSelector.DEFAULT_BACK_CAMERA,
            preview,
            imageAnalyzer
        )
    } catch (ise: IllegalStateException) {
        // Thrown if binding is not done from the main thread
        Log.e(TAG, "Binding failed", ise)
    }
}

标签: androidandroid-cameraxgoogle-mlkit

解决方案


你应该.addOnSuccessListener稍微改变你的块。

TextRecognition.getClient()
                    .process(image)
                    .addOnSuccessListener { visionText ->
                        processTextFromImage(visionText)
                        //Add below line here
                        imageProxy.close() 
                    }
                    .addOnFailureListener { error ->
                        Log.d(TAG, "Failed to process the image")
                        error.printStackTrace()
                        imageProxy.close()
                    }

推荐阅读