CameraX Extensions , 相机特性实现更简单了

46dfdbfee7e563abb251c6fcf4b3fcd9.png

Android CameraX 的设计旨在帮助您简化相机应用的开发工作。随着对 CameraX 不断的开发,相机应用的开发者们向我们展示了他们的激情和热忱,当前的 API 中已经融入了许多很棒的创意,例如值得称赞的 CameraX Extensions API。最近我们采纳了开发者社区的意见,对扩展进行了重构,如今有了新的 ExtensionsManager,您只需两行代码就可以使用这些扩展!本文将介绍如何在您的应用中使用 Extensions API。

  • Android CameraX
    https://android-developers.googleblog.com/2019/05/whats-new-with-android-jetpack.html

  • ExtensionsManager
    https://developer.android.google.cn/reference/androidx/camera/extensions/ExtensionsManager

afa22d0c448079b1043721be694ce5d5.png

CameraX Extensions

Android 设备配备了强大的相机,制造商们投入了大量精力将众多前沿的功能特性或特效融入这些相机设备中。过去,这些强大的功能只能由设备的原生相机应用提供。如今,凭借 CameraX Extensions API,第三方开发者可以通过一个通用的、简单的接口来访问这些强大的相机功能。

0d9bf1bc1703e2347de691edba5b2174.png

1612827e4e6251a5e41fa84dfa108b84.png

CameraX Extensions 涵盖的内容

1.0.0 版本的 CameraX Extensions 包括一些最常见的内置相机特效:

  • BOKEH (焦外成像): 在人像模式下拍摄照片时,让前景人物更清晰。

  • HDR (高动态范围): 拍照时使用不同的自动曝光 (AE) 配置,以获得最佳效果。

  • NIGHT (夜间): 在低照度环境下 (通常是在夜间) 捕获最佳静态图像。

  • FACE RETOUCH (脸部照片修复): 拍摄静态图像时,修饰脸部肤色、轮廓等。

  • AUTO (自动): 根据周围的景色自动调整最终图像。

让我们来看几组在 Android 手机上拍摄的照片,拍照时分别启用和禁用了由 CameraX Extensions API 提供的特效。

9009866ba798ee68d4a183b4df69fa4f.png

BOKEH 模式的例子

957bbb04ac013b652db55df2f4edf8cd.png

△ 图 1: 右侧照片启用了 BOKEH 特效。

e92e051ebff13730488002366d2b23a3.png

HDR 模式的例子

5e1d705857833b721c61b5a44d4f69d3.png

△ 图 2: 右侧照片启用了 HDR 特效。

db3bef10fb09c9ea48fa180f4b84d70b.png

NIGHT 模式例子

0b2f2ff6066e928a11cfb535ef0a5c26.png

△ 图 3: 右侧照片启用了 NIGHT 特效。

视觉上的差异是很明显的。您可以使用 CameraX Extensions API 在您自己的应用中实现这些图像的效果。

现在让我们看看如何将 CameraX 的 API 集成到您的应用中。

8aed8b5f93ac3de1f1e39d7a8077db27.png

Extensions API

在现有的 CameraX 应用中,首先您可以引入 camera-extensions Jetpack 库来添加 CameraX Extensions:

dependencies {
    // 与 Extensions 库版本号相匹配的 CameraX 核心库
    implementation 'androidx.camera:camera-core:1.1.0-alpha08'
    implementation 'androidx.camera:camera-camera2:1.1.0-alpha08'
    implementation 'androidx.camera:camera-lifecycle:1.1.0-alpha08'


    // CameraX Extensions 库
    implementation 'androidx.camera:camera-extensions:1.0.0-alpha28'


    // 其他依赖项
    implementation('androidx.concurrent:concurrent-futures-ktx:1.1.0')
        …
}

接下来,通过以下步骤集成 Extensions:

  1. 获取 ExtensionsManager 实例:

    https://developer.android.google.cn/reference/androidx/camera/extensions/ExtensionsManager

  2. 检查目标设备是否支持需要用到的扩展模式;

  3. 获取一个启用扩展的 CameraSelector;

  4. 使用启用扩展的 CameraSelector 调用 bindToLifecycle:

    https://developer.android.google.cn/reference/androidx/camera/lifecycle/ProcessCameraProvider#bindToLifecycle(androidx.lifecycle.LifecycleOwner,%20androidx.camera.core.CameraSelector,%20androidx.camera.core.UseCase...)

38925cea8573864cff965bc5a3690ecd.png

获取 ExtensionsManager 实例

第一步是用扩展库的 getInstance(Context) API 获得一个 ExtensionsManager 实例。这个 API 返回一个 ListenableFuture,我们可以在 Kotlin 挂起函数中使用 await() 来获取结果以避免阻塞主线程。(注意: 在 ListenableFuture 上使用 await() 须引入 androidx.concurrent:concurrent-futures-ktx: 1.1.0 依赖项。)

// 创建扩展管理器(使用 Jetpack Concurrent 库)
val extensionsManager =  ExtensionsManager.getInstance(context).await()
  • getInstance(Context)

    https://developer.android.google.cn/reference/androidx/camera/extensions/ExtensionsManager#getInstance(android.content.Context)

  • ExtensionsManager

    https://developer.android.google.cn/reference/androidx/camera/extensions/ExtensionsManager

通过 ExtensionsManager,您可以确定设备是否支持某一特定的扩展模式,并为其获取一个启用扩展的 CameraSelector。请注意以下几点:

  • ExtensionsManager 是一个进程范围的全局资源: 一个进程中只存在一个 ExtensionsManager 实例。

  • ExtensionsManager 始终存在: 无论底层设备是否支持扩展,CameraX 都提供一个有效的 ExtensionsManager 实例。

f367b8144e6e2da43dfc511af85d3ec8.png

检查扩展模式可用性

通过 ExtensionsManager,使用 isExtensionAvailable(CameraProvider, CameraSelector, int) 函数检查扩展的可用性: 如果设备上存在任何经由 CameraSelector 过滤的相机支持所查询的扩展,则返回 true,否则返回 false。

// 获取相机设备来检查是否支持扩展
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA


        // 检查是否支持 BOKEH
        if (extensionsManager.isExtensionAvailable(
                cameraProvider,
                cameraSelector,
                ExtensionMode.BOKEH
            )) {
            ...
        }
  • isExtensionAvailable(CameraProvider, CameraSelector, int)

    https://developer.android.google.cn/reference/androidx/camera/extensions/ExtensionsManager#isExtensionAvailable(androidx.camera.core.CameraProvider,%20androidx.camera.core.CameraSelector,%20int)

b6dd60202512254d4fe651d094f57391.png

获取启用扩展的 CameraSelector

一旦您确认了设备支持该扩展模式,就可以用 getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int) 函数获取一个启用扩展的 CameraSelector。此函数返回启用扩展的 CameraSelector,其包含关于指定扩展模式的所有详细信息。

val bokehCameraSelector = extensionsManager
                          .getExtensionEnabledCameraSelector(
                              cameraProvider, cameraSelector, ExtensionMode.BOKEH)
  • getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)

    https://developer.android.google.cn/reference/androidx/camera/extensions/ExtensionsManager#getExtensionEnabledCameraSelector(androidx.camera.core.CameraProvider,%20androidx.camera.core.CameraSelector,%20int)

fd67789ea1ef5a1fd3cdfa767f7afcc0.png

使用启用扩展的 CameraSelector 调用 bindToLifecycle()

最后一步是使用 bindToLifecycle() 将您的用例与启用扩展的 CameraSelector 绑定。使用启用扩展的 CameraSelector 如同使用普通的 CameraSelector 一样,例如使用 DEFAULT_BACK_CAMERA 或 DEFAULT_FRONT_CAMERA。当使用启用扩展的 CameraSelector 绑定用例时,CameraX 会直接在相机上启用指定的扩展模式。例如,当绑定到 Preview 时,扩展效果被应用到预览中,或者应用到由所绑定的 ImageCapture 所捕获的图像上。

// 将开启了 BOKEH 的相机选择器绑定到用例上
val imageCapture = ImageCapture.Builder().build()
val preview = Preview.Builder().build()
cameraProvider.bindToLifecycle(
                lifecycleOwner,
                bokehCameraSelector,
                imageCapture,
                preview
            )
  • bindToLifecycle()
    https://developer.android.google.cn/reference/androidx/camera/lifecycle/ProcessCameraProvider#bindToLifecycle(androidx.lifecycle.LifecycleOwner,%20androidx.camera.core.CameraSelector,%20androidx.camera.core.UseCase...)

  • DEFAULT_BACK_CAMERA
    https://developer.android.google.cn/reference/androidx/camera/core/CameraSelector#DEFAULT_BACK_CAMERA

  • DEFAULT_FRONT_CAMERA
    https://developer.android.google.cn/reference/androidx/camera/core/CameraSelector#DEFAULT_FRONT_CAMERA

1b520411ec94abb4e972e2fd96c74e01.png

使用 Extensions API 的样例代码

Extensions API 示例的完整代码如下:

fun onCreate() {
    lifecycleScope.launch {
        // 创建 cameraProvider
        val cameraProvider = ProcessCameraProvider.getInstance(context).await() 


        // 创建 extensionsManager(使用 Jetpack Concurrent 库)
        val extensionsManager = 
                ExtensionsManager.getInstance(context).await()


        // 获取相机设备来检查是否支持扩展        
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA


        // 检查是否支持 BOKEH
        if (extensionsManager.isExtensionAvailable(
                cameraProvider,
                cameraSelector,
                ExtensionMode.BOKEH
            )) {
            // 在启用不同扩展模式之前解除所有用例的绑定
            cameraProvider.unbindAll()


            // 获取启用了 BOKEH 的相机选择器
            val bokehCameraSelector = extensionsManager
                    .getExtensionEnabledCameraSelector(
                cameraProvider,
                cameraSelector,
                ExtensionMode.BOKEH
            )


            // 将开启了 BOKEH 的相机选择器绑定到用例上
            val imageCapture = ImageCapture.Builder().build()
            val preview = Preview.Builder().build()
            cameraProvider.bindToLifecycle(
                lifecycleOwner,
                bokehCameraSelector,
                imageCapture,
                preview
            )
        }
    }
}

0114b6c9e27cb0aa59d26bb935fffd25.png

Extensions API 对核心模块的依赖

CameraX Extensions API 是在 camera-extensions 库中实现的,并且它依赖 CameraX 核心模块 (core、camera2 和 lifecycle)。使用 CameraX Extensions 时,请务必使用与您正在使用的 CameraX 核心模块相同的发布包中的版本。例如,要使用 camera-extensions:1.0.0-alpha28,则您必须在应用的依赖列表中包含 1.0.0-alpha08 版本的 camera-lifecycle、camera-core 和 camera-camera2,因为它们是于 2021 年 8 月 18 日在同一软件包中发布的。

  • 相同的发布包
    https://developer.android.google.cn/jetpack/androidx/releases/camera

36e026c8be6c9981bfa3601d696fa18c.png

支持扩展的设备

为了能使用 CameraX Extensions API,设备制造商需要实现 CameraX Vendor Extensions 接口。您可以在 CameraX 设备页面上找到支持 CameraX Extensions API 的部分设备列表。请注意,这不是一个详尽的列表。如果您的设备被列出,但可用性检查返回了 false,您可能需要将您的设备更新到制造商的最新 ROM 版本。

  • CameraX Vendor Extensions 接口
    https://source.android.com/devices/camera/camerax-vendor-extensions

  • CameraX 设备页面
    https://developer.android.google.cn/training/camerax/devices

除了支持扩展的设备列表外,从 Android 12 开始,您还可以通过检查 Android 属性 ro.camerax.extensions.enabled 来确定设备是否支持 CameraX Extensions。

5328b6947709575c7bb6ad3812d4cbd1.png

移除旧版 Extensions API

2019 年 8 月发布的旧版 Extensions API 现已废弃。这个旧版的 Extensions API 提供了扩展器类,需要将扩展相关的配置应用到每个 Preview 和 ImageCapture 用例上。旧版的扩展器设计可能会导致开发人员忘记要在 Preview 或 ImageCapture 上启用扩展模式,并可能导致非预期的行为。

新的 CameraX Extensions 库在 1.0.0-alpha26 中引入。较新的 Extensions API 将扩展绑定从用例切换到目标相机,使用起来更加方便。请务必迁移以利用新的 Extensions API。

我们特别感谢那些帮助实现 CameraX Extensions API 的出色的 Android 相机开发者和设备制造商!如果您想了解 CameraX 的最新进展,请加入 Android CameraX 讨论组:

https://groups.google.com/a/android.com/g/camerax-developers

8652e43f80b3510229b2dd325abacdd9.png

更多信息

  • CameraX Extensions API 指南

    https://developer.android.google.cn/training/camerax/vendor-extensions

  • Extensions API 参考
    https://developer.android.google.cn/reference/androidx/camera/extensions/ExtensionsManager

  • 扩展测试应用
    https://android.googlesource.com/platform/frameworks/support/+/androidx-main/camera/integration-tests/extensionstestapp/

  • CameraX 发布说明
    https://developer.android.google.cn/jetpack/androidx/releases/camera

  • 开始使用 CameraX
    https://developer.android.google.cn/codelabs/camerax-getting-started#0

  • CameraX Github 样例代码
    https://github.com/android/camera-samples

4efa9b087f09d31db3639afbf41652d1.png

推荐阅读:

一篇文章带你了解Android 最新Camera框架

这可能是介绍Android UvcCamera最详细的文章了

深圳上班,

生活简简单单,

14年开始从事Android Camera相关软件开发工作,

做过车载、手机、执法记录仪......

公众号记录生活和工作的点滴,

点击关注“小驰笔记”,期待和你相遇~

e81ae7a4ceaf07c69224d177d526d970.png

3f680ab162ba6afc07a5735cfaa30538.png

点个赞,一起加油!

posted @ 2021-10-28 08:00  小驰行动派  阅读(29)  评论(0编辑  收藏  举报  来源