はじめに
スマホやデジカメで、夕暮れ、夜景、逆光、外光が差し込む暗い室内など、コントラストが強い環境で撮影すると、明るい部分が白くつぶれてしまったり、逆に、暗い部分が黒くつぶれてしまったりして、がっかりした経験はありませんか?
これは、明るい部分や暗い部分の階調が足りなくなってしまうためにおこる現象です。
今回は、明るい画像と暗い画像をいいとこどりで合成して、High Dynamic Range Imageを作ってみます。
環境
- OpenCV: 3.1.0
- Python: 3.5.2
これから環境構築をこちらを参考にしてください。
OpenCV 3とPython 3の環境構築
処理前の画像
露出を2段階づつ変えて撮影したJPEG画像が3枚。
綺麗に合成させるためには、カメラを固定して、絞りを同じにし、露光時間だけを変化させて、連続撮影するとよいです。
HDR処理後
OpenCVで処理した画像。
プログラム
# -*- coding: utf-8 -*-
import cv2
import numpy as np
# 3枚の画像ファイルを読み込む
img_fn = ["img1.jpg", "img2.jpg", "img3.jpg"]
img_list = [cv2.imread(fn) for fn in img_fn]
# 3枚の画像に対して露出時間をセット
exposure_times = np.array([0.2, 0.05, 0.0125], dtype=np.float32)
# Debevec法によるHDR合成
merge_debvec = cv2.createMergeDebevec()
hdr_debvec = merge_debvec.process(img_list, times=exposure_times.copy())
tonemap1 = cv2.createTonemapDurand(gamma=2.2)
res_debvec = tonemap1.process(hdr_debvec.copy())
# Robertson法によるHDR合成
merge_robertson = cv2.createMergeRobertson()
hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy())
tonemap2 = cv2.createTonemapDurand(gamma=2.2)
res_robertson = tonemap2.process(hdr_robertson.copy())
# Mertens法によるHDR合成
merge_mertens = cv2.createMergeMertens()
res_mertens = merge_mertens.process(img_list)
# 8ビットデータに変換
res_debvec_8bit = np.clip(res_debvec*255, 0, 255).astype('uint8')
res_robertson_8bit = np.clip(res_robertson*255, 0, 255).astype('uint8')
res_mertens_8bit = np.clip(res_mertens*255, 0, 255).astype('uint8')
# 画像をファイルに保存
cv2.imwrite("ldr_debvec.jpg", res_debvec_8bit)
cv2.imwrite("ldr_robertson.jpg", res_robertson_8bit)
cv2.imwrite("fusion_mertens.jpg", res_mertens_8bit)
写真の枚数が3枚、露出が-2, 0, +2の場合、次のようになります。
img_fn = ["img1.jpg", "img2.jpg", "img3.jpg"]
exposure_times = np.array([0.2, 0.05, 0.0125], dtype=np.float32)
写真の枚数が5枚、露出が-2, -1, 0, +1, +2だったら、この部分を次のように変更します。
img_fn = ["img1.jpg", "img2.jpg", "img3.jpg", "img4.jpg", "img5.jpg"]
exposure_times = np.array([0.2, 0.1, 0.05, 0.025, 0.0125], dtype=np.float32)
おわりに
今回、パラーメータ調整を一切しなかったMartens法で、迫力のある画像を合成することができました。他のサンプル画像〔1〕でもいろいろと試しましたが、3つの中では、Martens法が見た目に優れていました。
HDR関連の機能として、OpenCVにはトーンマップ調整用関数(Drago, Durand, Reinhard, Mantiuk)や、キャリブレーション用関数(Debevec, Robertson)なども用意されています。
OpenCVを使えば、自動でかなりよい合成ができることが分かったので、何かの際には活用したいと思います。