【问题标题】:How analize preview rectangle camerax android?如何分析预览矩形camerax android?
【发布时间】:2021-09-28 13:13:42
【问题描述】:

我是一名初学者。我很抱歉我的英语。 我正在尝试制作条形码阅读器应用程序。我使用 MLKit 和 CameraX。 我只想分析矩形中的预览部分。现在正在对预览进行全面分析。我只想分析矩形中的内容。我尝试使用 ViewPort,但似乎我不太了解它的用途,因为它无法解决问题。我在互联网上寻找解决方案,但我的问题仍然相关。我认为在分析之前有必要裁剪图像然后再分析它,但这是真的吗? 我的布局:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="false"
        tools:background="@android:color/white"
        tools:context=".ui.BarcodeScanningFragment">
    
        <androidx.camera.view.PreviewView
            android:id="@+id/viewFinder"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <com.t_ovchinnikova.android.scandroid_2.ui.ViewFinderOverlay
            android:id="@+id/overlay"
            android:layerType="software"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </FrameLayout>

相机类:

    class CameraSource (private val overlay: ViewFinderOverlay) {

    private lateinit var cameraExecutor: ExecutorService

    val preview : Preview = Preview.Builder()
        .build()

    fun startCamera() {

        val cameraProviderFuture = ProcessCameraProvider.getInstance(overlay.context)

        cameraProviderFuture.addListener(Runnable {
            //Используется для привязки жизненного цикла камер к владельцу жизненного цикла
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
            bindCameraUseCases(cameraProvider)
        }, ContextCompat.getMainExecutor(overlay.context))
    }

    @SuppressLint("UnsafeOptInUsageError")
    private fun bindCameraUseCases(cameraProvider: ProcessCameraProvider) {

        val imageAnalysis = ImageAnalysis.Builder()
            .setTargetResolution(Size(overlay.width, overlay.height))
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .build()

        val orientationEventListener = object : OrientationEventListener(overlay.context) {
            override fun onOrientationChanged(orientation : Int) {
                // Monitors orientation values to determine the target rotation value
                val rotation : Int = when (orientation) {
                    in 45..134 -> Surface.ROTATION_270
                    in 135..224 -> Surface.ROTATION_180
                    in 225..314 -> Surface.ROTATION_90
                    else -> Surface.ROTATION_0
                }

                imageAnalysis.targetRotation = rotation
            }
        }
        orientationEventListener.enable()

        cameraExecutor = Executors.newSingleThreadExecutor()

        val analyzer = BarcodeAnalyzer()

        imageAnalysis.setAnalyzer(cameraExecutor, analyzer)

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

        val useCaseGroup = UseCaseGroup.Builder()
            .addUseCase(preview)
            .addUseCase(imageAnalysis)
            .build()

        cameraProvider.bindToLifecycle(overlay.context as LifecycleOwner, cameraSelector, useCaseGroup)
    }
}

类 ViewFinderOverlay:

    class ViewFinderOverlay(context: Context, attrs: AttributeSet) : View(context, attrs) {

    private val boxPaint: Paint = Paint().apply {
        color = ContextCompat.getColor(context, R.color.barcode_reticle_stroke)
        style = Paint.Style.STROKE
        strokeWidth = context.resources.getDimensionPixelOffset(R.dimen.barcode_stroke_width).toFloat()
    }

    private val scrimPaint: Paint = Paint().apply {
        color = ContextCompat.getColor(context, R.color.barcode_reticle_background)
    }

    private val eraserPaint: Paint = Paint().apply {
        strokeWidth = boxPaint.strokeWidth
        xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
    }

    private val boxCornerRadius: Float =
        context.resources.getDimensionPixelOffset(R.dimen.barcode_reticle_corner_radius).toFloat()

    var boxRect: RectF? = null

    fun setViewFinder() {

        val overlayWidth =  width.toFloat()
        val overlayHeight = height.toFloat()

        val boxWidth = overlayWidth * 80 /100
        val boxHeight = overlayHeight * 36 / 100

        val cx = overlayWidth / 2
        val cy = overlayHeight / 2

        boxRect = RectF(cx - boxWidth / 2, cy - boxHeight / 2, cx + boxWidth / 2, cy + boxHeight / 2)

        invalidate()
    }

    override fun draw(canvas: Canvas) {
        super.draw(canvas)
        boxRect?.let {

            canvas.drawRect(0f, 0f, canvas.width.toFloat(), canvas.height.toFloat(), scrimPaint)

            eraserPaint.style = Paint.Style.FILL
            canvas.drawRoundRect(it, boxCornerRadius, boxCornerRadius, eraserPaint)
            eraserPaint.style = Paint.Style.STROKE
            canvas.drawRoundRect(it, boxCornerRadius, boxCornerRadius, eraserPaint)
            // Draws the box.
            canvas.drawRoundRect(it, boxCornerRadius, boxCornerRadius, boxPaint)
        }
    }
}

ViewFinderOverlay - 叠加在相机预览上的视图。 屏幕: [1]:https://i.stack.imgur.com/cYvFP.jpg

图像分析器:

        @SuppressLint("UnsafeOptInUsageError")
    override fun analyze(imageProxy: ImageProxy) {

        val mediaImage = imageProxy.image
        if (mediaImage != null) {
            val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)

            val scanner = BarcodeScanning.getClient()

            scanner.process(image)
                .addOnSuccessListener { barcodes ->
                    barcodes?.firstOrNull().let { barcode ->
                        val rawValue = barcode?.rawValue
                        rawValue?.let {
                        }
                    }
                }
            imageProxy.close()
        }
    }

请帮帮我。我很乐意接受任何建议。

【问题讨论】:

    标签: android-camerax google-mlkit


    【解决方案1】:

    你可以看看LifecycleCameraController。它负责创建用例以及配置 ViewPort。

    但是 AFAIK,MLKit 不尊重裁剪矩形。您可以做的是检查 MLKit 结果,并丢弃任何坐标在裁剪矩形之外的条形码。

    【讨论】:

      猜你喜欢
      • 2020-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-26
      • 2021-10-16
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多