Created
October 3, 2017 16:38
-
-
Save benoitrosa/ffdb96eae376503dba5ee56f28fa0943 to your computer and use it in GitHub Desktop.
Example for setting camera intrinsics in VTK using python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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