あらいさん日記(仮)

あらい日記

活動の記録

簡易分光器の製作

概要

透過型回折格子を使って簡易分光器を製作しました.製作した分光器を使って,ハロゲンランプと蛍光灯のスペクトルを撮影しました.

透過型回折格子による分光器 

透過型回折格子を使った分光器を下の図に示します.

f:id:raccoon15:20190220135205p:plain

透過型回折格子を使った分光器
回折格子

透過型回折格子は,格子周波数が500本/mmのフィルムをEdmund Opticsで購入しました.

回折格子はカメラのレンズの前に配置します.今回はステップアップリングに貼り付けてみました.

f:id:raccoon15:20190220002601j:plain

レンズに装着した回折格子
スリット

スリットの幅は小さいほどスペクトルの分解能がよくなります.

スリットの製作には,カッターナイフの刃を2枚を使いました.2枚の刃をコピー用紙に挟んで,スリット幅を調節しました.一般的なコピー用紙の厚さはだいたい0.10mmなので,そのくらいの幅のスリットが作れます.  

スペクトルの撮影

製作した分光器を使って光のスペクトルを撮影しました.ハロゲンランプと蛍光灯のスペクトルを撮影した結果を下の図に示します.

f:id:raccoon15:20190219234702p:plain

ハロゲンランプのスペクトル

f:id:raccoon15:20190219234706p:plain

蛍光灯のスペクトル

ハロゲンランプのスペクトルは連続スペクトルであることが確認できます.

蛍光灯のスペクトルでは,いくつかの輝線スペクトルを確認できます.

ランバート拡散反射を持つシーンに対するリライティング

概要

ランバート拡散反射を持つシーンの反射特性を測定することで,新たな光源が与えられた場合のシーンの画像を生成するリライティングを行いました.さらに,実シーンの光源分布を与えてイメージベーストライティングを行いました.

ランバート拡散反射面に対するリライティング

ランバート拡散反射面での明るさIは次式のように表せられます.

 I = \rho \boldsymbol{n} \cdot \boldsymbol{l}

\rhoは反射率,\boldsymbol{n}は法線,\boldsymbol{l}は光源ベクトルです. 

式より,反射率と法線が既知であれば,光源ベクトルが与えられた時の明るさが求まります.これを利用することで,新たな光源を設置したときのシーンの画像を生成(リライティング)することができます.

照度差ステレオ法

Woodhamの照度差ステレオ法を使うと,ランバート拡散反射面の法線と反射率の情報を獲得することができます.詳しくは以下の記事をご覧ください.

raccoon15.hatenablog.com

raccoon15.hatenablog.com

法線と反射率の測定

Woodhamの照度差ステレオ法を用いて,シーンの法線と反射率を測定しました.対象とする物体はイノシシの置物です.牙と目の部分に少し光沢があります.

f:id:raccoon15:20181227143756j:plain

対象物体

f:id:raccoon15:20181227143832j:plain

撮影の様子

測定によって得られた法線と反射率の画像です.

f:id:raccoon15:20181227145815p:plain
f:id:raccoon15:20181227145822p:plain
測定した法線と反射率

リライティングの結果

法線と反射率の情報から,単一の平行光源を設置した場合のシーンをリライティングした結果です. 


Lambertian Image Relighting

Reflectance Field

単一光源のリライティングだけではつまらないので,もう少し発展させてイメージベーストライティングを行います.

実シーンに対するイメージベーストライティングはDebevecらの手法が有名です.Debevecらは,light stageとよばれる装置を用いて,光源方向を変えながら撮影した複数の画像からreflectance fieldとよばれる反射光の分布を獲得しました.このreflectance fieldを用いることで,実物体に対してもイメージベーストライティングを行うことができます*1

ここで,シーンをランバート拡散反射を持つシーンに限定し,法線と反射率が既知であれば,light stageといった大型の装置を使わずにreflectance fieldを獲得することができます.

イメージベーストライティングの結果

法線と反射率からreflectance fieldを計算し,パノラマ画像を光源とした場合のイメージベーストライティングを行なった結果です.パノラマ画像の一部はこちらのものを使わせてもらってます.

f:id:raccoon15:20181225200722p:plain
f:id:raccoon15:20181227212624p:plain
f:id:raccoon15:20181225202259p:plain
f:id:raccoon15:20181227212632p:plain
f:id:raccoon15:20181225201318p:plain
f:id:raccoon15:20181227212639p:plain
f:id:raccoon15:20181227154725j:plain
f:id:raccoon15:20181227212655p:plain
ランバート拡散反射を持つシーンに対するイメージベーストライティング

*1:Paul Debevec, Tim Hawkins, Chris Tchou, Haarm-Pieter Duiker, Westley Sarokin, and Mark Sagar. Ac- quiring the Reflectance Field of a Human Face. In Proceedings of the 27th Annual Conference on Computer Graphics and Interactive Techniques, SIGGRAPH ’00, pages 145–156. ACM Press/Addison-Wesley Publish- ing Co., 2000.

POV-Rayによるイメージベーストライティング

概要

イメージベーストライティングの手法を用いて,合成画像に対してシーンに対する写実的な画像を生成しました.

イメージベーストライティング

実シーンの照明環境を計測して,それを仮想物体を描画する際に用いることで,写実的な画像を生成するという枠組みを,イメージベーストライティング(image-based lighting:IBL)とよびます. 

光源分布

シーン中にある遠方光源を表した関数を光源分布とよびます.光源分布の計測には,魚眼レンズを装着したカメラを用いる方法や,鏡面球などの較正用物体を用いる方法があります.鏡面球を用いて照明環境を記録した画像を,特にLight Probe画像とよびます*1

Light Probe画像についてはこちらをご覧ください.

raccoon15.hatenablog.com

撮影の際は広いレンジの明るさを記録するために,露出を変えた複数の画像を合成します.このような画像をHDR画像とよびます. 

POV-Rayにおける光源の設定

POV-RayではRadiance形式(拡張子".hdr")のHDR画像を天球(sky_sphre)に設定することで,遠方光源として扱うことができるようになります.

sky_sphere{
  pigment{
    image_map{ 
      hdr "panorama.hdr"
      map_type 1
      interpolate 2
    } 
  }
}

レンダリング

実際にPOV-Rayでイメージベーストライティングをやっていきます.

光源の設定に必要なHDR画像は以下のサイトにあるものを使わせてもらいました.こちらのサイトでは非常に高品質なHDRパノラマ画像を提供しています.

hdrihaven.com

ライティングする対象は下の図に示す物体です.中心にStanford dragonを配置し,周りには拡散球,鏡面急,ガラス球などを置いています,

f:id:raccoon15:20181225194612p:plain

対象物体

レンダリングの際にはラジオシティを使用しました.

Short Tunnelレンダリングした結果です.

f:id:raccoon15:20181225200722p:plain
f:id:raccoon15:20181225201224p:plain
レンダリング結果(Short Tunnel)

Skylit Garageレンダリングした結果です.

f:id:raccoon15:20181225202259p:plain
f:id:raccoon15:20181225201252p:plain
レンダリング結果(Skylit Garage)

The Sky Is On Fireレンダリングした結果です.

f:id:raccoon15:20181225201318p:plain
f:id:raccoon15:20181225201333p:plain
レンダリング結果(The Sky Is On Fire)

このように,イメージベーストライティングの手法を用いることで,シーンに対するフォトリアルな画像を生成することができました.

*1:Paul Debevec. Rendering Synthetic Objects into Real Scenes: Bridging Traditional and Image-based Graph- ics with Global Illumination and High Dynamic Range Photography. In Proceedings of the 25th Annual Conference on Computer Graphics and Interactive Techniques, SIGGRAPH ’98, pages 189–198. ACM, 1998.

鏡面球を用いたパノラマ画像の生成

概要

鏡面球は360°全ての方向のシーンが写り込んでいます(球自身によって隠れている領域を除いて).そこで,鏡面球を撮影してパノラマ画像を生成します.

鏡面球における反射

鏡面球において,入射光のベクトルを\boldsymbol{s},観測面からの視線ベクトルを\boldsymbol{v}とすると,鏡面球の単位法線ベクトル\boldsymbol{n}は次式のように表せられます.

\displaystyle \boldsymbol{n} = \frac{\boldsymbol{s}+\boldsymbol{v}}{\|\boldsymbol{s}+\boldsymbol{v}\|}

f:id:raccoon15:20181222171109p:plain

鏡面球での反射

変換の流れ

正距投影図形式のパノラマ画像に変換します.パノラマ画像の幅 \thetaを-180^ \circから180^ \circ,高さ \phiを0^ \circから180^ \circとして,(\theta, \phi)方向の輝度を表すとします.鏡面球を撮影した画像はアスペクト比が1:1として,撮影した球の中心が原点とする単位円として表すとします.

f:id:raccoon15:20181221133022p:plain

鏡面球の画像からパノラマ画像への変換

このとき,入射光のベクトル\boldsymbol{s}は次式で表せられます. 

s_{x} = \sin (\phi) \sin(\theta)

s_{y} = \cos (\phi)

s_{z} = -\sin (\phi) \cos(\theta)

視線ベクトル\boldsymbol{v}(0, 0, -1)と表します.\boldsymbol{s}\boldsymbol{v}が定まったので,(\theta, \phi)方向の入射光に対応する球の単位法線ベクトル\boldsymbol{n}を求めることができます.

鏡面球の画像を単位円で表したので,単位法線ベクトルのx軸成分とy軸成分がそのまま,画像中の座標に対応します.これにより,パノラマ画像の座標と鏡面球の画像の座標の関係が定まるので,鏡面球の画像からサンプリングすればパノラマ画像に変換することができます.

鏡面球の撮影

鏡面球を対象とする場所に設置して撮影します.このとき,カメラのレンズは出来るだけ望遠である方が正射影モデルに近づけることができるので好ましいです.また,カメラを遠くに置いて撮影できるので,カメラ自身の映り込みも少なくて済みます.

f:id:raccoon15:20181222202334j:plain

撮影の様子

撮影した画像を適当な画像処理ソフトでアスペクト比が1:1になるように切り出します.

f:id:raccoon15:20181222202502j:plain

撮影した鏡面球

パノラマ画像への変換結果

先ほどの鏡面球の画像をパノラマ画像に変換した結果です.

f:id:raccoon15:20181222202506j:plain

パノラマ画像に変換した結果

画像の中央の領域はいい感じになってます.しかし,画像の端の方の領域は歪んでしまっています.この領域は撮影した球の端の領域に対応しています.

プログラム

鏡面球の画像からパノラマ画像に変換するプログラムをGitHubに置いておきます. 

github.com

スパース最適化によるボケ画像の復元

概要

カメラの焦点ボケや手ブレなどによって劣化した画像から,劣化の過程に基づいて元の画像を復元することができます.このような復元する処理のことをデコンボリューション(deconvolution)とよびます.画像が有するスパース性を先験情報として利用した,スパース最適化によって劣化した画像の復元をやってみました.

画像の劣化モデル

画素数N(=width \times height)とする劣化画像を\boldsymbol{b} \in \mathbb{R}^{N}とするとき,劣化の過程を次式で表すことができます.

\boldsymbol{b} = \boldsymbol{A} \boldsymbol{x} +\boldsymbol{n}

ここで,\boldsymbol{A} \in \mathbb{R}^{N \times N}は劣化の過程を表す行列,\boldsymbol{x} \in \mathbb{R}^{N}は元の画像,\boldsymbol{n} \in \mathbb{R}^{N}はノイズです.

f:id:raccoon15:20190107041043p:plain

画像の劣化過程

画像の復元

画像復元で有名な手法はウィーナフィルタ(Wienar filter)やLucy-Richardsonアルゴリズムがあります.Lucy-Richardsonアルゴリズムについては福嶋先生の解説記事がわかりやすいです.

qiita.com

スパース最適化による復元

一般的に自然な画像では,近傍の画素は同じような値をとります.そのため,微分フィルタなどで画像の勾配を計算すると,多くの領域でゼロに近い値になり,エッジが強い箇所のみが大きな値(非ゼロ)になります.このように,多くの要素がゼロでごく一部が非ゼロで構成されているデータをスパース性が有るといいます.

画像が有するスパース性を最適化問題に取り入れるために,全変動TV(Total Variation)がよく使われています.全変動は勾配の値の合計値を表しています.

TV(\boldsymbol{x}) = \underset{i, j}{\sum} \sqrt{|x_{i+1, j} - x_{i, j}|^{2} +|x_{i, j+1} - x_{i, j}|^{2}}

全変動を取り入れた,画像復元は次式のように定式化されます.

\underset{\boldsymbol{x}}{\min} \  \cfrac{1}{2}\|\boldsymbol{A} \boldsymbol{x} - \boldsymbol{b}\|^{2}_{2} + \lambda TV(\boldsymbol{x})

\text{subject to} \ \boldsymbol{x} \in [0, 255]^{N}

\lambdaは全変動の重みを決定する定数です.この最適化問題を解くことで,元の画像\boldsymbol{x}を推定します.

復元結果

劣化画像は,元の画像に対してガウシアンフィルタでぼかし,ノイズを加えて作りました.ノイズは正規分布に従い,平均を0,標準偏差を5としました.

最適化問題を解くために,凸最適化モデリングツールであるCVXPYを使いました.

\lambda = 0.4としたときの結果を下の図に示します.左上は元画像,右上は劣化画像,左下はLucy-Richardsonアルゴリズムによる復元結果,右下はスパース最適化による復元結果です.

f:id:raccoon15:20190108170359p:plain
f:id:raccoon15:20190108170405p:plain
f:id:raccoon15:20190108170414p:plain
f:id:raccoon15:20190108170410p:plain
(左上)元画像,(右上)劣化画像,(左下)LRアルゴリズムによる復元結果,(右下)スパース最適化による復元結果

LRアルゴリズムではボケは取り除かれていますが,ノイズが増幅されています.一方,スパース最適化ではボケを取りつつ,ノイズは抑えられています.ピーク信号対雑音比(PSNR)は劣化画像が26.9 dBであったのに対して,LRアルゴリズムによる復元結果は29.2 dB,スパース最適化による復元結果は33.2 dBとなりました.

次に,\lambda を0.05,0.4,5.0と変化させたときの,復元結果の違いを下の図に示します.

f:id:raccoon15:20190108180414p:plain
f:id:raccoon15:20190108170410p:plain
f:id:raccoon15:20190108180425p:plain
\lambdaの変化と復元結果.(左)\lambda=0.05,(中)\lambda=0.4,(右)\lambda=5.0

図より,\lambda が小さいとノイズが強調され,大きくなるとノイズが抑えられています.しかし,\lambda が大きいと細かいディテールが失われ,全体的にのっぺりとした絵になっています.

プログラム

CVXPYで画像の復元をするプログラムをGitHubに置いておきます. 

github.com

Focal Stackを用いたボケ量の操作

概要

 カメラのピント位置をずらしながら撮影した複数の画像である,Focal Stackを用いて,被写界深度の操作を行いました.被写界深度の操作を行うことで,撮影後に自由にボケ量を操作することができます.ボケ量は撮影の際にレンズの絞りを操作することでも実現できますが,合成することで物理的にはありえない絞り値で撮影したようなボケを再現できます.

被写界深度

 被写界深度(Depth of Field)とは,ピントを合わせた部分の前後のピントが合っているように見える範囲のことです.絞りを開いて撮影したボケが多い写真は被写界深度が浅く,逆に絞りを閉じて撮影した全面にピントが合うような写真ほど被写界深度が深い,と言います.特に,被写体深度を深くすることで,全面にピントが合ったようにした写真をパンフォーカスと言ったりします.被写界深度は絞り値の他に,焦点距離や撮影距離も関係します.

深度合成

 被写体の全てにピントが合ったような写真を獲得する手法として,深度合成があります.カメラのピント位置をずらしながら撮影した複数の画像(Focal Stack)を,合成することであたかも全ての面でピントがあったような画像を生成することができます.深度合成はいくつかソフトウェアが存在するので*1,それを使うと簡単に合成することができます.また,OLYMPUSのOM-D E-M1には「深度合成モード」というのがあり,カメラ内で深度合成ができるそうです *2.このように,ピント位置をずらした複数の画像を使うことで,全ての面にピントがあった画像を生成することができます. 

被写界深度の操作

 ピント位置をずらしながら撮影した複数の画像を使って合成することで,被写界深度を自由に操作することができるようになります.今回は,Jacobsらのテクニカルレポート*3を参考に実際のシーンの被写界深度の操作を行いました.

 被写界深度の操作方法について簡単に説明します.下の図は撮影した画像を合成するための手順です.

f:id:raccoon15:20181106134223j:plain

合成の手順

 まず,ピント位置をずらしながら撮影した入力画像(Image)から距離画像(Depth Map)を推定します.入力画像において,ボケがなく,もっともエッジが大きいとき,そのピクセルはピントが合っていると言えます.各入力画像に対してラプラシアンフィルタなどで勾配とり,勾配の大きさが最大になっているときにピントが合っているとして,距離と対応させることで距離画像を生成できます.

 次に距離画像(Depth Map)と入力画像のピント面の距離(Focus Distance)から,各入力画像のボケ量(Defocus Blur)を求めます.このボケ量Cは次式で表せられます.

C=\frac{f}{2N}(1-\frac{S}{\hat{S}})

f焦点距離Nは絞り値,Sは撮影した際のレンズの中心からセンサまでの距離,\hat{S}はピントが合う場合のレンズの中心からセンサまでの距離です.Sとレンズからピント面までの距離Zの関係は次式で表せられます.

\frac{1}{f} = \frac{1}{S} + \frac{1}{Z}

これらの式を用いることで,各入力画像のボケ量の大きさを求めることができます.

 任意のピント位置Z^*,絞り値N^*を入力して,合成のためのボケ量(Requested Defocus)を求めます.このボケ量は先ほど示したボケ量Cと類似の式を用いることで,算出することができます.

 最後に,Requested Defocusに一番近いDefocus Blurを選択することで,ユーザが入力したピント位置,絞り値の画像を合成することができます.

実験方法

 実験に使用したカメラはCanon EOS 6D,レンズはEF50mm F1.8 IIです.レンズは前回の記事で紹介した改造レンズで,フォーカスリングを自由な位置に回転させることができます.

raccoon15.hatenablog.com

 下の図に撮影の様子を示します.対象とするシーンはテクスチャの多い庭です.

f:id:raccoon15:20181106005856j:plain

撮影の様子

対象のシーンについて,無限遠から最短撮影距離までピント面を移動させて20枚の画像を撮影しました.絞りは開放絞り値であるf/1.8で撮影しました.

実験結果

 撮影した画像からの中から,手前の植物にピント面があるときの画像を下の図に示します.

f:id:raccoon15:20181106013000j:plain

撮影シーン(f/1.8)

被写界深度の操作を行い,合成を行った結果を示します.まず,パンフォーカス(|C^*|=0)の場合の合成結果です.図から,手前から奥まで全ての面でピントが合っている画像が得られていることがわかります.

f:id:raccoon15:20181106012828j:plain

合成結果(パンフォーカス)

次に,絞り値をf/5.6とした場合の合成結果です.絞りを大きくすると,被写界深度が深くなり,ボケの量が減ります.f/1.8で撮影したシーンの図と比べると,奥のボケが少し減っていることがわかります.

f:id:raccoon15:20181106012834j:plain

合成結果(f/5.6)

最後に,絞り値をf/1.0とした場合の合成結果です.f/1.0というのは,撮影に用いたレンズではありえない値ですが,合成することで実現できます.f/1.8で撮影したシーンの図と比べると,奥のボケが増えていることがわかります.

f:id:raccoon15:20181106012837j:plain

合成結果(f/1.0)

このように,複数のピント面の画像から被写界深度を自由に操作することができました. 

 合成の過程で生成した距離画像も示します.この画像は,手前ほど黒く,奥ほど白い色として表しています.日差しが差し込んで,白トビしている石の部分では,推定がうまくいっていないですが,他の部分は概ね良さそうです.

f:id:raccoon15:20181106012840j:plain

距離画像の推定結果

*1:Focus stacking - Wikipedia

*2:特別企画:「深度合成」がブツ撮りを変える! - デジカメ Watch

*3:JACOBS, D. E., BAEK, J., AND LEVOY, M. 2012. Focal stack compositing for depth of field control. In Stanford Computer Graphics Laboratory Technical Report

Arduinoで動かすEFレンズ

*レンズの改造には、レンズやカメラの故障といったリスクを伴います。当ブログの記事を利用することによって生じるいかなる損害についても、当ブログは一切の責任を負いかねます。

概要

Arduinoを使ってCanonのEFレンズを動かしてみました。レンズの電子接点にArduinoを接続して、信号を送ることでフォーカスリングを回転させたり、絞りの開閉を行うことができます。

電子接点

EFレンズおいて、レンズとカメラを電気的に接続している電子接点は7点あります。このうち、2点がレンズのモータの電源、5点がレンズ内のデジタルロジックの電源と通信線です。

f:id:raccoon15:20180922224930j:plain

EFレンズの電子接点のピンアサイン

SPI通信

レンズとの通信にはSPI通信を使います。 レンズにコマンドを送信することでレンズを動作させることができます。コマンドは下の表のようになります。

f:id:raccoon15:20180922194307p:plain

Canon EF-S Protocol and Electronic Follow Focus | Pick and Place

器具

使用するレンズはCanonのEF50mm F1.8 IIです。 レンズにコマンドを送信するマイコンArduino Uno R3です。

f:id:raccoon15:20180922164312j:plain

レンズの分解と電線の接続

レンズの電子接点とArduinoを接続しやすいように、レンズを少し改造します。

レンズ内の電子回路基板に手を加えれるように、電子接点がある側のネジを外して、フタをしている部品を外します。

f:id:raccoon15:20180922164315j:plain

f:id:raccoon15:20180922164319j:plain

 

次に、電線をレンズ内に入れるために、レンズの側面に穴を開けます。このとき、レンズ内の部品まで穴を開けないように注意します。

f:id:raccoon15:20180922164322j:plain

 

穴が開いたら、電線をレンズ内の電子回路基板にはんだ付けしていきます。リボンケーブルをめくると、基板とリボンケーブルがはんだ付けされている箇所があります。この箇所に電線をはんだで接続します。使用した電線は5本です。モータGND(P-GND)とロジックGND(D-GND)は電気的に繋がっているようなので1本にまとめています。また、レンズからカメラにデータを転送する信号線(DLC)は使わないので配線していません。

f:id:raccoon15:20180922164325j:plain

f:id:raccoon15:20180922164329j:plain

 

分解した部品を元に戻したら完成です。

f:id:raccoon15:20180922204530j:plain

Arduinoとの接続

EFレンズとArduinoを接続します。回路は下の図のようにしました。P-GNDとD-GNDはレンズ内部で接続しています。DLCはどこにも接続していません。レンズのモータには6Vの電源が必要なので、1.5Vの乾電池を4本使いました。

f:id:raccoon15:20180922212214j:plain

f:id:raccoon15:20180922164332j:plain

プログラム

ArduinoでEFレンズを動作させるためのプログラムを下に示します。このプログラムではレンズのフォーカスリングを回転させます。

#include<SPI.h>

void SPIWrite(byte cmd){
  SPI.transfer(cmd);
  delayMicroseconds(250);
}

void setup(){
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV128);
  delay(100);
}

void loop(){
  SPIWrite(0x05); //Turn focus ring to AF min
  delay(1000);
  SPIWrite(0x06); //Turn focus ring to AF max
  delay(1000);
}

結果

レンズのフォーカスリングを回転させることができました。


EF-Lens Control via Arduino

参考