我正在使用与 ImageCapture 用例相关联的 ImageCapture.OnImageCapturedListener.onCaptureSuccess 提供的 ImageProxy 实例。该实例是在与按钮相关联的回调中创建的,以触发捕获。 上下文有点棘手,需要了解CameraX API才能完全理解它。
我的问题与摄影机回调而非CameraX API提供的ImageProxy的使用有关
onCaptureSuccess的原型如下: onCaptureSuccess(imageProxy:ImageProxy ?, angle_deg:Int),其中 imageProxy 是图像框架容器, angle_deg 相机旋转的值。
根据图像使用者的不同,有多种选择可以使图像执行逐像素处理。 其中之一是创建 Bitmap ,但是 BitmapFactory 创建者和 Bitmap 创建函数都无法提供直接的解决方案。
在我的上下文中,我使用了图像将其保存到文件中(为此,我需要创建一个文件,其中图像数据将从位图中流出来。 >)和同一张图片进行图片分类(为此,我需要创建一个张量-PyTorch InputTensor -使用临时的位图)。
我定义了Kotlin从ImageProxy转换为File或Bitmap的转换功能。
在以下代码示例中,输入ImageProxy
是调用对象this
。
通过作用域函数.let
和.apply
,输入对象被转换为级联的中间上下文对象,其级联深度足以能够调用buffer.get(data)
的像素数据。
从托管ImageProxy
中提取数据后,就可以“后退”以返回预期的对象(File
或Bitmap
)。
出于无法解释的原因,当多次使用ImageProxy
时,有必要“倒带”调用buffer.rewind()
的内部缓冲区。
要从File
创建ImageProxy
,必须从ByteBuffer
(buffer
)中提取数据并保存到ByteArray
({{1 }})通过data
(例如ByteArrayOutputStream
)流到文件中。
out
要从 fun ImageProxy.toFile(): File {
return File(parentActivity.getExternalFilesDir(Environment.DIRECTORY_PICTURES),"${System.currentTimeMillis()}.jpg").apply{
FileOutputStream(this.path).use { stream ->
getPlanes()[0].buffer.let{ buffer ->
buffer.rewind() // <---- it makes it work
ByteArray(buffer.capacity()).let { data ->
buffer.get(data)
BitmapFactory.decodeByteArray(data, 0, data.size).apply{
compress(Bitmap.CompressFormat.JPEG,100, stream)
}
}
}
}
}
创建Bitmap
,必须从ImageProxy
(ByteBuffer
)中提取数据并保存到buffer
({{1 }}),它用于使用因子类ByteArray
创建位图。
data
如果两个转换函数在同一个ImageProxy实例上一个接一个地调用
BitmapFactory
如果代码中省略了 fun ImageProxy.toBitmap(): Bitmap
{
getPlanes()[0].buffer.let { buffer ->
buffer.rewind() // <---- it makes it work
ByteArray(buffer.capacity()).let { data ->
buffer.get(data)
return BitmapFactory.decodeByteArray(data, 0, data.size)
}
}
}
,则第二个失败。
查看堆栈跟踪及其在何处被撞掉,这是因为缓冲区长度大于 ByteBuffer 类({{隐含的那个)中的其余数据( fun onCaptureSuccess(imageProxy: ImageProxy?, angle_deg: Int)
{
File saved=imageProxy.toFile()
Bitmap bitmap=imageProxy.toBitmap()
}
) 1}})。
似乎图像代理的状态取决于之前执行的操作。我找不到一些重置状态函数来处理。
得到的代码有些复杂,仅获得一堆像素。有没有其他更简单的方法可以做到这一点而又不影响ImageProxy的内部状态(某些带有某些缓冲区的像素平面的像素)?
还有其他编程替代方法(通过NDK或JNI或自定义的开放CV代码)处理图像像素吗?