python vtk: how to get the right intrinsic and extrinsic matrix given a camera?


def off_screen_render(file_in, file_out):
    """
    Save the render screen to a png file
    Args:
        file_in: .vtp file path
        file_out: .png file path
    """
    colors = vtk.vtkNamedColors()

    # Set up reader
    reader = vtk.vtkSTLReader()
    reader.SetFileName(file_in)

    # Set up mapper
    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputConnection(reader.GetOutputPort())

    # Set up actor
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.GetColor3d('white'))

    # Set up renderer and render window
    renderer = vtk.vtkRenderer()
    render_window = vtk.vtkRenderWindow()
    render_window.OffScreenRenderingOn()
    render_window.AddRenderer(renderer)

    # Add actor to renderer and set background color
    renderer.AddActor(actor)
    renderer.SetBackground(colors.GetColor3d('black'))

    camera = renderer.GetActiveCamera()
 
       # Get the extrinsic matrix
    extrinsic_matrix = array_from_vtkmatrix(camera.GetModelViewTransformMatrix())
   
    camera.Azimuth(90)
    camera.Elevation(0)
    renderer.ResetCamera()
  
    # Render and save image
    render_window.Render()

    render_window_size = render_window.GetSize()
     intrinsic_matrix = camera.GetProjectionTransformMatrix(render_window_size[0] / render_window_size[1],
                                                      camera.GetClippingRange()[0],
                                                      camera.GetClippingRange()[1])
    
    # window to image
    window2image = vtk.vtkWindowToImageFilter()
    window2image.SetInput(render_window)

    # png writer
    writer = vtk.vtkPNGWriter()
    writer.SetFileName(file_out)
    writer.SetInputConnection(window2image.GetOutputPort())
    writer.Write()

    return extrinsic_matrix, array_from_vtkmatrix(intrinsic_matrix)

reader = vtk.vtkSTLReader()
reader.SetFileName("data/new_tree.vtp")
reader.Update()

# Get the 3D points
polydata = reader.GetOutput()

points = np.asarray(polydata.GetPoints().GetData())
points_homog = np.hstack((points, np.ones((len(points), 1))))

extr, intr = off_screen_render('data/new_tree.vtp', 'data/osr.png')

points_homog = np.dot(np.linalg.inv(extr), points_homog.T).T
points_proj_homog = np.dot(intr, points_homog.T).T
points_proj = points_proj_homog[:, :2] / points_proj_homog[:, 2:3]

fig, ax = plt.subplots()
# ax.invert_yaxis()
ax.scatter(points_proj[:,0], points_proj[:,1])

In the code above I’ve tried to get the intrinsic and extrinsic matrices from a given camera, the camera has been moved by invoking camera.Azimuth(). To verify the correctness, I use the matrices to project the 3d points to the 2d panel, however, i cannot get the same shape as saved in the rendered image. I’m confused about the meaning of the GetModelViewTransformMatrix() and the GetProjectionTransformMatrix(), shouldn’t it be the extrinsic and the intrinsic matrices?
It would be deeply appreciated if you could give me a hand.

Woody