OpenCV solvePnPRansac() function

I am working on a 3D model reconstruction form multiple images project.

I have the camera matrix as well as 2D-3D point correspondence. I want to compute the projection matrix. I used cv.solvePnPRansac()function to get the projection matrix as follow:

retval, rvec, tvec, inliers = cv.solvePnPRansac(np.ascontiguousarray(np.squeeze(np.array(selectedpts3D)) [:,:-1]).reshape(len(selectedpts3D),1,3), np.ascontiguousarray(np.array(pts)[:,:-1]).reshape(len(pts),1,2), np.array(K_global), np.array([]), flags = cv.SOLVEPNP_ITERATIVE)

rvec_matrix = cv.Rodrigues(rvec)[0]

proj_matrix = np.hstack((rvec_matrix, tvec))


Then I factorize the output projection matrix to get camera matrix, rotation matrix and translation matrix as follow:

def factorize_proj_matrix(P):
""" Factorize the camera matrix into K,R,t as P = K[R|t]. """
# factor first 3*3 part
K1,R = linalg.rq(P[:,:3])
# make diagonal of K positive
T = np.diag(np.sign(np.diag(K1)))
if np.linalg.det(T) < 0:
T[1,1] *= -1
K1 = np.dot(K1,T)
R = np.dot(T,R) # T is its own inverse
t = np.dot(np.linalg.inv(K1),P[:,3])
return K1, R, t.reshape(3,1)


but the resulted camera matrix "K" has different values than the passed camera matrix to solvePnPRansac() function.

passed camera matrix to function is:

  [[1.5204e+03 0.0000e+00 3.0232e+02]
[0.0000e+00 1.5259e+03 2.4687e+02]
[0.0000e+00 0.0000e+00 1.0000e+00]]


output camera matrix is:

  array([[ 2.43791400e-03, -7.07610743e-21,  3.23838460e-22],
[ 0.00000000e+00,  2.43791400e-03, -2.88994138e-22],
[ 0.00000000e+00,  0.00000000e+00,  2.43791400e-03]])


My question is does cv.solvePnPRansac() function changes the cameraMatrix. if yes how to enforce it not to change the camera matrix?

edit retag close merge delete

Sort by » oldest newest most voted

Code:

Rotation_matrix_T = cv.Rodrigues(rvec)[0]
Rotation_matrix = Rotation_matrix_T.T
Translate_vector = - np.dot(Rotation_matrix , tvec)

Transformation_matrix = np.eye(4)
Transformation_matrix[:3, :3] = Rotation_matrix
Transformation_matrix[:3,  3] = Translate_vector

## method 1 ##
proj_matrix = np.hstack((Rotation_matrix_T, - np.dot(Rotation_matrix_T, Translate_vector)))

## method 2 ##
proj_matrix = np.zeros(3, 4)
Transformation_matrix_inv = np.linalg.inv(Transformation_matrix)
proj_matrix = Transformation_matrix_inv[:3, :4]

# # # # # # # # # # # # # # # # # #
# #     R | s*t                 # #
# # T = -------                 # #
# #     0 0 0 1                 # #
# #                             # #
# #           R.T | -R.T*s*t    # #
# # inv(T) =  --------------    # #
# #            0  0  0  1       # #
# #                             # #
# # P = R.T| -R.T*s*t           # #
# # P = inv(T)[:3, :4]          # #
# # # # # # # # # # # # # # # # # #
# s = Scale You don't need it now #
# # # # # # # # # # # # # # # # # #


This projection Matrix don't contain Camera Matrix

proj_matrix_Final_Camera1 = np.dot(cameraMatrix, np.eye(4)[:3, :4])
proj_matrix_Final_Camera2 = np.dot(cameraMatrix, proj_matrix)


To answer your question: The rvec and tvec returned by solvepnp don't include the values of the camera matrix. The rotation and translation are recovered in this way

Rotation = cv.rodriges (rvec) [0] .T
Traslation = - np.dot (Rotation.T, tvec)

more