Skip to content

Instantly share code, notes, and snippets.

@benoitrosa
Created October 3, 2017 16:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save benoitrosa/ffdb96eae376503dba5ee56f28fa0943 to your computer and use it in GitHub Desktop.
Save benoitrosa/ffdb96eae376503dba5ee56f28fa0943 to your computer and use it in GitHub Desktop.
Example for setting camera intrinsics in VTK using python
import vtk
import numpy as np
from vtk.util import numpy_support
import cv2
class Camera_VTK():
"""
Example class showing how to project a 3D world coordinate onto a 2D image plane using VTK
"""
def __init__(self, w, h, P, K):
self.w = w
self.h = h
self.P = P # position of 3D sphere
self.K = K # Camera matrix
self.f = np.array( [K[0,0], K[1,1]] ) # focal lengths
self.c = K[:2,2] # principal point
# projection of 3D sphere center onto the image plane
self.p_im = np.dot(self.K,P.reshape(3,1)).flatten()
self.p_im /= self.p_im[-1]
self.init_vtk()
def getImage(self):
"""
Render a sphere using VTK into an image, and plot the projection of that sphere onto the image plane. They should coincide
"""
# Set basic camera parameters in VTK
cam = self.renderer.GetActiveCamera()
near = 0.1
far = 1000.0
cam.SetClippingRange(near, far)
# Position is at origin, looking in z direction with y down
cam.SetPosition(0, 0, 0)
cam.SetFocalPoint(0, 0, 1)
cam.SetViewUp(0, -1, 0)
w,h = self.w, self.h
# Set window center for offset principal point
wcx = -2.0*(self.c[0] - self.w / 2.0) / self.w
wcy = 2.0*(self.c[1] - self.h / 2.0) / self.h
cam.SetWindowCenter(wcx, wcy)
# Set vertical view angle as a indirect way of setting the y focal distance
angle = 180 / np.pi * 2.0 * np.arctan2(self.h / 2.0, self.f[1])
cam.SetViewAngle(angle)
# Set the image aspect ratio as an indirect way of setting the x focal distance
m = np.eye(4)
aspect = self.f[1]/self.f[0]
m[0,0] = 1.0/aspect
t = vtk.vtkTransform()
t.SetMatrix(m.flatten())
cam.SetUserTransform(t)
# Render the scene into a numpy array for openCV processing
self.renWin.Render()
winToIm = vtk.vtkWindowToImageFilter()
winToIm.SetInput(self.renWin)
winToIm.Update()
vtk_image = winToIm.GetOutput()
width, height, _ = vtk_image.GetDimensions()
vtk_array = vtk_image.GetPointData().GetScalars()
components = vtk_array.GetNumberOfComponents()
arr = cv2.flip(numpy_support.vtk_to_numpy(vtk_array).reshape(height, width, components), 0)
arr = cv2.cvtColor(arr, cv2.COLOR_BGR2RGB)
# Draw a circle at the projected place of the 3D sphere onto the image plane
cv2.circle(arr,(int(self.p_im[0]),int(self.p_im[1])),5,(0,0,255),1)
return arr
def init_vtk(self):
"""
Initialize VTK actors and rendering pipeline
"""
self.shpereSource = vtk.vtkSphereSource()
self.shpereSource.SetCenter(self.P[0],self.P[1],self.P[2])
self.shpereSource.SetRadius(1.0)
self.shperemapper = vtk.vtkPolyDataMapper()
self.shperemapper.SetInputConnection(self.shpereSource.GetOutputPort())
self.shpereactor = vtk.vtkActor()
self.shpereactor.SetMapper(self.shperemapper)
self.renderer = vtk.vtkRenderer()
self.renWin = vtk.vtkRenderWindow()
self.renWin.SetOffScreenRendering(1)
self.renderer.AddActor(self.shpereactor)
self.renderer.SetBackground(0.1, 0.2, 0.4)
self.renderer.ResetCamera()
self.renWin.AddRenderer(self.renderer)
self.renWin.SetSize(self.w, self.h)
self.renWin.Render()
if __name__ == '__main__':
fx = 500.0
fy = 400.0
cx = 395.0
cy = 275.0
w = 760
h = 570
K = np.array( [ [fx, 0., cx],
[ 0. ,fx, cy],
[0.,0.,1.]])
P = np.array([ 11.14230157 , 11.23046172 , 28.56272345])
test = Camera_VTK(w,h,P,K)
arr = test.getImage()
cv2.imshow("test", arr)
cv2.waitKey(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment