StE
StE

Reputation: 21

OpenCV - undistort image and create point cloud based on it

I made around 40 images with a realsense camera, which gave me rgb and corresponding aligned depth images. With rs.getintrinsic() i got the intrinsic matrix of the camera. But there is still a distortion which can be seen in the pointcloud, which can be easily generated with the depth image. Here you can see it on the right side: PointCloud of a Plane in depth image The Pointcloud represent a plane.

Now I calculated based on cv.calibrateCamera(..., intrinsic_RS_matrix, flags= cv2.CALIB_USE_INTRINSIC_GUESS|cv2.CALIB_FIX_FOCAL_LENGTH|cv2.CALIB_FIX_PRINCIPAL_POINT) the distortion coefficients of the Camera. For that I use all the 40 rgb images.

Based on the new calculated distortion I calculate with cv2.getOptimalNewCameraMatrix() the new camera matrix and with cv2.undistort(image, cameraMatrix, distCoeffs, None, newCameraMatrix) the undistorted new rgb and depth image.

Now I want to compute the pointcloud of the new undistorted depth image. But which camera Matrix should I use? The newCameraMatrix or the old one which I got from rs.getIntrinsic()? As well I used alpha=0, so there is no cropping of the image. But if I would use alpha = 1 there would be a cropping. In that case should I use the cropped image or the uncropped one?

Here is the full Code for calculating the distortion and newCameraMatrix:

checkerboard = (6, 10)
criteria = (cv2.TERM_CRITERIA_EPS +
            cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# Vector for 3D points
threedpoints = []
# Vector for 2D points
twodpoints = []

#  3D points real world coordinates
objectp3d = np.zeros((1, checkerboard[0]*checkerboard[1], 3), np.float32) 
objectp3d[0, :, :2] = np.mgrid[0:checkerboard[0], 0:checkerboard[1]].T.reshape(-1, 2)* 30

prev_img_shape = None
 
path = r"..."
resolution= "1280_720"
_,dates,_ = next(os.walk(path))

images = glob.glob(path)

print(len(images))

for filename in images:
    image = cv2.imread(filename)
    grayColor = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(image, checkerboard, flags = cv2.CALIB_CB_ADAPTIVE_THRESH )
    
    if ret == True :  
        threedpoints.append(objectp3d)

        # Refining pixel coordinates for given 2d points.
        corners2 = cv2.cornerSubPix(
            grayColor, corners,
             (11, 11),
             (-1, -1), criteria)
 
        twodpoints.append(corners2)
 
        # Draw and display the corners
        image = cv2.drawChessboardCorners(image,
                                          checkerboard,
                                          corners2, ret)

print("detected corners: ", len(twodpoints))
K_RS = np.load(r"path to RS intrinsic")

ret, matrix, distortion, r_vecs, t_vecs = cv2.calibrateCamera(
    threedpoints, twodpoints, grayColor.shape[::-1], cameraMatrix=K_RS, distCoeffs= None, flags= cv2.CALIB_USE_INTRINSIC_GUESS|cv2.CALIB_FIX_FOCAL_LENGTH|cv2.CALIB_FIX_PRINCIPAL_POINT)# None, None)
 
def loadUndistortedImage(filename, cameraMatrix, distCoeffs):
    image = cv2.imread(filename,-1)

    # setup enlargement and offset for new image
    imageShape = image.shape  #image.size
    imageSize = (imageShape[1],imageShape[0])

    # # create a new camera matrix with the principal point offest according to the offset above
    newCameraMatrix, roi = cv2.getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize,
    alpha = 0, imageSize)

    # create undistortion maps
    R = np.array([[1,0,0],[0,1,0],[0,0,1]])

    outputImage = cv2.undistort(image, cameraMatrix, distCoeffs, None, newCameraMatrix)
    roi_x, roi_y, roi_w, roi_h = roi
    cropped_outputImage = outputImage[roi_y : roi_y + roi_h, roi_x : roi_x + roi_w]
    
    fixed_filename = r"..."
    cv2.imwrite(fixed_filename,outputImage)
    return newCameraMatrix
    
#Undistort the images, then save the restored images
newmatrix = loadUndistortedImage(r'...', matrix, distortion)

Upvotes: 1

Views: 868

Answers (1)

CVexpert
CVexpert

Reputation: 1

I would suggest to use uncropped image that has same width and length of the original images that been used for camera calibration. The cropped one will has different image shape/size.

Upvotes: 0

Related Questions