CameraX make ImageAnalysis same size as Preview

SMG*_*ost 5 android android-camerax

I want to be able to get the exact image for analysis step as I get in preview. I have preview use case:

val metrics = DisplayMetrics().also { binding.codeScannerView.display.getRealMetrics(it) }
    val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)
    val previewConfig = PreviewConfig.Builder().apply {
        setTargetAspectRatio(screenAspectRatio)
    }.build()
Run Code Online (Sandbox Code Playgroud)

And next to it I have analysis use case config:

val analyzerConfig = ImageAnalysisConfig.Builder().apply {
        setTargetResolution(Size(metrics.heightPixels, metrics.widthPixels))
        setTargetAspectRatio(screenAspectRatio)
        val analyzerThread = HandlerThread(
                "QrCodeReader").apply { start() }
        setCallbackHandler(Handler(analyzerThread.looper))
        setImageReaderMode(
                ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
    }.build()
Run Code Online (Sandbox Code Playgroud)

My preview is fullscreen so it's size is 1440x2560. But if I try to get dimensions from ImageProxy in analyzer, I get 1920x1050 which seems to have incorrect dimensions and switched width with height. Why is that and how can I force my analysis step to have same dimensions as full screen?

A. *_*rov 5

介绍:

implementation 'androidx.camera:camera-core:1.0.0-alpha10'
implementation 'androidx.camera:camera-camera2:1.0.0-alpha10'
implementation "androidx.camera:camera-lifecycle:1.0.0-alpha10"
implementation "androidx.camera:camera-view:1.0.0-alpha07"
implementation 'com.google.firebase:firebase-ml-vision:24.0.1'
implementation 'com.google.firebase:firebase-ml-vision-barcode-model:16.0.2'
Run Code Online (Sandbox Code Playgroud)

我通过以下方法解决这个问题FirebaseVisionImage.fromBitmap(bitmap) -bitmap根据预览配置手动裁剪和旋转图像。步骤是:

  1. 当您设置ImageAnalysis.Builder()&&Preview.Builder() 获取元素的屏幕渲染大小 时androidx.camera.view.PreviewView

    previewView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
    val previewSize = Size(previewView.width, previewView.height)
    
    Run Code Online (Sandbox Code Playgroud)

    然后将大小传递到您自己的ImageAnalysis.Analyzer 实现中(假设它将是viewFinderSize可变的,用法见下文)

  2. 发生时override fun analyze(mediaImage: ImageProxy){,手动裁剪收到的ImageProxy. 我使用另一个关于扭曲 YUV_420_888 图像的问题的片段:/sf/answers/3214879671/

当您进行裁剪时,请记住,ImageAnalysis用例接收在预览用例中垂直中间对齐的图像。换句话说,接收到的图像在旋转后将垂直居中,就好像它位于预览区域内一样(即使您的预览区域小于传递到分析的图像)。因此,裁剪面积应从垂直中心的两个方向计算:向上和向下。

作物的垂直尺寸(高度)应在水平尺寸的基础上手动计算。这意味着,当您接收图像进行分析时,它在预览区域内具有完整的水平尺寸(预览内宽度的 100% 等于分析内宽度的 100%)。因此,水平维度上没有隐藏区域。这为计算垂直裁剪的尺寸开辟了道路。我用下一个代码完成了这个:

var bitmap = ... <- obtain the bitmap as suggested in the SO link above
val matrix = Matrix()
matrix.postRotate(90f)
bitmap = Bitmap.createBitmap(bitmap, 0, 0, image.width, image.height, matrix, true)
val cropHeight = if (bitmap.width < viewFinderSize!!.width) {
    // if preview area larger than analysing image
    val koeff = bitmap.width.toFloat() / viewFinderSize!!.width.toFloat()
    viewFinderSize!!.height.toFloat() * koeff
} else {
    // if preview area smaller than analysing image
    val prc = 100 - (viewFinderSize!!.width.toFloat()/(bitmap.width.toFloat()/100f))
    viewFinderSize!!.height + ((viewFinderSize!!.height.toFloat()/100f) * prc)
}

val cropTop = (bitmap.height/2)-((cropHeight)/2)
bitmap = Bitmap.createBitmap(bitmap, 0, cropTop.toInt(), bitmap.width, cropHeight.toInt())
Run Code Online (Sandbox Code Playgroud)

变量中的最终值bitmap- 是准备传递到的裁剪后的图像FirebaseVisionImage.fromBitmap(bitmap)

附言。欢迎改进建议的变体