产品资讯

弱光增强功能可让实时摄像头画面更明亮

阅读用时:7 分钟
Donovan McMurray
开发者关系工程师

我们最近介绍了 Instagram 如何让用户使用夜间模式拍摄出色的弱光照片。此功能非常适合静态图片,因为有时间将多次曝光组合在一起,从而拍摄出高质量的静态照片。但是,照片之间的时刻呢?用户需要与摄像头互动,而不仅仅是按下快门按钮的那一刻。他们还会使用预览来构图或扫描二维码。

今天,我们将深入探讨弱光增强 (LLB)功能,这是一项强大的功能,旨在让实时摄像头画面更明亮。与需要保持静止拍摄时长的夜间模式不同,弱光增强功能可即时用于实时预览和视频录制。弱光增强功能会根据可用光线自动调整所需的亮度,因此针对每种环境都进行了优化。

通过最近的更新,Instagram 用户可以使用弱光增强功能来拍摄完美的照片,然后他们现有的夜间模式实现会拍摄出与用户一年多来一直使用的弱光照片相同的高画质照片。

实时亮度为何重要

夜间模式旨在提高最终图片质量,而弱光增强功能则旨在提高黑暗环境中的易用性和可交互性。另一个需要考虑的重要因素是,虽然弱光增强功能和夜间模式可以很好地协同工作,但您可以单独使用它们,并且您会发现,在某些用例中,当不需要夜间模式照片时,弱光增强功能本身就很有价值。以下是弱光增强功能如何改善用户体验:

  • 更好的取景和拍摄: 在光线昏暗的场景中,标准摄像头预览可能是漆黑一片。弱光增强功能可让取景器更明亮,让用户在按下快门按钮之前实际看到他们正在取景的内容。对于这种体验,您可以使用夜间模式来获得最佳质量的弱光照片,也可以让弱光增强功能为用户提供“所见即所得”的照片效果。
  • 可靠的扫描: 二维码无处不在,但在黑暗的餐厅或停车场中扫描二维码通常令人沮丧。借助明显更明亮的摄像头画面,扫描算法可以可靠地检测和解码二维码,即使在非常昏暗的环境中也是如此。
  • 增强的互动: 对于涉及实时视频互动(例如 AI 助理或视频通话)的应用,弱光增强功能会增加可感知的信息量,确保计算机视觉模型有足够的数据可供使用

Instagram 中的差异

LLB_IG_demo_white_background.gif

Android Instagram 应用背后的工程团队始终努力为用户提供最先进的摄像头体验。在上面的示例中,您可以看到弱光增强功能在 Pixel 10 Pro 上带来的差异。

lowlight.png

很容易想象这会对用户体验带来怎样的差异。如果用户无法看到他们正在拍摄的内容,那么他们放弃拍摄的可能性就会更高。

lowlight1.png

选择您的实现方式

您可以通过以下两种方式实现弱光增强功能,以便在最广泛的设备上提供最佳体验:

  1. 弱光增强 AE 模式: 这是一种硬件层自动曝光模式。它提供最高的质量和性能,因为它直接微调图像信号处理器 (ISP) 管道。请务必先检查此模式。
  2. Google 弱光增强功能: 如果设备不支持 AE 模式,您可以回退到 Google Play 服务提供的这种基于软件的解决方案。它会对摄像头画面应用后期处理,使其更明亮。作为一种纯软件解决方案,它可在更多设备上使用,因此这种实现方式有助于您在更多设备上使用弱光增强功能。

弱光增强 AE 模式(硬件)

机制
此模式在搭载 Android 15 及更高版本的设备上受支持,并且需要 OEM 在 HAL 中实现支持(目前在 Pixel 10 设备上提供)。它直接与摄像头的图像信号处理器 (ISP) 集成。如果您将 CaptureRequest.CONTROL_AE_MODE 设置为 CameraMetadata.CONTROL_AE_MODE_ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY,则摄像头系统会接管控制权。

行为
HAL/ISP 会分析场景并调整传感器和处理参数,通常包括增加曝光时间,以使图像更明亮。这可以生成信噪比 (SNR) 显著提高的帧,因为延长曝光时间(而不是增加数字传感器增益 (ISO))可让传感器捕获更多光线信息。

优势
由于它利用专用硬件路径,因此可能会提供更好的图片质量和电源效率。

缺点
在非常黑暗的条件下,可能会导致帧速率降低,因为传感器需要更多时间来捕获光线。在光线非常昏暗的条件下,帧速率可能会降至 10 FPS。

Google 弱光增强功能(通过 Google Play 服务提供的软件)

机制
此解决方案通过 Google Play 服务作为可选模块分发,会对摄像头画面应用后期处理。它使用一种名为 HDRNet 的复杂实时图像增强技术。

Google HDRNet
此深度学习模型会以较低的分辨率分析图像,以预测一组紧凑的参数(双边网格)。然后,此网格会引导 GPU 对全分辨率图像进行高效的、空间变化的增强。该模型经过训练,可在弱光条件下使图像更明亮并提高图片质量,重点是人脸可见性。

流程编排
HDRNet 模型及其随附的逻辑由弱光增强处理器编排。其中包括:

  1. 场景分析:
    一种自定义计算器,使用摄像头元数据(传感器灵敏度、曝光时间等)和图像内容估算真实场景亮度。此分析会确定增强级别。
  2. HDRNet 处理:
    应用 HDRNet 模型来使帧更明亮。所使用的模型针对弱光场景进行了调整,并针对实时性能进行了优化。
  3. 混合:
    原始帧和 HDRNet 处理后的帧会混合在一起。应用的混合量由场景亮度计算器动态控制,确保在增强状态和非增强状态之间平稳过渡。
low-light-boost-processor-diagram.png

优势
可在更广泛的设备上运行(目前支持 Samsung S22 Ultra、S23 Ultra、S24 Ultra、S25 Ultra 和 Pixel 6 到 Pixel 9),而无需特定的 HAL 支持。由于它是后期处理效果,因此会保持摄像头的帧速率。

缺点
作为一种后期处理方法,质量受传感器提供的帧中存在的信息的限制。它无法恢复因传感器级别的极度黑暗而丢失的细节。

弱光增强功能同时提供硬件和软件路径,为在整个 Android 生态系统中增强弱光摄像头性能提供可扩缩的解决方案。开发者应优先使用 AE 模式(如果可用),并将 Google 弱光增强功能用作可靠的回退方案。

在应用中实现弱光增强功能

现在,我们来看看如何实现这两种弱光增强功能。无论您在应用中使用 CameraX 还是 Camera2,都可以实现以下功能。为了获得最佳效果,我们建议您同时实现第 1 步和第 2 步。

第 1 步:弱光增强 AE 模式

弱光增强 AE 模式在搭载 Android 15 及更高版本的特定设备上提供,可作为特定的自动曝光 (AE) 模式运行。

1. 检查可用性

首先,检查摄像头设备是否支持弱光增强 AE 模式。

  val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)
val isLlbSupported = cameraInfo.isLowLightBoostSupported

2. 启用模式

如果支持,您可以使用 CameraX 的 CameraControl 对象启用弱光增强 AE 模式。

  // After setting up your camera, use the CameraInfo object to enable LLB AE Mode.
camera = cameraProvider.bindToLifecycle(...)

if (isLlbSupported) {
  try {
    // The .await() extension suspends the coroutine until the
    // ListenableFuture completes. If the operation fails, it throws
    // an exception which we catch below.
    camera?.cameraControl.enableLowLightBoostAsync(true).await()
  } catch (e: IllegalStateException) {
    Log.e(TAG, "Failed to enable low light boost: not available on this device or with the current camera configuration", e)
  } catch (e: CameraControl.OperationCanceledException) {
    Log.e(TAG, "Failed to enable low light boost: camera is closed or value has changed", e)
  }
}

3. 监控状态

仅仅请求该模式并不意味着它目前正在“增强”。系统仅在场景实际黑暗时才会激活增强功能。您可以设置一个 Observer 来更新界面(例如显示月亮图标),也可以使用扩展函数 asFlow() 转换为 Flow。

  if (isLlbSupported) {
  camera?.cameraInfo.lowLightBoostState.asFlow().collectLatest { state ->
    // Update UI accordingly
    updateMoonIcon(state == LowLightBoostState.ACTIVE)
  }
}

您可以点击此处阅读有关 弱光增强 AE 模式的完整指南

第 2 步:Google 弱光增强功能

对于不支持硬件 AE 模式的设备,Google 弱光增强功能可作为强大的回退方案。它使用 LowLightBoostSession 来拦截并增强画面。

1. 添加依赖项

此功能通过 Google Play 服务提供。

  implementation("com.google.android.gms:play-services-camera-low-light-boost:16.0.1-beta06")
// Add coroutines-play-services to simplify Task APIs
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.10.2")

2. 初始化客户端

在启动摄像头之前,请使用 LowLightBoostClient 确保模块已安装且设备受支持。

  val llbClient = LowLightBoost.getClient(context)

// Check support and install if necessary
val isSupported = llbClient.isCameraSupported(cameraId).await()
val isInstalled = llbClient.isModuleInstalled().await()

if (isSupported && !isInstalled) {
    // Trigger installation
    llbClient.installModule(installCallback).await()
}

3. 创建弱光增强会话

Google 弱光增强功能会处理每个帧,因此您必须将显示 Surface 提供给 LowLightBoostSession,它会返回一个应用了增强功能的 Surface。对于 Camera2 应用,您可以使用 CaptureRequest.Builder.addTarget() 添加生成的 Surface。对于 CameraX,此处理流水线最符合 CameraEffect 类,您可以在其中使用 SurfaceProcessor 应用效果,并使用 SurfaceProvider 将其返回给 Preview,如以下代码所示。

  // With a SurfaceOutput from SurfaceProcessor.onSurfaceOutput() and a
// SurfaceRequest from Preview.SurfaceProvider.onSurfaceRequested(),
// create a LLB Session.
suspend fun createLlbSession(surfaceRequest: SurfaceRequest, outputSurfaceForLlb: Surface) {
  // 1. Create the LLB Session configuration
  val options = LowLightBoostOptions(
    outputSurfaceForLlb,
    cameraId,
    surfaceRequest.resolution.width,
    surfaceRequest.resolution.height,
    true // Start enabled
  )

  // 2. Create the session.
  val llbSession = llbClient.createSession(options, callback).await()

  // 3. Get the surface to use.
  val llbInputSurface = llbSession.getCameraSurface()

  // 4. Provide the surface to the CameraX Preview UseCase.
  surfaceRequest.provideSurface(llbInputSurface, executor, resultListener)

  // 5. Set the scene detector callback to monitor how much boost is being applied.
  val onSceneBrightnessChanged = object : SceneDetectorCallback {
    override fun onSceneBrightnessChanged(
      session: LowLightBoostSession,
      boostStrength: Float
    ) {
      // Monitor the boostStrength from 0 (no boosting) to 1 (maximum boosting)
    }
  }
  llbSession.setSceneDetectorCallback(onSceneBrightnessChanged, null)
}

4. 传入元数据

为了使算法正常运行,它需要分析摄像头的自动曝光状态。您必须将拍摄结果返回给弱光增强会话。在 CameraX 中,可以通过使用 Camera2Interop.Extender.setSessionCaptureCallback() 扩展 Preview.Builder 来实现此目的。

  Camera2Interop.Extender(previewBuilder).setSessionCaptureCallback(
  object : CameraCaptureSession.CaptureCallback() {
    override fun onCaptureCompleted(
      session: CameraCaptureSession,
      request: CaptureRequest,
      result: TotalCaptureResult
    ) {
      super.onCaptureCompleted(session, request, result)
      llbSession?.processCaptureResult(result)
    }
  }
)

如需详细了解客户端和会话的实现步骤,请参阅 Google 弱光增强功能指南

后续步骤

通过实现这两个选项,您可以确保用户无论在何种光照条件下都能清晰地看到内容、可靠地扫描二维码并有效地互动。

如需查看这些功能在完整的、可用于生产用途的代码库中的实际效果,请查看 GitHub 上的 Jetpack Camera App。它实现了弱光增强 AE 模式Google 弱光增强功能,可供您参考以进行自己的集成。

作者:

继续阅读