![](/img/trans.png)
[英]Is it possible to combine Preview, ImageAnalysis, and VideoCapture with CameraX?
[英]CameraX make ImageAnalysis same size as Preview
我希望能够在预览时获得用于分析步骤的准确图像。 我有预览用例:
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,它似乎有不正确的尺寸并且宽度随高度切换。 为什么会这样?如何强制我的分析步骤具有与全屏相同的尺寸?
介绍:
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
- 根据预览配置手动裁剪 && 旋转图像。 步骤是:
当您设置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
变量,用法见下文)
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。 欢迎改进建议的变体
可能是我迟到了,但这是为我工作的代码
如果cropTop 很少以-ve 值出现,因此每当出现负值时,您应该处理来自 ImageProxy 的图像,在其他情况下,您可以处理裁剪的位图
val mediaImage = imageProxy.image ?: return
var bitmap = ImageUtils.convertYuv420888ImageToBitmap(mediaImage)
val rotationDegrees = imageProxy.imageInfo.rotationDegrees
val matrix = Matrix()
matrix.postRotate(rotationDegrees.toFloat())
bitmap =
Bitmap.createBitmap(bitmap, 0, 0, mediaImage.width, mediaImage.height, matrix, true)
val cropHeight = if (bitmap.width < previewView.width) {
// if preview area larger than analysing image
val koeff = bitmap.width.toFloat() / previewView.width.toFloat()
previewView.height.toFloat() * koeff
} else {
// if preview area smaller than analysing image
val prc = 100 - (previewView.width.toFloat() / (bitmap.width.toFloat() / 100f))
previewView.height + ((previewView.height.toFloat() / 100f) * prc)
}
val cropTop = (bitmap.height / 2) - ((cropHeight) / 2)
if (cropTop > 0) {
Bitmap.createBitmap(bitmap, 0, cropTop.toInt(), bitmap.width, cropHeight.toInt())
.also { process(it, imageProxy) }
} else {
imageProxy.image?.let { process(it, imageProxy) }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.