Reputation: 21
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
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