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”,它包含立体 (planar,如 I420)、半立体 (semi-planar,如 NV21/NV12) 和打包 (packed,如 UYVY) 格局。YUV_420_888 是一种通用的 YCbCr 格局,它可能示意任何 4:2:0 色度二次采样的立体或半立体缓冲区 (但不齐全交织),每个色彩样本有 8 位。且可能保障 Y 立体不会与 U/V 立体交织 (且像素步长始终为 1),以及 U/V 立体总是具备雷同的行步长和像素步长。
RGBA_8888 格局
RGBA_8888 是一种规范的具备红、绿、蓝和 alpha 通道的 RGB 格局,每个通道有 8 位。次要的转换对象是 RGB 色彩空间,RGB 因为色差变动较少,相对来说比较简单。
API 实现
咱们评估了三种将 YUV 转换为 RGB 的办法:
- 应用 Java/Kotlin
- 应用 Renderscript 渲染脚本
- 原生计划 (应用 C/C++ 和 NDK)
应用 Java/Kotlin 来实现对图片的解决须要长时间的计算,并面临着垃圾回收带来的压力。而 Renderscript 是面向计算密集型工作 (比方从 YUV 转换为 RGB 格局) 的一个候选计划,然而从 Android 12 开始,这种办法曾经被 废除 了。
思考到之后的扩展性和兼容性,咱们决定应用原生计划 (libyuv + NDK)。Libyuv 是一个开源我的项目,它蕴含了对 YUV 的缩放、转换和旋转性能。综合所有因素,宏观上来看,CameraX 色彩转换的 pipeline 如下图:
为了向后兼容,咱们仍然应用 ImageProxy 作为输入。ImageProxy 是 media.image 的一个封装类,它是 Android framework 中提供的一个图片缓冲。Java/Kotlin 层能够从 Surface 中通过 dequeueInputImage()) 取得一个输出的 Image,而后应用 ImageReader 和 ImageWriter 将 Image 数据写入其中,从而失去一个转换后的 Image。因为 ImageWriter 是在 API 23 中增加的,咱们应用 ANativeWindow 以及其缓冲区来产生 RGBA 格局的输入图像,以反对更多的 API 级别。
对于输出数据,咱们在 CameraX 外部反对 YUV_420_888 格局的不同变体 (I420,NV12,NV21 等)。对于输入数据,咱们当初反对 RGBA 格局,但未来会扩大到更多其余的 RGB 格局。
因为咱们应用 libyuv 作为新的依赖库,咱们的库大小减少了大概 50 KB。
API 应用
从 CameraX 1.1.0-alpha08 版本开始,利用能够通过在 ImageAnalysis 配置中应用 setOutputImageFormat 来抉择 YUV_420_888 或者 RGBA_8888 的图片输入格局。
一旦抉择了 RGBA_8888,输入的图片格式将会是 PixelFormat.RGBA_8888,它只有一个带有填充的图像立体 (一一 R,G,B,A 的像素)。原则上 Android framework 反对的图像缓冲区格局是 PixelFormat 和 ImageFormat 的子集。
相比之下,如果抉择了 YUV_420_888,输入的图片格式将是 ImageFormat.YUV_420_888,它有 3 个独立的图像立体 (Y,U,V)。
性能
咱们做了一些性能测试,并与在不同的 Android 版本和设施上应用 Renderscript 的后果进行了比拟。总体上来说,在不同分辨率和 Android 零碎版本上,应用 libyuv 的 pipeline 要优于应用 Renderscript 的实现。
总结
咱们在 CameraX ImageAnalysis pipeline 中反对了 YUV 到 RGB 的转换。用户当初能够简略地为一个 ImageAnalysis 用例抉择一个输入格局 (YUV_420_888 或 RGBA_8888),并用于其余库之中。而这仅仅是一个开始,咱们还打算在 CameraX ImageAnalysis pipeline 中减少更多的图像处理性能,并将其扩大到其余的用例中 (例如 ImageCapture 或 Preview 等)。如果您有任何性能上的需要,请分割咱们。
YUV 到 RGB 转换的示例代码能够在 GitHub 中查看。若需理解更多对于 CameraX 的音讯,请参考 官网文档。若要理解对于 CameraX 的最新进展,您能够退出 CameraX 讨论区。另外,您的反馈对咱们来说非常具备价值,欢送随时在 CameraX 讨论区留言或在官网的 Issue Tracker 中给咱们反馈。
相干援用
- CameraX 公布阐明
- 开始应用 CameraX
- CameraX Github 用例
- YUV 格局 Wiki
欢迎您 点击这里 向咱们提交反馈,或分享您喜爱的内容、发现的问题。您的反馈对咱们十分重要,感谢您的反对!