Android 图像已关闭。照相机分析器
我正在尝试将cameraX分析器中的ProxyImage转换为位图,以便使用张量流动光分析图像。 因此,我实现了cameraX Analyze回调,它将图像作为proxyImage提供。我需要将该代理图像转换为位图。 如果我在UI线程上进行此对话,会使相机预览延迟。所以我想用协同程序来实现。 现在的问题是,每当我将proxyImage传递给Corroutines以将其转换为背景线程上的位图时,它就会崩溃,出现非法状态异常“图像已关闭” 我认为下一帧是取消引用前一帧,而应用程序正在后台线程中将proxyImage转换为位图。 我读了文件,他们说 从该方法返回后,图像引用关闭。 因此,该方法应完成分析或复制 将图像引用传递到分析方法之外 我在这里感到困惑,当我们将图像传递到分析方法之外时,复制图像意味着什么。 我如何处理这种情况。 下面是代码片段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
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;
}
}
});