【问题标题】:Set width and height of ImageAnalyzer and PreviewView the same设置 ImageAnalyzer 和 PreviewView 的宽高相同
【发布时间】:2021-07-25 09:40:38
【问题描述】:

我有一个简单的设置:

preview = new Preview.Builder().build();
preview.setSurfaceProvider(mPreviewView.createSurfaceProvider());
imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(new Size(mPreviewView.getWidth(),mPreviewView.getHeight())).build();
imageAnalysis.setAnalyzer(executor, new PaperImageAnalyser());

图像分析器:

@SuppressLint("UnsafeExperimentalUsageError")
@Override
public void analyze(@NonNull ImageProxy imageProxy) {
    Image mediaImage = imageProxy.getImage();

    if (mediaImage != null) {
        InputImage image = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());
        Log.e("madieaimage",mediaImage.getHeight() + " and with" + mediaImage.getWidth()); //480 and with640
        Log.e("inputimage", image.getHeight() + " and width" + image.getWidth()); //480 and width640
        Log.e("imageproxy", image.getHeight() + " and width" + image.getWidth()); //480 and width640
        Log.e("cameraimp previewview ", CameraImp.mPreviewView.getBitmap().getHeight() + " and widht" +  CameraImp.mPreviewView.getBitmap().getWidth()); //2145 and widht1080
        image =  InputImage.fromBitmap(CameraImp.mPreviewView.getBitmap(),0); //analyzes much better cause resolution is set but its not good practise right?
    }
    
    //analyze with image...
}

问题是我从分析方法收到的图像分辨率远小于预览视图分辨率(宽度/高度),因此导致图像无法很好地识别。

如果我使用预览视图的位图,我基本上可以得到整个屏幕图片,这对分析更有效,但我认为这是不好的做法?

所以我的问题是:是否可以设置我上面尝试过的 ImageAnalyzer 的分辨率(例如 setTargetResolution)?

或者处理此类问题的最佳方法是什么?

【问题讨论】:

    标签: android image-processing android-imageview android-camerax google-mlkit


    【解决方案1】:

    如果我使用预览视图的位图,我会得到整个图片 屏幕基本上哪个更适合分析,但那很糟糕 我假设的练习?

    是的,这在性能方面是不好的做法,因为缓冲区复制非常昂贵。

    所以我的问题是:是否可以设置分辨率 ImageAnalyzer (eg setTargetResolution) 我在上面试过了吗?

    如果你在某些设备上是可能的,例如将两个分辨率都设置为1080p。但是,不能保证它可以在任何地方工作,因为相机硬件可能不支持它。此外,根据您的使用场景,高分辨率图像分析也可能是一种不好的做法,因为分析通常不需要如此高分辨率。

    请问为什么需要Preview和ImageAnalysis的分辨率一样?

    【讨论】:

    • 我需要分辨率“相同”,因为使用 imageProxy 图像返回错误的矩形坐标,分辨率较小。矩形未对齐/在实际对象之外。例如:pasteboard.co/K0dMhyj.jpgpasteboard.co/K0dMA4W.jpg 如果我使用 previewview 的位图,我基本上会收到更好的结果
    • ImageAnalysis 和 Preview 并不总是可以具有相同的分辨率,至少不是在所有设备上。在这种情况下,您需要手动转换坐标以对齐它们。如果你不关心性能,你可以从 PreviewView 中获取一个 Bitmap 并使用它进行分析。那么它将是所见即所得。
    • 嗯,我明白了。坏。当我的分析器 24/7 运行时,我可能会受到性能的影响,也许我可能只是更改它,以便分析器只分析静态图像,至少可以保证性能。谢谢老哥的回答
    【解决方案2】:

    我刚遇到同样的问题,我想为 PreviewView 和 ImageCapture 使用更高的分辨率,为 ImageAnalysis 使用更小的分辨率,但我希望它们在纵横比和内容上看起来都一样。

    但是,在某些特定分辨率下,来自 ImageAnalysis 和 ImageCapture 的图像看起来相同,但它们比 PreviewView 上的图像宽。

    我通过将 PreviewView 的 scaleType 设置为 FIT_CENTER 解决了这个问题,因为它的默认值是 FILL_CENTER,如果相机预览的纵横比与其容器的纵横比不匹配,这将导致预览被裁剪:

    previewView.scaleType = PreviewView.ScaleType.FIT_CENTER
    

    并且,为了确保 ImageAnalysis 的纵横比尽可能接近 PreviewView:

    val highSize = Size(3000, 4000)
    val preview = Preview.Builder().setTargetResolution(highSize).build()
    val imgCaptured = ImageCapture.Builder().setTargetResolution(highSize).build()
    preview.setSurfaceProvider(previewView.surfaceProvider)
    // bind empty lifycycle with id to get camera
    val supportSizes = getSupportedSizes(camera, 0)
    val analysisSize = getNearestSize(supportSizes, 480, 640, 30f)
    val analyzer = ImageAnalysis.Builder()
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                .setOutputImageRotationEnabled(true)
                .setTargetResolution(analysisSize).build()
    analyzer.setAnalyzer(...)
    cameraProvider.unbindAll()
    val camera = cameraProvider.bindToLifecycle(lifecycle, cameraSelector, preview, imgCaptured, analyzer)
    
    
    fun getSupportedSizes(camera: Camera, device: Int): Array<Size!>{
        val cInfo = camera.cameraInfo
        val camChars = Camera2CameraInfo.extractCameraCharacteristics(cInfo)
        val configs: StreamConfigurationMap? =
            camChars.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
        if (configs == null) {
            Log.i(TAG, "get camera out sizes fail, config empty")
            return
        }
        val sensorRotate = camChars.get(CameraCharacteristics.SENSOR_ORIENTATION) ?: 0
        return configs.getOutputSizes(ImageFormat.JPEG)
    }
    
    fun getNearestSize(sizes: Array<Size!>, inWidth: Int, inHeight: Int, aspectWeight: Float = 1f): Size? {
        if (inWidth <= 0 || inHeight <= 0 || device !in cameraInfoMap) return null
        val requireArea = inWidth * inHeight
        val requireAspect = inHeight * 1f / inWidth
        var bestSize: Size? = null
        var minDiff: Float = 10000f
        Log.i(TAG, "find near size for aspect: ${requireAspect}, $inWidth * $inHeight, weight: $aspectWeight")
        for (size in sizes) {
            val curArea = size.width * 1f * size.height
            val curAspect = size.height * 1f / size.width
            val curDiff = abs(curAspect - requireAspect) * aspectWeight + abs(curArea / requireArea - 1)
            if (bestSize == null || minDiff > curDiff) {
                Log.i(TAG, "better size: $size, diff: $curDiff")
                bestSize = size
                minDiff = curDiff
            }
        }
        return bestSize
    }
    

    最后,我可以得到小分辨率的图像进行分析,高分辨率的预览和捕获,具有相同的纵横比和外观!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-23
      • 1970-01-01
      • 2018-06-01
      相关资源
      最近更新 更多