///////////////////////////////////////////////////////////////////////////////////////////////
/// 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 ();
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);
}