2016.10.30.
2017.10. 1. OpenCV3.3.0とVisual C++ 2017で確認済み、このままのプログラムで使用可
石立 喬
OpenCV3.1.0とVisual C++ 2015による画像処理と認識(20)
----- tsukuba画像とaloe画像を使って視差マップ(disparity map)を作成する
-----
二つの視点から撮影した二次元画像の間には、被写体の遠近に応じて若干のズレがある。このズレを利用して、三次元物体の深度(depth)を求めることができる。ズレの量を直接画像化したものを視差マップ(depth
map)と呼び、StereoBMクラスやStereoSGBMクラスのメソッドで取得できる。
視差マップの詳細については、「OpenCVとVisual C++による画像処理と認識(20)」に詳しく述べてあるので、ここでは、OpenCV3.1.0になって変わった部分を中心に紹介する。
OpenCV3.1.0で変わったところ
ここで紹介するクラスは、Camera Calibration and 3D Reconstructionモジュールに属する。
◎StereoMatcher基底クラスができた
従来のStereoBMクラスとStreoSGBMクラスが、この基底クラスを継承する形になった。視差マップの作成には、従来、StereoBMとStereoSGBMにあった個別のoperator()メソッドを用いていたが、OpenCV3.1.0では、共通してStereoMatcher::compute()を使うことになった。継承関係にあるので、子クラスで、compute()を使用できる。
従来、StereoSGBM::operator()ではカラー画像が使用できたが、OpenCV3.1.0では、グレイスケールのみのStereoMatcher::compute()を共用するため、使えなくなった。
◎StereoBMクラス
型がPtr<StereoBM>に変わり、create(生成)メソッドからpresetパラメータが消えた(OpenCV2.4では、presetで、カメラの画角を表すBASIC_PRESETなどを設定していた)。
◎StereoSGBMクラス
型がPtr<StereoBM>に変わり、create(生成)メソッドで、従来のSADWindowSizeがblockSizeに、fullDPがmodeに変わった。内容的には同じものである。
◎tsukubaステレオ画像が無くなった
従来、OpenCV2.4では、opencv/sources/samples/cpp/にtsukuba_l.pngとtsukuba_r.pngがあったが、OpenCV3.1.0では、opencv/sources/samples/data/にこれが無くなった。ここでは、ダウンロード済のOpenCV2.4の前記tsukuba画像を使用したが、
http://s1.bitdownload.ir/Software/Development%26Programing/opencv/doc/pics/
などからダウンロードすることができる。
◎OpenCV3.1.0に備わっているステレオ画像
OpenCV3.1.0には、ステレオ画像として使用できるものに、opencv/source/samples/data/の下のaloeL.jpgとaloeR.jpg、および、rubberwhale1.pngとrubberwhal2.pngがある。これらは、OpenCV2.4では、opencv/sources/samples/gnu/にあったものである。aloeLとaloeR.jpgは、サイズが1282
x 1110と大きく、ここでは30%に縮小して使用した。rubberwhale1.pngとrubberwhale2.pngは、584
x 388であるが、視差が小さすぎるのか、あまり良い視差マップが得られなかった。
tsukubaステレオ画像を使用して、StereoBMとStreoSGBMで視差マップを作成する
OpenCV3.1.0の二つのクラス、StereoBMとStereoSGBMについて、デフォルト設定の場合と、最大視差ピクセル数numDisparitiesとブロックサイズblockSizeなどを最適状態に設定した場合の視差マップを求めた。図1はそのプログラムで、下記から成る。
1)tsukuba_l.pngとtsukuba_r.pngをグレイスケール画像として読み込み、左の画像を原画像として表示する。
2)StereoBMをデフォルトで用いて視差マップを作成し、表示する。
・sbmをデフォルト条件で生成する。
・sbm->computeでdisparity_dataを得る。
・minMaxLoc関数でdisparity_dataの最小値と最大値を求める
・convertTo関数でdisperity_dataの最小値が0に、最大値が255に対応するように線形変換してdisparity_mapを得る。
・disparity_mapを表示する(図3左)。
3)StereoBMのnumDisparotiesとblockSizeを試行錯誤で最適値に設定し、同様な方法で視差マップを表示する(図3右)。
4)StereoSGBMのnumDisparotiesとblockSizeを、StereoBMの場合と同じに設定し、他はデフォルトで生成し、視差マップを表示する(図4左)。
5)StereoSGBMで、スペックルフィルタ関連パラメータを試行錯誤で追加設定し、視差マップを表示する(図4右)。
使用したメソッド(OpenCV3.1.0で変わったもののみ)
◎StereoBMクラス
この生成には下記を使用する。
StereoBM::create(
numDisparities = 0 --- int、0はデフォルト値ではなく、デフォルトの意。求める視差の最大値を16の倍数で指定する
デフォルト値は48以上と推定される
blockSize = 21 ------ int、Sum of Absolute Differencesを計算するウィンドウのサイズ、奇数であること、
資料には3~11とあるが、5以上でないとエラーになる、
大きいと広範囲で平均化され、小さいと細かくなるが、ノイズに弱くなる。
)
blockSizeは、OpenCV2.4ではSADWindowSize(SAD = Sum of Absolute Differences)と呼ばれていたものである。
◎StereoSGBMクラス
この生成には下記を使用する。
StereoSGBM::create(
minDisparity ----------- int、最小視差値、シフト(平行移動)のない場合には0で良い
numDisparities --------- int、最大視差値と最小視差値の差、16の倍数にする
blockSize ------------- int、OpenCV2.4では、SADWindowSizeと呼ばれていた、3~11の奇数、
StereoBMと異なり、3から使用できる
P1 = 0 -------------- int、デフォルトのままで良かった
P2 = 0 --------------- int、 同上
disp12MaxDiff = 0 ------ int、 左右の視差の許容最大値、デフォルトはチェックなし、デフォルトで良かった
preFilterCap = 0 ------- int、 事前にフィルタで大きな視差をクリップする、デフォルトで良かった
uniquenessRatio = 0 ---- int、目的関数値の次点との差の%比率、0は比較しない意、デフォルトで十分であった
speckleWindowSize = 0 -- int、小さい斑点やノイズを消すフィルタのサイズ、デフォルトの0は使用しない意、
これは使って非常に効果があった。
speckleRange = 0 ------ int、上記フィルタを使用するときの、視差の最大値、1~2が推奨で、16倍される、1が良かった
mode = StereoSGBM::MODE_SGBM ---- int、OpenCV2.4では、fullDP = falseとされていたもの、
フルスケールの2パス・ダイナミックプログラミングを実行させるには、StereoSGBM::MODE_HHを使用
)
◎StereoMatcher基底クラス
このcomputeメソッドを使って、StereoBMやStereoSGBMで視差マップを求めるには、下記メソッドを使用する。
StereoMatcher::compute(
left -------- InputArray、左カメラの入力画像、CV_8UC1型(グレイスケール)
right ------- InputArray、右カメラの入力画像、CV_8UC1型(グレイスケール)
disparity ---- OutputArray、視差マップの出力配列、入力画像と同じサイズで、CV_16S型、
実際の値を16倍して整数化してある
)

図1 StereoBMとStereoSGBMで、tsukuba画像から視差マップを得るプログラム
tsukuba画像で得られた結果
図2は原画像、図3はStereoBMでの結果である。図3で、左はデフォルト条件を用いたもので、左端が大きく切れており、右は、試行錯誤の結果最適と思われた
numDispatities = 16、 blockSize = 15の条件を用いたものである。
図4はStereoSGBMを使用した場合で、図の左は、StereoBMで得た最適条件の設定以外はデフォルト値を使用している。図の右は、スペックルフィルタを使うために、speckleWindowSize
= 200とspeckleRange = 1をデフォルト以外に設定している。これらの値は試行錯誤で求めたものである。
図2 tsukuba_l.pngの原画像
図3 StereoBMのデフォルト(左)と最適設定(右)の結果
図4 StereoSGBMのスペックルフィルタなし(左)とあり(右)の結果
aloeステレオ画像で視差マップを作成した結果
図1のプログラムで、画像ファイル名をaloeLS.jpgとaloeRS.jpg(それぞれ、aloeL.jpgとaloeR.jpgを30%に縮小したもの)に書き換え、デフォルト以外の設定値を試行錯誤でaloe画像用に変更した。
図5は原画像、図6はStereoBMでの結果である。図6で、左はデフォルトで、右はnumDispatities
= 48、 blockSize = 9に設定した場合てある。
図7は、スペックフィルタを使用するにあたって、blockSizeを7に小さく設定するコードの追加を示す。blockSizeを小さくすると、ノイズが出やすいが、スペックルフィルタは、これを除去するので、総合的に良い結果が得られる。
図8はStereoSGBMの結果で、図の左は単純な条件設定(numDisparities = 48,、blockSize
= 9以外はデフォルト)の場合、右はスペックルフィルタあり(blockSize = 7に変更)の場合である。
なお、ここで使用したステレオ画像では、スペックルフィルタの効果は顕著でなかったが、OpenCV2.4を使用した「OpenCVとVisual
C++による画像処理と認識(20)」で使用した画像の例では、非常に有効であったことを付記する。
図5 aloeLS.jpgの原画像(グレイ化後)
図6 StereoBMのデフォルト(左)と詳細設定(右)の結果
図7 blockSizeを小さくするコードを追加した
図8 StereoSGBMのスペックルフィルタなし(左)とあり(右)の結果
結 論
OpenCV3.1.0で変わったところは、StereoMatcher基底クラスができ、視差マップ作成は、このcomputeメソッドを使うことである。StereoBMクラスもStereoSGBMクラスも、この共通メソッドを使うので、StereoSGBMでカラー画像を扱えなくなった。SADWindowSizeがblockSizeに名称が変わったが、内容は同じである。
tsukuba画像が付属しなくなり、従来gnuフォルダにあったステレオ画像二種がopencv/sources/samples/data/に移された。
「Visual C++の勉強部屋」(目次)へ