双目相机立体校正python
时间: 2023-05-08 07:00:43 浏览: 228
双目相机立体校正是指消除双目相机在拍摄场景时由于光学偏差而导致图像的不一致性,从而得到更加精准的深度信息。在Python中,可以使用OpenCV等图像处理库来实现双目相机立体校正。
首先,需要对每个相机进行单独的校正,即摄像机内参矩阵和畸变参数的计算。然后,通过选择相同场景点在左右相机中的对应像素点,计算出两个相机的外参矩阵。接着,使用cv2.stereoRectify()函数计算出左右相机的映射矩阵和去畸变之后的图像。
在运行程序时,需要加载左右相机的图像,并通过cv2.imshow()函数显示校正之后的图像。校正后的图像将具有更好的空间一致性和更加准确的深度信息。
需要注意的是,双目相机立体校正的效果受到多种因素的影响,如相机精度、场景复杂度等。因此,在实际应用时,还需要对算法进行优化和调试,以达到最佳效果。
相关问题
python双目相机立体校正技巧
### Python 实现双目相机立体校正的方法
#### 获取标定板图像
为了进行有效的双目相机校准,需要准备一系列不同角度下的棋盘格图案照片。这些照片用于计算相机内部参数以及外部参数。
```python
import cv2
import numpy as np
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
objp = np.zeros((6*9,3), np.float32)
objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2)*25 # 假设方格边长为25mm
objpoints = []
imgpointsL = []
imgpointsR = []
for i in range(1, number_of_images+1):
imgL = cv2.imread(f'left{i}.jpg')
imgR = cv2.imread(f'right{i}.jpg')
grayL = cv2.cvtColor(imgL,cv2.COLOR_BGR2GRAY)
grayR = cv2.cvtColor(imgR,cv2.COLOR_BGR2GRAY)
retL, cornersL = cv2.findChessboardCorners(grayL, (9,6),None)
retR, cornersR = cv2.findChessboardCorners(grayR, (9,6),None)
if retL and retR:
objpoints.append(objp)
corners2L = cv2.cornerSubPix(grayL,cornersL,(11,11),(-1,-1),criteria)
corners2R = cv2.cornerSubPix(grayR,cornersR,(11,11),(-1,-1),criteria)
imgpointsL.append(corners2L)
imgpointsR.append(corners2R)
cv2.drawChessboardCorners(imgL, (9,6), corners2L,retL)
cv2.drawChessboardCorners(imgR, (9,6), corners2R,retR)
cv2.imshow('Left',imgL)
cv2.imshow('Right',imgR)
cv2.waitKey(500)
cv2.destroyAllWindows()
```
这段代码展示了如何读取并处理来自左、右摄像头捕获到的一系列包含标准棋盘模式的图片[^1]。
#### 执行单目相机标定
接着分别对每只眼睛执行单独的摄像机模型拟合操作:
```python
h,w = imgL.shape[:2]
retL, mtxL, distL, rvecsL, tvecsL = cv2.calibrateCamera(
objpoints,imgpointsL,
grayL.shape[::-1],None,None
)
newcameramtxL, roiL=cv2.getOptimalNewCameraMatrix(mtxL,distL,(w,h),1,(w,h))
retR, mtxR, distR, rvecsR, tvecsR = cv2.calibrateCamera(
objpoints,imgpointsR,
grayR.shape[::-1],None,None
)
newcameramtxR, roiR=cv2.getOptimalNewCameraMatrix(mtxR,distR,(w,h),1,(w,h))
```
此部分完成了针对左右两台设备各自的内参求解过程,并通过`getOptimalNewCameraMatrix()`函数优化了新的投影矩阵以便后续使用[^2]。
#### 进行双目标定与极线约束调整
最后一步则是联合考虑两只眼的信息来进行完整的双目光学建模工作,同时引入极线重映射技术确保匹配点位于同一条直线上从而提高精度:
```python
flags = 0
flags |= cv2.CALIB_FIX_INTRINSIC
criteria_stereo= (cv2.TERM_CRITERIA_EPS +
cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
retStereo, new_mtxL, distL, new_mtxR, distR, R, T, E, F = \
cv2.stereoCalibrate(objpoints, imgpointsL, imgpointsR,
newcameramtxL, distL,
newcameramtxR, distR,
grayL.shape[::-1],
flags=flags,
criteria=criteria_stereo)
rectify_scale= 1
rect_l, rect_r, proj_mat_l, proj_mat_r, Q, roi_L, roi_R= \
cv2.stereoRectify(new_mtxL, distL,
new_mtxR, distR,
grayL.shape[::-1], R, T,
rectify_scale ,(0,0))
left_map_x, left_map_y = cv2.initUndistortRectifyMap(
new_mtxL, distL, rect_l, proj_mat_l,
grayL.shape[::-1], cv2.CV_16SC2
)
right_map_x, right_map_y = cv2.initUndistortRectifyMap(
new_mtxR, distR, rect_r, proj_mat_r,
grayR.shape[::-1], cv2.CV_16SC2
)
```
上述程序实现了基于OpenCV库的功能调用来完成整个流程——从原始数据采集直至最终获得可用于实际应用的理想化几何变换关系表征形式[^3]。
双目相机立体校正代码
### 实现双目相机立体校正的代码示例
#### 准备工作
为了完成双目相机的立体校正,首先需要准备棋盘格图案的照片来获取内参和外参矩阵。这些参数对于后续的校准至关重要。
```python
import cv2
import numpy as np
import glob
# 设置查找亚像素角点的参数
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 棋盘格内部交差点的数量
chessboard_size = (9, 6)
objp = np.zeros((np.prod(chessboard_size), 3), dtype=np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
# 存储检测到的对象点和图像点用于所有图片
objpoints_left = []
imgpoints_left = []
objpoints_right = []
imgpoints_right = []
images_left = glob.glob('left_*.jpg')
images_right = glob.glob('right_*.jpg')
for img_name in images_left:
img = cv2.imread(img_name)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
if ret:
objpoints_left.append(objp)
corners_subpix = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
imgpoints_left.append(corners_subpix)
# 绘制并显示找到的角落
cv2.drawChessboardCorners(img, chessboard_size, corners_subpix, ret)
cv2.imshow(f'Found Corners {img_name}', img)
cv2.waitKey(500)
cv2.destroyAllWindows()
for img_name in images_right:
img = cv2.imread(img_name)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
if ret:
objpoints_right.append(objp)
corners_subpix = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
imgpoints_right.append(corners_subpix)
# 绘制并显示找到的角落
cv2.drawChessboardCorners(img, chessboard_size, corners_subpix, ret)
cv2.imshow(f'Found Corners {img_name}', img)
cv2.waitKey(500)
cv2.destroyAllWindows()
```
#### 执行单目相机标定
接下来分别对左、右两个摄像机执行单独的标定过程以获得各自的内参矩阵 `K` 和失真系数向量 `D`。
```python
ret_l, mtx_l, dist_l, rvecs_l, tvecs_l = cv2.calibrateCamera(
objpoints_left,
imgpoints_left,
gray.shape[::-1],
None,
None
)
h, w = img.shape[:2]
newcameramtx_l, roi_l = cv2.getOptimalNewCameraMatrix(mtx_l, dist_l, (w,h), 1, (w,h))
ret_r, mtx_r, dist_r, rvecs_r, tvecs_r = cv2.calibrateCamera(
objpoints_right,
imgpoints_right,
gray.shape[::-1],
None,
None
)
newcameramtx_r, roi_r = cv2.getOptimalNewCameraMatrix(mtx_r, dist_r, (w,h), 1, (w,h))
```
#### 进行双目标定
利用上述得到的结果来进行联合标定操作,从而计算出旋转和平移矢量等信息以便于之后做极线约束调整。
```python
flags = 0
flags |= cv2.CALIB_FIX_INTRINSIC
criteria_stereo= (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
ret_s, MLS, dLS, MRS, dRS, R, T, E, F = cv2.stereoCalibrate(
objpoints_left,
imgpoints_left,
imgpoints_right,
newcameramtx_l,
dist_l,
newcameramtx_r,
dist_r,
gray.shape[::-1],
criteria=criteria_stereo,
flags=flags
)
```
#### 应用极线校正
最后一步是对原始采集的数据应用极线重映射算法,使得两张图中的对应特征位于同一条直线上,便于后续视差估计等工作开展。
```python
rectify_scale= 1
R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(
MLS, dLS, MRS, dRS, gray.shape[::-1], R, T, rectify_scale,(0,0))
mapLx, mapLy = cv2.initUndistortRectifyMap(newcameramtx_l, dist_l, R1, P1, gray.shape[::-1], cv2.CV_16SC2)
mapRx, mapRy = cv2.initUndistortRectifyMap(newcameramtx_r, dist_r, R2, P2, gray.shape[::-1], cv2.CV_16SC2)
imgL = cv2.remap(cv2.imread(images_left[0]), mapLx, mapLy, interpolation=cv2.INTER_LINEAR,borderMode=cv2.BORDER_CONSTANT)
imgR = cv2.remap(cv2.imread(images_right[0]), mapRx, mapRy, interpolation=cv2.INTER_LINEAR,borderMode=cv2.BORDER_CONSTANT)
cv2.imwrite("output/left_rectified.png", imgL)
cv2.imwrite("output/right_rectified.png", imgR)
```
通过以上步骤可以成功去除镜头畸变,并使两幅图像基本处于同一水平线上[^2]。
阅读全文
相关推荐
















