首页 > 解决方案 > opencv stereoCalibrate 给出错误的不失真图

问题描述

我正在尝试校准 Waveshare IMX219-83 Stereo-Camera 的图像。未失真的图像不正确,我无法理解为什么它不起作用。这些图像是 3280 × 2464,但我保存的 numpy 地图的长度都是 2464,这对我来说似乎很奇怪。

校准代码:

import cv2
import numpy as np 
import glob
from tqdm import tqdm

chessboard_size = (6,9)

obj_points = [] 
img_points_l = [] 
img_points_r = []

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)


calib_paths_left = sorted(glob.glob('./calib/left/*'))
calib_paths_right = sorted(glob.glob('./calib/right/*'))
print(calib_paths_left)

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

for i in tqdm(list(range(len(calib_paths_left)))[0::1]):
    image_l = cv2.imread(calib_paths_left[i])
    image_r = cv2.imread(calib_paths_right[i])

    gray_image_l = cv2.cvtColor(image_l, cv2.COLOR_BGR2GRAY)
    gray_image_r = cv2.cvtColor(image_r, cv2.COLOR_BGR2GRAY)

    
    print("Images loaded, Analizying...")
    ret_l,corners_l = cv2.findChessboardCorners(gray_image_l, chessboard_size, None)
    ret_r,corners_r = cv2.findChessboardCorners(gray_image_r, chessboard_size, None)

    if ret_l and ret_r:
        print("Chessboard detected on both images!")
        print(calib_paths_left[i] + " and " + calib_paths_right[i])
        
        obj_points.append(objp)
        corners_fine_l = cv2.cornerSubPix(gray_image_l,corners_l,(11,11),(-1,-1),criteria)
        corners_fine_r = cv2.cornerSubPix(gray_image_r,corners_r,(11,11),(-1,-1),criteria)
        img_points_l.append(corners_fine_l)
        img_points_r.append(corners_fine_r)

        output_l = image_l.copy()
        output_r = image_r.copy()

        cv2.drawChessboardCorners(output_l,(6,9),corners_fine_l,ret_l)
        cv2.drawChessboardCorners(output_r,(6,9),corners_fine_r,ret_r)
        cv2.imshow('corners_fine_l',output_l)
        cv2.imshow('corners_fine_r',output_r)
        cv2.waitKey(500)
        
cv2.destroyAllWindows()

# Calibrate cameras individually (undistort)
ret_l, mtx_l, dist_l, rvecs_l, tvecs_l = cv2.calibrateCamera(
    obj_points, img_points_l,gray_image_l.shape[::-1], None, None)
h_l,w_l= gray_image_l.shape[:2]
new_mtx_l, roi_l= cv2.getOptimalNewCameraMatrix(mtx_l,dist_l,(w_l,h_l),1,(w_l,h_l))

ret_r, mtx_r, dist_r, rvecs_r, tvecs_r = cv2.calibrateCamera(
    obj_points, img_points_r,gray_image_r.shape[::-1], None, None)
h_r,w_r= gray_image_l.shape[:2]
new_mtx_r, roi_r= cv2.getOptimalNewCameraMatrix(mtx_r,dist_r,(w_r,h_r),1,(w_r,h_r))


# Calibrate cameras as stereocamera
flags = 0
flags |= cv2.CALIB_FIX_INTRINSIC

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

retval_stereo, new_mtx_l, dist_l, new_mtx_r, dist_r, rot, trans, emat, fmat = cv2.stereoCalibrate(
    obj_points, img_points_l, img_points_r, new_mtx_l, dist_l, new_mtx_r, dist_r, gray_image_l.shape[::-1], criteria_stereo, flags)

rectify_scale= 1
rect_l, rect_r, proj_mat_l, proj_mat_r, Q, roi_l, roi_r= cv2.stereoRectify(
    new_mtx_l, dist_l, new_mtx_r, dist_r, gray_image_l.shape[::-1], rot, trans, rectify_scale,(0,0))


Left_Stereo_Map= cv2.initUndistortRectifyMap(new_mtx_l, dist_l, rect_l, proj_mat_l,
                                             gray_image_l.shape[::-1], cv2.CV_16SC2)
Right_Stereo_Map= cv2.initUndistortRectifyMap(new_mtx_r, dist_r, rect_r, proj_mat_r,
                                              gray_image_r.shape[::-1], cv2.CV_16SC2)

print("Saving parameters ......")
np.save("camera_params/Left_Stereo_Map_x", Left_Stereo_Map[0])
np.save("camera_params/Left_Stereo_Map_y", Left_Stereo_Map[1])
np.save("camera_params/Right_Stereo_Map_x", Right_Stereo_Map[0])
np.save("camera_params/Right_Stereo_Map_y", Right_Stereo_Map[1])

重新映射图像,显示不好的结果

import cv2
import numpy as np

Left_Stereo_Map_x = np.load("camera_params/Left_Stereo_Map_x.npy")
Left_Stereo_Map_y = np.load("camera_params/Left_Stereo_Map_y.npy")
Right_Stereo_Map_x = np.load("camera_params/Right_Stereo_Map_x.npy")
Right_Stereo_Map_y = np.load("camera_params/Right_Stereo_Map_y.npy")


image_l = cv2.imread("calib/left/frame_l_30.jpg")
image_r = cv2.imread("calib/right/frame_r_30.jpg")

gray_image_l = cv2.cvtColor(image_l, cv2.COLOR_BGR2GRAY)
gray_image_r = cv2.cvtColor(image_r, cv2.COLOR_BGR2GRAY)

cv2.imshow("Left image before rectification", gray_image_l)
cv2.imshow("Right image before rectification", gray_image_r)

image_l_undist = cv2.remap(image_l,Left_Stereo_Map_x,Left_Stereo_Map_y, cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0)
image_r_undist = cv2.remap(image_r,Right_Stereo_Map_x,Right_Stereo_Map_y, cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0)

cv2.imshow("Left image after rectification", image_l_undist)
cv2.imshow("Right image after rectification", image_r_undist)
cv2.waitKey(0)

这些是我校准的图像类型:

用于校准的示例左图

用于校准的示例右图

这是我得到的输出:

左输出

输出权

我现在检查了很多次代码,但无法理解为什么它不起作用。

标签: pythonopencvcv2remapstereoscopy

解决方案


推荐阅读