備忘録として作り方と動作結果を共有します。
使ったもの
- USBカメラ2台
- ダンボール
- python-opencvをインストールしたPC
カメラの準備
ざっくりと平行になるよう、ダンボールに固定します。動作させながら角度を調整するため、完全には固定はしません。
OpenCVのインストール
OpenCV2.7で良い場合はapt-getでインストールできます。sudo apt install libopencv-dev python-opencv参考: Raspberry Pi B+にOpenCV-Python環境を構築する
OpenCV3系が良い方は、ソースからコンパイルしてください。
参考: Install OpenCV 3.0 and Python 2.7+ on Ubuntu
プログラム作成
pythonで作成しました。カメラの番号(VideoCaptureの引数)はお使いの設定環境に合わせて変更してください。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import cv2 | |
IMAGE_WIDTH = 640 | |
IMAGE_HEIGHT = 480 | |
capL = cv2.VideoCapture(0) | |
capR = cv2.VideoCapture(1) | |
imgL = np.zeros((480,640,3), np.uint8) | |
imgR = np.zeros((480,640,3), np.uint8) | |
stereo = None | |
opencv_measure_version = int(cv2.__version__.split('.')[0]) | |
windowSize = 5 | |
minDisp = 32 | |
numDisp = 144 - minDisp | |
if (opencv_measure_version <= 2): | |
# for OpenCV2 | |
stereo = cv2.StereoSGBM( | |
minDisparity = minDisp, | |
numDisparities = numDisp, | |
SADWindowSize = 16, | |
P1 = 8*3*windowSize**2, | |
P2 = 32*3*windowSize**2, | |
disp12MaxDiff = 1, | |
uniquenessRatio = 10, | |
speckleWindowSize = 100, | |
speckleRange = 32 | |
) | |
capL.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH) | |
capL.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT) | |
capR.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH) | |
capR.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT) | |
else: | |
# for OpenCV3 | |
stereo = cv2.StereoSGBM_create( | |
minDisparity = minDisp, | |
numDisparities = numDisp, | |
blockSize = 16, | |
P1 = 8*3*windowSize**2, | |
P2 = 32*3*windowSize**2, | |
disp12MaxDiff = 1, | |
uniquenessRatio = 10, | |
speckleWindowSize = 100, | |
speckleRange = 32 | |
) | |
capL.set(cv2.CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH) | |
capL.set(cv2.CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT) | |
capR.set(cv2.CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH) | |
capR.set(cv2.CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT) | |
while True: | |
capL.read(imgL) | |
capR.read(imgR) | |
# create gray images | |
imgGrayL = cv2.cvtColor(imgL, cv2.COLOR_BGR2GRAY) | |
imgGrayR = cv2.cvtColor(imgR, cv2.COLOR_BGR2GRAY) | |
# calculate histogram | |
imtGrayL = cv2.equalizeHist(imgGrayL) | |
imtGrayR = cv2.equalizeHist(imgGrayR) | |
# through gausiann filter | |
imgGrayL = cv2.GaussianBlur(imgGrayL, (5,5), 0) | |
imgGrayR = cv2.GaussianBlur(imgGrayR, (5,5), 0) | |
cv2.imshow("image left", imgGrayL) | |
cv2.imshow("image right", imgGrayR) | |
# calculate disparity | |
disparity = stereo.compute(imgGrayL, imgGrayR).astype(np.float32)/16 | |
disparity = (disparity - minDisp) / numDisp | |
cv2.imshow("disparity", disparity) | |
k = cv2.waitKey(33) | |
if k == ord('q'): | |
break; |
wget -O stereo.py https://gist.github.com/asukiaaa/1d8c9f8667c321265e83edab2bc5d4e9/raw
OpenCVのバージョンが2か3によってStereoSGBMや定数の呼び出し方法が違うので、このように対応しています。
if (opencv_measure_version <= 2): # for OpenCV2 stereo = cv2.StereoSGBM( # .. SADWindowSize = 16, # .. ) capL.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH) capL.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT) capR.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH) capR.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT) else: # for OpenCV3 stereo = cv2.StereoSGBM_create( # .. blockSize = 16, # .. ) capL.set(cv2.CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH) capL.set(cv2.CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT) capR.set(cv2.CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH) capR.set(cv2.CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT)
動作させながら調整
下記のコマンドで実行します。python stereo.py「q」か「Ctl-c」でプログラムは止まります。
「image left」に左のカメラ、「Image right」に右のカメラの出力が表示されていることを確認します。
出力が合っていない場合は、コードの「cv.VideoCapture」に渡す番号を変えて、プログラムを再実行してみてください。
角度が悪いと認識が良くないので、左右が平行になるようにダンボールをねじったり折ったりして調整してください。
カメラによってレンズの向きに個体差があるため、平行になるとは限りません。
自分の持っているカメラの場合は、このような角度差だと良い結果を得られました。
調整がうまくいけば、画像処理から深度が算出されます。
ざっくりとした作りのカメラから、ざっくりとした深度が取れました。
以上です。
何かの参考になれば嬉しいです。
参考
Depth Map from Stereo ImagesStereo Vision Tutorial - Part I
2014-11-03 100均Webカメラ2台でステレオマッチングやってみた
Disparity of stereo images with Python and OpenCV
StereoBM in OpenCV 3 (Python) missing module
キャリブレーションを行うと、精度が上がるかもしれません。
How to calibrate a stereo setup (two DVS or DAVIS sensors)
変更履歴
2016/10/13OpenCVの設定を追加しました。
ソースコードをgist化しました。
OpenCV2にも対応しました。
2017/11/13
apt installコマンドが冗長だったので、短縮しました。
気になる日本語の記述がいくつかあったので、修正しました。
2019/04/29
OpenCVの記述が大文字だったり小文字だったりしたので、「OpenCV」に統一しました。
0 件のコメント :
コメントを投稿