我们最近分享了 Instagram 如何让用户使用夜间模式拍摄出令人惊艳的弱光照片。此功能非常适合拍摄静态图片,因为有足够的时间来组合多次曝光,从而拍摄出高质量的静态照片。但是,照片之间的时刻呢?用户与摄像头的互动不仅仅是按下快门按钮的那一刻。他们还会使用预览来构图或扫描二维码。
今天,我们将深入探讨弱光增强 (LLB)功能,这是一项旨在让实时摄像头画面更明亮的强大功能。与需要保持静止拍摄的夜间模式不同,弱光增强功能可即时用于实时预览和视频录制。LLB 会根据可用光线自动调整所需的亮度,因此针对每种环境都进行了优化。
通过最近的更新,Instagram 用户可以使用 LLB 拍摄出完美的照片,然后他们现有的夜间模式实现会拍摄出与用户一年多来一直享受的弱光照片相同的高质量照片。
实时亮度为何重要
夜间模式旨在提高最终图像质量,而弱光增强功能则旨在提高黑暗环境中的可用性和互动性。另一个需要考虑的重要因素是,虽然 LLB 和夜间模式可以很好地协同工作,但您可以独立使用 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 将其返回给 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. 传入元数据
为了使算法正常运行,它需要分析摄像头的自动曝光状态。您必须将拍摄结果返回给 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 Camera App。它实现了 LLB AE 模式 和 Google LLB,可供您参考以进行自己的集成。
继续阅读
-
产品资讯
在 Google Play,我们致力于为用户提供尽可能最佳的体验,同时确保开发者拥有成功所需的工具和适应能力。
Paul Feng • 阅读用时:3 分钟
-
产品资讯
去年,我们推出了 Android 开发者验证功能,以加强生态系统安全性,并阻止恶意方隐藏在匿名身份背后发布有害应用。
Matthew Forsythe • 阅读用时:2 分钟
-
产品资讯
从增强现实叠加层到完全沉浸式环境,Android XR 生态系统正在迅速扩展,Samsung Galaxy XR 今天已上市。
Stevan Silva, Vinny DaSilva • 阅读用时:3 分钟
随时了解最新动态
每周通过电子邮件接收最新的 Android 开发洞见 每周。