产品资讯

使用低亮度增强功能提升实时摄像头画面的亮度

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

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

今天,我们将深入探讨 Low Light Boost (LLB),这是一项旨在提亮实时摄像头视频流的强大功能。与需要保持静止拍摄时长的夜间模式不同,“弱光增强”功能可立即在实时预览和视频录制中发挥作用。LLB 会根据可用光线自动调整所需的提亮程度,因此可针对各种环境进行优化。

通过最近的一次更新,LLB 允许 Instagram 用户拍摄完美的照片,然后通过现有的夜间模式实现,拍摄出与用户一年多以来一直享受的低光照照片一样的高质量照片。

实时亮度功能的重要性

夜间模式旨在提高最终图像质量,而弱光增强功能则旨在提高黑暗环境中的易用性和互动性。另一个需要考虑的重要因素是,尽管 LLB 和夜间模式可以很好地协同工作,但您也可以单独使用它们。在某些使用情形下,即使不需要拍摄夜间模式照片,LLB 本身也很有价值。以下是 LLB 如何改善用户体验:

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

Instagram 中的差异

LLB_IG_demo_white_background.gif

Android Instagram 应用背后的工程团队一直在努力为用户提供最先进的相机体验。在上面的示例中,您可以直观地看到 LLB 对 Pixel 10 Pro 的影响。

lowlight.png

不难想象,这会对用户体验带来怎样的变化。如果用户无法看到自己拍摄的内容,则更有可能放弃拍摄。

lowlight1.png

选择实现方式

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

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

弱光增强 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 弱光增强功能用作可靠的后备方案。

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

现在,我们来看看如何实现这两种 LLB 产品。无论您在应用中使用的是 CameraX 还是 Camera2,都可以实现以下步骤。为获得最佳效果,我们建议您同时实现第 1 步和第 2 步。

第 1 步:弱光增强 AE 模式

LLB AE 模式适用于搭载 Android 15 及更高版本的特定设备,是一种特定的自动曝光 (AE) 模式。

1. 查看是否有空房

首先,检查相机设备是否支持 LLB AE 模式。

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

2. 启用模式

如果支持,您可以使用 CameraX 的 CameraControl 对象启用 LLB 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. 创建 LLB 会话

Google LLB 会处理每个帧,因此您必须将显示 Surface 提供给 LowLightBoostSession,然后它会返回应用了调亮效果的 Surface。对于 Camera2 应用,您可以使用 CaptureRequest.Builder.addTarget() 添加生成的 Surface。对于 CameraX,此处理流水线最适合使用 CameraEffect 类,您可以使用 SurfaceProcessor 应用效果,并通过 SurfaceProvider 将其提供回预览,如以下代码所示。

// 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. 传入元数据

为了让该算法正常运行,它需要分析相机的自动曝光状态。您必须将拍摄结果传递回 LLB 会话。在 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 相机应用。它同时实现了 LLB AE 模式和 Google LLB,可为您的自有集成提供参考。

作者:

继续阅读