我们最近分享了 Instagram 如何让用户使用夜间模式拍摄出色的低光照片。此功能非常适合拍摄静态图片,因为有足够的时间来组合多次曝光,从而拍摄出高品质的静态照片。但照片之间的瞬间呢?用户需要与相机互动,而不仅仅是在按下快门按钮的那一刻。他们还可以使用预览功能来构图或扫描二维码。
今天,我们将深入探讨 Low Light Boost (LLB),这是一项旨在提亮实时摄像头视频流的强大功能。与需要保持静止拍摄时长的夜间模式不同,“弱光增强”功能可立即在实时预览和视频录制中发挥作用。LLB 会根据可用光线自动调整所需的提亮程度,因此可针对各种环境进行优化。
通过最近的一次更新,LLB 允许 Instagram 用户拍摄完美的照片,然后通过现有的夜间模式实现,拍摄出与用户一年多以来一直享受的低光照照片一样的高质量照片。
实时亮度功能的重要性
夜间模式旨在提高最终图像质量,而弱光增强功能则旨在提高黑暗环境中的易用性和互动性。另一个需要考虑的重要因素是,尽管 LLB 和夜间模式可以很好地协同工作,但您也可以单独使用它们。在某些使用情形下,即使不需要拍摄夜间模式照片,LLB 本身也很有价值。以下是 LLB 如何改善用户体验:
- 更好的取景和拍摄效果:在光线昏暗的场景中,标准相机预览可能会漆黑一片。LLB 会调亮取景器,让用户在按下快门按钮之前能够清楚地看到取景范围。对于这种体验,您可以使用夜间模式来获得最佳的弱光照片效果,也可以让 LLB 为用户提供“所见即所得”的照片效果。
- 可靠的扫描功能:二维码随处可见,但在昏暗的餐厅或停车场中扫描二维码往往令人沮丧。借助明显更亮的摄像头画面,扫描算法可以可靠地检测和解码二维码,即使在非常昏暗的环境中也是如此。
- 增强互动:对于涉及实时视频互动的应用(例如 AI 助理或视频通话),LLB 可增加可感知的信息量,确保计算机视觉模型有足够的数据可供处理
Instagram 中的差异
Android Instagram 应用背后的工程团队一直在努力为用户提供最先进的相机体验。在上面的示例中,您可以直观地看到 LLB 对 Pixel 10 Pro 的影响。
不难想象,这会对用户体验带来怎样的变化。如果用户无法看到自己拍摄的内容,则更有可能放弃拍摄。
选择实现方式
您可以通过以下两种方式实现弱光增强功能,以便在尽可能多的设备上提供最佳体验:
- 弱光增强 AE 模式:这是一种硬件层自动曝光模式。它可直接对图像信号处理器 (ISP) 流水线进行微调,因此可提供出色的质量和性能。请务必先检查此项。
- 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 模型及其随附的逻辑由弱光增强处理器编排。其中包括:
- 场景分析:
一种自定义计算器,可使用相机元数据(传感器感光度、曝光时间等)和图像内容来估算真实的场景亮度。此分析用于确定提升级别。 - HDRNet 处理:
应用 HDRNet 模型来提亮帧。所用模型针对低光场景进行了调整,并针对实时性能进行了优化。 - 混合:
将原始帧和 HDRNet 处理后的帧混合在一起。应用混合的程度由场景亮度计算器动态控制,确保在增强状态和未增强状态之间平稳过渡。
优势:
可在更广泛的设备上使用(目前支持 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,可为您的自有集成提供参考。
继续阅读
-
产品资讯
我们很高兴地宣布,Android XR 现已正式支持 Unreal Engine 和 Godot。我们还推出了旨在提高您的工作效率并实现全新 XR 功能的新工具:Android XR Engine Hub 和 Android XR Interaction Framework。
Luke Hopkins • 阅读用时:4 分钟
-
产品资讯
随着 Android 17 的发布,我们正在向自适应优先开发标准过渡。您的用户不再依赖单一的设备形态,而是在一天中不断切换手机、可折叠设备、平板电脑、笔记本电脑、车载显示屏和沉浸式 XR 环境。
Fahd Imtiaz • 阅读用时:4 分钟
-
产品资讯
我们很高兴与您分享 Google TV 功能和开发者工具,这些功能和工具旨在提高您内容的发现率,并为您的应用做好准备,以迎接未来的电视体验。
Paul Lammertsma • 阅读用时:4 分钟
随时了解最新动态
每周通过电子邮件接收最新的 Android 开发洞见。