読者です 読者をやめる 読者になる 読者になる

まんぼう日記

takataka's diary

現実逃避に,例の場所の平均画像を合成してみる

2014年9月から何度も撮ってきた例の場所の景色の写真を重ね合わせて平均画像を作ってみました.最初におことわりしておきますが,綺麗な写真がでけたわけでも,学術的に面白い話になったわけでもありません (^^;  暇つぶし…ちゃうな,やらなあかん仕事はいっぱいあるから,現実逃避…(^^;;

 

使った画像は以下の通り.あ,最後の一枚,昨日撮った雪景色のやつは影響大きすぎるので除きました.

f:id:takatakamanbou:20150103163955j:plain f:id:takatakamanbou:20150103163956j:plain f:id:takatakamanbou:20150103163957j:plain f:id:takatakamanbou:20150103163958j:plain

f:id:takatakamanbou:20150103163959j:plain f:id:takatakamanbou:20150103164001j:plain f:id:takatakamanbou:20150103164000j:plain f:id:takatakamanbou:20150103164002j:plain

 

これらの写真を重ね合わせたいんですが,単純に画素値の平均をとると…

f:id:takatakamanbou:20150103170126j:plain f:id:takatakamanbou:20150103170122j:plain

こうなります(左).当然ですね.まともな重ね合わせをするためには,被写体の位置をあわせてやらないといけません.

 

が,それがなかなか一筋縄ではいかへん気配.各画像から局所的な特徴を抽出し,そのマッチングで,ってアプローチは(試してへんけど)無理っぽいです.ご覧のように画面のほとんどを空が占めてて,雲とか誤って対応付けしまくりそうやし.下の方の道路部分も,局所的に見たら相似な部分だらけで,やぱし誤対応付けまくりそうやし.

 

ほな完全自動化はあきらめて,手動で少数の特徴点を選択してってアプローチを考えてみても….きっちりとれそうな特徴点の候補が少ない上に,水平線の上下の狭い範囲からしか選べそうにないので,画像間を対応付ける変換のパラメータ推定で誤差でまくりそう.

 

まあそれでもまずはやってみよう,というわけで手動で特徴点の座標を拾ってみました.上記の右の写真のオレンジ色の丸で囲まれた所3カ所がその例です.ついでに,下の方の水色の箇所も,画像間で対応付くわけやないんやけど,試しに座標を読み取ってみました.

 

特徴点が3点取れたので(オレンジ色のんのことね),ある画像の座標 \( ( x_n, y_n ) \) の点と別の画像の座標 \( (X_n, Y_n) \) の点が対応するとして,両者の関係がアフィン変換

\[ \begin{pmatrix} X_n \\ Y_n \end{pmatrix} = A \ \begin{pmatrix} x_n \\ y_n \\ 1\end{pmatrix} \qquad (n = 1, 2, 3 ) \]

で表せると仮定すれば,その変換パラメータすなわち \( 2\times 3 \) 行列 \( A \) を求めることができます(未知数が \( 2\times 3 = 6 \) 個やから,3点あれば方程式が6本得られて解が一意に求まる,ちゅうこと).というわけで,7枚の画像のそれぞれについて,3つの対応点の座標を \( (x_n, y_n) \),「正しい座標」を \( (X_n, Y_n) \) として行列 \( A \) を推定し,これを用いて正しい位置にあわせた画像を求めます.「正しい座標」は,7枚の画像の特徴点のx座標y座標それぞれの中央値としました.

 

で,結果はこの通り.

f:id:takatakamanbou:20150103170131j:plain f:id:takatakamanbou:20150103170124j:plain

左は,7枚中1枚目の画像の3つの特徴点が「正しい座標」になるように変換した画像.右は,同じことを7枚それぞれでやって,それらの画素値の平均をとったもの.単純平均よりはずっとましですが,まだまだです.

 

ちなみに,Python + Numpy + OpenCV を使い,アフィン変換のパラメータ推定には

Geometric Image Transformations — OpenCV 2.4.9.0 documentation

の getAffineTransform を,画像の変換には warpAffine を用いました.

 

どうにか改良したいので,無理矢理透視変換( Perspective Transform )してみます.3点で推定できたアフィン変換と違い,こちらは4点必要です.仕方ないので,上記の水色の点も使いました(上述のようにこちらは明らかに画像間で対応してませんが…無理矢理 (^^; ).

 

Camera Calibration and 3D Reconstruction — OpenCV 2.4.9.0 documentation

の findHomography を用いると,4点以上の対応点の座標からロバストに透視変換のパラメータを推定したりできるので,水色の2点を加えた5点でやってみました(ほんとはもっとたくさん,画像のあちこちから特徴点がとれたときに使うような手法なんやけど).で,warpPerspective で画像を変換.

 

結果はこちら.

f:id:takatakamanbou:20150103170132j:plain f:id:takatakamanbou:20150103170125j:plain

2枚の画像の意味は,アフィン変換の時と同じです.水色の点のせいで,ずいぶんと上底の短い台形に変換されちゃってます.撮影位置が前後にずれてて全然対応してない所を無理矢理対応付けようとして,こんなんなってしもたんでしょう.あきませんな.

 

もうちょっとどうにかしたいなぁ,道路脇の直線を使うとかかなぁ,とかいろいろ考えましたが,だんだん凝った方法考えるようなやる気なくなってきました.そもそも現実逃避やったしー(現実逃避からも逃避しはじめた (^^;).

 

ちゅうことで,3つの特徴点のうち1つだけを使って,単純に各画像を平行移動して重ね合わせてみました.

f:id:takatakamanbou:20150103170129j:plain f:id:takatakamanbou:20150103170128j:plain f:id:takatakamanbou:20150103170130j:plain

左側の特徴点を合わせたもの,真ん中のを合わせたもの,右のを合わせたもの,の順です.変換には getRectSubPix を用いました.結構いけますな.想像通り,それぞれの特徴点付近はええ感じに合わさってます.

 

ほな,大域的な位置合わせはやめて,上の3枚をはり合わせてごまかしてみましょう.ただし,左の方の画素値は左の画像から,というように画素位置ごとに3枚のうち1枚の画素値を選択して代入する方法やと合わせ目が見えてまうから,画素位置ごとに3つの特徴点のうち近い方2点を求め,対応する2つの画素値を距離で按分した画素値を使うことにしました.つまり,左の特徴点と真ん中の特徴点を結ぶ線分を1:2に内分する位置にある画素には,上記の左と真ん中の画像のその位置の画素値を2:1で足し合わせた値を入れます(実際にはより単純に,x座標だけ使いました).

 

できた画像がこちら.

f:id:takatakamanbou:20150103170127j:plain f:id:takatakamanbou:20150103170133j:plain

左は,重ね合わせた結果そのまま.右は,画像の外側にはみ出した部分の影響を除くために,そこから周囲を除いたもの.まあこんなもんでしょうか.

 

現実逃避で半日つぶしてまいました.ありゃま.