OpenCV-Python을 이용한 다중 노출 병합 기법

1. 개요

사진 및 컴퓨터 비전 분야에서 고동적 범위(HDR) 기술은 다양한 밝기 세부사항과 현실감 있는 이미지를 포착하는 데 핵심적인 역할을 합니다. 전통적인 카메라 센서와 디스플레이 장치는 자연계의 광량 범위를 완전히 포착하지 못해 이미지가 밝기 손실을 겪게 됩니다. 이 문제를 해결하기 위해 HDR 기술이 도입되었으며, 이는 여러 가지 노출 시간의 이미지를 융합하여 더 넓은 밝기 범위를 가진 이미지를 생성합니다. 본문에서는 다중 노출 병합 기법의 원리와 실제 구현 방법을 설명하며, Python 및 OpenCV 라이브러리를 사용한 구체적인 예시를 제공합니다.

2. 다중 노출 병합 방식

먼저 다수의 이미지를 리스트 형태로 처리하고, 이미지 내용과 노출 시간을 기반으로 카메라 응답 함수(CRF)를 계산합니다. 이 단계는 이후 이미지 융합에 필수적이며, 계산된 CRF를 통해 노출 시간이 다른 이미지를 병합하여 더욱 풍부한 세부사항을 갖는 이미지를 생성합니다. 마지막으로 컬러 매핑 기법을 적용하여 최종 이미지의 색상 표현력을 높입니다.

3. 알고리즘 구현 단계

3.1 이미지 및 노출 시간 로드


def load_images_with_exposures():
    """
    다수의 이미지와 대응되는 노출 시간을 로드합니다.

    1. 노출 시간 배열을 정의합니다.
    2. 파일 경로 목록을 설정합니다.
    3. 각 파일을 순차적으로 읽어 이미지 리스트에 저장합니다.
    4. 이미지 리스트와 노출 시간 배열을 반환합니다.
    """
    exposure_times = np.array([1/30.0, 0.25, 2.5, 15.0], dtype=np.float32)
    file_paths = ["D:/images/img09.jpg", "D:/images/img08.jpg", "D:/images/img04.jpg", "D:/images/img01.jpg"]
    image_data = []
    for path in file_paths:
        img = cv2.imread(path)
        image_data.append(img)
    return image_data, exposure_times

3.2 응답 곡선 계산 및 병합

카메라 응답 곡선(CRF)을 계산하는 과정은 다음과 같습니다:

  1. 다양한 노출 시간의 이미지 데이터를 분석하여 CRF 모델링
  2. CNF를 기반으로 이미지의 픽셀 값을 시나리오 밝기 값으로 변환
  3. 변환된 밝기 값을 가중 평균하여 노출 차이 조정
  4. 재구성된 밝기 값을 픽셀 값으로 매핑하여 HDR 이미지 생성

calibrator = cv2.createCalibrateDebevec()
crf_model = calibrator.process(image_data, exposure_times)
merger = cv2.createMergeDebevec()
hdr_image = merger.process(image_data, exposure_times, crf_model)

3.3 색조 매핑

주요 매핑 기법은 다음과 같습니다:

  • Drago 매핑: 인지 기반 알고리즘으로 어두운 영역의 세부사항을 강조
  • Reinhard 매핑: 글로벌 명암비 압축을 통한 자연스러운 밝기 조절
  • Mantiuk 매핑: 지역 명암비 유지와 홀로우 효과 방지 기능

tonemapper_drago = cv2.createTonemapDrago(1.0, 0.7)
ldr_drago = tonemapper_drago.process(hdr_image) * 3
cv2.imwrite("ldr-Drago.jpg", ldr_drago * 255)

tonemapper_reinhard = cv2.createTonemapReinhard(1.5, 0, 0, 0)
ldr_reinhard = tonemapper_reinhard.process(hdr_image)
cv2.imwrite("ldr-Reinhard.jpg", ldr_reinhard * 255)

tonemapper_mantiuk = cv2.createTonemapMantiuk(2.2, 0.85, 1.2)
ldr_mantiuk = tonemapper_mantiuk.process(hdr_image) * 3
cv2.imwrite("ldr-Mantiuk.jpg", ldr_mantiuk * 255)

4. 전체 코드 구현


import cv2
import numpy as np

def load_images_with_exposures():
    exposure_times = np.array([1/30.0, 0.25, 2.5, 15.0], dtype=np.float32)
    file_paths = ["D:/images/img09.jpg", "D:/images/img08.jpg", "D:/images/img04.jpg", "D:/images/img01.jpg"]
    image_data = []
    for path in file_paths:
        img = cv2.imread(path)
        image_data.append(img)
    return image_data, exposure_times

if __name__ == '__main__':
    print("이미지 로드 중...")
    images, times = load_images_with_exposures()
    
    calibrator = cv2.createCalibrateDebevec()
    crf_model = calibrator.process(images, times)
    merger = cv2.createMergeDebevec()
    hdr_image = merger.process(images, times, crf_model)
    cv2.imwrite("hdrDebevec.hdr", hdr_image)
    
    tonemapper_drago = cv2.createTonemapDrago(1.0, 0.7)
    ldr_drago = tonemapper_drago.process(hdr_image) * 3
    cv2.imwrite("ldr-Drago.jpg", ldr_drago * 255)
    
    tonemapper_reinhard = cv2.createTonemapReinhard(1.5, 0, 0, 0)
    ldr_reinhard = tonemapper_reinhard.process(hdr_image)
    cv2.imwrite("ldr-Reinhard.jpg", ldr_reinhard * 255)
    
    tonemapper_mantiuk = cv2.createTonemapMantiuk(2.2, 0.85, 1.2)
    ldr_mantiuk = tonemapper_mantiuk.process(hdr_image) * 3
    cv2.imwrite("ldr-Mantiuk.jpg", ldr_mantiuk * 255)

태그: OpenCV HDR ToneMapping python ImageProcessing

6월 7일 20:52에 게시됨