triangulatePoints
X = cv2.triangulatePoints(P0, P1, x0, x1)
• P0.shape = (3,4): Camera projection from X to x0 • P1.shape = (3,4): Camera projection from X to x1 • x0.shape = (2,-1): 2D points • x1.shape = (2,-1): 2D points • X.shape = (4,-1): 3D points
Important: Divide X by X[3] to make it homogeneous.
X = cv2.triangulatePoints(P0, P1, x0, x1) X /= X[3] #(wx,wy,wz,w) -> (x,y,z,1)
———————————————————
Rodrigues
R3,J = cv2.Rodrigues(R3x3)
R3x3,J = cv2.Rodrigues(R3)
• R3.shape = (3,1) or (3,) or (1,3): Rotation vector (radians) • R3x3.shape = (3,3): Rotation matrix • J.shape = (9,3) or (3,9): Jacobian
Important: When applied twice (R3 -> R3x3 -> R3), the resulting rotation vector might look different if the values are greater than pi/2, but it represents the same rotation.
R = r_[1.,2.,1.] R = cv2.Rodrigues(R)[0] #I only use the first return value
———————————————————
decomposeProjectionMatrix
R,t = cv2.decomposeProjectionMatrix( P )[1:3]
• P.shape = (3,4): Camera projection matrix { x = dot(P,X) }
• R.shape = (3,3): Rotation matrix
• t.shape = (4,1): 3D Camera position in world coordinates
Important: Divide t by t[3] to make it homogeneous. This ‘t‘ is not the one in P = [R|t]. It is the one in P = [R | R(-t)]
R,t = cv2.decomposeProjectionMatrix( P )[1:3] t /= t[3] #Position of camera. (wx,wy,wz,w) -> (x,y,z,1)
Recompose the projection matrix like this:
P = append(R, dot(R,-t[:3]),1)
The ‘t‘ is negative because world points are shifted in the opposite direction of the camera position.
———————————————————
correctMatches
x0c, x1c = cv2.correctMatches(F, x0, x1)
• F.shape = (3,3): Fundamental or essential matrix • x0.shape = (1,-1,2): 2D points from 1st image • x1.shape = (1,-1,2): 2D points from 2nd image • x0c.shape = (1,-1,2): Optimized 2D points • x1c.shape = (1,-1,2): Optimized 2D points
Important: The point format is different than other cv2 methods.
# x0 and x1 have shape 3xN. Convert them inline to 1xNx2 x0c, x1c = cv2.correctMatches( F, r_[[x0[:2].T]], r_[[x1[:2].T]] ) # Convert the result from 1xNx2 to 3xN. x0c = append(x0c[0].T,ones((1,len(x0c[0]))),0)
———————————————————
solvePnP
r,t = cv2.solvePnP( X, x, K, distCoeffs)[1:3]
• X.shape = (-1,3) or (1,-1,3): 3D points (origin coordinates) • x.shape = (-1,2) or (1,-1,2): 2D image location • K.shape = (3,3): Use eye(3) for normalized points • distCoeffs = None: 'None' or array of 4, 5 or 8 values • r.shape = (3,1): Rotation vector (radians) • t.shape = (3,1): Translation vector, the 't' in [R|t]
Important: This ‘t‘ is not the camera position in world coordinates but the actual last column of the camera projection matrix. Just append ‘t‘ to the 3×3 R matrix.
r,t = cv2.solvePnP(X[:3].T, x[:2].T, eye(3), None)[1:3] # Compose the camera projection. Check it with x = dot(P,X) P = append( cv2.Rodrigues( r )[0], t, 1 )
———————————————————
convertPointsFromHomogeneous
x = cv2.convertPointsFromHomogeneous( xh )
• xh.shape = (-1,1,3) or (1,-1,3): (wx,wy,w) or (wx,wy,wz,w) • x.shape = (-1,1,2): (x,y) or (x,y,z)
Important: This cv2 method is unnecessary but it was difficult to figure out how to use it, so maybe this will save you some frustration.
# xh is a 3xN or 4xN array of points, x is 2xN or 3xN respectively x = cv2.convertPointsFromHomogeneous(r_[[xh.T]].astype(float32)) # Or simply do this instead x = xh[:-1]/xh[-1]
———————————————————
convertPointsToHomogeneous
xh = cv2.convertPointsToHomogeneous( x )
• x.shape = (-1,1,2) or (1,-1,2): (x,y) or (x,y,z) • x.shape = (-1,1,3): (x,y,1) or (x,y,z,1)
Important: This cv2 method is also unnecessary but it was difficult to figure out how to use it, so maybe this will save you some frustration.
# xh is a 3xN or 4xN array of points, x is 2xN or 3xN respectively xh = cv2.convertPointsToHomogeneous(r_[[x.T]].astype(float32)) # Or do this instead xh = append(x,ones((1,len(x[0]))),0)