はじめに
以前クリスマスに書いたwebカメラ2台で距離測定の続きになります。
前回は一度距離を測定してから,近似式を求めることで,距離を逆算しました。
今回はカメラのセンサーサイズを考えてステレオ画像の視差から距離を求めてみます。
ステレオカメラ
三角測量
三角測量とは空間の1つの点を別々の地点から観測することで、その地点の位置が計算できるというものです。
対象の位置と視差は図のように反比例の関係になります。
そのため、比較的近い距離のオブジェクトに対してのみ高精度な測定が行えます。
もう一度ステレオカメラにおける距離の計算式を考えてみます。
上の図のような単純なステレオ装置を考えます。図の$c_{x}^{left}$および$c_{x}^{right}$は左右の画面であり、$x^l$および$x^r$は左右の画面上の対象Pです。
$O_l$と$O_r$は左右のカメラの主光軸で、カメラと対象$P$との距離を$Z$としています。
焦点距離を$f$カメラ間の距離を$T$とすると、上図のとき距離$Z$は次の式で求められます。
\frac{T-(x^{l}-x^{r})}{Z-f} = \frac{T}{Z} \Rightarrow Z = \frac{fT}{x^{l}-x^{r}}
このとき視差$d$は$d = x^{l}-x^{r}$で表されます。
ここで視差$d$の単位はピクセルですが、実際の単位はカメラの撮像素子間の距離です。そのため1画素の大きさを求めることができれば視差を距離に変換して$Z$を求めることができます。
撮像素子の大きさを求める
使用したlogicoolのUSBカメラは撮像素子の大きさは公開されていませんでした。
そこで、USBカメラを分解して直接撮像素子のサイズを測りました。
カメラの撮像素子の大きさは光学サイズとか光学インチサイズと言われ、1/3インチとか4/3インチというふうにある程度大きさが決まっています。
そのためバラして測れば分かるだろうと憶測のもとに分解して測ってみました。
バラして測った結果1/4サイズの撮像素子を使用していて、大きさは3.6[mm]x2.7[mm]でした。
カメラのキャプチャサイズは1280[pixel]x960[pixel]なので1画素あたりの大きさは2.8[μm/pixel]となります。
したがって距離$Z$をも求める式は次のようになります。
Z = \frac{fT}{2.8(x^{l}-x^{r})}
距離を測定してみる
画像処理の手順は前回と同じで
- カメラから画像を取得
- 色抽出&二値化
- 平滑化処理
- 対象の重心位置の推定
- 左右の画像から得られた対象の重心位置の差を求める
- 重心位置の差から距離を求める
画像処理にはOpenCVを、ラベリングと重心位置の検出にはラベリングクラスを用いました。
カメラのキャプチャサイズは1280x960じゃ大きすぎるので640x480にリサイズしてから処理をしています。
結果
測定された視差から距離を計算したものをグラフにしました。
反比例のグラフが現れているため測定はできていると考えていいと思います。
動作してる様子は次の動画を御覧ください。
動画では処理速度と視差と求められた距離を表示しています。 1~2cmぐらいズレてますが、おおむね距離が測定できていると思います。オープンキャンパスもあるので久しぶりに動かしてみた pic.twitter.com/Os7Dl7bGiX
— ringo (@Malus_Mill_) 2018年6月23日
おわりに
前回は最初に距離ごとに視差を求め、逆算することで距離を求めましたが、今回は既知の値を使うことで距離を測定することができました。
今後は得られた値をもとになにか動かしたり、FPGAで速度を稼いだりしたいと思います。