Ubuntu16.04 Python/Opencv實現雙目定位及測距
1、安裝Python以及jupyter
本平臺是Ubuntu16.04,需要安裝python環境,我安裝的是python3版本。
(1)首先安裝python3
sudo apt-get install python3
#若要安裝指定版本的python,這地方可以更改成你需要的版本,比如你要安裝3.6版本:
sudo apt-get install python3.6 python3.6-dev
(2)切換python優先順序
安裝好後會在 /usr/bin/ 下出現 python3.6 這個可執行檔案,現在需要切換版本(預設版本2.7) 如下就是設定python3.6的路徑,並設定優先順序為200
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 200
所以如果想要使用系統預設的2.7版本,需要鍵入
sudo update-alternatives –install /usr/bin/python python /usr/bin/python2.7 250
並設定優先順序大於其他的版本
(3)安裝pip
當前python版本為3.x,輸入如下命令:
sudo apt-get install python3-pip python3-dev
若python版本為2.7,則輸入如下命令:
sudo apt-get install python-pip python-dev
在裝tensorflow之前,不管是不是最新的pip版本,都要更新一下,具體命令如下:
python 2.7版本:
sudo pip install --upgrade pip
python 3.x版本:
sudo pip3 install --upgrade pip
(4)安裝jupyter以及相關依賴包
若是Python3,把pip換成pip3
pip install pillow pip install lxml pip install jupyter pip install matplotlib
在終端執行:
jupyter notebook
會出現一個網址,如下圖:
開啟網址,便進入到網頁版的jupyter
注意:在哪個目錄開啟jupyter notebook,則該目錄為根目錄。
2、安裝opencv-python
這裡不需要進入官網下載opencv原始碼進行繁瑣的安裝,安裝opencv直接在終端執行:
sudo pip install opencv-python
檢視opencv版本,執行:
pkg-config --modversion opencv
下圖表安裝成功 ,我的是3.3.1
下面寫一個測試程式碼實現攝像頭實時捕捉:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
# get a frame
ret, frame = cap.read()
# show a frame
cv2.imshow("capture", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
同樣在jupyter上點選run all,或者按Shift+Eenter,就會顯示出視訊流
3、對專案攝像機進行標定
首先得買個雙目攝像機吧!
我用的是matlab標定(棋盤格方法),我是先分別對左右兩個圖形一幅一幅的抓取,20*2=40張,然後按照官網步驟一步一步來,過程還是比較繁瑣,沒辦法!標定的好壞決定最後的精度。
下面是抓取一張圖片的程式碼,按q結束並抓拍一張圖片。
#讀取視訊,按q結束並抓拍一張圖片
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
# get a frame
ret, frame = cap.read()
# show a frame
cv2.imshow("capture", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
cv2.imwrite('camera1.jpg', frame)
break
cap.release()
cv2.destroyAllWindows()
緊接著,新建一個camera_configs.py檔案,裡面專門用來儲存兩個攝像頭標定好的引數。
import cv2
import numpy as np
#左攝像頭引數
left_camera_matrix = np.array([[1394.26663, 0, 343.36581],
[0, 1393.25572, 206.56092],
[0, 0, 1]])
left_distortion = np.array([[-0.66451, 0.84137, -0.01001, -0.00274, 0]])
#右攝像頭引數
right_camera_matrix = np.array([[1385.46346, 0, 344.38903],
[0, 1385.09596, 197.18927],
[0, 0, 1]])
right_distortion = np.array([[-0.63339, -0.68796, -0.00491, -0.00675, 0]])
om = np.array([0.00456, 0.01463, 0.00042]) # 旋轉關係向量
R = cv2.Rodrigues(om)[0] # 使用Rodrigues變換將om變換為R
T = np.array([-59.63351, -0.15514, -0.35781]) # 平移關係向量
size = (640, 360) # 影象尺寸
# 進行立體更正
R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(left_camera_matrix, left_distortion,
right_camera_matrix, right_distortion, size, R,
T)
# 計算更正map
left_map1, left_map2 = cv2.initUndistortRectifyMap(left_camera_matrix, left_distortion, R1, P1, size, cv2.CV_16SC2)
right_map1, right_map2 = cv2.initUndistortRectifyMap(right_camera_matrix, right_distortion, R2, P2, size, cv2.CV_16SC2)
4、利用BM匹配演算法實現雙目測距
程式碼:
import cv2
import numpy as np
import camera_configs
cv2.namedWindow("depth")
cv2.moveWindow("left", 0, 0)
cv2.moveWindow("right", 640, 0)
cv2.createTrackbar("num", "depth", 2, 10, lambda x: None)
cv2.createTrackbar("blockSize", "depth", 5, 255, lambda x: None)
# 新增點選事件,列印當前點的距離q
def callbackFunc(e, x, y, f, p):
if e == cv2.EVENT_LBUTTONDOWN:
print (threeD[y][x])
cv2.setMouseCallback("depth", callbackFunc, None)
cap = cv2.VideoCapture(0)
while True:
ret1, frame = cap.read()
#ret2, frame2 = camera2.read()
#if not ret1 or not ret2:
if ret1 != True:
break
cv2.resize(frame,(2560,360),interpolation=cv2.INTER_LINEAR)
dsize = (1280, 360)
imagedst = cv2.resize(frame,dsize,interpolation=cv2.INTER_LINEAR)
frame1 = imagedst[0:360,0:640]
frame2 = imagedst[0:360,640:1280]
# 根據更正map對圖片進行重構
img1_rectified = cv2.remap(frame1, camera_configs.left_map1, camera_configs.left_map2, cv2.INTER_LINEAR)
img2_rectified = cv2.remap(frame2, camera_configs.right_map1, camera_configs.right_map2, cv2.INTER_LINEAR)
# 將圖片置為灰度圖,為StereoBM作準備
imgL = cv2.cvtColor(img1_rectified, cv2.COLOR_BGR2GRAY)
imgR = cv2.cvtColor(img2_rectified, cv2.COLOR_BGR2GRAY)
# 兩個trackbar用來調節不同的引數檢視效果
num = cv2.getTrackbarPos("num", "depth")
blockSize = cv2.getTrackbarPos("blockSize", "depth")
if blockSize % 2 == 0:
blockSize += 1
if blockSize < 5:
blockSize = 5
# 根據Block Maching方法生成差異圖(opencv裡也提供了SGBM/Semi-Global Block Matching演算法,有興趣可以試試)
stereo = cv2.StereoBM_create(numDisparities = 16*num,
blockSize = 31)
disparity = stereo.compute(imgL, imgR)
disp = cv2.normalize(disparity, disparity, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
# 將圖片擴充套件至3d空間中,其z方向的值則為當前的距離
threeD = cv2.reprojectImageTo3D(disparity.astype(np.float32)/16., camera_configs.Q)
cv2.imshow("left", img1_rectified)
cv2.imshow("right", img2_rectified)
cv2.imshow("depth", disp)
key = cv2.waitKey(1)
if key == ord("q"):
break
elif key == ord("s"):
cv2.imwrite(path_BM_left, imgL)
cv2.imwrite(path_BM_right, imgR)
cv2.imwrite(path_BM_depth, disp)
cap.release()
cv2.destroyAllWindows()
注意:需要把 camera_configs.py檔案放在同一個目錄。
測試結果: