# 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

Official site

GitHub

Wiki

Documentation