Loading [MathJax]/jax/output/CommonHTML/jax.js

10. Stereo Rectification

Stereo Rectificationとは

Stereo Rectificationは日本語ではステレオ平行化処理と言います. 右カメラと左カメラで撮影された右画像と左画像から 右カメラで撮影された右画像(これは元の右画像と同じ)と 同じ右カメラ(左カメラではありません)を左に平行移動(角度は変えないで)して 撮影した仮想的な左画像を得る処理です. この仮想的な左画像は元の左画像を変換することで得られます. 対象の3次元的な情報が全て分かっていない限り 任意の位置と角度から撮影した画像が得られる訳はありませんから, ステレオ並行化処理が可能というのは面白いことです. ステレオ並行化処理はステレオビジョンになくてはならない処理であり, 一方,ステレオビジョンは対象の3次元的な情報を求めることが目的であるわけですから, ステレオ並行化処理が可能ということは非常に重要なことです.あとで分かりますが 正確に左に移動して撮影した左画像とするには右画像にも変換が必要です.

座標系の変換

2つの3次元座標系OXYZoxyzとの間の変換を考えます. 2つの座標系は本来対等なのですが, ここではOXYZをワールド座標系またはグローバル座標系, oxyzをカメラに取り付けられたカメラ座標系としておきます. Ooは各々の原点を表しています. ベクトルは座標系に独立であるとして表現していきます.Oo=tと書くことにします.そうすると Pを空間上の点として OP=Oo+oP=t+oP=t+xe1+ye2+ze3 と表すことができます.ここでe1e2e3は座標系oxyzの基底ベクトルだとすると, P点の座標系oxyzでの座標は(x,y,z)となります. 一方,P点の座標系OXYZでの座標は(X,Y,Z)であるとします. ここで全てのベクトルを座標系OXYZによって成分表示することにすると, OP=(XYZ) となります.また t=(t1t2t3),e1=(e11e12e13),e2=(e21e22e23),e3=(e31e32e33) であるとします.そうすると OP=t+xe1+ye2+ze3 は成分表示では, (XYZ)=(t1t2t3)+(e11e12e13)x+(e21e22e23)y+(e31e32e33)z=(e11e21e31e12e22e32e13e23e33)(xyz)+(t1t2t3) となります.新しく X=(XYZ),x=(xyz),R1=(e11e21e31e12e22e32e13e23e33),t=(t1t2t3) と書くことにして (XYZ)=(e11e21e31e12e22e32e13e23e33)(xyz)+(t1t2t3)X=R1x+t と表します.RR1の逆行列だとして両辺に左から掛けると, RX=x+Rt となりますが,T=Rtと置いて x=RX+T と表します. XP点の座標系OXYZでの座標であり, xP点の座標系oxyzでの座標であることに注意して, 式(1)は 「座標系OXYZXRだけ回転させてTだけ平行移動した位置の座標系OXYZでの座標が座標系oxyzでのP点の座標となる」 と読みます.これが座標の変換の式です.これを成分表示で書いた (xyz)=(r11r12r13r21r22r23r31r32r33)(XYZ)+(T1T2T3)(xyz)=(r11r12r13T1r21r22r23T2r31r32r33T3)(XYZ1) と表現することができます.これを x=(R|T)˜X と書きます.˜XX1を追加したものという意味で,同次座標表現と言います. 同次座標(斉次座標とも言う)は無限遠点を扱うためのものだそうです. 今回の話に無限遠点は出てきませんので˜Xという書き方だけを使います. 同次座標を使うと座標系の変換が行列の積で表せるようになります.

座標系そのものの回転や平行移動がどうなっているかを考えたくなりますが, 回転行列や移動ベクトルがそもそも成分表示されていますのでけっこう面倒です. とりあえず座標系そのものの回転や平行移動は考えないことにします. また e1=(e11e12e13),e2=(e21e22e23),e3=(e31e32e33) は正規直交ベクトルですから ((e1)T(e2)T(e3)T)(e1e2e3)=(e11e12e13e21e22e23e31e32e33)(e11e21e31e12e22e32e13e23e33)=(100010001) となります.すなわち R=(e11e12e13e21e22e23e31e32e33)=(R1)T R1=(e11e21e31e12e22e32e13e23e33)=RT です.

カメラと透視変換

物体からの光が必ずピンホールを通過するピンホールカメラを考えます. このピンホールに3次元座標oxyzの原点oを合わせます. 次にf(0,0,f)oz軸と垂直に交わる平面を考えこれを撮像面と言うことにします. ただしfは正で,撮像面はピンホールと物体の間にあるものとします. f点は焦点とも言います. 実際のピンホールカメラでは撮像面はピンホールを挟んで物体とは反対側ですので これは式の見通しを良くするための仮想の配置です. f点を原点とする2次元のピクセル座標fuvを撮像面に置き, fu軸とox軸が平行になるように, fv軸とoy軸が平行になるようにします. このように2次元のピクセル座標fuvが配置された3次元座標oxyzをカメラ座標と言います.

物体上の点(x,y,z)から発せられた光が 撮像面の点(u,v)を通過するとき, x:z=u:fの関係がありますからu=fx/zとなります. ピクセル座標がピクセルを単位とするのであればピクセルサイズをpとしてu=fx/pzとなります. 同様にv=fy/pzです.これらを s(uv1)=(f/p000f/p0001)(xyz) と書きます.これは su=fx/p,sv=fy/p,s=z ということですから,第3式s=vを使うと,第1式はu=fx/pz,第2式はv=fy/pzとなるからです. また s(uv1)=(fx/p0cx0fy/pcy001)(xyz)su=fxx/p+cxz,sv=fyy/p+cyz,s=z ということですから,第3式s=vを使うと,第1式はu=fxx/pz+cx,第2式はv=fyy/pz+cyを表します. (cx,cy)は中心(oz軸と撮像面との交点)のピクセル座標です. これはピクセル座標の原点がoz軸からずれてしまった場合のためにあります. fx/pfy/pを新たにfxfyとして s(uv1)=(fx0cx0fycy001)(xyz) と表した場合,このfxfyはピクセルサイズを単位とする焦点距離です. 焦点距離にfxfyの2つがあるのはx方向とy方向で値が異なることがあるからです. またもともとcxcyはピクセルサイズを単位とする中央位置です. このカメラ座標系から撮像面のピクセル座標系への変換を透視変換と言います. ˜m=(uv1) は同次座標表現となっています.同次座標を使うと透視変換も行列の積で表現できてしまうわけです. 上のいくつかの式で出てきたsは任意のある実数で同次座標を使うと必要になります. 式(3)s˜m=Ax と書くことができます.Aはカメラ行列と言います. 前のパラグラフの式(1)と合わせて s˜m=A(RX+T) または前のパラグラフの式(2)と合わせて s˜m=A(R|T)˜X となります.これらの式はカメラの基本式と呼ばれます. カメラの基本式はグローバル座標系からピクセル座標系への変換, すなわち実世界がどのように撮影されるのかを表しています.

カメラの間の関係

ワールド座標系からカメラ座標系への変換を表す式(1)を左カメラ用と右カメラ用の2つ用意すると xl=RlX+Tl xr=RrX+Tr となります.式(6)の両辺に左からあるRを掛けると Rxl=RRlX+RTl となります.このRRr=RRlとなるRであったとすると,このことと式(7)を使って Rxl=RrX+RTl=xrTr+RTl xr=Rxl+TrRTl と変形できます.TrRTlを新たにTと置くと xr=RxlT となります.これは xlRだけ回転させてTだけ平行移動すればxrとなるということを表していますが, そのように言えるためには Rr=RRl Tr=RTlT の関係が必要ということです. ここでRTはカメラに写っているものの回転や平行移動で カメラそのものの回転や平行移動は考えないことにしたということに注意しておく必要があります. さてこれらと(8)は2つのカメラに写っているものが相対的にどのような位置関係にあるのかを表しています. あとで使うので(8)xl=R1(xr+T) と変形しておきます.

ステレオ並行化処理

カメラの基本式(5)を分離して書いた(4)(1)を 左カメラ用 sl~ml=Alxl xl=RlX+Tl と右カメラ用 sr~mr=Arxr xr=RrX+Tr に用意します. 式(10)の両辺に左からA1lを掛けて slA1l~ml=xl と変形して(9)を使うと slA1l~ml=R1(xr+T) となります.さらに(11)を使うと slA1l~ml=R1(RrX+Tr+T) と変形できます.両辺に左からRを掛けると slRA1l~ml=RrX+Tr+T となります.さらに両辺に左からArを掛けると slArRA1l~ml=Ar(RrX+Tr+T) となります. ~ml~˙ml=ArRA1l~ml によって変換した ~˙mlを使うと sl~˙ml=Ar(RrX+Tr+T) を得ることができます. これと右カメラの基本式 sr~mr=Ar(RrX+Tr) を比べてみると式(13)によって変換を受けた左ピクセル画像には 全く同じ右カメラのなかで対象がTだけ平行移動したときの投影画像が得られるということが分かります. さらにTを右カメラのox軸方向の移動とするために LT=c(er11er12er13)=b となる回転行列Lを考え(12)(14)の両辺に左から ArLA1rを掛けると slArLRA1l~ml=Ar(LRrX+LTr+b) srArLA1r~mr=Ar(LRrX+LTr) となってめでたくステレオ並行化が完了します. ピクセル変換は両方の画像で行う必要がありますが ~¨ml=ArLRA1l~ml ~¨mr=ArLA1r~mr と変換した 右画像~¨mr と 左画像~¨ml は あるカメラの撮影画像(右画像)とそのカメラが 正確にox軸方向にcだけ並行移動して撮影した画像(左画像)となっています. ここで初めてカメラそのものの平行移動というものを考えましたが, 写っているものがox軸方向にcだけ並行移動している状況は カメラがox軸方向にcだけ並行移動したために発生したと考えられるからです. またLにはox軸を回転軸とする任意に回転の分だけ自由度があることにも注意が必要です. 次に,この画像変換を行うOpenCVのinitUndistortRectifyMap関数について説明します.

initUndistortRectifyMap関数

OpenCVのinitUndistortRectifyMap関数の引数は

  • InputArray cameraMatrix
  • InputArray distCoeffs
  • InputArray R
  • InputArray newCameraMatrix
  • Size size
  • int m1type
  • OutputArray map1
  • OutputArray map2
となっています.左画像の変換である式(15)の変換では cameraMatrix=Al,distCoeffs=左カメラの歪係数,R=LR,newCameraMatrix=Ar とします. 右画像の変換である式(16)の変換では cameraMatrix=Ar,distCoeffs=右カメラの歪係数,R=L,newCameraMatrix=Ar とします.