我在尝试编写代码来校正两个图像时付出了很大的努力。我希望计算深度,然后提取点云。我无法计算深度,因为我无法校正图像并计算视差图。
这些是我校准相机和校正立体图像的功能
def CamIntr(image_paths, chessboard_params, square_size):
# Calibration chessboard parameters
#chessboard_params = [6, 9] # Number of corners in y, x
chessboard_params.append(square_size) # Square size in m
num_corners = chessboard_params[0] * chessboard_params[1]
# Termination criteria for corner refinement
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# Prepare object points (world coordinates)
objp = np.zeros((chessboard_params[0] * chessboard_params[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_params[0], 0:chessboard_params[1]].T.reshape(-1, 2)*chessboard_params[2]
# Arrays to store object points and image points from all images
objpoints = [] # 3D points in real-world space
imgpoints = [] # 2D points in image plane
for path in image_paths:
# Read the image
image = cv.imread(path)
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # Convert to grayscale
# Find chessboard corners
ret, corners = cv.findChessboardCorners(gray, (chessboard_params[0], chessboard_params[1]), None)
#print(f"Chessboard found in {path}")
objpoints.append(objp)
corners2 = cv.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
imgpoints.append(corners2)
# Draw and display the corners
#cv.drawChessboardCorners(image, (chessboard_params[1], chessboard_params[0]), corners2, ret)
#cv.imshow('img', image)
#cv.imwrite("Chessboard_draw.jpg", image)
#cv.waitKey(500)
ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
return ret, mtx, dist, rvecs, tvecs, objpoints, imgpoints
def RectifyStereoImages(img_left, img_right, chessboardL, chessboardR):
# Load stereo calibration data (intrinsics, extrinsics, etc.)
gray_left = cv.imread(img_left,0)
gray_right = cv.imread(img_right,0)
##CALIBRATION
_, mtx_left, dist_left, rvecs_left, tvecs_left, objpoints_left, imgpoints_left = CamIntr(chessboardL, [6,9], 0.025)
_, mtx_right, dist_right, rvecs_right, tvecs_right, objpoints_right, imgpoints_right = CamIntr(chessboardR, [6,9], 0.025)
##STEREO VISION CALIBRATION
_, _, _, _, _, R, T, E, F = cv.stereoCalibrate(objpoints_left, imgpoints_left, imgpoints_right,
mtx_left, dist_left, mtx_right, dist_right,
gray_left.shape[::-1], criteria=(cv.CALIB_FIX_INTRINSIC, 30, 0.001))
flags = 0
flags |= cv.CALIB_FIX_INTRINSIC
# Here we fix the intrinsic camara matrixes so that only Rot, Trns, Emat and Fmat are calculated.
# Hence intrinsic parameters are the same
criteria_stereo= (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# This step is performed to transformation between the two cameras and calculate Essential and Fundamenatl matrix
retStereo, newCameraMatrixL, distL, newCameraMatrixR, distR, rot, trans, essentialMatrix, fundamentalMatrix = cv.stereoCalibrate(objpoints_left, imgpoints_left, imgpoints_right, mtx_left, dist_left, mtx_right, dist_right, gray_left.shape[::-1], criteria_stereo, flags)
##STEREO RECTIFICATION
rectifyScale= 1
rectL, rectR, projMatrixL, projMatrixR, Q, roi_L, roi_R= cv.stereoRectify(newCameraMatrixL, distL, newCameraMatrixR, distR, gray_left.shape[::-1], rot, trans, rectifyScale,(0,0), alpha = 0.5)
stereoMapL = cv.initUndistortRectifyMap(mtx_left, distL, rectL, projMatrixL, gray_left.shape[::-1], cv.CV_16SC2)
stereoMapR = cv.initUndistortRectifyMap(mtx_right, distR, rectR, projMatrixR, gray_right.shape[::-1], cv.CV_16SC2)
map_left_x = stereoMapL[0]
map_left_y = stereoMapL[1]
map_right_x = stereoMapR[0]
map_right_y = stereoMapR[1]
# Rectify the images
img_left_rectified = cv.remap(gray_left, map_left_x, map_left_y, cv.INTER_LANCZOS4, cv.BORDER_CONSTANT, 0)
img_right_rectified = cv.remap(gray_right, map_right_x, map_right_y, cv.INTER_LANCZOS4, cv.BORDER_CONSTANT, 0)
return img_left_rectified, img_right_rectified
这就是我所说的。
# Get all files in the directory
all_files = os.listdir(r"C:\Users\emmay\Desktop\Folder")
# Filter files starting with the prefix "Chessboard"
chessboard1 = [file for file in all_files if file.startswith("Chessboard1")]
chessboard2 = [file for file in all_files if file.startswith("Chessboard2")]
squaresize = 0.025
img1 = "Chessboard1_1.png"
img2 = "Chessboard2_1.png"
imgL = cv.imread(img1,0)
imgR = cv.imread(img2,0)
fig, ax = plt.subplots()
im = ax.imshow(imgL)
plt.show()
ax.set_title("Left original image")
fig, ax = plt.subplots()
im = ax.imshow(imgR)
plt.show()
ax.set_title("Right original image")
L_rect, R_rect = RectifyStereoImages(img1, img2, chessboard1, chessboard2)
#images after rectification
fig, ax = plt.subplots()
im = ax.imshow(L_rect)
plt.show()
ax.set_title("Left rectified image")
fig, ax = plt.subplots()
im = ax.imshow(R_rect)
plt.show()
ax.set_title("Right rectified image")
我有来自每个相机的 10 张棋盘图像,同时拍摄。我是否单独校准每个相机,即使它们是同一台相机?我将图像分开,以防万一,但如果将它们全部集中在一起以获得相机的内在特性,我可以通过图像校正获得更好的结果。当我分离图像时,即使它们是同一台相机,我也会得到不同的相机内在参数和畸变变量。为了方便起见,我正在尝试纠正我的一张棋盘图像。
这是我的相机矩阵和第一个相机的畸变系数
array([[553.76951265, 0. , 359.52945636],
[ 0. , 558.7809926 , 322.92191203],
[ 0. , 0. , 1. ]])
array([[-5.74144340e-01, 2.21330577e+00, 2.87945868e-03,
9.47036694e-04, -3.28003833e+00]])
用于第二个相机
([[643.44291723, 0. , 297.31281198],
[ 0. , 639.47052736, 216.32413232],
[ 0. , 0. , 1. ]])
array([[ 0.16309873, -1.99119008, -0.02374205, -0.01189547, 10.39937883]])
如果我尝试找到包含所有图片的相机内在函数,并且不要像这样通过左或右相机将它们分开(强制内在函数相同):
_, mtx_left, dist_left, rvecs_left, tvecs_left, objpoints_left, imgpoints_left = CamIntr(chessboardL + chessboardR, [6,9], 0.025)
_, mtx_right, dist_right, rvecs_right, tvecs_right, objpoints_right, imgpoints_right = CamIntr(chessboardR, chessboardL, [6,9], 0.025)
我得到了这张稍微好一点的图片,但它们现在彼此之间差异太大,无法计算视差图
有人知道发生了什么事或者可以帮助我吗?
您的代码似乎是正确的,应该能够实现您想要的。问题源于方法论。一些要点: