이미지 분석 사용 사례에서는 이미지 처리, 컴퓨터 비전 또는 머신러닝 추론을 진행할 수 있도록 CPU에서 액세스 가능한 이미지를 앱에 제공합니다. 애플리케이션은 각 프레임에서 실행되는 analyze()
메서드를 구현합니다.
Google의 ML Kit를 CameraX 앱과 통합하는 방법은 ML Kit 분석 도구를 참고하세요.
작동 모드
애플리케이션의 분석 파이프라인이 CameraX의 프레임 속도 요구사항을 따라갈 수 없는 경우 다음 방법 중 하나로 프레임을 드롭하도록 CameraX를 구성할 수 있습니다.
비차단(기본값): 이 모드에서는 애플리케이션이 이전 이미지를 분석하는 동안 실행자가 항상 최신 이미지를 이미지 버퍼(깊이가 1인 큐와 유사)에 캐시합니다. 애플리케이션이 처리를 완료하기 전에 CameraX가 새 이미지를 수신하면 새 이미지가 동일한 버퍼에 저장되면서 이전 이미지를 덮어씁니다. 참고로,
ImageAnalysis.Builder.setImageQueueDepth()
는 이 시나리오와 별다른 관련이 없으며 버퍼 콘텐츠를 항상 덮어쓰게 됩니다.STRATEGY_KEEP_ONLY_LATEST
로setBackpressureStrategy()
를 호출하여 이 비차단 모드를 사용 설정할 수 있습니다. 실행자가 미치는 영향에 관한 자세한 내용은STRATEGY_KEEP_ONLY_LATEST
참조 문서를 확인하세요.차단: 이 모드에서는 내부 실행자가 내부 이미지 큐에 여러 개의 이미지를 추가할 수 있고, 큐가 가득 찬 경우에만 프레임을 드롭하기 시작합니다. 차단은 전체 카메라 기기 범위에서 이루어집니다. 즉, 카메라 기기에 결합된 사용 사례가 여러 개 있다면 CameraX가 이러한 이미지를 처리하는 동안 관련 사용 사례는 모두 차단됩니다. 예를 들어 미리보기와 이미지 분석이 모두 카메라 기기에 결합된 경우 CameraX가 이미지를 처리하는 동안 미리보기도 차단됩니다.
STRATEGY_BLOCK_PRODUCER
를setBackpressureStrategy()
에 전달하여 차단 모드를 사용 설정할 수 있습니다. ImageAnalysis.Builder.setImageQueueDepth()를 사용하여 이미지 큐 깊이를 구성할 수도 있습니다.
지연 시간이 짧고 고성능 분석 도구를 사용해 총 이미지 분석 시간이 CameraX 프레임의 기간(예: 60fps의 경우 16ms)보다 짧은 경우 어떤 작동 모드를 사용해도 전반적으로 매끄러운 환경이 제공됩니다. 아주 짧은 시스템 잡음을 처리할 때와 같은 일부 시나리오에서는 차단 모드가 여전히 유용할 수 있습니다.
지연 시간이 긴 고성능 분석 도구를 사용할 경우 지연 시간을 보완하려면 큐가 더 길게 설정된 차단 모드가 필요합니다. 하지만 애플리케이션에서 모든 프레임을 계속 처리할 수는 있습니다.
지연 시간이 길고 시간이 오래 걸리는 분석 도구(분석 도구에서 모든 프레임을 처리할 수는 없음)를 사용할 경우, 분석 경로를 위해 프레임을 드롭해야 하기 때문에 비차단 모드가 더 적합한 선택일 수 있습니다. 하지만 결합된 다른 동시 사용 사례에서 계속해서 모든 프레임이 인식될 수 있습니다.
구현
애플리케이션에서 이미지 분석을 사용하려면 다음 단계를 따르세요.
ImageAnalysis
사용 사례를 빌드합니다.ImageAnalysis.Analyzer
를 만듭니다.ImageAnalysis
로 분석 도구를 설정합니다.- 수명 주기 소유자, 카메라 선택기 및
ImageAnalysis
사용 사례를 수명 주기에 결합합니다.
결합되면 바로 CameraX에서 이미지를 등록된 분석 도구에 전송합니다.
분석을 완료한 후 분석을 중지하려면 ImageAnalysis.clearAnalyzer()
를 호출하거나 ImageAnalysis
사용 사례를 결합 해제합니다.
ImageAnalysis 사용 사례 빌드
ImageAnalysis
가 분석 도구(이미지 소비자)를 이미지 생산자인 CameraX에 연결합니다.
애플리케이션은 ImageAnalysis.Builder
를 사용하여 ImageAnalysis
객체를 빌드할 수 있습니다. 애플리케이션은 ImageAnalysis.Builder
를 사용하여 다음을 구성할 수 있습니다.
- 이미지 출력 매개변수:
- 형식: CameraX는
setOutputImageFormat(int)
를 통해YUV_420_888
및RGBA_8888
을 지원합니다. 기본 형식은YUV_420_888
입니다. - 해상도 및 가로세로 비율: 이 두 매개변수 중 어떤 것도 설정할 수 있지만, 두 값을 동시에 설정할 수는 없습니다.
- 회전
- 타겟 이름: 디버깅할 때 이 매개변수를 사용합니다.
- 형식: CameraX는
- 이미지 흐름 제어:
애플리케이션은 해상도 또는 가로세로 비율을 설정할 수 있지만 둘 다 설정할 수는 없습니다. 정확한 출력 해상도는 애플리케이션의 요청된 크기(또는 가로세로 비율)와 하드웨어 기능에 따라 다릅니다. 그리고 요청된 크기 또는 비율과 다를 수 있습니다. 해상도 일치 알고리즘에 관한 자세한 내용은 setTargetResolution()
문서를 참고하세요.
애플리케이션은 출력 이미지 픽셀을 YUV(기본값) 또는 RGBA 색상 공간 형식으로 구성할 수 있습니다. RGBA 출력 형식을 설정할 때 CameraX는 내부적으로 이미지를 YUV에서 RGBA 색상 공간으로 변환하고 다음 시퀀스를 사용하여 ImageProxy의 첫 번째 평면(다른 2개의 평면은 사용되지 않음)의 ByteBuffer
에 이미지 비트를 채웁니다.
ImageProxy.getPlanes()[0].buffer[0]: alpha
ImageProxy.getPlanes()[0].buffer[1]: red
ImageProxy.getPlanes()[0].buffer[2]: green
ImageProxy.getPlanes()[0].buffer[3]: blue
...
기기가 프레임 속도를 따라갈 수 없는 복잡한 이미지 분석을 실행할 경우 이 주제의 작동 모드 섹션에 설명된 전략을 활용해 프레임을 드롭하도록 CameraX를 구성할 수 있습니다.
분석 도구 만들기
애플리케이션은
ImageAnalysis.Analyzer
드림
인터페이스와 재정의를 사용하여
analyze(ImageProxy image)
각 분석 도구에서 애플리케이션은 Media.Image의 래퍼에 해당하는 ImageProxy
를 수신합니다.
이미지 형식은 ImageProxy.getFormat()
으로 쿼리할 수 있습니다.
형식은 애플리케이션이 ImageAnalysis.Builder
와 함께 제공하는 다음 값 중 하나입니다.
ImageFormat.RGBA_8888
(앱이OUTPUT_IMAGE_FORMAT_RGBA_8888
을 요청한 경우)ImageFormat.YUV_420_888
(앱이OUTPUT_IMAGE_FORMAT_YUV_420_888
을 요청한 경우)
색상 공간 구성과 픽셀 바이트를 가져올 수 있는 위치와 관련해서는 ImageAnalysis 사용 사례 빌드를 참고하세요.
분석 도구 내에서 애플리케이션은 다음을 실행해야 합니다.
- 가능한 한 빨리 주어진 프레임을 분석해야 합니다. 주어진 프레임 속도 시간 제한(예: 30fps 사례의 경우 32ms 미만) 내에서 하는 것이 좋습니다. 애플리케이션이 프레임을 빠르게 분석하지 못하는 경우 지원되는 프레임 드롭 메커니즘 중 하나를 사용하는 것이 좋습니다.
ImageProxy.close()
를 호출하여ImageProxy
를 CameraX에 해제해야 합니다. 래핑된 Media.Image의 close 함수(Media.Image.close()
)를 호출해서는 안 됩니다.
애플리케이션은 ImageProxy 내에서 래핑된 Media.Image
를 직접 사용할 수 있습니다.
래핑된 이미지에 Media.Image.close()
를 호출해서는 안 됩니다. CameraX 내의 이미지 공유 메커니즘이 중단되기 때문입니다. 대신 ImageProxy.close()
를 사용하여 기본 Media.Image
를 CameraX에 해제합니다.
ImageAnalysis를 위해 분석 도구 구성
분석 도구를 만든 후 분석을 시작하려면 ImageAnalysis.setAnalyzer()
를 사용하여 분석 도구를 등록합니다. 분석이 완료되면 ImageAnalysis.clearAnalyzer()
를 사용하여 등록된 분석 도구를 삭제하면 됩니다.
이미지 분석에는 활성 분석 도구를 하나만 구성할 수 있습니다. ImageAnalysis.setAnalyzer()
를 호출하면 이미 있는 등록된 분석 도구는 교체됩니다. 애플리케이션에서는 사용 사례 결합 전이나 후에 언제든지 새 분석 도구를 설정할 수 있습니다.
Lifecycle에 ImageAnalysis 결합
ProcessCameraProvider.bindToLifecycle()
함수를 사용하여 ImageAnalysis
를 기존 AndroidX 수명 주기에 결합하는 것이 좋습니다. bindToLifecycle()
함수는 선택된 Camera
기기를 반환하고, 반환된 기기는 노출 등의 고급 설정을 미세 조정하는 데 사용할 수 있습니다. 카메라 출력을 제어하는 방법은 이 가이드에서 자세히 알아보세요.
다음은 이전 단계의 모든 작업이 결합된 예로, CameraX ImageAnalysis
및 Preview
사용 사례를 lifeCycle
소유자에 결합하는 작업을 보여줍니다.
Kotlin
val imageAnalysis = ImageAnalysis.Builder() // enable the following line if RGBA output is needed. // .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy -> val rotationDegrees = imageProxy.imageInfo.rotationDegrees // insert your code here. ... // after done, release the ImageProxy object imageProxy.close() }) cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)
Java
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() // enable the following line if RGBA output is needed. //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(new Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build(); imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() { @Override public void analyze(@NonNull ImageProxy imageProxy) { int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees(); // insert your code here. ... // after done, release the ImageProxy object imageProxy.close(); } }); cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);
추가 리소스
CameraX에 관해 자세히 알아보려면 다음 추가 리소스를 참조하세요.
Codelab
코드 샘플