【问题标题】:How can I connect ImageAnalyzer class to class where qr code should be recognized?如何将 ImageAnalyzer 类连接到应识别 qr 代码的类?
【发布时间】:2020-09-28 14:12:07
【问题描述】:

我有两个类:QrActivity(打开相机以扫描二维码)和 BarcodeAnalyzer(图像分析过程正在进行)。我正在使用 cameraX 和 ML Kit。

这是我的 QrActivity:

package ge.softservice.nfcwithactivties

import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_qr.*
import java.io.File
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors


class QrActivity : AppCompatActivity() {
    private var preview: Preview? = null
    private var imageAnalyzer: ImageAnalysis? = null
    private var camera: Camera? = null

    private lateinit var outputDirectory: File
    private lateinit var cameraExecutor: ExecutorService

    override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<String>, grantResults:
        IntArray
    ) {
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                startCamera()
            } else {
                Toast.makeText(
                    this,
                    "Permissions not granted by the user.",
                    Toast.LENGTH_SHORT
                ).show()
                finish()
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_qr)

        // Request camera permissions
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(
                this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS
            )
        }

        //      outputDirectory = getOutputDirectory()

        cameraExecutor = Executors.newSingleThreadExecutor()
    }

    private fun startCamera() {

        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener(Runnable {
            // Used to bind the lifecycle of cameras to the lifecycle owner
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()


            // Preview
            preview = Preview.Builder()
                .build()

            // Select back camera
            val cameraSelector =
                CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()

            try {
                // Unbind use cases before rebinding
                cameraProvider.unbindAll()

                // Bind use cases to camera
                camera = cameraProvider.bindToLifecycle(
                    this, cameraSelector, preview
                )
                preview?.setSurfaceProvider(viewFinder.createSurfaceProvider(/*camera?.cameraInfo*/))
            } catch (exc: Exception) {
                Log.e(TAG, "Use case binding failed", exc)
            }

        }, ContextCompat.getMainExecutor(this))
    }

    private fun takePhoto() {
        // TODO
    }

    private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(
            baseContext, it
        ) == PackageManager.PERMISSION_GRANTED
    }

/*    fun getOutputDirectory(): File {
        val mediaDir = externalMediaDirs.firstOrNull()?.let {
            File(it, resources.getString(R.string.app_name)).apply { mkdirs() } }
        return if (mediaDir != null && mediaDir.exists())
            mediaDir else filesDir
    }*/

    companion object {
        private const val TAG = "CameraXBasic"
        private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
        private const val REQUEST_CODE_PERMISSIONS = 10
        private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
    }
}

那是我的条码分析器:

package ge.softservice.nfcwithactivties

import android.annotation.SuppressLint
import android.content.Context
import android.widget.Toast
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.firebase.ml.vision.FirebaseVision
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetectorOptions
import com.google.firebase.ml.vision.common.FirebaseVisionImage
import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata

class BarcodeAnalyzer : ImageAnalysis.Analyzer {

   lateinit var context: Context;


    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.")
    }


    @SuppressLint("UnsafeExperimentalUsageError")
    override fun analyze(imageProxy: ImageProxy) {
 //     val degrees by Delegates.notNull<Int>()
        val mediaImage = imageProxy.image
        val imageRotation = degreesToFirebaseRotation(imageProxy.imageInfo.rotationDegrees)
        if (mediaImage != null) {
            val image = FirebaseVisionImage.fromMediaImage(mediaImage, imageRotation)
            // Pass image to an ML Kit Vision API
            val options = FirebaseVisionBarcodeDetectorOptions.Builder()
                .setBarcodeFormats(
                    FirebaseVisionBarcode.FORMAT_QR_CODE
                )
                .build()
            val detector = FirebaseVision.getInstance().getVisionBarcodeDetector(options)

            val result = detector.detectInImage(image)
                .addOnSuccessListener { barcodes ->
                    // Task completed successfully
                    Toast.makeText(context, "it works", Toast.LENGTH_SHORT).show()
                }
                .addOnFailureListener {
                    // Task failed with an exception
                    Toast.makeText(context, "something went wrong", Toast.LENGTH_SHORT).show()
                }
        }
    }
}

我也尝试将此代码而不是 BarcodeAnalyzer 放入 QrActivity 类,但图像值无法识别。

    val options = FirebaseVisionBarcodeDetectorOptions.Builder()
        .setBarcodeFormats(
            FirebaseVisionBarcode.FORMAT_QR_CODE
        )
        .build()
    val detector = FirebaseVision.getInstance().getVisionBarcodeDetector(options)

    val result = detector.detectInImage(image)
        .addOnSuccessListener { barcodes ->
            // Task completed successfully
            Toast.makeText(context, "it works", Toast.LENGTH_SHORT).show()
        }
        .addOnFailureListener {
            // Task failed with an exception
            Toast.makeText(context, "something went wrong", Toast.LENGTH_SHORT).show()
        }

如果我把它放在现在的BarcodeAnalyzer中,没有错误,但结果值是灰色并且没有使用。

我找到了这个项目并尝试做类似的事情,但在我的项目中它显示错误:https://github.com/Lavanyagaur22/Visitor-Card

我也尝试过这个教程和其他教程,但我不清楚很多事情:https://www.bignerdranch.com/blog/using-firebasemlkit-with-camerax/

我尝试在 BarcodeAnalyzer 的 QrActivty 类中执行实例,但显示错误。

我正在关注 google 的 firebase ML Kit 教程,但仍然对我不起作用:https://firebase.google.com/docs/ml-kit/android/read-barcodes#kotlin+ktx_1

那么,如何将 BarcodeAnalyzer 类连接到 QrActivity 类或如何创建一个实例来识别二维码?

【问题讨论】:

    标签: android firebase kotlin firebase-mlkit android-camerax


    【解决方案1】:

    要将图像分析仪连接到相机,您需要添加一个已添加的用例;这里的预览用例:cameraProvider.bindToLifecycle(this, cameraSelector, preview)

    您可以像这样创建分析器的实例:

    val analyzer = ImageAnalysis.Builder()
        .setTargetAspectRatio(AspectRatio.RATIO_16_9)
        .setTargetRotation(previewView.display.rotation)
        .build().also {
             it.setAnalyzer(Executors.newSingleThreadExecutor(), BarcodeAnalyzer())
         }
    

    然后绑定这个用例:

    cameraProvider.bindToLifecycle(this, cameraSelector, preview, analyzer)
    

    【讨论】:

    • 我应该把那个代码放在哪里?我在预览后放入了 startCamera 方法。但在这里: .setTargetRotation(rotation) 旋转是未解决的参考。在这里: cameraProvider.bindToLifecycle(this, cameraSelector, preview, analyzer) cameraSelector 是未解析的参考。分析器是 Unit 而不是 UseCase。不,我应该使用 imageanalyzer 而不是分析器。但是我应该如何处理这些未解决的引用?
    • 检查我更新的答案。 rotation是设备的旋转,你可以把previewView.display.rotation给它。
    • 现在 previewView 是未解决的参考。我将其添加为:lateinit var previewView: PreviewView 但它在空指针异常时崩溃。我试过: var previewView: PreviewView? = null 但它又崩溃了
    • 使用您用于取景器的任何变量,而不是 previewView
    • 我改了,没有错误了。但在 BarcodeAnalyzer 类中,“结果”值仍为灰色且未使用。我怎样才能在 QrActivity 类中访问这个变量或者我应该如何使它工作?
    猜你喜欢
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-13
    • 1970-01-01
    • 2021-11-09
    相关资源
    最近更新 更多