0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

從雙目標定到立體匹配:Python實踐指南

3D視覺工坊 ? 來源:3D視覺工坊 ? 2023-06-08 16:28 ? 次閱讀

立體匹配是計算機視覺中的一個重要領(lǐng)域,旨在將從不同角度拍攝的圖像匹配起來,以創(chuàng)建類似人類視覺的3D效果。實現(xiàn)立體匹配的過程需要涉及許多步驟,包括雙目標定、立體校正、視差計算等。在這篇文章中,將介紹如何使用Python實現(xiàn)立體匹配的基本步驟和技巧。

f03103a6-05d5-11ee-962d-dac502259ad0.png

下面的代碼實現(xiàn)了從相機標定到立體匹配的完整流程,下面將分別介紹各個函數(shù)的參數(shù)和輸出。

標定

首先,該程序需要用到以下庫:

numpy
cv2(OpenCV)
os

在程序開頭,需要定義一些變量來存儲標定圖片的路徑、棋盤格參數(shù)、角點坐標等等。具體介紹如下:

path_left="./data/left/"
path_right="./data/right/"

path_left和path_right是左右相機標定圖片文件夾的路徑。

CHESSBOARD_SIZE=(8,11)
CHESSBOARD_SQUARE_SIZE=15#mm

CHESSBOARD_SIZE是棋盤格內(nèi)部角點的行列數(shù),CHESSBOARD_SQUARE_SIZE是棋盤格內(nèi)部每個小正方形的大?。▎挝粸楹撩祝?/p>

objp=np.zeros((CHESSBOARD_SIZE[0]*CHESSBOARD_SIZE[1],3),np.float32)
objp[:,:2]=np.mgrid[0:CHESSBOARD_SIZE[0],0:CHESSBOARD_SIZE[1]].T.reshape(-1,2)*CHESSBOARD_SQUARE_SIZE

objp是物理坐標系下每個角點的三維坐標,即棋盤格的位置。該變量在后續(xù)的相機標定以及立體匹配中都會被用到。

criteria=(cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,30,0.001)

criteria是角點檢測的終止準則,一般都使用這個默認值。

img_list_left=sorted(os.listdir(path_left))
img_list_right=sorted(os.listdir(path_right))

img_list_left和img_list_right分別是左、右圖像的文件名列表,使用os.listdir()函數(shù)獲取。

obj_points=[]
img_points_left=[]
img_points_right=[]

obj_points、img_points_left和img_points_right分別是存儲每個標定圖片對應(yīng)的物理坐標系下的角點坐標、左相機的像素坐標和右相機的像素坐標。這些變量同樣在后續(xù)的相機標定和立體匹配中用到。

接下來,程序讀取標定圖片并檢測角點。對于每幅圖片,程序執(zhí)行以下操作:

img_l=cv2.imread(path_left+img_list_left[i])
img_r=cv2.imread(path_right+img_list_right[i])
gray_l=cv2.cvtColor(img_l,cv2.COLOR_BGR2GRAY)
gray_r=cv2.cvtColor(img_r,cv2.COLOR_BGR2GRAY)

首先讀取左右圖像,然后將它們轉(zhuǎn)換為灰度圖像。

ret_l,corners_l=cv2.findChessboardCorners(gray_l,CHESSBOARD_SIZE,None)
ret_r,corners_r=cv2.findChessboardCorners(gray_r,CHESSBOARD_SIZE,None)

通過OpenCV的cv2.findChessboardCorners()函數(shù)檢測左右圖像上的棋盤格角點。這個函數(shù)的參數(shù)包括:

image:需要檢測角點的灰度圖像。patternSize:內(nèi)部角點的行列數(shù),即(CHESSBOARD_SIZE[1]-1, CHESSBOARD_SIZE[0]-1)。corners:用于存儲檢測到的角點坐標的數(shù)組。如果檢測失敗,則該參數(shù)為空(None)。flags:檢測時使用的可選標志。這個函數(shù)的返回值包括:

ret:一個布爾值,用于指示檢測是否成功。如果檢測成功,則為True,否則為False。corners:用于存儲檢測到的角點坐標的數(shù)組。接下來是亞像素級別的角點檢測。

cv2.cornerSubPix(gray_l,corners_l,(11,11),(-1,-1),criteria)
cv2.cornerSubPix(gray_r,corners_r,(11,11),(-1,-1),criteria)

這里使用了OpenCV的cv2.cornerSubPix()函數(shù)來進行亞像素級別的角點檢測。這個函數(shù)的參數(shù)包括:

image:輸入的灰度圖像。
corners:用于存儲檢測到的角點坐標的數(shù)組。
winSize:每次迭代中搜索窗口的大小,即每個像素周圍的搜索范圍大小。通常為11x11。
zeroZone:死區(qū)大小,表示怎樣的對稱性(如果有的話)不考慮。通常為(-1,-1)。
criteria:定義迭代停止的誤差范圍、迭代次數(shù)等標準,和以上的criteria一樣。

img_points_left.append(corners_l)
img_points_right.append(corners_r)

如果檢測到了左右圖像上的角點,則將這些角點的坐標存儲到img_points_left和img_points_right中。

cv2.drawChessboardCorners(img_l,CHESSBOARD_SIZE,corners_l,ret_l)
cv2.imshow("ChessboardCorners-Left",cv2.resize(img_l,(img_l.shape[1]//2,img_l.shape[0]//2)))
cv2.waitKey(50)

cv2.drawChessboardCorners(img_r,CHESSBOARD_SIZE,corners_r,ret_r)
cv2.imshow("ChessboardCorners-Right",cv2.resize(img_r,(img_r.shape[1]//2,img_r.shape[0]//2)))
cv2.waitKey(50)

f067cae4-05d5-11ee-962d-dac502259ad0.png在圖片上標出檢測到的角點,并在窗口中顯示。這里使用了cv2.drawChessboardCorners()函數(shù),該函數(shù)的參數(shù)包括:

img:需要標定角點的圖像。patternSize:內(nèi)部角點的行列數(shù),即(CHESSBOARD_SIZE[1]-1, CHESSBOARD_SIZE[0]-1)。
corners:存儲檢測到的角點坐標的數(shù)組。patternfound:檢測到角點的標記,即ret。

程序接下來對雙目攝像機進行標定。

ret_l,mtx_l,dist_l,rvecs_l,tvecs_l=cv2.calibrateCamera(obj_points,img_points_left,gray_l.shape[::-1],None,None)
ret_r,mtx_r,dist_r,rvecs_r,tvecs_r=cv2.calibrateCamera(obj_points,img_points_right,gray_r.shape[::-1],None,None)

flags=0
flags|=cv2.CALIB_FIX_INTRINSIC
criteria=(cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,30,0.001)
ret,M1,d1,M2,d2,R,T,E,F=cv2.stereoCalibrate(
obj_points,img_points_left,img_points_right,
mtx_l,dist_l,mtx_r,dist_r,
gray_l.shape[::-1],criteria=criteria,flags=flags)

這段代碼首先對左右相機進行單獨標定:

ret_l,mtx_l,dist_l,rvecs_l,tvecs_l=cv2.calibrateCamera(obj_points,img_points_left,gray_l.shape[::-1],None,None)
ret_r,mtx_r,dist_r,rvecs_r,tvecs_r=cv2.calibrateCamera(obj_points,img_points_right,gray_r.shape[::-1],None,None)

這里使用了OpenCV的cv2.calibrateCamera()函數(shù)對左右相機進行標定。這個函數(shù)的參數(shù)包括:

objectPoints:每幅標定圖片對應(yīng)的物理坐標系下的角點坐標。
imagePoints:每幅標定圖片上檢測到的像素坐標。
imageSize:標定圖片的尺寸。
cameraMatrix:用于存儲標定結(jié)果的內(nèi)參數(shù)矩陣。
distCoeffs:用于存儲標定結(jié)果的畸變系數(shù)。
rvecs:每幅標定圖片的外參數(shù)矩陣中的旋轉(zhuǎn)向量。
tvecs:每幅標定圖片的外參數(shù)矩陣中的平移向量。
這個函數(shù)的返回值包括:

ret:一個標志位,表示標定是否成功。
cameraMatrix:用于存儲標定結(jié)果的內(nèi)參數(shù)矩陣。
distCoeffs:用于存儲標定結(jié)果的畸變系數(shù)。
rvecs:每幅標定圖片的外參數(shù)矩陣中的旋轉(zhuǎn)向量。
tvecs:每幅標定圖片的外參數(shù)矩陣中的平移向量。
然后對雙目攝像機進行標定:

flags=0
flags|=cv2.CALIB_FIX_INTRINSIC
criteria=(cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,30,0.001)
ret,M1,d1,M2,d2,R,T,E,F=cv2.stereoCalibrate(
obj_points,img_points_left,img_points_right,
mtx_l,dist_l,mtx_r,dist_r,
gray_l.shape[::-1],criteria=criteria,flags=flags)

這里使用了OpenCV的cv2.stereoCalibrate()函數(shù)進行雙目攝像機標定。這個函數(shù)的參數(shù)包括:

objectPoints:每幅標定圖片對應(yīng)的物理坐標系下的角點坐標。
imagePoints1:每幅標定圖片的左相機上檢測到的像素坐標。
imagePoints2:每幅標定圖片的右相機上檢測到的像素坐標。
cameraMatrix1:左相機的內(nèi)參數(shù)矩陣。
distCoeffs1:左相機的畸變系數(shù)。
cameraMatrix2:右相機的內(nèi)參數(shù)矩陣。
distCoeffs2:右相機的畸變系數(shù)。
imageSize:標定圖片的尺寸。
criteria:定義迭代停止的誤差范圍、迭代次數(shù)等標準。
flags:標定的可選標志。
這個函數(shù)的返回值包括:

ret:一個標志,表示標定是否成功。
cameraMatrix1:左相機的內(nèi)參數(shù)矩陣。
distCoeffs1:左相機的畸變系數(shù)。
cameraMatrix2:右相機的內(nèi)參數(shù)矩陣。
distCoeffs2:右相機的畸變系數(shù)。
R:旋轉(zhuǎn)矩陣。
T:平移向量。
E:本質(zhì)矩陣。
F:基礎(chǔ)矩陣。

立體匹配

通過圖像標定得到的參數(shù)進行立體匹配的整個流程,如下:

首先,我們需要讀取左右兩張圖像:

img_left=cv2.imread("./left.png")
img_right=cv2.imread("./right.png")

其中,"./left.png" 和 "./right.png" 是放置左右圖像的路徑。這兩幅圖像是未經(jīng)校正和矯正的圖像。

接下來,通過圖像標定得到相機的參數(shù),根據(jù)得到的參數(shù),將圖像進行去畸變:

img_left_undistort=cv2.undistort(img_left,M1,d1)
img_right_undistort=cv2.undistort(img_right,M2,d2)

在上述代碼中,M1、M2、d1、d2 是從雙目相機標定中獲得的參數(shù)。去畸變后的圖像 img_left_undistort 和 img_right_undistort 可供之后的操作使用。

然后,進行極線校正,以實現(xiàn)左右圖像在幾何上的一致性:

R1,R2,P1,P2,Q,roi1,roi2=cv2.stereoRectify(M1,d1,M2,d2,(width,height),R,T,alpha=1)
map1x,map1y=cv2.initUndistortRectifyMap(M1,d1,R1,P1,(width,height),cv2.CV_32FC1)
map2x,map2y=cv2.initUndistortRectifyMap(M2,d2,R2,P2,(width,height),cv2.CV_32FC1)
img_left_rectified=cv2.remap(img_left_undistort,map1x,map1y,cv2.INTER_LINEAR)
img_right_rectified=cv2.remap(img_right_undistort,map2x,map2y,cv2.INTER_LINEAR)

其中,R、T 是雙目相機標定得到的旋轉(zhuǎn)和平移矩陣, (width, height)是左右圖像的尺寸。R1、R2 是左右圖像的旋轉(zhuǎn)矩陣,P1、P2 是左右圖像的投影矩陣,Q 是視差轉(zhuǎn)換矩陣,roi1、roi2 是矯正后的圖像中可以使用的區(qū)域。

然后,將左右圖像拼接在一起以方便觀察:

img_stereo=cv2.hconcat([img_left_rectified,img_right_rectified])
f0de119a-05d5-11ee-962d-dac502259ad0.png

接下來,需要計算視差圖:

minDisparity=0
numDisparities=256
blockSize=9
P1=1200
P2=4800
disp12MaxDiff=10
preFilterCap=63
uniquenessRatio=5
speckleWindowSize=100
speckleRange=32
sgbm=cv2.StereoSGBM_create(minDisparity=minDisparity,numDisparities=numDisparities,blockSize=blockSize,
P1=P1,P2=P2,disp12MaxDiff=disp12MaxDiff,preFilterCap=preFilterCap,
uniquenessRatio=uniquenessRatio,speckleWindowSize=speckleWindowSize,
speckleRange=speckleRange,mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY)

disparity=sgbm.compute(img_left_rectified,img_right_rectified)

上面的代碼塊定義了使用的視差算法的參數(shù),并使用了 SGBM(Semi Global Block Matching)算法計算了原始的視差圖。注意,由于使用的是16位的 SGBM 輸出,因此需要將它除以16。f15a6560-05d5-11ee-962d-dac502259ad0.png接下來,可以對視差圖進行 WLS 濾波,減少視差空洞:

#定義WLS濾波參數(shù)
lambda_val=4000
sigma_val=1.5

#運行WLS濾波
wls_filter=cv2.ximgproc.createDisparityWLSFilterGeneric(False)
wls_filter.setLambda(lambda_val)
wls_filter.setSigmaColor(sigma_val)
filtered_disp=wls_filter.filter(disparity,img_left_rectified,None,img_right_rectified)
filtered_disp_nor=cv2.normalize(filtered_disp,filtered_disp,alpha=0,beta=255,norm_type=cv2.NORM_MINMAX,dtype=cv2.CV_8U)

上述代碼塊中,WLS 濾波為視差圖降噪,并進行平滑處理。這里使用了 cv2.ximgproc.createDisparityWLSFilterGeneric 函數(shù),創(chuàng)建一個生成 WLS 濾波器的對象 wls_filter,然后設(shè)置了濾波參數(shù) lambda_val 和 sigma_val。filtered_disp 是經(jīng)過濾波后的視差圖。filtered_disp_nor 是經(jīng)過歸一化處理后的、用于顯示的視差圖。

最后,可以在窗口中顯示原始視差圖、預處理后的 WLS 濾波器的視差圖:

cv2.imshow("disparity",cv2.resize(disparity_nor,(disparity_nor.shape[1]//2,disparity_nor.shape[0]//2)))
cv2.imshow("filtered_disparity",cv2.resize(filtered_disp_nor,(filtered_disp_nor.shape[1]//2,filtered_disp_nor.shape[0]//2)))
cv2.waitKey()
cv2.destroyAllWindows()
f166ca1c-05d5-11ee-962d-dac502259ad0.png


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 3D
    3D
    +關(guān)注

    關(guān)注

    9

    文章

    2878

    瀏覽量

    107555
  • 計算機視覺
    +關(guān)注

    關(guān)注

    8

    文章

    1698

    瀏覽量

    45994
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4797

    瀏覽量

    84695

原文標題:從雙目標定到立體匹配:Python實踐指南

文章出處:【微信號:3D視覺工坊,微信公眾號:3D視覺工坊】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    雙目立體視覺原理大揭秘(一)

    的三維坐標值了。把該三維坐標值輸入機器人控制系統(tǒng),機器人就可以智能的實現(xiàn)避障了。在這部分中用到了“立體匹配”算法,其實該算法是和雙目標定相結(jié)合,該算法根據(jù)特征點在左右圖像中的坐標點進行基礎(chǔ)矩陣的計算并將
    發(fā)表于 11-21 16:20

    雙目立體視覺原理大揭秘(二)

    圖像處理(二值化、邊緣提取、去噪等)后,得到一系列特征點在左右相機圖像中的平面坐標X、Y。第四、根據(jù)雙目立體視覺CCAS的立體匹配原理——極限約束公式。把第三步提取到的特征點在左右相機視場中的X、Y
    發(fā)表于 11-21 16:22

    維視雙目產(chǎn)品在高??蒲袘?yīng)用中的實例及優(yōu)點分析

    包含的設(shè)備選型、系統(tǒng)搭建、圖像獲取、立體匹配,并給出標定結(jié)果,在用戶需要進行開發(fā)的特征捕捉部分,也給予了豐富的支持。雙目標定可以說是整套雙目視覺系統(tǒng)的最關(guān)鍵技術(shù),能夠快速準確的完成
    發(fā)表于 01-19 16:59

    立體匹配SAD算法原理

    立體匹配SAD算法matlab實現(xiàn)
    發(fā)表于 06-05 16:08

    雙目視覺立體匹配算法研究

    雙日視覺是計算機視覺領(lǐng)域的一個重要組成部分。雙目視覺研究中的關(guān)鍵技術(shù)攝像機標定立體匹配一直是研究的熱點。本文由兩部分組成,分別對雙目視覺的算法和未
    發(fā)表于 08-14 16:41 ?0次下載

    一種快速雙目立體匹配方法_梅金燕

    一種快速雙目立體匹配方法_梅金燕
    發(fā)表于 03-19 11:46 ?0次下載

    基于顏色調(diào)整的立體匹配改進算法

    的前提,因此如何提升立體匹配算法在各種場景中的魯棒性也是計算機視覺研究的熱點問題。 立體匹配算法的目標兩幅校正后的匹配圖片中尋找每個像素
    發(fā)表于 11-02 11:07 ?0次下載
    基于顏色調(diào)整的<b class='flag-5'>立體匹配</b>改進算法

    基于HALCON的雙目是相機立體視覺系統(tǒng)標定

    攝像機標定是機器視覺和攝像測量領(lǐng)域相對基礎(chǔ)的工作,同時也是最復雜、困難的T作。攝像機標定的意義是得到立體空間中對象的幾何信息,其中所使用的圖像信息由雙目攝像機所得。定后的
    發(fā)表于 11-06 14:41 ?30次下載
    基于HALCON的<b class='flag-5'>雙目</b>是相機<b class='flag-5'>立體</b>視覺系統(tǒng)<b class='flag-5'>標定</b>

    雙目立體匹配的四個步驟解析

    雙目立體匹配可劃分為四個步驟:匹配代價計算、代價聚合、視差計算和視差優(yōu)化。
    的頭像 發(fā)表于 08-31 10:08 ?5191次閱讀

    雙目立體計算機視覺的立體匹配研究綜述

    雙目立體視覺技術(shù)具有成本低、適用性廣的優(yōu)點,在物體識別、目標檢測等方面應(yīng)用廣泛,成為計算機視覺領(lǐng)域的研究熱點。立體匹配雙目
    發(fā)表于 04-12 09:47 ?3次下載
    <b class='flag-5'>雙目</b><b class='flag-5'>立體</b>計算機視覺的<b class='flag-5'>立體匹配</b>研究綜述

    一種基于PatchMatch的半全局雙目立體匹配算法

    景。因此,計算復雜度、匹配精度、匹配原理等多方面綜合考慮,提出了一種基于 Patchmatch的半全局雙目立體匹配算法,在路徑代價計算過程
    發(fā)表于 04-20 11:31 ?13次下載
    一種基于PatchMatch的半全局<b class='flag-5'>雙目</b><b class='flag-5'>立體匹配</b>算法

    融合邊緣特征的立體匹配算法Edge-Gray

    為保證SAD算法的立體匹配效率,提高匹配精度,提出一種融合邊緣特征的立體匹配算法 Edge-gray。通過邊緣計算得到邊緣特征圖,在進行匹配的過程中,根據(jù)當前點與領(lǐng)域點的差值確定
    發(fā)表于 04-29 11:06 ?8次下載
    融合邊緣特征的<b class='flag-5'>立體匹配</b>算法Edge-Gray

    雙目標定是什么?為什么要進行雙目標定

    在這里我們所說的雙目標定是狹義的,講解理論的時候僅指兩臺相機之間相互位置的標定,在代碼實踐的時候,我們才說完整的雙目標定。
    的頭像 發(fā)表于 07-04 11:04 ?1.2w次閱讀
    <b class='flag-5'>雙目標定</b>是什么?為什么要進行<b class='flag-5'>雙目標定</b>?

    相機之間為什么要進行雙目標定呢?

    在這里我們所說的雙目標定是狹義的,講解理論的時候僅指兩臺相機之間相互位置的標定,在代碼實踐的時候,我們才說完整的雙目標定。
    的頭像 發(fā)表于 12-28 17:17 ?2728次閱讀

    雙目立體匹配的四個步驟

    根據(jù)Schrstein和Szeliski的總結(jié),雙目立體匹配可劃分為四個步驟: 匹配代價計算、代價聚合、視差計算和視差優(yōu)化 。 一 、匹配代價計算
    的頭像 發(fā)表于 06-28 16:59 ?1180次閱讀
    <b class='flag-5'>雙目</b><b class='flag-5'>立體匹配</b>的四個步驟