Commit 4a1573de authored by ozantonkal's avatar ozantonkal

principal point is always set even though the intrinsic parameters are not given…

principal point is always set even though the intrinsic parameters are not given (center of window), fixed computation mistakes in setWindowSize in camera class
parent bb057491
......@@ -155,10 +155,11 @@ cv::viz::Camera::Camera(const Vec2f &fov, const Size &window_size)
{
CV_Assert(window_size.width > 0 && window_size.height > 0);
setClip(Vec2d(0.01, 1000.01)); // Default clipping
principal_point_ = Vec2f(-1.0f, -1.0f); // Default symmetric lens
focal_ = Vec2f(-1.0f, -1.0f);
setFov(fov);
setWindowSize(window_size);
window_size_ = window_size;
// Principal point at the center
principal_point_ = Vec2f(static_cast<float>(window_size.width)*0.5f, static_cast<float>(window_size.height)*0.5f);
focal_ = Vec2f(principal_point_[0] / tan(fov_[0]*0.5f), principal_point_[1] / tan(fov_[1]*0.5f));
}
cv::viz::Camera::Camera(const cv::Matx33f & K, const Size &window_size)
......@@ -172,6 +173,8 @@ cv::viz::Camera::Camera(const cv::Matx33f & K, const Size &window_size)
cv::viz::Camera::Camera(const Matx44f &proj, const Size &window_size)
{
CV_Assert(window_size.width > 0 && window_size.height > 0);
double near = proj(2,3) / (proj(2,2) - 1.0);
double far = near * (proj(2,2) - 1.0) / (proj(2,2) + 1.0);
double left = near * (proj(0,2)-1) / proj(0,0);
......@@ -179,32 +182,19 @@ cv::viz::Camera::Camera(const Matx44f &proj, const Size &window_size)
double bottom = near * (proj(1,2)-1) / proj(1,1);
double top = 2.0 * near / proj(1,1) + bottom;
if (fabs(left-right) < std::numeric_limits<double>::epsilon())
{
principal_point_[0] = -1.0f;
focal_[0] = -1.0f;
}
else
{
principal_point_[0] = (left * static_cast<float>(window_size.width)) / (left - right);
focal_[0] = - near * principal_point_[0] / left;
}
if (fabs(left-right) < std::numeric_limits<double>::epsilon()) principal_point_[0] = static_cast<float>(window_size.width) * 0.5f;
else principal_point_[0] = (left * static_cast<float>(window_size.width)) / (left - right);
focal_[0] = -near * principal_point_[0] / left;
if (fabs(top-bottom) < std::numeric_limits<double>::epsilon())
{
principal_point_[1] = -1.0f;
focal_[1] = -1.0f;
}
else
{
principal_point_[1] = (top * static_cast<float>(window_size.height)) / (top - bottom);
focal_[1] = near * principal_point_[1] / top;
}
if (fabs(top-bottom) < std::numeric_limits<double>::epsilon()) principal_point_[1] = static_cast<float>(window_size.height) * 0.5f;
else principal_point_[1] = (top * static_cast<float>(window_size.height)) / (top - bottom);
focal_[1] = near * principal_point_[1] / top;
setClip(Vec2d(near, far));
// Set the vertical field of view
fov_[0] = (atan2(principal_point_[0],focal_[0]) + atan2(window_size.width-principal_point_[0],focal_[0]));
fov_[1] = (atan2(principal_point_[1],focal_[1]) + atan2(window_size.height-principal_point_[1],focal_[1]));
setWindowSize(window_size);
window_size_ = window_size;
}
void cv::viz::Camera::init(float f_x, float f_y, float c_x, float c_y, const Size &window_size)
......@@ -221,50 +211,32 @@ void cv::viz::Camera::init(float f_x, float f_y, float c_x, float c_y, const Siz
focal_[0] = f_x;
focal_[1] = f_y;
setWindowSize(window_size);
window_size_ = window_size;
}
void cv::viz::Camera::setWindowSize(const Size &window_size)
{
CV_Assert(window_size.width > 0 && window_size.height > 0);
// Vertical field of view is fixed!
// Horizontal field of view is expandable based on the aspect ratio
float aspect_ratio_new = static_cast<float>(window_size.width) / static_cast<float>(window_size.height);
// Get the scale factor and update the principal points
if (window_size_.height != 0)
{
float aspect_ratio_old = window_size_.width / window_size_.height;
float expected_width = aspect_ratio_old * window_size.height;
float scale = window_size_.width / expected_width;
principal_point_[0] *= scale;
principal_point_[1] *= static_cast<float>(window_size.height) / static_cast<float>(window_size_.height);
}
if (principal_point_[0] < 0.0f)
fov_[0] = 2.f * atan(tan(fov_[1] * 0.5f) * aspect_ratio_new); // This assumes that the lens is symmetric!
else
fov_[0] = (atan2(principal_point_[0],focal_[0]) + atan2(window_size.width-principal_point_[0],focal_[0]));
float scalex = static_cast<float>(window_size.width) / static_cast<float>(window_size_.width);
float scaley = static_cast<float>(window_size.height) / static_cast<float>(window_size_.height);
principal_point_[0] *= scalex;
principal_point_[1] *= scaley;
focal_ *= scaley;
// Vertical field of view is fixed! Update horizontal field of view
fov_[0] = (atan2(principal_point_[0],focal_[0]) + atan2(window_size.width-principal_point_[0],focal_[0]));
window_size_ = window_size;
}
void cv::viz::Camera::computeProjectionMatrix(Matx44f &proj) const
{
// Symmetric case
double top = clip_[0] * tan (0.5 * fov_[1]);
double left = -(top * window_size_.width) / window_size_.height;
double right = -left;
double bottom = -top;
// If principal point is defined (i.e intrinsic parameters are known)
if (principal_point_[0] > 0.0f)
{
top = clip_[0] * principal_point_[1] / focal_[1];
left = -clip_[0] * principal_point_[0] / focal_[0];
right = clip_[0] * (window_size_.width - principal_point_[0]) / focal_[0];
bottom = -clip_[0] * (window_size_.height - principal_point_[1]) / focal_[1];
}
double top = clip_[0] * principal_point_[1] / focal_[1];
double left = -clip_[0] * principal_point_[0] / focal_[0];
double right = clip_[0] * (window_size_.width - principal_point_[0]) / focal_[0];
double bottom = -clip_[0] * (window_size_.height - principal_point_[1]) / focal_[1];
double temp1 = 2.0 * clip_[0];
double temp2 = 1.0 / (right - left);
......
......@@ -569,18 +569,16 @@ void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera)
vtkCamera& active_camera = *renderer_->GetActiveCamera();
// Set the intrinsic parameters of the camera
active_camera.SetUseHorizontalViewAngle (0); // Horizontal view angle is set based on the window size
active_camera.SetViewAngle (camera.getFov()[1] * 180.0f / CV_PI);
active_camera.SetClippingRange (camera.getClip()[0], camera.getClip()[1]);
window_->SetSize (camera.getWindowSize().width, camera.getWindowSize().height);
double aspect_ratio = static_cast<double>(camera.getWindowSize().width)/static_cast<double>(camera.getWindowSize().height);
Matx44f proj_mat;
camera.computeProjectionMatrix(proj_mat);
// Use the intrinsic parameters of the camera to simulate more realistically
Matx44f proj_matrix;
camera.computeProjectionMatrix(proj_matrix);
Matx44f old_proj_matrix = convertToMatx(active_camera.GetProjectionTransformMatrix(static_cast<float>(camera.getWindowSize().width) / static_cast<float>(camera.getWindowSize().height), -1.0f, 1.0f));
vtkTransform * transform = vtkTransform::New();
Matx44f old_proj_mat = convertToMatx(active_camera.GetProjectionTransformMatrix(aspect_ratio, -1.0, 1.0));
vtkTransform *transform = vtkTransform::New();
// This is a hack around not being able to set Projection Matrix
transform->SetMatrix(convertToVtkMatrix(proj_matrix * old_proj_matrix.inv()));
transform->SetMatrix(convertToVtkMatrix(proj_mat * old_proj_mat.inv()));
active_camera.SetUserTransform(transform);
transform->Delete();
}
......@@ -590,13 +588,12 @@ cv::viz::Camera cv::viz::Viz3d::VizImpl::getCamera() const
{
vtkCamera& active_camera = *renderer_->GetActiveCamera();
Vec2f fov(0.0, active_camera.GetViewAngle() * CV_PI / 180.0f);
Vec2d clip(active_camera.GetClippingRange());
Size window_size(renderer_->GetRenderWindow()->GetSize()[0],
renderer_->GetRenderWindow()->GetSize()[1]);
Matx44f old_proj_matrix = convertToMatx(active_camera.GetProjectionTransformMatrix(((float)window_size.width) / window_size.height, -1.0f, 1.0f));
Camera camera(old_proj_matrix, window_size);
// camera.setClip(clip);
double aspect_ratio = static_cast<double>(window_size.width) / static_cast<double>(window_size.height);
Matx44f proj_matrix = convertToMatx(active_camera.GetProjectionTransformMatrix(aspect_ratio, -1.0f, 1.0f));
Camera camera(proj_matrix, window_size);
return camera;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment