-
-
Save decrispell/fc4b69f6bedf07a3425b to your computer and use it in GitHub Desktop.
/** | |
* Convert standard camera intrinsic and extrinsic parameters to a vtkCamera instance for rendering | |
* Assume square pixels and 0 skew (for now). | |
* | |
* focal_len : camera focal length (units pixels) | |
* nx,ny : image dimensions in pixels | |
* principal_pt: camera principal point, | |
* i.e. the intersection of the principal ray with the image plane (units pixels) | |
* camera_rot, camera_trans : rotation, translation matrix mapping world points to camera coordinates | |
* depth_min, depth_max : needed to set the clipping range | |
* | |
**/ | |
vtkSmartPointer<vtkCamera> make_vtk_camera(double focal_len, | |
int nx, int ny, | |
vgl_point_2d<double> const& principal_pt, | |
vgl_rotation_3d<double> const& camera_rot, | |
vgl_vector_3d<double> const& camera_trans, | |
double depth_min, double depth_max) | |
{ | |
// create the camera | |
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New(); | |
// convert camera rotation and translation into a 4x4 homogeneous transformation matrix | |
vtkSmartPointer<vtkMatrix4x4> camera_RT = make_transform(camera_rot, camera_trans); | |
// apply the transform to scene objects | |
camera->SetModelTransformMatrix( camera_RT ); | |
// the camera can stay at the origin because we are transforming the scene objects | |
camera->SetPosition(0, 0, 0); | |
// look in the +Z direction of the camera coordinate system | |
camera->SetFocalPoint(0, 0, 1); | |
// the camera Y axis points down | |
camera->SetViewUp(0,-1,0); | |
// ensure the relevant range of depths are rendered | |
camera->SetClippingRange(depth_min, depth_max); | |
// convert the principal point to window center (normalized coordinate system) and set it | |
double wcx = -2*(principal_pt.x() - double(nx)/2) / nx; | |
double wcy = 2*(principal_pt.y() - double(ny)/2) / ny; | |
camera->SetWindowCenter(wcx, wcy); | |
// convert the focal length to view angle and set it | |
double view_angle = vnl_math::deg_per_rad * (2.0 * std::atan2( ny/2.0, focal_len )); | |
std::cout << "view_angle = " << view_angle << std::endl; | |
camera->SetViewAngle( view_angle ); | |
return camera; | |
} | |
/** | |
* Helper function: Convert rotation and translation into a vtk 4x4 homogeneous transform | |
*/ | |
vtkSmartPointer<vtkMatrix4x4> make_transform(vgl_rotation_3d<double> const& R, | |
vgl_vector_3d<double> const& T) | |
{ | |
vtkSmartPointer<vtkMatrix4x4> m = vtkSmartPointer<vtkMatrix4x4>::New(); | |
vnl_matrix_fixed<double,3,3> R_mat = R.as_matrix(); | |
for (int r=0; r<3; ++r) { | |
for (int c=0; c<3; ++c) { | |
m->SetElement(r,c,R_mat[r][c]); | |
} | |
} | |
m->SetElement(0,3,T.x()); | |
m->SetElement(1,3,T.y()); | |
m->SetElement(2,3,T.z()); | |
m->SetElement(3,3,1); | |
return m; | |
} |
Awesome, this saved me a lot of experimentation, thanks!
Thanks a lot! That is really helpful for the augmented reality, I have been stuck here for a while.
what is the coordinate system here? +X left, +Y down, +Z forward?
^
/
z
/
--- x --->
|
y
|
v
Note: I am trying to get the same result but using python.
what is the coordinate system here? +X left, +Y down, +Z forward?
^ / z / --- x ---> | y | v
Note: I am trying to get the same result but using python.
Yes, that is correct. Origin at upper left corner of the image.
Thanks for the answer! Ok, I have a working version for python and pyvista (VTK):
pyvista/pyvista#1215
Thanks a lot for sharing this! It saved me a lot of time.
Is this correct? Why wcy
doesn't have the -2
?
// convert the principal point to window center (normalized coordinate system) and set it
double wcx = -2*(principal_pt.x() - double(nx)/2) / nx;
double wcy = 2*(principal_pt.y() - double(ny)/2) / ny;
I tried increasing the windows size, nx2 and nyy but it seems there something wrong here.
I believe there is no negative sign on wcy
because the direction of the y axis is "up" in the opengl normalized coordinate system. That said, this code may have only been tested with the principal point at the image center, in which case the term in the parentheses is 0 and the negative sign (or lack thereof) doesn't matter. So it is possible that something is wrong - (Sorry, it's been a while)
If you are increasing the window size (nx and ny), you probably also want to increase the principal point, so keep that in mind.
This works! Great Appreciation!