Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/183.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 图像已关闭。照相机分析器_Android_Android Architecture Components_Android Jetpack_Kotlin Coroutines_Android Camerax - Fatal编程技术网

Android 图像已关闭。照相机分析器

Android 图像已关闭。照相机分析器,android,android-architecture-components,android-jetpack,kotlin-coroutines,android-camerax,Android,Android Architecture Components,Android Jetpack,Kotlin Coroutines,Android Camerax,我正在尝试将cameraX分析器中的ProxyImage转换为位图,以便使用张量流动光分析图像。 因此,我实现了cameraX Analyze回调,它将图像作为proxyImage提供。我需要将该代理图像转换为位图。 如果我在UI线程上进行此对话,会使相机预览延迟。所以我想用协同程序来实现。 现在的问题是,每当我将proxyImage传递给Corroutines以将其转换为背景线程上的位图时,它就会崩溃,出现非法状态异常“图像已关闭” 我认为下一帧是取消引用前一帧,而应用程序正在后台线程中将pr

我正在尝试将cameraX分析器中的ProxyImage转换为位图,以便使用张量流动光分析图像。 因此,我实现了cameraX Analyze回调,它将图像作为proxyImage提供。我需要将该代理图像转换为位图。 如果我在UI线程上进行此对话,会使相机预览延迟。所以我想用协同程序来实现。 现在的问题是,每当我将proxyImage传递给Corroutines以将其转换为背景线程上的位图时,它就会崩溃,出现非法状态异常“图像已关闭”

我认为下一帧是取消引用前一帧,而应用程序正在后台线程中将proxyImage转换为位图。 我读了文件,他们说

从该方法返回后,图像引用关闭。 因此,该方法应完成分析或复制 将图像引用传递到分析方法之外

我在这里感到困惑,当我们将图像传递到分析方法之外时,复制图像意味着什么。 我如何处理这种情况。 下面是代码片段

  val imageAnalysisConfig = ImageAnalysisConfig.Builder()
            .setTargetResolution(Size(1280, 720))
            .build()
        val imageAnalysis = ImageAnalysis(imageAnalysisConfig)
        imageAnalysis.setAnalyzer { image: ImageProxy, _: Int ->

            classifier = Classifier.create(this, Classifier.Model.FLOAT, Classifier.Device.CPU, 1)

            CoroutineScope(Default).launch {
                convertProxyImageToBitmap(image)
            }
        }
方法将proxyImage转换为位图

private fun getImageFromProxy(image: ImageProxy): Bitmap {

        val yBuffer = image.planes[0].buffer // Y
        val uBuffer = image.planes[1].buffer // U
        val vBuffer = image.planes[2].buffer // V
        val ySize = yBuffer.remaining()
        val uSize = uBuffer.remaining()
        val vSize = vBuffer.remaining()
        val nv21 = ByteArray(ySize + uSize + vSize)
        //U and V are swapped
        yBuffer.get(nv21, 0, ySize)
        vBuffer.get(nv21, ySize, vSize)
        uBuffer.get(nv21, ySize + vSize, uSize)
        val yuvImage = YuvImage(nv21, ImageFormat.NV21, image.width, image.height, null)
        val out = ByteArrayOutputStream()
        yuvImage.compressToJpeg(Rect(0, 0, yuvImage.width, yuvImage.height), 100, out)
        val imageBytes = out.toByteArray()
        return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
    }

提前感谢您的帮助。

setAnalyzer api已更新。现在可以在api中设置executor。 你可以将自己的处理程序传递到那里。 例如:

mImageAnalysis.setAnalyzer(


我最近遇到了这个问题。如果我是正确的,这意味着在调用了
image.close()
之后,您正在使用
image
执行某些操作。在您的情况下,它可能会在
setAnalyzer{}内的lambda块末尾自动调用
,但当这种情况发生时,您仍在使用协同程序进行一些异步工作

您需要完全删除协同程序,或者将其包装在
runBlocking{}
块中以等待其完成,因为否则错误不会消失(至少我最近就是这样解决的)。如果您已将策略设置为“仅保留最新的”,理论上,您可以在执行图像分析的代码块内花费所有时间,因为相机当前生成的帧将被丢弃,而不是不必要地等待

如果同时您已经更新了项目以使用最新的CameraX版本,并且您使用的是专用类,请记住每次从覆盖的
analyze()
方法返回时都要调用
image.close()
自己,否则屏幕上的相机预览将永远冻结

我在这里感到困惑,当我们将图像传递到分析方法之外时,复制图像意味着什么。我如何处理这种情况


我认为在这种情况下,您需要制作一个深入的
图像副本
,这意味着您创建了一个新实例,并将其所有内容和内部状态设置为原始实例的内容和内部状态,而不是简单地分配引用。

您解决了这个问题吗?我也遇到过,我不知道该怎么办!@MahsaSeifikar t请看下面。
private fun getImageFromProxy(image: ImageProxy): Bitmap {

        val yBuffer = image.planes[0].buffer // Y
        val uBuffer = image.planes[1].buffer // U
        val vBuffer = image.planes[2].buffer // V
        val ySize = yBuffer.remaining()
        val uSize = uBuffer.remaining()
        val vSize = vBuffer.remaining()
        val nv21 = ByteArray(ySize + uSize + vSize)
        //U and V are swapped
        yBuffer.get(nv21, 0, ySize)
        vBuffer.get(nv21, ySize, vSize)
        uBuffer.get(nv21, ySize + vSize, uSize)
        val yuvImage = YuvImage(nv21, ImageFormat.NV21, image.width, image.height, null)
        val out = ByteArrayOutputStream()
        yuvImage.compressToJpeg(Rect(0, 0, yuvImage.width, yuvImage.height), 100, out)
        val imageBytes = out.toByteArray()
        return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
    }
            CameraXExecutors.newHandlerExecutor(mBackgroundHandler), //pass your background thread handler here
            new ImageAnalysis.Analyzer() {

                @Override
                public void analyze(@NonNull ImageProxy image, int rotationDegrees) {
                    // This will be called in your background thread;
                    }
                }
            });