乐趣区

关于android:CameraX-11-有哪些新的特性发布

CameraX 是一个 Jetpack 反对库,旨在帮忙您简化相机利用的开发工作。它提供统一且易用的 API 接口,实用于大多数 Android 设施,并可向后兼容至 Android 5.0 (API 级别 21)。咱们将在本文中介绍 CameraX 1.1 的多项性能,比方视频性能。

如果您更喜爱通过视频理解此内容,请在此处查看:

https://www.bilibili.com/vide…
△ CameraX 1.1 有哪些新的个性公布?

CameraX 概览

CameraX 是一个为了简化编写相机利用而设计的反对库,它所提供的高级 API 能够让开发者专一于和用户交互而非相机的外部实现。咱们始终在摸索并修复其背地简单的兼容性问题,让每个新版本都得以在更多的设施上稳固运行。

何时应用 CameraX 或 Camera2,这取决于您冀望更快的开发速度或是想要更高的自定义水平。

  • CameraX 能够很不便地实现一般照片视频的拍摄性能,而 Camera2 则能够对拍摄流程进行非凡管制,例如实现多重曝光或全手动捕捉;
  • CameraX 旨在打消不同设施间的差别并在不同设施上进行了测试,而 Camera2 则须要利用来治理不同设施间的差别并测试其行为;
  • CameraX 晋升了代码开发速度,让您更专一于用户界面和体验流程,而 Camera2 则用于更深刻地开发以发明基于相机的定制性能;
  • CameraX 公布新版本频繁,而 Camera2 则随着 Android 的版本而更新;
  • CameraX 能够在您不相熟相机的状况下也可能进行开发,而 Camera2 则须要您对相机的专业知识有更深层次的理解。

CameraX 基于次要的应用场景来构建,比方实时预览相机、检索缓冲区以进行剖析和拍摄照片,在 CameraX 1.1 版本中还退出了视频拍摄性能。咱们来看一个简略的 CameraX 示例:

fun bindPreview(cameraProvider : ProcessCameraProvider) {
    // 应用 CameraX 创立 Preview 用例
    var preview : Preview = Preview.Builder().build()

    // 创立 cameraSelector,它会在设施上搜寻所需的相机
    var cameraSelector : CameraSelector = CameraSelector.Builder()
        // 在本例中,咱们抉择搜寻后置相机
        .requireLensFacing(CameraSelector.LENS_FACING_BACK).build()

    // 从 CameraX 的 CameraView 包中获取 previewView 的句柄
    // 利用此办法能够轻松的将相机内容增加到视图上
    preview.setSurfaceProvider(previewView.getSurfaceProvider())

    // 将 preview 与其生命周期绑定
    var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner,
                                cameraSelector, preview)
}

△ CameraX 代码示例

CameraX 是生命周期感知型组件,这意味着它将主动解决利用的生命周期事件来实现开始、进行、暂停和复原。当初,利用启动时屏幕上便会显示实时预览。

咱们已于 2021 年 5 月公布了 1.0 稳固版本,目前正在开发 1.1 Alpha 版本并且很快将会进入 Beta 阶段。并且咱们判若两人地一直为新增设施推出兼容性修复程序,例如 1.0.1 和 1.0.2。

在 CameraX 1.1 版本中咱们新增了开发者呼声很高的性能,具体而言,在本文中咱们将重点介绍:

  • 视频拍摄
  • YUV 到 RGB 的转换
  • Beta 版 Extensions API
  • 一些须要理解的其它性能

视频拍摄

在 CameraX 1.1 版本中咱们退出了视频拍摄性能,视频拍摄 API (尚处于 Alpha 阶段,细节可能会发生变化,但整体构造根本会放弃不变) 提供了录制到文件等基本功能、可主动适配每台设施的 Quality Setting API,以及 Lifecycle Management API。接下来咱们先来理解如何设定视频拍摄性能,代码示例如下:

// 创立 Recorder
val recorder = Recorder.Builder()
                       // 咱们能够在此处应用 setQualitySelector 设置视频品质
                       .setQualitySelector(...)
                       .build()

// 应用新创建的 Recorder 创立 VideoCapture
val videoCapture = VideoCapture.withOutput(recorder)

// 将其与生命周期绑定
cameraProvider.bindToLifecycle(this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture)

// 设定 VideoRecordEvent 监听器
val videoRecordEventListener = Consumer<VideoRecordEvent>{when (it) {is VideoRecordEvent.Start -> {}
        is VideoRecordEvent.Finalize -> {}
        is VideoRecordEvent.Status -> {
            // status 事件将会在录制时继续更新
            val stats: RecordingStats = it.recordingStats
            // RecordingStats 中蕴含录制文件的尺寸和时长
        }
        is VideoRecordEvent.Pause -> {}
        is VideoRecordEvent.Resume -> {}

// 指定输入
val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
        MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
    .setContentValues(contentValues)
    .build()

// 筹备录制
val activeRecording = videoCapture.output.prepareRecording(this, mediaStoreOutput)
    // 关联事件监听器
    .withEventListener(ContextCompat.getMainExecutor(this), videoRecordEventListener)
    // 启用音频 (前提是此利用已取得音频权限)
    .withAudioEnabled()
    // 开始录制
    .start()

△ 视频拍摄示例

videoCapture 会在利用启动时就绪,利用能够应用 videoRecordEventListener 响应开始、完结、暂停和复原等拍摄事件,其中 Status 事件会提供包含文件大小和持续时间的 RecordingStats。视频拍摄能够输入到 File、FileDescriptorMediaStore,在本例中咱们抉择 MediaStore。如果抉择启用音频,则须要此利用曾经取得音频权限。调用 start() 开始录制为咱们提供了 activeRecording 句柄,它能够用来暂停、复原或进行录制。您能够在 1.1 版本中试用这些 API。

YUV 至 RGB 的转换

另一个呼声很高的性能是 YUV 到 RGB 的转换,咱们来理解一下此性能。

△ YUV 格局 (图左) 转换至 RGB 格局 (图右)

相机通常以 YUV420 格局生成数据,其中包含亮堂度 (Luminance, Y)、色度 (Chroma, U, V) 和一些填充字节以将各行与无效的内存步幅对齐。然而这种格局的图像处理起来可能很麻烦,而当初 CameraX 能够将 ImageAnalysis 的输入转换为大家更相熟的 RGBA 以不便解决。接下来咱们看一个示例:

val imageAnalysis = ImageAnalysis.Builder()
        .setTargetResolution(Size(1280, 720))
        .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
        .build()

△ 从 ImageAnalysis 获取 RGB 输入

在示例代码中,咱们创立了 ImageAnalysis 实例,为图像缓冲区指定了所需的分辨率和背压策略,并调用新的 setOutputImageFormat 办法以申请 RGBA 8888 格局的输入。当初,ImageAnalysis 输入的帧为 RGBA 8888 数据而不再是 YUV 格局。

CameraX 中 YUV 到 RGB 的转换基于 libyuv。此外,在 CameraX 1.1 版本中数据自身能够转换到指标分辨率。在中端设施上对图像大小为 640×480 至 1080p 的数据进行转换大概须要 5~10 毫秒,具体性能因设施而异。此外 APK 会稍微减少 50KB 左右。

修复单像素漂移

YUV 转换还修复了局部设施上存在的单像素漂移问题。在这些设施上,YUV 输入通过桶形移位一个像素,导致最左边的一列数据呈现在图像的左边缘。在已知会产生这种状况的设施上,进行 YUV 到 RGB 的转换及输入 YUV 或 RGB 都会被修复,并且 CameraX 将会继续对更多有须要的设施进行修复。

△ 修复单像素漂移

如需理解更多,请参阅咱们之前的推文《为 CameraX ImageAnalysis 进行 YUV 到 RGB 的转换》。

CameraX Extensions API

相机特效

在 CameraX 1.1 中的 CameraX Extensions API 能够更为充沛地施展设施弱小的性能。

CameraX Extensions 包含一些最常见的内置相机特效:

  • BOKEH (焦外虚化) : 在人像模式下拍摄照片时,让前景人物更清晰。
  • HDR (高动静范畴) : 拍照时应用不同的主动曝光 (AE) 配置,以获得最佳成果。
  • NIGHT (夜间) : 在低照度环境下 (通常是在夜间) 捕捉最佳动态图像。
  • FACE RETOUCH (脸部照片修复) : 拍摄动态图像时,润饰脸部肤色、轮廓等。
  • AUTO (主动) : 依据四周的风景主动调整最终图像。

咱们来看看如何应用 CameraX Extensions API:

// 获取后置相机列表
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

// 查看所有的后置相机中是否有反对焦外虚化
if (extensionsManager.isExtensionAvailable(
    cameraProvider,
    cameraSelector,
    ExtensionMode.BOKEH
)) {
    // 创立扩大 cameraSelector,咱们提供了相机并指定焦外虚化模式
    // 它将开始在后盾搜寻反对焦外虚化的后置相机
    val bokehCameraSelector = extensionsManager.getExtensionCameraSelector(
        cameraProvider,
        cameraSelector,
        ExtensionMode.BOKEH
    )

    // 创立 imageCapture 和 preview
    val imageCapture = ImageCapture.Builder().builder()
    val preview = Preview.Builder().build()

    // 应用 bokehCameraSelector 将它们绑定到生命周期
    cameraProvider.bindToLifecycle(lifecycleOwner,
        bokehCameraSelector,
        imageCapture,
        preview
    )
}

△ 以 BOKEH 成果捕获并预览图像

在下面的例子中,imageCapture 输入的图像将会具备焦外虚化成果,如果设施反对的话,preview 也将预览焦外虚化成果。

如需具体理解,请参阅咱们之前的推文《应用 CameraX Extensions API 将特效利用到照片上》。

曝光弥补

CarmeraX 1.1 中还增加了曝光弥补 API,此性能能够帮忙用户更好地捕获适度曝光或者曝光有余的区域。

如图所示咱们所处的场景窗外很亮堂而室内很暗淡,此时则能够调整曝光弥补来更好地捕获亮堂的室外或暗淡的室内场景。咱们来看一个例子:

// 创立变量来跟踪 exposureIndex 值
var exposureIndex = 0
// 应用 cameraSelector 将 imageCapture 和 preview 绑定到生命周期
val camera = cameraProvider.bindToLifecycle(
    lifecycleOwner,
    getCameraSelector(),
    preview,
    imageCapture
)
 
// 为视图中的按钮增加点击事件
evButton.setOnclickListener {
 
    // 查看无效的范畴以避免可能的异样
    val range = camera.cameraInfo.exposureState.exposureCompensationRange
 
    if (range.contains(exposureIndex + 1)) {// 调用 camera.cameraControl 的 setExposureCompenstation() 办法来设置曝光弥补
        camera.cameraControl.setExposureCompenstation(++exposureIndex)
        // 应用 exposureCompensationStep 来实现从 index 到 EV 到转换
        val ev = camera.cameraInfo.exposureState.exposureCompensationStep.toFloat() * exposureIndex
        Log.i("CameraXLog", "EV: $ev")
    }
}

△ 通过按钮调整曝光

其中 exposureIndex 是一个与设施无关的数字,它将以硬件容许的最小步长递增或递加曝光值,因而能够在不同的设施上以相似的形式运作。如果您想向用户展现 EV 值,能够获取 exposureCompensationStep 来实现转换。

如需理解 CameraX 中曝光弥补 API 的利用背景和调用办法,请参阅咱们之前的推文《CameraX 曝光弥补 API 入门指南》。

平滑缩放

在 CameraX 1.1 中,咱们还减少了平滑缩放性能。有一些设施有包含广角和长焦在内的多个镜头,CameraX 能够检测这些设施是否反对 SMOOTH_ZOOM 框架,在受反对的设施上应用 CameraX 的缩放控件时,会主动应用所有的相机来实现更大的缩放范畴。如果您曾经在应用这个缩放控件,那当您应用 1.1 版本进行编译时,您的利用应该就能够拜访这些设施上的所有相机。

CameraX 1.1 的更多功能

接下来介绍咱们在 1.1 中增加的更多功能。

CameraState API 当初能够提供诸如另一个利用正在应用相机或者正处于勿扰模式等更多无关相机状态的信息,使得利用可能围绕不同的相机工夫来设计更好的界面和用户体验流程。Image Analysis 当初能够提供超过 1080p 的图像。Logging API 能够更具体的调试日志并改善了错误报告。Coordinate Transformation API 能够将不同用例间的坐标关联起来,如果您在 imageAnalysis 缓冲区中定位了趣味点,便能够不便地在图像捕获的输入或预览中轻松找到它。您能够应用 CameraFilter API 来指定具体的规定以抉择适合的相机。如果利用只须要前置或者后置相机,能够应用 AvailableCamerasLimiter 来放慢启动工夫。CameraControllerInfo 中可提供相机性能的更多详细信息。

设施兼容性

CameraX 会继续关注设施兼容性,以便利用在泛滥设施上都可能良好运行。咱们修复了很多诸如图像拉伸、缩放不正确、图像颠倒及敞开相机时意外输入了绿色图形等问题。每个 CameraX 的公布版本或补丁版本中都会增加此类修复,最新的稳定版为 1.0.2。

您能够在 版本记录 中看到每个版本中的具体变更,还能够在 问题跟踪器 中看曾经修复的问题。

更多信息

  • CameraX 概览
  • CameraX 应用入门 Codelab
  • CameraX Github 样例代码
  • Android CameraX 讨论组

心愿对 CameraX 1.1 版本的简要介绍对大家有所帮忙,十分期待看到大家应用 CameraX 构建的性能!

欢迎您 点击这里 向咱们提交反馈,或分享您喜爱的内容、发现的问题。您的反馈对咱们十分重要,感谢您的反对!

退出移动版