another constructor for CameraPositionWidget for displaying image by also using field of view instead of intrinsic matrix

This commit is contained in:
Ozan Tonkal 2013-09-08 13:06:40 +02:00
parent 2170559bed
commit 3bdb55e1ef
2 changed files with 107 additions and 83 deletions

View File

@ -206,6 +206,11 @@ namespace cv
CameraPositionWidget(const Vec2f &fov, double scale = 1.0, const Color &color = Color::white());
//! Creates frustum and display given image at the far plane
CameraPositionWidget(const Matx33f &K, const Mat &img, double scale = 1.0, const Color &color = Color::white());
//! Creates frustum and display given image at the far plane
CameraPositionWidget(const Vec2f &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white());
private:
struct ProjectImage;
};
class CV_EXPORTS TrajectoryWidget : public Widget3D

View File

@ -846,6 +846,96 @@ template<> cv::viz::Image3DWidget cv::viz::Widget::cast<cv::viz::Image3DWidget>(
///////////////////////////////////////////////////////////////////////////////////////////////
/// camera position widget implementation
struct cv::viz::CameraPositionWidget::ProjectImage
{
static void projectImage(float fovy, float far_end_height, const Mat &image,
double scale, const Color &color, vtkSmartPointer<vtkActor> actor)
{
// Create a camera
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
float aspect_ratio = float(image.cols)/float(image.rows);
// Create the vtk image
vtkSmartPointer<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
// Adjust a pixel of the vtk_image
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 0, color[2]);
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 1, color[1]);
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 2, color[0]);
// Need to flip the image as the coordinates are different in OpenCV and VTK
vtkSmartPointer<vtkImageFlip> flipFilter = vtkSmartPointer<vtkImageFlip>::New();
flipFilter->SetFilteredAxis(1); // Vertical flip
flipFilter->SetInputConnection(vtk_image->GetProducerPort());
flipFilter->Update();
Vec3d plane_center(0.0, 0.0, scale);
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]);
plane->SetNormal(0.0, 0.0, 1.0);
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->PreMultiply();
transform->Translate(plane_center[0], plane_center[1], plane_center[2]);
transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0);
transform->RotateY(180.0);
transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]);
// Apply the texture
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(flipFilter->GetOutputPort());
vtkSmartPointer<vtkTextureMapToPlane> texturePlane = vtkSmartPointer<vtkTextureMapToPlane>::New();
texturePlane->SetInputConnection(plane->GetOutputPort());
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transform_filter->SetTransform(transform);
transform_filter->SetInputConnection(texturePlane->GetOutputPort());
transform_filter->Update();
// Create frustum
camera->SetViewAngle(fovy);
camera->SetPosition(0.0,0.0,0.0);
camera->SetViewUp(0.0,1.0,0.0);
camera->SetFocalPoint(0.0,0.0,1.0);
camera->SetClippingRange(0.01, scale);
double planesArray[24];
camera->GetFrustumPlanes(aspect_ratio, planesArray);
vtkSmartPointer<vtkPlanes> planes = vtkSmartPointer<vtkPlanes>::New();
planes->SetFrustumPlanes(planesArray);
vtkSmartPointer<vtkFrustumSource> frustumSource =
vtkSmartPointer<vtkFrustumSource>::New();
frustumSource->SetPlanes(planes);
frustumSource->Update();
vtkSmartPointer<vtkExtractEdges> filter = vtkSmartPointer<vtkExtractEdges>::New();
filter->SetInput(frustumSource->GetOutput());
filter->Update();
// Frustum needs to be textured or else it can't be combined with image
vtkSmartPointer<vtkTextureMapToPlane> frustum_texture = vtkSmartPointer<vtkTextureMapToPlane>::New();
frustum_texture->SetInputConnection(filter->GetOutputPort());
// Texture mapping with only one pixel from the image to have constant color
frustum_texture->SetSRange(0.0, 0.0);
frustum_texture->SetTRange(0.0, 0.0);
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
appendFilter->AddInputConnection(frustum_texture->GetOutputPort());
appendFilter->AddInputConnection(transform_filter->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> planeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
planeMapper->SetInputConnection(appendFilter->GetOutputPort());
actor->SetMapper(planeMapper);
actor->SetTexture(texture);
}
};
cv::viz::CameraPositionWidget::CameraPositionWidget(double scale)
{
vtkSmartPointer<vtkAxes> axes = vtkSmartPointer<vtkAxes>::New ();
@ -963,96 +1053,25 @@ cv::viz::CameraPositionWidget::CameraPositionWidget(const Vec2f &fov, double sca
cv::viz::CameraPositionWidget::CameraPositionWidget(const Matx33f &K, const Mat &image, double scale, const Color &color)
{
CV_Assert(!image.empty() && image.depth() == CV_8U);
// Create a camera
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
float f_y = K(1,1);
float c_y = K(1,2);
float aspect_ratio = float(image.cols)/float(image.rows);
// Assuming that this is an ideal camera (c_y and c_x are at the center of the image)
float fovy = 2.0f * atan2(c_y,f_y) * 180 / CV_PI;
float fovy = 2.0f * atan2(c_y,f_y) * 180.0f / CV_PI;
float far_end_height = 2.0f * c_y * scale / f_y;
// Create the vtk image
vtkSmartPointer<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
// Adjust a pixel of the vtk_image
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 0, color[2]);
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 1, color[1]);
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 2, color[0]);
// Need to flip the image as the coordinates are different in OpenCV and VTK
vtkSmartPointer<vtkImageFlip> flipFilter = vtkSmartPointer<vtkImageFlip>::New();
flipFilter->SetFilteredAxis(1); // Vertical flip
flipFilter->SetInputConnection(vtk_image->GetProducerPort());
flipFilter->Update();
Vec3d plane_center(0.0, 0.0, scale);
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]);
plane->SetNormal(0.0, 0.0, 1.0);
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->PreMultiply();
transform->Translate(plane_center[0], plane_center[1], plane_center[2]);
transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0);
transform->RotateY(180.0);
transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]);
// Apply the texture
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(flipFilter->GetOutputPort());
vtkSmartPointer<vtkTextureMapToPlane> texturePlane = vtkSmartPointer<vtkTextureMapToPlane>::New();
texturePlane->SetInputConnection(plane->GetOutputPort());
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transform_filter->SetTransform(transform);
transform_filter->SetInputConnection(texturePlane->GetOutputPort());
transform_filter->Update();
// Create frustum
camera->SetViewAngle(fovy);
camera->SetPosition(0.0,0.0,0.0);
camera->SetViewUp(0.0,1.0,0.0);
camera->SetFocalPoint(0.0,0.0,1.0);
camera->SetClippingRange(0.01, scale);
double planesArray[24];
camera->GetFrustumPlanes(aspect_ratio, planesArray);
vtkSmartPointer<vtkPlanes> planes = vtkSmartPointer<vtkPlanes>::New();
planes->SetFrustumPlanes(planesArray);
vtkSmartPointer<vtkFrustumSource> frustumSource =
vtkSmartPointer<vtkFrustumSource>::New();
frustumSource->SetPlanes(planes);
frustumSource->Update();
vtkSmartPointer<vtkExtractEdges> filter = vtkSmartPointer<vtkExtractEdges>::New();
filter->SetInput(frustumSource->GetOutput());
filter->Update();
// Frustum needs to be textured or else it can't be combined with image
vtkSmartPointer<vtkTextureMapToPlane> frustum_texture = vtkSmartPointer<vtkTextureMapToPlane>::New();
frustum_texture->SetInputConnection(filter->GetOutputPort());
// Texture mapping with only one pixel from the image to have constant color
frustum_texture->SetSRange(0.0, 0.0);
frustum_texture->SetTRange(0.0, 0.0);
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
appendFilter->AddInputConnection(frustum_texture->GetOutputPort());
appendFilter->AddInputConnection(transform_filter->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> planeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
planeMapper->SetInputConnection(appendFilter->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
ProjectImage::projectImage(fovy, far_end_height, image, scale, color, actor);
WidgetAccessor::setProp(*this, actor);
}
cv::viz::CameraPositionWidget::CameraPositionWidget(const Vec2f &fov, const Mat &image, double scale, const Color &color)
{
CV_Assert(!image.empty() && image.depth() == CV_8U);
float fovy = fov[1] * 180.0f / CV_PI;
float far_end_height = 2.0 * scale * tan(fov[1] * 0.5);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(planeMapper);
actor->SetTexture(texture);
ProjectImage::projectImage(fovy, far_end_height, image, scale, color, actor);
WidgetAccessor::setProp(*this, actor);
}