原文作者:medium.com/@bbfee
发布时间:2021年11月20日
CameraX是一个支持Jetpack的库,它的建立是为了帮助相机应用的开发更容易。它支持不同的用例,如ImageCapture、Preview和ImageAnalysis,它们可以与ML Kit或TensorFlow Lite无缝结合。这为创建文本识别、图像标签等应用提供了很多可能性,甚至可以使用你自己训练的TensorFlow Lite模型检测和识别物体。然而,CameraX和这些库之间的图像格式转换是不容易的,有时还很费时。在这篇博客中,我们将讨论我们最近建立的一个新功能,以支持CameraX ImageAnalysis的YUV到RGB转换,包括我们为什么建立它,以及如何使用它,只需少量的代码。
背景介绍
CameraX用YUV420_888制作图像,每个通道有8比特的Luma(Y)、Chroma(U,V)和Paddings(P)。YUV是一种通用和灵活的格式,它允许在不同的设备上进行OEM的变化,这涵盖了很多ImageAnalysis的用例。然而,许多应用程序仍然依赖于RGB格式。在我们的开发者社区,YUV到RGB的转换是要求最高的功能之一,因为RGB格式很流行,容易操作,而且有时需要,如TensorFlow Lite模型)。让我们先来看看YUV和RGB格式。
YUV_420_888格式
YUV格式也可以被称为 "YCbCr"。它包括平面(如I420)、半平面(如NV21/NV12)和包装格式(如UYVY)。YUV_420_888是一种通用的YCbCr格式,能够描述任何4:2:0色度子采样的平面或半平面缓冲器(但不是完全交错的),每个颜色样本有8比特。Y平面被保证不与U/V平面交错(特别是,像素跨度总是1)。U/V平面被保证具有相同的行跨度和像素跨度。
RGBA_8888格式
RGBA_8888是一种标准的RGB格式,有红、绿、蓝和α通道,每个通道有8位。转换的主要目标是RGB颜色空间。RGB比较简单,变化较少。
API实现
我们评估了3种YUV到RGB转换的方法
- Java/Kotlin
- 渲染脚本
- 本地(C/C++和NDK)
Java/Kotlin实现的图像处理有很长的计算时间和垃圾回收压力。Renderscript是计算密集型任务的候选者,如YUV到RGB。然而,从Android 12开始,它已经被弃用。
考虑到未来的扩展性和兼容性,我们决定使用本地方法(libyuv + NDK)。Libyuv是一个开源项目,包括YUV的缩放、转换和旋转功能。考虑到所有因素,CameraX的颜色转换管道可以从高层次上看如下。
为了向后兼容,我们的管道仍然产生ImageProxy作为输出。ImageProxy是media.Image的一个封装类,它是由Android框架产生的一个图像缓冲区。为了产生一个转换后的Image,Java/Kotlin层可以通过dequeueInputImage()从Surface获得一个输入Image,然后使用ImageReader和ImageWriter将Image数据写入其中。由于ImageWriter是在API 23中添加的,我们使用ANativeWindow及其缓冲区来产生RGBA格式的输出图像,以支持更多的API级别。
对于输入,我们在CameraX内部支持YUV_420_888格式的不同变化(I420、NV12、NV21等)。对于输出,我们现在支持RGBA格式,但将来可以扩展到其他RGB格式。
由于我们使用libyuv作为新的依赖,我们的库的大小增加了约50KB。
API使用情况
从CameraX 1.1.0-alpha08开始,应用程序可以通过在ImageAnalysis配置中使用setOutputImageFormat选择YUV_420_888或RGBA_8888格式的输出图像。
一旦选择了RGBA_8888,输出的图像格式将是PixelFormat.RGBA_8888,它只有一个图像平面(R、G、B、A逐个像素),并带有衬垫。传统上,Android框架支持的图像缓冲区格式是PixelFormat和ImageFormat的一个子集。 相比之下,如果选择YUV_420_888,输出的图像将是ImageFormat.YUV_420_888,它有三个独立的图像平面(Y、U、V)。
性能
我们测量了速度,并与Renderscript在不同的Android版本和设备上的结果进行了比较。总的来说,在不同的设备上,在不同的分辨率和Android操作系统版本上,我们使用libyuv的管道优于我们的参考Renderscript实现。
总结
我们在CameraX ImageAnalysis管道中支持YUV到RGB的转换。用户现在可以简单地选择输出格式(YUV_420_888或RGBA_8888)用于ImageAnalysis用例,以与其他库连接。这是一个令人兴奋的旅程的开始,我们正在考虑在CameraX ImageAnalysis管道中添加更多的图像处理功能,并将其扩展到其他用户案例(ImageCapture或Preview等)。如果您有任何功能要求,请告诉我们。
YUV到RGB转换的示例代码可以在GitHub上找到。要了解更多关于CameraX的信息,请参考官方文档。要了解CameraX的最新进展,请加入CameraX讨论组。反馈是非常有价值的,欢迎在此留言,在CameraX讨论组与我们交流,或通过官方问题跟踪器创建CameraX问题。
请继续关注!