another constructor for CameraPositionWidget for displaying image by also using field...
authorOzan Tonkal <ozantonkal@gmail.com>
Sun, 8 Sep 2013 11:06:40 +0000 (13:06 +0200)
committerOzan Tonkal <ozantonkal@gmail.com>
Sun, 8 Sep 2013 17:03:55 +0000 (19:03 +0200)
modules/viz/include/opencv2/viz/widgets.hpp
modules/viz/src/shape_widgets.cpp

index 4769073..1216d04 100644 (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
index f10c39f..f42cebd 100644 (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);
 }