CameraX使ImageAnalysis的尺寸与Preview相同

时间:2019-08-12 13:21:16

标签: android android-camerax

我希望能够在预览时获得准确的图像用于分析。 我有预览用例:

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

在它旁边,我有分析用例配置:

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()

我的预览是全屏的,因此尺寸为1440x2560。但是,如果我尝试从分析器中的ImageProxy中获取尺寸,则会得到1920x1050,它的尺寸和宽度随高度的变化似乎不正确。为什么会这样,我如何强制我的分析步骤具有与全屏相同的尺寸?

1 个答案:

答案 0 :(得分:2)

简介:

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'

我正在通过方法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)
    

    然后将尺寸传递到您自己的ImageAnalysis.Analyzer中 实现(假设它将是viewFinderSize变量,用法请参见下文)

  2. 发生override fun analyze(mediaImage: ImageProxy){时,请手动裁剪接收到的ImageProxy。我正在使用另一个有关扭曲YUV_420_888图片的SO问题的代码段:https://stackoverflow.com/a/45926852/2118862

进行裁剪时,请记住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())

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

PS。 欢迎改进建议的变体