Eyal S.
Eyal S.

Reputation: 1161

Calibrate Camera with only radial distortion

I'm trying to run camera calibration using opencv in python. I'm using:

cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)

and it seems like it is working well for 5 distortion coefficients. However, I would like to try and run it without the tangential distortion and possibly with only 2 radial distortion coefficients. Is that possible?

Upvotes: 1

Views: 4567

Answers (2)

motobói
motobói

Reputation: 1805

The relevant documentation:

distCoeffs – Output vector of distortion coefficients formula of 4, 5, or 8 elements.

CV_CALIB_USE_INTRINSIC_GUESS cameraMatrix contains valid initial values of fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image center ( imageSize is used), and focal distances are computed in a least-squares fashion. Note, that if intrinsic parameters are known, there is no need to use this function just to estimate extrinsic parameters. Use solvePnP() instead.

CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6 The corresponding radial distortion coefficient is not changed during the optimization. If CV_CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0.

CV_CALIB_ZERO_TANGENT_DIST Tangential distortion coefficients formula are set to zeros and stay zero.

IMPORTANT: in Python, cv flags DON'T BEGIN WITH CV_. So I will remove them from now on.


What the documentation means is:

If you already have a camera matrix AND distortion coefficient vector, you can supply them to the calibration as an initial value and let it guess from there (using CALIB_USE_INTRINSIC_GUESS). You can supply an initial distortion vector and make some components of it static (will always be the supplied value) with the CALIB_FIX_K1,…,CALIB_FIX_K6 flags.

BUT: if you set CALIB_FIX_K1, CALIB_FIX_K2, CALIB_FIX_K3, CALIB_FIX_K4, CALIB_FIX_K5 or CALIB_FIX_K6 without giving an initial estimate, they will be set to zero.

Note that the result distCoeffs vector will be: [K1, K2, tangential1, tangential2, K3]. OpenCV will give you K4, K5 or K6 only if you explicitly ask for it with CALIB_RATIONAL_MODEL.

So, if you want no tangential distortion factors and only two radial distortion factors, you can supply flags=CALIB_FIX_K3 + CALIB_ZERO_TANGENT_DIST. You don't need distCoeffs or just pass it as distCoeffs=None.

success, mtx, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(
        objectPoints, imagePoints, (width, height),
        flags=CALIB_FIX_K3 + CALIB_ZERO_TANGENT_DIST)

print(distCoeffs)

This will result in a distortion vector like this:

[ 0.10509459 -0.31389323 0. 0. 0. ]

Upvotes: 2

Eyal S.
Eyal S.

Reputation: 1161

I found the answer.

For no tangential distortion:

 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None, 4,None,None,cv2.CALIB_ZERO_TANGENT_DIST,
                                                   criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 2e-16))

For only 2 radial distortion coefficients it seems like the documentation suggests using 4 instead of 5 for the number of coefficients. That does not seem to work. Instead I fix the k3 parameter:

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None, 4,None,None,cv2.CALIB_ZERO_TANGENT_DIST+cv2.CALIB_FIX_K3,
                                                   criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 2e-16))

Upvotes: 2

Related Questions