From e21f2a81fff4a21a5bf9ef6a3b71588da24e28d9 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 20:40:10 +0400 Subject: [PATCH] factored camera postions with image --- modules/viz/doc/widget.rst | 8 +- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/shapes.cpp | 127 +++++++++----------- 3 files changed, 60 insertions(+), 79 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 54b740b0b..ec4a858e2 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -660,9 +660,9 @@ This 3D Widget represents camera position in a scene by its axes or viewing frus //! Creates frustum based on the field of view at the origin WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, InputArray image, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white()); }; viz::WCameraPosition::WCameraPosition @@ -703,7 +703,7 @@ Constructs a WCameraPosition. - **Display image on the far plane of the viewing frustum.** - .. ocv:function:: WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Matx33d &K, InputArray image, double scale = 1.0, const Color &color = Color::white()) :param K: Intrinsic matrix of the camera. :param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum. @@ -712,7 +712,7 @@ Constructs a WCameraPosition. Creates viewing frustum of the camera based on its intrinsic matrix K, and displays image on the far end plane. - .. ocv:function:: WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white()) :param fov: Field of view of the camera (horizontal, vertical). :param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 49a0512cc..44cb50074 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -256,9 +256,9 @@ namespace cv //! Creates frustum based on the field of view at the origin WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, InputArray image, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 3295a5238..2067c5c9e 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -777,80 +777,23 @@ namespace cv { namespace viz { namespace return extract_edges->GetOutput(); } - static vtkSmartPointer projectImage(vtkSmartPointer frustum, double far_end_height, const Mat &image, double scale, const Color &color) + static Mat ensureColorImage(InputArray image) { - Mat color_image = image; - if (color_image.channels() == 1) + Mat color(image.size(), CV_8UC3); + if (image.channels() == 1) { - color_image.create(image.size(), CV_8UC3); - Vec3b *drow = color_image.ptr(); - for(int y = 0; y < image.rows; ++y) + Vec3b *drow = color.ptr(); + for(int y = 0; y < color.rows; ++y) { - const unsigned char *srow = image.ptr(y); - const unsigned char *send = srow + image.cols; + const unsigned char *srow = image.getMat().ptr(y); + const unsigned char *send = srow + color.cols; for(;srow < send;) *drow++ = Vec3b::all(*srow++); } } - - - double aspect_ratio = color_image.cols/(double)color_image.rows; - - // Create the vtk image - vtkSmartPointer source = vtkSmartPointer::New(); - source->SetImage(color_image); - source->Update(); - vtkSmartPointer vtk_image = source->GetOutput(); - - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, color[2]); - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 1, color[1]); - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 2, color[0]); - - Vec3d plane_center(0.0, 0.0, scale); - - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(plane_center.val); - plane->SetNormal(0.0, 0.0, 1.0); - - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(plane_center.val); - 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 texture = vtkSmartPointer::New(); - texture->SetInputConnection(vtk_image->GetProducerPort()); - - vtkSmartPointer texture_plane = vtkSmartPointer::New(); - texture_plane->SetInputConnection(plane->GetOutputPort()); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetInputConnection(texture_plane->GetOutputPort()); - transform_filter->SetTransform(transform); - - - - // Frustum needs to be textured or else it can't be combined with image - vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(frustum->GetProducerPort()); - // 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 appendFilter = vtkSmartPointer::New(); - appendFilter->AddInputConnection(frustum_texture->GetOutputPort()); - appendFilter->AddInputConnection(transform_filter->GetOutputPort()); - - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(appendFilter->GetOutputPort()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(planeMapper); - actor->SetTexture(texture); - - return actor; + else + image.copyTo(color); + return color; } }; }}} @@ -904,31 +847,69 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const setColor(color); } -cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, double scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, InputArray _image, double scale, const Color &color) { - CV_Assert(!image.empty() && image.depth() == CV_8U); + CV_Assert(!_image.empty() && _image.depth() == CV_8U); + Mat image = CameraPositionUtils::ensureColorImage(_image); + image.at(0, 0) = Vec3d(color.val); //workaround of VTK limitation + double f_y = K(1,1), c_y = K(1,2); // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI; double far_end_height = 2.00 * c_y * scale / f_y; double aspect_ratio = image.cols/(double)image.rows; + double image_scale = far_end_height/image.rows; + + WImage3D image_widget(image, Size2d(image.size()) * image_scale); + image_widget.applyTransform(Affine3d().translate(Vec3d(0, 0, scale))); + vtkSmartPointer plane = getPolyData(image_widget); vtkSmartPointer frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); - vtkSmartPointer actor = CameraPositionUtils::projectImage(frustum, far_end_height, image, scale, color); + // Frustum needs to be textured or else it can't be combined with image + vtkSmartPointer frustum_texture = vtkSmartPointer::New(); + frustum_texture->SetInputConnection(frustum->GetProducerPort()); + frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel + frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color + + vtkSmartPointer append_filter = vtkSmartPointer::New(); + append_filter->AddInputConnection(frustum_texture->GetOutputPort()); + append_filter->AddInputConnection(plane->GetProducerPort()); + + vtkSmartPointer actor = getActor(image_widget); + actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort()); WidgetAccessor::setProp(*this, actor); } -cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, const Mat &image, double scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, InputArray _image, double scale, const Color &color) { - CV_Assert(!image.empty() && image.depth() == CV_8U); + CV_Assert(!_image.empty() && _image.depth() == CV_8U); + Mat image = CameraPositionUtils::ensureColorImage(_image); + image.at(0, 0) = Vec3d(color.val); //workaround of VTK limitation + double fovy = fov[1] * 180.0 / CV_PI; double far_end_height = 2.0 * scale * tan(fov[1] * 0.5); double aspect_ratio = image.cols/(double)image.rows; + double image_scale = far_end_height/image.rows; + + WImage3D image_widget(image, Size2d(image.size()) * image_scale); + image_widget.applyTransform(Affine3d().translate(Vec3d(0, 0, scale))); + vtkSmartPointer plane = getPolyData(image_widget); vtkSmartPointer frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); - vtkSmartPointer actor = CameraPositionUtils::projectImage(frustum, far_end_height, image, scale, color); + // Frustum needs to be textured or else it can't be combined with image + vtkSmartPointer frustum_texture = vtkSmartPointer::New(); + frustum_texture->SetInputConnection(frustum->GetProducerPort()); + frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel + frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color + + vtkSmartPointer append_filter = vtkSmartPointer::New(); + append_filter->AddInputConnection(frustum_texture->GetOutputPort()); + append_filter->AddInputConnection(plane->GetProducerPort()); + + vtkSmartPointer actor = getActor(image_widget); + actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort()); WidgetAccessor::setProp(*this, actor); }