Home > Software engineering >  Project 3D points to 2D points in python
Project 3D points to 2D points in python

Time:11-30

I'm trying to project 3D body keypoints to 2D keypoints, My 3D points are:

points = np.array([[-7.55801499e-02, -3.69511306e-01, -2.63576955e-01],
   [ 0.00000000e 00,  0.00000000e 00,  0.00000000e 00],
   [ 3.08661222e-01, -2.93346141e-02,  3.72593999e-02],
   [ 5.96781611e-01, -2.82074720e-01,  4.71359938e-01],
   [ 5.38534284e-01, -8.05779934e-01,  4.68694866e-01],
   [-3.67936224e-01, -1.09069087e-01,  9.90774706e-02],
   [-5.24732828e-01, -2.87176669e-01,  6.09635711e-01],
   [-4.37022656e-01, -7.87327409e-01,  4.43706572e-01],
   [ 1.33009470e-09, -5.10657072e-09,  1.00000000e 00],
   [ 1.13241628e-01,  3.25177647e-02,  1.24026799e 00],
   [ 3.43442023e-01, -2.51034945e-01,  1.90472209e 00],
   [ 2.57550180e-01, -2.86886752e-01,  2.75528717e 00],
   [-1.37361348e-01, -2.60521360e-02,  1.19951272e 00],
   [-3.26779515e-01, -5.59706092e-01,  1.75905156e 00],
   [-4.65996087e-01, -7.69565761e-01,  2.56634569e 00],
   [-1.89841837e-02, -3.19088846e-01, -3.69913191e-01],
   [-1.61812544e-01, -3.10732543e-01, -3.47061515e-01],
   [ 7.68100023e-02, -1.19293019e-01, -3.72248143e-01],
   [-2.24317372e-01, -1.02143347e-01, -3.32051814e-01],
   [-3.77829641e-01, -1.19915462e 00,  2.56900430e 00],
   [-5.45104921e-01, -1.13393784e 00,  2.57149625e 00],
   [-5.66698492e-01, -6.89325571e-01,  2.67840290e 00],
   [ 4.65222150e-01, -6.44857705e-01,  2.83186650e 00],
   [ 5.27995050e-01, -4.69421804e-01,  2.87518311e 00],
   [ 1.77749291e-01, -1.74753308e-01,  2.88810611e 00]])

I plotted them using:

fig = plt.figure()
ax = plt.axes(projection='3d')
ax.set_xlim3d(1, -1)
ax.set_ylim3d(1, -1)
ax.set_zlim3d(1, -1)
ax.scatter3D(points[:, 0], points[:, 1],
      points[:, 2], cmap='Greens')

The result is: enter image description here

I want an array of 2D points with the same camera view, so my desired result a 2D array: enter image description here

I have tried so far:

import cv2
ans = []
for k in range(25):
  tmp = np.array(s[0, k, :]).reshape(1,3)
  revc = np.array([0, 0, 0], np.float)  # rotation vector
  tvec = np.array([0, 0, 0], np.float)  # translation vector
  fx = fy = 1.0
  cx = cy = 0.0
  cameraMatrix = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]])
  result = cv2.projectPoints(tmp, revc, tvec, cameraMatrix, None)
  ans.append(result[0])

ans = np.array(ans).squeeze()

But the result I'm getting is:

plt.scatter(ans[:,0], ans[:, 1])

enter image description here

I can't figure out why the information is lost during projection, kindly help me in this. Also its not necessary for me to use OpenCV so you can suggest other methods like using numpy too.

Thanks

CodePudding user response:

Here's a way to do this from "scratch". I have the following import statements:

import numpy as np
import matplotlib.pyplot as plt
from numpy import sin,cos,pi
from scipy.linalg import norm

After your 3d plotting code, I added the following:

azim = ax.azim*pi/180
elev = ax.elev*pi/180
elev *= 1.2          # this seems to improve the outcome

a_vec = np.array([cos(azim),sin(azim),0])
normal = cos(elev)*a_vec   np.array([0,0,sin(elev)])

z_vec = np.array([0,0,1])
y_comp = z_vec - (z_vec@normal)*normal
y_comp = y_comp/norm(y_comp)
x_comp = np.cross(y_comp,normal)

proj_mat = np.vstack([x_comp,y_comp]) # build projection matrix
proj_mat = -proj_mat                  # account for flipped axes
points_2D = points @ proj_mat.T       # apply projection

plt.figure()
plt.scatter(*points_2D.T)
plt.gca().set_aspect('equal', adjustable='box')
plt.axis('off')
plt.show()

The resulting points:

enter image description here

  • Related