歪曲収差の実装
歪曲収差
レンズを通した光が,像となるときに歪んでしまう収差のことです。 大雑把に言えば魚眼レンズみたいな歪みです。
https://en.wikipedia.org/wiki/Distortion_(optics)
http://www.nikon-instruments.jp/jpn/learn-know/microscope-abc/learn-more-microscope/about-aberration
格子状のグリッドを撮影したときに,樽型に歪んだり(樽型),中央に収縮するように歪んだり(糸巻き型)します。
半径方向歪み
Brownのレンズ歪みモデルなるものがレンズ歪みを表すモデルとして使われることが多いようです。
https://www.asprs.org/wp-content/uploads/pers/1971journal/aug/1971_aug_855-866.pdf
http://www.roboken.iit.tsukuba.ac.jp/~ohya/pdf/Robomech2014-KNS.pdf
Brownのレンズ歪みモデルでは,レンズの光軸中心からの半径方向の歪みと,円周方向の歪みをわけて表現されますが, まずは半径方向歪みについて考えます。
光軸中心をとして,光軸中心からの像の位置をとします。 この時,歪んだ像の位置は,距離の2乗の多項式の展開で表せるとしたものが,多項式モデルと言うそうです。
一方,OpenCV等の画像処理ライブラリでは,カメラキャリブレーションに,有理関数モデルを利用しているようです。
http://opencv.jp/opencv-2svn/cpp/calib3d_camera_calibration_and_3d_reconstruction.html
https://www.robots.ox.ac.uk/~vgg/publications/2005/Claus05a/claus05a.pdf
他にも半径方向歪みのモデルには,有理関数モデルの特殊化として以外0としたDivisionModel
)http://www.robots.ox.ac.uk/~vgg/publications/papers/fitzgibbon01b.pdf) とか,
魚眼モデルとかFOVモデルといった多項式で表せないものもあります。
ちなみに,UnityのPostProcessingStackの歪曲収差は,樽型のときにFOVモデルを利用しているようなコードでした。
https://pdfs.semanticscholar.org/260d/bcca2edddeb7f743d186cc99a7d586023234.pdf
http://www.close-range.com/docs/Straight_Lines_Have_To_Be_Straight-Automatic_Calibration_and_Removal_of_Distortion--Devernay-Faugeras2001.pdf
今回はOpenCVのカメラキャリブレーションにも使われている実績や,計算の簡単さから4次までの有理関数モデルをレンズ歪みに利用することにします。
円周方向歪み
レンズによる光学的な歪みではなく,レンズとフィルムが完全に並行ではない場合に生じうる幾何学的な歪みが円周方向の歪みの項です。
この項の以降を無視して,先程のレンズ歪みモデルに組み込みます。
結果
歪曲収差の式をUVに適用してテクスチャのフェッチする位置を歪めることで実装します。
半径方向歪みが正の値の場合(UVフェッチ時逆転なので,本来の計算式的には負),歪みが外に膨らんで行くので樽型の歪曲収差を作れます。
歪曲収差 OFF |
歪曲収差 ON (樽型) |
---|
ただし,樽型の場合,画面内に元のテクスチャよりも外側のUVもフェッチされてしまうので,画面端の方が不正確なものになります。
そのため,歪曲収差を適用した後のUVを画面中心から拡大することで,見せたくない画面外側の範囲をクリップしても良いでしょう。
半径方向歪みが負の値の場合は,糸巻き型となります。
歪曲収差 OFF |
歪曲収差 ON (糸巻き型) |
---|
樽型と糸巻き型の歪みが組み合わさったものは陣笠型と呼びますが, これもパラメータの組み合わせで半径方向の歪みが距離によって正負入れ変えるような関数系をつくって再現できます。
円周方向の歪みのパラメータを与えると,画面自体が奥に傾いたような歪みを作り出すこともできます。
実装してみると,思っていたよりも画面端の違和感が強いので, 周辺減光や, 倍率色収差をかけると, よりレンズっぽく画面端をごまかせるかと思います。