OpenCV Python でHDR画像を合成してみよう
趣味全開です。趣味と実益とごっちゃになってきてます。
良いんだか悪いんだか。
Google PhotoのHDRレンダリング
Google PhotoにはHDRレンダリング機能があります。
feb29.org
つまりこんなかんじのこと。
これスマホの写真でやりたい!という記事になります。
追記:iPhoneを始め多くのカメラにはHDR機能が搭載されているそうな。知りませんでした…。
しかし以前手ブレの問題はあるのでかろうじて意義はあります。
以下説明
通常カメラが取る画像には明るさの幅に限界があって(ダイナミックレンジといいます)明るい所と暗い所を同時にきれいにとれないという問題が有ります。
結果、人間が見てきれいだと思う風景もカメラで取るとなんだか物足りない、ということになります。
そこで暗い画像と明るい画像を合成して人間が見た風景に近づけるのがこのHDRという技術です。
残念ながらGooglePhotoでは現状はスマホで取った画像ではHDR合成をしてくれないようです。
OpenCVにはHDR合成のサンプルコードがあるのでこれをうまく使って合成を試みてみようという試みになります。
OpenCV: High Dynamic Range (HDR)
レッツゴー!
1.手ぶれ補正
手で取るので必ずしも同じ画像とは限りませんね。このブレをなんとか補正したいです。
手ブレを微小回転と仮定し、SIFT特徴点を用いて回転を補正するコードを書けばいいんでなかろうか。
この論文とかそれっぽい。
A study on the compensation of image rotation for optical three-dimensional microscope - IEEE Conference Publication
追記1
OpenCV3ではSIFTが使えないのでAKAZEを使いました。
また,画像の変形はとりあえずホモグラフィー変換を用いましたがきちんとした式を建てると解くのが大変そうです。
これってちょっとした技術誌書けるんではないだろうか?
オプティカルフローからワープを推定してうまいこと処理する必要がありそうですがアイデアとしては既にどこかがやっているかと思われます。
追記2
訂正。並進要素のない微小回転とホモグラフィーワープは計算してみたら等価でした。
image stabilization(手ぶれ補正)で調べると結構関連記事が出てきます。
matlabの情報は古くAffineワープを使っていますが
Video Stabilization Using Point Feature Matching - MATLAB & Simulink
IEEEにもそれっぽい記事があります。うーん流石にちゃんと研究されていますね笑。
Video stabilization using classification-based homography estimation for consumer video camera - IEEE Conference Publication
ソース?
対応点から微小回転の射影変換行列を求めるmファイル。
三軸回転と焦点距離に関して式がでるので本当は4変数ですが線形方程式で解きたかったので5変数で解きます。ホモグラフィーの9変数より変数が少ないのでノイズには多少強いはず。ニッチなプログラムだなぁ。
function H = solveHomo_2(pts1,pts2) % H is 3*3, H*[pts1(:,i);1] ~ [pts2(:,i);1], H(3,3) = 1 % the solving method see "projective-Seitz-UWCSE.ppt" n = size(pts1,2); x1 = pts1(1,:)'; x2 = pts2(1,:)'; y1 = pts1(2,:)'; y2 = pts2(2,:)'; zero = zeros(n,1); one = ones(n,1); A = [zero,-one, y1, x2.*y1, -x2.*x1, x2-x1; one, zero, -x1, y2.*y1, -y2.*x1, y2-y1]; %[evec,fuga] = eig(A'*A); [U W V] = svd(A); evec = V(:,6); evec = evec/evec(end); H = [1 -evec(3) evec(2); evec(3) 1 -evec(1); -evec(5) evec(4) 1]; end
でもよく考えたら中心点がわからないから正規化もできないし、その分も未知変数にすると結局8変数を推定することになるので普通に射影変換を求めれば良いという結論になりうる…
2.レンダリング
これはOpenCVのソースみれば書けそうな気がします。あとで書く。
OpenCV: High Dynamic Range (HDR)
やるよ。
追記1
よくみたら露光時間とかいう要素がありました。
なるほど携帯のカメラではまだそこまでやってくれませんね。
ゆくゆくは輝度値からうまく推定すべきでしょうが割りと適当でもそれなりにうまくいくようです。
やってみた
元画像はこちら。
どうしても空などと一緒に撮るとこういうことになっちゃいます。