Android GPUImage setImage和getBitmapWithFilterApplied导致屏幕闪烁

问题描述

我一直使用这个github作为我的代码的开头:https://github.com/xizhang/camerax-gpuimage

代码是一种显示带有GPUImage滤镜的相机视图的方法。 我还希望能够对应用了过滤器的位图进行分析,以进行一些分析(图像中红色/绿色/蓝色的百分比)。

我已经成功地向用户显示认的相机视图以及我创建的滤镜。

通过注释掉setimage代码行,我已经能够获得过滤图像的分析结果,但是当我尝试同时执行这两个操作时,屏幕会闪烁。我更改了StartCameraifReady函数获取过滤的图像,如下所示:

    @SuppressLint("UnsafeExperimentalUsageError")
    private fun startCameraifReady() {
        if (!isPermissionsGranted() || cameraProvider == null) {
            return;
        }
        val imageAnalysis = ImageAnalysis.Builder().setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build()
        imageAnalysis.setAnalyzer(executor,ImageAnalysis.Analyzer {
            var bitmap = allocateBitmapIfNecessary(it.width,it.height)
            converter.yuvToRgb(it.image!!,bitmap)
            it.close()
            gpuImageView.post {
                // These two lines conflict causing the screen to flicker
                // I can comment out one or the other and it works great
                // But running both at the same time causes issues
                gpuImageView.gpuImage.setimage(bitmap)
                val filtered = gpuImageView.gpuImage.getBitmapWithFilterapplied(bitmap)

                /*
                Analyze the filtered image...
                Print details about image here
                 */
            }
        })
        cameraProvider!!.unbindAll()
        cameraProvider!!.bindToLifecycle(this,CameraSelector.DEFAULT_BACK_CAMERA,imageAnalysis)
    }

当我尝试获取过滤后的位图时,它似乎与setimage代码行发生冲突,并导致屏幕闪烁,如下面的视频所示。我可以向用户显示预览,也可以分析图像,但不能同时分析两者。我尝试过同步运行它们,以及在各自的后台线程上运行它们。我还尝试添加一个图像分析器,并将其绑定到相机的生命周期(一个用于预览,另一个用于获取过滤后的位图),屏幕仍然闪烁,但频率较低。

https://imgur.com/a/mXeuEhe

<blockquote class="imgur-embed-pub" lang="en" data-id="a/mxeuEhe"  ><a href="//imgur.com/a/mxeuEhe">screenRocord</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>

解决方法

如果要在位图上应用过滤器,则甚至不需要GPUImageView。您可以只获取位图,然后在常规ImageView上进行设置。这就是您的分析仪的外观:

ImageAnalysis.Analyzer {
   var bitmap = allocateBitmapIfNecessary(it.width,it.height)
   converter.yuvToRgb(it.image!!,bitmap)
   it.close()
   val filteredBitmap = gpuImage.getBitmapWithFilterApplied(bitmap)
   regularImageView.post {
      regularImageView.setImageBitmap(filteredBitmap)
   }
}

请注意,原始的GitHub示例效率低下,而上面的示例甚至更糟,因为它们在将输出反馈给GPU之前将输出转换为Bitmap。为了获得最佳的预览流参数,请参见CameraX's core test app,了解如何通过OpenGL访问预览Surface。