0

I'm trying to use OpenCV's solvePnPRansac method to locate the camera position around a 3D model loaded in Blender. However, manually putting in points gives me an incorrect t/r vector and cv2.projectPoints gets the image coordinates wrong, so I suspect something about the input is messed up.

I manually selected 10 points on the 3D model in Blender's arbitrary units, and used those as the world coordinates. I found the corresponding locations of those points in the 960x540 rendered image, and those are my input 2D coordinates (by pixels).

The camera's focal length and sensor size are set to 40mm focal and 40x18mm sensor, and since this is mm I manually measured both as approximated their lengths in pixels as about 916 pixels and 412 pixels - however, both these sets of values give me coordinates that are completely off.

The output of projectPoints for me are coordinates that range from -13,000 to 20,000. I think my input values are incorrect but how do I fix this?

size = (960, 540)
image_points = np.array([
                        (315, 279), # 1
                        (440, 273), # 2
                        (407, 386), # 3
                        (369, 372), # 4
                        (440, 317), # 5
                        (457, 373), # 6
                        (439, 385), # 7
                        (369, 337), # 8
                        (407, 358), # 9
                        (313, 291), # 10
                    ], dtype="double")

model_points = np.array([
                            (0.77644, -0.63806, 2.55822), # stripe of adidas 1/3 down
                            (0.75437, 0.49247, 2.75569), # first curve up on the logo
                            (0.82970, 0.17763, 1.58873), # lower right part of hole in a
                            (0.82900, -0.16946, 1.68983), # 1/3 down left side of i
                            (0.84466, 0.52011, 2.37269), # bottom of gold circle left of F
                            (0.67476, 0.59525, 1.68853), # left side of thick top 's'
                            (0.74288, 0.46100, 1.58926), # inwards (left) of right below e joint
                            (0.82560, -0.14537, 2.07217), # middle of f top bar, left of upwards
                            (0.83161, 0.17382, 1.88820), # middle line of a near bottom of Y
                            (0.78115, -0.66043, 2.46363) # 1/4 up 2nd d circle in adidas
                        ], dtype = "double")

f = 916.8
sx = 916.8
sy = 412.56

width, height = (size[1], size[0])

camera_matrix = np.array([
                [width*f/sx, 0, width/2],
                [0, height*f/sy, height/2],
                [0, 0, 1]
                ], dtype = "double")

dist_coeffs = np.zeros((4,1))
s,t,r, i = cv2.solvePnPRansac(model_points, image_points, camera_matrix, dist_coeffs)

img, x = cv2.projectPoints(model_points, r, t, camera_matrix, dist_coeffs)
print(img)           
Almond Joy
  • 119
  • 12
  • [here](https://imgur.com/a/GdFZWIz) is the 2D image I'm using to locate the camera! – Almond Joy Feb 13 '19 at 16:37
  • I have also tried flipping the image coordinates (y,x) instead of (x,y) and both give me results where projectPoints does not match up – Almond Joy Feb 13 '19 at 16:42
  • solePnP computes the object pose with a stationary camera. Do you get better results if you invert the transformation (which would be same as computing the camera pose for a stationary object)? – Micka Feb 13 '19 at 17:20
  • I am inverting the transformation and it's still extremely far off! I started to just use projectPoints as shown at the bottom of the code sample to see if the transformation could turn the points it used as a reference from object to camera, and this fails pretty spectacularly – Almond Joy Feb 13 '19 at 18:36

0 Answers0