Why R is not considered in cv2.undistortPoints?

Why following pairs can get same result respectively? R is not considered in the function.

Pair One:
cv2.undistortPoints(pts, K, None,None, None)
cv2.undistortPoints(pts, K, None,R, None)

Pair Two:
cv2.undistortPoints(pts, K, D,None, None)
cv2.undistortPoints(pts, K, D, R, None)

what is the value of R?

R is a rotation matrix, e.g.
R=np.array([[ 0.9999648 , -0.0069988 , 0.00462683],
[ 0.00702214, 0.99996259, -0.00504964],
[-0.00459131, 0.00508195, 0.99997655]])

I investigated the source. R is only used if P is also given: opencv/undistort.dispatch.cpp at 17234f82d025e3bbfbf611089637e5aa2038e7b8 · opencv/opencv · GitHub

this certainly deviates from the documentation. I believe it’s a bug. I’ve filed an issue.

Although R is changed to a large one and both R and P are given, the same issue still exists.

pts=np.array([[  0., 639.,   0., 639.],
              [  0.,   0., 479., 479.],
              [  1.,   1.,   1.,   1.]])
K=np.array([[536.86303957,   0.        , 338.54127669],
            [  0.        , 537.17967509, 231.541806  ],
            [  0.        ,   0.        ,   1.        ]])

R=cv2.Rodrigues(np.array([-.1,.1,.3]))[0]

P=np.array([[538.40307187,   0.        , 341.6945076 ,    0.        ],
             [  0.        , 538.40307187, 243.63676453,   0.        ],
             [  0.        ,   0.        ,   1.        ,   0.        ]])

#only R is given without P
pts_0=cv2.undistortPoints(pts[:2], K, None, None, None)
pts_1=cv2.undistortPoints(pts[:2], K, None, R, None)
print(np.allclose(pts_0, pts_1)) #True

#both R and P are given
pts_2=cv2.undistortPoints(pts[:2], K, None, R, P[:3,:3]) 
temp=np.ones((3,4))
temp[:2]=pts_0.squeeze().T
temp=P[:3,:3]@temp
print(np.allclose(temp[:2]/temp[-1],pts_2.squeeze().T)) #True

yes, I judged the OpenCV code too quickly. P seems irrelevant to the issue… and the given value for R is simply not affecting the calculation.

must be something they do with these old C APIs

OK! This bug has been submitted to github for your reference:

Thanks!

upon further investigation, it appears that one argument gets assigned to the dst parameter, and the intended parameter is never given a value.

The function signature is:
undistortPoints(src, cameraMatrix, distCoeffs[, dst[, R[, P]]]) -> dst

fix this by using named arguments:

further, I would recommend care with the shape of the src argument. OpenCV does have some tolerance for weirdly shaped data but generally it expects a column vector of 2-channel elements. if you had just two points, the corresponding 2x2 array would be ambiguous. it’s best to establish a shape of (N, 1, 2) which is unambiguous.

It works! Thank you very much!