최근 Instagram에서 사용자가 야간 모드를 사용하여 멋진 저조도 사진을 찍을 수 있도록 지원하는 방법 을 공유했습니다. 이 기능은 여러 노출을 결합하여 고품질의 정지된 사진을 만들 시간이 있는 정지 이미지에 적합합니다. 하지만 사진 사이에 발생하는 순간은 어떻게 해야 할까요? 사용자는 셔터 버튼을 누르는 순간뿐만 아니라 카메라와 더 많이 상호작용해야 합니다. 또한 미리보기를 사용하여 장면을 구성하거나 QR 코드를 스캔합니다.
오늘은 실시간 카메라 스트림을 밝게 하도록 설계된 강력한 기능인 어두운 조명 모드 (LLB)에 대해 알아보겠습니다. 정지된 캡처 지속 시간이 필요한 야간 모드와 달리 어두운 조명 모드는 실시간 미리보기 및 동영상 녹화에서 즉시 작동합니다. LLB는 사용 가능한 조명에 따라 필요한 밝기 조정량을 자동으로 조정하므로 모든 환경에 최적화되어 있습니다.
최근 업데이트를 통해 LLB를 사용하면 Instagram 사용자가 완벽한 사진을 촬영할 수 있으며 기존 야간 모드 구현을 통해 사용자가 1년 넘게 즐겨온 것과 동일한 고품질 저조도 사진을 얻을 수 있습니다.
실시간 밝기가 중요한 이유
야간 모드는 최종 이미지 품질을 개선하는 것을 목표로 하는 반면 어두운 조명 모드는 어두운 환경에서의 유용성과 상호작용을 위한 것입니다. 고려해야 할 또 다른 중요한 요소는 매우 잘 작동하지만 LLB와 야간 모드를 독립적으로 사용할 수 있으며 이러한 사용 사례 중 일부에서 야간 모드 사진이 필요하지 않은 경우 LLB가 자체적으로 가치를 지닌다는 것을 알 수 있다는 것입니다. 다음은 LLB가 사용자 환경을 개선하는 방법입니다.
- 더 나은 프레임 및 캡처: 조명이 어두운 장면에서는 표준 카메라 미리보기가 완전히 검은색일 수 있습니다. LLB는 뷰파인더를 밝게 하여 사용자가 셔터 버튼을 누르기 전에 실제로 프레임을 구성하는 내용을 볼 수 있도록 합니다. 이 환경에서는 야간 모드를 사용하여 최상의 저조도 사진 결과를 얻거나 LLB를 사용하여 사용자에게 '보이는 대로 얻는' 사진 결과를 제공할 수 있습니다.
- 안정적인 스캔: QR 코드는 어디에나 있지만 어두운 레스토랑이나 주차장에서 스캔하는 것은 종종 답답합니다. 카메라 피드가 훨씬 밝아지면 스캔 알고리즘이 매우 어두운 환경에서도 QR 코드를 안정적으로 감지하고 디코딩할 수 있습니다.
- 향상된 상호작용: 실시간 동영상 상호작용 (예: AI 어시스턴트 또는 영상 통화)과 관련된 앱의 경우 LLB는 인식 가능한 정보의 양을 늘려 컴퓨터 비전 모델이 작업할 수 있는 충분한 데이터를 확보하도록 합니다.
Instagram의 차이점
Android Instagram 앱을 지원하는 엔지니어링팀은 항상 사용자에게 최첨단 카메라 환경을 제공하기 위해 노력하고 있습니다. 위의 예에서 Pixel 10 Pro에서 LLB가 얼마나 큰 차이를 만드는지 확인할 수 있습니다.
이것이 사용자 환경에 어떤 차이를 가져오는지 쉽게 상상할 수 있습니다. 사용자가 캡처하는 내용을 볼 수 없는 경우 캡처를 포기할 가능성이 높습니다.
구현 선택
어두운 조명 모드를 구현하여 가장 광범위한 기기에서 최상의 환경을 제공하는 방법은 두 가지가 있습니다.
- 어두운 조명 모드 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는 장면을 분석하고 노출 시간 증가를 포함하여 센서 및 처리 매개변수를 조정하여 이미지를 밝게 합니다. 디지털 센서 게인 (ISO)을 늘리는 대신 노출 시간을 늘리면 센서가 더 많은 조명 정보를 캡처할 수 있으므로 신호 대 노이즈 비율 (SNR)이 크게 개선된 프레임을 생성할 수 있습니다.
이점:
전용 하드웨어 경로를 활용하므로 이미지 품질과 전력 효율성이 잠재적으로 더 좋습니다.
절충안:
센서가 조명을 캡처하는 데 더 많은 시간이 필요하므로 매우 어두운 조건에서 프레임 속도가 낮아질 수 있습니다. 매우 어두운 조명 조건에서는 프레임 속도가 10FPS까지 떨어질 수 있습니다.
Google 어두운 조명 모드 (Google Play 서비스를 통한 소프트웨어)
메커니즘:
Google Play 서비스를 통해 선택적 모듈로 배포되는 이 솔루션은 카메라 스트림에 후처리 작업을 적용합니다. HDRNet이라는 정교한 실시간 이미지 개선 기술을 사용합니다.
Google HDRNet:
이 딥 러닝 모델은 낮은 해상도로 이미지를 분석하여 압축된 매개변수 집합 (양방향 그리드)을 예측합니다. 그런 다음 이 그리드는 GPU에서 전체 해상도 이미지의 효율적이고 공간적으로 다양한 개선을 안내합니다. 이 모델은 얼굴 가시성에 중점을 두고 저조도 조건에서 이미지 품질을 밝게 하고 개선하도록 학습됩니다.
프로세스 오케스트레이션:
HDRNet 모델과 관련 로직은 어두운 조명 모드 프로세서에 의해 오케스트레이션됩니다. 여기에는 다음이 포함됩니다.
- 장면 분석:
카메라 메타데이터 (센서 감도, 노출 시간 등)와 이미지 콘텐츠를 사용하여 실제 장면 밝기를 추정하는 맞춤 계산기입니다. 이 분석은 부스트 수준을 결정합니다. - HDRNet 처리:
HDRNet 모델을 적용하여 프레임을 밝게 합니다. 사용된 모델은 저조도 장면을 위해 조정되고 실시간 성능에 최적화되어 있습니다. - 혼합:
원본 프레임과 HDRNet 처리된 프레임이 혼합됩니다. 적용되는 혼합량은 장면 밝기 계산기에 의해 동적으로 제어되어 부스트된 상태와 부스트되지 않은 상태 간에 원활한 전환을 보장합니다.
이점:
특정 HAL 지원이 필요하지 않고 더 광범위한 기기에서 작동합니다 (현재 Samsung S22 Ultra, S23 Ultra, S24 Ultra, S25 Ultra, Pixel 6~Pixel 9 지원). 후처리 효과이므로 카메라의 프레임 속도를 유지합니다.
절충안:
후처리 방법이므로 품질은 센서에서 제공하는 프레임에 있는 정보에 의해 제한됩니다. 센서 수준에서 극도의 어둠으로 인해 손실된 세부정보는 복구할 수 없습니다.
어두운 조명 모드는 하드웨어 및 소프트웨어 경로를 모두 제공하여 Android 생태계 전반에서 저조도 카메라 성능을 개선하는 확장 가능한 솔루션을 제공합니다. 개발자는 사용 가능한 경우 AE 모드를 우선시하고 Google 어두운 조명 모드를 강력한 대체 솔루션으로 사용해야 합니다.
앱에서 어두운 조명 모드 구현
이제 두 가지 LLB 제품을 구현하는 방법을 살펴보겠습니다. 앱에서 CameraX 또는 Camera2를 사용하는지 여부에 관계없이 다음을 구현할 수 있습니다. 최상의 결과를 얻으려면 1단계와 2단계를 모두 구현하는 것이 좋습니다.
1단계: 어두운 조명 모드 AE 모드
Android 15 이상을 실행하는 일부 기기에서 사용할 수 있는 LLB AE 모드는 특정 자동 노출 (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를 설정하여 UI를 업데이트하거나 (예: 달 아이콘 표시) 확장 함수 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에서는 Preview.Builder를 Camera2Interop.Extender.setSessionCaptureCallback()으로 확장하여 이 작업을 실행할 수 있습니다.
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 Emulator를 사용하여 다중 기기 상호작용을 그 어느 때보다 쉽게 테스트할 수 있습니다.
Steven Jenkins • 2분 읽기
-
제품 소식
모든 개발자의 AI 워크플로와 요구사항은 고유하며 AI가 개발에 어떻게 도움이 되는지 선택할 수 있는 것이 중요합니다. 1월에 Android 스튜디오에서 AI 기능을 지원하는 로컬 또는 원격 AI 모델을 선택할 수 있는 기능을 도입했습니다.
Matthew Warner • 2분 읽기
-
제품 소식
이제 Android 스튜디오 Panda 3이 안정화되어 프로덕션에서 사용할 수 있습니다. 이 출시를 통해 AI 기반 워크플로를 더욱 세부적으로 제어하고 맞춤설정할 수 있으므로 그 어느 때보다 쉽게 고품질 Android 앱을 빌드할 수 있습니다.
Matt Dyor • 3분 읽기
소식 받아 보기
Android 개발 관련 최신 정보를 이메일로 받아 보세요. 매주