From 2cbfb0414464053a20c9f2a6b2a93792a9a55b3c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 28 Nov 2013 12:45:22 +0400 Subject: [PATCH 01/91] viz: rich set of named colors --- modules/viz/include/opencv2/viz/types.hpp | 67 +++++++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 682006f959..780f200ed9 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -77,6 +77,34 @@ namespace cv static Color white(); static Color gray(); + + static Color mlab(); + + static Color navy(); + static Color olive(); + static Color maroon(); + static Color teal(); + static Color rose(); + static Color azure(); + static Color lime(); + static Color gold(); + static Color brown(); + static Color orange(); + static Color chartreuse(); + static Color orange_red(); + static Color purple(); + static Color indigo(); + + static Color pink(); + static Color cherry(); + static Color bluberry(); + static Color raspberry(); + static Color silver(); + static Color violet(); + static Color apricot(); + static Color turquoise(); + static Color celestial_blue(); + static Color amethyst(); }; class CV_EXPORTS Mesh3d @@ -180,15 +208,46 @@ inline cv::viz::Color::Color(double _gray) : Scalar(_gray, _gray, _gray) {} inline cv::viz::Color::Color(double _blue, double _green, double _red) : Scalar(_blue, _green, _red) {} inline cv::viz::Color::Color(const Scalar& color) : Scalar(color) {} -inline cv::viz::Color cv::viz::Color::black() { return Color( 0, 0, 0); } -inline cv::viz::Color cv::viz::Color::green() { return Color( 0, 255, 0); } -inline cv::viz::Color cv::viz::Color::blue() { return Color(255, 0, 0); } -inline cv::viz::Color cv::viz::Color::cyan() { return Color(255, 255, 0); } +inline cv::viz::Color cv::viz::Color::black() { return Color( 0, 0, 0); } +inline cv::viz::Color cv::viz::Color::green() { return Color( 0, 255, 0); } +inline cv::viz::Color cv::viz::Color::blue() { return Color(255, 0, 0); } +inline cv::viz::Color cv::viz::Color::cyan() { return Color(255, 255, 0); } inline cv::viz::Color cv::viz::Color::red() { return Color( 0, 0, 255); } inline cv::viz::Color cv::viz::Color::yellow() { return Color( 0, 255, 255); } inline cv::viz::Color cv::viz::Color::magenta() { return Color(255, 0, 255); } inline cv::viz::Color cv::viz::Color::white() { return Color(255, 255, 255); } inline cv::viz::Color cv::viz::Color::gray() { return Color(128, 128, 128); } +inline cv::viz::Color cv::viz::Color::mlab() { return Color(235, 118, 118); } + +inline cv::viz::Color cv::viz::Color::navy() { return Color(0, 0, 128); } +inline cv::viz::Color cv::viz::Color::olive() { return Color(0, 128, 128); } +inline cv::viz::Color cv::viz::Color::maroon() { return Color(0, 0, 128); } +inline cv::viz::Color cv::viz::Color::teal() { return Color(128, 128, 0); } +inline cv::viz::Color cv::viz::Color::rose() { return Color(127, 0, 255); } +inline cv::viz::Color cv::viz::Color::azure() { return Color(255, 127, 0); } +inline cv::viz::Color cv::viz::Color::lime() { return Color(0, 255, 191); } +inline cv::viz::Color cv::viz::Color::gold() { return Color(0, 215, 255); } +inline cv::viz::Color cv::viz::Color::brown() { return Color(0, 75, 150); } +inline cv::viz::Color cv::viz::Color::orange() { return Color(0, 165, 255); } +inline cv::viz::Color cv::viz::Color::chartreuse() { return Color(0, 255, 127); } +inline cv::viz::Color cv::viz::Color::orange_red() { return Color(0, 69, 255); } +inline cv::viz::Color cv::viz::Color::purple() { return Color(128, 0, 128); } +inline cv::viz::Color cv::viz::Color::indigo() { return Color(130, 0, 75); } + +inline cv::viz::Color cv::viz::Color::pink() { return Color(203, 192, 255); } +inline cv::viz::Color cv::viz::Color::cherry() { return Color( 99, 29, 222); } +inline cv::viz::Color cv::viz::Color::bluberry() { return Color(247, 134, 79); } +inline cv::viz::Color cv::viz::Color::raspberry() { return Color( 92, 11, 227); } +inline cv::viz::Color cv::viz::Color::silver() { return Color(192, 192, 192); } +inline cv::viz::Color cv::viz::Color::violet() { return Color(226, 43, 138); } +inline cv::viz::Color cv::viz::Color::apricot() { return Color(177, 206, 251); } +inline cv::viz::Color cv::viz::Color::turquoise() { return Color(208, 224, 64); } +inline cv::viz::Color cv::viz::Color::celestial_blue() { return Color(208, 151, 73); } +inline cv::viz::Color cv::viz::Color::amethyst() { return Color(204, 102, 153); } + + + + #endif From 15fd3faa40bc5bc21283cab4414c67a452f03e1d Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 30 Nov 2013 19:00:10 +0400 Subject: [PATCH 02/91] support gray color clouds --- modules/viz/src/cloud_widgets.cpp | 9 ++- modules/viz/src/viz3d_impl.hpp | 108 ++++++++++++++---------------- 2 files changed, 56 insertions(+), 61 deletions(-) diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/cloud_widgets.cpp index 73cc26201b..ab4d0c3d84 100644 --- a/modules/viz/src/cloud_widgets.cpp +++ b/modules/viz/src/cloud_widgets.cpp @@ -151,7 +151,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - CV_Assert(colors.type() == CV_8UC3 && cloud.size() == colors.size()); + CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); if (cloud.isContinuous() && colors.isContinuous()) { @@ -388,7 +388,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - CV_Assert(colors.type() == CV_8UC3 && cloud.size() == colors.size()); + CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); if (cloud.isContinuous() && colors.isContinuous()) { @@ -651,7 +651,7 @@ struct cv::viz::WMesh::CopyImpl cv::viz::WMesh::WMesh(const Mesh3d &mesh) { CV_Assert(mesh.cloud.rows == 1 && (mesh.cloud.type() == CV_32FC3 || mesh.cloud.type() == CV_64FC3 || mesh.cloud.type() == CV_32FC4 || mesh.cloud.type() == CV_64FC4)); - CV_Assert(mesh.colors.empty() || (mesh.colors.type() == CV_8UC3 && mesh.cloud.size() == mesh.colors.size())); + CV_Assert(mesh.colors.empty() || (mesh.colors.depth() == CV_8U && mesh.cloud.size() == mesh.colors.size())); CV_Assert(!mesh.polygons.empty() && mesh.polygons.type() == CV_32SC1); vtkSmartPointer points = vtkSmartPointer::New(); @@ -680,8 +680,7 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) if (!mesh.colors.empty()) { - Vec3b * colors_data = 0; - colors_data = new Vec3b[nr_points]; + Vec3b *colors_data = new Vec3b[nr_points]; NanFilter::copyColor(mesh.colors, colors_data, mesh.cloud); scalars = vtkSmartPointer::New(); diff --git a/modules/viz/src/viz3d_impl.hpp b/modules/viz/src/viz3d_impl.hpp index 59f45a8fa0..a7ef9c4374 100644 --- a/modules/viz/src/viz3d_impl.hpp +++ b/modules/viz/src/viz3d_impl.hpp @@ -191,14 +191,29 @@ namespace cv vtkSmartPointer convertToVtkMatrix(const cv::Matx44f &m); cv::Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix); + struct color_tag {}; + struct gray_tag {}; + + static Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } + static Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } + + inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } + template inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } + + inline Color vtkcolor(const Color& color) + { + Color scaled_color = color * (1.0/255.0); + std::swap(scaled_color[0], scaled_color[2]); + return scaled_color; + } + struct NanFilter { - template + template struct Impl { - typedef Vec<_Tp, 3> _Out; - - static _Out* copy(const Mat& source, _Out* output, const Mat& nan_mask) + template + static Vec<_Tp, 3>* copy(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) { CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); @@ -214,14 +229,15 @@ namespace cv for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - *output++ = _Out(srow); + *output++ = Vec<_Tp, 3>(srow); } return output; } - static _Out* copyColor(const Mat& source, _Out* output, const Mat& nan_mask) + template + static Vec3b* copyColor(const Mat& source, Vec3b* output, const Mat& nan_mask) { - CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); + CV_Assert(source.size() == nan_mask.size()); CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); CV_DbgAssert(DataDepth<_Msk>::value == nan_mask.depth()); @@ -230,16 +246,12 @@ namespace cv for (int y = 0; y < source.rows; ++y) { - const _Tp* srow = source.ptr<_Tp>(y); + const unsigned char* srow = source.ptr(y); const _Msk* mrow = nan_mask.ptr<_Msk>(y); for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - { - *output = _Out(srow); - std::swap((*output)[0], (*output)[2]); // BGR -> RGB - ++output; - } + *output++ = fetchRgb(srow, _Tag()); } return output; } @@ -251,20 +263,23 @@ namespace cv CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); typedef Vec<_Tp, 3>* (*copy_func)(const Mat&, Vec<_Tp, 3>*, const Mat&); - const static copy_func table[2] = { &NanFilter::Impl<_Tp, float>::copy, &NanFilter::Impl<_Tp, double>::copy }; + const static copy_func table[2] = { &NanFilter::Impl::copy<_Tp>, &NanFilter::Impl::copy<_Tp> }; return table[nan_mask.depth() - 5](source, output, nan_mask); } - template - static inline Vec<_Tp, 3>* copyColor(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) + static inline Vec3b* copyColor(const Mat& source, Vec3b* output, const Mat& nan_mask) { CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); - typedef Vec<_Tp, 3>* (*copy_func)(const Mat&, Vec<_Tp, 3>*, const Mat&); - const static copy_func table[2] = { &NanFilter::Impl<_Tp, float>::copyColor, &NanFilter::Impl<_Tp, double>::copyColor }; + typedef Vec3b* (*copy_func)(const Mat&, Vec3b*, const Mat&); + const static copy_func table[2][2] = + { + { &NanFilter::Impl::copyColor, &NanFilter::Impl ::copyColor }, + { &NanFilter::Impl::copyColor, &NanFilter::Impl::copyColor } + }; - return table[nan_mask.depth() - 5](source, output, nan_mask); + return table[nan_mask.depth() - 5][source.channels() == 1 ? 0 : 1](source, output, nan_mask); } }; @@ -292,47 +307,31 @@ namespace cv }; - inline Color vtkcolor(const Color& color) - { - Color scaled_color = color * (1.0/255.0); - std::swap(scaled_color[0], scaled_color[2]); - return scaled_color; - } - - inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } - template inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } struct ConvertToVtkImage { struct Impl { - static void copyImageMultiChannel(const Mat &image, vtkSmartPointer output) - { - int i_chs = image.channels(); + typedef unsigned char uchar; - for (int i = 0; i < image.rows; ++i) + static void copyImage(const Mat &source, vtkSmartPointer output, color_tag tag) + { + for (int y = 0; y < source.rows; ++y) { - const unsigned char * irows = image.ptr(i); - for (int j = 0; j < image.cols; ++j, irows += i_chs) - { - unsigned char * vrows = static_cast(output->GetScalarPointer(j,i,0)); - memcpy(vrows, irows, i_chs); - std::swap(vrows[0], vrows[2]); // BGR -> RGB - } + const uchar *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x, srow += source.channels()) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = fetchRgb(srow, tag); } output->Modified(); } - static void copyImageSingleChannel(const Mat &image, vtkSmartPointer output) + static void copyImage(const Mat &source, vtkSmartPointer output, gray_tag) { - for (int i = 0; i < image.rows; ++i) + for (int y = 0; y < source.rows; ++y) { - const unsigned char * irows = image.ptr(i); - for (int j = 0; j < image.cols; ++j, ++irows) - { - unsigned char * vrows = static_cast(output->GetScalarPointer(j,i,0)); - *vrows = *irows; - } + const uchar *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; } output->Modified(); } @@ -349,16 +348,13 @@ namespace cv #else output->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); #endif - - int i_chs = image.channels(); - if (i_chs > 1) - { - // Multi channel images are handled differently because of BGR <-> RGB - Impl::copyImageMultiChannel(image, output); - } - else + switch(image.channels()) { - Impl::copyImageSingleChannel(image, output); + case 1: Impl::copyImage(image, output, gray_tag()); break; + case 3: + case 4: Impl::copyImage(image, output, color_tag()); break; + default: + CV_Assert(!"Unsupported channel number"); } } }; From 2d63f60d435d7a7db0b79479b68c8051216ab8f6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 30 Nov 2013 17:57:53 +0400 Subject: [PATCH 03/91] minor changes, opencv cross-branch code --- modules/viz/include/opencv2/viz/viz3d.hpp | 1 + modules/viz/include/opencv2/viz/widgets.hpp | 2 +- modules/viz/src/cloud_widgets.cpp | 12 +++--- modules/viz/src/interactor_style.cpp | 47 +++++---------------- 4 files changed, 19 insertions(+), 43 deletions(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index f19709eb52..f572059197 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -64,6 +64,7 @@ namespace cv class CV_EXPORTS Viz3d { public: + typedef cv::viz::Color Color; typedef void (*KeyboardCallback)(const KeyboardEvent&, void*); typedef void (*MouseCallback)(const MouseEvent&, void*); diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 07b3358993..f333c1d0b5 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -219,7 +219,7 @@ namespace cv class CV_EXPORTS WText : public Widget2D { public: - WText(const String &text, const Point2i &pos, int font_size = 10, const Color &color = Color::white()); + WText(const String &text, const Point2i &pos, int font_size = 20, const Color &color = Color::white()); void setText(const String &text); String getText() const; diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/cloud_widgets.cpp index ab4d0c3d84..0f36ef976b 100644 --- a/modules/viz/src/cloud_widgets.cpp +++ b/modules/viz/src/cloud_widgets.cpp @@ -124,7 +124,7 @@ struct cv::viz::WCloud::CreateCloudWidget cells->SetNumberOfTuples(nr_points); vtkIdType *cell = cells->GetPointer(0); // Fill it with 1s - std::fill_n(cell, nr_points * 2, 1); + std::fill(cell, cell + nr_points * 2, 1); cell++; for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) *cell = i; @@ -155,8 +155,8 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) if (cloud.isContinuous() && colors.isContinuous()) { - cloud.reshape(cloud.channels(), 1); - colors.reshape(colors.channels(), 1); + cloud = cloud.reshape(cloud.channels(), 1); + colors = colors.reshape(colors.channels(), 1); } vtkIdType nr_points; @@ -307,7 +307,7 @@ struct cv::viz::WCloudCollection::CreateCloudWidget cells->SetNumberOfTuples(nr_points); vtkIdType *cell = cells->GetPointer(0); // Fill it with 1s - std::fill_n(cell, nr_points * 2, 1); + std::fill(cell, cell + nr_points * 2, 1); cell++; for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) *cell = i; @@ -392,8 +392,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, if (cloud.isContinuous() && colors.isContinuous()) { - cloud.reshape(cloud.channels(), 1); - colors.reshape(colors.channels(), 1); + cloud = cloud.reshape(cloud.channels(), 1); + colors = colors.reshape(colors.channels(), 1); } vtkIdType nr_points; diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index ccf188ded2..78f2ac680f 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -236,7 +236,7 @@ cv::viz::InteractorStyle::OnKeyDown() "\n" " j, J : take a .PNG snapshot of the current window view\n" " c, C : display current camera/window parameters\n" - " f, F : fly to point mode\n" + " f, F : fly to point mode, hold the key and move mouse where to fly\n" "\n" " e, E : exit the interactor\n" " q, Q : stop and call VTK's TerminateApp\n" @@ -271,28 +271,8 @@ cv::viz::InteractorStyle::OnKeyDown() { unsigned int t = static_cast(time(0)); String png_file = cv::format("screenshot-%d.png", t); - String cam_file = cv::format("screenshot-%d.cam", t); - - vtkSmartPointer cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); - Vec2d clip; - Vec3d focal, pos, view; - cam->GetClippingRange(clip.val); - cam->GetFocalPoint(focal.val); - cam->GetPosition(pos.val); - cam->GetViewUp(view.val); - Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); - Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); - double angle = cam->GetViewAngle() / 180.0 * CV_PI; - - String data = cv::format("%f,%f/%f,%f,%f/%f,%f,%f/%f,%f,%f/%f/%d,%d/%d,%d", clip[0],clip[1], focal[0],focal[1],focal[2], - pos[0],pos[1],pos[2], view[0],view[1], view[2], angle , win_size[0],win_size[1], win_pos[0], win_pos[1]); - saveScreenshot(png_file); - ofstream ofs_cam(cam_file.c_str()); - ofs_cam << data.c_str() << endl; - ofs_cam.close(); - - cout << "Screenshot (" << png_file.c_str() << ") and camera information (" << cam_file.c_str() << ") successfully captured." << endl; + cout << "Screenshot (" << png_file.c_str() << ") successfully captured." << endl; break; } // display current camera settings/parameters @@ -301,26 +281,21 @@ cv::viz::InteractorStyle::OnKeyDown() vtkSmartPointer cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); Vec2d clip; - Vec3d focal, pose, view; + Vec3d focal, pos, view; cam->GetClippingRange(clip.val); cam->GetFocalPoint(focal.val); - cam->GetPosition(pose.val); + cam->GetPosition(pos.val); cam->GetViewUp(view.val); Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); + double angle = cam->GetViewAngle () / 180.0 * CV_PI; + + String data = cv::format("clip(%f,%f) focal(%f,%f,%f) pos(%f,%f,%f) view(%f,%f,%f) angle(%f) winsz(%d,%d) winpos(%d,%d)", + clip[0], clip[1], focal[0], focal[1], focal[2], pos[0], pos[1], pos[2], view[0], view[1], view[2], + angle, win_size[0], win_size[1], win_pos[0], win_pos[1]); + + std::cout << data.c_str() << std::endl; - cv::print(Mat(clip, false).reshape(1, 1)); - std::cout << "/"; - cv::print(Mat(focal, false).reshape(1, 1)); - std::cout << "/"; - cv::print(Mat(pose, false).reshape(1, 1)); - std::cout << "/"; - cv::print(Mat(view, false).reshape(1, 1)); - std::cout << "/" << cam->GetViewAngle () / 180.0 * CV_PI; - cv::print(Mat(win_size, false).reshape(1, 1)); - std::cout << "/"; - cv::print(Mat(win_pos, false).reshape(1, 1)); - std::cout << std::endl; break; } case '=': From 44c1d4dfdc8fc14093966d08d48cbf3666b41680 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 1 Dec 2013 14:58:29 +0400 Subject: [PATCH 04/91] allow fast switch between actors (except mesh, cloud, cloud collection) --- modules/viz/src/cloud_widgets.cpp | 2 +- modules/viz/src/precomp.hpp | 4 ++++ modules/viz/src/shape_widgets.cpp | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/cloud_widgets.cpp index 0f36ef976b..894051e39b 100644 --- a/modules/viz/src/cloud_widgets.cpp +++ b/modules/viz/src/cloud_widgets.cpp @@ -604,7 +604,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in mapper->SetColorModeToMapScalars(); mapper->SetScalarModeToUsePointData(); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); setColor(color); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index ab673b389c..1beb43587c 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -101,6 +101,7 @@ #include #include #include +#include #include #include #include @@ -120,6 +121,9 @@ namespace cv { namespace viz { + typedef vtkLODActor vizActor; + //typedef vtkActor vizActor; + typedef std::map > WidgetActorMap; typedef std::map VizMap; diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 6e4f4c70ff..aff3609c95 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -68,7 +68,7 @@ cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(line->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -117,7 +117,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(SetSizeImpl::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -138,7 +138,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(SetSizeImpl::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -167,7 +167,7 @@ cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolu vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(sphere->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -240,7 +240,7 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(transformPD->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -276,7 +276,7 @@ cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, cons vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tf->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -307,7 +307,7 @@ cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_dir vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tuber->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -339,7 +339,7 @@ cv::viz::WCube::WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_fr mapper->SetInputConnection(cube->GetOutputPort()); } - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -391,7 +391,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -1068,7 +1068,7 @@ cv::viz::WCameraPosition::WCameraPosition(float scale) mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); From f6e9b81188c634de6254136987d36c14e6fa4540 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 1 Dec 2013 15:25:44 +0400 Subject: [PATCH 05/91] reduced exported interface names (to make IntelliSense hints less littered) --- modules/viz/include/opencv2/viz/widgets.hpp | 29 -- modules/viz/src/cloud_widgets.cpp | 528 ++++++++++---------- modules/viz/src/shape_widgets.cpp | 349 ++++++------- modules/viz/src/widget.cpp | 31 +- 4 files changed, 456 insertions(+), 481 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index f333c1d0b5..42e0f1968b 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -119,8 +119,6 @@ namespace cv Affine3f getPose() const; void setColor(const Color &color); - private: - struct MatrixConverter; }; @@ -145,8 +143,6 @@ namespace cv public: WPlane(const Vec4f& coefs, float size = 1.f, const Color &color = Color::white()); WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.f, const Color &color = Color::white()); - private: - struct SetSizeImpl; }; class CV_EXPORTS WSphere : public Widget3D @@ -189,9 +185,6 @@ namespace cv { public: WPolyLine(InputArray points, const Color &color = Color::white()); - - private: - struct CopyImpl; }; class CV_EXPORTS WGrid : public Widget3D @@ -201,10 +194,6 @@ namespace cv WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - - private: - struct GridImpl; - }; class CV_EXPORTS WText3D : public Widget3D @@ -257,9 +246,6 @@ namespace cv WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); - - private: - struct ProjectImage; }; class CV_EXPORTS WTrajectory : public Widget3D @@ -273,9 +259,6 @@ namespace cv WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); - - private: - struct ApplyPath; }; class CV_EXPORTS WSpheresTrajectory: public Widget3D @@ -292,9 +275,6 @@ namespace cv WCloud(InputArray cloud, InputArray colors); //! All points in cloud have the same color WCloud(InputArray cloud, const Color &color = Color::white()); - - private: - struct CreateCloudWidget; }; class CV_EXPORTS WCloudCollection : public Widget3D @@ -306,27 +286,18 @@ namespace cv void addCloud(InputArray cloud, InputArray colors, const Affine3f &pose = Affine3f::Identity()); //! All points in cloud have the same color void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3f &pose = Affine3f::Identity()); - - private: - struct CreateCloudWidget; }; class CV_EXPORTS WCloudNormals : public Widget3D { public: WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); - - private: - struct ApplyCloudNormals; }; class CV_EXPORTS WMesh : public Widget3D { public: WMesh(const Mesh3d &mesh); - - private: - struct CopyImpl; }; template<> CV_EXPORTS Widget2D Widget::cast(); diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/cloud_widgets.cpp index 894051e39b..27a0285fc7 100644 --- a/modules/viz/src/cloud_widgets.cpp +++ b/modules/viz/src/cloud_widgets.cpp @@ -59,92 +59,96 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Point Cloud Widget implementation -struct cv::viz::WCloud::CreateCloudWidget +namespace cv { namespace viz { namespace { - static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) + struct CloudUtils { - vtkSmartPointer polydata = vtkSmartPointer::New(); - vtkSmartPointer vertices = vtkSmartPointer::New(); + static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) + { + vtkSmartPointer polydata = vtkSmartPointer::New(); + vtkSmartPointer vertices = vtkSmartPointer::New(); - polydata->SetVerts(vertices); + polydata->SetVerts(vertices); - vtkSmartPointer points = polydata->GetPoints(); - vtkSmartPointer initcells; - nr_points = cloud.total(); + vtkSmartPointer points = polydata->GetPoints(); + vtkSmartPointer initcells; + nr_points = cloud.total(); + + if (!points) + { + points = vtkSmartPointer::New(); + if (cloud.depth() == CV_32F) + points->SetDataTypeToFloat(); + else if (cloud.depth() == CV_64F) + points->SetDataTypeToDouble(); + polydata->SetPoints(points); + } + points->SetNumberOfPoints(nr_points); - if (!points) - { - points = vtkSmartPointer::New(); if (cloud.depth() == CV_32F) - points->SetDataTypeToFloat(); + { + // Get a pointer to the beginning of the data array + Vec3f *data_beg = vtkpoints_data(points); + Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); + nr_points = data_end - data_beg; + } else if (cloud.depth() == CV_64F) - points->SetDataTypeToDouble(); - polydata->SetPoints(points); - } - points->SetNumberOfPoints(nr_points); - - if (cloud.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - else if (cloud.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - points->SetNumberOfPoints(nr_points); + { + // Get a pointer to the beginning of the data array + Vec3d *data_beg = vtkpoints_data(points); + Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); + nr_points = data_end - data_beg; + } + points->SetNumberOfPoints(nr_points); - // Update cells - vtkSmartPointer cells = vertices->GetData(); - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); + // Update cells + vtkSmartPointer cells = vertices->GetData(); + // If no init cells and cells has not been initialized... + if (!cells) + cells = vtkSmartPointer::New(); - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); - - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) + // If we have less values then we need to recreate the array + if (cells->GetNumberOfTuples() < nr_points) { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); + cells = vtkSmartPointer::New(); + + // If init cells is given, and there's enough data in it, use it + if (initcells && initcells->GetNumberOfTuples() >= nr_points) + { + cells->DeepCopy(initcells); + cells->SetNumberOfComponents(2); + cells->SetNumberOfTuples(nr_points); + } + else + { + // If the number of tuples is still too small, we need to recreate the array + cells->SetNumberOfComponents(2); + cells->SetNumberOfTuples(nr_points); + vtkIdType *cell = cells->GetPointer(0); + // Fill it with 1s + std::fill(cell, cell + nr_points * 2, 1); + cell++; + for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) + *cell = i; + // Save the results in initcells + initcells = vtkSmartPointer::New(); + initcells->DeepCopy(cells); + } } else { - // If the number of tuples is still too small, we need to recreate the array + // The assumption here is that the current set of cells has more data than needed cells->SetNumberOfComponents(2); cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); } + + // Set the cells and the vertices + vertices->SetCells(nr_points, cells); + return polydata; } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } + }; +}}} - // Set the cells and the vertices - vertices->SetCells(nr_points, cells); - return polydata; - } -}; cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) { @@ -160,7 +164,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) } vtkIdType nr_points; - vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); + vtkSmartPointer polydata = CloudUtils::create(cloud, nr_points); // Filter colors Vec3b* colors_data = new Vec3b[nr_points]; @@ -207,7 +211,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); vtkIdType nr_points; - vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); + vtkSmartPointer polydata = CloudUtils::create(cloud, nr_points); vtkSmartPointer mapper = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 @@ -242,139 +246,142 @@ template<> cv::viz::WCloud cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// Cloud Collection Widget implementation -struct cv::viz::WCloudCollection::CreateCloudWidget +namespace cv { namespace viz { namespace { - static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) + struct CloudCollectionUtils { - vtkSmartPointer polydata = vtkSmartPointer::New(); - vtkSmartPointer vertices = vtkSmartPointer::New(); + static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) + { + vtkSmartPointer polydata = vtkSmartPointer::New(); + vtkSmartPointer vertices = vtkSmartPointer::New(); - polydata->SetVerts(vertices); + polydata->SetVerts(vertices); - vtkSmartPointer points = polydata->GetPoints(); - vtkSmartPointer initcells; - nr_points = cloud.total(); + vtkSmartPointer points = polydata->GetPoints(); + vtkSmartPointer initcells; + nr_points = cloud.total(); + + if (!points) + { + points = vtkSmartPointer::New(); + if (cloud.depth() == CV_32F) + points->SetDataTypeToFloat(); + else if (cloud.depth() == CV_64F) + points->SetDataTypeToDouble(); + polydata->SetPoints(points); + } + points->SetNumberOfPoints(nr_points); - if (!points) - { - points = vtkSmartPointer::New(); if (cloud.depth() == CV_32F) - points->SetDataTypeToFloat(); + { + // Get a pointer to the beginning of the data array + Vec3f *data_beg = vtkpoints_data(points); + Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); + nr_points = data_end - data_beg; + } else if (cloud.depth() == CV_64F) - points->SetDataTypeToDouble(); - polydata->SetPoints(points); - } - points->SetNumberOfPoints(nr_points); - - if (cloud.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - else if (cloud.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - points->SetNumberOfPoints(nr_points); - - // Update cells - vtkSmartPointer cells = vertices->GetData(); - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); + { + // Get a pointer to the beginning of the data array + Vec3d *data_beg = vtkpoints_data(points); + Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); + nr_points = data_end - data_beg; + } + points->SetNumberOfPoints(nr_points); - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); + // Update cells + vtkSmartPointer cells = vertices->GetData(); + // If no init cells and cells has not been initialized... + if (!cells) + cells = vtkSmartPointer::New(); - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) + // If we have less values then we need to recreate the array + if (cells->GetNumberOfTuples() < nr_points) { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); + cells = vtkSmartPointer::New(); + + // If init cells is given, and there's enough data in it, use it + if (initcells && initcells->GetNumberOfTuples() >= nr_points) + { + cells->DeepCopy(initcells); + cells->SetNumberOfComponents(2); + cells->SetNumberOfTuples(nr_points); + } + else + { + // If the number of tuples is still too small, we need to recreate the array + cells->SetNumberOfComponents(2); + cells->SetNumberOfTuples(nr_points); + vtkIdType *cell = cells->GetPointer(0); + // Fill it with 1s + std::fill(cell, cell + nr_points * 2, 1); + cell++; + for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) + *cell = i; + // Save the results in initcells + initcells = vtkSmartPointer::New(); + initcells->DeepCopy(cells); + } } else { - // If the number of tuples is still too small, we need to recreate the array + // The assumption here is that the current set of cells has more data than needed cells->SetNumberOfComponents(2); cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); } - } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - // Set the cells and the vertices - vertices->SetCells(nr_points, cells); - return polydata; - } + // Set the cells and the vertices + vertices->SetCells(nr_points, cells); + return polydata; + } - static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data, Vec3d& minmax) - { - vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); - if (!mapper) + static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data, Vec3d& minmax) { - // This is the first cloud - vtkSmartPointer mapper_new = vtkSmartPointer::New(); + vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); + if (!mapper) + { + // This is the first cloud + vtkSmartPointer mapper_new = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - mapper_new->SetInputConnection(poly_data->GetProducerPort()); + mapper_new->SetInputConnection(poly_data->GetProducerPort()); #else - mapper_new->SetInputData(poly_data); + mapper_new->SetInputData(poly_data); #endif - mapper_new->SetScalarRange(minmax.val); - mapper_new->SetScalarModeToUsePointData(); + mapper_new->SetScalarRange(minmax.val); + mapper_new->SetScalarModeToUsePointData(); - bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); + bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); - mapper_new->SetInterpolateScalarsBeforeMapping(interpolation); - mapper_new->ScalarVisibilityOn(); - mapper_new->ImmediateModeRenderingOff(); + mapper_new->SetInterpolateScalarsBeforeMapping(interpolation); + mapper_new->ScalarVisibilityOn(); + mapper_new->ImmediateModeRenderingOff(); - actor->SetNumberOfCloudPoints(int(std::max(1, poly_data->GetNumberOfPoints() / 10))); - actor->GetProperty()->SetInterpolationToFlat(); - actor->GetProperty()->BackfaceCullingOn(); - actor->SetMapper(mapper_new); - return ; - } + actor->SetNumberOfCloudPoints(int(std::max(1, poly_data->GetNumberOfPoints() / 10))); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper_new); + return ; + } - vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); - CV_Assert("Cloud Widget without data" && data); + vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); + CV_Assert("Cloud Widget without data" && data); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); + vtkSmartPointer appendFilter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInputConnection(mapper->GetInput()->GetProducerPort()); - appendFilter->AddInputConnection(poly_data->GetProducerPort()); + appendFilter->AddInputConnection(mapper->GetInput()->GetProducerPort()); + appendFilter->AddInputConnection(poly_data->GetProducerPort()); #else - appendFilter->AddInputData(data); - appendFilter->AddInputData(poly_data); + appendFilter->AddInputData(data); + appendFilter->AddInputData(poly_data); #endif - mapper->SetInputConnection(appendFilter->GetOutputPort()); + mapper->SetInputConnection(appendFilter->GetOutputPort()); - // Update the number of cloud points - vtkIdType old_cloud_points = actor->GetNumberOfCloudPoints(); - actor->SetNumberOfCloudPoints(int(std::max(1, old_cloud_points+poly_data->GetNumberOfPoints() / 10))); - } -}; + // Update the number of cloud points + vtkIdType old_cloud_points = actor->GetNumberOfCloudPoints(); + actor->SetNumberOfCloudPoints(int(std::max(1, old_cloud_points+poly_data->GetNumberOfPoints() / 10))); + } + }; +}}} cv::viz::WCloudCollection::WCloudCollection() { @@ -397,7 +404,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, } vtkIdType nr_points; - vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); + vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); // Filter colors Vec3b* colors_data = new Vec3b[nr_points]; @@ -429,7 +436,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, CV_Assert("Incompatible widget type." && actor); Vec3d minmax(scalars->GetRange()); - CreateCloudWidget::createMapper(actor, transform_filter->GetOutput(), minmax); + CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput(), minmax); } void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) @@ -438,7 +445,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); vtkIdType nr_points; - vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); + vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); vtkSmartPointer scalars = vtkSmartPointer::New(); scalars->SetNumberOfComponents(3); @@ -468,7 +475,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, CV_Assert("Incompatible widget type." && actor); Vec3d minmax(scalars->GetRange()); - CreateCloudWidget::createMapper(actor, transform_filter->GetOutput(), minmax); + CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput(), minmax); } template<> cv::viz::WCloudCollection cv::viz::Widget::cast() @@ -480,80 +487,84 @@ template<> cv::viz::WCloudCollection cv::viz::Widget::cast - struct Impl + struct CloudNormalsUtils { - static vtkSmartPointer applyOrganized(const Mat &cloud, const Mat& normals, double level, float scale, _Tp *&pts, vtkIdType &nr_normals) + template + struct Impl { - vtkIdType point_step = static_cast(std::sqrt(level)); - nr_normals = (static_cast((cloud.cols - 1) / point_step) + 1) * - (static_cast((cloud.rows - 1) / point_step) + 1); - vtkSmartPointer lines = vtkSmartPointer::New(); + static vtkSmartPointer applyOrganized(const Mat &cloud, const Mat& normals, double level, float scale, _Tp *&pts, vtkIdType &nr_normals) + { + vtkIdType point_step = static_cast(std::sqrt(level)); + nr_normals = (static_cast((cloud.cols - 1) / point_step) + 1) * + (static_cast((cloud.rows - 1) / point_step) + 1); + vtkSmartPointer lines = vtkSmartPointer::New(); - pts = new _Tp[2 * nr_normals * 3]; + pts = new _Tp[2 * nr_normals * 3]; - int cch = cloud.channels(); - vtkIdType cell_count = 0; - for (vtkIdType y = 0; y < cloud.rows; y += point_step) - { - const _Tp *prow = cloud.ptr<_Tp>(y); - const _Tp *nrow = normals.ptr<_Tp>(y); - for (vtkIdType x = 0; x < cloud.cols; x += point_step * cch) + int cch = cloud.channels(); + vtkIdType cell_count = 0; + for (vtkIdType y = 0; y < cloud.rows; y += point_step) { - pts[2 * cell_count * 3 + 0] = prow[x]; - pts[2 * cell_count * 3 + 1] = prow[x+1]; - pts[2 * cell_count * 3 + 2] = prow[x+2]; - pts[2 * cell_count * 3 + 3] = prow[x] + nrow[x] * scale; - pts[2 * cell_count * 3 + 4] = prow[x+1] + nrow[x+1] * scale; - pts[2 * cell_count * 3 + 5] = prow[x+2] + nrow[x+2] * scale; - - lines->InsertNextCell(2); - lines->InsertCellPoint(2 * cell_count); - lines->InsertCellPoint(2 * cell_count + 1); - cell_count++; + const _Tp *prow = cloud.ptr<_Tp>(y); + const _Tp *nrow = normals.ptr<_Tp>(y); + for (vtkIdType x = 0; x < cloud.cols; x += point_step * cch) + { + pts[2 * cell_count * 3 + 0] = prow[x]; + pts[2 * cell_count * 3 + 1] = prow[x+1]; + pts[2 * cell_count * 3 + 2] = prow[x+2]; + pts[2 * cell_count * 3 + 3] = prow[x] + nrow[x] * scale; + pts[2 * cell_count * 3 + 4] = prow[x+1] + nrow[x+1] * scale; + pts[2 * cell_count * 3 + 5] = prow[x+2] + nrow[x+2] * scale; + + lines->InsertNextCell(2); + lines->InsertCellPoint(2 * cell_count); + lines->InsertCellPoint(2 * cell_count + 1); + cell_count++; + } } + return lines; } - return lines; - } - static vtkSmartPointer applyUnorganized(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - vtkSmartPointer lines = vtkSmartPointer::New(); - nr_normals = (cloud.size().area() - 1) / level + 1 ; - pts = new _Tp[2 * nr_normals * 3]; - - int cch = cloud.channels(); - const _Tp *p = cloud.ptr<_Tp>(); - const _Tp *n = normals.ptr<_Tp>(); - for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level * cch) + static vtkSmartPointer applyUnorganized(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) { + vtkSmartPointer lines = vtkSmartPointer::New(); + nr_normals = (cloud.size().area() - 1) / level + 1 ; + pts = new _Tp[2 * nr_normals * 3]; + + int cch = cloud.channels(); + const _Tp *p = cloud.ptr<_Tp>(); + const _Tp *n = normals.ptr<_Tp>(); + for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level * cch) + { - pts[2 * j * 3 + 0] = p[i]; - pts[2 * j * 3 + 1] = p[i+1]; - pts[2 * j * 3 + 2] = p[i+2]; - pts[2 * j * 3 + 3] = p[i] + n[i] * scale; - pts[2 * j * 3 + 4] = p[i+1] + n[i+1] * scale; - pts[2 * j * 3 + 5] = p[i+2] + n[i+2] * scale; + pts[2 * j * 3 + 0] = p[i]; + pts[2 * j * 3 + 1] = p[i+1]; + pts[2 * j * 3 + 2] = p[i+2]; + pts[2 * j * 3 + 3] = p[i] + n[i] * scale; + pts[2 * j * 3 + 4] = p[i+1] + n[i+1] * scale; + pts[2 * j * 3 + 5] = p[i+2] + n[i+2] * scale; - lines->InsertNextCell(2); - lines->InsertCellPoint(2 * j); - lines->InsertCellPoint(2 * j + 1); + lines->InsertNextCell(2); + lines->InsertCellPoint(2 * j); + lines->InsertCellPoint(2 * j + 1); + } + return lines; } - return lines; + }; + + template + static inline vtkSmartPointer apply(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) + { + if (cloud.cols > 1 && cloud.rows > 1) + return CloudNormalsUtils::Impl<_Tp>::applyOrganized(cloud, normals, level, scale, pts, nr_normals); + else + return CloudNormalsUtils::Impl<_Tp>::applyUnorganized(cloud, normals, level, scale, pts, nr_normals); } }; - template - static inline vtkSmartPointer apply(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - if (cloud.cols > 1 && cloud.rows > 1) - return ApplyCloudNormals::Impl<_Tp>::applyOrganized(cloud, normals, level, scale, pts, nr_normals); - else - return ApplyCloudNormals::Impl<_Tp>::applyUnorganized(cloud, normals, level, scale, pts, nr_normals); - } -}; +}}} cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, int level, float scale, const Color &color) { @@ -574,7 +585,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in data->SetNumberOfComponents(3); float* pts = 0; - lines = ApplyCloudNormals::apply(cloud, normals, level, scale, pts, nr_normals); + lines = CloudNormalsUtils::apply(cloud, normals, level, scale, pts, nr_normals); data->SetArray(&pts[0], 2 * nr_normals * 3, 0); points->SetData(data); } @@ -586,7 +597,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in data->SetNumberOfComponents(3); double* pts = 0; - lines = ApplyCloudNormals::apply(cloud, normals, level, scale, pts, nr_normals); + lines = CloudNormalsUtils::apply(cloud, normals, level, scale, pts, nr_normals); data->SetArray(&pts[0], 2 * nr_normals * 3, 0); points->SetData(data); } @@ -619,34 +630,37 @@ template<> cv::viz::WCloudNormals cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// Mesh Widget implementation -struct cv::viz::WMesh::CopyImpl +namespace cv { namespace viz { namespace { - template - static Vec<_Tp, 3> * copy(const Mat &source, Vec<_Tp, 3> *output, int *look_up, const Mat &nan_mask) + struct MeshUtils { - CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); - CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); - CV_DbgAssert(DataDepth<_Tp>::value == nan_mask.depth()); + template + static Vec<_Tp, 3> * copy(const Mat &source, Vec<_Tp, 3> *output, int *look_up, const Mat &nan_mask) + { + CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); + CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); + CV_DbgAssert(DataDepth<_Tp>::value == nan_mask.depth()); - int s_chs = source.channels(); - int m_chs = nan_mask.channels(); + int s_chs = source.channels(); + int m_chs = nan_mask.channels(); - int index = 0; - const _Tp* srow = source.ptr<_Tp>(0); - const _Tp* mrow = nan_mask.ptr<_Tp>(0); + int index = 0; + const _Tp* srow = source.ptr<_Tp>(0); + const _Tp* mrow = nan_mask.ptr<_Tp>(0); - for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) - { - if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) + for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) { - look_up[x] = index; - *output++ = Vec<_Tp, 3>(srow); - ++index; + if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) + { + look_up[x] = index; + *output++ = Vec<_Tp, 3>(srow); + ++index; + } } + return output; } - return output; - } -}; + }; +}}} cv::viz::WMesh::WMesh(const Mesh3d &mesh) { @@ -665,14 +679,14 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) { points->SetDataTypeToFloat(); Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = CopyImpl::copy(mesh.cloud, data_beg, look_up, mesh.cloud); + Vec3f *data_end = MeshUtils::copy(mesh.cloud, data_beg, look_up, mesh.cloud); nr_points = data_end - data_beg; } else { points->SetDataTypeToDouble(); Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = CopyImpl::copy(mesh.cloud, data_beg, look_up, mesh.cloud); + Vec3d *data_end = MeshUtils::copy(mesh.cloud, data_beg, look_up, mesh.cloud); nr_points = data_end - data_beg; } diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index aff3609c95..482397251e 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -84,25 +84,28 @@ template<> cv::viz::WLine cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// plane widget implementation -struct cv::viz::WPlane::SetSizeImpl +namespace cv { namespace viz { namespace { - template - static vtkSmartPointer setSize(const Vec<_Tp, 3> ¢er, vtkSmartPointer poly_data_port, double size) + struct PlaneUtils { - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(center[0], center[1], center[2]); - transform->Scale(size, size, size); - transform->Translate(-center[0], -center[1], -center[2]); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetInputConnection(poly_data_port); - transform_filter->SetTransform(transform); - transform_filter->Update(); - - return transform_filter; - } -}; + template + static vtkSmartPointer setSize(const Vec<_Tp, 3> ¢er, vtkSmartPointer poly_data_port, double size) + { + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->PreMultiply(); + transform->Translate(center[0], center[1], center[2]); + transform->Scale(size, size, size); + transform->Translate(-center[0], -center[1], -center[2]); + + vtkSmartPointer transform_filter = vtkSmartPointer::New(); + transform_filter->SetInputConnection(poly_data_port); + transform_filter->SetTransform(transform); + transform_filter->Update(); + + return transform_filter; + } + }; +}}} cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) { @@ -115,7 +118,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) plane->GetOrigin(p_center.val); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(SetSizeImpl::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); + mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -136,7 +139,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const plane->SetCenter(p_center[0], p_center[1], p_center[2]); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(SetSizeImpl::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); + mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -406,25 +409,28 @@ template<> cv::viz::WCoordinateSystem cv::viz::Widget::cast - static void copy(const Mat& source, Vec<_Tp, 3> *output, vtkSmartPointer polyLine) + struct PolyLineUtils { - int s_chs = source.channels(); - - for (int y = 0, id = 0; y < source.rows; ++y) + template + static void copy(const Mat& source, Vec<_Tp, 3> *output, vtkSmartPointer polyLine) { - const _Tp* srow = source.ptr<_Tp>(y); + int s_chs = source.channels(); - for (int x = 0; x < source.cols; ++x, srow += s_chs, ++id) + for (int y = 0, id = 0; y < source.rows; ++y) { - *output++ = Vec<_Tp, 3>(srow); - polyLine->GetPointIds()->SetId(id,id); + const _Tp* srow = source.ptr<_Tp>(y); + + for (int x = 0; x < source.cols; ++x, srow += s_chs, ++id) + { + *output++ = Vec<_Tp, 3>(srow); + polyLine->GetPointIds()->SetId(id,id); + } } } - } -}; + }; +}}} cv::viz::WPolyLine::WPolyLine(InputArray _pointData, const Color &color) { @@ -448,13 +454,13 @@ cv::viz::WPolyLine::WPolyLine(InputArray _pointData, const Color &color) { // Get a pointer to the beginning of the data array Vec3f *data_beg = vtkpoints_data(points); - CopyImpl::copy(pointData, data_beg, polyLine); + PolyLineUtils::copy(pointData, data_beg, polyLine); } else if (pointData.depth() == CV_64F) { // Get a pointer to the beginning of the data array Vec3d *data_beg = vtkpoints_data(points); - CopyImpl::copy(pointData, data_beg, polyLine); + PolyLineUtils::copy(pointData, data_beg, polyLine); } vtkSmartPointer cells = vtkSmartPointer::New(); @@ -486,36 +492,39 @@ template<> cv::viz::WPolyLine cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// grid widget implementation -struct cv::viz::WGrid::GridImpl +namespace cv { namespace viz { namespace { - static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2d &spacing) + struct GridUtils { - // Create the grid using image data - vtkSmartPointer grid = vtkSmartPointer::New(); + static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2d &spacing) + { + // Create the grid using image data + vtkSmartPointer grid = vtkSmartPointer::New(); - // Add 1 to dimensions because in ImageData dimensions is the number of lines - // - however here it means number of cells - grid->SetDimensions(dimensions[0]+1, dimensions[1]+1, 1); - grid->SetSpacing(spacing[0], spacing[1], 0.); + // Add 1 to dimensions because in ImageData dimensions is the number of lines + // - however here it means number of cells + grid->SetDimensions(dimensions[0]+1, dimensions[1]+1, 1); + grid->SetSpacing(spacing[0], spacing[1], 0.); - // Set origin of the grid to be the middle of the grid - grid->SetOrigin(dimensions[0] * spacing[0] * (-0.5), dimensions[1] * spacing[1] * (-0.5), 0); + // Set origin of the grid to be the middle of the grid + grid->SetOrigin(dimensions[0] * spacing[0] * (-0.5), dimensions[1] * spacing[1] * (-0.5), 0); - // Extract the edges so we have the grid - vtkSmartPointer filter = vtkSmartPointer::New(); + // Extract the edges so we have the grid + vtkSmartPointer filter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - filter->SetInputConnection(grid->GetProducerPort()); + filter->SetInputConnection(grid->GetProducerPort()); #else - filter->SetInputData(grid); + filter->SetInputData(grid); #endif - filter->Update(); - return filter->GetOutput(); - } -}; + filter->Update(); + return filter->GetOutput(); + } + }; +}}} cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color) { - vtkSmartPointer grid = GridImpl::createGrid(dimensions, spacing); + vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); vtkSmartPointer mapper = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 @@ -533,7 +542,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color) { - vtkSmartPointer grid = GridImpl::createGrid(dimensions, spacing); + vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); // Estimate the transform to set the normal based on the coefficients Vec3f normal(coefs[0], coefs[1], coefs[2]); @@ -938,99 +947,102 @@ template<> cv::viz::WImage3D cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// camera position widget implementation -struct cv::viz::WCameraPosition::ProjectImage +namespace cv { namespace viz { namespace { - static void projectImage(float fovy, float far_end_height, const Mat &image, - double scale, const Color &color, vtkSmartPointer actor) + struct CameraPositionUtils { - // Create a camera - vtkSmartPointer camera = vtkSmartPointer::New(); - float aspect_ratio = float(image.cols)/float(image.rows); - - // Create the vtk image - vtkSmartPointer vtk_image = vtkSmartPointer::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 flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip + static void projectImage(float fovy, float far_end_height, const Mat &image, + double scale, const Color &color, vtkSmartPointer actor) + { + // Create a camera + vtkSmartPointer camera = vtkSmartPointer::New(); + float aspect_ratio = float(image.cols)/float(image.rows); + + // Create the vtk image + vtkSmartPointer vtk_image = vtkSmartPointer::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 flipFilter = vtkSmartPointer::New(); + flipFilter->SetFilteredAxis(1); // Vertical flip #if VTK_MAJOR_VERSION <= 5 - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(vtk_image->GetProducerPort()); #else - flipFilter->SetInputData(vtk_image); + flipFilter->SetInputData(vtk_image); #endif - flipFilter->Update(); - - Vec3d plane_center(0.0, 0.0, scale); - - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]); - plane->SetNormal(0.0, 0.0, 1.0); - - vtkSmartPointer transform = vtkSmartPointer::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 texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); - - vtkSmartPointer texturePlane = vtkSmartPointer::New(); - texturePlane->SetInputConnection(plane->GetOutputPort()); - - vtkSmartPointer transform_filter = vtkSmartPointer::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 planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = - vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); - - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); - - // Frustum needs to be textured or else it can't be combined with image - vtkSmartPointer frustum_texture = vtkSmartPointer::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 appendFilter = vtkSmartPointer::New(); - appendFilter->AddInputConnection(frustum_texture->GetOutputPort()); - appendFilter->AddInputConnection(transform_filter->GetOutputPort()); - - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(appendFilter->GetOutputPort()); - - actor->SetMapper(planeMapper); - actor->SetTexture(texture); - } -}; + flipFilter->Update(); + + Vec3d plane_center(0.0, 0.0, scale); + + vtkSmartPointer plane = vtkSmartPointer::New(); + plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]); + plane->SetNormal(0.0, 0.0, 1.0); + + vtkSmartPointer transform = vtkSmartPointer::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 texture = vtkSmartPointer::New(); + texture->SetInputConnection(flipFilter->GetOutputPort()); + + vtkSmartPointer texturePlane = vtkSmartPointer::New(); + texturePlane->SetInputConnection(plane->GetOutputPort()); + + vtkSmartPointer transform_filter = vtkSmartPointer::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 planes = vtkSmartPointer::New(); + planes->SetFrustumPlanes(planesArray); + + vtkSmartPointer frustumSource = + vtkSmartPointer::New(); + frustumSource->SetPlanes(planes); + frustumSource->Update(); + + vtkSmartPointer filter = vtkSmartPointer::New(); + filter->SetInputConnection(frustumSource->GetOutputPort()); + filter->Update(); + + // Frustum needs to be textured or else it can't be combined with image + vtkSmartPointer frustum_texture = vtkSmartPointer::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 appendFilter = vtkSmartPointer::New(); + appendFilter->AddInputConnection(frustum_texture->GetOutputPort()); + appendFilter->AddInputConnection(transform_filter->GetOutputPort()); + + vtkSmartPointer planeMapper = vtkSmartPointer::New(); + planeMapper->SetInputConnection(appendFilter->GetOutputPort()); + + actor->SetMapper(planeMapper); + actor->SetTexture(texture); + } + }; +}}} cv::viz::WCameraPosition::WCameraPosition(float scale) { @@ -1164,7 +1176,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, fl float far_end_height = 2.0f * c_y * scale / f_y; vtkSmartPointer actor = vtkSmartPointer::New(); - ProjectImage::projectImage(fovy, far_end_height, image, scale, color, actor); + CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); WidgetAccessor::setProp(*this, actor); } @@ -1175,7 +1187,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, const Mat &image, fl float far_end_height = 2.0 * scale * tan(fov[1] * 0.5); vtkSmartPointer actor = vtkSmartPointer::New(); - ProjectImage::projectImage(fovy, far_end_height, image, scale, color, actor); + CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); WidgetAccessor::setProp(*this, actor); } @@ -1188,37 +1200,40 @@ template<> cv::viz::WCameraPosition cv::viz::Widget::cast poly_data, vtkSmartPointer append_filter, const std::vector &path) + struct TrajectoryUtils { - vtkIdType nr_points = path.size(); - - for (vtkIdType i = 0; i < nr_points; ++i) + static void applyPath(vtkSmartPointer poly_data, vtkSmartPointer append_filter, const std::vector &path) { - vtkSmartPointer new_data = vtkSmartPointer::New(); - new_data->DeepCopy(poly_data); + vtkIdType nr_points = path.size(); - // Transform the default coordinate frame - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans = convertToVtkMatrix(path[i].matrix); - transform->SetMatrix(mat_trans); + for (vtkIdType i = 0; i < nr_points; ++i) + { + vtkSmartPointer new_data = vtkSmartPointer::New(); + new_data->DeepCopy(poly_data); - vtkSmartPointer filter = vtkSmartPointer::New(); + // Transform the default coordinate frame + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->PreMultiply(); + vtkSmartPointer mat_trans = vtkSmartPointer::New(); + mat_trans = convertToVtkMatrix(path[i].matrix); + transform->SetMatrix(mat_trans); + + vtkSmartPointer filter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - filter->SetInput(new_data); + filter->SetInput(new_data); #else - filter->SetInputData(new_data); + filter->SetInputData(new_data); #endif - filter->SetTransform(transform); - filter->Update(); + filter->SetTransform(transform); + filter->Update(); - append_filter->AddInputConnection(filter->GetOutputPort()); + append_filter->AddInputConnection(filter->GetOutputPort()); + } } - } -}; + }; +}}} cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, const Color &color, float scale) { @@ -1303,7 +1318,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display axes_tubes->SetNumberOfSides(6); axes_tubes->Update(); - ApplyPath::applyPath(axes_tubes->GetOutput(), appendFilter, path); + TrajectoryUtils::applyPath(axes_tubes->GetOutput(), appendFilter, path); } vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -1348,7 +1363,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx3 filter->Update(); vtkSmartPointer appendFilter = vtkSmartPointer::New(); - ApplyPath::applyPath(filter->GetOutput(), appendFilter, path); + TrajectoryUtils::applyPath(filter->GetOutput(), appendFilter, path); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(appendFilter->GetOutputPort()); @@ -1388,7 +1403,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Vec2f filter->Update(); vtkSmartPointer appendFilter = vtkSmartPointer::New(); - ApplyPath::applyPath(filter->GetOutput(), appendFilter, path); + TrajectoryUtils::applyPath(filter->GetOutput(), appendFilter, path); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(appendFilter->GetOutputPort()); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 04abdcf7a0..5c2df04dcd 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -303,27 +303,6 @@ void cv::viz::WidgetAccessor::setProp(Widget& widget, vtkSmartPointer p /////////////////////////////////////////////////////////////////////////////////////////////// /// widget3D implementation -struct cv::viz::Widget3D::MatrixConverter -{ - static Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix) - { - Matx44f m; - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - m(i, k) = vtk_matrix->GetElement(i, k); - return m; - } - - static vtkSmartPointer convertToVtkMatrix(const Matx44f& m) - { - vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - vtk_matrix->SetElement(i, k, m(i, k)); - return vtk_matrix; - } -}; - void cv::viz::Widget3D::setPose(const Affine3f &pose) { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); @@ -345,10 +324,9 @@ void cv::viz::Widget3D::updatePose(const Affine3f &pose) setPose(pose); return ; } - Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix); - Affine3f updated_pose = pose * Affine3f(matrix_cv); - matrix = MatrixConverter::convertToVtkMatrix(updated_pose.matrix); + Affine3f updated_pose = pose * Affine3f(convertToMatx(matrix)); + matrix = convertToVtkMatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); @@ -358,10 +336,7 @@ cv::Affine3f cv::viz::Widget3D::getPose() const { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); - - vtkSmartPointer matrix = actor->GetUserMatrix(); - Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix); - return Affine3f(matrix_cv); + return Affine3f(convertToMatx(actor->GetUserMatrix())); } void cv::viz::Widget3D::setColor(const Color &color) From c7ff13873d6e5e371f2658f128d7fbfc4ef77832 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 16:57:09 +0400 Subject: [PATCH 06/91] minor --- modules/viz/include/opencv2/viz/widgets.hpp | 12 ++++++++++++ modules/viz/src/precomp.hpp | 7 ++++++- modules/viz/src/viz3d_impl.cpp | 8 ++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 42e0f1968b..ea43976dd1 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -132,6 +132,9 @@ namespace cv void setColor(const Color &color); }; + ///////////////////////////////////////////////////////////////////////////// + /// Simple widgets + class CV_EXPORTS WLine : public Widget3D { public: @@ -175,6 +178,9 @@ namespace cv WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, const Color &color = Color::white()); }; + ///////////////////////////////////////////////////////////////////////////// + /// Compond widgets + class CV_EXPORTS WCoordinateSystem : public Widget3D { public: @@ -268,6 +274,9 @@ namespace cv float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; + ///////////////////////////////////////////////////////////////////////////// + /// Cloud widgets + class CV_EXPORTS WCloud: public Widget3D { public: @@ -300,6 +309,9 @@ namespace cv WMesh(const Mesh3d &mesh); }; + ///////////////////////////////////////////////////////////////////////////// + /// Utility exports + template<> CV_EXPORTS Widget2D Widget::cast(); template<> CV_EXPORTS Widget3D Widget::cast(); template<> CV_EXPORTS WLine Widget::cast(); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 1beb43587c..5994aaa1bc 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -94,7 +94,6 @@ #include #include #include -#include #include #include #include @@ -111,6 +110,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include diff --git a/modules/viz/src/viz3d_impl.cpp b/modules/viz/src/viz3d_impl.cpp index b1173f645d..af3f93b71c 100644 --- a/modules/viz/src/viz3d_impl.cpp +++ b/modules/viz/src/viz3d_impl.cpp @@ -48,9 +48,9 @@ #include "precomp.hpp" -vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew(); -#if 1 || !defined __APPLE__ +#if (1 || !defined __APPLE__) && !defined _MSC_VER +vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew(); vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew() { return vtkRenderWindowInteractor::New(); @@ -79,7 +79,11 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) style_->UseTimersOn(); ///////////////////////////////////////////////// +#if (1 || !defined __APPLE__) && !defined _MSC_VER interactor_ = vtkSmartPointer::Take(vtkRenderWindowInteractorFixNew()); +#else + interactor_ = vtkSmartPointer::New(); +#endif window_->AlphaBitPlanesOff(); window_->PointSmoothingOff(); From 54fa69cab2266ffe4ad8e0ad8a57bf29ee2b5979 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 17:12:02 +0400 Subject: [PATCH 07/91] renamed Spheres Trajectory, minor changes in Trajectory --- modules/viz/doc/widget.rst | 28 ++++++++++----------- modules/viz/include/opencv2/viz/widgets.hpp | 12 ++++----- modules/viz/src/shape_widgets.cpp | 10 ++++---- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index bbbfef63a9..90147e441b 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -729,10 +729,10 @@ This 3D Widget represents a trajectory. :: class CV_EXPORTS WTrajectory : public Widget3D { public: - enum {DISPLAY_FRAMES = 1, DISPLAY_PATH = 2}; + enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.0); //! Displays trajectory of the given path by frustums WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums @@ -746,18 +746,18 @@ viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0) +.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.0) :param path: List of poses on a trajectory. - :param display_mode: Display mode. This can be DISPLAY_PATH, DISPLAY_FRAMES, DISPLAY_PATH & DISPLAY_FRAMES. + :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. :param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected. :param scale: Scale of the frames. Polyline is not affected. Displays trajectory of the given path as follows: - * DISPLAY_PATH : Displays a poly line that represents the path. - * DISPLAY_FRAMES : Displays coordinate frames at each pose. - * DISPLAY_PATH & DISPLAY_FRAMES : Displays both poly line and coordinate frames. + * PATH : Displays a poly line that represents the path. + * FRAMES : Displays coordinate frames at each pose. + * PATH & FRAMES : Displays both poly line and coordinate frames. .. ocv:function:: WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) @@ -777,26 +777,26 @@ Constructs a WTrajectory. Displays frustums at each pose of the trajectory. -viz::WSpheresTrajectory +viz::WTrajectorySpheres ----------------------- -.. ocv:class:: WSpheresTrajectory +.. ocv:class:: WTrajectorySpheres This 3D Widget represents a trajectory using spheres and lines, where spheres represent the positions of the camera, and lines represent the direction from previous position to the current. :: - class CV_EXPORTS WSpheresTrajectory : public Widget3D + class CV_EXPORTS WTrajectorySpheres : public Widget3D { public: - WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, + WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, sphere_radius = 0.007, Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; -viz::WSpheresTrajectory::WSpheresTrajectory +viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- -Constructs a WSpheresTrajectory. +Constructs a WTrajectorySpheres. -.. ocv:function:: WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) :param path: List of poses on a trajectory. :param line_length: Length of the lines. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index ea43976dd1..fb2783b17d 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -257,21 +257,21 @@ namespace cv class CV_EXPORTS WTrajectory : public Widget3D { public: - enum {DISPLAY_FRAMES = 1, DISPLAY_PATH = 2}; + enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.f); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.f); //! Displays trajectory of the given path by frustums WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); }; - class CV_EXPORTS WSpheresTrajectory: public Widget3D + class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: - WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, - float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, + float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// @@ -330,7 +330,7 @@ namespace cv template<> CV_EXPORTS WImage3D Widget::cast(); template<> CV_EXPORTS WCameraPosition Widget::cast(); template<> CV_EXPORTS WTrajectory Widget::cast(); - template<> CV_EXPORTS WSpheresTrajectory Widget::cast(); + template<> CV_EXPORTS WTrajectorySpheres Widget::cast(); template<> CV_EXPORTS WCloud Widget::cast(); template<> CV_EXPORTS WCloudCollection Widget::cast(); template<> CV_EXPORTS WCloudNormals Widget::cast(); diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 482397251e..8d226ff669 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -1240,7 +1240,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display vtkSmartPointer appendFilter = vtkSmartPointer::New(); // Bitwise and with 3 in order to limit the domain to 2 bits - if ((~display_mode & 3) ^ WTrajectory::DISPLAY_PATH) + if ((~display_mode & 3) ^ WTrajectory::PATH) { // Create a poly line along the path vtkIdType nr_points = path.size(); @@ -1284,7 +1284,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display #endif } - if ((~display_mode & 3) ^ WTrajectory::DISPLAY_FRAMES) + if ((~display_mode & 3) ^ WTrajectory::FRAMES) { // Create frames and transform along the path vtkSmartPointer axes = vtkSmartPointer::New(); @@ -1424,7 +1424,7 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// spheres trajectory widget implementation -cv::viz::WSpheresTrajectory::WSpheresTrajectory(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, +cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, const Color &line_color, const Color &sphere_color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1505,8 +1505,8 @@ cv::viz::WSpheresTrajectory::WSpheresTrajectory(const std::vector &pat WidgetAccessor::setProp(*this, actor); } -template<> cv::viz::WSpheresTrajectory cv::viz::Widget::cast() +template<> cv::viz::WTrajectorySpheres cv::viz::Widget::cast() { Widget3D widget = this->cast(); - return static_cast(widget); + return static_cast(widget); } From 31d42ce18f55f4f42388eaa52e106a8733a099de Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 18:07:16 +0400 Subject: [PATCH 08/91] refactored Trajectory: split into Trajectory and TrajectoryFrustums) --- modules/viz/doc/widget.rst | 36 ++++++++++++++------- modules/viz/include/opencv2/viz/widgets.hpp | 20 ++++++++---- modules/viz/src/shape_widgets.cpp | 21 ++++++++---- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 90147e441b..a629b7bc91 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -732,26 +732,19 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.0); - //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); - //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); - - private: - /* hidden */ + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.0) +.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. - :param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected. :param scale: Scale of the frames. Polyline is not affected. + :param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected. Displays trajectory of the given path as follows: @@ -759,7 +752,26 @@ Constructs a WTrajectory. * FRAMES : Displays coordinate frames at each pose. * PATH & FRAMES : Displays both poly line and coordinate frames. -.. ocv:function:: WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) +viz::WTrajectoryFrustums +---------------- +.. ocv:class:: WTrajectoryFrustums + +This 3D Widget represents a trajectory. :: + + class CV_EXPORTS WTrajectoryFrustums : public Widget3D + { + public: + //! Displays trajectory of the given path by frustums + WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); + //! Displays trajectory of the given path by frustums + WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); + }; + +viz::WTrajectoryFrustums::WTrajectoryFrustums +----------------------------- +Constructs a WTrajectoryFrustums. + +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param K: Intrinsic matrix of the camera. @@ -768,7 +780,7 @@ Constructs a WTrajectory. Displays frustums at each pose of the trajectory. -.. ocv:function:: WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param fov: Field of view of the camera (horizontal, vertical). diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index fb2783b17d..cb2dae20e7 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -245,13 +245,13 @@ namespace cv //! Creates camera coordinate frame (axes) at the origin WCameraPosition(float scale = 1.f); //! Creates frustum based on the intrinsic marix K at the origin - WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + explicit WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + explicit WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + explicit WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + explicit WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectory : public Widget3D @@ -260,11 +260,16 @@ namespace cv enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.f); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); + }; + + class CV_EXPORTS WTrajectoryFrustums : public Widget3D + { + public: //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + explicit WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + explicit WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D @@ -330,6 +335,7 @@ namespace cv template<> CV_EXPORTS WImage3D Widget::cast(); template<> CV_EXPORTS WCameraPosition Widget::cast(); template<> CV_EXPORTS WTrajectory Widget::cast(); + template<> CV_EXPORTS WTrajectoryFrustums Widget::cast(); template<> CV_EXPORTS WTrajectorySpheres Widget::cast(); template<> CV_EXPORTS WCloud Widget::cast(); template<> CV_EXPORTS WCloudCollection Widget::cast(); diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 8d226ff669..3a2ba58f95 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -1235,7 +1235,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, const Color &color, float scale) +cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, float scale, const Color &color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1331,7 +1331,16 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display WidgetAccessor::setProp(*this, actor); } -cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx33f &K, float scale, const Color &color) +template<> cv::viz::WTrajectory cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// WTrajectoryFrustums widget implementation + +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); float f_x = K(0,0); @@ -1375,7 +1384,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx3 setColor(color); } -cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Vec2f &fov, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -1415,14 +1424,14 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Vec2f setColor(color); } -template<> cv::viz::WTrajectory cv::viz::Widget::cast() +template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast() { Widget3D widget = this->cast(); - return static_cast(widget); + return static_cast(widget); } /////////////////////////////////////////////////////////////////////////////////////////////// -/// spheres trajectory widget implementation +/// WTrajectorySpheres widget implementation cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, const Color &line_color, const Color &sphere_color) From 4979f44cfa83a3fb0b18fec9a56fdb36efb97adb Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 18:11:19 +0400 Subject: [PATCH 09/91] minor --- modules/viz/include/opencv2/viz/viz3d.hpp | 3 - .../include/opencv2/viz/widget_accessor.hpp | 5 +- modules/viz/include/opencv2/viz/widgets.hpp | 53 ++++---- modules/viz/src/precomp.cpp | 3 - modules/viz/src/precomp.hpp | 3 - modules/viz/src/viz.cpp | 3 - modules/viz/src/viz3d_impl.hpp | 4 +- modules/viz/test/test_precomp.hpp | 3 - modules/viz/test/test_viz3d.cpp | 125 +----------------- 9 files changed, 38 insertions(+), 164 deletions(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index f572059197..d3f5a109cc 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_VIZ3D_HPP__ diff --git a/modules/viz/include/opencv2/viz/widget_accessor.hpp b/modules/viz/include/opencv2/viz/widget_accessor.hpp index 394cfa8587..29352a214b 100644 --- a/modules/viz/include/opencv2/viz/widget_accessor.hpp +++ b/modules/viz/include/opencv2/viz/widget_accessor.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_WIDGET_ACCESSOR_HPP__ @@ -69,4 +66,4 @@ namespace cv } } -#endif \ No newline at end of file +#endif diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index cb2dae20e7..0b0c5fc28c 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_WIDGETS_HPP__ @@ -178,43 +175,28 @@ namespace cv WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, const Color &color = Color::white()); }; - ///////////////////////////////////////////////////////////////////////////// - /// Compond widgets - - class CV_EXPORTS WCoordinateSystem : public Widget3D - { - public: - WCoordinateSystem(float scale = 1.f); - }; - class CV_EXPORTS WPolyLine : public Widget3D { public: WPolyLine(InputArray points, const Color &color = Color::white()); }; - class CV_EXPORTS WGrid : public Widget3D - { - public: - //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - //! Creates grid based on the plane equation - WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - }; + ///////////////////////////////////////////////////////////////////////////// + /// Text and image widgets - class CV_EXPORTS WText3D : public Widget3D + class CV_EXPORTS WText : public Widget2D { public: - WText3D(const String &text, const Point3f &position, float text_scale = 1.f, bool face_camera = true, const Color &color = Color::white()); + WText(const String &text, const Point2i &pos, int font_size = 20, const Color &color = Color::white()); void setText(const String &text); String getText() const; }; - class CV_EXPORTS WText : public Widget2D + class CV_EXPORTS WText3D : public Widget3D { public: - WText(const String &text, const Point2i &pos, int font_size = 20, const Color &color = Color::white()); + WText3D(const String &text, const Point3f &position, float text_scale = 1.f, bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -239,6 +221,24 @@ namespace cv void setImage(const Mat &image); }; + ///////////////////////////////////////////////////////////////////////////// + /// Compond widgets + + class CV_EXPORTS WCoordinateSystem : public Widget3D + { + public: + WCoordinateSystem(float scale = 1.f); + }; + + class CV_EXPORTS WGrid : public Widget3D + { + public: + //! Creates grid at the origin + WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + //! Creates grid based on the plane equation + WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + }; + class CV_EXPORTS WCameraPosition : public Widget3D { public: @@ -254,6 +254,9 @@ namespace cv explicit WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); }; + ///////////////////////////////////////////////////////////////////////////// + /// Trajectories + class CV_EXPORTS WTrajectory : public Widget3D { public: @@ -280,7 +283,7 @@ namespace cv }; ///////////////////////////////////////////////////////////////////////////// - /// Cloud widgets + /// Clouds class CV_EXPORTS WCloud: public Widget3D { diff --git a/modules/viz/src/precomp.cpp b/modules/viz/src/precomp.cpp index 834648577c..631a300da2 100644 --- a/modules/viz/src/precomp.cpp +++ b/modules/viz/src/precomp.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 5994aaa1bc..7f09ee0766 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_PRECOMP_HPP__ diff --git a/modules/viz/src/viz.cpp b/modules/viz/src/viz.cpp index 6a08dfa34a..445d483de0 100644 --- a/modules/viz/src/viz.cpp +++ b/modules/viz/src/viz.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" diff --git a/modules/viz/src/viz3d_impl.hpp b/modules/viz/src/viz3d_impl.hpp index a7ef9c4374..b38ad29666 100644 --- a/modules/viz/src/viz3d_impl.hpp +++ b/modules/viz/src/viz3d_impl.hpp @@ -73,10 +73,10 @@ public: double getDesiredUpdateRate(); /** \brief Returns true when the user tried to close the window */ - bool wasStopped() const { if (interactor_ != NULL) return (stopped_); else return true; } + bool wasStopped() const { return interactor_ ? stopped_ : true; } /** \brief Set the stopped flag back to false */ - void resetStoppedFlag() { if (interactor_ != NULL) stopped_ = false; } + void resetStoppedFlag() { if (interactor_) stopped_ = false; } /** \brief Stop the interaction and close the visualizaton window. */ void close() diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index 9b98f206b1..ff7606ed9b 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifdef __GNUC__ diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 98811165ab..29cf81ebb2 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -41,141 +41,30 @@ //M*/ #include "test_precomp.hpp" - using namespace cv; static cv::Mat cvcloud_load() { cv::Mat cloud(1, 20000, CV_32FC3); - std::ifstream ifs("/Users/nerei/cloud_dragon.ply"); + std::ifstream ifs("d:/cloud_dragon.ply"); std::string str; for(size_t i = 0; i < 11; ++i) std::getline(ifs, str); cv::Point3f* data = cloud.ptr(); - for(size_t i = 0; i < 20000; ++i) + for(size_t i = 0; i < cloud.total(); ++i) ifs >> data[i].x >> data[i].y >> data[i].z; return cloud; } -bool constant_cam = true; -cv::viz::Widget cam_1, cam_coordinates; - -void keyboard_callback(const viz::KeyboardEvent & event, void * cookie) -{ - if (event.keyDown()) - { - if (event.getKeySym() == "space") - { - viz::Viz3d &viz = *((viz::Viz3d *) cookie); - constant_cam = !constant_cam; - if (constant_cam) - { - viz.showWidget("cam_1", cam_1); - viz.showWidget("cam_coordinate", cam_coordinates); - viz.showWidget("cam_text", viz::WText("Global View", Point2i(5,5), 28)); - viz.resetCamera(); - } - else - { - viz.showWidget("cam_text", viz::WText("Cam View", Point2i(5,5), 28)); - viz.removeWidget("cam_1"); - viz.removeWidget("cam_coordinate"); - } - } - } -} - TEST(Viz_viz3d, develop) { + cv::Mat cloud = cvcloud_load(); cv::viz::Viz3d viz("abc"); - - cv::viz::Mesh3d bunny_mesh = cv::viz::Mesh3d::loadMesh("bunny.ply"); - cv::viz::WMesh bunny_widget(bunny_mesh); - bunny_widget.setColor(cv::viz::Color::cyan()); - - cam_1 = cv::viz::WCameraPosition(cv::Vec2f(0.6f, 0.4f), 0.2, cv::viz::Color::green()); - cam_coordinates = cv::viz::WCameraPosition(0.2); - - viz.showWidget("bunny", bunny_widget); - viz.showWidget("cam_1", cam_1, viz::makeCameraPose(Point3f(1.f,0.f,0.f), Point3f(0.f,0.f,0.f), Point3f(0.f,1.f,0.f))); - viz.showWidget("cam_coordinate", cam_coordinates, viz::makeCameraPose(Point3f(1.f,0.f,0.f), Point3f(0.f,0.f,0.f), Point3f(0.f,1.f,0.f))); - - std::vector cam_path; - - for (int i = 0, j = 0; i <= 360; ++i, j+=5) - { - cam_path.push_back(viz::makeCameraPose(Vec3d(0.5*cos(i*CV_PI/180.0), 0.5*sin(j*CV_PI/180.0), 0.5*sin(i*CV_PI/180.0)), Vec3f(0.f, 0.f, 0.f), Vec3f(0.f, 1.f, 0.f))); - } - - int path_counter = 0; - int cam_path_size = cam_path.size(); - - // OTHER WIDGETS - cv::Mat img = imread("opencv.png"); - - int downSample = 4; - - int row_max = img.rows/downSample; - int col_max = img.cols/downSample; - - cv::Mat *clouds = new cv::Mat[img.cols/downSample]; - cv::Mat *colors = new cv::Mat[img.cols/downSample]; - - for (int col = 0; col < col_max; ++col) - { - clouds[col] = Mat::zeros(img.rows/downSample, 1, CV_32FC3); - colors[col] = Mat::zeros(img.rows/downSample, 1, CV_8UC3); - for (int row = 0; row < row_max; ++row) - { - clouds[col].at(row) = Vec3f(downSample * float(col) / img.cols, 1.f-(downSample * float(row) / img.rows), 0.f); - colors[col].at(row) = img.at(row*downSample,col*downSample); - } - } - - for (int col = 0; col < col_max; ++col) - { - std::stringstream strstrm; - strstrm << "cloud_" << col; - viz.showWidget(strstrm.str(), viz::WCloud(clouds[col], colors[col])); - viz.getWidget(strstrm.str()).setRenderingProperty(viz::POINT_SIZE, 3.0); - viz.getWidget(strstrm.str()).setRenderingProperty(viz::OPACITY, 0.45); - } - - viz.showWidget("trajectory", viz::WTrajectory(cam_path, viz::WTrajectory::DISPLAY_PATH, viz::Color::yellow())); - viz.showWidget("cam_text", viz::WText("Global View", Point2i(5,5), 28)); - viz.registerKeyboardCallback(keyboard_callback, (void *) &viz); - - int angle = 0; - - while(!viz.wasStopped()) - { - if (path_counter == cam_path_size) - { - path_counter = 0; - } - - if (!constant_cam) - { - viz.setViewerPose(cam_path[path_counter]); - } - - if (angle == 360) angle = 0; - - cam_1.cast().setPose(cam_path[path_counter]); - cam_coordinates.cast().setPose(cam_path[path_counter++]); - - for (int i = 0; i < col_max; ++i) - { - std::stringstream strstrm; - strstrm << "cloud_" << i; - viz.setWidgetPose(strstrm.str(), Affine3f().translate(Vec3f(-0.5f, 0.f, (float)(-0.7 + 0.2*sin((angle+i*10)*CV_PI / 180.0))))); - } - angle += 10; - viz.spinOnce(42, true); - } - - volatile void* a = (void*)&cvcloud_load; (void)a; //fixing warnings + cv::viz::WCloud c(cloud, cv::Mat(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0))); + //cv::viz::WCloud c(cloud, cv::viz::Color::bluberry()); + viz.showWidget("c", c); + viz.spin(); } From e048df51ced6ff5863c806104ae0019deafcbb38 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 18:31:04 +0400 Subject: [PATCH 10/91] for shapes switched vtkDataSetMapper to more efficient vtkPolyDataMapper --- modules/viz/src/shape_widgets.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 3a2ba58f95..b7af4b7604 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -65,7 +65,7 @@ cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color line->SetPoint2(pt2.x, pt2.y, pt2.z); line->Update(); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(line->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -117,7 +117,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) Vec3d p_center; plane->GetOrigin(p_center.val); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -138,7 +138,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const Vec3f p_center = pt - coefs3 * t * norm_sqr; plane->SetCenter(p_center[0], p_center[1], p_center[2]); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -167,7 +167,7 @@ cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolu sphere->LatLongTessellationOff(); sphere->Update(); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(sphere->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -240,7 +240,7 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, transformPD->SetTransform(transform); transformPD->SetInputConnection(arrowSource->GetOutputPort()); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(transformPD->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -276,7 +276,7 @@ cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, cons tf->SetTransform(t); tf->SetInputConnection(disk->GetOutputPort()); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tf->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -307,7 +307,7 @@ cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_dir tuber->SetRadius(radius); tuber->SetNumberOfSides(numsides); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tuber->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -328,7 +328,7 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() cv::viz::WCube::WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame, const Color &color) { - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); if (wire_frame) { vtkSmartPointer cube = vtkSmartPointer::New(); @@ -390,7 +390,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); axes_tubes->SetNumberOfSides(6); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); @@ -526,7 +526,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 mapper->SetInputConnection(grid->GetProducerPort()); #else @@ -583,7 +583,7 @@ cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2d & #endif transform_filter->Update(); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(transform_filter->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -1076,7 +1076,7 @@ cv::viz::WCameraPosition::WCameraPosition(float scale) axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); axes_tubes->SetNumberOfSides(6); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); From e990d5b99913ac48da075d5f2048c797c31c6e8b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 19:31:23 +0400 Subject: [PATCH 11/91] reading/writing trajectories --- modules/viz/include/opencv2/viz.hpp | 16 +++++ modules/viz/src/{viz.cpp => vizcore.cpp} | 82 ++++++++++++++++++++++++ 2 files changed, 98 insertions(+) rename modules/viz/src/{viz.cpp => vizcore.cpp} (67%) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index d4f08af725..65ad10aacc 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -91,6 +91,22 @@ namespace cv template inline bool isNan(const Point3_<_Tp>& p) { return isNan(p.x) || isNan(p.y) || isNan(p.z); } + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Read/write poses and trajectories + + CV_EXPORTS bool readPose(const String& file, Affine3f& pose, const String& tag = "pose"); + CV_EXPORTS bool readPose(const String& file, Affine3d& pose, const String& tag = "pose"); + + CV_EXPORTS void writePose(const String& file, const Affine3f& pose, const String& tag = "pose"); + CV_EXPORTS void writePose(const String& file, const Affine3d& pose, const String& tag = "pose"); + + CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); + CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); + + CV_EXPORTS void readTrajectory(std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); + CV_EXPORTS void readTrajectory(std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); + } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/src/viz.cpp b/modules/viz/src/vizcore.cpp similarity index 67% rename from modules/viz/src/viz.cpp rename to modules/viz/src/vizcore.cpp index 445d483de0..dd998e7d92 100644 --- a/modules/viz/src/viz.cpp +++ b/modules/viz/src/vizcore.cpp @@ -160,3 +160,85 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Read/write poses and trajectories + +namespace cv { namespace viz { namespace impl +{ + template + bool readPose(const String& file, Affine3<_Tp>& pose, const String& tag) + { + FileStorage fs(file, FileStorage::READ); + if (!fs.isOpened()) + return false; + + Mat hdr(pose.matrix, false); + fs[tag] >> hdr; + return !hdr.empty() && hdr.depth() == DataDepth<_Tp>::value; + } + + template + void writePose(const String& file, const Affine3<_Tp>& pose, const String& tag) + { + FileStorage fs(file, FileStorage::WRITE); + fs << tag << Mat(pose.matrix, false); + } + + template + void readTrajectory(std::vector >& traj, const String& files_format, int start, int end, const String& tag) + { + start = max(0, std::min(start, end)); + end = std::max(start, end); + + std::vector< Affine3<_Tp> > temp; + + for(int i = start; i < end; ++i) + { + Affine3<_Tp> affine; + bool ok = readPose(cv::format(files_format.c_str(), i),affine, tag); + if (!ok) + break; + + temp.push_back(affine); + } + traj.swap(temp); + } + + template + void writeTrajectory(const std::vector >& traj, const String& files_format, int start, const String& tag) + { + for(size_t i = 0, index = max(0, start); i < traj.size(); ++i, ++index) + writePose(cv::format(files_format.c_str(), index), traj[i], tag); + } +}}} + + +bool cv::viz::readPose(const String& file, Affine3f& pose, const String& tag) { return impl::readPose(file, pose, tag); } +bool cv::viz::readPose(const String& file, Affine3d& pose, const String& tag) { return impl::readPose(file, pose, tag); } + +void cv::viz::writePose(const String& file, const Affine3f& pose, const String& tag) { impl::writePose(file, pose, tag); } +void cv::viz::writePose(const String& file, const Affine3d& pose, const String& tag) { impl::writePose(file, pose, tag); } + +void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) +{ impl::readTrajectory(traj, files_format, start, end, tag); } + +void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) +{ impl::readTrajectory(traj, files_format, start, end, tag); } + +void cv::viz::writeTrajectory(const std::vector& traj, const String& files_format, int start, const String& tag) +{ impl::writeTrajectory(traj, files_format, start, tag); } + +void cv::viz::writeTrajectory(const std::vector& traj, const String& files_format, int start, const String& tag) +{ impl::writeTrajectory(traj, files_format, start, tag); } + + + + + + + + + + From abc94657980594ac1aea311c194a3ceb2776f2dc Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 19:37:44 +0400 Subject: [PATCH 12/91] kinect camera CAD parameters --- modules/viz/src/types.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 861a783181..f0be75f65a 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -278,13 +278,6 @@ void cv::viz::Camera::computeProjectionMatrix(Matx44f &proj) const cv::viz::Camera cv::viz::Camera::KinectCamera(const Size &window_size) { - // Without distortion, RGB Camera - // Received from http://nicolas.burrus.name/index.php/Research/KinectCalibration - Matx33f K = Matx33f::zeros(); - K(0,0) = 5.2921508098293293e+02; - K(0,2) = 3.2894272028759258e+02; - K(1,1) = 5.2556393630057437e+02; - K(1,2) = 2.6748068171871557e+02; - K(2,2) = 1.0f; + Matx33f K(525.f, 0.f, 320.f, 0.f, 525.f, 240.f, 0.f, 0.f, 1.f) ; return Camera(K, window_size); } From 45aeecb0431f809fd5f4e1b27fd5f895cec6e588 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 20:33:53 +0400 Subject: [PATCH 13/91] renaming --- modules/viz/src/{cloud_widgets.cpp => clouds.cpp} | 0 modules/viz/src/precomp.hpp | 2 +- modules/viz/src/{shape_widgets.cpp => shapes.cpp} | 0 modules/viz/src/{viz3d_impl.cpp => vizimpl.cpp} | 0 modules/viz/src/{viz3d_impl.hpp => vizimpl.hpp} | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename modules/viz/src/{cloud_widgets.cpp => clouds.cpp} (100%) rename modules/viz/src/{shape_widgets.cpp => shapes.cpp} (100%) rename modules/viz/src/{viz3d_impl.cpp => vizimpl.cpp} (100%) rename modules/viz/src/{viz3d_impl.hpp => vizimpl.hpp} (100%) diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/clouds.cpp similarity index 100% rename from modules/viz/src/cloud_widgets.cpp rename to modules/viz/src/clouds.cpp diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 7f09ee0766..83e0b6f85f 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -154,7 +154,7 @@ namespace cv } #include "interactor_style.hpp" -#include "viz3d_impl.hpp" +#include "vizimpl.hpp" #endif diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shapes.cpp similarity index 100% rename from modules/viz/src/shape_widgets.cpp rename to modules/viz/src/shapes.cpp diff --git a/modules/viz/src/viz3d_impl.cpp b/modules/viz/src/vizimpl.cpp similarity index 100% rename from modules/viz/src/viz3d_impl.cpp rename to modules/viz/src/vizimpl.cpp diff --git a/modules/viz/src/viz3d_impl.hpp b/modules/viz/src/vizimpl.hpp similarity index 100% rename from modules/viz/src/viz3d_impl.hpp rename to modules/viz/src/vizimpl.hpp From cad2f98007ea2e69157d8f300528b068e60635ff Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 20:58:55 +0400 Subject: [PATCH 14/91] removed vizActor (since unnecessarily in new design concept with simplified widgets) --- modules/viz/src/clouds.cpp | 2 +- modules/viz/src/precomp.hpp | 3 --- modules/viz/src/shapes.cpp | 20 ++++++++++---------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 27a0285fc7..d43ae2d4fb 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -615,7 +615,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in mapper->SetColorModeToMapScalars(); mapper->SetScalarModeToUsePointData(); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); setColor(color); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 83e0b6f85f..24b7e3f97e 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -123,9 +123,6 @@ namespace cv { namespace viz { - typedef vtkLODActor vizActor; - //typedef vtkActor vizActor; - typedef std::map > WidgetActorMap; typedef std::map VizMap; diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index b7af4b7604..0cf41bdecd 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -68,7 +68,7 @@ cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(line->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -120,7 +120,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -141,7 +141,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -170,7 +170,7 @@ cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolu vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(sphere->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -243,7 +243,7 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(transformPD->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -279,7 +279,7 @@ cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, cons vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tf->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -310,7 +310,7 @@ cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_dir vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tuber->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -342,7 +342,7 @@ cv::viz::WCube::WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_fr mapper->SetInputConnection(cube->GetOutputPort()); } - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -394,7 +394,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -1080,7 +1080,7 @@ cv::viz::WCameraPosition::WCameraPosition(float scale) mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); From 270506829055623504e6c7313524beaedfb44ebb Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 21:00:00 +0400 Subject: [PATCH 15/91] refactored Keyboard and Mouse Events --- modules/viz/doc/viz3d.rst | 48 +++++-------- modules/viz/include/opencv2/viz/types.hpp | 84 +++++++++-------------- modules/viz/src/clouds.cpp | 2 +- modules/viz/src/interactor_style.cpp | 67 +++++++++--------- modules/viz/src/interactor_style.hpp | 9 +-- modules/viz/src/types.cpp | 59 ++++------------ modules/viz/src/vizimpl.cpp | 4 +- 7 files changed, 99 insertions(+), 174 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 2f8dfcd9d0..63c5ac34c5 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -506,40 +506,28 @@ This class represents a keyboard event. :: class CV_EXPORTS KeyboardEvent { public: - static const unsigned int Alt = 1; - static const unsigned int Ctrl = 2; - static const unsigned int Shift = 4; + enum { ALT = 1, CTRL = 2, SHIFT = 4 }; + enum Action { KEY_UP = 0, KEY_DOWN = 1 }; - //! Create a keyboard event - //! - Note that action is true if key is pressed, false if released - KeyboardEvent (bool action, const std::string& key_sym, unsigned char key, bool alt, bool ctrl, bool shift); + KeyboardEvent(Action action, const String& symbol, unsigned char code, int modifiers); - bool isAltPressed () const; - bool isCtrlPressed () const; - bool isShiftPressed () const; - - unsigned char getKeyCode () const; - - const String& getKeySym () const; - bool keyDown () const; - bool keyUp () const; - - protected: - /* hidden */ + Action action; + String symbol; + unsigned char code; + int modifiers; }; viz::KeyboardEvent::KeyboardEvent --------------------------------- Constructs a KeyboardEvent. -.. ocv:function:: KeyboardEvent (bool action, const std::string& key_sym, unsigned char key, bool alt, bool ctrl, bool shift) +.. ocv:function:: KeyboardEvent (Action action, const String& symbol, unsigned char code, Modifiers modifiers) - :param action: If true, key is pressed. If false, key is released. - :param key_sym: Name of the key. - :param key: Code of the key. - :param alt: If true, ``alt`` is pressed. - :param ctrl: If true, ``ctrl`` is pressed. - :param shift: If true, ``shift`` is pressed. + :param action: Signals if key is pressed or released. + :param symbol: Name of the key. + :param code: Code of the key. + :param modifiers: Signals if ``alt``, ``ctrl`` or ``shift`` are pressed or their combination. + viz::MouseEvent --------------- @@ -553,26 +541,24 @@ This class represents a mouse event. :: enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ; enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ; - MouseEvent (const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift); + MouseEvent(const Type& type, const MouseButton& button, const Point& pointer, int modifiers); Type type; MouseButton button; Point pointer; - unsigned int key_state; + int modifiers; }; viz::MouseEvent::MouseEvent --------------------------- Constructs a MouseEvent. -.. ocv:function:: MouseEvent (const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift) +.. ocv:function:: MouseEvent (const Type& type, const MouseButton& button, const Point& p, Modifiers modifiers) :param type: Type of the event. This can be **MouseMove**, **MouseButtonPress**, **MouseButtonRelease**, **MouseScrollDown**, **MouseScrollUp**, **MouseDblClick**. :param button: Mouse button. This can be **NoButton**, **LeftButton**, **MiddleButton**, **RightButton**, **VScroll**. :param p: Position of the event. - :param alt: If true, ``alt`` is pressed. - :param ctrl: If true, ``ctrl`` is pressed. - :param shift: If true, ``shift`` is pressed. + :param modifiers: Signals if ``alt``, ``ctrl`` or ``shift`` are pressed or their combination. viz::Camera ----------- diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 780f200ed9..9a88b46eae 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_TYPES_HPP__ @@ -121,56 +118,13 @@ namespace cv struct loadMeshImpl; }; - class CV_EXPORTS KeyboardEvent - { - public: - static const unsigned int Alt = 1; - static const unsigned int Ctrl = 2; - static const unsigned int Shift = 4; - - //! Create a keyboard event - //! - Note that action is true if key is pressed, false if released - KeyboardEvent(bool action, const String& key_sym, unsigned char key, bool alt, bool ctrl, bool shift); - - bool isAltPressed() const; - bool isCtrlPressed() const; - bool isShiftPressed() const; - - unsigned char getKeyCode() const; - - const String& getKeySym() const; - bool keyDown() const; - bool keyUp() const; - - protected: - - bool action_; - unsigned int modifiers_; - unsigned char key_code_; - String key_sym_; - }; - - class CV_EXPORTS MouseEvent - { - public: - enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ; - enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ; - - MouseEvent(const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift); - - Type type; - MouseButton button; - Point pointer; - unsigned int key_state; - }; - class CV_EXPORTS Camera { public: - Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size); - Camera(const Vec2f &fov, const Size &window_size); - Camera(const cv::Matx33f &K, const Size &window_size); - Camera(const cv::Matx44f &proj, const Size &window_size); + Camera(float fx, float fy, float cx, float cy, const Size &window_size); + explicit Camera(const Vec2f &fov, const Size &window_size); + explicit Camera(const cv::Matx33f &K, const Size &window_size); + explicit Camera(const cv::Matx44f &proj, const Size &window_size); inline const Vec2d & getClip() const { return clip_; } inline void setClip(const Vec2d &clip) { clip_ = clip; } @@ -189,7 +143,7 @@ namespace cv static Camera KinectCamera(const Size &window_size); private: - void init(float f_x, float f_y, float c_x, float c_y, const Size &window_size); + void init(float fx, float fy, float cx, float cy, const Size &window_size); Vec2d clip_; Vec2f fov_; @@ -197,6 +151,34 @@ namespace cv Vec2f principal_point_; Vec2f focal_; }; + + class CV_EXPORTS KeyboardEvent + { + public: + enum { NONE = 0, ALT = 1, CTRL = 2, SHIFT = 4 }; + enum Action { KEY_UP = 0, KEY_DOWN = 1 }; + + KeyboardEvent(Action action, const String& symbol, unsigned char code, int modifiers); + + Action action; + String symbol; + unsigned char code; + int modifiers; + }; + + class CV_EXPORTS MouseEvent + { + public: + enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ; + enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ; + + MouseEvent(const Type& type, const MouseButton& button, const Point& pointer, int modifiers); + + Type type; + MouseButton button; + Point pointer; + int modifiers; + }; } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index d43ae2d4fb..7da425c38f 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -185,7 +185,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) mapper->SetInputData(polydata); #endif - Vec3d minmax(scalars->GetRange()); + Vec2d minmax(scalars->GetRange()); mapper->SetScalarRange(minmax.val); mapper->SetScalarModeToUsePointData(); diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 78f2ac680f..74340ca8d7 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -51,7 +51,6 @@ ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::InteractorStyle::Initialize() { - modifier_ = cv::viz::InteractorStyle::KB_MOD_ALT; // Set windows size (width, height) to unknown (-1) win_size_ = Vec2i(-1, -1); win_pos_ = Vec2i(0, 0); @@ -121,13 +120,7 @@ void cv::viz::InteractorStyle::OnChar() else if (key.find("XF86ZoomOut") != String::npos) zoomOut(); - int keymod = false; - switch (modifier_) - { - case KB_MOD_ALT: keymod = Interactor->GetAltKey(); break; - case KB_MOD_CTRL: keymod = Interactor->GetControlKey(); break; - case KB_MOD_SHIFT: keymod = Interactor->GetShiftKey(); break; - } + int keymod = Interactor->GetAltKey(); switch (Interactor->GetKeyCode()) { @@ -184,6 +177,21 @@ bool cv::viz::InteractorStyle::getAltKey() { return Interactor->GetAltKey() != 0 bool cv::viz::InteractorStyle::getShiftKey() { return Interactor->GetShiftKey()!= 0; } bool cv::viz::InteractorStyle::getControlKey() { return Interactor->GetControlKey()!= 0; } +int cv::viz::InteractorStyle::getModifiers() +{ + int modifiers = KeyboardEvent::NONE; + + if (Interactor->GetAltKey()) + modifiers |= KeyboardEvent::ALT; + + if (Interactor->GetControlKey()) + modifiers |= KeyboardEvent::CTRL; + + if (Interactor->GetShiftKey()) + modifiers |= KeyboardEvent::SHIFT; + return modifiers; +} + ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::InteractorStyle::OnKeyDown() @@ -204,19 +212,7 @@ cv::viz::InteractorStyle::OnKeyDown() if (win_size_[0] == -1 || win_size_[1] == -1) win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); - - // Get the status of special keys (Cltr+Alt+Shift) - bool shift = getShiftKey(); - bool ctrl = getControlKey(); - bool alt = getAltKey(); - - bool keymod = false; - switch (modifier_) - { - case KB_MOD_ALT: keymod = alt; break; - case KB_MOD_CTRL: keymod = ctrl; break; - case KB_MOD_SHIFT: keymod = shift; break; - } + bool alt = getAltKey(); std::string key(Interactor->GetKeySym()); if (key.find("XF86ZoomIn") != std::string::npos) @@ -344,7 +340,7 @@ cv::viz::InteractorStyle::OnKeyDown() // Switch between maximize and original window size case 'f': case 'F': { - if (keymod) + if (alt) { Vec2i screen_size(Interactor->GetRenderWindow()->GetScreenSize()); Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); @@ -386,7 +382,7 @@ cv::viz::InteractorStyle::OnKeyDown() // 's'/'S' w/out ALT case 's': case 'S': { - if (keymod) + if (alt) { int stereo_render = Interactor->GetRenderWindow()->GetStereoRender(); if (!stereo_render) @@ -423,7 +419,7 @@ cv::viz::InteractorStyle::OnKeyDown() // Overwrite the camera reset case 'r': case 'R': { - if (!keymod) + if (!alt) { Superclass::OnKeyDown(); break; @@ -491,7 +487,8 @@ cv::viz::InteractorStyle::OnKeyDown() } } - KeyboardEvent event(true, Interactor->GetKeySym(), Interactor->GetKeyCode(), getAltKey(), getControlKey(), getShiftKey()); + + KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); // Check if there is a keyboard callback registered if (keyboardCallback_) keyboardCallback_(event, keyboard_callback_cookie_); @@ -503,7 +500,7 @@ cv::viz::InteractorStyle::OnKeyDown() ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::InteractorStyle::OnKeyUp() { - KeyboardEvent event(false, Interactor->GetKeySym(), Interactor->GetKeyCode(), getAltKey(), getControlKey(), getShiftKey()); + KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); // Check if there is a keyboard callback registered if (keyboardCallback_) keyboardCallback_(event, keyboard_callback_cookie_); @@ -515,7 +512,7 @@ void cv::viz::InteractorStyle::OnKeyUp() void cv::viz::InteractorStyle::OnMouseMove() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMouseMove(); @@ -526,7 +523,7 @@ void cv::viz::InteractorStyle::OnLeftButtonDown() { Vec2i p(Interactor->GetEventPosition()); MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::LeftButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(type, MouseEvent::LeftButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnLeftButtonDown(); @@ -536,7 +533,7 @@ void cv::viz::InteractorStyle::OnLeftButtonDown() void cv::viz::InteractorStyle::OnLeftButtonUp() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnLeftButtonUp(); @@ -548,7 +545,7 @@ void cv::viz::InteractorStyle::OnMiddleButtonDown() Vec2i p(Interactor->GetEventPosition()); MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::MiddleButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMiddleButtonDown(); @@ -558,7 +555,7 @@ void cv::viz::InteractorStyle::OnMiddleButtonDown() void cv::viz::InteractorStyle::OnMiddleButtonUp() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMiddleButtonUp(); @@ -570,7 +567,7 @@ void cv::viz::InteractorStyle::OnRightButtonDown() Vec2i p(Interactor->GetEventPosition()); MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::RightButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(type, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnRightButtonDown(); @@ -580,7 +577,7 @@ void cv::viz::InteractorStyle::OnRightButtonDown() void cv::viz::InteractorStyle::OnRightButtonUp() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnRightButtonUp(); @@ -590,7 +587,7 @@ void cv::viz::InteractorStyle::OnRightButtonUp() void cv::viz::InteractorStyle::OnMouseWheelForward() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers()); // If a mouse callback registered, call it! if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); @@ -622,7 +619,7 @@ void cv::viz::InteractorStyle::OnMouseWheelForward() void cv::viz::InteractorStyle::OnMouseWheelBackward() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers()); // If a mouse callback registered, call it! if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 3af13fcc43..3141bbeaa9 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -56,9 +56,6 @@ namespace cv class InteractorStyle : public vtkInteractorStyleTrackballCamera { public: - - enum KeyboardModifier { KB_MOD_ALT, KB_MOD_CTRL, KB_MOD_SHIFT }; - static InteractorStyle *New(); virtual ~InteractorStyle() {} @@ -74,9 +71,6 @@ namespace cv void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); - /** \brief Change the default keyboard modified from ALT to a different special key.*/ - inline void setKeyboardModifier(const KeyboardModifier &modifier) { modifier_ = modifier; } - private: /** \brief Set to true after initialization is complete. */ bool init_; @@ -121,8 +115,6 @@ namespace cv /** \brief True if we're using red-blue colors for anaglyphic stereo, false if magenta-green. */ bool stereo_anaglyph_mask_default_; - KeyboardModifier modifier_; - void (*keyboardCallback_)(const KeyboardEvent&, void*); void *keyboard_callback_cookie_; @@ -132,6 +124,7 @@ namespace cv bool getAltKey(); bool getControlKey(); bool getShiftKey(); + int getModifiers(); }; } } diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index f0be75f65a..e3537c475d 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -49,44 +49,13 @@ #include "precomp.hpp" //////////////////////////////////////////////////////////////////// -/// cv::viz::KeyboardEvent +/// Events -cv::viz::KeyboardEvent::KeyboardEvent(bool _action, const String& _key_sym, unsigned char key, bool alt, bool ctrl, bool shift) - : action_(_action), modifiers_(0), key_code_(key), key_sym_(_key_sym) -{ - if (alt) - modifiers_ = Alt; - - if (ctrl) - modifiers_ |= Ctrl; - - if (shift) - modifiers_ |= Shift; -} - -bool cv::viz::KeyboardEvent::isAltPressed() const { return (modifiers_ & Alt) != 0; } -bool cv::viz::KeyboardEvent::isCtrlPressed() const { return (modifiers_ & Ctrl) != 0; } -bool cv::viz::KeyboardEvent::isShiftPressed() const { return (modifiers_ & Shift) != 0; } -unsigned char cv::viz::KeyboardEvent::getKeyCode() const { return key_code_; } -const cv::String& cv::viz::KeyboardEvent::getKeySym() const { return key_sym_; } -bool cv::viz::KeyboardEvent::keyDown() const { return action_; } -bool cv::viz::KeyboardEvent::keyUp() const { return !action_; } - -//////////////////////////////////////////////////////////////////// -/// cv::viz::MouseEvent - -cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, const Point& _p, bool alt, bool ctrl, bool shift) - : type(_type), button(_button), pointer(_p), key_state(0) -{ - if (alt) - key_state = KeyboardEvent::Alt; +cv::viz::KeyboardEvent::KeyboardEvent(Action _action, const String& _symbol, unsigned char _code, int _modifiers) + : action(_action), symbol(_symbol), code(_code), modifiers(_modifiers) {} - if (ctrl) - key_state |= KeyboardEvent::Ctrl; - - if (shift) - key_state |= KeyboardEvent::Shift; -} +cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, const Point& _pointer, int _modifiers) + : type(_type), button(_button), pointer(_pointer), modifiers(_modifiers) {} //////////////////////////////////////////////////////////////////// /// cv::viz::Mesh3d @@ -167,9 +136,9 @@ cv::viz::Mesh3d cv::viz::Mesh3d::loadMesh(const String& file) //////////////////////////////////////////////////////////////////// /// Camera implementation -cv::viz::Camera::Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size) +cv::viz::Camera::Camera(float fx, float fy, float cx, float cy, const Size &window_size) { - init(f_x, f_y, c_x, c_y, window_size); + init(fx, fy, cx, cy, window_size); } cv::viz::Camera::Camera(const Vec2f &fov, const Size &window_size) @@ -220,19 +189,19 @@ cv::viz::Camera::Camera(const Matx44f &proj, const Size &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) +void cv::viz::Camera::init(float fx, float fy, float cx, float cy, const Size &window_size) { CV_Assert(window_size.width > 0 && window_size.height > 0); setClip(Vec2d(0.01, 1000.01));// Default clipping - fov_[0] = (atan2(c_x,f_x) + atan2(window_size.width-c_x,f_x)); - fov_[1] = (atan2(c_y,f_y) + atan2(window_size.height-c_y,f_y)); + fov_[0] = (atan2(cx,fx) + atan2(window_size.width-cx,fx)); + fov_[1] = (atan2(cy,fy) + atan2(window_size.height-cy,fy)); - principal_point_[0] = c_x; - principal_point_[1] = c_y; + principal_point_[0] = cx; + principal_point_[1] = cy; - focal_[0] = f_x; - focal_[1] = f_y; + focal_[0] = fx; + focal_[1] = fy; window_size_ = window_size; } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index af3f93b71c..7702d973d2 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -247,9 +247,7 @@ void cv::viz::Viz3d::VizImpl::setDesiredUpdateRate(double rate) ///////////////////////////////////////////////////////////////////////////////////////////// double cv::viz::Viz3d::VizImpl::getDesiredUpdateRate() { - if (interactor_) - return interactor_->GetDesiredUpdateRate(); - return 0.0; + return interactor_ ? interactor_->GetDesiredUpdateRate() : 0.0; } ///////////////////////////////////////////////////////////////////////////////////////////// From 159de9cc477123429941f0ad7582f2c17a241b70 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 12 Dec 2013 22:05:10 +0400 Subject: [PATCH 16/91] fixed potential crash --- modules/viz/src/clouds.cpp | 11 +++++------ modules/viz/src/widget.cpp | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 7da425c38f..ec83676eef 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -334,7 +334,7 @@ namespace cv { namespace viz { namespace return polydata; } - static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data, Vec3d& minmax) + static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data) { vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); if (!mapper) @@ -347,7 +347,7 @@ namespace cv { namespace viz { namespace mapper_new->SetInputData(poly_data); #endif - mapper_new->SetScalarRange(minmax.val); + mapper_new->SetScalarRange(0, 255); mapper_new->SetScalarModeToUsePointData(); bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); @@ -435,8 +435,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - Vec3d minmax(scalars->GetRange()); - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput(), minmax); + + CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); } void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) @@ -474,8 +474,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - Vec3d minmax(scalars->GetRange()); - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput(), minmax); + CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); } template<> cv::viz::WCloudCollection cv::viz::Widget::cast() diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 5c2df04dcd..c16d27ae3a 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -102,7 +102,7 @@ cv::viz::Widget cv::viz::Widget::fromPlyFile(const String &file_name) vtkSmartPointer scalars = data->GetPointData()->GetScalars(); if (scalars) { - cv::Vec3d minmax(scalars->GetRange()); + cv::Vec2d minmax(scalars->GetRange()); mapper->SetScalarRange(minmax.val); mapper->SetScalarModeToUsePointData(); From 7dbf6bc8df019240ff6f07bcb52e4d078c9a087c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 12 Dec 2013 23:21:55 +0400 Subject: [PATCH 17/91] rewrote cloud widget in vtk filters style Conflicts: modules/viz/src/clouds.cpp --- modules/viz/src/clouds.cpp | 153 ++-------------- modules/viz/src/precomp.hpp | 4 + .../viz/src/vtk/vtkCloudColorMatSource.cpp | 168 ++++++++++++++++++ modules/viz/src/vtk/vtkCloudColorMatSource.h | 88 +++++++++ modules/viz/src/vtk/vtkCloudMatSource.cpp | 105 +++++++++++ modules/viz/src/vtk/vtkCloudMatSource.h | 83 +++++++++ modules/viz/src/vtk/vtkColorMatSource.cpp | 132 ++++++++++++++ modules/viz/src/vtk/vtkColorMatSource.h | 82 +++++++++ 8 files changed, 675 insertions(+), 140 deletions(-) create mode 100644 modules/viz/src/vtk/vtkCloudColorMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkCloudColorMatSource.h create mode 100644 modules/viz/src/vtk/vtkCloudMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkCloudMatSource.h create mode 100644 modules/viz/src/vtk/vtkColorMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkColorMatSource.h diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index ec83676eef..3d8105c3f8 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -59,103 +59,10 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Point Cloud Widget implementation -namespace cv { namespace viz { namespace -{ - struct CloudUtils - { - static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) - { - vtkSmartPointer polydata = vtkSmartPointer::New(); - vtkSmartPointer vertices = vtkSmartPointer::New(); - - polydata->SetVerts(vertices); - - vtkSmartPointer points = polydata->GetPoints(); - vtkSmartPointer initcells; - nr_points = cloud.total(); - - if (!points) - { - points = vtkSmartPointer::New(); - if (cloud.depth() == CV_32F) - points->SetDataTypeToFloat(); - else if (cloud.depth() == CV_64F) - points->SetDataTypeToDouble(); - polydata->SetPoints(points); - } - points->SetNumberOfPoints(nr_points); - - if (cloud.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - else if (cloud.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - points->SetNumberOfPoints(nr_points); - - // Update cells - vtkSmartPointer cells = vertices->GetData(); - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); - - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); - - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) - { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - else - { - // If the number of tuples is still too small, we need to recreate the array - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); - } - } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - - // Set the cells and the vertices - vertices->SetCells(nr_points, cells); - return polydata; - } - }; -}}} - - cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) { Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); - CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); if (cloud.isContinuous() && colors.isContinuous()) { @@ -163,41 +70,18 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) colors = colors.reshape(colors.channels(), 1); } - vtkIdType nr_points; - vtkSmartPointer polydata = CloudUtils::create(cloud, nr_points); - - // Filter colors - Vec3b* colors_data = new Vec3b[nr_points]; - NanFilter::copyColor(colors, colors_data, cloud); - - vtkSmartPointer scalars = vtkSmartPointer::New(); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(nr_points); - scalars->SetArray(colors_data->val, 3 * nr_points, 0); - - // Assign the colors - polydata->GetPointData()->SetScalars(scalars); + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetCloud(cloud); + cloud_source->SetColors(colors, cloud); vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polydata); -#else - mapper->SetInputData(polydata); -#endif - - Vec2d minmax(scalars->GetRange()); - mapper->SetScalarRange(minmax.val); + mapper->SetInputConnection(cloud_source->GetOutputPort()); mapper->SetScalarModeToUsePointData(); - - bool interpolation = (polydata && polydata->GetNumberOfCells() != polydata->GetNumberOfVerts()); - - mapper->SetInterpolateScalarsBeforeMapping(interpolation); - mapper->ScalarVisibilityOn(); - mapper->ImmediateModeRenderingOff(); + mapper->SetScalarRange(0, 255); + mapper->ScalarVisibilityOn(); - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetNumberOfCloudPoints(int(std::max(1, polydata->GetNumberOfPoints() / 10))); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); actor->SetMapper(mapper); @@ -208,27 +92,16 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) { Mat cloud = _cloud.getMat(); - CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - vtkIdType nr_points; - vtkSmartPointer polydata = CloudUtils::create(cloud, nr_points); + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetCloud(cloud); vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polydata); -#else - mapper->SetInputData(polydata); -#endif - - bool interpolation = (polydata && polydata->GetNumberOfCells() != polydata->GetNumberOfVerts()); - - mapper->SetInterpolateScalarsBeforeMapping(interpolation); - mapper->ScalarVisibilityOff(); - + mapper->SetInputConnection(cloud_source->GetOutputPort()); mapper->ImmediateModeRenderingOff(); + mapper->ScalarVisibilityOff(); - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetNumberOfCloudPoints(int(std::max(1, polydata->GetNumberOfPoints() / 10))); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); actor->SetMapper(mapper); @@ -435,8 +308,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); + } void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 24b7e3f97e..7741dc7df5 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -114,6 +114,10 @@ #include #include +#include +#include +#include + #include #include #include diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.cpp b/modules/viz/src/vtk/vtkCloudColorMatSource.cpp new file mode 100644 index 0000000000..8979873eb3 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudColorMatSource.cpp @@ -0,0 +1,168 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkCloudColorMatSource); + + struct IsNotNan + { + template + bool operator()(const _Tp* data) const + { + return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); + } + }; +}} + +cv::viz::vtkCloudColorMatSource::vtkCloudColorMatSource() { SetNumberOfInputPorts(0); } +cv::viz::vtkCloudColorMatSource::~vtkCloudColorMatSource() {} + +void cv::viz::vtkCloudColorMatSource::SetCloud(const Mat& cloud) +{ + CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); + CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); + + int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) + : filterNanCopy(cloud, VTK_DOUBLE); + + vertices = vtkSmartPointer::New(); + vertices->Allocate(vertices->EstimateSize(1, total)); + vertices->InsertNextCell(total); + for(int i = 0; i < total; ++i) + vertices->InsertCellPoint(i); +} + +void cv::viz::vtkCloudColorMatSource::SetColors(const Mat &colors, const Mat &cloud_mask) +{ + CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); + CV_Assert(cloud_mask.depth() == CV_32F || cloud_mask.depth() == CV_64F); + CV_Assert(colors.size() == cloud_mask.size()); + + if (cloud_mask.depth() == CV_32F) + filterNanCopy(colors, cloud_mask); + else if (cloud_mask.depth() == CV_64F) + filterNanCopy(colors, cloud_mask); +} + +int cv::viz::vtkCloudColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetPoints(points); + output->SetVerts(vertices); + output->GetPointData()->SetScalars(scalars); + return 1; +} + +template +int cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& source, int dataType) +{ + CV_DbgAssert(DataType<_Tp>::depth == source.depth()); + points = vtkSmartPointer::New(); + points->SetDataType(dataType); + points->Allocate(source.total()); + points->SetNumberOfPoints(source.total()); + + int cn = source.channels(); + int total = 0; + for (int y = 0; y < source.rows; ++y) + { + const _Tp* srow = source.ptr<_Tp>(y); + const _Tp* send = srow + source.cols * cn; + + for (; srow != send; srow += cn) + if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + points->SetPoint(total++, srow); + } + points->SetNumberOfPoints(total); + points->Squeeze(); + return total; +} + +template +void cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& colors, const Mat& mask) +{ + Mat buffer(colors.size(), CV_8UC3); + Vec3b* pos = buffer.ptr(); + + int s_chs = colors.channels(); + int m_chs = mask.channels(); + + _NanPred pred; + + for (int y = 0; y < colors.rows; ++y) + { + const unsigned char* srow = colors.ptr(y); + const unsigned char* send = srow + colors.cols * colors.channels(); + const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); + + if (colors.channels() == 1) + { + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[0], srow[0], srow[0]); + } + else + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[2], srow[1], srow[0]); + + } + + int total = pos - buffer.ptr(); + Vec3b* array = new Vec3b[total]; + std::copy(buffer.ptr(), pos, array); + + scalars = vtkSmartPointer::New(); + scalars->SetName("colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(array->val, total * 3, 0); +} + + diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.h b/modules/viz/src/vtk/vtkCloudColorMatSource.h new file mode 100644 index 0000000000..0aa5b87a3e --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudColorMatSource.h @@ -0,0 +1,88 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkCloudColorMatSource_h +#define __vtkCloudColorMatSource_h + +#include +#include +#include +#include +#include + +namespace cv +{ + namespace viz + { + class vtkCloudColorMatSource : public vtkPolyDataAlgorithm + { + public: + static vtkCloudColorMatSource *New(); + vtkTypeMacro(vtkCloudColorMatSource,vtkPolyDataAlgorithm); + + virtual void SetCloud(const Mat& cloud); + virtual void SetColors(const Mat &colors, const Mat &cloud_mask); + + protected: + vtkCloudColorMatSource(); + ~vtkCloudColorMatSource(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkSmartPointer points; + vtkSmartPointer vertices; + vtkSmartPointer scalars; + private: + vtkCloudColorMatSource(const vtkCloudColorMatSource&); // Not implemented. + void operator=(const vtkCloudColorMatSource&); // Not implemented. + + template int filterNanCopy(const Mat& source, int dataType); + + template + void filterNanCopy(const Mat& colors, const Mat& mask); + }; + } +} + +#endif diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp new file mode 100644 index 0000000000..a27653a4f6 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -0,0 +1,105 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkCloudMatSource); +}} + +cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } +cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {} + +void cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) +{ + CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); + CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); + + int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) + : filterNanCopy(cloud, VTK_DOUBLE); + + vertices = vtkSmartPointer::New(); + vertices->Allocate(vertices->EstimateSize(1, total)); + vertices->InsertNextCell(total); + for(int i = 0; i < total; ++i) + vertices->InsertCellPoint(i); +} + +int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetPoints(points); + output->SetVerts(vertices); + return 1; +} + +template +int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) +{ + CV_DbgAssert(DataType<_Tp>::depth == source.depth()); + points = vtkSmartPointer::New(); + points->SetDataType(dataType); + points->Allocate(source.total()); + points->SetNumberOfPoints(source.total()); + + int cn = source.channels(); + int total = 0; + for (int y = 0; y < source.rows; ++y) + { + const _Tp* srow = source.ptr<_Tp>(y); + const _Tp* send = srow + source.cols * cn; + + for (; srow != send; srow += cn) + if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + points->SetPoint(total++, srow); + } + points->SetNumberOfPoints(total); + points->Squeeze(); + return total; +} + + diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h new file mode 100644 index 0000000000..6a8dbebd16 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -0,0 +1,83 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkCloudMatSource_h +#define __vtkCloudMatSource_h + +#include +#include +#include +#include +#include + +namespace cv +{ + namespace viz + { + class vtkCloudMatSource : public vtkPolyDataAlgorithm + { + public: + static vtkCloudMatSource *New(); + vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); + + virtual void SetCloud(const Mat& cloud); + + protected: + vtkCloudMatSource(); + ~vtkCloudMatSource(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkSmartPointer points; + vtkSmartPointer vertices; + private: + vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. + void operator=(const vtkCloudMatSource&); // Not implemented. + + template int filterNanCopy(const Mat& source, int dataType); + }; + } +} + +#endif diff --git a/modules/viz/src/vtk/vtkColorMatSource.cpp b/modules/viz/src/vtk/vtkColorMatSource.cpp new file mode 100644 index 0000000000..aa09a2d49d --- /dev/null +++ b/modules/viz/src/vtk/vtkColorMatSource.cpp @@ -0,0 +1,132 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkColorMatSource); + + struct IsNotNan + { + template + bool operator()(const _Tp* data) const + { + return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); + } + }; + + struct AllOk + { + template + bool operator()(const _Tp*) const { return true; } + }; +}} + +cv::viz::vtkColorMatSource::vtkColorMatSource() { SetNumberOfInputPorts(0); } +cv::viz::vtkColorMatSource::~vtkColorMatSource() {} + +void cv::viz::vtkColorMatSource::SetColors(const Mat &colors, const Mat& mask) +{ + CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); + CV_Assert(mask.empty() || mask.depth() == CV_32F || mask.depth() == CV_64F); + + if (!mask.empty() && mask.depth() == CV_32F) + filterNanCopy(colors, mask); + else if (!mask.empty() && mask.depth() == CV_64F) + filterNanCopy(colors, mask); + else /* mask.empty() */ + filterNanCopy(colors, mask); +} + +int cv::viz::vtkColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->GetPointData()->SetScalars(scalars); + + return 1; +} + +template +void cv::viz::vtkColorMatSource::filterNanCopy(const Mat& colors, const Mat& cloud_mask) +{ + Mat buffer(colors.size(), CV_8UC3); + Vec3b* pos = buffer.ptr(); + + int s_chs = colors.channels(); + int m_chs = cloud_mask.channels(); + + _NanPred pred; + + for (int y = 0; y < colors.rows; ++y) + { + const unsigned char* srow = colors.ptr(y); + const unsigned char* send = srow + colors.cols * colors.channels(); + const _Msk* mrow = cloud_mask.empty() ? 0 : cloud_mask.ptr<_Msk>(y); + + if (colors.channels() == 1) + { + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[0], srow[0], srow[0]); + } + else + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[2], srow[1], srow[0]); + + } + + int total = pos - buffer.ptr(); + Vec3b* array = new Vec3b[total]; + std::copy(buffer.ptr(), pos, array); + + scalars = vtkSmartPointer::New(); + scalars->SetName("colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(array->val, total * 3, 0); +} diff --git a/modules/viz/src/vtk/vtkColorMatSource.h b/modules/viz/src/vtk/vtkColorMatSource.h new file mode 100644 index 0000000000..d1650faad8 --- /dev/null +++ b/modules/viz/src/vtk/vtkColorMatSource.h @@ -0,0 +1,82 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkColorMatSource_h +#define __vtkColorMatSource_h + +#include +#include +#include + +namespace cv +{ + namespace viz + { + class vtkColorMatSource : public vtkPolyDataAlgorithm + { + public: + static vtkColorMatSource *New(); + vtkTypeMacro(vtkColorMatSource,vtkPolyDataAlgorithm); + + virtual void SetColors(const Mat &colors, const Mat &cloud_mask = Mat()); + + + protected: + vtkColorMatSource(); + ~vtkColorMatSource(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkSmartPointer scalars; + private: + vtkColorMatSource(const vtkColorMatSource&); // Not implemented. + void operator=(const vtkColorMatSource&); // Not implemented. + + template + void filterNanCopy(const Mat& colors, const Mat& mask); + }; + } +} + +#endif From 80ab6e889fc30ef42dd5420e3f372db192284927 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 12 Dec 2013 23:46:41 +0400 Subject: [PATCH 18/91] refactoring --- modules/viz/include/opencv2/viz/types.hpp | 9 +- modules/viz/include/opencv2/viz/viz3d.hpp | 4 +- modules/viz/include/opencv2/viz/widgets.hpp | 12 +-- modules/viz/src/clouds.cpp | 12 +-- modules/viz/src/interactor_style.cpp | 58 +++++----- modules/viz/src/interactor_style.hpp | 6 -- modules/viz/src/shapes.cpp | 48 +++------ modules/viz/src/types.cpp | 110 +++++++++---------- modules/viz/src/viz3d.cpp | 7 +- modules/viz/src/vizimpl.cpp | 16 +-- modules/viz/src/vizimpl.hpp | 7 +- modules/viz/src/widget.cpp | 114 +++++--------------- 12 files changed, 142 insertions(+), 261 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 9a88b46eae..ab5aafc38f 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -112,10 +112,7 @@ namespace cv Mat polygons; //! Loads mesh from a given ply file - static cv::viz::Mesh3d loadMesh(const String& file); - - private: - struct loadMeshImpl; + static Mesh3d loadMesh(const String& file); }; class CV_EXPORTS Camera @@ -123,8 +120,8 @@ namespace cv public: Camera(float fx, float fy, float cx, float cy, const Size &window_size); explicit Camera(const Vec2f &fov, const Size &window_size); - explicit Camera(const cv::Matx33f &K, const Size &window_size); - explicit Camera(const cv::Matx44f &proj, const Size &window_size); + explicit Camera(const Matx33f &K, const Size &window_size); + explicit Camera(const Matx44f &proj, const Size &window_size); inline const Vec2d & getClip() const { return clip_; } inline void setClip(const Vec2d &clip) { clip_ = clip; } diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index d3f5a109cc..1b31b2447f 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -94,8 +94,8 @@ namespace cv void setWindowSize(const Size &window_size); String getWindowName() const; void saveScreenshot(const String &file); - void setWindowPosition(int x, int y); - void setFullScreen(bool mode); + void setWindowPosition(const Point& window_position); + void setFullScreen(bool mode = true); void setBackgroundColor(const Color& color = Color::black()); void spin(); diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 0b0c5fc28c..1f48686f4a 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -245,13 +245,13 @@ namespace cv //! Creates camera coordinate frame (axes) at the origin WCameraPosition(float scale = 1.f); //! Creates frustum based on the intrinsic marix K at the origin - explicit WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - explicit WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - explicit WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - explicit WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// @@ -270,9 +270,9 @@ namespace cv { public: //! Displays trajectory of the given path by frustums - explicit WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - explicit WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 3d8105c3f8..8549acafdb 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -61,6 +58,8 @@ namespace cv cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) { + CV_Assert(!_cloud.empty() && !_colors.empty()); + Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); @@ -74,7 +73,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) cloud_source->SetCloud(cloud); cloud_source->SetColors(colors, cloud); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(cloud_source->GetOutputPort()); mapper->SetScalarModeToUsePointData(); mapper->ImmediateModeRenderingOff(); @@ -96,7 +95,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetCloud(cloud); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(cloud_source->GetOutputPort()); mapper->ImmediateModeRenderingOff(); mapper->ScalarVisibilityOff(); @@ -213,7 +212,7 @@ namespace cv { namespace viz { namespace if (!mapper) { // This is the first cloud - vtkSmartPointer mapper_new = vtkSmartPointer::New(); + vtkSmartPointer mapper_new = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 mapper_new->SetInputConnection(poly_data->GetProducerPort()); #else @@ -309,7 +308,6 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, CV_Assert("Incompatible widget type." && actor); CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); - } void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 74340ca8d7..1a7c8a4c11 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -48,6 +48,13 @@ #include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(InteractorStyle) +}} + + ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::InteractorStyle::Initialize() { @@ -173,10 +180,6 @@ void cv::viz::InteractorStyle::registerKeyboardCallback(void (*callback)(const K } ////////////////////////////////////////////////////////////////////////////////////////////// -bool cv::viz::InteractorStyle::getAltKey() { return Interactor->GetAltKey() != 0; } -bool cv::viz::InteractorStyle::getShiftKey() { return Interactor->GetShiftKey()!= 0; } -bool cv::viz::InteractorStyle::getControlKey() { return Interactor->GetControlKey()!= 0; } - int cv::viz::InteractorStyle::getModifiers() { int modifiers = KeyboardEvent::NONE; @@ -212,7 +215,7 @@ cv::viz::InteractorStyle::OnKeyDown() if (win_size_[0] == -1 || win_size_[1] == -1) win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); - bool alt = getAltKey(); + bool alt = Interactor->GetAltKey() != 0; std::string key(Interactor->GetKeySym()); if (key.find("XF86ZoomIn") != std::string::npos) @@ -245,7 +248,7 @@ cv::viz::InteractorStyle::OnKeyDown() " ALT + s, S : turn stereo mode on/off\n" " ALT + f, F : switch between maximized window mode and original size\n" "\n" - << std::endl; + << std::endl; break; } @@ -287,8 +290,8 @@ cv::viz::InteractorStyle::OnKeyDown() double angle = cam->GetViewAngle () / 180.0 * CV_PI; String data = cv::format("clip(%f,%f) focal(%f,%f,%f) pos(%f,%f,%f) view(%f,%f,%f) angle(%f) winsz(%d,%d) winpos(%d,%d)", - clip[0], clip[1], focal[0], focal[1], focal[2], pos[0], pos[1], pos[2], view[0], view[1], view[2], - angle, win_size[0], win_size[1], win_pos[0], win_pos[1]); + clip[0], clip[1], focal[0], focal[1], focal[2], pos[0], pos[1], pos[2], view[0], view[1], view[2], + angle, win_size[0], win_size[1], win_pos[0], win_pos[1]); std::cout << data.c_str() << std::endl; @@ -416,7 +419,7 @@ cv::viz::InteractorStyle::OnKeyDown() break; } - // Overwrite the camera reset + // Overwrite the camera reset case 'r': case 'R': { if (!alt) @@ -425,8 +428,6 @@ cv::viz::InteractorStyle::OnKeyDown() break; } - vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); - static WidgetActorMap::iterator it = widget_actor_map_->begin(); // it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault. bool found_transformation = false; @@ -444,6 +445,8 @@ cv::viz::InteractorStyle::OnKeyDown() } } + vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); + // if a valid transformation was found, use it otherwise fall back to default view point. if (found_transformation) { @@ -487,11 +490,10 @@ cv::viz::InteractorStyle::OnKeyDown() } } - KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); // Check if there is a keyboard callback registered if (keyboardCallback_) - keyboardCallback_(event, keyboard_callback_cookie_); + keyboardCallback_(event, keyboard_callback_cookie_); renderer_->Render(); Interactor->Render(); @@ -503,7 +505,7 @@ void cv::viz::InteractorStyle::OnKeyUp() KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); // Check if there is a keyboard callback registered if (keyboardCallback_) - keyboardCallback_(event, keyboard_callback_cookie_); + keyboardCallback_(event, keyboard_callback_cookie_); Superclass::OnKeyUp(); } @@ -514,7 +516,7 @@ void cv::viz::InteractorStyle::OnMouseMove() Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMouseMove(); } @@ -525,7 +527,7 @@ void cv::viz::InteractorStyle::OnLeftButtonDown() MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::LeftButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnLeftButtonDown(); } @@ -535,7 +537,7 @@ void cv::viz::InteractorStyle::OnLeftButtonUp() Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnLeftButtonUp(); } @@ -547,7 +549,7 @@ void cv::viz::InteractorStyle::OnMiddleButtonDown() MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMiddleButtonDown(); } @@ -557,7 +559,7 @@ void cv::viz::InteractorStyle::OnMiddleButtonUp() Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMiddleButtonUp(); } @@ -569,7 +571,7 @@ void cv::viz::InteractorStyle::OnRightButtonDown() MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnRightButtonDown(); } @@ -579,7 +581,7 @@ void cv::viz::InteractorStyle::OnRightButtonUp() Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnRightButtonUp(); } @@ -590,9 +592,9 @@ void cv::viz::InteractorStyle::OnMouseWheelForward() MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers()); // If a mouse callback registered, call it! if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetRepeatCount() && mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetAltKey()) { @@ -622,10 +624,10 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers()); // If a mouse callback registered, call it! if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetRepeatCount() && mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetAltKey()) { @@ -656,9 +658,3 @@ void cv::viz::InteractorStyle::OnTimer() renderer_->Render(); Interactor->Render(); } - -namespace cv { namespace viz -{ - //Standard VTK macro for *New() - vtkStandardNewMacro(InteractorStyle) -}} diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 3141bbeaa9..51f98635bc 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_INTERACTOR_STYLE_H__ @@ -121,9 +118,6 @@ namespace cv void (*mouseCallback_)(const MouseEvent&, void*); void *mouse_callback_cookie_; - bool getAltKey(); - bool getControlKey(); - bool getShiftKey(); int getModifiers(); }; } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 0cf41bdecd..0450eb816e 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -63,7 +60,6 @@ cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1(pt1.x, pt1.y, pt1.z); line->SetPoint2(pt2.x, pt2.y, pt2.z); - line->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(line->GetOutputPort()); @@ -165,7 +161,6 @@ cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolu sphere->SetPhiResolution(sphere_resolution); sphere->SetThetaResolution(sphere_resolution); sphere->LatLongTessellationOff(); - sphere->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(sphere->GetOutputPort()); @@ -194,44 +189,27 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, arrowSource->SetTipRadius(thickness * 3.0); arrowSource->SetTipLength(thickness * 10.0); - float startPoint[3], endPoint[3]; - startPoint[0] = pt1.x; - startPoint[1] = pt1.y; - startPoint[2] = pt1.z; - endPoint[0] = pt2.x; - endPoint[1] = pt2.y; - endPoint[2] = pt2.z; - float normalizedX[3], normalizedY[3], normalizedZ[3]; - - // The X axis is a vector from start to end - vtkMath::Subtract(endPoint, startPoint, normalizedX); - float length = vtkMath::Norm(normalizedX); - vtkMath::Normalize(normalizedX); - - // The Z axis is an arbitrary vecotr cross X - float arbitrary[3]; - arbitrary[0] = vtkMath::Random(-10,10); - arbitrary[1] = vtkMath::Random(-10,10); - arbitrary[2] = vtkMath::Random(-10,10); - vtkMath::Cross(normalizedX, arbitrary, normalizedZ); - vtkMath::Normalize(normalizedZ); - - // The Y axis is Z cross X - vtkMath::Cross(normalizedZ, normalizedX, normalizedY); - vtkSmartPointer matrix = vtkSmartPointer::New(); + Vec3f startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); + Vec3f arbitrary(theRNG().uniform(-10.f, 10.f), theRNG().uniform(-10.f, 10.f), theRNG().uniform(-10.f, 10.f)); + double length = cv::norm(endPoint - startPoint); + + Vec3f xvec = normalized(endPoint - startPoint); + Vec3f zvec = normalized(xvec.cross(arbitrary)); + Vec3f yvec = zvec.cross(xvec); // Create the direction cosine matrix + vtkSmartPointer matrix = vtkSmartPointer::New(); matrix->Identity(); - for (unsigned int i = 0; i < 3; i++) + for (int i = 0; i < 3; ++i) { - matrix->SetElement(i, 0, normalizedX[i]); - matrix->SetElement(i, 1, normalizedY[i]); - matrix->SetElement(i, 2, normalizedZ[i]); + matrix->SetElement(i, 0, xvec[i]); + matrix->SetElement(i, 1, yvec[i]); + matrix->SetElement(i, 2, zvec[i]); } // Apply the transforms vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Translate(startPoint); + transform->Translate(startPoint.val); transform->Concatenate(matrix); transform->Scale(length, length, length); diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index e3537c475d..2c7f8e74be 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -60,77 +57,80 @@ cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, c //////////////////////////////////////////////////////////////////// /// cv::viz::Mesh3d -struct cv::viz::Mesh3d::loadMeshImpl +namespace cv { namespace viz { namespace { - static cv::viz::Mesh3d loadMesh(const String &file) + struct MeshUtils { - Mesh3d mesh; - - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName(file.c_str()); - reader->Update(); + static Mesh3d loadMesh(const String &file) + { + Mesh3d mesh; - vtkSmartPointer poly_data = reader->GetOutput(); - CV_Assert("File does not exist or file format is not supported." && poly_data); + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(file.c_str()); + reader->Update(); - vtkSmartPointer mesh_points = poly_data->GetPoints(); - vtkIdType nr_points = mesh_points->GetNumberOfPoints(); + vtkSmartPointer poly_data = reader->GetOutput(); + CV_Assert("File does not exist or file format is not supported." && poly_data); - mesh.cloud.create(1, nr_points, CV_32FC3); + vtkSmartPointer mesh_points = poly_data->GetPoints(); + vtkIdType nr_points = mesh_points->GetNumberOfPoints(); - Vec3f *mesh_cloud = mesh.cloud.ptr(); - for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) - { - Vec3d point; - mesh_points->GetPoint(i, point.val); - mesh_cloud[i] = point; - } + mesh.cloud.create(1, nr_points, CV_32FC3); - // Then the color information, if any - vtkUnsignedCharArray* poly_colors = 0; - if (poly_data->GetPointData()) - poly_colors = vtkUnsignedCharArray::SafeDownCast(poly_data->GetPointData()->GetScalars()); + Vec3f *mesh_cloud = mesh.cloud.ptr(); + for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) + { + Vec3d point; + mesh_points->GetPoint(i, point.val); + mesh_cloud[i] = point; + } - if (poly_colors && (poly_colors->GetNumberOfComponents() == 3)) - { - mesh.colors.create(1, nr_points, CV_8UC3); - Vec3b *mesh_colors = mesh.colors.ptr(); + // Then the color information, if any + vtkUnsignedCharArray* poly_colors = 0; + if (poly_data->GetPointData()) + poly_colors = vtkUnsignedCharArray::SafeDownCast(poly_data->GetPointData()->GetScalars()); - for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) + if (poly_colors && (poly_colors->GetNumberOfComponents() == 3)) { - Vec3b point_color; - poly_colors->GetTupleValue(i, point_color.val); + mesh.colors.create(1, nr_points, CV_8UC3); + Vec3b *mesh_colors = mesh.colors.ptr(); + + for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) + { + Vec3b point_color; + poly_colors->GetTupleValue(i, point_color.val); - std::swap(point_color[0], point_color[2]); // RGB -> BGR - mesh_colors[i] = point_color; + std::swap(point_color[0], point_color[2]); // RGB -> BGR + mesh_colors[i] = point_color; + } } - } - else - mesh.colors.release(); + else + mesh.colors.release(); - // Now handle the polygons - vtkIdType* cell_points; - vtkIdType nr_cell_points; - vtkCellArray * mesh_polygons = poly_data->GetPolys(); - mesh_polygons->InitTraversal(); + // Now handle the polygons + vtkIdType* cell_points; + vtkIdType nr_cell_points; + vtkCellArray * mesh_polygons = poly_data->GetPolys(); + mesh_polygons->InitTraversal(); - mesh.polygons.create(1, mesh_polygons->GetSize(), CV_32SC1); + mesh.polygons.create(1, mesh_polygons->GetSize(), CV_32SC1); - int* polygons = mesh.polygons.ptr(); - while (mesh_polygons->GetNextCell(nr_cell_points, cell_points)) - { - *polygons++ = nr_cell_points; - for (int i = 0; i < nr_cell_points; ++i) - *polygons++ = static_cast(cell_points[i]); - } + int* polygons = mesh.polygons.ptr(); + while (mesh_polygons->GetNextCell(nr_cell_points, cell_points)) + { + *polygons++ = nr_cell_points; + for (int i = 0; i < nr_cell_points; ++i) + *polygons++ = static_cast(cell_points[i]); + } - return mesh; - } -}; + return mesh; + } + }; +}}} cv::viz::Mesh3d cv::viz::Mesh3d::loadMesh(const String& file) { - return loadMeshImpl::loadMesh(file); + return MeshUtils::loadMesh(file); } //////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 08cb880dec..0f21e08cc7 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -131,10 +128,10 @@ void cv::viz::Viz3d::convertToWindowCoordinates(const Point3d &pt, Point3d &wind void cv::viz::Viz3d::converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction) { impl_->converTo3DRay(window_coord, origin, direction); } cv::Size cv::viz::Viz3d::getWindowSize() const { return impl_->getWindowSize(); } -void cv::viz::Viz3d::setWindowSize(const Size &window_size) { impl_->setWindowSize(window_size.width, window_size.height); } +void cv::viz::Viz3d::setWindowSize(const Size &window_size) { impl_->setWindowSize(window_size); } cv::String cv::viz::Viz3d::getWindowName() const { return impl_->getWindowName(); } void cv::viz::Viz3d::saveScreenshot(const String &file) { impl_->saveScreenshot(file); } -void cv::viz::Viz3d::setWindowPosition(int x, int y) { impl_->setWindowPosition(x,y); } +void cv::viz::Viz3d::setWindowPosition(const Point& window_position) { impl_->setWindowPosition(window_position); } void cv::viz::Viz3d::setFullScreen(bool mode) { impl_->setFullScreen(mode); } void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 7702d973d2..c727a99d21 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -62,14 +59,11 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); - - // Create a RendererWindow window_ = vtkSmartPointer::New(); // Set the window size as 1/2 of the screen size cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); - window_->AddRenderer(renderer_); // Create the interactor style @@ -100,11 +94,6 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) interactor_->Initialize(); timer_id_ = interactor_->CreateRepeatingTimer(5000L); - // Set a simple PointPicker - //vtkSmartPointer pp = vtkSmartPointer::New(); - //pp->SetTolerance(pp->GetTolerance() * 2); - //interactor_->SetPicker(pp); - exit_main_loop_timer_callback_ = vtkSmartPointer::New(); exit_main_loop_timer_callback_->viz_ = this; exit_main_loop_timer_callback_->right_timer_id = -1; @@ -116,7 +105,6 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) resetStoppedFlag(); - ////////////////////////////// String window_name = VizStorage::generateWindowName(name); window_->SetWindowName(window_name.c_str()); @@ -521,6 +509,6 @@ cv::String cv::viz::Viz3d::VizImpl::getWindowName() const } ////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setWindowPosition(int x, int y) { window_->SetPosition(x, y); } -void cv::viz::Viz3d::VizImpl::setWindowSize(int xw, int yw) { window_->SetSize(xw, yw); } +void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } +void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); } diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index b38ad29666..d958f46726 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_VIZ3D_IMPL_HPP__ @@ -105,9 +102,9 @@ public: void converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction); void saveScreenshot(const String &file); - void setWindowPosition(int x, int y); + void setWindowPosition(const Point& position); Size getWindowSize() const; - void setWindowSize(int xw, int yw); + void setWindowSize(const Size& window_size); void setFullScreen(bool mode); String getWindowName() const; void setBackgroundColor(const Color& color); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index c16d27ae3a..a70fb925a3 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -55,7 +52,6 @@ class cv::viz::Widget::Impl { public: vtkSmartPointer prop; - Impl() : prop(0) {} }; @@ -63,13 +59,17 @@ cv::viz::Widget::Widget() : impl_( new Impl() ) { } cv::viz::Widget::Widget(const Widget& other) : impl_( new Impl() ) { - if (other.impl_ && other.impl_->prop) impl_->prop = other.impl_->prop; + if (other.impl_ && other.impl_->prop) + impl_->prop = other.impl_->prop; } cv::viz::Widget& cv::viz::Widget::operator=(const Widget& other) { - if (!impl_) impl_ = new Impl(); - if (other.impl_) impl_->prop = other.impl_->prop; + if (!impl_) + impl_ = new Impl(); + + if (other.impl_) + impl_->prop = other.impl_->prop; return *this; } @@ -84,45 +84,22 @@ cv::viz::Widget::~Widget() cv::viz::Widget cv::viz::Widget::fromPlyFile(const String &file_name) { + CV_Assert(vtkPLYReader::CanReadFile(file_name.c_str())); + vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(file_name.c_str()); - vtkSmartPointer data = reader->GetOutput(); - CV_Assert("File does not exist or file format is not supported." && data); - - vtkSmartPointer actor = vtkSmartPointer::New(); - vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(data); -#else - mapper->SetInputData(data); -#endif - - vtkSmartPointer scalars = data->GetPointData()->GetScalars(); - if (scalars) - { - cv::Vec2d minmax(scalars->GetRange()); - mapper->SetScalarRange(minmax.val); - mapper->SetScalarModeToUsePointData(); - - // interpolation OFF, if data is a vtkPolyData that contains only vertices, ON for anything else. - vtkPolyData* polyData = vtkPolyData::SafeDownCast(data); - bool interpolation = (polyData && polyData->GetNumberOfCells() != polyData->GetNumberOfVerts()); - - mapper->SetInterpolateScalarsBeforeMapping(interpolation); - mapper->ScalarVisibilityOn(); - } + mapper->SetInputConnection( reader->GetOutputPort() ); mapper->ImmediateModeRenderingOff(); - actor->SetNumberOfCloudPoints(int(std::max(1, data->GetNumberOfPoints() / 10))); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); - actor->SetMapper(mapper); Widget widget; - widget.impl_->prop = actor; + WidgetAccessor::setProp(widget, actor); return widget; } @@ -133,37 +110,15 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) switch (property) { - case POINT_SIZE: - { - actor->GetProperty()->SetPointSize(float(value)); - actor->Modified(); - break; - } - case OPACITY: - { - actor->GetProperty()->SetOpacity(value); - actor->Modified(); - break; - } - case IMMEDIATE_RENDERING: - { - actor->GetMapper()->SetImmediateModeRendering(int(value)); - actor->Modified(); - break; - } - case LINE_WIDTH: - { - actor->GetProperty()->SetLineWidth(float(value)); - actor->Modified(); - break; - } + case POINT_SIZE: actor->GetProperty()->SetPointSize(float(value)); break; + case OPACITY: actor->GetProperty()->SetOpacity(value); break; + case LINE_WIDTH: actor->GetProperty()->SetLineWidth(float(value)); break; + case IMMEDIATE_RENDERING: actor->GetMapper()->SetImmediateModeRendering(int(value)); break; case FONT_SIZE: { vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor); CV_Assert("Widget does not have text content." && text_actor); - vtkSmartPointer tprop = text_actor->GetTextProperty(); - tprop->SetFontSize(int(value)); - text_actor->Modified(); + text_actor->GetTextProperty()->SetFontSize(int(value)); break; } case REPRESENTATION: @@ -174,7 +129,6 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) case REPRESENTATION_WIREFRAME: actor->GetProperty()->SetRepresentationToWireframe(); break; case REPRESENTATION_SURFACE: actor->GetProperty()->SetRepresentationToSurface(); break; } - actor->Modified(); break; } case SHADING: @@ -215,14 +169,12 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) break; } } - actor->Modified(); break; } - - default: CV_Assert("setPointCloudRenderingProperties: Unknown property"); } + actor->Modified(); } double cv::viz::Widget::getRenderingProperty(int property) const @@ -233,32 +185,16 @@ double cv::viz::Widget::getRenderingProperty(int property) const double value = 0.0; switch (property) { - case POINT_SIZE: - { - value = actor->GetProperty()->GetPointSize(); - break; - } - case OPACITY: - { - value = actor->GetProperty()->GetOpacity(); - break; - } - case IMMEDIATE_RENDERING: - { - value = actor->GetMapper()->GetImmediateModeRendering(); - break; - } - case LINE_WIDTH: - { - value = actor->GetProperty()->GetLineWidth(); - break; - } + case POINT_SIZE: value = actor->GetProperty()->GetPointSize(); break; + case OPACITY: value = actor->GetProperty()->GetOpacity(); break; + case LINE_WIDTH: value = actor->GetProperty()->GetLineWidth(); break; + case IMMEDIATE_RENDERING: value = actor->GetMapper()->GetImmediateModeRendering(); break; + case FONT_SIZE: { vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor); CV_Assert("Widget does not have text content." && text_actor); - vtkSmartPointer tprop = text_actor->GetTextProperty(); - value = tprop->GetFontSize(); + value = text_actor->GetTextProperty()->GetFontSize();; break; } case REPRESENTATION: @@ -322,7 +258,7 @@ void cv::viz::Widget3D::updatePose(const Affine3f &pose) if (!matrix) { setPose(pose); - return ; + return; } Affine3f updated_pose = pose * Affine3f(convertToMatx(matrix)); From 84d6fe397d90887c4a823d9e7e6666821aadf969 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 13 Dec 2013 19:20:20 +0400 Subject: [PATCH 19/91] reading/writing clouds functionality --- modules/viz/include/opencv2/viz.hpp | 6 + modules/viz/src/clouds.cpp | 5 +- modules/viz/src/precomp.hpp | 20 +- modules/viz/src/vizcore.cpp | 112 ++++++++ .../viz/src/vtk/vtkCloudColorMatSource.cpp | 168 ------------ modules/viz/src/vtk/vtkCloudMatSource.cpp | 68 +++++ modules/viz/src/vtk/vtkCloudMatSource.h | 5 + modules/viz/src/vtk/vtkColorMatSource.cpp | 132 ---------- modules/viz/src/vtk/vtkOBJWriter.cpp | 241 ++++++++++++++++++ .../{vtkColorMatSource.h => vtkOBJWriter.h} | 35 ++- modules/viz/src/vtk/vtkXYZWriter.cpp | 93 +++++++ ...tkCloudColorMatSource.h => vtkXYZWriter.h} | 42 ++- modules/viz/test/test_tutorial3.cpp | 24 +- 13 files changed, 578 insertions(+), 373 deletions(-) delete mode 100644 modules/viz/src/vtk/vtkCloudColorMatSource.cpp delete mode 100644 modules/viz/src/vtk/vtkColorMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkOBJWriter.cpp rename modules/viz/src/vtk/{vtkColorMatSource.h => vtkOBJWriter.h} (71%) create mode 100644 modules/viz/src/vtk/vtkXYZWriter.cpp rename modules/viz/src/vtk/{vtkCloudColorMatSource.h => vtkXYZWriter.h} (65%) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 65ad10aacc..49b36a9b2f 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -92,6 +92,12 @@ namespace cv { return isNan(p.x) || isNan(p.y) || isNan(p.z); } + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Read/write clouds. Supported formats: ply, stl, xyz, obj + + CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray()); + CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = cv::noArray()); + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 8549acafdb..555da22d0f 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -69,9 +69,8 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) colors = colors.reshape(colors.channels(), 1); } - vtkSmartPointer cloud_source = vtkSmartPointer::New(); - cloud_source->SetCloud(cloud); - cloud_source->SetColors(colors, cloud); + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetColorCloud(cloud, colors); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(cloud_source->GetOutputPort()); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 7741dc7df5..6b2c1478e1 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -113,16 +114,31 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif #include -#include -#include +#include +#include #include #include #include #include + namespace cv { namespace viz diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index dd998e7d92..5a1a7a8fe2 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -161,6 +161,118 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Read/write clouds. Supported formats: ply, stl, xyz, obj + +void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors) +{ + CV_Assert(file.size() > 4 && "Extention is required"); + String extention = file.substr(file.size()-4); + + Mat cloud = _cloud.getMat(); + Mat colors = _colors.getMat(); + + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetColorCloud(cloud, colors); + + vtkSmartPointer writer; + if (extention == ".xyz") + { + writer = vtkSmartPointer::New(); + vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".ply") + { + writer = vtkSmartPointer::New(); + vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".obj") + { + writer = vtkSmartPointer::New(); + vtkOBJWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".stl") + { + writer = vtkSmartPointer::New(); + vtkSTLWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else + CV_Assert(!"Unsupported format"); + + writer->SetInputConnection(source->GetOutputPort()); + writer->Write(); +} + +cv::Mat cv::viz::readCloud(const String& file, OutputArray colors) +{ + CV_Assert(file.size() > 4 && "Extention is required"); + String extention = file.substr(file.size()-4); + + vtkSmartPointer reader; + if (extention == ".xyz") + { + reader = vtkSmartPointer::New(); + vtkSimplePointsReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".ply") + { + reader = vtkSmartPointer::New(); + CV_Assert(vtkPLYReader::CanReadFile(file.c_str())); + vtkPLYReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".obj") + { + reader = vtkSmartPointer::New(); + vtkOBJReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".stl") + { + reader = vtkSmartPointer::New(); + vtkSTLReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else + CV_Assert(!"Unsupported format"); + + reader->Update(); + vtkSmartPointer poly_data = reader->GetOutput(); + vtkSmartPointer points = poly_data->GetPoints(); + + int vtktype = points->GetDataType(); + CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); + + Mat cloud(1, points->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); + Vec3d *ddata = cloud.ptr(); + Vec3f *fdata = cloud.ptr(); + + if (cloud.depth() == CV_32F) + for(size_t i = 0; i < cloud.total(); ++i) + *fdata++ = Vec3d(points->GetPoint(i)); + + if (cloud.depth() == CV_64F) + for(size_t i = 0; i < cloud.total(); ++i) + *ddata++ = Vec3d(points->GetPoint(i)); + + vtkSmartPointer scalars = poly_data->GetPointData() ? poly_data->GetPointData()->GetScalars() : 0; + + if (colors.needed() && scalars) + { + int channels = scalars->GetNumberOfComponents(); + int vtktype = scalars->GetDataType(); + + CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented"); + CV_Assert(cloud.total() == (size_t)scalars->GetNumberOfTuples()); + Mat buffer(cloud.size(), CV_64FC(channels)); + Vec3d *cptr = buffer.ptr(); + for(size_t i = 0; i < colors.total(); ++i) + *cptr++ = Vec3d(scalars->GetTuple(i)); + + buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); + } + else + colors.release(); + + return cloud; +} /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.cpp b/modules/viz/src/vtk/vtkCloudColorMatSource.cpp deleted file mode 100644 index 8979873eb3..0000000000 --- a/modules/viz/src/vtk/vtkCloudColorMatSource.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -// Authors: -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -//M*/ - -#include "precomp.hpp" - -namespace cv { namespace viz -{ - vtkStandardNewMacro(vtkCloudColorMatSource); - - struct IsNotNan - { - template - bool operator()(const _Tp* data) const - { - return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); - } - }; -}} - -cv::viz::vtkCloudColorMatSource::vtkCloudColorMatSource() { SetNumberOfInputPorts(0); } -cv::viz::vtkCloudColorMatSource::~vtkCloudColorMatSource() {} - -void cv::viz::vtkCloudColorMatSource::SetCloud(const Mat& cloud) -{ - CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); - CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); - - int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) - : filterNanCopy(cloud, VTK_DOUBLE); - - vertices = vtkSmartPointer::New(); - vertices->Allocate(vertices->EstimateSize(1, total)); - vertices->InsertNextCell(total); - for(int i = 0; i < total; ++i) - vertices->InsertCellPoint(i); -} - -void cv::viz::vtkCloudColorMatSource::SetColors(const Mat &colors, const Mat &cloud_mask) -{ - CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); - CV_Assert(cloud_mask.depth() == CV_32F || cloud_mask.depth() == CV_64F); - CV_Assert(colors.size() == cloud_mask.size()); - - if (cloud_mask.depth() == CV_32F) - filterNanCopy(colors, cloud_mask); - else if (cloud_mask.depth() == CV_64F) - filterNanCopy(colors, cloud_mask); -} - -int cv::viz::vtkCloudColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) -{ - vtkInformation *outInfo = outputVector->GetInformationObject(0); - vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); - - output->SetPoints(points); - output->SetVerts(vertices); - output->GetPointData()->SetScalars(scalars); - return 1; -} - -template -int cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& source, int dataType) -{ - CV_DbgAssert(DataType<_Tp>::depth == source.depth()); - points = vtkSmartPointer::New(); - points->SetDataType(dataType); - points->Allocate(source.total()); - points->SetNumberOfPoints(source.total()); - - int cn = source.channels(); - int total = 0; - for (int y = 0; y < source.rows; ++y) - { - const _Tp* srow = source.ptr<_Tp>(y); - const _Tp* send = srow + source.cols * cn; - - for (; srow != send; srow += cn) - if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) - points->SetPoint(total++, srow); - } - points->SetNumberOfPoints(total); - points->Squeeze(); - return total; -} - -template -void cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& colors, const Mat& mask) -{ - Mat buffer(colors.size(), CV_8UC3); - Vec3b* pos = buffer.ptr(); - - int s_chs = colors.channels(); - int m_chs = mask.channels(); - - _NanPred pred; - - for (int y = 0; y < colors.rows; ++y) - { - const unsigned char* srow = colors.ptr(y); - const unsigned char* send = srow + colors.cols * colors.channels(); - const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); - - if (colors.channels() == 1) - { - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[0], srow[0], srow[0]); - } - else - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[2], srow[1], srow[0]); - - } - - int total = pos - buffer.ptr(); - Vec3b* array = new Vec3b[total]; - std::copy(buffer.ptr(), pos, array); - - scalars = vtkSmartPointer::New(); - scalars->SetName("colors"); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(total); - scalars->SetArray(array->val, total * 3, 0); -} - - diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index a27653a4f6..f533361bca 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -47,6 +47,14 @@ namespace cv { namespace viz { vtkStandardNewMacro(vtkCloudMatSource); + + struct IsNotNan + { + template bool operator()(const _Tp* data) const + { + return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); + } + }; }} cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } @@ -67,6 +75,22 @@ void cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) vertices->InsertCellPoint(i); } +void cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) +{ + vtkCloudMatSource::SetCloud(cloud); + + if (colors.empty()) + return; + + CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); + CV_Assert(colors.size() == cloud.size()); + + if (cloud.depth() == CV_32F) + filterNanColorsCopy(colors, cloud); + else if (cloud.depth() == CV_64F) + filterNanColorsCopy(colors, cloud); +} + int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { vtkInformation *outInfo = outputVector->GetInformationObject(0); @@ -74,6 +98,8 @@ int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), output->SetPoints(points); output->SetVerts(vertices); + if (scalars) + output->GetPointData()->SetScalars(scalars); return 1; } @@ -103,3 +129,45 @@ int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) } +template +void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& colors, const Mat& mask) +{ + Mat buffer(colors.size(), CV_8UC3); + Vec3b* pos = buffer.ptr(); + + int s_chs = colors.channels(); + int m_chs = mask.channels(); + + _NanPred pred; + + for (int y = 0; y < colors.rows; ++y) + { + const unsigned char* srow = colors.ptr(y); + const unsigned char* send = srow + colors.cols * colors.channels(); + const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); + + if (colors.channels() == 1) + { + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[0], srow[0], srow[0]); + } + else + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[2], srow[1], srow[0]); + + } + + int total = pos - buffer.ptr(); + Vec3b* array = new Vec3b[total]; + std::copy(buffer.ptr(), pos, array); + + scalars = vtkSmartPointer::New(); + scalars->SetName("colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(array->val, total * 3, 0); +} + + diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 6a8dbebd16..876ab994f6 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -62,6 +62,7 @@ namespace cv vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); virtual void SetCloud(const Mat& cloud); + virtual void SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); protected: vtkCloudMatSource(); @@ -71,11 +72,15 @@ namespace cv vtkSmartPointer points; vtkSmartPointer vertices; + vtkSmartPointer scalars; private: vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. void operator=(const vtkCloudMatSource&); // Not implemented. template int filterNanCopy(const Mat& source, int dataType); + + template + void filterNanColorsCopy(const Mat& colors, const Mat& mask); }; } } diff --git a/modules/viz/src/vtk/vtkColorMatSource.cpp b/modules/viz/src/vtk/vtkColorMatSource.cpp deleted file mode 100644 index aa09a2d49d..0000000000 --- a/modules/viz/src/vtk/vtkColorMatSource.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -// Authors: -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -//M*/ - -#include "precomp.hpp" - -namespace cv { namespace viz -{ - vtkStandardNewMacro(vtkColorMatSource); - - struct IsNotNan - { - template - bool operator()(const _Tp* data) const - { - return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); - } - }; - - struct AllOk - { - template - bool operator()(const _Tp*) const { return true; } - }; -}} - -cv::viz::vtkColorMatSource::vtkColorMatSource() { SetNumberOfInputPorts(0); } -cv::viz::vtkColorMatSource::~vtkColorMatSource() {} - -void cv::viz::vtkColorMatSource::SetColors(const Mat &colors, const Mat& mask) -{ - CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); - CV_Assert(mask.empty() || mask.depth() == CV_32F || mask.depth() == CV_64F); - - if (!mask.empty() && mask.depth() == CV_32F) - filterNanCopy(colors, mask); - else if (!mask.empty() && mask.depth() == CV_64F) - filterNanCopy(colors, mask); - else /* mask.empty() */ - filterNanCopy(colors, mask); -} - -int cv::viz::vtkColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) -{ - vtkInformation *outInfo = outputVector->GetInformationObject(0); - vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); - - output->GetPointData()->SetScalars(scalars); - - return 1; -} - -template -void cv::viz::vtkColorMatSource::filterNanCopy(const Mat& colors, const Mat& cloud_mask) -{ - Mat buffer(colors.size(), CV_8UC3); - Vec3b* pos = buffer.ptr(); - - int s_chs = colors.channels(); - int m_chs = cloud_mask.channels(); - - _NanPred pred; - - for (int y = 0; y < colors.rows; ++y) - { - const unsigned char* srow = colors.ptr(y); - const unsigned char* send = srow + colors.cols * colors.channels(); - const _Msk* mrow = cloud_mask.empty() ? 0 : cloud_mask.ptr<_Msk>(y); - - if (colors.channels() == 1) - { - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[0], srow[0], srow[0]); - } - else - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[2], srow[1], srow[0]); - - } - - int total = pos - buffer.ptr(); - Vec3b* array = new Vec3b[total]; - std::copy(buffer.ptr(), pos, array); - - scalars = vtkSmartPointer::New(); - scalars->SetName("colors"); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(total); - scalars->SetArray(array->val, total * 3, 0); -} diff --git a/modules/viz/src/vtk/vtkOBJWriter.cpp b/modules/viz/src/vtk/vtkOBJWriter.cpp new file mode 100644 index 0000000000..452ad19a7a --- /dev/null +++ b/modules/viz/src/vtk/vtkOBJWriter.cpp @@ -0,0 +1,241 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkOBJWriter); +}} + +cv::viz::vtkOBJWriter::vtkOBJWriter() +{ + std::ofstream fout; // only used to extract the default precision + this->DecimalPrecision = fout.precision(); + this->FileName = NULL; + this->FileType = VTK_ASCII; +} + +cv::viz::vtkOBJWriter::~vtkOBJWriter(){} + +void cv::viz::vtkOBJWriter::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + std::ostream *outfilep = this->OpenVTKFile(); + if (!outfilep) + return; + + std::ostream& outfile = *outfilep; + + //write header + outfile << "# wavefront obj file written by the visualization toolkit" << std::endl << std::endl; + outfile << "mtllib NONE" << std::endl << std::endl; + + // write out the points + for (int i = 0; i < input->GetNumberOfPoints(); i++) + { + Vec3d p; + input->GetPoint(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "v " << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + + const int idStart = 1; + + // write out the point data + vtkSmartPointer normals = input->GetPointData()->GetNormals(); + if(normals) + { + for (int i = 0; i < normals->GetNumberOfTuples(); i++) + { + Vec3d p; + normals->GetTuple(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "vn " << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + } + + vtkSmartPointer tcoords = input->GetPointData()->GetTCoords(); + if (tcoords) + { + for (int i = 0; i < tcoords->GetNumberOfTuples(); i++) + { + Vec2d p; + tcoords->GetTuple(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "vt " << p[0] << " " << p[1] << std::endl; + } + } + + // write out a group name and material + outfile << std::endl << "g grp" << idStart << std::endl; + outfile << "usemtl mtlNONE" << std::endl; + + // write out verts if any + if (input->GetNumberOfVerts() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetVerts(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "p "; + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << " "; + outfile << std::endl; + } + } + + // write out lines if any + if (input->GetNumberOfLines() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetLines(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "l "; + if (tcoords) + { + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << "/" << index[i] + idStart << " "; + } + else + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << " "; + + outfile << std::endl; + } + } + + // write out polys if any + if (input->GetNumberOfPolys() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetPolys(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "f "; + for (int i = 0; i < npts; i++) + { + if (normals) + { + if (tcoords) + outfile << index[i] + idStart << "/" << index[i] + idStart << "/" << index[i] + idStart << " "; + else + outfile << index[i] + idStart << "//" << index[i] + idStart << " "; + } + else + { + if (tcoords) + outfile << index[i] + idStart << " " << index[i] + idStart << " "; + else + outfile << index[i] + idStart << " "; + } + } + outfile << std::endl; + } + } + + // write out tstrips if any + if (input->GetNumberOfStrips() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetStrips(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + for (int i = 2, i1, i2; i < npts; ++i) + { + if (i % 2) + { + i1 = i - 1; + i2 = i - 2; + } + else + { + i1 = i - 1; + i2 = i - 2; + } + + if(normals) + { + if (tcoords) + { + outfile << "f " << index[i1] + idStart << "/" << index[i1] + idStart << "/" << index[i1] + idStart << " " + << index[i2]+ idStart << "/" << index[i2] + idStart << "/" << index[i2] + idStart << " " + << index[i] + idStart << "/" << index[i] + idStart << "/" << index[i] + idStart << std::endl; + } + else + { + outfile << "f " << index[i1] + idStart << "//" << index[i1] + idStart << " " << index[i2] + idStart + << "//" << index[i2] + idStart << " " << index[i] + idStart << "//" << index[i] + idStart << std::endl; + } + } + else + { + if (tcoords) + { + outfile << "f " << index[i1] + idStart << "/" << index[i1] + idStart << " " << index[i2] + idStart + << "/" << index[i2] + idStart << " " << index[i] + idStart << "/" << index[i] + idStart << std::endl; + } + else + outfile << "f " << index[i1] + idStart << " " << index[i2] + idStart << " " << index[i] + idStart << std::endl; + } + } /* for (int i = 2; i < npts; ++i) */ + } + } /* if (input->GetNumberOfStrips() > 0) */ + + this->CloseVTKFile(outfilep); + + // Delete the file if an error occurred + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + unlink(this->FileName); + } +} + +void cv::viz::vtkOBJWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + Superclass::PrintSelf(os, indent); + os << indent << "DecimalPrecision: " << DecimalPrecision << "\n"; +} diff --git a/modules/viz/src/vtk/vtkColorMatSource.h b/modules/viz/src/vtk/vtkOBJWriter.h similarity index 71% rename from modules/viz/src/vtk/vtkColorMatSource.h rename to modules/viz/src/vtk/vtkOBJWriter.h index d1650faad8..9bf5403e43 100644 --- a/modules/viz/src/vtk/vtkColorMatSource.h +++ b/modules/viz/src/vtk/vtkOBJWriter.h @@ -42,39 +42,36 @@ // //M*/ -#ifndef __vtkColorMatSource_h -#define __vtkColorMatSource_h +#ifndef __vtkOBJWriter_h +#define __vtkOBJWriter_h -#include -#include -#include +#include namespace cv { namespace viz { - class vtkColorMatSource : public vtkPolyDataAlgorithm + class vtkOBJWriter : public vtkPolyDataWriter { public: - static vtkColorMatSource *New(); - vtkTypeMacro(vtkColorMatSource,vtkPolyDataAlgorithm); - - virtual void SetColors(const Mat &colors, const Mat &cloud_mask = Mat()); + static vtkOBJWriter *New(); + vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + vtkGetMacro(DecimalPrecision, int); + vtkSetMacro(DecimalPrecision, int); protected: - vtkColorMatSource(); - ~vtkColorMatSource(); + vtkOBJWriter(); + ~vtkOBJWriter(); - int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void WriteData(); - vtkSmartPointer scalars; - private: - vtkColorMatSource(const vtkColorMatSource&); // Not implemented. - void operator=(const vtkColorMatSource&); // Not implemented. + int DecimalPrecision; - template - void filterNanCopy(const Mat& colors, const Mat& mask); + private: + vtkOBJWriter(const vtkOBJWriter&); // Not implemented. + void operator=(const vtkOBJWriter&); // Not implemented. }; } } diff --git a/modules/viz/src/vtk/vtkXYZWriter.cpp b/modules/viz/src/vtk/vtkXYZWriter.cpp new file mode 100644 index 0000000000..4518a0103a --- /dev/null +++ b/modules/viz/src/vtk/vtkXYZWriter.cpp @@ -0,0 +1,93 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkXYZWriter); +}} + +cv::viz::vtkXYZWriter::vtkXYZWriter() +{ + std::ofstream fout; // only used to extract the default precision + this->DecimalPrecision = fout.precision(); +} + +void cv::viz::vtkXYZWriter::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + // OpenVTKFile() will report any errors that happen + ostream *outfilep = this->OpenVTKFile(); + if (!outfilep) + return; + + ostream &outfile = *outfilep; + + for(vtkIdType i = 0; i < input->GetNumberOfPoints(); ++i) + { + Vec3d p; + input->GetPoint(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + + // Close the file + this->CloseVTKFile(outfilep); + + // Delete the file if an error occurred + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + unlink(this->FileName); + } +} + +void cv::viz::vtkXYZWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "DecimalPrecision: " << this->DecimalPrecision << "\n"; +} diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.h b/modules/viz/src/vtk/vtkXYZWriter.h similarity index 65% rename from modules/viz/src/vtk/vtkCloudColorMatSource.h rename to modules/viz/src/vtk/vtkXYZWriter.h index 0aa5b87a3e..bc49d10ef1 100644 --- a/modules/viz/src/vtk/vtkCloudColorMatSource.h +++ b/modules/viz/src/vtk/vtkXYZWriter.h @@ -42,47 +42,37 @@ // //M*/ -#ifndef __vtkCloudColorMatSource_h -#define __vtkCloudColorMatSource_h +#ifndef __vtkXYZWriter_h +#define __vtkXYZWriter_h -#include -#include -#include -#include -#include +#include "vtkPolyDataWriter.h" namespace cv { namespace viz { - class vtkCloudColorMatSource : public vtkPolyDataAlgorithm + class vtkXYZWriter : public vtkPolyDataWriter { public: - static vtkCloudColorMatSource *New(); - vtkTypeMacro(vtkCloudColorMatSource,vtkPolyDataAlgorithm); + static vtkXYZWriter *New(); + vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); - virtual void SetCloud(const Mat& cloud); - virtual void SetColors(const Mat &colors, const Mat &cloud_mask); + vtkGetMacro(DecimalPrecision, int); + vtkSetMacro(DecimalPrecision, int); protected: - vtkCloudColorMatSource(); - ~vtkCloudColorMatSource(); + vtkXYZWriter(); + ~vtkXYZWriter(){} - int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void WriteData(); - vtkSmartPointer points; - vtkSmartPointer vertices; - vtkSmartPointer scalars; - private: - vtkCloudColorMatSource(const vtkCloudColorMatSource&); // Not implemented. - void operator=(const vtkCloudColorMatSource&); // Not implemented. - - template int filterNanCopy(const Mat& source, int dataType); + int DecimalPrecision; - template - void filterNanCopy(const Mat& colors, const Mat& mask); + private: + vtkXYZWriter(const vtkXYZWriter&); // Not implemented. + void operator=(const vtkXYZWriter&); // Not implemented. }; } } - #endif diff --git a/modules/viz/test/test_tutorial3.cpp b/modules/viz/test/test_tutorial3.cpp index 6c63763dfd..12eca311c1 100644 --- a/modules/viz/test/test_tutorial3.cpp +++ b/modules/viz/test/test_tutorial3.cpp @@ -3,28 +3,6 @@ using namespace cv; using namespace std; -/** - * @function cvcloud_load - * @brief load bunny.ply - */ -Mat cvcloud_load() -{ - Mat cloud(1, 20000, CV_32FC3); - ifstream ifs("d:/cloud_dragon.ply"); - - string str; - for(size_t i = 0; i < 12; ++i) - getline(ifs, str); - - Point3f* data = cloud.ptr(); - //float dummy1, dummy2; - for(size_t i = 0; i < 20000; ++i) - ifs >> data[i].x >> data[i].y >> data[i].z;// >> dummy1 >> dummy2; - - //cloud *= 5.0f; - return cloud; -} - /** * @function main */ @@ -47,7 +25,7 @@ void tutorial3(bool camera_pov) Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos); /// Create a cloud widget. - Mat bunny_cloud = cvcloud_load(); + Mat bunny_cloud = viz::readCloud("d:/cloud_dragon.ply"); viz::WCloud cloud_widget(bunny_cloud, viz::Color::green()); /// Pose of the widget in camera frame From b2cd526e6ab15b897a9935750a584c69715d3020 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 13 Dec 2013 19:35:48 +0400 Subject: [PATCH 20/91] removed extra code --- modules/viz/src/interactor_style.cpp | 28 +++++++++------------------- modules/viz/src/interactor_style.hpp | 6 ------ 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 1a7c8a4c11..5c2ee1cd15 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -63,11 +63,6 @@ void cv::viz::InteractorStyle::Initialize() win_pos_ = Vec2i(0, 0); max_win_size_ = Vec2i(-1, -1); - // Create the image filter and PNG writer objects - wif_ = vtkSmartPointer::New(); - snapshot_writer_ = vtkSmartPointer::New(); - snapshot_writer_->SetInputConnection(wif_->GetOutputPort()); - init_ = true; stereo_anaglyph_mask_default_ = true; @@ -84,11 +79,14 @@ void cv::viz::InteractorStyle::Initialize() void cv::viz::InteractorStyle::saveScreenshot(const String &file) { FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - wif_->SetInput(Interactor->GetRenderWindow()); - wif_->Modified(); // Update the WindowToImageFilter - snapshot_writer_->Modified(); - snapshot_writer_->SetFileName(file.c_str()); - snapshot_writer_->Write(); + + vtkSmartPointer wif = vtkSmartPointer::New(); + wif->SetInput(Interactor->GetRenderWindow()); + + vtkSmartPointer snapshot_writer = vtkSmartPointer::New(); + snapshot_writer->SetInputConnection(wif->GetOutputPort()); + snapshot_writer->SetFileName(file.c_str()); + snapshot_writer->Write(); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -196,21 +194,13 @@ int cv::viz::InteractorStyle::getModifiers() } ////////////////////////////////////////////////////////////////////////////////////////////// -void -cv::viz::InteractorStyle::OnKeyDown() +void cv::viz::InteractorStyle::OnKeyDown() { CV_Assert("Interactor style not initialized. Please call Initialize() before continuing" && init_); CV_Assert("No renderer given! Use SetRendererCollection() before continuing." && renderer_); FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - if (wif_->GetInput() == NULL) - { - wif_->SetInput(Interactor->GetRenderWindow()); - wif_->Modified(); - snapshot_writer_->Modified(); - } - // Save the initial windows width/height if (win_size_[0] == -1 || win_size_[1] == -1) win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 51f98635bc..7ae4fa75c2 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -79,12 +79,6 @@ namespace cv Vec2i win_pos_; Vec2i max_win_size_; - /** \brief A PNG writer for screenshot captures. */ - vtkSmartPointer snapshot_writer_; - - /** \brief Internal window to image filter. Needed by \a snapshot_writer_. */ - vtkSmartPointer wif_; - /** \brief Interactor style internal method. Gets called whenever a key is pressed. */ virtual void OnChar(); From b131faa8f958e3eff8749a776c437984d3bd7108 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 13 Dec 2013 20:05:19 +0400 Subject: [PATCH 21/91] export scene to vrml and obj formats --- modules/viz/src/interactor_style.cpp | 39 ++++++++++++++++++++++++---- modules/viz/src/interactor_style.hpp | 1 + modules/viz/src/precomp.hpp | 2 ++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 5c2ee1cd15..4126d8c359 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -87,6 +87,29 @@ void cv::viz::InteractorStyle::saveScreenshot(const String &file) snapshot_writer->SetInputConnection(wif->GetOutputPort()); snapshot_writer->SetFileName(file.c_str()); snapshot_writer->Write(); + + cout << "Screenshot successfully captured (" << file.c_str() << ")" << endl; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::InteractorStyle::exportScene(const String &file) +{ + vtkSmartPointer exporter; + if (file.size() > 5 && file.substr(file.size() - 5) == ".vrml") + { + exporter = vtkSmartPointer::New(); + vtkVRMLExporter::SafeDownCast(exporter)->SetFileName(file.c_str()); + } + else + { + exporter = vtkSmartPointer::New(); + vtkOBJExporter::SafeDownCast(exporter)->SetFilePrefix(file.c_str()); + } + + exporter->SetInput(Interactor->GetRenderWindow()); + exporter->Write(); + + cout << "Scene successfully exported (" << file.c_str() << ")" << endl; } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -224,6 +247,8 @@ void cv::viz::InteractorStyle::OnKeyDown() " s, S : switch to a surface-based representation (where available)\n" "\n" " j, J : take a .PNG snapshot of the current window view\n" + " k, K : export scene to Wavefront .obj format\n" + " ALT + k, K : export scene to VRML format\n" " c, C : display current camera/window parameters\n" " f, F : fly to point mode, hold the key and move mouse where to fly\n" "\n" @@ -255,15 +280,19 @@ void cv::viz::InteractorStyle::OnKeyDown() } break; } - // Save a PNG snapshot with the current screen + + // Save a PNG snapshot case 'j': case 'J': + saveScreenshot(cv::format("screenshot-%d.png", (unsigned int)time(0))); break; + + // Export scene as in obj or vrml format + case 'k': case 'K': { - unsigned int t = static_cast(time(0)); - String png_file = cv::format("screenshot-%d.png", t); - saveScreenshot(png_file); - cout << "Screenshot (" << png_file.c_str() << ") successfully captured." << endl; + String format = alt ? "scene-%d.vrml" : "scene-%d"; + exportScene(cv::format(format.c_str(), (unsigned int)time(0))); break; } + // display current camera settings/parameters case 'c': case 'C': { diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 7ae4fa75c2..92876d8945 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -67,6 +67,7 @@ namespace cv void registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); + void exportScene(const String &file); private: /** \brief Set to true after initialization is complete. */ diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 6b2c1478e1..83b779dd8e 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -122,6 +122,8 @@ #include #include #include +#include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ From bf30c33e6e3fd8c3735ba9e713419790acc05209 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 27 Dec 2013 18:10:51 +0400 Subject: [PATCH 22/91] getting data from opencv_extra --- modules/viz/test/test_main.cpp | 2 +- modules/viz/test/test_viz3d.cpp | 33 +++++++++++++++++---------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/modules/viz/test/test_main.cpp b/modules/viz/test/test_main.cpp index 6b24993447..e737d2db31 100644 --- a/modules/viz/test/test_main.cpp +++ b/modules/viz/test/test_main.cpp @@ -1,3 +1,3 @@ #include "test_precomp.hpp" -CV_TEST_MAIN("cv") +CV_TEST_MAIN("viz") diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 29cf81ebb2..9fb291ce1d 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -43,28 +43,29 @@ using namespace cv; -static cv::Mat cvcloud_load() +TEST(Viz_viz3d, develop) { - cv::Mat cloud(1, 20000, CV_32FC3); - std::ifstream ifs("d:/cloud_dragon.ply"); + std::cout << std::string(cvtest::TS::ptr()->get_data_path()) + "dragon.ply" << std::endl; - std::string str; - for(size_t i = 0; i < 11; ++i) - std::getline(ifs, str); + cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); - cv::Point3f* data = cloud.ptr(); - for(size_t i = 0; i < cloud.total(); ++i) - ifs >> data[i].x >> data[i].y >> data[i].z; + cv::viz::Viz3d viz("abc"); + viz.showWidget("coo", cv::viz::WCoordinateSystem()); - return cloud; -} + cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); -TEST(Viz_viz3d, develop) -{ - cv::Mat cloud = cvcloud_load(); - cv::viz::Viz3d viz("abc"); - cv::viz::WCloud c(cloud, cv::Mat(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0))); + //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); + + //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); + + cv::RNG rng; + rng.fill(colors, cv::RNG::UNIFORM, 0, 255); + cv::viz::WCloud c(cloud, colors); //cv::viz::WCloud c(cloud, cv::viz::Color::bluberry()); viz.showWidget("c", c); + + //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); + //viz.showWidget("s", cv::viz::WSphere(Point3f(0,0,0), 1)); + //viz.showWidget("d", cv::viz::WCircle(Point3f(0,0,0), 1)); viz.spin(); } From 7e952e2f101c17aeceedad76534981211069a579 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 31 Dec 2013 18:52:10 +0400 Subject: [PATCH 23/91] removed incorrect and unnecessarily methods from Affine3f --- modules/core/include/opencv2/core/affine.hpp | 21 -------------------- 1 file changed, 21 deletions(-) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index fefcef8f12..0aaf57e0a2 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -73,9 +73,6 @@ namespace cv //Combines all contructors above. Supports 4x4, 3x3, 1x3, 3x1 sizes of data matrix explicit Affine3(const cv::Mat& data, const Vec3& t = Vec3::all(0)); - //Euler angles - Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t = Vec3::all(0)); - static Affine3 Identity(); //Rotation matrix @@ -87,9 +84,6 @@ namespace cv //Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; void rotation(const Mat& data); - //Euler angles - void rotation(float_type alpha, float_type beta, float_type gamma); - void linear(const Mat3& L); void translation(const Vec3& t); @@ -186,15 +180,6 @@ cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) matrix.val[15] = 1; } -template inline -cv::Affine3::Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t) -{ - rotation(alpha, beta, gamma); - translation(t); - matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; - matrix.val[15] = 1; -} - template inline cv::Affine3 cv::Affine3::Identity() { @@ -261,12 +246,6 @@ void cv::Affine3::rotation(const cv::Mat& data) CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); } -template inline -void cv::Affine3::rotation(float_type alpha, float_type beta, float_type gamma) -{ - rotation(Vec3(alpha, beta, gamma)); -} - template inline void cv::Affine3::linear(const Mat3& L) { From 1c4cfd8eaf2dee020303733f23532ed7cabf30d3 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 31 Dec 2013 21:03:10 +0400 Subject: [PATCH 24/91] normals support for CloudMatSource --- modules/viz/src/vtk/vtkCloudMatSource.cpp | 143 +++++++++++++++------- modules/viz/src/vtk/vtkCloudMatSource.h | 13 +- modules/viz/test/test_viz3d.cpp | 8 ++ 3 files changed, 116 insertions(+), 48 deletions(-) diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index f533361bca..b603a39b76 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -48,47 +48,86 @@ namespace cv { namespace viz { vtkStandardNewMacro(vtkCloudMatSource); - struct IsNotNan + template bool isNan(const _Tp* data) { - template bool operator()(const _Tp* data) const - { - return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); - } + return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); + } + + template struct VtkDepthTraits; + + template<> struct VtkDepthTraits + { + const static int data_type = VTK_FLOAT; + typedef vtkFloatArray array_type; + }; + + template<> struct VtkDepthTraits + { + const static int data_type = VTK_DOUBLE; + typedef vtkDoubleArray array_type; }; }} cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {} -void cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) +int cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) { CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); - int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) - : filterNanCopy(cloud, VTK_DOUBLE); + int total = cloud.depth() == CV_32F ? filterNanCopy(cloud) : filterNanCopy(cloud); vertices = vtkSmartPointer::New(); vertices->Allocate(vertices->EstimateSize(1, total)); vertices->InsertNextCell(total); for(int i = 0; i < total; ++i) vertices->InsertCellPoint(i); + + return total; } -void cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) +int cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) { - vtkCloudMatSource::SetCloud(cloud); + int total = SetCloud(cloud); if (colors.empty()) - return; + return total; CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); CV_Assert(colors.size() == cloud.size()); if (cloud.depth() == CV_32F) - filterNanColorsCopy(colors, cloud); + filterNanColorsCopy(colors, cloud, total); else if (cloud.depth() == CV_64F) - filterNanColorsCopy(colors, cloud); + filterNanColorsCopy(colors, cloud, total); + + return total; +} + +int cv::viz::vtkCloudMatSource::SetColorCloudNormals(const Mat &cloud, const Mat &colors, const Mat &normals) +{ + int total = SetColorCloud(cloud, colors); + + if (normals.empty()) + return total; + + CV_Assert(normals.depth() == CV_32F || normals.depth() == CV_64F); + CV_Assert(normals.channels() == 3 || normals.channels() == 4); + CV_Assert(normals.size() == cloud.size()); + + if (normals.depth() == CV_32F && cloud.depth() == CV_32F) + filterNanNormalsCopy(colors, cloud, total); + else if (normals.depth() == CV_32F && cloud.depth() == CV_64F) + filterNanNormalsCopy(colors, cloud, total); + else if (normals.depth() == CV_64F && cloud.depth() == CV_32F) + filterNanNormalsCopy(colors, cloud, total); + else if (normals.depth() == CV_64F && cloud.depth() == CV_64F) + filterNanNormalsCopy(colors, cloud, total); + else + CV_Assert(!"Unsupported normals type"); + + return total; } int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) @@ -100,27 +139,31 @@ int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), output->SetVerts(vertices); if (scalars) output->GetPointData()->SetScalars(scalars); + + if (normals) + output->GetPointData()->SetNormals(normals); + return 1; } template -int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) +int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& cloud) { - CV_DbgAssert(DataType<_Tp>::depth == source.depth()); + CV_DbgAssert(DataType<_Tp>::depth == cloud.depth()); points = vtkSmartPointer::New(); - points->SetDataType(dataType); - points->Allocate(source.total()); - points->SetNumberOfPoints(source.total()); + points->SetDataType(VtkDepthTraits<_Tp>::data_type); + points->Allocate(cloud.total()); + points->SetNumberOfPoints(cloud.total()); - int cn = source.channels(); + int cn = cloud.channels(); int total = 0; - for (int y = 0; y < source.rows; ++y) + for (int y = 0; y < cloud.rows; ++y) { - const _Tp* srow = source.ptr<_Tp>(y); - const _Tp* send = srow + source.cols * cn; + const _Tp* srow = cloud.ptr<_Tp>(y); + const _Tp* send = srow + cloud.cols * cn; for (; srow != send; srow += cn) - if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + if (!isNan(srow)) points->SetPoint(total++, srow); } points->SetNumberOfPoints(total); @@ -128,41 +171,33 @@ int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) return total; } - -template -void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& colors, const Mat& mask) +template +void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total) { - Mat buffer(colors.size(), CV_8UC3); - Vec3b* pos = buffer.ptr(); + Vec3b* array = new Vec3b[total]; + Vec3b* pos = array; - int s_chs = colors.channels(); + int s_chs = cloud_colors.channels(); int m_chs = mask.channels(); - - _NanPred pred; - - for (int y = 0; y < colors.rows; ++y) + for (int y = 0; y < cloud_colors.rows; ++y) { - const unsigned char* srow = colors.ptr(y); - const unsigned char* send = srow + colors.cols * colors.channels(); - const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); + const unsigned char* srow = cloud_colors.ptr(y); + const unsigned char* send = srow + cloud_colors.cols * cloud_colors.channels(); + const _Msk* mrow = mask.ptr<_Msk>(y); - if (colors.channels() == 1) + if (cloud_colors.channels() == 1) { for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) + if (!isNan(mrow)) *pos++ = Vec3b(srow[0], srow[0], srow[0]); } else for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) + if (!isNan(mrow)) *pos++ = Vec3b(srow[2], srow[1], srow[0]); } - int total = pos - buffer.ptr(); - Vec3b* array = new Vec3b[total]; - std::copy(buffer.ptr(), pos, array); - scalars = vtkSmartPointer::New(); scalars->SetName("colors"); scalars->SetNumberOfComponents(3); @@ -170,4 +205,26 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& colors, const Ma scalars->SetArray(array->val, total * 3, 0); } +template +void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total) +{ + normals = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(total); + + int s_chs = cloud_normals.channels(); + int m_chs = mask.channels(); + + int pos = 0; + for (int y = 0; y < cloud_normals.rows; ++y) + { + const _Tn* srow = cloud_normals.ptr<_Tn>(y); + const _Tn* send = srow + cloud_normals.cols * s_chs; + + const _Msk* mrow = mask.ptr<_Msk>(y); + for (; srow != send; srow += s_chs, mrow += m_chs) + if (!isNan(mrow)) + normals->SetTuple(pos++, srow); + } +} diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 876ab994f6..023e723247 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -61,8 +61,9 @@ namespace cv static vtkCloudMatSource *New(); vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); - virtual void SetCloud(const Mat& cloud); - virtual void SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); + virtual int SetCloud(const Mat& cloud); + virtual int SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); + virtual int SetColorCloudNormals(const Mat &cloud, const Mat &colors = cv::Mat(), const Mat &normals = cv::Mat()); protected: vtkCloudMatSource(); @@ -73,14 +74,16 @@ namespace cv vtkSmartPointer points; vtkSmartPointer vertices; vtkSmartPointer scalars; + vtkSmartPointer normals; private: vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. void operator=(const vtkCloudMatSource&); // Not implemented. - template int filterNanCopy(const Mat& source, int dataType); + template int filterNanCopy(const Mat& cloud); + template void filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total); - template - void filterNanColorsCopy(const Mat& colors, const Mat& mask); + template + void filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total); }; } } diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 9fb291ce1d..ee91023999 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -49,6 +49,14 @@ TEST(Viz_viz3d, develop) cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); +// for(size_t i = 0; i < cloud.total(); ++i) +// { +// if (i % 15 == 0) +// continue; +// const static float qnan = std::numeric_limits::quiet_NaN(); +// cloud.at(i) = Vec3f(qnan, qnan, qnan); +// } + cv::viz::Viz3d viz("abc"); viz.showWidget("coo", cv::viz::WCoordinateSystem()); From c1b41caa7cec1bb42cfde238f0ba1ea7c178f1d2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 31 Dec 2013 21:50:38 +0400 Subject: [PATCH 25/91] added vtkCloudMatSink, reworked cloud IO functions, added normals support --- modules/viz/include/opencv2/viz.hpp | 6 +- modules/viz/src/precomp.hpp | 1 + modules/viz/src/vizcore.cpp | 57 ++------- modules/viz/src/vtk/vtkCloudMatSink.cpp | 137 ++++++++++++++++++++++ modules/viz/src/vtk/vtkCloudMatSink.h | 76 ++++++++++++ modules/viz/src/vtk/vtkCloudMatSource.cpp | 2 +- modules/viz/test/test_viz3d.cpp | 7 +- 7 files changed, 233 insertions(+), 53 deletions(-) create mode 100644 modules/viz/src/vtk/vtkCloudMatSink.cpp create mode 100644 modules/viz/src/vtk/vtkCloudMatSink.h diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 49b36a9b2f..cb399a8eb5 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -93,10 +93,10 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// - /// Read/write clouds. Supported formats: ply, stl, xyz, obj + /// Read/write clouds. Supported formats: ply, xyz, obj and stl (readonly) - CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray()); - CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = cv::noArray()); + CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray(), bool binary = false); + CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 83b779dd8e..b10e83ad50 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -132,6 +132,7 @@ #endif #include +#include #include #include diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 5a1a7a8fe2..29f6be2882 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -164,38 +164,36 @@ void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write clouds. Supported formats: ply, stl, xyz, obj -void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors) +void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors, InputArray _normals, bool binary) { CV_Assert(file.size() > 4 && "Extention is required"); String extention = file.substr(file.size()-4); Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); + Mat normals = _normals.getMat(); vtkSmartPointer source = vtkSmartPointer::New(); - source->SetColorCloud(cloud, colors); + source->SetColorCloudNormals(cloud, colors, normals); vtkSmartPointer writer; if (extention == ".xyz") { writer = vtkSmartPointer::New(); - vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + vtkXYZWriter::SafeDownCast(writer)->SetFileName(file.c_str()); } else if (extention == ".ply") { writer = vtkSmartPointer::New(); vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + vtkPLYWriter::SafeDownCast(writer)->SetFileType(binary ? VTK_BINARY : VTK_ASCII); + vtkPLYWriter::SafeDownCast(writer)->SetArrayName("Colors"); } else if (extention == ".obj") { writer = vtkSmartPointer::New(); vtkOBJWriter::SafeDownCast(writer)->SetFileName(file.c_str()); } - else if (extention == ".stl") - { - writer = vtkSmartPointer::New(); - vtkSTLWriter::SafeDownCast(writer)->SetFileName(file.c_str()); - } else CV_Assert(!"Unsupported format"); @@ -203,7 +201,7 @@ void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colo writer->Write(); } -cv::Mat cv::viz::readCloud(const String& file, OutputArray colors) +cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray normals) { CV_Assert(file.size() > 4 && "Extention is required"); String extention = file.substr(file.size()-4); @@ -233,43 +231,12 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors) else CV_Assert(!"Unsupported format"); - reader->Update(); - vtkSmartPointer poly_data = reader->GetOutput(); - vtkSmartPointer points = poly_data->GetPoints(); - - int vtktype = points->GetDataType(); - CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); - - Mat cloud(1, points->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); - Vec3d *ddata = cloud.ptr(); - Vec3f *fdata = cloud.ptr(); - - if (cloud.depth() == CV_32F) - for(size_t i = 0; i < cloud.total(); ++i) - *fdata++ = Vec3d(points->GetPoint(i)); + cv::Mat cloud; - if (cloud.depth() == CV_64F) - for(size_t i = 0; i < cloud.total(); ++i) - *ddata++ = Vec3d(points->GetPoint(i)); - - vtkSmartPointer scalars = poly_data->GetPointData() ? poly_data->GetPointData()->GetScalars() : 0; - - if (colors.needed() && scalars) - { - int channels = scalars->GetNumberOfComponents(); - int vtktype = scalars->GetDataType(); - - CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented"); - CV_Assert(cloud.total() == (size_t)scalars->GetNumberOfTuples()); - Mat buffer(cloud.size(), CV_64FC(channels)); - Vec3d *cptr = buffer.ptr(); - for(size_t i = 0; i < colors.total(); ++i) - *cptr++ = Vec3d(scalars->GetTuple(i)); - - buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); - } - else - colors.release(); + vtkSmartPointer sink = vtkSmartPointer::New(); + sink->SetInputConnection(reader->GetOutputPort()); + sink->SetOutput(cloud, colors, normals); + sink->Write(); return cloud; } diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp new file mode 100644 index 0000000000..b96db385b3 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -0,0 +1,137 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkCloudMatSink); +}} + +cv::viz::vtkCloudMatSink::vtkCloudMatSink() {} +cv::viz::vtkCloudMatSink::~vtkCloudMatSink() {} + +void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals) +{ + cloud = _cloud; + colors = _colors; + normals = _normals; +} + +void cv::viz::vtkCloudMatSink::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + vtkSmartPointer points_Data = input->GetPoints(); + + if (cloud.needed() && points_Data) + { + int vtktype = points_Data->GetDataType(); + CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); + + cloud.create(1, points_Data->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); + Vec3d *ddata = (Vec3d*)cloud.getMat().ptr(); + Vec3f *fdata = (Vec3f*)cloud.getMat().ptr(); + + if (cloud.depth() == CV_32F) + for(size_t i = 0; i < cloud.total(); ++i) + *fdata++ = Vec3d(points_Data->GetPoint(i)); + + if (cloud.depth() == CV_64F) + for(size_t i = 0; i < cloud.total(); ++i) + *ddata++ = Vec3d(points_Data->GetPoint(i)); + } + else + cloud.release(); + + vtkSmartPointer scalars_data = input->GetPointData() ? input->GetPointData()->GetScalars() : 0; + + if (colors.needed() && scalars_data) + { + int channels = scalars_data->GetNumberOfComponents(); + int vtktype = scalars_data->GetDataType(); + + CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented"); + CV_Assert(cloud.total() == (size_t)scalars_data->GetNumberOfTuples()); + + Mat buffer(cloud.size(), CV_64FC(channels)); + Vec3d *cptr = buffer.ptr(); + for(size_t i = 0; i < buffer.total(); ++i) + *cptr++ = Vec3d(scalars_data->GetTuple(i)); + + buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); + } + else + colors.release(); + + vtkSmartPointer normals_data = input->GetPointData() ? input->GetPointData()->GetNormals() : 0; + + if (normals.needed() && normals_data) + { + int channels = normals_data->GetNumberOfComponents(); + int vtktype = normals_data->GetDataType(); + + CV_Assert((vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE) && (channels == 3 || channels == 4)); + CV_Assert(cloud.total() == (size_t)normals_data->GetNumberOfTuples()); + + Mat buffer(cloud.size(), CV_64FC(channels)); + Vec3d *cptr = buffer.ptr(); + for(size_t i = 0; i < buffer.total(); ++i) + *cptr++ = Vec3d(scalars_data->GetTuple(i)); + + buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F); + } + else + normals.release(); +} + +void cv::viz::vtkCloudMatSink::PrintSelf(ostream& os, vtkIndent indent) +{ + Superclass::PrintSelf(os, indent); + os << indent << "Cloud: " << cloud.needed() << "\n"; + os << indent << "Colors: " << colors.needed() << "\n"; + os << indent << "Normals: " << normals.needed() << "\n"; +} diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h new file mode 100644 index 0000000000..e4a55f0783 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -0,0 +1,76 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkCloudMatSink_h +#define __vtkCloudMatSink_h + +namespace cv +{ + namespace viz + { + class vtkCloudMatSink : public vtkPolyDataWriter + { + public: + static vtkCloudMatSink *New(); + vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); + + protected: + vtkCloudMatSink(); + ~vtkCloudMatSink(); + + void WriteData(); + + _OutputArray cloud, colors, normals; + + private: + vtkCloudMatSink(const vtkCloudMatSink&); // Not implemented. + void operator=(const vtkCloudMatSink&); // Not implemented. + }; + } +} + +#endif diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index b603a39b76..476e0d5ed2 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -199,7 +199,7 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, co } scalars = vtkSmartPointer::New(); - scalars->SetName("colors"); + scalars->SetName("Colors"); scalars->SetNumberOfComponents(3); scalars->SetNumberOfTuples(total); scalars->SetArray(array->val, total * 3, 0); diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index ee91023999..99476f6757 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -49,6 +49,7 @@ TEST(Viz_viz3d, develop) cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); + // for(size_t i = 0; i < cloud.total(); ++i) // { // if (i % 15 == 0) @@ -63,14 +64,12 @@ TEST(Viz_viz3d, develop) cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); - //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); cv::RNG rng; rng.fill(colors, cv::RNG::UNIFORM, 0, 255); - cv::viz::WCloud c(cloud, colors); - //cv::viz::WCloud c(cloud, cv::viz::Color::bluberry()); - viz.showWidget("c", c); + viz.showWidget("c", cv::viz::WCloud(cloud, colors)); + //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); //viz.showWidget("s", cv::viz::WSphere(Point3f(0,0,0), 1)); From e7791e1590a81010afb18a61fe913c90dbface74 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 16:35:16 +0400 Subject: [PATCH 26/91] colors minor --- modules/viz/include/opencv2/viz/types.hpp | 12 ++++-------- modules/viz/test/test_viz3d.cpp | 12 ++++++++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index ab5aafc38f..ff6bd5a689 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -197,19 +197,19 @@ inline cv::viz::Color cv::viz::Color::magenta() { return Color(255, 0, 255); } inline cv::viz::Color cv::viz::Color::white() { return Color(255, 255, 255); } inline cv::viz::Color cv::viz::Color::gray() { return Color(128, 128, 128); } -inline cv::viz::Color cv::viz::Color::mlab() { return Color(235, 118, 118); } +inline cv::viz::Color cv::viz::Color::mlab() { return Color(255, 128, 128); } inline cv::viz::Color cv::viz::Color::navy() { return Color(0, 0, 128); } inline cv::viz::Color cv::viz::Color::olive() { return Color(0, 128, 128); } inline cv::viz::Color cv::viz::Color::maroon() { return Color(0, 0, 128); } inline cv::viz::Color cv::viz::Color::teal() { return Color(128, 128, 0); } -inline cv::viz::Color cv::viz::Color::rose() { return Color(127, 0, 255); } -inline cv::viz::Color cv::viz::Color::azure() { return Color(255, 127, 0); } +inline cv::viz::Color cv::viz::Color::rose() { return Color(128, 0, 255); } +inline cv::viz::Color cv::viz::Color::azure() { return Color(255, 128, 0); } inline cv::viz::Color cv::viz::Color::lime() { return Color(0, 255, 191); } inline cv::viz::Color cv::viz::Color::gold() { return Color(0, 215, 255); } inline cv::viz::Color cv::viz::Color::brown() { return Color(0, 75, 150); } inline cv::viz::Color cv::viz::Color::orange() { return Color(0, 165, 255); } -inline cv::viz::Color cv::viz::Color::chartreuse() { return Color(0, 255, 127); } +inline cv::viz::Color cv::viz::Color::chartreuse() { return Color(0, 255, 128); } inline cv::viz::Color cv::viz::Color::orange_red() { return Color(0, 69, 255); } inline cv::viz::Color cv::viz::Color::purple() { return Color(128, 0, 128); } inline cv::viz::Color cv::viz::Color::indigo() { return Color(130, 0, 75); } @@ -225,8 +225,4 @@ inline cv::viz::Color cv::viz::Color::turquoise() { return Color(208, 224, inline cv::viz::Color cv::viz::Color::celestial_blue() { return Color(208, 151, 73); } inline cv::viz::Color cv::viz::Color::amethyst() { return Color(204, 102, 153); } - - - - #endif diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 99476f6757..df66727d89 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -59,16 +59,24 @@ TEST(Viz_viz3d, develop) // } cv::viz::Viz3d viz("abc"); - viz.showWidget("coo", cv::viz::WCoordinateSystem()); + viz.setBackgroundColor(cv::viz::Color::mlab()); + viz.showWidget("coo", cv::viz::WCoordinateSystem(0.1)); cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); + std::vector gt, es; + cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); + cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); + + viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::PATH, 1.f, viz::Color::blue()), gt[0].inv()); + viz.showWidget("tr", viz::WTrajectory(es, viz::WTrajectory::PATH, 1.f, viz::Color::red()), gt[0].inv()); + cv::RNG rng; rng.fill(colors, cv::RNG::UNIFORM, 0, 255); - viz.showWidget("c", cv::viz::WCloud(cloud, colors)); + //viz.showWidget("c", cv::viz::WCloud(cloud, colors)); //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); From f610c295f2badb79386e81d0b4df4b594f5d4ced Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 17:55:18 +0400 Subject: [PATCH 27/91] more tests --- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/clouds.cpp | 12 --- modules/viz/src/shapes.cpp | 12 +-- modules/viz/test/test_precomp.cpp | 23 ++++++ modules/viz/test/test_precomp.hpp | 16 ++++ modules/viz/test/test_tutorial2.cpp | 2 +- modules/viz/test/test_tutorial3.cpp | 16 ++-- modules/viz/test/tests_simple.cpp | 87 +++++++++++++++++++++ 8 files changed, 143 insertions(+), 29 deletions(-) create mode 100644 modules/viz/test/tests_simple.cpp diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 1f48686f4a..5ca06800b3 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -234,9 +234,9 @@ namespace cv { public: //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation - WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2f &spacing, const Color &color = Color::white()); }; class CV_EXPORTS WCameraPosition : public Widget3D diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 555da22d0f..ce9acd3463 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -63,12 +63,6 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); - if (cloud.isContinuous() && colors.isContinuous()) - { - cloud = cloud.reshape(cloud.channels(), 1); - colors = colors.reshape(colors.channels(), 1); - } - vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetColorCloud(cloud, colors); @@ -268,12 +262,6 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); - if (cloud.isContinuous() && colors.isContinuous()) - { - cloud = cloud.reshape(cloud.channels(), 1); - colors = colors.reshape(colors.channels(), 1); - } - vtkIdType nr_points; vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 0450eb816e..e9102b7284 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -474,7 +474,7 @@ namespace cv { namespace viz { namespace { struct GridUtils { - static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2d &spacing) + static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2f &spacing) { // Create the grid using image data vtkSmartPointer grid = vtkSmartPointer::New(); @@ -500,7 +500,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color &color) { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); @@ -518,7 +518,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color setColor(color); } -cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2f &spacing, const Color &color) { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); @@ -1224,11 +1224,11 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display vtkIdType nr_points = path.size(); vtkSmartPointer points = vtkSmartPointer::New(); - vtkSmartPointer polyData = vtkSmartPointer::New(); - vtkSmartPointer polyLine = vtkSmartPointer::New(); - points->SetDataTypeToFloat(); points->SetNumberOfPoints(nr_points); + + vtkSmartPointer polyData = vtkSmartPointer::New(); + vtkSmartPointer polyLine = vtkSmartPointer::New(); polyLine->GetPointIds()->SetNumberOfIds(nr_points); Vec3f *data_beg = vtkpoints_data(points); diff --git a/modules/viz/test/test_precomp.cpp b/modules/viz/test/test_precomp.cpp index 5956e13e3e..c2673fee69 100644 --- a/modules/viz/test/test_precomp.cpp +++ b/modules/viz/test/test_precomp.cpp @@ -1 +1,24 @@ #include "test_precomp.hpp" + +cv::String cv::Path::combine(const String& item1, const String& item2) +{ + if (item1.empty()) + return item2; + + if (item2.empty()) + return item1; + + char last = item1[item1.size()-1]; + + bool need_append = last != '/' && last != '\\'; + return item1 + (need_append ? "/" : "") + item2; +} + +cv::String cv::Path::combine(const String& item1, const String& item2, const String& item3) +{ return combine(combine(item1, item2), item3); } + +cv::String cv::Path::change_extension(const String& file, const String& ext) +{ + String::size_type pos = file.find_last_of('.'); + return pos == String::npos ? file : file.substr(0, pos+1) + ext; +} diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index ff7606ed9b..efc89b27f5 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -63,5 +63,21 @@ #include #include #include +#include + +namespace cv +{ + struct Path + { + static String combine(const String& item1, const String& item2); + static String combine(const String& item1, const String& item2, const String& item3); + static String change_extension(const String& file, const String& ext); + }; + + inline cv::String get_dragon_ply_file_path() + { + return Path::combine(cvtest::TS::ptr()->get_data_path(), "dragon.ply"); + } +} #endif diff --git a/modules/viz/test/test_tutorial2.cpp b/modules/viz/test/test_tutorial2.cpp index 6e9189b8f2..cba24638bb 100644 --- a/modules/viz/test/test_tutorial2.cpp +++ b/modules/viz/test/test_tutorial2.cpp @@ -48,7 +48,7 @@ void tutorial2() } -TEST(Viz_viz3d, DISABLED_tutorial2_pose_of_widget) +TEST(Viz, DISABLED_tutorial2_pose_of_widget) { tutorial2(); } diff --git a/modules/viz/test/test_tutorial3.cpp b/modules/viz/test/test_tutorial3.cpp index 12eca311c1..8b43215482 100644 --- a/modules/viz/test/test_tutorial3.cpp +++ b/modules/viz/test/test_tutorial3.cpp @@ -15,21 +15,21 @@ void tutorial3(bool camera_pov) myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); /// Let's assume camera has the following properties - Point3f cam_pos(3.0f,3.0f,3.0f), cam_focal_point(3.0f,3.0f,2.0f), cam_y_dir(-1.0f,0.0f,0.0f); + Point3f cam_pos(3.f, 3.f, 3.f), cam_focal_point(3.f, 3.f, 2.f), cam_y_dir(-1.f, 0.f, 0.f); /// We can get the pose of the cam using makeCameraPose Affine3f cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); /// We can get the transformation matrix from camera coordinate system to global using /// - makeTransformToGlobal. We need the axes of the camera - Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos); + Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.f, -1.f, 0.f), Vec3f(-1.f, 0.f, 0.f), Vec3f(0.f, 0.f, -1.f), cam_pos); /// Create a cloud widget. - Mat bunny_cloud = viz::readCloud("d:/cloud_dragon.ply"); - viz::WCloud cloud_widget(bunny_cloud, viz::Color::green()); + Mat dragon_cloud = viz::readCloud(get_dragon_ply_file_path()); + viz::WCloud cloud_widget(dragon_cloud, viz::Color::green()); /// Pose of the widget in camera frame - Affine3f cloud_pose = Affine3f().translate(Vec3f(0.0f,0.0f,3.0f)); + Affine3f cloud_pose = Affine3f().translate(Vec3f(0.f, 0.f, 3.f)); /// Pose of the widget in global frame Affine3f cloud_pose_global = transform * cloud_pose; @@ -37,7 +37,7 @@ void tutorial3(bool camera_pov) if (!camera_pov) { viz::WCameraPosition cpw(0.5); // Coordinate axes - viz::WCameraPosition cpw_frustum(Vec2f(0.889484, 0.523599)); // Camera frustum + viz::WCameraPosition cpw_frustum(Vec2f(0.889484f, 0.523599f)); // Camera frustum myWindow.showWidget("CPW", cpw, cam_pose); myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose); } @@ -53,12 +53,12 @@ void tutorial3(bool camera_pov) myWindow.spin(); } -TEST(Viz_viz3d, DISABLED_tutorial3_global_view) +TEST(Viz, DISABLED_tutorial3_global_view) { tutorial3(false); } -TEST(Viz_viz3d, DISABLED_tutorial3_camera_view) +TEST(Viz, DISABLED_tutorial3_camera_view) { tutorial3(true); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp new file mode 100644 index 0000000000..1a2e9fc94c --- /dev/null +++ b/modules/viz/test/tests_simple.cpp @@ -0,0 +1,87 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// + // + // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. + // + // By downloading, copying, installing or using the software you agree to this license. + // If you do not agree to this license, do not download, install, + // copy or use the software. + // + // + // License Agreement + // For Open Source Computer Vision Library + // + // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. + // Copyright (C) 2008-2013, Willow Garage Inc., all rights reserved. + // Third party copyrights are property of their respective owners. + // + // Redistribution and use in source and binary forms, with or without modification, + // are permitted provided that the following conditions are met: + // + // * Redistribution's of source code must retain the above copyright notice, + // this list of conditions and the following disclaimer. + // + // * Redistribution's in binary form must reproduce the above copyright notice, + // this list of conditions and the following disclaimer in the documentation + // and / or other materials provided with the distribution. + // + // * The name of the copyright holders may not be used to endorse or promote products + // derived from this software without specific prior written permission. + // + // This software is provided by the copyright holders and contributors "as is" and + // any express or implied warranties, including, but not limited to, the implied + // warranties of merchantability and fitness for a particular purpose are disclaimed. + // In no event shall the Intel Corporation or contributors be liable for any direct, + // indirect, incidental, special, exemplary, or consequential damages + // (including, but not limited to, procurement of substitute goods or services; + // loss of use, data, or profits; or business interruption) however caused + // and on any theory of liability, whether in contract, strict liability, + // or tort (including negligence or otherwise) arising in any way out of + // the use of this software, even if advised of the possibility of such damage. + // + //M*/ + +#include "test_precomp.hpp" + +using namespace cv; +using namespace cv::viz; + +TEST(Viz, DISABLED_show_cloud_bluberry) +{ + Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); + + Viz3d viz("show_cloud_bluberry"); + viz.setBackgroundColor(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry())); + viz.spin(); +} + +TEST(Viz, DISABLED_show_cloud_random_color) +{ + Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); + + Mat colors(dragon_cloud.size(), CV_8UC3); + theRNG().fill(colors, RNG::UNIFORM, 0, 255); + + Viz3d viz("show_cloud_random_color"); + viz.setBackgroundColor(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("dragon", WCloud(dragon_cloud, colors)); + viz.spin(); +} + +TEST(Viz, DISABLED_show_cloud_masked) +{ + Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); + + Vec3f qnan = Vec3f::all(std::numeric_limits::quiet_NaN()); + for(size_t i = 0; i < dragon_cloud.total(); ++i) + if (i % 15 != 0) + dragon_cloud.at(i) = qnan; + + Viz3d viz("show_cloud_masked"); + viz.setBackgroundColor(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("dragon", WCloud(dragon_cloud)); + viz.spin(); +} From 1615527426dab092712665f05610440432bfbcc7 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 18:21:23 +0400 Subject: [PATCH 28/91] switched source to InputArrays --- modules/viz/src/clouds.cpp | 11 ++---- modules/viz/src/vizcore.cpp | 6 +-- modules/viz/src/vtk/vtkCloudMatSource.cpp | 46 +++++++++++++---------- modules/viz/src/vtk/vtkCloudMatSource.h | 6 +-- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index ce9acd3463..4746bc2e5d 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -56,12 +56,9 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Point Cloud Widget implementation -cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) +cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors) { - CV_Assert(!_cloud.empty() && !_colors.empty()); - - Mat cloud = _cloud.getMat(); - Mat colors = _colors.getMat(); + CV_Assert(!cloud.empty() && !colors.empty()); vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetColorCloud(cloud, colors); @@ -81,10 +78,8 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) WidgetAccessor::setProp(*this, actor); } -cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) +cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) { - Mat cloud = _cloud.getMat(); - vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetCloud(cloud); diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 29f6be2882..5029756c27 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -164,15 +164,11 @@ void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write clouds. Supported formats: ply, stl, xyz, obj -void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors, InputArray _normals, bool binary) +void cv::viz::writeCloud(const String& file, InputArray cloud, InputArray colors, InputArray normals, bool binary) { CV_Assert(file.size() > 4 && "Extention is required"); String extention = file.substr(file.size()-4); - Mat cloud = _cloud.getMat(); - Mat colors = _colors.getMat(); - Mat normals = _normals.getMat(); - vtkSmartPointer source = vtkSmartPointer::New(); source->SetColorCloudNormals(cloud, colors, normals); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 476e0d5ed2..46603a7b90 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -71,12 +71,14 @@ namespace cv { namespace viz cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {} -int cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) +int cv::viz::vtkCloudMatSource::SetCloud(InputArray _cloud) { - CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); - CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); + CV_Assert(_cloud.depth() == CV_32F || _cloud.depth() == CV_64F); + CV_Assert(_cloud.channels() == 3 || _cloud.channels() == 4); - int total = cloud.depth() == CV_32F ? filterNanCopy(cloud) : filterNanCopy(cloud); + Mat cloud = _cloud.getMat(); + + int total = _cloud.depth() == CV_32F ? filterNanCopy(cloud) : filterNanCopy(cloud); vertices = vtkSmartPointer::New(); vertices->Allocate(vertices->EstimateSize(1, total)); @@ -87,15 +89,18 @@ int cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) return total; } -int cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) +int cv::viz::vtkCloudMatSource::SetColorCloud(InputArray _cloud, InputArray _colors) { - int total = SetCloud(cloud); + int total = SetCloud(_cloud); - if (colors.empty()) + if (_colors.empty()) return total; - CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); - CV_Assert(colors.size() == cloud.size()); + CV_Assert(_colors.depth() == CV_8U && _colors.channels() <= 4 && _colors.channels() != 2); + CV_Assert(_colors.size() == _cloud.size()); + + Mat cloud = _cloud.getMat(); + Mat colors = _colors.getMat(); if (cloud.depth() == CV_32F) filterNanColorsCopy(colors, cloud, total); @@ -105,25 +110,28 @@ int cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &color return total; } -int cv::viz::vtkCloudMatSource::SetColorCloudNormals(const Mat &cloud, const Mat &colors, const Mat &normals) +int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArray _colors, InputArray _normals) { - int total = SetColorCloud(cloud, colors); + int total = SetColorCloud(_cloud, _colors); - if (normals.empty()) + if (_normals.empty()) return total; - CV_Assert(normals.depth() == CV_32F || normals.depth() == CV_64F); - CV_Assert(normals.channels() == 3 || normals.channels() == 4); - CV_Assert(normals.size() == cloud.size()); + CV_Assert(_normals.depth() == CV_32F || _normals.depth() == CV_64F); + CV_Assert(_normals.channels() == 3 || _normals.channels() == 4); + CV_Assert(_normals.size() == _cloud.size()); + + Mat cloud = _cloud.getMat(); + Mat normals = _normals.getMat(); if (normals.depth() == CV_32F && cloud.depth() == CV_32F) - filterNanNormalsCopy(colors, cloud, total); + filterNanNormalsCopy(normals, cloud, total); else if (normals.depth() == CV_32F && cloud.depth() == CV_64F) - filterNanNormalsCopy(colors, cloud, total); + filterNanNormalsCopy(normals, cloud, total); else if (normals.depth() == CV_64F && cloud.depth() == CV_32F) - filterNanNormalsCopy(colors, cloud, total); + filterNanNormalsCopy(normals, cloud, total); else if (normals.depth() == CV_64F && cloud.depth() == CV_64F) - filterNanNormalsCopy(colors, cloud, total); + filterNanNormalsCopy(normals, cloud, total); else CV_Assert(!"Unsupported normals type"); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 023e723247..a1d854c326 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -61,9 +61,9 @@ namespace cv static vtkCloudMatSource *New(); vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); - virtual int SetCloud(const Mat& cloud); - virtual int SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); - virtual int SetColorCloudNormals(const Mat &cloud, const Mat &colors = cv::Mat(), const Mat &normals = cv::Mat()); + virtual int SetCloud(InputArray cloud); + virtual int SetColorCloud(InputArray cloud, InputArray colors = noArray()); + virtual int SetColorCloudNormals(InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray()); protected: vtkCloudMatSource(); From b1c0bf1fee85b37e52dbbf6e491a7fbab8639861 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 19:26:04 +0400 Subject: [PATCH 29/91] Affine::rotate(rvec) method --- modules/core/include/opencv2/core/affine.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 0aaf57e0a2..b4e7472a9f 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -99,6 +99,9 @@ namespace cv // a.rotate(R) is equivalent to Affine(R, 0) * a; Affine3 rotate(const Mat3& R) const; + // a.rotate(R) is equivalent to Affine(rvec, 0) * a; + Affine3 rotate(const Vec3& rvec) const; + // a.translate(t) is equivalent to Affine(E, t) * a; Affine3 translate(const Vec3& t) const; @@ -361,6 +364,12 @@ cv::Affine3 cv::Affine3::rotate(const Mat3& R) const return result; } +template inline +cv::Affine3 cv::Affine3::rotate(const Vec3& _rvec) const +{ + return rotate(Affine3f(_rvec).rotation()); +} + template inline cv::Affine3 cv::Affine3::translate(const Vec3& t) const { From 186853a50fddc7a814433cb082956ace780a4f47 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 19:58:41 +0400 Subject: [PATCH 30/91] mass switch from Affine3f to Affine3d --- modules/viz/doc/viz3d.rst | 28 ++--- modules/viz/doc/widget.rst | 36 +++---- modules/viz/include/opencv2/viz.hpp | 7 +- modules/viz/include/opencv2/viz/viz3d.hpp | 12 +-- modules/viz/include/opencv2/viz/widgets.hpp | 17 +-- modules/viz/src/clouds.cpp | 4 +- modules/viz/src/shapes.cpp | 112 ++++++++++++++++++-- modules/viz/src/viz3d.cpp | 12 +-- modules/viz/src/vizcore.cpp | 58 +++++----- modules/viz/src/vizimpl.cpp | 40 +++---- modules/viz/src/vizimpl.hpp | 37 ++----- modules/viz/src/widget.cpp | 10 +- modules/viz/test/test_tutorial2.cpp | 18 ++-- modules/viz/test/test_tutorial3.cpp | 10 +- modules/viz/test/test_viz3d.cpp | 2 +- 15 files changed, 236 insertions(+), 167 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 63c5ac34c5..ad1356e587 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -13,7 +13,7 @@ viz::makeTransformToGlobal -------------------------- Takes coordinate frame data and builds transform to global coordinate frame. -.. ocv:function:: Affine3f viz::makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin = Vec3f::all(0)) +.. ocv:function:: Affine3d viz::makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin = Vec3f::all(0)) :param axis_x: X axis vector in global coordinate frame. :param axis_y: Y axis vector in global coordinate frame. @@ -26,7 +26,7 @@ viz::makeCameraPose ------------------- Constructs camera pose from position, focal_point and up_vector (see gluLookAt() for more infromation). -.. ocv:function:: Affine3f makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir) +.. ocv:function:: Affine3d makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir) :param position: Position of the camera in global coordinate frame. :param focal_point: Focal point of the camera in global coordinate frame. @@ -94,19 +94,19 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar Viz3d& operator=(const Viz3d&); ~Viz3d(); - void showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()); + void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); Widget getWidget(const String &id) const; void removeAllWidgets(); - void setWidgetPose(const String &id, const Affine3f &pose); - void updateWidgetPose(const String &id, const Affine3f &pose); - Affine3f getWidgetPose(const String &id) const; + void setWidgetPose(const String &id, const Affine3d &pose); + void updateWidgetPose(const String &id, const Affine3d &pose); + Affine3d getWidgetPose(const String &id) const; void setCamera(const Camera &camera); Camera getCamera() const; - Affine3f getViewerPose(); - void setViewerPose(const Affine3f &pose); + Affine3d getViewerPose(); + void setViewerPose(const Affine3d &pose); void resetCameraViewpoint (const String &id); void resetCamera(); @@ -152,7 +152,7 @@ viz::Viz3d::showWidget ---------------------- Shows a widget in the window. -.. ocv:function:: void Viz3d::showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()) +.. ocv:function:: void Viz3d::showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()) :param id: A unique id for the widget. :param widget: The widget to be displayed in the window. @@ -186,7 +186,7 @@ viz::Viz3d::setWidgetPose ------------------------- Sets pose of a widget in the window. -.. ocv:function:: void setWidgetPose(const String &id, const Affine3f &pose) +.. ocv:function:: void setWidgetPose(const String &id, const Affine3d &pose) :param id: The id of the widget whose pose will be set. :param pose: The new pose of the widget. @@ -195,7 +195,7 @@ viz::Viz3d::updateWidgetPose ---------------------------- Updates pose of a widget in the window by pre-multiplying its current pose. -.. ocv:function:: void updateWidgetPose(const String &id, const Affine3f &pose) +.. ocv:function:: void updateWidgetPose(const String &id, const Affine3d &pose) :param id: The id of the widget whose pose will be updated. :param pose: The pose that the current pose of the widget will be pre-multiplied by. @@ -204,7 +204,7 @@ viz::Viz3d::getWidgetPose ------------------------- Returns the current pose of a widget in the window. -.. ocv:function:: Affine3f getWidgetPose(const String &id) const +.. ocv:function:: Affine3d getWidgetPose(const String &id) const :param id: The id of the widget whose pose will be returned. @@ -226,13 +226,13 @@ viz::Viz3d::getViewerPose ------------------------- Returns the current pose of the viewer. -..ocv:function:: Affine3f getViewerPose() +..ocv:function:: Affine3d getViewerPose() viz::Viz3d::setViewerPose ------------------------- Sets pose of the viewer. -.. ocv:function:: void setViewerPose(const Affine3f &pose) +.. ocv:function:: void setViewerPose(const Affine3d &pose) :param pose: The new pose of the viewer. diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index a629b7bc91..c420799640 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -170,9 +170,9 @@ Base class of all 3D widgets. :: public: Widget3D() {} - void setPose(const Affine3f &pose); - void updatePose(const Affine3f &pose); - Affine3f getPose() const; + void setPose(const Affine3d &pose); + void updatePose(const Affine3d &pose); + Affine3d getPose() const; void setColor(const Color &color); private: @@ -183,7 +183,7 @@ viz::Widget3D::setPose ---------------------- Sets pose of the widget. -.. ocv:function:: void setPose(const Affine3f &pose) +.. ocv:function:: void setPose(const Affine3d &pose) :param pose: The new pose of the widget. @@ -191,7 +191,7 @@ viz::Widget3D::updateWidgetPose ------------------------------- Updates pose of the widget by pre-multiplying its current pose. -.. ocv:function:: void updateWidgetPose(const Affine3f &pose) +.. ocv:function:: void updateWidgetPose(const Affine3d &pose) :param pose: The pose that the current pose of the widget will be pre-multiplied by. @@ -199,7 +199,7 @@ viz::Widget3D::getPose ---------------------- Returns the current pose of the widget. -.. ocv:function:: Affine3f getWidgetPose() const +.. ocv:function:: Affine3d getWidgetPose() const viz::Widget3D::setColor ----------------------- @@ -732,14 +732,14 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. @@ -762,16 +762,16 @@ This 3D Widget represents a trajectory. :: { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); }; viz::WTrajectoryFrustums::WTrajectoryFrustums ----------------------------- Constructs a WTrajectoryFrustums. -.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param K: Intrinsic matrix of the camera. @@ -780,7 +780,7 @@ Constructs a WTrajectoryFrustums. Displays frustums at each pose of the trajectory. -.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param fov: Field of view of the camera (horizontal, vertical). @@ -799,7 +799,7 @@ represent the direction from previous position to the current. :: class CV_EXPORTS WTrajectorySpheres : public Widget3D { public: - WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, + WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, sphere_radius = 0.007, Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; @@ -808,7 +808,7 @@ viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- Constructs a WTrajectorySpheres. -.. ocv:function:: WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) :param path: List of poses on a trajectory. :param line_length: Length of the lines. @@ -867,9 +867,9 @@ This 3D Widget defines a collection of clouds. :: WCloudCollection(); //! Each point in cloud is mapped to a color in colors - void addCloud(InputArray cloud, InputArray colors, const Affine3f &pose = Affine3f::Identity()); + void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()); //! All points in cloud have the same color - void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3f &pose = Affine3f::Identity()); + void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3d &pose = Affine3d::Identity()); private: /* hidden */ @@ -885,7 +885,7 @@ viz::WCloudCollection::addCloud ------------------------------- Adds a cloud to the collection. -.. ocv:function:: void addCloud(InputArray cloud, InputArray colors, const Affine3f &pose = Affine3f::Identity()) +.. ocv:function:: void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()) :param cloud: Point set which can be of type: ``CV_32FC3``, ``CV_32FC4``, ``CV_64FC3``, ``CV_64FC4``. :param colors: Set of colors. It has to be of the same size with cloud. @@ -893,7 +893,7 @@ Adds a cloud to the collection. Points in the cloud belong to mask when they are set to (NaN, NaN, NaN). -.. ocv:function:: void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3f &pose = Affine3f::Identity()) +.. ocv:function:: void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3d &pose = Affine3d::Identity()) :param cloud: Point set which can be of type: ``CV_32FC3``, ``CV_32FC4``, ``CV_64FC3``, ``CV_64FC4``. :param colors: A single :ocv:class:`Color` for the whole cloud. diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index cb399a8eb5..2724e921d2 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -58,10 +58,10 @@ namespace cv namespace viz { //! takes coordiante frame data and builds transfrom to global coordinate frame - CV_EXPORTS Affine3f makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin = Vec3f::all(0)); + CV_EXPORTS Affine3d makeTransformToGlobal(const Vec3d& axis_x, const Vec3d& axis_y, const Vec3d& axis_z, const Vec3d& origin = Vec3d::all(0)); //! constructs camera pose from position, focal_point and up_vector (see gluLookAt() for more infromation) - CV_EXPORTS Affine3f makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir); + CV_EXPORTS Affine3d makeCameraPose(const Vec3d& position, const Vec3d& focal_point, const Vec3d& y_dir); //! retrieves a window by its name. If no window with such name, then it creates new. CV_EXPORTS Viz3d get(const String &window_name); @@ -101,10 +101,7 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories - CV_EXPORTS bool readPose(const String& file, Affine3f& pose, const String& tag = "pose"); CV_EXPORTS bool readPose(const String& file, Affine3d& pose, const String& tag = "pose"); - - CV_EXPORTS void writePose(const String& file, const Affine3f& pose, const String& tag = "pose"); CV_EXPORTS void writePose(const String& file, const Affine3d& pose, const String& tag = "pose"); CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 1b31b2447f..7cd27eb616 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -70,19 +70,19 @@ namespace cv Viz3d& operator=(const Viz3d&); ~Viz3d(); - void showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()); + void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); Widget getWidget(const String &id) const; void removeAllWidgets(); - void setWidgetPose(const String &id, const Affine3f &pose); - void updateWidgetPose(const String &id, const Affine3f &pose); - Affine3f getWidgetPose(const String &id) const; + void setWidgetPose(const String &id, const Affine3d &pose); + void updateWidgetPose(const String &id, const Affine3d &pose); + Affine3d getWidgetPose(const String &id) const; void setCamera(const Camera &camera); Camera getCamera() const; - Affine3f getViewerPose(); - void setViewerPose(const Affine3f &pose); + Affine3d getViewerPose(); + void setViewerPose(const Affine3d &pose); void resetCameraViewpoint(const String &id); void resetCamera(); diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 5ca06800b3..28a2acb0de 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -111,9 +111,9 @@ namespace cv public: Widget3D() {} - void setPose(const Affine3f &pose); - void updatePose(const Affine3f &pose); - Affine3f getPose() const; + void setPose(const Affine3d &pose); + void updatePose(const Affine3d &pose); + Affine3d getPose() const; void setColor(const Color &color); @@ -264,21 +264,22 @@ namespace cv //! Displays trajectory of the given path either by coordinate frames or polyline WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectoryFrustums : public Widget3D { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: - WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, + WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; @@ -300,9 +301,9 @@ namespace cv WCloudCollection(); //! Each point in cloud is mapped to a color in colors - void addCloud(InputArray cloud, InputArray colors, const Affine3f &pose = Affine3f::Identity()); + void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()); //! All points in cloud have the same color - void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3f &pose = Affine3f::Identity()); + void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3d &pose = Affine3d::Identity()); }; class CV_EXPORTS WCloudNormals : public Widget3D diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 4746bc2e5d..16f274cf2d 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -250,7 +250,7 @@ cv::viz::WCloudCollection::WCloudCollection() WidgetAccessor::setProp(*this, actor); } -void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, const Affine3f &pose) +void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, const Affine3d &pose) { Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); @@ -292,7 +292,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); } -void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) +void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3d &pose) { Mat cloud = _cloud.getMat(); CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index e9102b7284..7da4063f70 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1182,7 +1182,7 @@ namespace cv { namespace viz { namespace { struct TrajectoryUtils { - static void applyPath(vtkSmartPointer poly_data, vtkSmartPointer append_filter, const std::vector &path) + static void applyPath(vtkSmartPointer poly_data, vtkSmartPointer append_filter, const std::vector &path) { vtkIdType nr_points = path.size(); @@ -1213,7 +1213,105 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, float scale, const Color &color) +cv::viz::WTrajectory::WTrajectory(const std::vector &_path, int display_mode, float scale, const Color &color) +{ + std::vector path(_path.begin(), _path.end()); + + vtkSmartPointer appendFilter = vtkSmartPointer::New(); + + // Bitwise and with 3 in order to limit the domain to 2 bits + if ((~display_mode & 3) ^ WTrajectory::PATH) + { + // Create a poly line along the path + vtkIdType nr_points = path.size(); + + vtkSmartPointer points = vtkSmartPointer::New(); + points->SetDataTypeToFloat(); + points->SetNumberOfPoints(nr_points); + + vtkSmartPointer polyData = vtkSmartPointer::New(); + vtkSmartPointer polyLine = vtkSmartPointer::New(); + polyLine->GetPointIds()->SetNumberOfIds(nr_points); + + Vec3f *data_beg = vtkpoints_data(points); + + for (vtkIdType i = 0; i < nr_points; ++i) + { + Vec3f cam_pose = path[i].translation(); + *data_beg++ = cam_pose; + polyLine->GetPointIds()->SetId(i,i); + } + + vtkSmartPointer cells = vtkSmartPointer::New(); + cells->InsertNextCell(polyLine); + + polyData->SetPoints(points); + polyData->SetLines(cells); + + // Set the color for polyData + vtkSmartPointer colors = vtkSmartPointer::New(); + colors->SetNumberOfComponents(3); + colors->SetNumberOfTuples(nr_points); + colors->FillComponent(0, color[2]); + colors->FillComponent(1, color[1]); + colors->FillComponent(2, color[0]); + + polyData->GetPointData()->SetScalars(colors); +#if VTK_MAJOR_VERSION <= 5 + appendFilter->AddInputConnection(polyData->GetProducerPort()); +#else + appendFilter->AddInputData(polyData); +#endif + } + + if ((~display_mode & 3) ^ WTrajectory::FRAMES) + { + // Create frames and transform along the path + vtkSmartPointer axes = vtkSmartPointer::New(); + axes->SetOrigin(0, 0, 0); + axes->SetScaleFactor(scale); + + vtkSmartPointer axes_colors = vtkSmartPointer::New(); + axes_colors->SetNumberOfComponents(3); + axes_colors->InsertNextTuple3(255,0,0); + axes_colors->InsertNextTuple3(255,0,0); + axes_colors->InsertNextTuple3(0,255,0); + axes_colors->InsertNextTuple3(0,255,0); + axes_colors->InsertNextTuple3(0,0,255); + axes_colors->InsertNextTuple3(0,0,255); + + vtkSmartPointer axes_data = axes->GetOutput(); +#if VTK_MAJOR_VERSION <= 5 + axes_data->Update(); +#else + axes->Update(); +#endif + axes_data->GetPointData()->SetScalars(axes_colors); + + vtkSmartPointer axes_tubes = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 + axes_tubes->SetInput(axes_data); +#else + axes_tubes->SetInputData(axes_data); +#endif + axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); + axes_tubes->SetNumberOfSides(6); + axes_tubes->Update(); + + TrajectoryUtils::applyPath(axes_tubes->GetOutput(), appendFilter, path); + } + + vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetScalarModeToUsePointData(); + mapper->SetInputConnection(appendFilter->GetOutputPort()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); +} + +cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, float scale, const Color &color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1318,7 +1416,7 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// WTrajectoryFrustums widget implementation -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); float f_x = K(0,0); @@ -1362,7 +1460,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &p setColor(color); } -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -1411,7 +1509,7 @@ template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast &path, float line_length, float init_sphere_radius, float sphere_radius, +cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, const Color &line_color, const Color &sphere_color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1469,8 +1567,8 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &pat } - Affine3f relativeAffine = path[i].inv() * path[i-1]; - Vec3f v = path[i].rotation() * relativeAffine.translation(); + Affine3d relativeAffine = path[i].inv() * path[i-1]; + Vec3d v = path[i].rotation() * relativeAffine.translation(); v = normalize(v) * line_length; vtkSmartPointer line_source = vtkSmartPointer::New(); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 0f21e08cc7..33d851d642 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -108,18 +108,18 @@ void cv::viz::Viz3d::registerKeyboardCallback(KeyboardCallback callback, void* c void cv::viz::Viz3d::registerMouseCallback(MouseCallback callback, void* cookie) { impl_->registerMouseCallback(callback, cookie); } -void cv::viz::Viz3d::showWidget(const String &id, const Widget &widget, const Affine3f &pose) { impl_->showWidget(id, widget, pose); } +void cv::viz::Viz3d::showWidget(const String &id, const Widget &widget, const Affine3d &pose) { impl_->showWidget(id, widget, pose); } void cv::viz::Viz3d::removeWidget(const String &id) { impl_->removeWidget(id); } cv::viz::Widget cv::viz::Viz3d::getWidget(const String &id) const { return impl_->getWidget(id); } void cv::viz::Viz3d::removeAllWidgets() { impl_->removeAllWidgets(); } -void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3f &pose) { impl_->setWidgetPose(id, pose); } -void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3f &pose) { impl_->updateWidgetPose(id, pose); } -cv::Affine3f cv::viz::Viz3d::getWidgetPose(const String &id) const { return impl_->getWidgetPose(id); } +void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3d &pose) { impl_->setWidgetPose(id, pose); } +void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3d &pose) { impl_->updateWidgetPose(id, pose); } +cv::Affine3d cv::viz::Viz3d::getWidgetPose(const String &id) const { return impl_->getWidgetPose(id); } void cv::viz::Viz3d::setCamera(const Camera &camera) { impl_->setCamera(camera); } cv::viz::Camera cv::viz::Viz3d::getCamera() const { return impl_->getCamera(); } -void cv::viz::Viz3d::setViewerPose(const Affine3f &pose) { impl_->setViewerPose(pose); } -cv::Affine3f cv::viz::Viz3d::getViewerPose() { return impl_->getViewerPose(); } +void cv::viz::Viz3d::setViewerPose(const Affine3d &pose) { impl_->setViewerPose(pose); } +cv::Affine3d cv::viz::Viz3d::getViewerPose() { return impl_->getViewerPose(); } void cv::viz::Viz3d::resetCameraViewpoint(const String &id) { impl_->resetCameraViewpoint(id); } void cv::viz::Viz3d::resetCamera() { impl_->resetCamera(); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 5029756c27..c26b04301e 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -45,21 +45,21 @@ #include "precomp.hpp" -cv::Affine3f cv::viz::makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin) +cv::Affine3d cv::viz::makeTransformToGlobal(const Vec3d& axis_x, const Vec3d& axis_y, const Vec3d& axis_z, const Vec3d& origin) { - Affine3f::Mat3 R(axis_x[0], axis_y[0], axis_z[0], + Affine3d::Mat3 R(axis_x[0], axis_y[0], axis_z[0], axis_x[1], axis_y[1], axis_z[1], axis_x[2], axis_y[2], axis_z[2]); - return Affine3f(R, origin); + return Affine3d(R, origin); } -cv::Affine3f cv::viz::makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir) +cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_point, const Vec3d& y_dir) { // Compute the transformation matrix for drawing the camera frame in a scene - Vec3f n = normalize(focal_point - position); - Vec3f u = normalize(y_dir.cross(n)); - Vec3f v = n.cross(u); + Vec3d n = normalize(focal_point - position); + Vec3d u = normalize(y_dir.cross(n)); + Vec3d v = n.cross(u); return makeTransformToGlobal(u, v, n, position); } @@ -240,27 +240,29 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray n /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories -namespace cv { namespace viz { namespace impl +bool cv::viz::readPose(const String& file, Affine3d& pose, const String& tag) { - template - bool readPose(const String& file, Affine3<_Tp>& pose, const String& tag) - { - FileStorage fs(file, FileStorage::READ); - if (!fs.isOpened()) - return false; + FileStorage fs(file, FileStorage::READ); + if (!fs.isOpened()) + return false; - Mat hdr(pose.matrix, false); - fs[tag] >> hdr; - return !hdr.empty() && hdr.depth() == DataDepth<_Tp>::value; - } + Mat hdr(pose.matrix, false); + fs[tag] >> hdr; + if (hdr.empty() || hdr.cols != pose.matrix.cols || hdr.rows != pose.matrix.rows) + return false; - template - void writePose(const String& file, const Affine3<_Tp>& pose, const String& tag) - { - FileStorage fs(file, FileStorage::WRITE); - fs << tag << Mat(pose.matrix, false); - } + hdr.convertTo(pose.matrix, CV_64F); + return true; +} + +void cv::viz::writePose(const String& file, const Affine3d& pose, const String& tag) +{ + FileStorage fs(file, FileStorage::WRITE); + fs << tag << Mat(pose.matrix, false); +} +namespace cv { namespace viz { namespace impl +{ template void readTrajectory(std::vector >& traj, const String& files_format, int start, int end, const String& tag) { @@ -271,8 +273,8 @@ namespace cv { namespace viz { namespace impl for(int i = start; i < end; ++i) { - Affine3<_Tp> affine; - bool ok = readPose(cv::format(files_format.c_str(), i),affine, tag); + Affine3d affine; + bool ok = readPose(cv::format(files_format.c_str(), i), affine, tag); if (!ok) break; @@ -290,11 +292,7 @@ namespace cv { namespace viz { namespace impl }}} -bool cv::viz::readPose(const String& file, Affine3f& pose, const String& tag) { return impl::readPose(file, pose, tag); } -bool cv::viz::readPose(const String& file, Affine3d& pose, const String& tag) { return impl::readPose(file, pose, tag); } -void cv::viz::writePose(const String& file, const Affine3f& pose, const String& tag) { impl::writePose(file, pose, tag); } -void cv::viz::writePose(const String& file, const Affine3d& pose, const String& tag) { impl::writePose(file, pose, tag); } void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) { impl::readTrajectory(traj, files_format, start, end, tag); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index c727a99d21..cac58350b2 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -120,7 +120,7 @@ cv::viz::Viz3d::VizImpl::~VizImpl() } ///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::showWidget(const String &id, const Widget &widget, const Affine3f &pose) +void cv::viz::Viz3d::VizImpl::showWidget(const String &id, const Widget &widget, const Affine3d &pose) { WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id); bool exists = wam_itr != widget_actor_map_->end(); @@ -172,7 +172,7 @@ cv::viz::Widget cv::viz::Viz3d::VizImpl::getWidget(const String &id) const } ///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3f &pose) +void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3d &pose) { WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id); bool exists = wam_itr != widget_actor_map_->end(); @@ -187,7 +187,7 @@ void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3f &po } ///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3f &pose) +void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3d &pose) { WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id); bool exists = wam_itr != widget_actor_map_->end(); @@ -202,8 +202,8 @@ void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3f setWidgetPose(id, pose); return ; } - Matx44f matrix_cv = convertToMatx(matrix); - Affine3f updated_pose = pose * Affine3f(matrix_cv); + Matx44d matrix_cv = convertToMatx(matrix); + Affine3d updated_pose = pose * Affine3d(matrix_cv); matrix = convertToVtkMatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); @@ -211,7 +211,7 @@ void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3f } ///////////////////////////////////////////////////////////////////////////////////////////// -cv::Affine3f cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const +cv::Affine3d cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const { WidgetActorMap::const_iterator wam_itr = widget_actor_map_->find(id); bool exists = wam_itr != widget_actor_map_->end(); @@ -221,8 +221,8 @@ cv::Affine3f cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const CV_Assert("Widget is not 3D." && actor); vtkSmartPointer matrix = actor->GetUserMatrix(); - Matx44f matrix_cv = convertToMatx(matrix); - return Affine3f(matrix_cv); + Matx44d matrix_cv = convertToMatx(matrix); + return Affine3d(matrix_cv); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -350,32 +350,32 @@ cv::viz::Camera cv::viz::Viz3d::VizImpl::getCamera() const } ///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3f &pose) +void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3d &pose) { vtkCamera& camera = *renderer_->GetActiveCamera(); // Position = extrinsic translation - cv::Vec3f pos_vec = pose.translation(); + cv::Vec3d pos_vec = pose.translation(); // Rotate the view vector - cv::Matx33f rotation = pose.rotation(); - cv::Vec3f y_axis(0.f, 1.f, 0.f); - cv::Vec3f up_vec(rotation * y_axis); + cv::Matx33d rotation = pose.rotation(); + cv::Vec3d y_axis(0.0, 1.0, 0.0); + cv::Vec3d up_vec(rotation * y_axis); // Compute the new focal point - cv::Vec3f z_axis(0.f, 0.f, 1.f); - cv::Vec3f focal_vec = pos_vec + rotation * z_axis; + cv::Vec3d z_axis(0.0, 0.0, 1.0); + cv::Vec3d focal_vec = pos_vec + rotation * z_axis; - camera.SetPosition(pos_vec[0], pos_vec[1], pos_vec[2]); - camera.SetFocalPoint(focal_vec[0], focal_vec[1], focal_vec[2]); - camera.SetViewUp(up_vec[0], up_vec[1], up_vec[2]); + camera.SetPosition(pos_vec.val); + camera.SetFocalPoint(focal_vec.val); + camera.SetViewUp(up_vec.val); renderer_->ResetCameraClippingRange(); renderer_->Render(); } ///////////////////////////////////////////////////////////////////////////////////////////// -cv::Affine3f cv::viz::Viz3d::VizImpl::getViewerPose() +cv::Affine3d cv::viz::Viz3d::VizImpl::getViewerPose() { vtkCamera& camera = *renderer_->GetActiveCamera(); @@ -400,7 +400,7 @@ cv::Affine3f cv::viz::Viz3d::VizImpl::getViewerPose() R(2, 1) = y_axis[2]; R(2, 2) = z_axis[2]; - return cv::Affine3f(R, pos); + return cv::Affine3d(R, pos); } ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index d958f46726..0cfb403095 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -57,14 +57,14 @@ public: VizImpl(const String &name); virtual ~VizImpl(); - void showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()); + void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); Widget getWidget(const String &id) const; void removeAllWidgets(); - void setWidgetPose(const String &id, const Affine3f &pose); - void updateWidgetPose(const String &id, const Affine3f &pose); - Affine3f getWidgetPose(const String &id) const; + void setWidgetPose(const String &id, const Affine3d &pose); + void updateWidgetPose(const String &id, const Affine3d &pose); + Affine3d getWidgetPose(const String &id) const; void setDesiredUpdateRate(double rate); double getDesiredUpdateRate(); @@ -95,8 +95,8 @@ public: void resetCameraViewpoint(const String& id); void resetCamera(); - void setViewerPose(const Affine3f &pose); - Affine3f getViewerPose(); + void setViewerPose(const Affine3d &pose); + Affine3d getViewerPose(); void convertToWindowCoordinates(const Point3d &pt, Point3d &window_coord); void converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction); @@ -280,31 +280,6 @@ namespace cv } }; - struct ApplyAffine - { - const Affine3f& affine_; - ApplyAffine(const Affine3f& affine) : affine_(affine) {} - - template Point3_<_Tp> operator()(const Point3_<_Tp>& p) const { return affine_ * p; } - - template Vec<_Tp, 3> operator()(const Vec<_Tp, 3>& v) const - { - const float* m = affine_.matrix.val; - - Vec<_Tp, 3> result; - result[0] = (_Tp)(m[0] * v[0] + m[1] * v[1] + m[ 2] * v[2] + m[ 3]); - result[1] = (_Tp)(m[4] * v[0] + m[5] * v[1] + m[ 6] * v[2] + m[ 7]); - result[2] = (_Tp)(m[8] * v[0] + m[9] * v[1] + m[10] * v[2] + m[11]); - return result; - } - - private: - ApplyAffine(const ApplyAffine&); - ApplyAffine& operator=(const ApplyAffine&); - }; - - - struct ConvertToVtkImage { struct Impl diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index a70fb925a3..839ea20146 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -239,7 +239,7 @@ void cv::viz::WidgetAccessor::setProp(Widget& widget, vtkSmartPointer p /////////////////////////////////////////////////////////////////////////////////////////////// /// widget3D implementation -void cv::viz::Widget3D::setPose(const Affine3f &pose) +void cv::viz::Widget3D::setPose(const Affine3d &pose) { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); @@ -249,7 +249,7 @@ void cv::viz::Widget3D::setPose(const Affine3f &pose) actor->Modified(); } -void cv::viz::Widget3D::updatePose(const Affine3f &pose) +void cv::viz::Widget3D::updatePose(const Affine3d &pose) { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); @@ -261,18 +261,18 @@ void cv::viz::Widget3D::updatePose(const Affine3f &pose) return; } - Affine3f updated_pose = pose * Affine3f(convertToMatx(matrix)); + Affine3d updated_pose = pose * Affine3d(convertToMatx(matrix)); matrix = convertToVtkMatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); } -cv::Affine3f cv::viz::Widget3D::getPose() const +cv::Affine3d cv::viz::Widget3D::getPose() const { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); - return Affine3f(convertToMatx(actor->GetUserMatrix())); + return Affine3d(convertToMatx(actor->GetUserMatrix())); } void cv::viz::Widget3D::setColor(const Color &color) diff --git a/modules/viz/test/test_tutorial2.cpp b/modules/viz/test/test_tutorial2.cpp index cba24638bb..a901adc2c7 100644 --- a/modules/viz/test/test_tutorial2.cpp +++ b/modules/viz/test/test_tutorial2.cpp @@ -12,34 +12,34 @@ void tutorial2() myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); /// Add line to represent (1,1,1) axis - viz::WLine axis(Point3f(-1.0f,-1.0f,-1.0f), Point3f(1.0f,1.0f,1.0f)); + viz::WLine axis(Point3f(-1.0, -1.0, -1.0), Point3d(1.0, 1.0, 1.0)); axis.setRenderingProperty(viz::LINE_WIDTH, 4.0); myWindow.showWidget("Line Widget", axis); /// Construct a cube widget - viz::WCube cube_widget(Point3f(0.5,0.5,0.0), Point3f(0.0,0.0,-0.5), true, viz::Color::blue()); + viz::WCube cube_widget(Point3d(0.5, 0.5, 0.0), Point3d(0.0, 0.0, -0.5), true, viz::Color::blue()); cube_widget.setRenderingProperty(viz::LINE_WIDTH, 4.0); /// Display widget (update if already displayed) myWindow.showWidget("Cube Widget", cube_widget); /// Rodrigues vector - Mat rot_vec = Mat::zeros(1,3,CV_32F); - float translation_phase = 0.0, translation = 0.0; + Vec3d rot_vec = Vec3d::all(0); + double translation_phase = 0.0, translation = 0.0; while(!myWindow.wasStopped()) { /* Rotation using rodrigues */ /// Rotate around (1,1,1) - rot_vec.at(0,0) += CV_PI * 0.01f; - rot_vec.at(0,1) += CV_PI * 0.01f; - rot_vec.at(0,2) += CV_PI * 0.01f; + rot_vec[0] += CV_PI * 0.01; + rot_vec[1] += CV_PI * 0.01; + rot_vec[2] += CV_PI * 0.01; /// Shift on (1,1,1) - translation_phase += CV_PI * 0.01f; + translation_phase += CV_PI * 0.01; translation = sin(translation_phase); /// Construct pose - Affine3f pose(rot_vec, Vec3f(translation, translation, translation)); + Affine3d pose(rot_vec, Vec3d(translation, translation, translation)); myWindow.setWidgetPose("Cube Widget", pose); diff --git a/modules/viz/test/test_tutorial3.cpp b/modules/viz/test/test_tutorial3.cpp index 8b43215482..590e29ebfd 100644 --- a/modules/viz/test/test_tutorial3.cpp +++ b/modules/viz/test/test_tutorial3.cpp @@ -15,23 +15,23 @@ void tutorial3(bool camera_pov) myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); /// Let's assume camera has the following properties - Point3f cam_pos(3.f, 3.f, 3.f), cam_focal_point(3.f, 3.f, 2.f), cam_y_dir(-1.f, 0.f, 0.f); + Point3d cam_pos(3.0, 3.0, 3.0), cam_focal_point(3.0, 3.0, 2.0), cam_y_dir(-1.0, 0.0, 0.0); /// We can get the pose of the cam using makeCameraPose - Affine3f cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); + Affine3d cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); /// We can get the transformation matrix from camera coordinate system to global using /// - makeTransformToGlobal. We need the axes of the camera - Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.f, -1.f, 0.f), Vec3f(-1.f, 0.f, 0.f), Vec3f(0.f, 0.f, -1.f), cam_pos); + Affine3d transform = viz::makeTransformToGlobal(Vec3d(0.0, -1.0, 0.0), Vec3d(-1.0, 0.0, 0.0), Vec3d(0.0, 0.0, -1.0), cam_pos); /// Create a cloud widget. Mat dragon_cloud = viz::readCloud(get_dragon_ply_file_path()); viz::WCloud cloud_widget(dragon_cloud, viz::Color::green()); /// Pose of the widget in camera frame - Affine3f cloud_pose = Affine3f().translate(Vec3f(0.f, 0.f, 3.f)); + Affine3d cloud_pose = Affine3d().translate(Vec3d(0.0, 0.0, 3.0)); /// Pose of the widget in global frame - Affine3f cloud_pose_global = transform * cloud_pose; + Affine3d cloud_pose_global = transform * cloud_pose; /// Visualize camera frame if (!camera_pov) diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index df66727d89..ce0344f1e4 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -67,7 +67,7 @@ TEST(Viz_viz3d, develop) //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); - std::vector gt, es; + std::vector gt, es; cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); From cb5806164946379b77f328cbb7bf00959b194f6f Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 20:13:39 +0400 Subject: [PATCH 31/91] getViewerPose implementation simplified (and error seems to be fixed) --- modules/viz/src/vizimpl.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index cac58350b2..34f78c64c1 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -387,20 +387,7 @@ cv::Affine3d cv::viz::Viz3d::VizImpl::getViewerPose() Vec3d z_axis = normalized(focal - pos); Vec3d x_axis = normalized(y_axis.cross(z_axis)); - cv::Matx33d R; - R(0, 0) = x_axis[0]; - R(0, 1) = y_axis[0]; - R(0, 2) = z_axis[0]; - - R(1, 0) = x_axis[1]; - R(1, 1) = y_axis[1]; - R(1, 2) = z_axis[1]; - - R(2, 0) = x_axis[2]; - R(2, 1) = y_axis[2]; - R(2, 2) = z_axis[2]; - - return cv::Affine3d(R, pos); + return makeTransformToGlobal(x_axis, y_axis, z_axis, pos); } ///////////////////////////////////////////////////////////////////////////////////////////// From 70a81db5672b17f14ffdd461cf9f5f75cb55f751 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 20:51:04 +0400 Subject: [PATCH 32/91] fixed bugs in cloud collection and added test --- modules/viz/doc/viz3d.rst | 8 +- modules/viz/include/opencv2/viz/types.hpp | 2 +- modules/viz/src/clouds.cpp | 238 ++++------------------ modules/viz/src/types.cpp | 2 +- modules/viz/test/tests_simple.cpp | 15 ++ 5 files changed, 63 insertions(+), 202 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index ad1356e587..b57e04118d 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -482,19 +482,19 @@ This class wraps mesh attributes, and it can load a mesh from a ``ply`` file. :: Mat polygons; //! Loads mesh from a given ply file - static Mesh3d loadMesh(const String& file); + static Mesh3d load(const String& file); private: /* hidden */ }; -viz::Mesh3d::loadMesh +viz::Mesh3d::load --------------------- Loads a mesh from a ``ply`` file. -.. ocv:function:: static Mesh3d loadMesh(const String& file) +.. ocv:function:: static Mesh3d load(const String& file) - :param file: File name. + :param file: File name (for no only PLY is supported) viz::KeyboardEvent diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index ff6bd5a689..0a1fc14699 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -112,7 +112,7 @@ namespace cv Mat polygons; //! Loads mesh from a given ply file - static Mesh3d loadMesh(const String& file); + static Mesh3d load(const String& file); }; class CV_EXPORTS Camera diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 16f274cf2d..014f79921f 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -106,143 +106,6 @@ template<> cv::viz::WCloud cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// Cloud Collection Widget implementation -namespace cv { namespace viz { namespace -{ - struct CloudCollectionUtils - { - static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) - { - vtkSmartPointer polydata = vtkSmartPointer::New(); - vtkSmartPointer vertices = vtkSmartPointer::New(); - - polydata->SetVerts(vertices); - - vtkSmartPointer points = polydata->GetPoints(); - vtkSmartPointer initcells; - nr_points = cloud.total(); - - if (!points) - { - points = vtkSmartPointer::New(); - if (cloud.depth() == CV_32F) - points->SetDataTypeToFloat(); - else if (cloud.depth() == CV_64F) - points->SetDataTypeToDouble(); - polydata->SetPoints(points); - } - points->SetNumberOfPoints(nr_points); - - if (cloud.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - else if (cloud.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - points->SetNumberOfPoints(nr_points); - - // Update cells - vtkSmartPointer cells = vertices->GetData(); - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); - - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); - - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) - { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - else - { - // If the number of tuples is still too small, we need to recreate the array - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); - } - } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - - // Set the cells and the vertices - vertices->SetCells(nr_points, cells); - return polydata; - } - - static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data) - { - vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); - if (!mapper) - { - // This is the first cloud - vtkSmartPointer mapper_new = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper_new->SetInputConnection(poly_data->GetProducerPort()); -#else - mapper_new->SetInputData(poly_data); -#endif - - mapper_new->SetScalarRange(0, 255); - mapper_new->SetScalarModeToUsePointData(); - - bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); - - mapper_new->SetInterpolateScalarsBeforeMapping(interpolation); - mapper_new->ScalarVisibilityOn(); - mapper_new->ImmediateModeRenderingOff(); - - actor->SetNumberOfCloudPoints(int(std::max(1, poly_data->GetNumberOfPoints() / 10))); - actor->GetProperty()->SetInterpolationToFlat(); - actor->GetProperty()->BackfaceCullingOn(); - actor->SetMapper(mapper_new); - return ; - } - - vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); - CV_Assert("Cloud Widget without data" && data); - - vtkSmartPointer appendFilter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInputConnection(mapper->GetInput()->GetProducerPort()); - appendFilter->AddInputConnection(poly_data->GetProducerPort()); -#else - appendFilter->AddInputData(data); - appendFilter->AddInputData(poly_data); -#endif - mapper->SetInputConnection(appendFilter->GetOutputPort()); - - // Update the number of cloud points - vtkIdType old_cloud_points = actor->GetNumberOfCloudPoints(); - actor->SetNumberOfCloudPoints(int(std::max(1, old_cloud_points+poly_data->GetNumberOfPoints() / 10))); - } - }; -}}} - cv::viz::WCloudCollection::WCloudCollection() { // Just create the actor @@ -250,84 +113,67 @@ cv::viz::WCloudCollection::WCloudCollection() WidgetAccessor::setProp(*this, actor); } -void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, const Affine3d &pose) +void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, const Affine3d &pose) { - Mat cloud = _cloud.getMat(); - Mat colors = _colors.getMat(); - CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); - - vtkIdType nr_points; - vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); - - // Filter colors - Vec3b* colors_data = new Vec3b[nr_points]; - NanFilter::copyColor(colors, colors_data, cloud); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetColorCloud(cloud, colors); - vtkSmartPointer scalars = vtkSmartPointer::New(); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(nr_points); - scalars->SetArray(colors_data->val, 3 * nr_points, 0); - - // Assign the colors - polydata->GetPointData()->SetScalars(scalars); - - // Transform the poly data based on the pose vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->SetMatrix(convertToVtkMatrix(pose.matrix)); + transform->SetMatrix(pose.matrix.val); vtkSmartPointer transform_filter = vtkSmartPointer::New(); + transform_filter->SetInputConnection(source->GetOutputPort()); transform_filter->SetTransform(transform); -#if VTK_MAJOR_VERSION <= 5 - transform_filter->SetInputConnection(polydata->GetProducerPort()); -#else - transform_filter->SetInputData(polydata); -#endif transform_filter->Update(); - vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); + vtkSmartPointer actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); -} - -void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3d &pose) -{ - Mat cloud = _cloud.getMat(); - CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - - vtkIdType nr_points; - vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); + vtkSmartPointer poly_data = transform_filter->GetOutput(); - vtkSmartPointer scalars = vtkSmartPointer::New(); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(nr_points); - scalars->FillComponent(0, color[2]); - scalars->FillComponent(1, color[1]); - scalars->FillComponent(2, color[0]); + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); - // Assign the colors - polydata->GetPointData()->SetScalars(scalars); + if (!mapper) + { + // This is the first cloud + mapper = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 + mapper->SetInput(poly_data); +#else + mapper->SetInputData(poly_data); +#endif + mapper->SetScalarRange(0, 255); + mapper->SetScalarModeToUsePointData(); + mapper->ScalarVisibilityOn(); + mapper->ImmediateModeRenderingOff(); + + actor->SetNumberOfCloudPoints(std::max(1, poly_data->GetNumberOfPoints()/10)); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper); + return; + } - // Transform the poly data based on the pose - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->SetMatrix(convertToVtkMatrix(pose.matrix)); + vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); + CV_Assert("Cloud Widget without data" && data); - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); + vtkSmartPointer appendFilter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - transform_filter->SetInputConnection(polydata->GetProducerPort()); + appendFilter->AddInput(data); + appendFilter->AddInput(poly_data); + mapper->SetInput(appendFilter->GetOutput()); #else - transform_filter->SetInputData(polydata); + appendFilter->AddInputData(data); + appendFilter->AddInputData(poly_data); + mapper->SetInputData(appendFilter->GetOutput()); #endif - transform_filter->Update(); - vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); - CV_Assert("Incompatible widget type." && actor); + actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + poly_data->GetNumberOfPoints()/10)); +} - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); +void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, const Affine3d &pose) +{ + addCloud(cloud, Mat(cloud.size(), CV_8UC3, color), pose); } template<> cv::viz::WCloudCollection cv::viz::Widget::cast() diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 2c7f8e74be..63b9a0214d 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -128,7 +128,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::Mesh3d cv::viz::Mesh3d::loadMesh(const String& file) +cv::viz::Mesh3d cv::viz::Mesh3d::load(const String& file) { return MeshUtils::loadMesh(file); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 1a2e9fc94c..76e448da63 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -85,3 +85,18 @@ TEST(Viz, DISABLED_show_cloud_masked) viz.showWidget("dragon", WCloud(dragon_cloud)); viz.spin(); } + +TEST(Viz, DISABLED_show_cloud_collection) +{ + Mat cloud = readCloud(get_dragon_ply_file_path()); + + WCloudCollection ccol; + ccol.addCloud(cloud, Color::white(), Affine3d().translate(Vec3d(0, 0, 0)).rotate(Vec3d(1.57, 0, 0))); + ccol.addCloud(cloud, Color::blue(), Affine3d().translate(Vec3d(1, 0, 0))); + ccol.addCloud(cloud, Color::red(), Affine3d().translate(Vec3d(2, 0, 0))); + + Viz3d viz("show_cloud_collection"); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("ccol", ccol); + viz.spin(); +} From baee8c3aa58fb88ec25b231ac41c65df122531f1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 22:36:08 +0400 Subject: [PATCH 33/91] refactored Mesh, added tests, added failing "twice spin()" test --- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/clouds.cpp | 192 ++++++-------------- modules/viz/src/vtk/vtkCloudMatSource.cpp | 6 +- modules/viz/test/tests_simple.cpp | 34 ++++ 4 files changed, 98 insertions(+), 138 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 28a2acb0de..27f211cd63 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -65,14 +65,14 @@ namespace cv SHADING }; - enum RenderingRepresentationProperties + enum RepresentationValues { REPRESENTATION_POINTS, REPRESENTATION_WIREFRAME, REPRESENTATION_SURFACE }; - enum ShadingRepresentationProperties + enum ShadingValues { SHADING_FLAT, SHADING_GOURAUD, diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 014f79921f..2247dffe91 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -126,49 +126,47 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co transform_filter->SetTransform(transform); transform_filter->Update(); + vtkSmartPointer polydata = transform_filter->GetOutput(); vtkSmartPointer actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - vtkSmartPointer poly_data = transform_filter->GetOutput(); - vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); - if (!mapper) { // This is the first cloud mapper = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(poly_data); + mapper->SetInput(polydata); #else - mapper->SetInputData(poly_data); + mapper->SetInputData(polydata); #endif mapper->SetScalarRange(0, 255); mapper->SetScalarModeToUsePointData(); mapper->ScalarVisibilityOn(); mapper->ImmediateModeRenderingOff(); - actor->SetNumberOfCloudPoints(std::max(1, poly_data->GetNumberOfPoints()/10)); + actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); actor->SetMapper(mapper); return; } - vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); - CV_Assert("Cloud Widget without data" && data); + vtkPolyData *currdata = vtkPolyData::SafeDownCast(mapper->GetInput()); + CV_Assert("Cloud Widget without data" && currdata); vtkSmartPointer appendFilter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInput(data); - appendFilter->AddInput(poly_data); + appendFilter->AddInput(currdata); + appendFilter->AddInput(polydata); mapper->SetInput(appendFilter->GetOutput()); #else - appendFilter->AddInputData(data); - appendFilter->AddInputData(poly_data); + appendFilter->AddInputData(currdata); + appendFilter->AddInputData(polydata); mapper->SetInputData(appendFilter->GetOutput()); #endif - actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + poly_data->GetNumberOfPoints()/10)); + actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); } void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, const Affine3d &pose) @@ -328,150 +326,78 @@ template<> cv::viz::WCloudNormals cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// Mesh Widget implementation -namespace cv { namespace viz { namespace -{ - struct MeshUtils - { - template - static Vec<_Tp, 3> * copy(const Mat &source, Vec<_Tp, 3> *output, int *look_up, const Mat &nan_mask) - { - CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); - CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); - CV_DbgAssert(DataDepth<_Tp>::value == nan_mask.depth()); - - int s_chs = source.channels(); - int m_chs = nan_mask.channels(); - - int index = 0; - const _Tp* srow = source.ptr<_Tp>(0); - const _Tp* mrow = nan_mask.ptr<_Tp>(0); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) - { - if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - { - look_up[x] = index; - *output++ = Vec<_Tp, 3>(srow); - ++index; - } - } - return output; - } - }; -}}} - cv::viz::WMesh::WMesh(const Mesh3d &mesh) { - CV_Assert(mesh.cloud.rows == 1 && (mesh.cloud.type() == CV_32FC3 || mesh.cloud.type() == CV_64FC3 || mesh.cloud.type() == CV_32FC4 || mesh.cloud.type() == CV_64FC4)); - CV_Assert(mesh.colors.empty() || (mesh.colors.depth() == CV_8U && mesh.cloud.size() == mesh.colors.size())); - CV_Assert(!mesh.polygons.empty() && mesh.polygons.type() == CV_32SC1); - - vtkSmartPointer points = vtkSmartPointer::New(); - vtkIdType nr_points = mesh.cloud.total(); - Mat look_up_mat(1, nr_points, CV_32SC1); - int * look_up = look_up_mat.ptr(); - points->SetNumberOfPoints(nr_points); - - // Copy data from cloud to vtkPoints - if (mesh.cloud.depth() == CV_32F) - { - points->SetDataTypeToFloat(); - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = MeshUtils::copy(mesh.cloud, data_beg, look_up, mesh.cloud); - nr_points = data_end - data_beg; - } - else - { - points->SetDataTypeToDouble(); - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = MeshUtils::copy(mesh.cloud, data_beg, look_up, mesh.cloud); - nr_points = data_end - data_beg; - } + CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1); - vtkSmartPointer scalars; - - if (!mesh.colors.empty()) - { - Vec3b *colors_data = new Vec3b[nr_points]; - NanFilter::copyColor(mesh.colors, colors_data, mesh.cloud); - - scalars = vtkSmartPointer::New(); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(nr_points); - scalars->SetArray(colors_data->val, 3 * nr_points, 0); - } - - points->SetNumberOfPoints(nr_points); - - vtkSmartPointer data; + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetColorCloud(mesh.cloud, mesh.colors); + source->Update(); - if (mesh.polygons.size().area() > 1) + Mat lookup_buffer(1, mesh.cloud.total(), CV_32SC1); + int *lookup = lookup_buffer.ptr(); + for(int y = 0, index = 0; y < mesh.cloud.rows; ++y) { - vtkSmartPointer cell_array = vtkSmartPointer::New(); - const int * polygons = mesh.polygons.ptr(); + int s_chs = mesh.cloud.channels(); - int idx = 0; - int poly_size = mesh.polygons.total(); - for (int i = 0; i < poly_size; ++idx) + if (mesh.cloud.depth() == CV_32F) { - int n_points = polygons[i++]; + const float* srow = mesh.cloud.ptr(y); + const float* send = srow + mesh.cloud.cols * s_chs; - cell_array->InsertNextCell(n_points); - for (int j = 0; j < n_points; ++j, ++idx) - cell_array->InsertCellPoint(look_up[polygons[i++]]); + for (; srow != send; srow += s_chs, ++lookup) + if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + *lookup = index++; } - vtkSmartPointer polydata = vtkSmartPointer::New(); - cell_array->GetData()->SetNumberOfValues(idx); - cell_array->Squeeze(); - polydata->SetStrips(cell_array); - polydata->SetPoints(points); - if (scalars) - polydata->GetPointData()->SetScalars(scalars); + if (mesh.cloud.depth() == CV_64F) + { + const double* srow = mesh.cloud.ptr(y); + const double* send = srow + mesh.cloud.cols * s_chs; - data = polydata; + for (; srow != send; srow += s_chs, ++lookup) + if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + *lookup = index++; + } } - else - { - // Only one polygon - vtkSmartPointer polygon = vtkSmartPointer::New(); - const int * polygons = mesh.polygons.ptr(); - int n_points = polygons[0]; + lookup = lookup_buffer.ptr(); - polygon->GetPointIds()->SetNumberOfIds(n_points); + vtkSmartPointer polydata = source->GetOutput(); + polydata->SetVerts(0); - for (int j = 1; j < n_points+1; ++j) - polygon->GetPointIds()->SetId(j, look_up[polygons[j]]); + const int * polygons = mesh.polygons.ptr(); + vtkSmartPointer cell_array = vtkSmartPointer::New(); - vtkSmartPointer poly_grid = vtkSmartPointer::New(); - poly_grid->Allocate(1, 1); - poly_grid->InsertNextCell(polygon->GetCellType(), polygon->GetPointIds()); - poly_grid->SetPoints(points); - - if (scalars) - poly_grid->GetPointData()->SetScalars(scalars); + int idx = 0; + int poly_size = mesh.polygons.total(); + for (int i = 0; i < poly_size; ++idx) + { + int n_points = polygons[i++]; - data = poly_grid; + cell_array->InsertNextCell(n_points); + for (int j = 0; j < n_points; ++j, ++idx) + cell_array->InsertCellPoint(lookup[polygons[i++]]); } + cell_array->GetData()->SetNumberOfValues(idx); + cell_array->Squeeze(); + polydata->SetStrips(cell_array); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetScalarModeToUsePointData(); + mapper->ImmediateModeRenderingOff(); +#if VTK_MAJOR_VERSION <= 5 + mapper->SetInput(polydata); +#else + mapper->SetInputData(polydata); +#endif + vtkSmartPointer actor = vtkSmartPointer::New(); + //actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints() / 10)); actor->GetProperty()->SetRepresentationToSurface(); actor->GetProperty()->BackfaceCullingOff(); // Backface culling is off for higher efficiency actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->EdgeVisibilityOff(); actor->GetProperty()->ShadingOff(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(data); -#else - mapper->SetInputData(data); -#endif - mapper->ImmediateModeRenderingOff(); - - vtkIdType numberOfCloudPoints = nr_points * 0.1; - actor->SetNumberOfCloudPoints(int(numberOfCloudPoints > 1 ? numberOfCloudPoints : 1)); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 46603a7b90..cf3d21e6dd 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -163,14 +163,14 @@ int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& cloud) points->Allocate(cloud.total()); points->SetNumberOfPoints(cloud.total()); - int cn = cloud.channels(); + int s_chs = cloud.channels(); int total = 0; for (int y = 0; y < cloud.rows; ++y) { const _Tp* srow = cloud.ptr<_Tp>(y); - const _Tp* send = srow + cloud.cols * cn; + const _Tp* send = srow + cloud.cols * s_chs; - for (; srow != send; srow += cn) + for (; srow != send; srow += s_chs) if (!isNan(srow)) points->SetPoint(total++, srow); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 76e448da63..ece1370d57 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -100,3 +100,37 @@ TEST(Viz, DISABLED_show_cloud_collection) viz.showWidget("ccol", ccol); viz.spin(); } + +TEST(Viz, DISABLED_show_mesh) +{ + Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + + Viz3d viz("show_mesh"); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("mesh", WMesh(mesh)); + viz.spin(); +} + +TEST(Viz, DISABLED_show_mesh_random_colors) +{ + Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); + + Viz3d viz("show_mesh_random_color"); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("mesh", WMesh(mesh)); + viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); + viz.spin(); +} + +TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) +{ + Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + + Viz3d viz("spin_twice"); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("mesh", WMesh(mesh)); + viz.spin(); + viz.spin(); +} + From 3e071491c93e22c7bd5bead117fae196738ba759 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 2 Jan 2014 16:10:08 +0400 Subject: [PATCH 34/91] added Affine3 ctor from array --- modules/core/include/opencv2/core/affine.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index b4e7472a9f..55b3f8fb0c 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -73,6 +73,9 @@ namespace cv //Combines all contructors above. Supports 4x4, 3x3, 1x3, 3x1 sizes of data matrix explicit Affine3(const cv::Mat& data, const Vec3& t = Vec3::all(0)); + //From 16th element array + Affine3(const float_type* vals); + static Affine3 Identity(); //Rotation matrix @@ -183,6 +186,10 @@ cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) matrix.val[15] = 1; } +template inline +cv::Affine3::Affine3(const float_type* vals) : matrix(vals) +{} + template inline cv::Affine3 cv::Affine3::Identity() { From a76a34d28e9e0cb6b15c419181dccee77078d6fb Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 2 Jan 2014 16:16:29 +0400 Subject: [PATCH 35/91] added Affine3: 3x4 input Mat support --- modules/core/include/opencv2/core/affine.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 55b3f8fb0c..3f072e78f6 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -179,6 +179,12 @@ cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) data.copyTo(matrix); return; } + else if (data.cols == 4 && data.rows == 3) + { + rotation(data(Rect(0, 0, 3, 3))); + translation(data(Rect(3, 0, 1, 3))); + return; + } rotation(data); translation(t); From b7cb3fe8e0a3cd210ed47b9d09ab53fed0c5cb8c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 2 Jan 2014 16:33:47 +0400 Subject: [PATCH 36/91] switched more to doubles --- modules/viz/doc/viz3d.rst | 34 ++++----- modules/viz/include/opencv2/viz/types.hpp | 26 +++---- modules/viz/src/interactor_style.cpp | 2 +- modules/viz/src/shapes.cpp | 2 +- modules/viz/src/types.cpp | 40 +++++----- modules/viz/src/vizcore.cpp | 18 ----- modules/viz/src/vizimpl.cpp | 36 +++++---- modules/viz/src/vizimpl.hpp | 89 ++--------------------- modules/viz/src/widget.cpp | 8 +- modules/viz/test/tests_simple.cpp | 3 - 10 files changed, 80 insertions(+), 178 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index b57e04118d..1cb9b5dc3b 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -571,24 +571,24 @@ that can extract the intrinsic parameters from ``field of view``, ``intrinsic ma class CV_EXPORTS Camera { public: - Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size); - Camera(const Vec2f &fov, const Size &window_size); - Camera(const cv::Matx33f &K, const Size &window_size); - Camera(const cv::Matx44f &proj, const Size &window_size); + Camera(double f_x, double f_y, double c_x, double c_y, const Size &window_size); + Camera(const Vec2d &fov, const Size &window_size); + Camera(const Matx33d &K, const Size &window_size); + Camera(const Matx44d &proj, const Size &window_size); - inline const Vec2d & getClip() const { return clip_; } - inline void setClip(const Vec2d &clip) { clip_ = clip; } + inline const Vec2d & getClip() const; + inline void setClip(const Vec2d &clip); - inline const Size & getWindowSize() const { return window_size_; } + inline const Size & getWindowSize() const; void setWindowSize(const Size &window_size); - inline const Vec2f & getFov() const { return fov_; } - inline void setFov(const Vec2f & fov) { fov_ = fov; } + inline const Vec2d & getFov() const; + inline void setFov(const Vec2d & fov); - inline const Vec2f & getPrincipalPoint() const { return principal_point_; } - inline const Vec2f & getFocalLength() const { return focal_; } + inline const Vec2d & getPrincipalPoint() const; + inline const Vec2d & getFocalLength() const; - void computeProjectionMatrix(Matx44f &proj) const; + void computeProjectionMatrix(Matx44d &proj) const; static Camera KinectCamera(const Size &window_size); @@ -600,7 +600,7 @@ viz::Camera::Camera ------------------- Constructs a Camera. -.. ocv:function:: Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size) +.. ocv:function:: Camera(double f_x, double f_y, double c_x, double c_y, const Size &window_size) :param f_x: Horizontal focal length. :param f_y: Vertical focal length. @@ -608,19 +608,19 @@ Constructs a Camera. :param c_y: y coordinate of the principal point. :param window_size: Size of the window. This together with focal length and principal point determines the field of view. -.. ocv:function:: Camera(const Vec2f &fov, const Size &window_size) +.. ocv:function:: Camera(const Vec2d &fov, const Size &window_size) :param fov: Field of view (horizontal, vertical) :param window_size: Size of the window. Principal point is at the center of the window by default. -.. ocv:function:: Camera(const cv::Matx33f &K, const Size &window_size) +.. ocv:function:: Camera(const Matx33d &K, const Size &window_size) :param K: Intrinsic matrix of the camera. :param window_size: Size of the window. This together with intrinsic matrix determines the field of view. -.. ocv:function:: Camera(const cv::Matx44f &proj, const Size &window_size) +.. ocv:function:: Camera(const Matx44d &proj, const Size &window_size) :param proj: Projection matrix of the camera. :param window_size: Size of the window. This together with projection matrix determines the field of view. @@ -629,7 +629,7 @@ viz::Camera::computeProjectionMatrix ------------------------------------ Computes projection matrix using intrinsic parameters of the camera. -.. ocv:function:: void computeProjectionMatrix(Matx44f &proj) const +.. ocv:function:: void computeProjectionMatrix(Matx44d &proj) const :param proj: Output projection matrix. diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 0a1fc14699..8393550f88 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -118,10 +118,10 @@ namespace cv class CV_EXPORTS Camera { public: - Camera(float fx, float fy, float cx, float cy, const Size &window_size); - explicit Camera(const Vec2f &fov, const Size &window_size); - explicit Camera(const Matx33f &K, const Size &window_size); - explicit Camera(const Matx44f &proj, const Size &window_size); + Camera(double fx, double fy, double cx, double cy, const Size &window_size); + explicit Camera(const Vec2d &fov, const Size &window_size); + explicit Camera(const Matx33d &K, const Size &window_size); + explicit Camera(const Matx44d &proj, const Size &window_size); inline const Vec2d & getClip() const { return clip_; } inline void setClip(const Vec2d &clip) { clip_ = clip; } @@ -129,24 +129,24 @@ namespace cv inline const Size & getWindowSize() const { return window_size_; } void setWindowSize(const Size &window_size); - inline const Vec2f & getFov() const { return fov_; } - inline void setFov(const Vec2f & fov) { fov_ = fov; } + inline const Vec2d& getFov() const { return fov_; } + inline void setFov(const Vec2d& fov) { fov_ = fov; } - inline const Vec2f & getPrincipalPoint() const { return principal_point_; } - inline const Vec2f & getFocalLength() const { return focal_; } + inline const Vec2d& getPrincipalPoint() const { return principal_point_; } + inline const Vec2d& getFocalLength() const { return focal_; } - void computeProjectionMatrix(Matx44f &proj) const; + void computeProjectionMatrix(Matx44d &proj) const; static Camera KinectCamera(const Size &window_size); private: - void init(float fx, float fy, float cx, float cy, const Size &window_size); + void init(double fx, double fy, double cx, double cy, const Size &window_size); Vec2d clip_; - Vec2f fov_; + Vec2d fov_; Size window_size_; - Vec2f principal_point_; - Vec2f focal_; + Vec2d principal_point_; + Vec2d focal_; }; class CV_EXPORTS KeyboardEvent diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 4126d8c359..19a3476a88 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -469,7 +469,7 @@ void cv::viz::InteractorStyle::OnKeyDown() // if a valid transformation was found, use it otherwise fall back to default view point. if (found_transformation) { - const vtkMatrix4x4* m = vtkProp3D::SafeDownCast(it->second)->GetUserMatrix(); + vtkMatrix4x4* m = vtkProp3D::SafeDownCast(it->second)->GetUserMatrix(); cam->SetFocalPoint(m->GetElement(0, 3) - m->GetElement(0, 2), m->GetElement(1, 3) - m->GetElement(1, 2), diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 7da4063f70..fa6662862a 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1195,7 +1195,7 @@ namespace cv { namespace viz { namespace vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans = convertToVtkMatrix(path[i].matrix); + mat_trans = vtkmatrix(path[i].matrix); transform->SetMatrix(mat_trans); vtkSmartPointer filter = vtkSmartPointer::New(); diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 63b9a0214d..a6ea95ab5f 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -136,12 +136,12 @@ cv::viz::Mesh3d cv::viz::Mesh3d::load(const String& file) //////////////////////////////////////////////////////////////////// /// Camera implementation -cv::viz::Camera::Camera(float fx, float fy, float cx, float cy, const Size &window_size) +cv::viz::Camera::Camera(double fx, double fy, double cx, double cy, const Size &window_size) { init(fx, fy, cx, cy, window_size); } -cv::viz::Camera::Camera(const Vec2f &fov, const Size &window_size) +cv::viz::Camera::Camera(const Vec2d &fov, const Size &window_size) { CV_Assert(window_size.width > 0 && window_size.height > 0); setClip(Vec2d(0.01, 1000.01)); // Default clipping @@ -152,16 +152,16 @@ cv::viz::Camera::Camera(const Vec2f &fov, const Size &window_size) 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) +cv::viz::Camera::Camera(const cv::Matx33d & K, const Size &window_size) { - float f_x = K(0,0); - float f_y = K(1,1); - float c_x = K(0,2); - float c_y = K(1,2); + double f_x = K(0,0); + double f_y = K(1,1); + double c_x = K(0,2); + double c_y = K(1,2); init(f_x, f_y, c_x, c_y, window_size); } -cv::viz::Camera::Camera(const Matx44f &proj, const Size &window_size) +cv::viz::Camera::Camera(const Matx44d &proj, const Size &window_size) { CV_Assert(window_size.width > 0 && window_size.height > 0); @@ -174,28 +174,26 @@ cv::viz::Camera::Camera(const Matx44f &proj, const Size &window_size) double epsilon = 2.2204460492503131e-16; - if (fabs(left-right) < epsilon) principal_point_[0] = static_cast(window_size.width) * 0.5f; - else principal_point_[0] = (left * static_cast(window_size.width)) / (left - right); - focal_[0] = -near * principal_point_[0] / left; + principal_point_[0] = fabs(left-right) < epsilon ? window_size.width * 0.5 : (left * window_size.width) / (left - right); + principal_point_[1] = fabs(top-bottom) < epsilon ? window_size.height * 0.5 : (top * window_size.height) / (top - bottom); - if (fabs(top-bottom) < epsilon) principal_point_[1] = static_cast(window_size.height) * 0.5f; - else principal_point_[1] = (top * static_cast(window_size.height)) / (top - bottom); - focal_[1] = near * principal_point_[1] / top; + focal_[0] = -near * principal_point_[0] / left; + focal_[1] = near * principal_point_[1] / top; setClip(Vec2d(near, far)); - 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])); + 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]); window_size_ = window_size; } -void cv::viz::Camera::init(float fx, float fy, float cx, float cy, const Size &window_size) +void cv::viz::Camera::init(double fx, double fy, double cx, double cy, const Size &window_size) { CV_Assert(window_size.width > 0 && window_size.height > 0); setClip(Vec2d(0.01, 1000.01));// Default clipping - fov_[0] = (atan2(cx,fx) + atan2(window_size.width-cx,fx)); - fov_[1] = (atan2(cy,fy) + atan2(window_size.height-cy,fy)); + fov_[0] = atan2(cx, fx) + atan2(window_size.width - cx, fx); + fov_[1] = atan2(cy, fy) + atan2(window_size.height - cy, fy); principal_point_[0] = cx; principal_point_[1] = cy; @@ -223,7 +221,7 @@ void cv::viz::Camera::setWindowSize(const Size &window_size) window_size_ = window_size; } -void cv::viz::Camera::computeProjectionMatrix(Matx44f &proj) const +void cv::viz::Camera::computeProjectionMatrix(Matx44d &proj) const { double top = clip_[0] * principal_point_[1] / focal_[1]; double left = -clip_[0] * principal_point_[0] / focal_[0]; @@ -247,6 +245,6 @@ void cv::viz::Camera::computeProjectionMatrix(Matx44f &proj) const cv::viz::Camera cv::viz::Camera::KinectCamera(const Size &window_size) { - Matx33f K(525.f, 0.f, 320.f, 0.f, 525.f, 240.f, 0.f, 0.f, 1.f) ; + Matx33d K(525.0, 0.0, 320.0, 0.0, 525.0, 240.0, 0.0, 0.0, 1.0) ; return Camera(K, window_size); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index c26b04301e..39f34b35d4 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -64,24 +64,6 @@ cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_p return makeTransformToGlobal(u, v, n, position); } -vtkSmartPointer cv::viz::convertToVtkMatrix(const cv::Matx44f &m) -{ - vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - vtk_matrix->SetElement(i, k, m(i, k)); - return vtk_matrix; -} - -cv::Matx44f cv::viz::convertToMatx(const vtkSmartPointer& vtk_matrix) -{ - cv::Matx44f m; - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - m(i, k) = vtk_matrix->GetElement(i, k); - return m; -} - namespace cv { namespace viz { template Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer& points); diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 34f78c64c1..4b9d65b43e 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -134,7 +134,7 @@ void cv::viz::Viz3d::VizImpl::showWidget(const String &id, const Widget &widget, if (actor) { // If the actor is 3D, apply pose - vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); + vtkSmartPointer matrix = vtkmatrix(pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); } @@ -181,7 +181,7 @@ void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3d &po vtkProp3D *actor = vtkProp3D::SafeDownCast(wam_itr->second); CV_Assert("Widget is not 3D." && actor); - vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); + vtkSmartPointer matrix = vtkmatrix(pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); } @@ -202,9 +202,8 @@ void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3d setWidgetPose(id, pose); return ; } - Matx44d matrix_cv = convertToMatx(matrix); - Affine3d updated_pose = pose * Affine3d(matrix_cv); - matrix = convertToVtkMatrix(updated_pose.matrix); + Affine3d updated_pose = pose * Affine3d(*matrix->Element); + matrix = vtkmatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); @@ -220,9 +219,7 @@ cv::Affine3d cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const vtkProp3D *actor = vtkProp3D::SafeDownCast(wam_itr->second); CV_Assert("Widget is not 3D." && actor); - vtkSmartPointer matrix = actor->GetUserMatrix(); - Matx44d matrix_cv = convertToMatx(matrix); - return Affine3d(matrix_cv); + return Affine3d(*actor->GetUserMatrix()->Element); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -315,21 +312,23 @@ void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera) { - vtkCamera& active_camera = *renderer_->GetActiveCamera(); + vtkSmartPointer active_camera = renderer_->GetActiveCamera(); // Set the intrinsic parameters of the camera window_->SetSize(camera.getWindowSize().width, camera.getWindowSize().height); double aspect_ratio = static_cast(camera.getWindowSize().width)/static_cast(camera.getWindowSize().height); - Matx44f proj_mat; + Matx44d proj_mat; camera.computeProjectionMatrix(proj_mat); + // Use the intrinsic parameters of the camera to simulate more realistically - Matx44f old_proj_mat = convertToMatx(active_camera.GetProjectionTransformMatrix(aspect_ratio, -1.0, 1.0)); - vtkTransform *transform = vtkTransform::New(); + vtkSmartPointer vtk_matrix = active_camera->GetProjectionTransformMatrix(aspect_ratio, -1.0, 1.0); + Matx44d old_proj_mat(*vtk_matrix->Element); + // This is a hack around not being able to set Projection Matrix - transform->SetMatrix(convertToVtkMatrix(proj_mat * old_proj_mat.inv())); - active_camera.SetUserTransform(transform); - transform->Delete(); + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetMatrix(vtkmatrix(proj_mat * old_proj_mat.inv())); + active_camera->SetUserTransform(transform); renderer_->ResetCameraClippingRange(); renderer_->Render(); @@ -338,15 +337,14 @@ void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera) ///////////////////////////////////////////////////////////////////////////////////////////// cv::viz::Camera cv::viz::Viz3d::VizImpl::getCamera() const { - vtkCamera& active_camera = *renderer_->GetActiveCamera(); + vtkSmartPointer active_camera = renderer_->GetActiveCamera(); Size window_size(renderer_->GetRenderWindow()->GetSize()[0], renderer_->GetRenderWindow()->GetSize()[1]); double aspect_ratio = window_size.width / (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; + vtkSmartPointer proj_matrix = active_camera->GetProjectionTransformMatrix(aspect_ratio, -1.0f, 1.0f); + return Camera(Matx44d(*proj_matrix->Element), window_size); } ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 0cfb403095..d5274b49ce 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -180,19 +180,22 @@ private: }; - namespace cv { namespace viz { - vtkSmartPointer convertToVtkMatrix(const cv::Matx44f &m); - cv::Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix); + inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) + { + vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); + vtk_matrix->DeepCopy(matrix.val); + return vtk_matrix; + } struct color_tag {}; struct gray_tag {}; - static Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } - static Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } + inline Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } + inline Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } template inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } @@ -204,82 +207,6 @@ namespace cv return scaled_color; } - struct NanFilter - { - template - struct Impl - { - template - static Vec<_Tp, 3>* copy(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) - { - CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); - CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); - CV_DbgAssert(DataDepth<_Msk>::value == nan_mask.depth()); - - int s_chs = source.channels(); - int m_chs = nan_mask.channels(); - - for (int y = 0; y < source.rows; ++y) - { - const _Tp* srow = source.ptr<_Tp>(y); - const _Msk* mrow = nan_mask.ptr<_Msk>(y); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) - if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - *output++ = Vec<_Tp, 3>(srow); - } - return output; - } - - template - static Vec3b* copyColor(const Mat& source, Vec3b* output, const Mat& nan_mask) - { - CV_Assert(source.size() == nan_mask.size()); - CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); - CV_DbgAssert(DataDepth<_Msk>::value == nan_mask.depth()); - - int s_chs = source.channels(); - int m_chs = nan_mask.channels(); - - for (int y = 0; y < source.rows; ++y) - { - const unsigned char* srow = source.ptr(y); - const _Msk* mrow = nan_mask.ptr<_Msk>(y); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) - if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - *output++ = fetchRgb(srow, _Tag()); - } - return output; - } - }; - - template - static inline Vec<_Tp, 3>* copy(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) - { - CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); - - typedef Vec<_Tp, 3>* (*copy_func)(const Mat&, Vec<_Tp, 3>*, const Mat&); - const static copy_func table[2] = { &NanFilter::Impl::copy<_Tp>, &NanFilter::Impl::copy<_Tp> }; - - return table[nan_mask.depth() - 5](source, output, nan_mask); - } - - static inline Vec3b* copyColor(const Mat& source, Vec3b* output, const Mat& nan_mask) - { - CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); - - typedef Vec3b* (*copy_func)(const Mat&, Vec3b*, const Mat&); - const static copy_func table[2][2] = - { - { &NanFilter::Impl::copyColor, &NanFilter::Impl ::copyColor }, - { &NanFilter::Impl::copyColor, &NanFilter::Impl::copyColor } - }; - - return table[nan_mask.depth() - 5][source.channels() == 1 ? 0 : 1](source, output, nan_mask); - } - }; - struct ConvertToVtkImage { struct Impl diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 839ea20146..23099ba728 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -244,7 +244,7 @@ void cv::viz::Widget3D::setPose(const Affine3d &pose) vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); - vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); + vtkSmartPointer matrix = vtkmatrix(pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); } @@ -261,8 +261,8 @@ void cv::viz::Widget3D::updatePose(const Affine3d &pose) return; } - Affine3d updated_pose = pose * Affine3d(convertToMatx(matrix)); - matrix = convertToVtkMatrix(updated_pose.matrix); + Affine3d updated_pose = pose * Affine3d(*matrix->Element); + matrix = vtkmatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); @@ -272,7 +272,7 @@ cv::Affine3d cv::viz::Widget3D::getPose() const { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); - return Affine3d(convertToMatx(actor->GetUserMatrix())); + return Affine3d(*actor->GetUserMatrix()->Element); } void cv::viz::Widget3D::setColor(const Color &color) diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ece1370d57..9f76bb2a2f 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -50,7 +50,6 @@ TEST(Viz, DISABLED_show_cloud_bluberry) Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); Viz3d viz("show_cloud_bluberry"); - viz.setBackgroundColor(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry())); viz.spin(); @@ -64,7 +63,6 @@ TEST(Viz, DISABLED_show_cloud_random_color) theRNG().fill(colors, RNG::UNIFORM, 0, 255); Viz3d viz("show_cloud_random_color"); - viz.setBackgroundColor(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, colors)); viz.spin(); @@ -80,7 +78,6 @@ TEST(Viz, DISABLED_show_cloud_masked) dragon_cloud.at(i) = qnan; Viz3d viz("show_cloud_masked"); - viz.setBackgroundColor(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud)); viz.spin(); From cd57c4e189cb70318875534dadae1dcf10a35e89 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 10:53:04 +0400 Subject: [PATCH 37/91] refactored CloudNormals and added test for it --- modules/viz/include/opencv2/viz/types.hpp | 2 +- modules/viz/src/clouds.cpp | 157 +++++++--------------- modules/viz/src/precomp.hpp | 5 + modules/viz/src/vtk/vtkCloudMatSink.cpp | 4 +- modules/viz/src/vtk/vtkCloudMatSource.cpp | 7 +- modules/viz/test/tests_simple.cpp | 15 ++- 6 files changed, 72 insertions(+), 118 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 8393550f88..1e222c8004 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -108,7 +108,7 @@ namespace cv { public: - Mat cloud, colors; + Mat cloud, colors, normals; Mat polygons; //! Loads mesh from a given ply file diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 2247dffe91..3c28624f31 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -45,14 +45,6 @@ #include "precomp.hpp" -namespace cv -{ - namespace viz - { - template Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer& points); - } -} - /////////////////////////////////////////////////////////////////////////////////////////////// /// Point Cloud Widget implementation @@ -183,119 +175,67 @@ template<> cv::viz::WCloudCollection cv::viz::Widget::cast - struct Impl - { - static vtkSmartPointer applyOrganized(const Mat &cloud, const Mat& normals, double level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - vtkIdType point_step = static_cast(std::sqrt(level)); - nr_normals = (static_cast((cloud.cols - 1) / point_step) + 1) * - (static_cast((cloud.rows - 1) / point_step) + 1); - vtkSmartPointer lines = vtkSmartPointer::New(); - - pts = new _Tp[2 * nr_normals * 3]; - - int cch = cloud.channels(); - vtkIdType cell_count = 0; - for (vtkIdType y = 0; y < cloud.rows; y += point_step) - { - const _Tp *prow = cloud.ptr<_Tp>(y); - const _Tp *nrow = normals.ptr<_Tp>(y); - for (vtkIdType x = 0; x < cloud.cols; x += point_step * cch) - { - pts[2 * cell_count * 3 + 0] = prow[x]; - pts[2 * cell_count * 3 + 1] = prow[x+1]; - pts[2 * cell_count * 3 + 2] = prow[x+2]; - pts[2 * cell_count * 3 + 3] = prow[x] + nrow[x] * scale; - pts[2 * cell_count * 3 + 4] = prow[x+1] + nrow[x+1] * scale; - pts[2 * cell_count * 3 + 5] = prow[x+2] + nrow[x+2] * scale; - - lines->InsertNextCell(2); - lines->InsertCellPoint(2 * cell_count); - lines->InsertCellPoint(2 * cell_count + 1); - cell_count++; - } - } - return lines; - } - - static vtkSmartPointer applyUnorganized(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - vtkSmartPointer lines = vtkSmartPointer::New(); - nr_normals = (cloud.size().area() - 1) / level + 1 ; - pts = new _Tp[2 * nr_normals * 3]; - - int cch = cloud.channels(); - const _Tp *p = cloud.ptr<_Tp>(); - const _Tp *n = normals.ptr<_Tp>(); - for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level * cch) - { - - pts[2 * j * 3 + 0] = p[i]; - pts[2 * j * 3 + 1] = p[i+1]; - pts[2 * j * 3 + 2] = p[i+2]; - pts[2 * j * 3 + 3] = p[i] + n[i] * scale; - pts[2 * j * 3 + 4] = p[i+1] + n[i+1] * scale; - pts[2 * j * 3 + 5] = p[i+2] + n[i+2] * scale; - - lines->InsertNextCell(2); - lines->InsertCellPoint(2 * j); - lines->InsertCellPoint(2 * j + 1); - } - return lines; - } - }; - - template - static inline vtkSmartPointer apply(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - if (cloud.cols > 1 && cloud.rows > 1) - return CloudNormalsUtils::Impl<_Tp>::applyOrganized(cloud, normals, level, scale, pts, nr_normals); - else - return CloudNormalsUtils::Impl<_Tp>::applyUnorganized(cloud, normals, level, scale, pts, nr_normals); - } - }; - -}}} - cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, int level, float scale, const Color &color) { Mat cloud = _cloud.getMat(); Mat normals = _normals.getMat(); + CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); CV_Assert(cloud.size() == normals.size() && cloud.type() == normals.type()); + int sqlevel = (int)std::sqrt((double)level); + int ystep = (cloud.cols > 1 && cloud.rows > 1) ? sqlevel : 1; + int xstep = (cloud.cols > 1 && cloud.rows > 1) ? sqlevel : level; + vtkSmartPointer points = vtkSmartPointer::New(); + points->SetDataType(cloud.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE); + vtkSmartPointer lines = vtkSmartPointer::New(); - vtkIdType nr_normals = 0; - if (cloud.depth() == CV_32F) + int s_chs = cloud.channels(); + int n_chs = normals.channels(); + int total = 0; + + for(int y = 0; y < cloud.rows; y += ystep) { - points->SetDataTypeToFloat(); + if (cloud.depth() == CV_32F) + { + const float *srow = cloud.ptr(y); + const float *send = srow + cloud.cols * s_chs; + const float *nrow = normals.ptr(y); - vtkSmartPointer data = vtkSmartPointer::New(); - data->SetNumberOfComponents(3); + for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs) + if (!isNan(srow) && !isNan(nrow)) + { + Vec3f endp = Vec3f(srow) + Vec3f(nrow) * scale; - float* pts = 0; - lines = CloudNormalsUtils::apply(cloud, normals, level, scale, pts, nr_normals); - data->SetArray(&pts[0], 2 * nr_normals * 3, 0); - points->SetData(data); - } - else - { - points->SetDataTypeToDouble(); + points->InsertNextPoint(srow); + points->InsertNextPoint(endp.val); - vtkSmartPointer data = vtkSmartPointer::New(); - data->SetNumberOfComponents(3); + lines->InsertNextCell(2); + lines->InsertCellPoint(total++); + lines->InsertCellPoint(total++); + } + } + else + { + const double *srow = cloud.ptr(y); + const double *send = srow + cloud.cols * s_chs; + const double *nrow = normals.ptr(y); - double* pts = 0; - lines = CloudNormalsUtils::apply(cloud, normals, level, scale, pts, nr_normals); - data->SetArray(&pts[0], 2 * nr_normals * 3, 0); - points->SetData(data); + for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs) + if (!isNan(srow) && !isNan(nrow)) + { + Vec3d endp = Vec3d(srow) + Vec3d(nrow) * (double)scale; + + points->InsertNextPoint(srow); + points->InsertNextPoint(endp.val); + + lines->InsertNextCell(2); + lines->InsertCellPoint(total++); + lines->InsertCellPoint(total++); + } + } } vtkSmartPointer polyData = vtkSmartPointer::New(); @@ -303,16 +243,17 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in polyData->SetLines(lines); vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetColorModeToMapScalars(); + mapper->SetScalarModeToUsePointData(); #if VTK_MAJOR_VERSION <= 5 mapper->SetInput(polyData); #else mapper->SetInputData(polyData); #endif - mapper->SetColorModeToMapScalars(); - mapper->SetScalarModeToUsePointData(); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); + WidgetAccessor::setProp(*this, actor); setColor(color); } diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index b10e83ad50..5bb0a5cd4b 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -170,6 +170,11 @@ namespace cv static VizMap storage; friend class Viz3d; }; + + template bool isNan(const _Tp* data) + { + return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); + } } } diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp index b96db385b3..cf1eb46482 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -73,8 +73,8 @@ void cv::viz::vtkCloudMatSink::WriteData() CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); cloud.create(1, points_Data->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); - Vec3d *ddata = (Vec3d*)cloud.getMat().ptr(); - Vec3f *fdata = (Vec3f*)cloud.getMat().ptr(); + Vec3d *ddata = cloud.getMat().ptr(); + Vec3f *fdata = cloud.getMat().ptr(); if (cloud.depth() == CV_32F) for(size_t i = 0; i < cloud.total(); ++i) diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index cf3d21e6dd..f1dabe66b9 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -48,11 +48,6 @@ namespace cv { namespace viz { vtkStandardNewMacro(vtkCloudMatSource); - template bool isNan(const _Tp* data) - { - return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); - } - template struct VtkDepthTraits; template<> struct VtkDepthTraits @@ -190,7 +185,7 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, co for (int y = 0; y < cloud_colors.rows; ++y) { const unsigned char* srow = cloud_colors.ptr(y); - const unsigned char* send = srow + cloud_colors.cols * cloud_colors.channels(); + const unsigned char* send = srow + cloud_colors.cols * s_chs; const _Msk* mrow = mask.ptr<_Msk>(y); if (cloud_colors.channels() == 1) diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 9f76bb2a2f..b183f7bb56 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -120,6 +120,20 @@ TEST(Viz, DISABLED_show_mesh_random_colors) viz.spin(); } +TEST(Viz, DISABLED_show_sampled_normals) +{ + Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + computeNormals(mesh, mesh.normals); + + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + + Viz3d viz("show_sampled_normals"); + viz.showWidget("mesh", WMesh(mesh), pose); + viz.showWidget("normals", WCloudNormals(mesh.cloud, mesh.normals, 30, 0.1f, Color::green()), pose); + viz.setRenderingProperty("normals", LINE_WIDTH, 2.0); + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); @@ -130,4 +144,3 @@ TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) viz.spin(); viz.spin(); } - From 7b28f730f42c419bc9d17e394a91e5df4a65a20b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 12:32:33 +0400 Subject: [PATCH 38/91] traits for Affine3 --- modules/core/include/opencv2/core/affine.hpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 3f072e78f6..62720b572a 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -134,8 +134,24 @@ namespace cv static cv::Vec3f operator*(const cv::Affine3f& affine, const cv::Vec3f& vector); static cv::Vec3d operator*(const cv::Affine3d& affine, const cv::Vec3d& vector); -} + template class DataType< Affine3<_Tp> > + { + public: + typedef Affine3<_Tp> value_type; + typedef Affine3::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 16, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; + }; +} /////////////////////////////////////////////////////////////////////////////////// From e26b7e1e4fa855a30798fdd11ad92b7cd87aa518 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 12:34:42 +0400 Subject: [PATCH 39/91] ported some trajectories functionality to InputArray style --- modules/viz/doc/widget.rst | 6 +- modules/viz/include/opencv2/viz.hpp | 14 ++- modules/viz/include/opencv2/viz/widgets.hpp | 7 +- modules/viz/src/shapes.cpp | 105 ++----------------- modules/viz/src/vizcore.cpp | 108 ++++++++++++++------ modules/viz/test/tests_simple.cpp | 20 +++- 6 files changed, 120 insertions(+), 140 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index c420799640..159e4ba806 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -732,16 +732,16 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) - :param path: List of poses on a trajectory. + :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. :param scale: Scale of the frames. Polyline is not affected. :param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected. diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 2724e921d2..b281635a61 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -104,11 +104,17 @@ namespace cv CV_EXPORTS bool readPose(const String& file, Affine3d& pose, const String& tag = "pose"); CV_EXPORTS void writePose(const String& file, const Affine3d& pose, const String& tag = "pose"); - CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); - CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); + //! takes vector> with T = float/dobule and writes to a sequence of files with given filename format + CV_EXPORTS void writeTrajectory(InputArray traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); - CV_EXPORTS void readTrajectory(std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); - CV_EXPORTS void readTrajectory(std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); + //! takes vector> with T = float/dobule and loads poses from sequence of files + CV_EXPORTS void readTrajectory(OutputArray traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); + + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Computing normals for mesh + + CV_EXPORTS void computeNormals(const Mesh3d& mesh, OutputArray normals); } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 27f211cd63..2868880ec5 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -262,9 +262,8 @@ namespace cv public: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; - //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); + //! Takes vector> and displays trajectory of the given path either by coordinate frames or polyline + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectoryFrustums : public Widget3D @@ -309,7 +308,7 @@ namespace cv class CV_EXPORTS WCloudNormals : public Widget3D { public: - WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); + WCloudNormals(InputArray cloud, InputArray normals, int level = 64, float scale = 0.1f, const Color &color = Color::white()); }; class CV_EXPORTS WMesh : public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index fa6662862a..490be3b3bd 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1213,106 +1213,21 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WTrajectory::WTrajectory(const std::vector &_path, int display_mode, float scale, const Color &color) +cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, float scale, const Color &color) { - std::vector path(_path.begin(), _path.end()); + CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT); + CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16)); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - - // Bitwise and with 3 in order to limit the domain to 2 bits - if ((~display_mode & 3) ^ WTrajectory::PATH) - { - // Create a poly line along the path - vtkIdType nr_points = path.size(); - - vtkSmartPointer points = vtkSmartPointer::New(); - points->SetDataTypeToFloat(); - points->SetNumberOfPoints(nr_points); - - vtkSmartPointer polyData = vtkSmartPointer::New(); - vtkSmartPointer polyLine = vtkSmartPointer::New(); - polyLine->GetPointIds()->SetNumberOfIds(nr_points); - - Vec3f *data_beg = vtkpoints_data(points); - - for (vtkIdType i = 0; i < nr_points; ++i) - { - Vec3f cam_pose = path[i].translation(); - *data_beg++ = cam_pose; - polyLine->GetPointIds()->SetId(i,i); - } - - vtkSmartPointer cells = vtkSmartPointer::New(); - cells->InsertNextCell(polyLine); - - polyData->SetPoints(points); - polyData->SetLines(cells); - - // Set the color for polyData - vtkSmartPointer colors = vtkSmartPointer::New(); - colors->SetNumberOfComponents(3); - colors->SetNumberOfTuples(nr_points); - colors->FillComponent(0, color[2]); - colors->FillComponent(1, color[1]); - colors->FillComponent(2, color[0]); - - polyData->GetPointData()->SetScalars(colors); -#if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInputConnection(polyData->GetProducerPort()); -#else - appendFilter->AddInputData(polyData); -#endif - } + const Affine3d* dpath = _path.getMat().ptr(), *dend = dpath + _path.total(); + const Affine3f* fpath = _path.getMat().ptr(), *fend = fpath + _path.total(); + std::vector path; - if ((~display_mode & 3) ^ WTrajectory::FRAMES) - { - // Create frames and transform along the path - vtkSmartPointer axes = vtkSmartPointer::New(); - axes->SetOrigin(0, 0, 0); - axes->SetScaleFactor(scale); - - vtkSmartPointer axes_colors = vtkSmartPointer::New(); - axes_colors->SetNumberOfComponents(3); - axes_colors->InsertNextTuple3(255,0,0); - axes_colors->InsertNextTuple3(255,0,0); - axes_colors->InsertNextTuple3(0,255,0); - axes_colors->InsertNextTuple3(0,255,0); - axes_colors->InsertNextTuple3(0,0,255); - axes_colors->InsertNextTuple3(0,0,255); - - vtkSmartPointer axes_data = axes->GetOutput(); -#if VTK_MAJOR_VERSION <= 5 - axes_data->Update(); -#else - axes->Update(); -#endif - axes_data->GetPointData()->SetScalars(axes_colors); + if (_path.depth() == CV_32F) + path.assign(fpath, fend); - vtkSmartPointer axes_tubes = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - axes_tubes->SetInput(axes_data); -#else - axes_tubes->SetInputData(axes_data); -#endif - axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); - axes_tubes->SetNumberOfSides(6); - axes_tubes->Update(); - - TrajectoryUtils::applyPath(axes_tubes->GetOutput(), appendFilter, path); - } + if (_path.depth() == CV_64F) + path.assign(dpath, dend); - vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetScalarModeToUsePointData(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); -} - -cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, float scale, const Color &color) -{ vtkSmartPointer appendFilter = vtkSmartPointer::New(); // Bitwise and with 3 in order to limit the domain to 2 bits diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 39f34b35d4..d01b947a45 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -243,53 +243,103 @@ void cv::viz::writePose(const String& file, const Affine3d& pose, const String& fs << tag << Mat(pose.matrix, false); } -namespace cv { namespace viz { namespace impl +void cv::viz::readTrajectory(OutputArray _traj, const String& files_format, int start, int end, const String& tag) { - template - void readTrajectory(std::vector >& traj, const String& files_format, int start, int end, const String& tag) + CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); + + start = max(0, std::min(start, end)); + end = std::max(start, end); + + std::vector traj; + + for(int i = start; i < end; ++i) { - start = max(0, std::min(start, end)); - end = std::max(start, end); + Affine3d affine; + bool ok = readPose(cv::format(files_format.c_str(), i), affine, tag); + if (!ok) + break; - std::vector< Affine3<_Tp> > temp; + traj.push_back(affine); + } + + Mat(traj).convertTo(_traj, _traj.depth()); +} - for(int i = start; i < end; ++i) +void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int start, const String& tag) +{ + if (_traj.kind() == _InputArray::STD_VECTOR_MAT) + { + std::vector& v = *(std::vector*)_traj.getObj(); + + for(size_t i = 0, index = max(0, start); i < v.size(); ++i, ++index) { Affine3d affine; - bool ok = readPose(cv::format(files_format.c_str(), i), affine, tag); - if (!ok) - break; - - temp.push_back(affine); + Mat pose = v[i]; + CV_Assert(pose.type() == CV_32FC(16) || pose.type() == CV_64FC(16)); + pose.copyTo(affine.matrix); + writePose(cv::format(files_format.c_str(), index), affine, tag); } - traj.swap(temp); + return; } - template - void writeTrajectory(const std::vector >& traj, const String& files_format, int start, const String& tag) + if (_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT) { - for(size_t i = 0, index = max(0, start); i < traj.size(); ++i, ++index) - writePose(cv::format(files_format.c_str(), index), traj[i], tag); - } -}}} + CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); + Mat traj = _traj.getMat(); + if (traj.depth() == CV_32F) + for(size_t i = 0, index = max(0, start); i < traj.total(); ++i, ++index) + writePose(cv::format(files_format.c_str(), index), traj.at(i), tag); + if (traj.depth() == CV_64F) + for(size_t i = 0, index = max(0, start); i < traj.total(); ++i, ++index) + writePose(cv::format(files_format.c_str(), index), traj.at(i), tag); + } -void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) -{ impl::readTrajectory(traj, files_format, start, end, tag); } - -void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) -{ impl::readTrajectory(traj, files_format, start, end, tag); } - -void cv::viz::writeTrajectory(const std::vector& traj, const String& files_format, int start, const String& tag) -{ impl::writeTrajectory(traj, files_format, start, tag); } + CV_Assert(!"Unsupported array kind"); +} -void cv::viz::writeTrajectory(const std::vector& traj, const String& files_format, int start, const String& tag) -{ impl::writeTrajectory(traj, files_format, start, tag); } +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Computing normals for mesh +void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) +{ + vtkSmartPointer prop = WidgetAccessor::getProp(WMesh(mesh)); + vtkSmartPointer mapper = vtkActor::SafeDownCast(prop)->GetMapper(); + vtkSmartPointer polydata = vtkPolyData::SafeDownCast(mapper->GetInput()); + + vtkSmartPointer normal_generator = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 + normal_generator->SetInput(polydata); +#else + normal_generator->SetInputData(polydata); +#endif + normal_generator->ComputePointNormalsOn(); + normal_generator->ComputeCellNormalsOff(); + + normal_generator->SetFeatureAngle(0.1); + normal_generator->SetSplitting(0); + normal_generator->SetConsistency(1); + normal_generator->SetAutoOrientNormals(0); + normal_generator->SetFlipNormals(0); + normal_generator->SetNonManifoldTraversal(1); + normal_generator->Update(); + + vtkSmartPointer generic_normals = normal_generator->GetOutput()->GetPointData()->GetNormals(); + if(generic_normals) + { + Mat normals(1, generic_normals->GetNumberOfTuples(), CV_64FC3); + Vec3d *optr = normals.ptr(); + for(int i = 0; i < generic_normals->GetNumberOfTuples(); ++i, ++optr) + generic_normals->GetTuple(i, optr->val); + normals.convertTo(_normals, mesh.cloud.type()); + } + else + _normals.release(); +} diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index b183f7bb56..f311ff2b79 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -49,9 +49,11 @@ TEST(Viz, DISABLED_show_cloud_bluberry) { Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_cloud_bluberry"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry())); + viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry()), pose); viz.spin(); } @@ -62,9 +64,11 @@ TEST(Viz, DISABLED_show_cloud_random_color) Mat colors(dragon_cloud.size(), CV_8UC3); theRNG().fill(colors, RNG::UNIFORM, 0, 255); + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_cloud_random_color"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("dragon", WCloud(dragon_cloud, colors)); + viz.showWidget("dragon", WCloud(dragon_cloud, colors), pose); viz.spin(); } @@ -77,9 +81,11 @@ TEST(Viz, DISABLED_show_cloud_masked) if (i % 15 != 0) dragon_cloud.at(i) = qnan; + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_cloud_masked"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("dragon", WCloud(dragon_cloud)); + viz.showWidget("dragon", WCloud(dragon_cloud), pose); viz.spin(); } @@ -102,9 +108,11 @@ TEST(Viz, DISABLED_show_mesh) { Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_mesh"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("mesh", WMesh(mesh)); + viz.showWidget("mesh", WMesh(mesh), pose); viz.spin(); } @@ -113,9 +121,11 @@ TEST(Viz, DISABLED_show_mesh_random_colors) Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_mesh_random_color"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("mesh", WMesh(mesh)); + viz.showWidget("mesh", WMesh(mesh), pose); viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); viz.spin(); } From b100299644d8c2c486fcbe4e5e281056de056d82 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 14:51:32 +0400 Subject: [PATCH 40/91] code beatification --- modules/viz/src/interactor_style.hpp | 2 +- modules/viz/src/precomp.hpp | 1 + modules/viz/src/shapes.cpp | 85 ++++++++-------------------- 3 files changed, 25 insertions(+), 63 deletions(-) diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 92876d8945..583860911a 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -63,7 +63,7 @@ namespace cv virtual void Initialize(); void setWidgetActorMap(const Ptr& actors) { widget_actor_map_ = actors; } - void setRenderer(vtkSmartPointer& ren) { renderer_ = ren; } + void setRenderer(vtkSmartPointer& renderer) { renderer_ = renderer; } void registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 5bb0a5cd4b..85977a800e 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -124,6 +124,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 490be3b3bd..2088e7d402 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -189,28 +189,22 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, arrowSource->SetTipRadius(thickness * 3.0); arrowSource->SetTipLength(thickness * 10.0); - Vec3f startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); - Vec3f arbitrary(theRNG().uniform(-10.f, 10.f), theRNG().uniform(-10.f, 10.f), theRNG().uniform(-10.f, 10.f)); + RNG rng = theRNG(); + Vec3d arbitrary(rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0)); + Vec3d startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); + double length = cv::norm(endPoint - startPoint); - Vec3f xvec = normalized(endPoint - startPoint); - Vec3f zvec = normalized(xvec.cross(arbitrary)); - Vec3f yvec = zvec.cross(xvec); + Vec3d xvec = normalized(endPoint - startPoint); + Vec3d zvec = normalized(xvec.cross(arbitrary)); + Vec3d yvec = zvec.cross(xvec); - // Create the direction cosine matrix - vtkSmartPointer matrix = vtkSmartPointer::New(); - matrix->Identity(); - for (int i = 0; i < 3; ++i) - { - matrix->SetElement(i, 0, xvec[i]); - matrix->SetElement(i, 1, yvec[i]); - matrix->SetElement(i, 2, zvec[i]); - } + Affine3d pose = makeTransformToGlobal(xvec, yvec, zvec); // Apply the transforms vtkSmartPointer transform = vtkSmartPointer::New(); transform->Translate(startPoint.val); - transform->Concatenate(matrix); + transform->Concatenate(vtkmatrix(pose.matrix)); transform->Scale(length, length, length); // Transform the polydata @@ -523,34 +517,18 @@ cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2f & vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); // Estimate the transform to set the normal based on the coefficients - Vec3f normal(coefs[0], coefs[1], coefs[2]); - Vec3f up_vector(0.0f, 1.0f, 0.0f); // Just set as default + Vec3d normal(coefs[0], coefs[1], coefs[2]); + Vec3d up_vector(0.0, 1.0, 0.0); // Just set as default double push_distance = -coefs[3]/cv::norm(Vec3f(coefs.val)); - Vec3f u,v,n; - n = normalize(normal); - u = normalize(up_vector.cross(n)); - v = n.cross(u); - - vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans->SetElement(0,0,u[0]); - mat_trans->SetElement(0,1,u[1]); - mat_trans->SetElement(0,2,u[2]); - mat_trans->SetElement(1,0,v[0]); - mat_trans->SetElement(1,1,v[1]); - mat_trans->SetElement(1,2,v[2]); - mat_trans->SetElement(2,0,n[0]); - mat_trans->SetElement(2,1,n[1]); - mat_trans->SetElement(2,2,n[2]); - // Inverse rotation (orthogonal, so just take transpose) - mat_trans->Transpose(); - mat_trans->SetElement(0,3,n[0] * push_distance); - mat_trans->SetElement(1,3,n[1] * push_distance); - mat_trans->SetElement(2,3,n[2] * push_distance); - mat_trans->SetElement(3,3,1); + Vec3d n = normalize(normal); + Vec3d u = normalize(up_vector.cross(n)); + Vec3d v = n.cross(u); + + Affine3d pose = makeTransformToGlobal(u, v, n, n * push_distance); vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); - transform->SetMatrix(mat_trans); + transform->SetMatrix(vtkmatrix(pose.matrix)); vtkSmartPointer transform_filter = vtkSmartPointer::New(); transform_filter->SetTransform(transform); @@ -837,28 +815,11 @@ cv::viz::WImage3D::WImage3D(const Vec3f &position, const Vec3f &normal, const Ve plane->SetNormal(0.0, 0.0, 1.0); // Compute the transformation matrix for drawing the camera frame in a scene - Vec3f u,v,n; - n = normalize(normal); - u = normalize(up_vector.cross(n)); - v = n.cross(u); - - vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans->SetElement(0,0,u[0]); - mat_trans->SetElement(0,1,u[1]); - mat_trans->SetElement(0,2,u[2]); - mat_trans->SetElement(1,0,v[0]); - mat_trans->SetElement(1,1,v[1]); - mat_trans->SetElement(1,2,v[2]); - mat_trans->SetElement(2,0,n[0]); - mat_trans->SetElement(2,1,n[1]); - mat_trans->SetElement(2,2,n[2]); - // Inverse rotation (orthogonal, so just take transpose) - mat_trans->Transpose(); - // Then translate the coordinate frame to camera position - mat_trans->SetElement(0,3,position[0]); - mat_trans->SetElement(1,3,position[1]); - mat_trans->SetElement(2,3,position[2]); - mat_trans->SetElement(3,3,1); + Vec3d n = normalize(normal); + Vec3d u = normalize(up_vector.cross(n)); + Vec3d v = n.cross(u); + + Affine3d pose = makeTransformToGlobal(u, v, n, position); // Apply the texture vtkSmartPointer texture = vtkSmartPointer::New(); @@ -870,7 +831,7 @@ cv::viz::WImage3D::WImage3D(const Vec3f &position, const Vec3f &normal, const Ve // Apply the transform after texture mapping vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); - transform->SetMatrix(mat_trans); + transform->SetMatrix(vtkmatrix(pose)); transform->Scale(size.width, size.height, 1.0); vtkSmartPointer transform_filter = vtkSmartPointer::New(); From 406444037d9e03ed7a5136cc4fcf8d8a1df86ec0 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 18:18:06 +0400 Subject: [PATCH 41/91] refactored polyline --- modules/viz/src/shapes.cpp | 81 +++++++++---------------------- modules/viz/test/tests_simple.cpp | 12 +++++ 2 files changed, 36 insertions(+), 57 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 2088e7d402..b1ef3de5e0 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -381,72 +381,39 @@ template<> cv::viz::WCoordinateSystem cv::viz::Widget::cast - static void copy(const Mat& source, Vec<_Tp, 3> *output, vtkSmartPointer polyLine) - { - int s_chs = source.channels(); - - for (int y = 0, id = 0; y < source.rows; ++y) - { - const _Tp* srow = source.ptr<_Tp>(y); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, ++id) - { - *output++ = Vec<_Tp, 3>(srow); - polyLine->GetPointIds()->SetId(id,id); - } - } - } - }; -}}} + CV_Assert(_points.type() == CV_32FC3 || _points.type() == CV_32FC4 || _points.type() == CV_64FC3 || _points.type() == CV_64FC4); -cv::viz::WPolyLine::WPolyLine(InputArray _pointData, const Color &color) -{ - Mat pointData = _pointData.getMat(); - CV_Assert(pointData.type() == CV_32FC3 || pointData.type() == CV_32FC4 || pointData.type() == CV_64FC3 || pointData.type() == CV_64FC4); - vtkIdType nr_points = pointData.total(); + const float *fpoints = _points.getMat().ptr(); + const double *dpoints = _points.getMat().ptr(); + size_t total = _points.total(); + int s_chs = _points.channels(); vtkSmartPointer points = vtkSmartPointer::New(); - vtkSmartPointer polyData = vtkSmartPointer::New(); - vtkSmartPointer polyLine = vtkSmartPointer::New(); + points->SetDataType(_points.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE); + points->SetNumberOfPoints(total); - if (pointData.depth() == CV_32F) - points->SetDataTypeToFloat(); - else - points->SetDataTypeToDouble(); + if (_points.depth() == CV_32F) + for(size_t i = 0; i < total; ++i, fpoints += s_chs) + points->SetPoint(i, fpoints); - points->SetNumberOfPoints(nr_points); - polyLine->GetPointIds()->SetNumberOfIds(nr_points); + if (_points.depth() == CV_64F) + for(size_t i = 0; i < total; ++i, dpoints += s_chs) + points->SetPoint(i, dpoints); - if (pointData.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - PolyLineUtils::copy(pointData, data_beg, polyLine); - } - else if (pointData.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - PolyLineUtils::copy(pointData, data_beg, polyLine); - } + vtkSmartPointer cell_array = vtkSmartPointer::New(); + cell_array->Allocate(cell_array->EstimateSize(1, total)); + cell_array->InsertNextCell(total); + for(size_t i = 0; i < total; ++i) + cell_array->InsertCellPoint(i); - vtkSmartPointer cells = vtkSmartPointer::New(); - cells->InsertNextCell(polyLine); - - polyData->SetPoints(points); - polyData->SetLines(cells); + vtkSmartPointer polydata = vtkSmartPointer::New(); + polydata->SetPoints(points); + polydata->SetLines(cell_array); vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polyData); -#else - mapper->SetInputData(polyData); -#endif + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -831,7 +798,7 @@ cv::viz::WImage3D::WImage3D(const Vec3f &position, const Vec3f &normal, const Ve // Apply the transform after texture mapping vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); - transform->SetMatrix(vtkmatrix(pose)); + transform->SetMatrix(vtkmatrix(pose.matrix)); transform->Scale(size.width, size.height, 1.0); vtkSmartPointer transform_filter = vtkSmartPointer::New(); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index f311ff2b79..6f61a806c6 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -130,6 +130,18 @@ TEST(Viz, DISABLED_show_mesh_random_colors) viz.spin(); } +TEST(Viz, DISABLED_show_polyline) +{ + Mat polyline(1, 32, CV_64FC3); + for(size_t i = 0; i < polyline.total(); ++i) + polyline.at(i) = Vec3d(i/16.0, cos(i * CV_PI/6), sin(i * CV_PI/6)); + + Viz3d viz("show_polyline"); + viz.showWidget("polyline", WPolyLine(Mat(polyline), Color::apricot())); + viz.showWidget("coosys", WCoordinateSystem()); + viz.spin(); +} + TEST(Viz, DISABLED_show_sampled_normals) { Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); From d26446542248d4d3442a761a46bcd77e36a8e45c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:13:15 +0400 Subject: [PATCH 42/91] more refactoring --- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/precomp.hpp | 32 +++++++++++++- modules/viz/src/vizcore.cpp | 4 +- modules/viz/test/test_viz3d.cpp | 46 ++++++++++++++------- 4 files changed, 64 insertions(+), 22 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 2868880ec5..b48795290d 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -227,7 +227,7 @@ namespace cv class CV_EXPORTS WCoordinateSystem : public Widget3D { public: - WCoordinateSystem(float scale = 1.f); + WCoordinateSystem(double scale = 1.f); }; class CV_EXPORTS WGrid : public Widget3D @@ -263,7 +263,7 @@ namespace cv enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; //! Takes vector> and displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectoryFrustums : public Widget3D diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 85977a800e..b91e50c6ef 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -172,10 +172,40 @@ namespace cv friend class Viz3d; }; - template bool isNan(const _Tp* data) + template inline bool isNan(const _Tp* data) { return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); } + + inline vtkSmartPointer getPolyData(const Widget3D& widget) + { + vtkSmartPointer prop = WidgetAccessor::getProp(widget); + vtkSmartPointer mapper = vtkActor::SafeDownCast(prop)->GetMapper(); + return vtkPolyData::SafeDownCast(mapper->GetInput()); + } + + struct VtkUtils + { + template + static inline void SetInputData(vtkSmartPointer filter, vtkPolyData *polydata) + { + #if VTK_MAJOR_VERSION <= 5 + filter->SetInput(polydata); + #else + filter->SetInputData(polydata); + #endif + } + + template + static inline void AddInputData(vtkSmartPointer filter, vtkPolyData *polydata) + { + #if VTK_MAJOR_VERSION <= 5 + filter->AddInput(polydata); + #else + filter->AddInputData(polydata); + #endif + } + }; } } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index d01b947a45..ffb2d84f55 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -305,9 +305,7 @@ void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) { - vtkSmartPointer prop = WidgetAccessor::getProp(WMesh(mesh)); - vtkSmartPointer mapper = vtkActor::SafeDownCast(prop)->GetMapper(); - vtkSmartPointer polydata = vtkPolyData::SafeDownCast(mapper->GetInput()); + vtkSmartPointer polydata = getPolyData(WMesh(mesh)); vtkSmartPointer normal_generator = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index ce0344f1e4..6bc3622c63 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -45,37 +45,51 @@ using namespace cv; TEST(Viz_viz3d, develop) { - std::cout << std::string(cvtest::TS::ptr()->get_data_path()) + "dragon.ply" << std::endl; + cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); - cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); + //cv::viz::Mesh3d mesh = cv::viz::Mesh3d::load(get_dragon_ply_file_path()); - -// for(size_t i = 0; i < cloud.total(); ++i) -// { -// if (i % 15 == 0) -// continue; -// const static float qnan = std::numeric_limits::quiet_NaN(); -// cloud.at(i) = Vec3f(qnan, qnan, qnan); -// } + //theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); cv::viz::Viz3d viz("abc"); viz.setBackgroundColor(cv::viz::Color::mlab()); viz.showWidget("coo", cv::viz::WCoordinateSystem(0.1)); - cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); + +// double c = cos(CV_PI/6); +// std::vector pts; +// pts.push_back(Vec3d(0, 0.0, -1.0)); +// pts.push_back(Vec3d(1, c, -0.5)); +// pts.push_back(Vec3d(2, c, 0.5)); +// pts.push_back(Vec3d(3, 0.0, 1.0)); +// pts.push_back(Vec3d(4, -c, 0.5)); +// pts.push_back(Vec3d(5, -c, -0.5)); + +// viz.showWidget("pl", cv::viz::WPolyLine(Mat(pts), cv::viz::Color::green())); + + //viz.showWidget("pl", cv::viz::WPolyLine(cloud.colRange(0, 100), cv::viz::Color::green())); + //viz.spin(); + + //cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); std::vector gt, es; cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); - cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); + //cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); + gt.resize(20); + + Affine3d inv = gt[0].inv(); + for(size_t i = 0; i < gt.size(); ++i) + gt[i] = inv * gt[i]; + + //viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::PATH, 1.f, viz::Color::blue()), gt[0].inv()); + viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::BOTH, 0.01f, viz::Color::blue())); - viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::PATH, 1.f, viz::Color::blue()), gt[0].inv()); - viz.showWidget("tr", viz::WTrajectory(es, viz::WTrajectory::PATH, 1.f, viz::Color::red()), gt[0].inv()); + //viz.showWidget("tr", viz::WTrajectory(es, viz::WTrajectory::PATH, 1.f, viz::Color::red()), gt[0].inv()); - cv::RNG rng; - rng.fill(colors, cv::RNG::UNIFORM, 0, 255); + //theRNG().fill(colors, cv::RNG::UNIFORM, 0, 255); //viz.showWidget("c", cv::viz::WCloud(cloud, colors)); //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); From 56819eaf198ddcca5ebab5039676e84ac8f0250b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:27:11 +0400 Subject: [PATCH 43/91] switched completer API to doubles, updated docs --- modules/viz/doc/widget.rst | 82 +++++++-------- modules/viz/include/opencv2/viz/widgets.hpp | 44 ++++---- modules/viz/src/clouds.cpp | 4 +- modules/viz/src/shapes.cpp | 109 ++++++++++---------- 4 files changed, 119 insertions(+), 120 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 159e4ba806..936cc5a9df 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -262,8 +262,8 @@ This 3D Widget defines a finite plane. :: class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white()); - WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); private: /* hidden */ }; @@ -272,13 +272,13 @@ viz::WPlane::WPlane ------------------- Constructs a WPlane. -.. ocv:function:: WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white()) +.. ocv:function:: WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()) :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. :param size: Size of the plane. :param color: :ocv:class:`Color` of the plane. -.. ocv:function:: WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white()) +.. ocv:function:: WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()) :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. :param pt: Position of the plane. @@ -294,14 +294,14 @@ This 3D Widget defines a sphere. :: class CV_EXPORTS WSphere : public Widget3D { public: - WSphere(const cv::Point3f ¢er, float radius, int sphere_resolution = 10, const Color &color = Color::white()) + WSphere(const cv::Point3f ¢er, double radius, int sphere_resolution = 10, const Color &color = Color::white()) }; viz::WSphere::WSphere --------------------- Constructs a WSphere. -.. ocv:function:: WSphere(const cv::Point3f ¢er, float radius, int sphere_resolution = 10, const Color &color = Color::white()) +.. ocv:function:: WSphere(const cv::Point3f ¢er, double radius, int sphere_resolution = 10, const Color &color = Color::white()) :param center: Center of the sphere. :param radius: Radius of the sphere. @@ -317,14 +317,14 @@ This 3D Widget defines an arrow. :: class CV_EXPORTS WArrow : public Widget3D { public: - WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03, const Color &color = Color::white()); + WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white()); }; viz::WArrow::WArrow ----------------------------- Constructs an WArrow. -.. ocv:function:: WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03, const Color &color = Color::white()) +.. ocv:function:: WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white()) :param pt1: Start point of the arrow. :param pt2: End point of the arrow. @@ -342,14 +342,14 @@ This 3D Widget defines a circle. :: class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white()); + WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); }; viz::WCircle::WCircle ------------------------------- Constructs a WCircle. -.. ocv:function:: WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white()) +.. ocv:function:: WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()) :param pt: Center of the circle. :param radius: Radius of the circle. @@ -365,14 +365,14 @@ This 3D Widget defines a cylinder. :: class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); }; viz::WCylinder::WCylinder ----------------------------------- Constructs a WCylinder. -.. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()) +.. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()) :param pt_on_axis: A point on the axis of the cylinder. :param axis_direction: Direction of the axis of the cylinder. @@ -416,14 +416,14 @@ This 3D Widget represents a coordinate system. :: class CV_EXPORTS WCoordinateSystem : public Widget3D { public: - WCoordinateSystem(float scale = 1.0); + WCoordinateSystem(double scale = 1.0); }; viz::WCoordinateSystem::WCoordinateSystem --------------------------------------------------- Constructs a WCoordinateSystem. -.. ocv:function:: WCoordinateSystem(float scale = 1.0) +.. ocv:function:: WCoordinateSystem(double scale = 1.0) :param scale: Determines the size of the axes. @@ -463,7 +463,7 @@ This 3D Widget defines a grid. :: //! Creates grid at the origin WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation - WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); private: /* hidden */ }; @@ -478,7 +478,7 @@ Constructs a WGrid. :param spacing: Size of each column and row, respectively. :param color: :ocv:class:`Color` of the grid. -.. ocv:function: WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()) +.. ocv:function: WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()) :param coeffs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. :param dimensions: Number of columns and rows, respectively. @@ -494,7 +494,7 @@ This 3D Widget represents 3D text. The text always faces the camera. :: class CV_EXPORTS WText3D : public Widget3D { public: - WText3D(const String &text, const Point3f &position, float text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()); + WText3D(const String &text, const Point3f &position, double text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -504,7 +504,7 @@ viz::WText3D::WText3D ------------------------------- Constructs a WText3D. -.. ocv:function:: WText3D(const String &text, const Point3f &position, float text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()) +.. ocv:function:: WText3D(const String &text, const Point3f &position, double text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()) :param text: Text content of the widget. :param position: Position of the text. @@ -609,7 +609,7 @@ This 3D Widget represents an image in 3D space. :: //! Creates 3D image at the origin WImage3D(const Mat &image, const Size &size); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size); + WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size); void setImage(const Mat &image); }; @@ -623,7 +623,7 @@ Constructs an WImage3D. :param image: BGR or Gray-Scale image. :param size: Size of the image. -.. ocv:function:: WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size) +.. ocv:function:: WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size) :param position: Position of the image. :param normal: Normal of the plane that represents the image. @@ -649,15 +649,15 @@ This 3D Widget represents camera position in a scene by its axes or viewing frus { public: //! Creates camera coordinate frame (axes) at the origin - WCameraPosition(float scale = 1.0); + WCameraPosition(double scale = 1.0); //! Creates frustum based on the intrinsic marix K at the origin - WCameraPosition(const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - WCameraPosition(const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); + 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 Matx33f &K, const Mat &img, float scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); }; viz::WCameraPosition::WCameraPosition @@ -666,7 +666,7 @@ Constructs a WCameraPosition. - **Display camera coordinate frame.** - .. ocv:function:: WCameraPosition(float scale = 1.0) + .. ocv:function:: WCameraPosition(double scale = 1.0) Creates camera coordinate frame at the origin. @@ -676,7 +676,7 @@ Constructs a WCameraPosition. - **Display the viewing frustum.** - .. ocv:function:: WCameraPosition(const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Matx33d &K, double scale = 1.0, const Color &color = Color::white()) :param K: Intrinsic matrix of the camera. :param scale: Scale of the frustum. @@ -684,7 +684,7 @@ Constructs a WCameraPosition. Creates viewing frustum of the camera based on its intrinsic matrix K. - .. ocv:function:: WCameraPosition(const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()) :param fov: Field of view of the camera (horizontal, vertical). :param scale: Scale of the frustum. @@ -698,7 +698,7 @@ Constructs a WCameraPosition. - **Display image on the far plane of the viewing frustum.** - .. ocv:function:: WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Matx33d &K, const Mat &img, 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. @@ -707,7 +707,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 Vec2f &fov, const Mat &img, float scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Vec2d &fov, const Mat &img, 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. @@ -732,14 +732,14 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white()) :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. @@ -762,16 +762,16 @@ This 3D Widget represents a trajectory. :: { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); }; viz::WTrajectoryFrustums::WTrajectoryFrustums ----------------------------- Constructs a WTrajectoryFrustums. -.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param K: Intrinsic matrix of the camera. @@ -780,7 +780,7 @@ Constructs a WTrajectoryFrustums. Displays frustums at each pose of the trajectory. -.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param fov: Field of view of the camera (horizontal, vertical). @@ -799,8 +799,8 @@ represent the direction from previous position to the current. :: class CV_EXPORTS WTrajectorySpheres : public Widget3D { public: - WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, - float init_sphere_radius = 0.021, sphere_radius = 0.007, + WTrajectorySpheres(const std::vector &path, double line_length = 0.05f, + double init_sphere_radius = 0.021, sphere_radius = 0.007, Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; @@ -808,7 +808,7 @@ viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- Constructs a WTrajectorySpheres. -.. ocv:function:: WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WTrajectorySpheres(const std::vector &path, double line_length = 0.05f, double init_sphere_radius = 0.021, double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) :param path: List of poses on a trajectory. :param line_length: Length of the lines. @@ -912,7 +912,7 @@ This 3D Widget represents normals of a point cloud. :: class CV_EXPORTS WCloudNormals : public Widget3D { public: - WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); + WCloudNormals(InputArray cloud, InputArray normals, int level = 100, double scale = 0.02f, const Color &color = Color::white()); private: /* hidden */ @@ -922,7 +922,7 @@ viz::WCloudNormals::WCloudNormals --------------------------------- Constructs a WCloudNormals. -.. ocv:function:: WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()) +.. ocv:function:: WCloudNormals(InputArray cloud, InputArray normals, int level = 100, double scale = 0.02f, const Color &color = Color::white()) :param cloud: Point set which can be of type: ``CV_32FC3``, ``CV_32FC4``, ``CV_64FC3``, ``CV_64FC4``. :param normals: A set of normals that has to be of same type with cloud. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index b48795290d..8fedb0c2c9 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -135,44 +135,44 @@ namespace cv class CV_EXPORTS WLine : public Widget3D { public: - WLine(const Point3f &pt1, const Point3f &pt2, const Color &color = Color::white()); + WLine(const Point3d &pt1, const Point3d &pt2, const Color &color = Color::white()); }; class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4f& coefs, float size = 1.f, const Color &color = Color::white()); - WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.f, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, double size = 1.f, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, const Point3d& pt, double size = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WSphere : public Widget3D { public: - WSphere(const cv::Point3f ¢er, float radius, int sphere_resolution = 10, const Color &color = Color::white()); + WSphere(const cv::Point3d ¢er, double radius, int sphere_resolution = 10, const Color &color = Color::white()); }; class CV_EXPORTS WArrow : public Widget3D { public: - WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03f, const Color &color = Color::white()); + WArrow(const Point3d& pt1, const Point3d& pt2, double thickness = 0.03, const Color &color = Color::white()); }; class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3f& pt, float radius, float thickness = 0.01f, const Color &color = Color::white()); + WCircle(const Point3d& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); }; class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); }; class CV_EXPORTS WCube : public Widget3D { public: - WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, const Color &color = Color::white()); + WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame = true, const Color &color = Color::white()); }; class CV_EXPORTS WPolyLine : public Widget3D @@ -196,7 +196,7 @@ namespace cv class CV_EXPORTS WText3D : public Widget3D { public: - WText3D(const String &text, const Point3f &position, float text_scale = 1.f, bool face_camera = true, const Color &color = Color::white()); + WText3D(const String &text, const Point3d &position, double text_scale = 1., bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -216,7 +216,7 @@ namespace cv //! Creates 3D image at the origin WImage3D(const Mat &image, const Size &size); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size); + WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size); void setImage(const Mat &image); }; @@ -234,24 +234,24 @@ namespace cv { public: //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color &color = Color::white()); + WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation - WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2f &spacing, const Color &color = Color::white()); + WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); }; class CV_EXPORTS WCameraPosition : public Widget3D { public: //! Creates camera coordinate frame (axes) at the origin - WCameraPosition(float scale = 1.f); + WCameraPosition(double scale = 1.0); //! Creates frustum based on the intrinsic marix K at the origin - WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + 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 Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// @@ -270,16 +270,16 @@ namespace cv { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1., const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1., const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: - WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, - float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WTrajectorySpheres(const std::vector &path, double line_length = 0.05, double init_sphere_radius = 0.021, + double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// @@ -308,7 +308,7 @@ namespace cv class CV_EXPORTS WCloudNormals : public Widget3D { public: - WCloudNormals(InputArray cloud, InputArray normals, int level = 64, float scale = 0.1f, const Color &color = Color::white()); + WCloudNormals(InputArray cloud, InputArray normals, int level = 64, double scale = 0.1, const Color &color = Color::white()); }; class CV_EXPORTS WMesh : public Widget3D diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 3c28624f31..15e9d4a616 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -175,7 +175,7 @@ template<> cv::viz::WCloudCollection cv::viz::Widget::castInsertNextPoint(srow); points->InsertNextPoint(endp.val); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index b1ef3de5e0..8afe649571 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -55,7 +55,7 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// line widget implementation -cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color) +cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color) { vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1(pt1.x, pt1.y, pt1.z); @@ -103,11 +103,11 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) +cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); plane->SetNormal(coefs[0], coefs[1], coefs[2]); - double norm = cv::norm(Vec3f(coefs.val)); + double norm = cv::norm(Vec3d(coefs.val)); plane->Push(-coefs[3] / norm); Vec3d p_center; @@ -123,15 +123,15 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) setColor(color); } -cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const Color &color) +cv::viz::WPlane::WPlane(const Vec4d& coefs, const Point3d& pt, double size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); - Point3f coefs3(coefs[0], coefs[1], coefs[2]); + Point3d coefs3(coefs[0], coefs[1], coefs[2]); double norm_sqr = 1.0 / coefs3.dot(coefs3); plane->SetNormal(coefs[0], coefs[1], coefs[2]); double t = coefs3.dot(pt) + coefs[3]; - Vec3f p_center = pt - coefs3 * t * norm_sqr; + Vec3d p_center = pt - coefs3 * t * norm_sqr; plane->SetCenter(p_center[0], p_center[1], p_center[2]); vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -153,7 +153,7 @@ template<> cv::viz::WPlane cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// sphere widget implementation -cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolution, const Color &color) +cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resolution, const Color &color) { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(radius); @@ -181,7 +181,7 @@ template<> cv::viz::WSphere cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// arrow widget implementation -cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, const Color &color) +cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness, const Color &color) { vtkSmartPointer arrowSource = vtkSmartPointer::New(); arrowSource->SetShaftRadius(thickness); @@ -231,7 +231,7 @@ template<> cv::viz::WArrow cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// circle widget implementation -cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, const Color& color) +cv::viz::WCircle::WCircle(const Point3d& pt, double radius, double thickness, const Color& color) { vtkSmartPointer disk = vtkSmartPointer::New(); // Maybe the resolution should be lower e.g. 50 or 25 @@ -267,9 +267,9 @@ template<> cv::viz::WCircle cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides, const Color &color) +cv::viz::WCylinder::WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides, const Color &color) { - const Point3f pt2 = pt_on_axis + axis_direction; + const Point3d pt2 = pt_on_axis + axis_direction; vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1(pt_on_axis.x, pt_on_axis.y, pt_on_axis.z); line->SetPoint2(pt2.x, pt2.y, pt2.z); @@ -298,7 +298,7 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCube::WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame, const Color &color) +cv::viz::WCube::WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame, const Color &color) { vtkSmartPointer mapper = vtkSmartPointer::New(); if (wire_frame) @@ -330,7 +330,7 @@ template<> cv::viz::WCube cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// coordinate system widget implementation -cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) +cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) { vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(0, 0, 0); @@ -461,7 +461,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color) { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); @@ -479,14 +479,14 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color setColor(color); } -cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2f &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec4d &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color) { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); // Estimate the transform to set the normal based on the coefficients Vec3d normal(coefs[0], coefs[1], coefs[2]); Vec3d up_vector(0.0, 1.0, 0.0); // Just set as default - double push_distance = -coefs[3]/cv::norm(Vec3f(coefs.val)); + double push_distance = -coefs[3]/cv::norm(Vec3d(coefs.val)); Vec3d n = normalize(normal); Vec3d u = normalize(up_vector.cross(n)); Vec3d v = n.cross(u); @@ -525,7 +525,7 @@ template<> cv::viz::WGrid cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// text3D widget implementation -cv::viz::WText3D::WText3D(const String &text, const Point3f &position, float text_scale, bool face_camera, const Color &color) +cv::viz::WText3D::WText3D(const String &text, const Point3d &position, double text_scale, bool face_camera, const Color &color) { vtkSmartPointer textSource = vtkSmartPointer::New(); textSource->SetText(text.c_str()); @@ -759,7 +759,7 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size &size) WidgetAccessor::setProp(*this, actor); } -cv::viz::WImage3D::WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size) +cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size) { CV_Assert(!image.empty() && image.depth() == CV_8U); @@ -857,7 +857,7 @@ namespace cv { namespace viz { namespace { struct CameraPositionUtils { - static void projectImage(float fovy, float far_end_height, const Mat &image, + static void projectImage(double fovy, double far_end_height, const Mat &image, double scale, const Color &color, vtkSmartPointer actor) { // Create a camera @@ -950,7 +950,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WCameraPosition::WCameraPosition(float scale) +cv::viz::WCameraPosition::WCameraPosition(double scale) { vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(0, 0, 0); @@ -992,20 +992,20 @@ cv::viz::WCameraPosition::WCameraPosition(float scale) WidgetAccessor::setProp(*this, actor); } -cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, float scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); - float f_x = K(0,0); - float f_y = K(1,1); - float c_y = K(1,2); - float aspect_ratio = f_y / f_x; + double f_x = K(0,0); + double f_y = K(1,1); + double c_y = K(1,2); + double aspect_ratio = f_y / f_x; // 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; + double fovy = 2.0 * atan2(c_y,f_y) * 180 / CV_PI; 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->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]; @@ -1014,8 +1014,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, float scale, const C vtkSmartPointer planes = vtkSmartPointer::New(); planes->SetFrustumPlanes(planesArray); - vtkSmartPointer frustumSource = - vtkSmartPointer::New(); + vtkSmartPointer frustumSource = vtkSmartPointer::New(); frustumSource->SetPlanes(planes); frustumSource->Update(); @@ -1034,14 +1033,14 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, float scale, const C } -cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, float scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); camera->SetViewAngle(fov[1] * 180 / CV_PI); // Vertical field of view - 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->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 aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); @@ -1072,25 +1071,25 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, float scale, const C setColor(color); } -cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, float scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, double scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); - float f_y = K(1,1); - float c_y = K(1,2); + double f_y = K(1,1); + double c_y = K(1,2); // 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.0f / CV_PI; - float far_end_height = 2.0f * c_y * scale / f_y; + double fovy = 2.0 * atan2(c_y,f_y) * 180.0 / CV_PI; + double far_end_height = 2.0f * c_y * scale / f_y; vtkSmartPointer actor = vtkSmartPointer::New(); CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); WidgetAccessor::setProp(*this, actor); } -cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, const Mat &image, float scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Vec2d &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); + double fovy = fov[1] * 180.0 / CV_PI; + double far_end_height = 2.0 * scale * tan(fov[1] * 0.5); vtkSmartPointer actor = vtkSmartPointer::New(); CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); @@ -1141,7 +1140,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, float scale, const Color &color) +cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double scale, const Color &color) { CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT); CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16)); @@ -1259,15 +1258,15 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// WTrajectoryFrustums widget implementation -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); - float f_x = K(0,0); - float f_y = K(1,1); - float c_y = K(1,2); - float aspect_ratio = f_y / f_x; + double f_x = K(0,0); + double f_y = K(1,1); + double c_y = K(1,2); + double aspect_ratio = f_y / f_x; // 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; + double fovy = 2.0 * atan2(c_y,f_y) * 180 / CV_PI; camera->SetViewAngle(fovy); camera->SetPosition(0.0,0.0,0.0); @@ -1303,14 +1302,14 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &p setColor(color); } -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); camera->SetViewAngle(fov[1] * 180 / CV_PI); // Vertical field of view - 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->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 aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); @@ -1352,7 +1351,7 @@ template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast &path, float line_length, float init_sphere_radius, float sphere_radius, +cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &path, double line_length, double init_sphere_radius, double sphere_radius, const Color &line_color, const Color &sphere_color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); From e94ee94be329e40bdd32cf08e2748529838d45f6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:28:29 +0400 Subject: [PATCH 44/91] refactored WCoordinateSystem widget --- modules/viz/src/shapes.cpp | 40 +++++++++++++++----------------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 8afe649571..c8395c6644 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -335,36 +335,28 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(0, 0, 0); axes->SetScaleFactor(scale); + axes->Update(); - vtkSmartPointer axes_colors = vtkSmartPointer::New(); - axes_colors->Allocate(6); - axes_colors->InsertNextValue(0.0); - axes_colors->InsertNextValue(0.0); - axes_colors->InsertNextValue(0.5); - axes_colors->InsertNextValue(0.5); - axes_colors->InsertNextValue(1.0); - axes_colors->InsertNextValue(1.0); + vtkSmartPointer colors = vtkSmartPointer::New(); + colors->SetNumberOfComponents(3); + colors->InsertNextTuple3(255, 0, 0); + colors->InsertNextTuple3(255, 0, 0); + colors->InsertNextTuple3(0, 255, 0); + colors->InsertNextTuple3(0, 255, 0); + colors->InsertNextTuple3(0, 0, 255); + colors->InsertNextTuple3(0, 0, 255); - vtkSmartPointer axes_data = axes->GetOutput(); -#if VTK_MAJOR_VERSION <= 5 - axes_data->Update(); -#else - axes->Update(); -#endif - axes_data->GetPointData()->SetScalars(axes_colors); + vtkSmartPointer polydata = axes->GetOutput(); + polydata->GetPointData()->SetScalars(colors); - vtkSmartPointer axes_tubes = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - axes_tubes->SetInput(axes_data); -#else - axes_tubes->SetInputData(axes_data); -#endif - axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); - axes_tubes->SetNumberOfSides(6); + vtkSmartPointer tube_filter = vtkSmartPointer::New(); + VtkUtils::SetInputData(tube_filter, polydata); + tube_filter->SetRadius(axes->GetScaleFactor() / 50.0); + tube_filter->SetNumberOfSides(6); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); - mapper->SetInputConnection(axes_tubes->GetOutputPort()); + VtkUtils::SetInputData(mapper, tube_filter->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); From 771d9509a8dcf50b84ecd60c1340e49a4c62cf81 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:32:54 +0400 Subject: [PATCH 45/91] polyline now uses scalars for color data (for reuse by other widgets) --- modules/viz/src/shapes.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index c8395c6644..67fa43cf70 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -400,18 +400,29 @@ cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color) for(size_t i = 0; i < total; ++i) cell_array->InsertCellPoint(i); + Vec3b rgb = Vec3d(color[2], color[1], color[0]); + Vec3b* color_data = new Vec3b[total]; + std::fill(color_data, color_data + total, rgb); + + vtkSmartPointer scalars = vtkSmartPointer::New(); + scalars->SetName("Colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(color_data->val, total * 3, 0); + vtkSmartPointer polydata = vtkSmartPointer::New(); polydata->SetPoints(points); polydata->SetLines(cell_array); + polydata->GetPointData()->SetScalars(scalars); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(polydata->GetProducerPort()); + mapper->SetScalarRange(0, 255); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WPolyLine cv::viz::Widget::cast() From a8556134aef1c1c9a5ea90b3d97eaf20dd67b77f Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:37:33 +0400 Subject: [PATCH 46/91] refactored simple trajectory to use TensorGlyph --- modules/viz/src/precomp.hpp | 5 +- modules/viz/src/shapes.cpp | 115 ++++---------------- modules/viz/src/vtk/vtkCloudMatSink.h | 3 + modules/viz/src/vtk/vtkCloudMatSource.h | 2 +- modules/viz/src/vtk/vtkTrajectorySource.cpp | 112 +++++++++++++++++++ modules/viz/src/vtk/vtkTrajectorySource.h | 84 ++++++++++++++ 6 files changed, 227 insertions(+), 94 deletions(-) create mode 100644 modules/viz/src/vtk/vtkTrajectorySource.cpp create mode 100644 modules/viz/src/vtk/vtkTrajectorySource.h diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index b91e50c6ef..d57e677c5d 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -132,10 +132,11 @@ # include /* unlink */ #endif -#include -#include #include #include +#include +#include +#include #include #include diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 67fa43cf70..cd649ad234 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1145,106 +1145,39 @@ namespace cv { namespace viz { namespace cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double scale, const Color &color) { - CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT); - CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16)); - - const Affine3d* dpath = _path.getMat().ptr(), *dend = dpath + _path.total(); - const Affine3f* fpath = _path.getMat().ptr(), *fend = fpath + _path.total(); - std::vector path; - - if (_path.depth() == CV_32F) - path.assign(fpath, fend); - - if (_path.depth() == CV_64F) - path.assign(dpath, dend); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); // Bitwise and with 3 in order to limit the domain to 2 bits - if ((~display_mode & 3) ^ WTrajectory::PATH) + if (display_mode & WTrajectory::PATH) { - // Create a poly line along the path - vtkIdType nr_points = path.size(); - - vtkSmartPointer points = vtkSmartPointer::New(); - points->SetDataTypeToFloat(); - points->SetNumberOfPoints(nr_points); - - vtkSmartPointer polyData = vtkSmartPointer::New(); - vtkSmartPointer polyLine = vtkSmartPointer::New(); - polyLine->GetPointIds()->SetNumberOfIds(nr_points); - - Vec3f *data_beg = vtkpoints_data(points); - - for (vtkIdType i = 0; i < nr_points; ++i) - { - Vec3f cam_pose = path[i].translation(); - *data_beg++ = cam_pose; - polyLine->GetPointIds()->SetId(i,i); - } - - vtkSmartPointer cells = vtkSmartPointer::New(); - cells->InsertNextCell(polyLine); - - polyData->SetPoints(points); - polyData->SetLines(cells); - - // Set the color for polyData - vtkSmartPointer colors = vtkSmartPointer::New(); - colors->SetNumberOfComponents(3); - colors->SetNumberOfTuples(nr_points); - colors->FillComponent(0, color[2]); - colors->FillComponent(1, color[1]); - colors->FillComponent(2, color[0]); - - polyData->GetPointData()->SetScalars(colors); -#if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInputConnection(polyData->GetProducerPort()); -#else - appendFilter->AddInputData(polyData); -#endif + Mat points = vtkTrajectorySource::ExtractPoints(_path); + vtkSmartPointer polydata = getPolyData(WPolyLine(points, color)); + appendFilter->AddInputConnection(polydata->GetProducerPort()); } - if ((~display_mode & 3) ^ WTrajectory::FRAMES) + vtkSmartPointer tensor_glyph; + if (display_mode & WTrajectory::FRAMES) { - // Create frames and transform along the path - vtkSmartPointer axes = vtkSmartPointer::New(); - axes->SetOrigin(0, 0, 0); - axes->SetScaleFactor(scale); - - vtkSmartPointer axes_colors = vtkSmartPointer::New(); - axes_colors->SetNumberOfComponents(3); - axes_colors->InsertNextTuple3(255,0,0); - axes_colors->InsertNextTuple3(255,0,0); - axes_colors->InsertNextTuple3(0,255,0); - axes_colors->InsertNextTuple3(0,255,0); - axes_colors->InsertNextTuple3(0,0,255); - axes_colors->InsertNextTuple3(0,0,255); - - vtkSmartPointer axes_data = axes->GetOutput(); -#if VTK_MAJOR_VERSION <= 5 - axes_data->Update(); -#else - axes->Update(); -#endif - axes_data->GetPointData()->SetScalars(axes_colors); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetTrajectory(_path); - vtkSmartPointer axes_tubes = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - axes_tubes->SetInput(axes_data); -#else - axes_tubes->SetInputData(axes_data); -#endif - axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); - axes_tubes->SetNumberOfSides(6); - axes_tubes->Update(); + vtkSmartPointer glyph = getPolyData(WCoordinateSystem(scale)); - TrajectoryUtils::applyPath(axes_tubes->GetOutput(), appendFilter, path); + tensor_glyph = vtkSmartPointer::New(); + tensor_glyph->SetInputConnection(source->GetOutputPort()); + tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues + tensor_glyph->ThreeGlyphsOff(); + tensor_glyph->SymmetricOff(); + tensor_glyph->ColorGlyphsOff(); + + appendFilter->AddInputConnection(tensor_glyph->GetOutputPort()); } vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, appendFilter->GetOutput()); mapper->SetScalarModeToUsePointData(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); + mapper->SetScalarRange(0, 255); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1269,12 +1202,12 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &p double c_y = K(1,2); double aspect_ratio = f_y / f_x; // 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 / CV_PI; + double fovy = 2.0 * atan2(c_y, f_y) * 180 / CV_PI; 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->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]; diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index e4a55f0783..1d299f47ce 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -45,6 +45,9 @@ #ifndef __vtkCloudMatSink_h #define __vtkCloudMatSink_h +#include +#include + namespace cv { namespace viz diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index a1d854c326..00e6adf1ee 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -45,7 +45,7 @@ #ifndef __vtkCloudMatSource_h #define __vtkCloudMatSource_h -#include +#include #include #include #include diff --git a/modules/viz/src/vtk/vtkTrajectorySource.cpp b/modules/viz/src/vtk/vtkTrajectorySource.cpp new file mode 100644 index 0000000000..1510208819 --- /dev/null +++ b/modules/viz/src/vtk/vtkTrajectorySource.cpp @@ -0,0 +1,112 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkTrajectorySource); +}} + +cv::viz::vtkTrajectorySource::vtkTrajectorySource() { SetNumberOfInputPorts(0); } +cv::viz::vtkTrajectorySource::~vtkTrajectorySource() {} + +void cv::viz::vtkTrajectorySource::SetTrajectory(InputArray _traj) +{ + CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); + CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); + + Mat traj; + _traj.getMat().convertTo(traj, CV_64F); + const Affine3d* dpath = _traj.getMat().ptr(); + + size_t total = _traj.total(); + + points = vtkSmartPointer::New(); + points->SetDataType(VTK_DOUBLE); + points->SetNumberOfPoints(total); + + tensors = vtkSmartPointer::New(); + tensors->SetNumberOfComponents(9); + tensors->SetNumberOfTuples(total); + + for(size_t i = 0; i < total; ++i, ++dpath) + { + Matx33d R = dpath->rotation().t(); // transposed because of + tensors->SetTuple(i, R.val); // column major order + + Vec3d p = dpath->translation(); + points->SetPoint(i, p.val); + } +} + + +cv::Mat cv::viz::vtkTrajectorySource::ExtractPoints(InputArray _traj) +{ + CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); + CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); + + Mat points(1, _traj.total(), CV_MAKETYPE(_traj.depth(), 3)); + const Affine3d* dpath = _traj.getMat().ptr(); + const Affine3f* fpath = _traj.getMat().ptr(); + + if (_traj.depth() == CV_32F) + for(int i = 0; i < points.cols; ++i) + points.at(i) = fpath[i].translation(); + + if (_traj.depth() == CV_64F) + for(int i = 0; i < points.cols; ++i) + points.at(i) = dpath[i].translation(); + + return points; +} + +int cv::viz::vtkTrajectorySource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + output->SetPoints(points); + output->GetPointData()->SetTensors(tensors); + return 1; +} diff --git a/modules/viz/src/vtk/vtkTrajectorySource.h b/modules/viz/src/vtk/vtkTrajectorySource.h new file mode 100644 index 0000000000..9182509653 --- /dev/null +++ b/modules/viz/src/vtk/vtkTrajectorySource.h @@ -0,0 +1,84 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkTrajectorySource_h +#define __vtkTrajectorySource_h + +#include +#include +#include +#include +#include + +namespace cv +{ + namespace viz + { + class vtkTrajectorySource : public vtkPolyDataAlgorithm + { + public: + static vtkTrajectorySource *New(); + vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm); + + virtual void SetTrajectory(InputArray trajectory); + + static Mat ExtractPoints(InputArray trajectory); + + protected: + vtkTrajectorySource(); + ~vtkTrajectorySource(); + + vtkSmartPointer points; + vtkSmartPointer tensors; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + private: + vtkTrajectorySource(const vtkTrajectorySource&); // Not implemented. + void operator=(const vtkTrajectorySource&); // Not implemented. + + }; + } +} + +#endif From 45879fb9db59701f9f57e25224860a70ee05b1a6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:48:32 +0400 Subject: [PATCH 47/91] more refactoring --- modules/viz/src/precomp.hpp | 18 ++++++++-- modules/viz/src/shapes.cpp | 69 ++++++------------------------------- 2 files changed, 27 insertions(+), 60 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index d57e677c5d..155612724e 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -188,7 +188,7 @@ namespace cv struct VtkUtils { template - static inline void SetInputData(vtkSmartPointer filter, vtkPolyData *polydata) + static void SetInputData(vtkSmartPointer filter, vtkPolyData *polydata) { #if VTK_MAJOR_VERSION <= 5 filter->SetInput(polydata); @@ -198,7 +198,7 @@ namespace cv } template - static inline void AddInputData(vtkSmartPointer filter, vtkPolyData *polydata) + static void AddInputData(vtkSmartPointer filter, vtkPolyData *polydata) { #if VTK_MAJOR_VERSION <= 5 filter->AddInput(polydata); @@ -206,6 +206,20 @@ namespace cv filter->AddInputData(polydata); #endif } + + static vtkSmartPointer FillScalars(size_t size, const Color& color) + { + Vec3b rgb = Vec3d(color[2], color[1], color[0]); + Vec3b* color_data = new Vec3b[size]; + std::fill(color_data, color_data + size, rgb); + + vtkSmartPointer scalars = vtkSmartPointer::New(); + scalars->SetName("Colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(size); + scalars->SetArray(color_data->val, size * 3, 0); + return scalars; + } }; } } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index cd649ad234..a4401869e5 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -400,15 +400,7 @@ cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color) for(size_t i = 0; i < total; ++i) cell_array->InsertCellPoint(i); - Vec3b rgb = Vec3d(color[2], color[1], color[0]); - Vec3b* color_data = new Vec3b[total]; - std::fill(color_data, color_data + total, rgb); - - vtkSmartPointer scalars = vtkSmartPointer::New(); - scalars->SetName("Colors"); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(total); - scalars->SetArray(color_data->val, total * 3, 0); + vtkSmartPointer scalars = VtkUtils::FillScalars(total, color); vtkSmartPointer polydata = vtkSmartPointer::New(); polydata->SetPoints(points); @@ -913,9 +905,9 @@ namespace cv { namespace viz { namespace // 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->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]; @@ -955,39 +947,10 @@ namespace cv { namespace viz { namespace cv::viz::WCameraPosition::WCameraPosition(double scale) { - vtkSmartPointer axes = vtkSmartPointer::New(); - axes->SetOrigin(0, 0, 0); - axes->SetScaleFactor(scale); - - vtkSmartPointer axes_colors = vtkSmartPointer::New(); - axes_colors->Allocate(6); - axes_colors->InsertNextValue(0.0); - axes_colors->InsertNextValue(0.0); - axes_colors->InsertNextValue(0.5); - axes_colors->InsertNextValue(0.5); - axes_colors->InsertNextValue(1.0); - axes_colors->InsertNextValue(1.0); - - vtkSmartPointer axes_data = axes->GetOutput(); -#if VTK_MAJOR_VERSION <= 5 - axes_data->Update(); -#else - axes->Update(); -#endif - axes_data->GetPointData()->SetScalars(axes_colors); - - vtkSmartPointer axes_tubes = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - axes_tubes->SetInput(axes_data); -#else - axes_tubes->SetInputData(axes_data); -#endif - axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); - axes_tubes->SetNumberOfSides(6); - vtkSmartPointer mapper = vtkSmartPointer::New(); + + VtkUtils::SetInputData(mapper, getPolyData(WCoordinateSystem(scale))); mapper->SetScalarModeToUsePointData(); - mapper->SetInputConnection(axes_tubes->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1035,7 +998,6 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const setColor(color); } - cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -1299,28 +1261,19 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &pat line_scalars->InsertNextTuple3(line_color[2], line_color[1], line_color[0]); // Create color array for sphere - vtkSphereSource * dummy_sphere = vtkSphereSource::New(); + vtkSmartPointer dummy_sphere = vtkSmartPointer::New(); // Create the array for big sphere dummy_sphere->SetRadius(init_sphere_radius); dummy_sphere->Update(); vtkIdType nr_points = dummy_sphere->GetOutput()->GetNumberOfCells(); - vtkSmartPointer sphere_scalars_init = vtkSmartPointer::New(); - sphere_scalars_init->SetNumberOfComponents(3); - sphere_scalars_init->SetNumberOfTuples(nr_points); - sphere_scalars_init->FillComponent(0, sphere_color[2]); - sphere_scalars_init->FillComponent(1, sphere_color[1]); - sphere_scalars_init->FillComponent(2, sphere_color[0]); + vtkSmartPointer sphere_scalars_init = VtkUtils::FillScalars(nr_points, sphere_color); + // Create the array for small sphere dummy_sphere->SetRadius(sphere_radius); dummy_sphere->Update(); nr_points = dummy_sphere->GetOutput()->GetNumberOfCells(); - vtkSmartPointer sphere_scalars = vtkSmartPointer::New(); - sphere_scalars->SetNumberOfComponents(3); - sphere_scalars->SetNumberOfTuples(nr_points); - sphere_scalars->FillComponent(0, sphere_color[2]); - sphere_scalars->FillComponent(1, sphere_color[1]); - sphere_scalars->FillComponent(2, sphere_color[0]); - dummy_sphere->Delete(); + vtkSmartPointer sphere_scalars = VtkUtils::FillScalars(nr_points, sphere_color); + for (vtkIdType i = 0; i < nr_poses; ++i) { From 42dc90295dc6cc179939605cad170f5f957ba37a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 22:21:42 +0400 Subject: [PATCH 48/91] refactored camera position - simplified frustum creation --- modules/viz/src/shapes.cpp | 94 ++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index a4401869e5..df383337ce 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -942,6 +942,32 @@ namespace cv { namespace viz { namespace actor->SetMapper(planeMapper); actor->SetTexture(texture); } + + static vtkSmartPointer createFrustrum(double aspect_ratio, double fovy, double scale) + { + vtkSmartPointer camera = vtkSmartPointer::New(); + 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 planes = vtkSmartPointer::New(); + planes->SetFrustumPlanes(planesArray); + + vtkSmartPointer frustumSource = vtkSmartPointer::New(); + frustumSource->SetPlanes(planes); + + vtkSmartPointer extract_edges = vtkSmartPointer::New(); + extract_edges->SetInputConnection(frustumSource->GetOutputPort()); + extract_edges->Update(); + + return extract_edges->GetOutput(); + } + }; }}} @@ -960,36 +986,16 @@ cv::viz::WCameraPosition::WCameraPosition(double scale) cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const Color &color) { - vtkSmartPointer camera = vtkSmartPointer::New(); - double f_x = K(0,0); - double f_y = K(1,1); - double c_y = K(1,2); - double aspect_ratio = f_y / f_x; - // 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 / CV_PI; - - 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 f_x = K(0,0), f_y = K(1,1), c_y = K(1,2); - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); - - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); + // 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 / CV_PI; + double aspect_ratio = f_y / f_x; - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); + vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(filter->GetOutputPort()); + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1000,34 +1006,13 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color) { - vtkSmartPointer camera = vtkSmartPointer::New(); - - camera->SetViewAngle(fov[1] * 180 / CV_PI); // Vertical field of view - 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 aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); + double fovy = fov[1] * 180 / CV_PI; - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); - - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = - vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); - - // Extract the edges so we have the grid - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); + vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(filter->GetOutputPort()); + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1039,11 +1024,12 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, double scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); - double f_y = K(1,1); - double c_y = K(1,2); + + 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.0f * c_y * scale / f_y; + double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI; + double far_end_height = 2.00 * c_y * scale / f_y; vtkSmartPointer actor = vtkSmartPointer::New(); CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); From 4833976a0c7fce492cf69a33f2815fcedd3a2890 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 22:35:21 +0400 Subject: [PATCH 49/91] refactored frustum trajectory to use glyphs --- modules/viz/doc/widget.rst | 8 +- modules/viz/include/opencv2/viz/widgets.hpp | 9 +- modules/viz/src/shapes.cpp | 122 +++++--------------- modules/viz/src/types.cpp | 2 +- 4 files changed, 39 insertions(+), 102 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 936cc5a9df..4119df0832 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -762,9 +762,9 @@ This 3D Widget represents a trajectory. :: { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(InputArray path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(InputArray path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); }; viz::WTrajectoryFrustums::WTrajectoryFrustums @@ -773,7 +773,7 @@ Constructs a WTrajectoryFrustums. .. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()) - :param path: List of poses on a trajectory. + :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param K: Intrinsic matrix of the camera. :param scale: Scale of the frustums. :param color: :ocv:class:`Color` of the frustums. @@ -782,7 +782,7 @@ Constructs a WTrajectoryFrustums. .. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()) - :param path: List of poses on a trajectory. + :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param fov: Field of view of the camera (horizontal, vertical). :param scale: Scale of the frustums. :param color: :ocv:class:`Color` of the frustums. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 8fedb0c2c9..ad75199f89 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -269,10 +269,11 @@ namespace cv class CV_EXPORTS WTrajectoryFrustums : public Widget3D { public: - //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1., const Color &color = Color::white()); - //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1., const Color &color = Color::white()); + //! Takes vector> and displays trajectory of the given path by frustums + WTrajectoryFrustums(InputArray path, const Matx33d &K, double scale = 1., const Color &color = Color::white()); + + //! Takes vector> and displays trajectory of the given path by frustums + WTrajectoryFrustums(InputArray path, const Vec2d &fov, double scale = 1., const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index df383337ce..c177a9b673 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1056,41 +1056,6 @@ template<> cv::viz::WCameraPosition cv::viz::Widget::cast poly_data, vtkSmartPointer append_filter, const std::vector &path) - { - vtkIdType nr_points = path.size(); - - for (vtkIdType i = 0; i < nr_points; ++i) - { - vtkSmartPointer new_data = vtkSmartPointer::New(); - new_data->DeepCopy(poly_data); - - // Transform the default coordinate frame - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans = vtkmatrix(path[i].matrix); - transform->SetMatrix(mat_trans); - - vtkSmartPointer filter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - filter->SetInput(new_data); -#else - filter->SetInputData(new_data); -#endif - filter->SetTransform(transform); - filter->Update(); - - append_filter->AddInputConnection(filter->GetOutputPort()); - } - } - }; -}}} - cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double scale, const Color &color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1103,7 +1068,6 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca appendFilter->AddInputConnection(polydata->GetProducerPort()); } - vtkSmartPointer tensor_glyph; if (display_mode & WTrajectory::FRAMES) { vtkSmartPointer source = vtkSmartPointer::New(); @@ -1111,7 +1075,7 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca vtkSmartPointer glyph = getPolyData(WCoordinateSystem(scale)); - tensor_glyph = vtkSmartPointer::New(); + vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues @@ -1142,42 +1106,26 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// WTrajectoryFrustums widget implementation -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33d &K, double scale, const Color &color) { - vtkSmartPointer camera = vtkSmartPointer::New(); - double f_x = K(0,0); - double f_y = K(1,1); - double c_y = K(1,2); - double aspect_ratio = f_y / f_x; - // 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 / CV_PI; - - 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 source = vtkSmartPointer::New(); + source->SetTrajectory(_path); - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); + vtkSmartPointer glyph = getPolyData(WCameraPosition(K, scale)); - vtkSmartPointer frustumSource = vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); + vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); + tensor_glyph->SetInputConnection(source->GetOutputPort()); + tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues + tensor_glyph->ThreeGlyphsOff(); + tensor_glyph->SymmetricOff(); + tensor_glyph->ColorGlyphsOff(); + tensor_glyph->Update(); - // Extract the edges - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); - - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - TrajectoryUtils::applyPath(filter->GetOutput(), appendFilter, path); + vtkSmartPointer polydata = tensor_glyph->GetOutput(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1186,38 +1134,26 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &p setColor(color); } -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d &fov, double scale, const Color &color) { - vtkSmartPointer camera = vtkSmartPointer::New(); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetTrajectory(_path); - camera->SetViewAngle(fov[1] * 180 / CV_PI); // Vertical field of view - 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); + vtkSmartPointer glyph = getPolyData(WCameraPosition(fov, scale)); - double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); - - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); - - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); + vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); + tensor_glyph->SetInputConnection(source->GetOutputPort()); + tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues + tensor_glyph->ThreeGlyphsOff(); + tensor_glyph->SymmetricOff(); + tensor_glyph->ColorGlyphsOff(); + tensor_glyph->Update(); - // Extract the edges - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); - - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - TrajectoryUtils::applyPath(filter->GetOutput(), appendFilter, path); + vtkSmartPointer polydata = tensor_glyph->GetOutput(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index a6ea95ab5f..d233e735df 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -245,6 +245,6 @@ void cv::viz::Camera::computeProjectionMatrix(Matx44d &proj) const cv::viz::Camera cv::viz::Camera::KinectCamera(const Size &window_size) { - Matx33d K(525.0, 0.0, 320.0, 0.0, 525.0, 240.0, 0.0, 0.0, 1.0) ; + Matx33d K(525.0, 0.0, 320.0, 0.0, 525.0, 240.0, 0.0, 0.0, 1.0); return Camera(K, window_size); } From 38c9fa4a92edbce45265ce92b3f79d87962defb4 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 22:59:40 +0400 Subject: [PATCH 50/91] more refactoring --- modules/viz/src/shapes.cpp | 18 +----------------- modules/viz/src/vizcore.cpp | 27 +-------------------------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index c177a9b673..bcd6870df1 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -45,14 +45,6 @@ #include "precomp.hpp" -namespace cv -{ - namespace viz - { - template Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer& points); - } -} - /////////////////////////////////////////////////////////////////////////////////////////////// /// line widget implementation cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color) @@ -350,7 +342,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) polydata->GetPointData()->SetScalars(colors); vtkSmartPointer tube_filter = vtkSmartPointer::New(); - VtkUtils::SetInputData(tube_filter, polydata); + tube_filter->SetInputConnection(polydata->GetProducerPort()); tube_filter->SetRadius(axes->GetScaleFactor() / 50.0); tube_filter->SetNumberOfSides(6); @@ -445,11 +437,7 @@ namespace cv { namespace viz { namespace // Extract the edges so we have the grid vtkSmartPointer filter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 filter->SetInputConnection(grid->GetProducerPort()); -#else - filter->SetInputData(grid); -#endif filter->Update(); return filter->GetOutput(); } @@ -461,11 +449,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 mapper->SetInputConnection(grid->GetProducerPort()); -#else - mapper->SetInputData(grid); -#endif vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index ffb2d84f55..a6b2fffaa1 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -64,27 +64,6 @@ cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_p return makeTransformToGlobal(u, v, n, position); } -namespace cv { namespace viz -{ - template Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer& points); - - template<> Vec3f* vtkpoints_data(vtkSmartPointer& points) - { - CV_Assert(points->GetDataType() == VTK_FLOAT); - vtkDataArray *data = points->GetData(); - float *pointer = static_cast(data)->GetPointer(0); - return reinterpret_cast(pointer); - } - - template<> Vec3d* vtkpoints_data(vtkSmartPointer& points) - { - CV_Assert(points->GetDataType() == VTK_DOUBLE); - vtkDataArray *data = points->GetData(); - double *pointer = static_cast(data)->GetPointer(0); - return reinterpret_cast(pointer); - } -}} - /////////////////////////////////////////////////////////////////////////////////////////////// /// VizStorage implementation @@ -308,11 +287,7 @@ void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) vtkSmartPointer polydata = getPolyData(WMesh(mesh)); vtkSmartPointer normal_generator = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - normal_generator->SetInput(polydata); -#else - normal_generator->SetInputData(polydata); -#endif + normal_generator->SetInputConnection(polydata->GetProducerPort()); normal_generator->ComputePointNormalsOn(); normal_generator->ComputeCellNormalsOff(); From a3b1f29d23de60b4eaec656489d69e02e510ad33 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 8 Jan 2014 16:25:14 +0400 Subject: [PATCH 51/91] refactored spheres trajectory --- modules/viz/doc/widget.rst | 18 ++--- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/shapes.cpp | 87 +++++++++------------ 3 files changed, 47 insertions(+), 62 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 4119df0832..55dca7679f 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -799,23 +799,21 @@ represent the direction from previous position to the current. :: class CV_EXPORTS WTrajectorySpheres : public Widget3D { public: - WTrajectorySpheres(const std::vector &path, double line_length = 0.05f, - double init_sphere_radius = 0.021, sphere_radius = 0.007, - Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, + const Color &from = Color::red(), const Color &to = Color::white()); }; viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- Constructs a WTrajectorySpheres. -.. ocv:function:: WTrajectorySpheres(const std::vector &path, double line_length = 0.05f, double init_sphere_radius = 0.021, double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white()); - :param path: List of poses on a trajectory. - :param line_length: Length of the lines. - :param init_sphere_radius: Radius of the first sphere which represents the initial position of the camera. - :param sphere_radius: Radius of the rest of the spheres. - :param line_color: :ocv:class:`Color` of the lines. - :param sphere_color: :ocv:class:`Color` of the spheres. + :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] + :param line_length: Max length of the lines which point to previous position + :param sphere_radius: Radius of the spheres. + :param from: :ocv:class:`Color` for first sphere. + :param to: :ocv:class:`Color` for last sphere. Intermediate spheres will have interpolated color. viz::WCloud ----------- diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index ad75199f89..32665e74ab 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -279,8 +279,8 @@ namespace cv class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: - WTrajectorySpheres(const std::vector &path, double line_length = 0.05, double init_sphere_radius = 0.021, - double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, + const Color &from = Color::red(), const Color &to = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index bcd6870df1..347a58b6e4 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1155,71 +1155,58 @@ template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast &path, double line_length, double init_sphere_radius, double sphere_radius, - const Color &line_color, const Color &sphere_color) +cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_length, double radius, const Color &from, const Color &to) { - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - vtkIdType nr_poses = path.size(); - - // Create color arrays - vtkSmartPointer line_scalars = vtkSmartPointer::New(); - line_scalars->SetNumberOfComponents(3); - line_scalars->InsertNextTuple3(line_color[2], line_color[1], line_color[0]); - - // Create color array for sphere - vtkSmartPointer dummy_sphere = vtkSmartPointer::New(); - // Create the array for big sphere - dummy_sphere->SetRadius(init_sphere_radius); - dummy_sphere->Update(); - vtkIdType nr_points = dummy_sphere->GetOutput()->GetNumberOfCells(); - vtkSmartPointer sphere_scalars_init = VtkUtils::FillScalars(nr_points, sphere_color); + CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT); + CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16)); - // Create the array for small sphere - dummy_sphere->SetRadius(sphere_radius); - dummy_sphere->Update(); - nr_points = dummy_sphere->GetOutput()->GetNumberOfCells(); - vtkSmartPointer sphere_scalars = VtkUtils::FillScalars(nr_points, sphere_color); + Mat path64; + _path.getMat().convertTo(path64, CV_64F); + Affine3d *traj = path64.ptr(); + size_t total = path64.total(); + vtkSmartPointer append_filter = vtkSmartPointer::New(); - for (vtkIdType i = 0; i < nr_poses; ++i) + for(size_t i = 0; i < total; ++i) { - Point3f new_pos = path[i].translation(); + Vec3d curr = traj[i].translation(); vtkSmartPointer sphere_source = vtkSmartPointer::New(); - sphere_source->SetCenter(new_pos.x, new_pos.y, new_pos.z); - if (i == 0) - { - sphere_source->SetRadius(init_sphere_radius); - sphere_source->Update(); - sphere_source->GetOutput()->GetCellData()->SetScalars(sphere_scalars_init); - appendFilter->AddInputConnection(sphere_source->GetOutputPort()); - continue; - } - else - { - sphere_source->SetRadius(sphere_radius); - sphere_source->Update(); - sphere_source->GetOutput()->GetCellData()->SetScalars(sphere_scalars); - appendFilter->AddInputConnection(sphere_source->GetOutputPort()); - } + sphere_source->SetCenter(curr.val); + sphere_source->SetRadius( (i == 0) ? 2 * radius : radius ); + sphere_source->Update(); + + double alpha = static_cast(i)/total; + Color c = from * (1 - alpha) + to * alpha; + vtkSmartPointer polydata = sphere_source->GetOutput(); + polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); + append_filter->AddInputConnection(polydata->GetProducerPort()); - Affine3d relativeAffine = path[i].inv() * path[i-1]; - Vec3d v = path[i].rotation() * relativeAffine.translation(); - v = normalize(v) * line_length; + if (i > 0) + { + Vec3d prev = traj[i-1].translation(); + Vec3d lvec = prev - curr; + + if(norm(lvec) > line_length) + lvec = normalize(lvec) * line_length; - vtkSmartPointer line_source = vtkSmartPointer::New(); - line_source->SetPoint1(new_pos.x + v[0], new_pos.y + v[1], new_pos.z + v[2]); - line_source->SetPoint2(new_pos.x, new_pos.y, new_pos.z); - line_source->Update(); - line_source->GetOutput()->GetCellData()->SetScalars(line_scalars); + Vec3d lend = curr + lvec; - appendFilter->AddInputConnection(line_source->GetOutputPort()); + vtkSmartPointer line_source = vtkSmartPointer::New(); + line_source->SetPoint1(curr.val); + line_source->SetPoint2(lend.val); + line_source->Update(); + vtkSmartPointer polydata = line_source->GetOutput(); + polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); + append_filter->AddInputConnection(polydata->GetProducerPort()); + } } + append_filter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUseCellData(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); + VtkUtils::SetInputData(mapper, append_filter->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); From 0d702b83f4bbcdcaed1f3463e21c7bbe89445dee Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 8 Jan 2014 17:16:25 +0400 Subject: [PATCH 52/91] updated code to use mapper->SetInput instead of SetInputConnection. All widgets except plane, images ans texts --- modules/core/include/opencv2/core/affine.hpp | 8 ++ modules/viz/include/opencv2/viz.hpp | 3 - modules/viz/src/clouds.cpp | 40 +++------ modules/viz/src/interactor_style.cpp | 2 - modules/viz/src/shapes.cpp | 89 ++++++++------------ 5 files changed, 54 insertions(+), 88 deletions(-) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 62720b572a..0ee6fabe9b 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -113,6 +113,8 @@ namespace cv template operator Affine3() const; + template Affine3 cast() const; + Mat4 matrix; #if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H @@ -421,6 +423,12 @@ cv::Affine3::operator Affine3() const return Affine3(matrix); } +template template inline +cv::Affine3 cv::Affine3::cast() const +{ + return Affine3(matrix); +} + template inline cv::Affine3 cv::operator*(const cv::Affine3& affine1, const cv::Affine3& affine2) { diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index b281635a61..9ceed08506 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_HPP__ diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 15e9d4a616..4b4010eefd 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -54,9 +54,10 @@ cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors) vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetColorCloud(cloud, colors); + cloud_source->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(cloud_source->GetOutputPort()); + VtkUtils::SetInputData(mapper, cloud_source->GetOutput()); mapper->SetScalarModeToUsePointData(); mapper->ImmediateModeRenderingOff(); mapper->SetScalarRange(0, 255); @@ -74,9 +75,10 @@ cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) { vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetCloud(cloud); + cloud_source->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(cloud_source->GetOutputPort()); + VtkUtils::SetInputData(mapper, cloud_source->GetOutput()); mapper->ImmediateModeRenderingOff(); mapper->ScalarVisibilityOff(); @@ -127,15 +129,11 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co { // This is the first cloud mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polydata); -#else - mapper->SetInputData(polydata); -#endif mapper->SetScalarRange(0, 255); mapper->SetScalarModeToUsePointData(); mapper->ScalarVisibilityOn(); mapper->ImmediateModeRenderingOff(); + VtkUtils::SetInputData(mapper, polydata); actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); actor->GetProperty()->SetInterpolationToFlat(); @@ -147,16 +145,12 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co vtkPolyData *currdata = vtkPolyData::SafeDownCast(mapper->GetInput()); CV_Assert("Cloud Widget without data" && currdata); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInput(currdata); - appendFilter->AddInput(polydata); - mapper->SetInput(appendFilter->GetOutput()); -#else - appendFilter->AddInputData(currdata); - appendFilter->AddInputData(polydata); - mapper->SetInputData(appendFilter->GetOutput()); -#endif + vtkSmartPointer append_filter = vtkSmartPointer::New(); + append_filter->AddInputConnection(currdata->GetProducerPort()); + append_filter->AddInputConnection(polydata->GetProducerPort()); + append_filter->Update(); + + VtkUtils::SetInputData(mapper, append_filter->GetOutput()); actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); } @@ -245,11 +239,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetColorModeToMapScalars(); mapper->SetScalarModeToUsePointData(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polyData); -#else - mapper->SetInputData(polyData); -#endif + VtkUtils::SetInputData(mapper, polyData); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -326,11 +316,7 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); mapper->ImmediateModeRenderingOff(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polydata); -#else - mapper->SetInputData(polydata); -#endif + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); //actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints() / 10)); diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 19a3476a88..2e948e660d 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -564,7 +564,6 @@ void cv::viz::InteractorStyle::OnLeftButtonUp() void cv::viz::InteractorStyle::OnMiddleButtonDown() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) @@ -586,7 +585,6 @@ void cv::viz::InteractorStyle::OnMiddleButtonUp() void cv::viz::InteractorStyle::OnRightButtonDown() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 347a58b6e4..cc674dcf49 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -52,9 +52,10 @@ cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1(pt1.x, pt1.y, pt1.z); line->SetPoint2(pt2.x, pt2.y, pt2.z); + line->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(line->GetOutputPort()); + VtkUtils::SetInputData(mapper, line->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -153,9 +154,10 @@ cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resol sphere->SetPhiResolution(sphere_resolution); sphere->SetThetaResolution(sphere_resolution); sphere->LatLongTessellationOff(); + sphere->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(sphere->GetOutputPort()); + VtkUtils::SetInputData(mapper, sphere->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -203,9 +205,10 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness vtkSmartPointer transformPD = vtkSmartPointer::New(); transformPD->SetTransform(transform); transformPD->SetInputConnection(arrowSource->GetOutputPort()); + transformPD->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(transformPD->GetOutputPort()); + VtkUtils::SetInputData(mapper, transformPD->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -239,9 +242,10 @@ cv::viz::WCircle::WCircle(const Point3d& pt, double radius, double thickness, co vtkSmartPointer tf = vtkSmartPointer::New(); tf->SetTransform(t); tf->SetInputConnection(disk->GetOutputPort()); + tf->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(tf->GetOutputPort()); + VtkUtils::SetInputData(mapper, tf->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -270,9 +274,10 @@ cv::viz::WCylinder::WCylinder(const Point3d& pt_on_axis, const Point3d& axis_dir tuber->SetInputConnection(line->GetOutputPort()); tuber->SetRadius(radius); tuber->SetNumberOfSides(numsides); + tuber->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(tuber->GetOutputPort()); + VtkUtils::SetInputData(mapper, tuber->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -292,19 +297,21 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() cv::viz::WCube::WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame, const Color &color) { - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer cube; if (wire_frame) { - vtkSmartPointer cube = vtkSmartPointer::New(); - cube->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); - mapper->SetInputConnection(cube->GetOutputPort()); + cube = vtkSmartPointer::New(); + vtkOutlineSource::SafeDownCast(cube)->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); } else { - vtkSmartPointer cube = vtkSmartPointer::New(); - cube->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); - mapper->SetInputConnection(cube->GetOutputPort()); + cube = vtkSmartPointer::New(); + vtkCubeSource::SafeDownCast(cube)->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); } + cube->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, cube->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -345,6 +352,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) tube_filter->SetInputConnection(polydata->GetProducerPort()); tube_filter->SetRadius(axes->GetScaleFactor() / 50.0); tube_filter->SetNumberOfSides(6); + tube_filter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); @@ -400,7 +408,7 @@ cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color) polydata->GetPointData()->SetScalars(scalars); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, polydata); mapper->SetScalarRange(0, 255); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -449,7 +457,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(grid->GetProducerPort()); + VtkUtils::SetInputData(mapper, grid); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -478,15 +486,11 @@ cv::viz::WGrid::WGrid(const Vec4d &coefs, const Vec2i &dimensions, const Vec2d & vtkSmartPointer transform_filter = vtkSmartPointer::New(); transform_filter->SetTransform(transform); -#if VTK_MAJOR_VERSION <= 5 transform_filter->SetInputConnection(grid->GetProducerPort()); -#else - transform_filter->SetInputData(grid); -#endif transform_filter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(transform_filter->GetOutputPort()); + VtkUtils::SetInputData(mapper, transform_filter->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -544,6 +548,7 @@ void cv::viz::WText3D::setText(const String &text) CV_Assert("This widget does not support text." && textSource); textSource->SetText(text.c_str()); + textSource->Modified(); textSource->Update(); } @@ -620,11 +625,7 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); // Scale the image based on the Rect @@ -667,11 +668,7 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); mapper->SetInputConnection(flipFilter->GetOutputPort()); @@ -697,11 +694,7 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size &size) // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); Vec3d plane_center(size.width * 0.5, size.height * 0.5, 0.0); @@ -749,11 +742,7 @@ cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Ve // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); vtkSmartPointer plane = vtkSmartPointer::New(); @@ -809,11 +798,7 @@ void cv::viz::WImage3D::setImage(const Mat &image) // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); // Apply the texture @@ -855,11 +840,7 @@ namespace cv { namespace viz { namespace // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); Vec3d plane_center(0.0, 0.0, scale); @@ -958,7 +939,6 @@ namespace cv { namespace viz { namespace cv::viz::WCameraPosition::WCameraPosition(double scale) { vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, getPolyData(WCoordinateSystem(scale))); mapper->SetScalarModeToUsePointData(); @@ -979,7 +959,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -996,7 +976,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1042,14 +1022,14 @@ template<> cv::viz::WCameraPosition cv::viz::Widget::cast appendFilter = vtkSmartPointer::New(); + vtkSmartPointer append_filter = vtkSmartPointer::New(); // Bitwise and with 3 in order to limit the domain to 2 bits if (display_mode & WTrajectory::PATH) { Mat points = vtkTrajectorySource::ExtractPoints(_path); vtkSmartPointer polydata = getPolyData(WPolyLine(points, color)); - appendFilter->AddInputConnection(polydata->GetProducerPort()); + append_filter->AddInputConnection(polydata->GetProducerPort()); } if (display_mode & WTrajectory::FRAMES) @@ -1067,11 +1047,12 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca tensor_glyph->SymmetricOff(); tensor_glyph->ColorGlyphsOff(); - appendFilter->AddInputConnection(tensor_glyph->GetOutputPort()); + append_filter->AddInputConnection(tensor_glyph->GetOutputPort()); } + append_filter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, appendFilter->GetOutput()); + VtkUtils::SetInputData(mapper, append_filter->GetOutput()); mapper->SetScalarModeToUsePointData(); mapper->SetScalarRange(0, 255); @@ -1106,10 +1087,8 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33 tensor_glyph->ColorGlyphsOff(); tensor_glyph->Update(); - vtkSmartPointer polydata = tensor_glyph->GetOutput(); - vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, tensor_glyph->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1134,10 +1113,8 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d tensor_glyph->ColorGlyphsOff(); tensor_glyph->Update(); - vtkSmartPointer polydata = tensor_glyph->GetOutput(); - vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, tensor_glyph->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); From 64566e617805e28d25d213539d7097bc04ad5764 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 8 Jan 2014 17:46:32 +0400 Subject: [PATCH 53/91] minor --- modules/viz/src/interactor_style.cpp | 8 ++----- modules/viz/src/vizimpl.cpp | 31 ++++------------------------ 2 files changed, 6 insertions(+), 33 deletions(-) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 2e948e660d..c2583f9363 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -298,12 +298,8 @@ void cv::viz::InteractorStyle::OnKeyDown() { vtkSmartPointer cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); - Vec2d clip; - Vec3d focal, pos, view; - cam->GetClippingRange(clip.val); - cam->GetFocalPoint(focal.val); - cam->GetPosition(pos.val); - cam->GetViewUp(view.val); + Vec2d clip(cam->GetClippingRange()); + Vec3d focal(cam->GetFocalPoint()), pos(cam->GetPosition()), view(cam->GetViewUp()); Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); double angle = cam->GetViewAngle () / 180.0 * CV_PI; diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 4b9d65b43e..5974cc6e03 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -45,18 +45,9 @@ #include "precomp.hpp" - -#if (1 || !defined __APPLE__) && !defined _MSC_VER -vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew(); -vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew() -{ - return vtkRenderWindowInteractor::New(); -} -#endif - ///////////////////////////////////////////////////////////////////////////////////////////// cv::viz::Viz3d::VizImpl::VizImpl(const String &name) - : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) + : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); window_ = vtkSmartPointer::New(); @@ -72,12 +63,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) style_->setWidgetActorMap(widget_actor_map_); style_->UseTimersOn(); - ///////////////////////////////////////////////// -#if (1 || !defined __APPLE__) && !defined _MSC_VER - interactor_ = vtkSmartPointer::Take(vtkRenderWindowInteractorFixNew()); -#else interactor_ = vtkSmartPointer::New(); -#endif window_->AlphaBitPlanesOff(); window_->PointSmoothingOff(); @@ -88,7 +74,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); - interactor_->SetDesiredUpdateRate(30.0); + interactor_->SetDesiredUpdateRate(24.0); // Initialize and create timer, also create window interactor_->Initialize(); @@ -401,10 +387,7 @@ void cv::viz::Viz3d::VizImpl::converTo3DRay(const Point3d &window_coord, Point3d { Vec4d world_pt; vtkInteractorObserver::ComputeDisplayToWorld(renderer_, window_coord.x, window_coord.y, window_coord.z, world_pt.val); - - vtkCamera &active_camera = *renderer_->GetActiveCamera(); - Vec3d cam_pos; - active_camera.GetPosition(cam_pos.val); + Vec3d cam_pos(renderer_->GetActiveCamera()->GetPosition()); origin = cam_pos; direction = normalize(Vec3d(world_pt.val) - cam_pos); } @@ -479,7 +462,6 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation) } } - ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) { @@ -488,12 +470,7 @@ void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) } ////////////////////////////////////////////////////////////////////////////////////////////// -cv::String cv::viz::Viz3d::VizImpl::getWindowName() const -{ - return (window_ ? window_->GetWindowName() : ""); -} - -////////////////////////////////////////////////////////////////////////////////////////////// +cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_ ? window_->GetWindowName() : ""; } void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); } From 25b417e8b27ee6d6007c97ff56992551d103e2d1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 8 Jan 2014 19:43:20 +0400 Subject: [PATCH 54/91] added test for trajectories and fixed bug with float type --- modules/viz/include/opencv2/viz/widgets.hpp | 1 + modules/viz/src/precomp.hpp | 16 +++++ modules/viz/src/shapes.cpp | 79 ++++++++++----------- modules/viz/src/vizimpl.hpp | 18 ----- modules/viz/src/vtk/vtkTrajectorySource.cpp | 6 +- modules/viz/src/widget.cpp | 18 ++--- modules/viz/test/test_precomp.hpp | 15 ++++ modules/viz/test/test_viz3d.cpp | 37 ++-------- modules/viz/test/tests_simple.cpp | 43 +++++++++++ 9 files changed, 128 insertions(+), 105 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 32665e74ab..12373cd133 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -279,6 +279,7 @@ namespace cv class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: + //! Takes vector> and displays trajectory of the given path WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white()); }; diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 155612724e..3f4feaf046 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -221,6 +221,22 @@ namespace cv return scalars; } }; + + inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) + { + vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); + vtk_matrix->DeepCopy(matrix.val); + return vtk_matrix; + } + + inline Color vtkcolor(const Color& color) + { + Color scaled_color = color * (1.0/255.0); + std::swap(scaled_color[0], scaled_color[2]); + return scaled_color; + } + + template inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); } } } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index cc674dcf49..f4b68a9fb8 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -70,6 +70,35 @@ template<> cv::viz::WLine cv::viz::Widget::cast() return static_cast(widget); } +/////////////////////////////////////////////////////////////////////////////////////////////// +/// sphere widget implementation + +cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resolution, const Color &color) +{ + vtkSmartPointer sphere = vtkSmartPointer::New(); + sphere->SetRadius(radius); + sphere->SetCenter(center.x, center.y, center.z); + sphere->SetPhiResolution(sphere_resolution); + sphere->SetThetaResolution(sphere_resolution); + sphere->LatLongTessellationOff(); + sphere->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, sphere->GetOutput()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); + setColor(color); +} + +template<> cv::viz::WSphere cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} + /////////////////////////////////////////////////////////////////////////////////////////////// /// plane widget implementation @@ -143,51 +172,21 @@ template<> cv::viz::WPlane cv::viz::Widget::cast() return static_cast(widget); } -/////////////////////////////////////////////////////////////////////////////////////////////// -/// sphere widget implementation - -cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resolution, const Color &color) -{ - vtkSmartPointer sphere = vtkSmartPointer::New(); - sphere->SetRadius(radius); - sphere->SetCenter(center.x, center.y, center.z); - sphere->SetPhiResolution(sphere_resolution); - sphere->SetThetaResolution(sphere_resolution); - sphere->LatLongTessellationOff(); - sphere->Update(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, sphere->GetOutput()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); - setColor(color); -} - -template<> cv::viz::WSphere cv::viz::Widget::cast() -{ - Widget3D widget = this->cast(); - return static_cast(widget); -} - /////////////////////////////////////////////////////////////////////////////////////////////// /// arrow widget implementation cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness, const Color &color) { - vtkSmartPointer arrowSource = vtkSmartPointer::New(); - arrowSource->SetShaftRadius(thickness); - // The thickness and radius of the tip are adjusted based on the thickness of the arrow - arrowSource->SetTipRadius(thickness * 3.0); - arrowSource->SetTipLength(thickness * 10.0); + vtkSmartPointer arrow_source = vtkSmartPointer::New(); + arrow_source->SetShaftRadius(thickness); + arrow_source->SetTipRadius(thickness * 3.0); + arrow_source->SetTipLength(thickness * 10.0); RNG rng = theRNG(); Vec3d arbitrary(rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0)); Vec3d startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); - double length = cv::norm(endPoint - startPoint); + double length = norm(endPoint - startPoint); Vec3d xvec = normalized(endPoint - startPoint); Vec3d zvec = normalized(xvec.cross(arbitrary)); @@ -204,7 +203,7 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness // Transform the polydata vtkSmartPointer transformPD = vtkSmartPointer::New(); transformPD->SetTransform(transform); - transformPD->SetInputConnection(arrowSource->GetOutputPort()); + transformPD->SetInputConnection(arrow_source->GetOutputPort()); transformPD->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -908,14 +907,14 @@ namespace cv { namespace viz { namespace actor->SetTexture(texture); } - static vtkSmartPointer createFrustrum(double aspect_ratio, double fovy, double scale) + static vtkSmartPointer createFrustum(double aspect_ratio, double fovy, double scale) { vtkSmartPointer camera = vtkSmartPointer::New(); 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); + camera->SetClippingRange(1e-9, scale); double planesArray[24]; camera->GetFrustumPlanes(aspect_ratio, planesArray); @@ -956,7 +955,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const double fovy = 2.0 * atan2(c_y, f_y) * 180 / CV_PI; double aspect_ratio = f_y / f_x; - vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); + vtkSmartPointer polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); VtkUtils::SetInputData(mapper, polydata); @@ -973,7 +972,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); double fovy = fov[1] * 180 / CV_PI; - vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); + vtkSmartPointer polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); VtkUtils::SetInputData(mapper, polydata); diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index d5274b49ce..03d5c0325e 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -179,34 +179,16 @@ private: bool removeActorFromRenderer(const vtkSmartPointer &actor); }; - namespace cv { namespace viz { - inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) - { - vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); - vtk_matrix->DeepCopy(matrix.val); - return vtk_matrix; - } - struct color_tag {}; struct gray_tag {}; inline Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } inline Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } - inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } - template inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } - - inline Color vtkcolor(const Color& color) - { - Color scaled_color = color * (1.0/255.0); - std::swap(scaled_color[0], scaled_color[2]); - return scaled_color; - } - struct ConvertToVtkImage { struct Impl diff --git a/modules/viz/src/vtk/vtkTrajectorySource.cpp b/modules/viz/src/vtk/vtkTrajectorySource.cpp index 1510208819..e098a1d553 100644 --- a/modules/viz/src/vtk/vtkTrajectorySource.cpp +++ b/modules/viz/src/vtk/vtkTrajectorySource.cpp @@ -59,9 +59,8 @@ void cv::viz::vtkTrajectorySource::SetTrajectory(InputArray _traj) Mat traj; _traj.getMat().convertTo(traj, CV_64F); - const Affine3d* dpath = _traj.getMat().ptr(); - - size_t total = _traj.total(); + const Affine3d* dpath = traj.ptr(); + size_t total = traj.total(); points = vtkSmartPointer::New(); points->SetDataType(VTK_DOUBLE); @@ -81,7 +80,6 @@ void cv::viz::vtkTrajectorySource::SetTrajectory(InputArray _traj) } } - cv::Mat cv::viz::vtkTrajectorySource::ExtractPoints(InputArray _traj) { CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 23099ba728..b0e84037fd 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -140,14 +140,11 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) { if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) { + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); vtkSmartPointer normals = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - normals->SetInput(actor->GetMapper()->GetInput()); -#else - normals->SetInputData(actor->GetMapper()->GetInput()); -#endif + VtkUtils::SetInputData(normals, mapper->GetInput()); normals->Update(); - vtkDataSetMapper::SafeDownCast(actor->GetMapper())->SetInputConnection(normals->GetOutputPort()); + VtkUtils::SetInputData(mapper, normals->GetOutput()); } actor->GetProperty()->SetInterpolationToGouraud(); break; @@ -156,14 +153,11 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) { if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) { + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); vtkSmartPointer normals = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - normals->SetInput(actor->GetMapper()->GetInput()); -#else - normals->SetInputData(actor->GetMapper()->GetInput()); -#endif + VtkUtils::SetInputData(normals, mapper->GetInput()); normals->Update(); - vtkDataSetMapper::SafeDownCast(actor->GetMapper())->SetInputConnection(normals->GetOutputPort()); + VtkUtils::SetInputData(mapper, normals->GetOutput()); } actor->GetProperty()->SetInterpolationToPhong(); break; diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index efc89b27f5..e4fe78420c 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -78,6 +78,21 @@ namespace cv { return Path::combine(cvtest::TS::ptr()->get_data_path(), "dragon.ply"); } + + template + inline std::vector< Affine3<_Tp> > generate_test_trajectory() + { + std::vector< Affine3<_Tp> > result; + + for (int i = 0, j = 0; i <= 270; i += 3, j += 10) + { + double x = 2 * cos(i * 3 * CV_PI/180.0) * (1.0 + 0.5 * cos(1.2 + i * 1.2 * CV_PI/180.0)); + double y = 0.25 + i/270.0 + sin(j * CV_PI/180.0) * 0.2 * sin(0.6 + j * 1.5 * CV_PI/180.0); + double z = 2 * sin(i * 3 * CV_PI/180.0) * (1.0 + 0.5 * cos(1.2 + i * CV_PI/180.0)); + result.push_back(viz::makeCameraPose(Vec3d(x, y, z), Vec3d::all(0.0), Vec3d(0.0, 1.0, 0.0))); + } + return result; + } } #endif diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 6bc3622c63..aec326508e 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -48,46 +48,21 @@ TEST(Viz_viz3d, develop) cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); //cv::viz::Mesh3d mesh = cv::viz::Mesh3d::load(get_dragon_ply_file_path()); - //theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); cv::viz::Viz3d viz("abc"); viz.setBackgroundColor(cv::viz::Color::mlab()); - viz.showWidget("coo", cv::viz::WCoordinateSystem(0.1)); - - -// double c = cos(CV_PI/6); -// std::vector pts; -// pts.push_back(Vec3d(0, 0.0, -1.0)); -// pts.push_back(Vec3d(1, c, -0.5)); -// pts.push_back(Vec3d(2, c, 0.5)); -// pts.push_back(Vec3d(3, 0.0, 1.0)); -// pts.push_back(Vec3d(4, -c, 0.5)); -// pts.push_back(Vec3d(5, -c, -0.5)); - -// viz.showWidget("pl", cv::viz::WPolyLine(Mat(pts), cv::viz::Color::green())); - - //viz.showWidget("pl", cv::viz::WPolyLine(cloud.colRange(0, 100), cv::viz::Color::green())); - //viz.spin(); - - //cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); + viz.showWidget("coo", cv::viz::WCoordinateSystem(1)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); - std::vector gt, es; - cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); + //---->>>>> + //std::vector gt, es; + //cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); //cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); - gt.resize(20); - - Affine3d inv = gt[0].inv(); - for(size_t i = 0; i < gt.size(); ++i) - gt[i] = inv * gt[i]; - - //viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::PATH, 1.f, viz::Color::blue()), gt[0].inv()); - viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::BOTH, 0.01f, viz::Color::blue())); - - //viz.showWidget("tr", viz::WTrajectory(es, viz::WTrajectory::PATH, 1.f, viz::Color::red()), gt[0].inv()); + //cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); + //---->>>>> //theRNG().fill(colors, cv::RNG::UNIFORM, 0, 255); //viz.showWidget("c", cv::viz::WCloud(cloud, colors)); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 6f61a806c6..93428c6b95 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -156,6 +156,49 @@ TEST(Viz, DISABLED_show_sampled_normals) viz.spin(); } +TEST(Viz, DISABLED_show_trajectories) +{ + std::vector path = generate_test_trajectory(), sub0, sub1, sub2, sub3, sub4, sub5; + + Mat(path).rowRange(0, path.size()/10+1).copyTo(sub0); + Mat(path).rowRange(path.size()/10, path.size()/5+1).copyTo(sub1); + Mat(path).rowRange(path.size()/5, 11*path.size()/12).copyTo(sub2); + Mat(path).rowRange(11*path.size()/12, path.size()).copyTo(sub3); + Mat(path).rowRange(3*path.size()/4, 33*path.size()/40).copyTo(sub4); + Mat(path).rowRange(33*path.size()/40, 9*path.size()/10).copyTo(sub5); + Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); + + Viz3d viz("show_trajectories"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("sub0", WTrajectorySpheres(sub0, 0.25, 0.07)); + viz.showWidget("sub1", WTrajectory(sub1, WTrajectory::PATH, 0.2, Color::brown())); + viz.showWidget("sub2", WTrajectory(sub2, WTrajectory::FRAMES, 0.2)); + viz.showWidget("sub3", WTrajectory(sub3, WTrajectory::BOTH, 0.2, Color::green())); + viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3)); + viz.showWidget("sub5", WTrajectoryFrustums(sub5, Vec2d(0.78, 0.78), 0.15)); + + int i = 0; + while(!viz.wasStopped()) + { + double a = --i % 360; + Vec3d pose(sin(a * CV_PI/180), 0.7, cos(a * CV_PI/180)); + viz.setViewerPose(makeCameraPose(pose * 7.5, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); + viz.spinOnce(20, true); + } + //viz.spin(); +} + +TEST(Viz, DISABLED_show_trajectory_reposition) +{ + std::vector path = generate_test_trajectory(); + + Viz3d viz("show_trajectory_reposition_to_origin"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("sub3", WTrajectory(Mat(path).rowRange(0, path.size()/3), WTrajectory::BOTH, 0.2, Color::brown()), path.front().inv()); + viz.spin(); +} + + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); From e478d6b1e9d7eabc1901875b75da945dcba114f9 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 9 Jan 2014 19:08:06 +0400 Subject: [PATCH 55/91] renamed cv::viz::get() to getWindowByName() --- modules/viz/doc/viz3d.rst | 8 ++++---- modules/viz/include/opencv2/viz.hpp | 4 ++-- modules/viz/include/opencv2/viz/widgets.hpp | 8 ++++---- modules/viz/src/vizcore.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 1cb9b5dc3b..215437eda1 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -34,11 +34,11 @@ Constructs camera pose from position, focal_point and up_vector (see gluLookAt() This function returns pose of the camera in global coordinate frame. -viz::get +viz::getWindowByName -------- Retrieves a window by its name. -.. ocv:function:: Viz3d get(const String &window_name) +.. ocv:function:: Viz3d getWindowByName(const String &window_name) :param window_name: Name of the window that is to be retrieved. @@ -51,8 +51,8 @@ This function returns a :ocv:class:`Viz3d` object with the given name. .. code-block:: cpp /// window and window_2 are the same windows. - viz::Viz3d window = viz::get("myWindow"); - viz::Viz3d window_2 = viz::get("Viz - myWindow"); + viz::Viz3d window = viz::getWindowByName("myWindow"); + viz::Viz3d window_2 = viz::getWindowByName("Viz - myWindow"); viz::isNan ---------- diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 9ceed08506..d2b46dd0e5 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -61,9 +61,9 @@ namespace cv CV_EXPORTS Affine3d makeCameraPose(const Vec3d& position, const Vec3d& focal_point, const Vec3d& y_dir); //! retrieves a window by its name. If no window with such name, then it creates new. - CV_EXPORTS Viz3d get(const String &window_name); + CV_EXPORTS Viz3d getWindowByName(const String &window_name); - //! Unregisters all Viz windows from internal database. After it 'get()' will create new windows instead getting existing from the database. + //! Unregisters all Viz windows from internal database. After it 'getWindowByName()' will create new windows instead getting existing from the database. CV_EXPORTS void unregisterAllWindows(); //! checks float value for Nan diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 12373cd133..5b575774f1 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -141,8 +141,8 @@ namespace cv class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4d& coefs, double size = 1.f, const Color &color = Color::white()); - WPlane(const Vec4d& coefs, const Point3d& pt, double size = 1.f, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, const Point3d& pt, double size = 1.0, const Color &color = Color::white()); }; class CV_EXPORTS WSphere : public Widget3D @@ -227,7 +227,7 @@ namespace cv class CV_EXPORTS WCoordinateSystem : public Widget3D { public: - WCoordinateSystem(double scale = 1.f); + WCoordinateSystem(double scale = 1.0); }; class CV_EXPORTS WGrid : public Widget3D @@ -263,7 +263,7 @@ namespace cv enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; //! Takes vector> and displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white()); + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectoryFrustums : public Widget3D diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index a6b2fffaa1..bf01ff5a56 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -119,7 +119,7 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) return output; } -cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } +cv::viz::Viz3d cv::viz::getWindowByName(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } /////////////////////////////////////////////////////////////////////////////////////////////// From d591bd875b659d6128d47e3b1cbd52e906d7d762 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 9 Jan 2014 19:34:55 +0400 Subject: [PATCH 56/91] fixed crash in enabling shading for polydata widgets --- modules/viz/src/clouds.cpp | 2 +- modules/viz/src/precomp.hpp | 16 ++++++++++++++++ modules/viz/src/vizcore.cpp | 16 ++-------------- modules/viz/src/widget.cpp | 16 ++++++++-------- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 4b4010eefd..ceb4d9c0ba 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -313,7 +313,7 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) cell_array->Squeeze(); polydata->SetStrips(cell_array); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); mapper->ImmediateModeRenderingOff(); VtkUtils::SetInputData(mapper, polydata); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 3f4feaf046..425502d641 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -220,6 +220,22 @@ namespace cv scalars->SetArray(color_data->val, size * 3, 0); return scalars; } + + static vtkSmartPointer ComputeNormals(vtkSmartPointer polydata) + { + vtkSmartPointer normals_generator = vtkSmartPointer::New(); + normals_generator->ComputePointNormalsOn(); + normals_generator->ComputeCellNormalsOff(); + normals_generator->SetFeatureAngle(0.1); + normals_generator->SetSplitting(0); + normals_generator->SetConsistency(1); + normals_generator->SetAutoOrientNormals(0); + normals_generator->SetFlipNormals(0); + normals_generator->SetNonManifoldTraversal(1); + VtkUtils::SetInputData(normals_generator, polydata); + normals_generator->Update(); + return normals_generator->GetOutput(); + } }; inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index bf01ff5a56..19e2b9394a 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -285,21 +285,9 @@ void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) { vtkSmartPointer polydata = getPolyData(WMesh(mesh)); + vtkSmartPointer with_normals = VtkUtils::ComputeNormals(polydata); - vtkSmartPointer normal_generator = vtkSmartPointer::New(); - normal_generator->SetInputConnection(polydata->GetProducerPort()); - normal_generator->ComputePointNormalsOn(); - normal_generator->ComputeCellNormalsOff(); - - normal_generator->SetFeatureAngle(0.1); - normal_generator->SetSplitting(0); - normal_generator->SetConsistency(1); - normal_generator->SetAutoOrientNormals(0); - normal_generator->SetFlipNormals(0); - normal_generator->SetNonManifoldTraversal(1); - normal_generator->Update(); - - vtkSmartPointer generic_normals = normal_generator->GetOutput()->GetPointData()->GetNormals(); + vtkSmartPointer generic_normals = with_normals->GetPointData()->GetNormals(); if(generic_normals) { Mat normals(1, generic_normals->GetNumberOfTuples(), CV_64FC3); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index b0e84037fd..a633f24ba6 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -141,10 +141,10 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) { vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); - vtkSmartPointer normals = vtkSmartPointer::New(); - VtkUtils::SetInputData(normals, mapper->GetInput()); - normals->Update(); - VtkUtils::SetInputData(mapper, normals->GetOutput()); + CV_Assert("Can't set shading property for such type of widget" && mapper); + + vtkSmartPointer with_normals = VtkUtils::ComputeNormals(mapper->GetInput()); + VtkUtils::SetInputData(mapper, with_normals); } actor->GetProperty()->SetInterpolationToGouraud(); break; @@ -154,10 +154,10 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) { vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); - vtkSmartPointer normals = vtkSmartPointer::New(); - VtkUtils::SetInputData(normals, mapper->GetInput()); - normals->Update(); - VtkUtils::SetInputData(mapper, normals->GetOutput()); + CV_Assert("Can't set shading property for such type of widget" && mapper); + + vtkSmartPointer with_normals = VtkUtils::ComputeNormals(mapper->GetInput()); + VtkUtils::SetInputData(mapper, with_normals); } actor->GetProperty()->SetInterpolationToPhong(); break; From 8309d19f319df0ac23aa7e27f859d6bf2e40b0e5 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 9 Jan 2014 20:26:51 +0400 Subject: [PATCH 57/91] renamed Mesh3d -> Mesh --- modules/viz/doc/viz3d.rst | 20 +++++------ modules/viz/doc/widget.rst | 38 ++++++++------------- modules/viz/include/opencv2/viz.hpp | 2 +- modules/viz/include/opencv2/viz/types.hpp | 22 ++++++------ modules/viz/include/opencv2/viz/widgets.hpp | 3 +- modules/viz/src/clouds.cpp | 16 +++++++-- modules/viz/src/types.cpp | 6 ++-- modules/viz/src/vizcore.cpp | 2 +- modules/viz/test/tests_simple.cpp | 8 ++--- 9 files changed, 60 insertions(+), 57 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 215437eda1..9d4bb674d3 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -468,31 +468,31 @@ This class a represents BGR color. :: static Color gray(); }; -viz::Mesh3d +viz::Mesh ----------- -.. ocv:class:: Mesh3d +.. ocv:class:: Mesh This class wraps mesh attributes, and it can load a mesh from a ``ply`` file. :: - class CV_EXPORTS Mesh3d + class CV_EXPORTS Mesh { public: - Mat cloud, colors; + Mat cloud, colors, normals; + + //! Raw integer list of the form: (n,id1,id2,...,idn, n,id1,id2,...,idn, ...) + //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud. Mat polygons; //! Loads mesh from a given ply file - static Mesh3d load(const String& file); - - private: - /* hidden */ + static Mesh load(const String& file); }; -viz::Mesh3d::load +viz::Mesh::load --------------------- Loads a mesh from a ``ply`` file. -.. ocv:function:: static Mesh3d load(const String& file) +.. ocv:function:: static Mesh load(const String& file) :param file: File name (for no only PLY is supported) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 55dca7679f..a8dcedd4b9 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -264,8 +264,6 @@ This 3D Widget defines a finite plane. :: public: WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); - private: - /* hidden */ }; viz::WPlane::WPlane @@ -437,9 +435,6 @@ This 3D Widget defines a poly line. :: { public: WPolyLine(InputArray points, const Color &color = Color::white()); - - private: - /* hidden */ }; viz::WPolyLine::WPolyLine @@ -464,8 +459,6 @@ This 3D Widget defines a grid. :: WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - private: - /* hidden */ }; viz::WGrid::WGrid @@ -732,14 +725,14 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white(),; + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. @@ -828,9 +821,6 @@ This 3D Widget defines a point cloud. :: WCloud(InputArray cloud, InputArray colors); //! All points in cloud have the same color WCloud(InputArray cloud, const Color &color = Color::white()); - - private: - /* hidden */ }; viz::WCloud::WCloud @@ -868,9 +858,6 @@ This 3D Widget defines a collection of clouds. :: void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()); //! All points in cloud have the same color void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3d &pose = Affine3d::Identity()); - - private: - /* hidden */ }; viz::WCloudCollection::WCloudCollection @@ -911,9 +898,6 @@ This 3D Widget represents normals of a point cloud. :: { public: WCloudNormals(InputArray cloud, InputArray normals, int level = 100, double scale = 0.02f, const Color &color = Color::white()); - - private: - /* hidden */ }; viz::WCloudNormals::WCloudNormals @@ -939,16 +923,22 @@ This 3D Widget defines a mesh. :: class CV_EXPORTS WMesh : public Widget3D { public: - WMesh(const Mesh3d &mesh); - - private: - /* hidden */ + WMesh(const Mesh &mesh); + WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); }; viz::WMesh::WMesh ----------------- Constructs a WMesh. -.. ocv:function:: WMesh(const Mesh3d &mesh) +.. ocv:function:: WMesh(const Mesh &mesh) + + :param mesh: :ocv:class:`Mesh` object that will be displayed. + +.. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); - :param mesh: :ocv:class:`Mesh3d` object that will be displayed. + :param cloud: Points of the mesh object. + :param polygons: Points of the mesh object. + :param colors: Point colors. + :param normals: Point normals. + diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index d2b46dd0e5..9b1f21a8d5 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -111,7 +111,7 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Computing normals for mesh - CV_EXPORTS void computeNormals(const Mesh3d& mesh, OutputArray normals); + CV_EXPORTS void computeNormals(const Mesh& mesh, OutputArray normals); } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 1e222c8004..01ddd0289e 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -104,15 +104,17 @@ namespace cv static Color amethyst(); }; - class CV_EXPORTS Mesh3d + class CV_EXPORTS Mesh { public: - Mat cloud, colors, normals; + + //! Raw integer list of the form: (n,id1,id2,...,idn, n,id1,id2,...,idn, ...) + //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud. Mat polygons; //! Loads mesh from a given ply file - static Mesh3d load(const String& file); + static Mesh load(const String& file); }; class CV_EXPORTS Camera @@ -123,17 +125,17 @@ namespace cv explicit Camera(const Matx33d &K, const Size &window_size); explicit Camera(const Matx44d &proj, const Size &window_size); - inline const Vec2d & getClip() const { return clip_; } - inline void setClip(const Vec2d &clip) { clip_ = clip; } + const Vec2d & getClip() const { return clip_; } + void setClip(const Vec2d &clip) { clip_ = clip; } - inline const Size & getWindowSize() const { return window_size_; } + const Size & getWindowSize() const { return window_size_; } void setWindowSize(const Size &window_size); - inline const Vec2d& getFov() const { return fov_; } - inline void setFov(const Vec2d& fov) { fov_ = fov; } + const Vec2d& getFov() const { return fov_; } + void setFov(const Vec2d& fov) { fov_ = fov; } - inline const Vec2d& getPrincipalPoint() const { return principal_point_; } - inline const Vec2d& getFocalLength() const { return focal_; } + const Vec2d& getPrincipalPoint() const { return principal_point_; } + const Vec2d& getFocalLength() const { return focal_; } void computeProjectionMatrix(Matx44d &proj) const; diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 5b575774f1..4dde94df62 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -316,7 +316,8 @@ namespace cv class CV_EXPORTS WMesh : public Widget3D { public: - WMesh(const Mesh3d &mesh); + WMesh(const Mesh &mesh); + WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index ceb4d9c0ba..e7759e323d 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -257,7 +257,7 @@ template<> cv::viz::WCloudNormals cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// Mesh Widget implementation -cv::viz::WMesh::WMesh(const Mesh3d &mesh) +cv::viz::WMesh::WMesh(const Mesh &mesh) { CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1); @@ -300,8 +300,8 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) vtkSmartPointer cell_array = vtkSmartPointer::New(); int idx = 0; - int poly_size = mesh.polygons.total(); - for (int i = 0; i < poly_size; ++idx) + size_t polygons_size = mesh.polygons.total(); + for (size_t i = 0; i < polygons_size; ++idx) { int n_points = polygons[i++]; @@ -330,6 +330,16 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) WidgetAccessor::setProp(*this, actor); } +cv::viz::WMesh::WMesh(InputArray cloud, InputArray polygons, InputArray colors, InputArray normals) +{ + Mesh mesh; + mesh.cloud = cloud.getMat(); + mesh.colors = colors.getMat(); + mesh.normals = normals.getMat(); + mesh.polygons = polygons.getMat(); + *this = WMesh(mesh); +} + template<> CV_EXPORTS cv::viz::WMesh cv::viz::Widget::cast() { Widget3D widget = this->cast(); diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index d233e735df..09a2f4d0f3 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -61,9 +61,9 @@ namespace cv { namespace viz { namespace { struct MeshUtils { - static Mesh3d loadMesh(const String &file) + static Mesh loadMesh(const String &file) { - Mesh3d mesh; + Mesh mesh; vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(file.c_str()); @@ -128,7 +128,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::Mesh3d cv::viz::Mesh3d::load(const String& file) +cv::viz::Mesh cv::viz::Mesh::load(const String& file) { return MeshUtils::loadMesh(file); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 19e2b9394a..d00a22b4c5 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -282,7 +282,7 @@ void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int /////////////////////////////////////////////////////////////////////////////////////////////// /// Computing normals for mesh -void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) +void cv::viz::computeNormals(const Mesh& mesh, OutputArray _normals) { vtkSmartPointer polydata = getPolyData(WMesh(mesh)); vtkSmartPointer with_normals = VtkUtils::ComputeNormals(polydata); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 93428c6b95..4fd0dc4fc4 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -106,7 +106,7 @@ TEST(Viz, DISABLED_show_cloud_collection) TEST(Viz, DISABLED_show_mesh) { - Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Mesh mesh = Mesh::load(get_dragon_ply_file_path()); Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); @@ -118,7 +118,7 @@ TEST(Viz, DISABLED_show_mesh) TEST(Viz, DISABLED_show_mesh_random_colors) { - Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Mesh mesh = Mesh::load(get_dragon_ply_file_path()); theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); @@ -144,7 +144,7 @@ TEST(Viz, DISABLED_show_polyline) TEST(Viz, DISABLED_show_sampled_normals) { - Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Mesh mesh = Mesh::load(get_dragon_ply_file_path()); computeNormals(mesh, mesh.normals); Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); @@ -201,7 +201,7 @@ TEST(Viz, DISABLED_show_trajectory_reposition) TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { - Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Mesh mesh = Mesh::load(get_dragon_ply_file_path()); Viz3d viz("spin_twice"); viz.showWidget("coosys", WCoordinateSystem()); From 462d516743bf9bc5d6fc8eabe1a250828e6b8bae Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 10 Jan 2014 00:31:27 +0400 Subject: [PATCH 58/91] added test for camera positions, slightly refactored the widgets --- modules/viz/src/shapes.cpp | 140 +++++++++++++----------------- modules/viz/test/tests_simple.cpp | 27 ++++++ 2 files changed, 86 insertions(+), 81 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index f4b68a9fb8..422ea9be33 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -622,29 +622,29 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) ConvertToVtkImage::convert(image, vtk_image); // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); - flipFilter->Update(); + vtkSmartPointer flip_filter = vtkSmartPointer::New(); + flip_filter->SetFilteredAxis(1); // Vertical flip + flip_filter->SetInputConnection(vtk_image->GetProducerPort()); + flip_filter->Update(); // Scale the image based on the Rect vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Scale(double(image.cols)/rect.width,double(image.rows)/rect.height,1.0); + transform->Scale(image.cols/(double)rect.width, image.rows/(double)rect.height, 1.0); vtkSmartPointer image_reslice = vtkSmartPointer::New(); image_reslice->SetResliceTransform(transform); - image_reslice->SetInputConnection(flipFilter->GetOutputPort()); + image_reslice->SetInputConnection(flip_filter->GetOutputPort()); image_reslice->SetOutputDimensionality(2); image_reslice->InterpolateOn(); image_reslice->AutoCropOutputOn(); - vtkSmartPointer imageMapper = vtkSmartPointer::New(); - imageMapper->SetInputConnection(image_reslice->GetOutputPort()); - imageMapper->SetColorWindow(255); // OpenCV color - imageMapper->SetColorLevel(127.5); + vtkSmartPointer image_mapper = vtkSmartPointer::New(); + image_mapper->SetInputConnection(image_reslice->GetOutputPort()); + image_mapper->SetColorWindow(255); // OpenCV color + image_mapper->SetColorLevel(127.5); vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(imageMapper); + actor->SetMapper(image_mapper); actor->SetPosition(rect.x, rect.y); WidgetAccessor::setProp(*this, actor); @@ -820,11 +820,33 @@ namespace cv { namespace viz { namespace { struct CameraPositionUtils { - static void projectImage(double fovy, double far_end_height, const Mat &image, - double scale, const Color &color, vtkSmartPointer actor) + static vtkSmartPointer createFrustum(double aspect_ratio, double fovy, double scale) { - // Create a camera vtkSmartPointer camera = vtkSmartPointer::New(); + 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(1e-9, scale); + + double planes_array[24]; + camera->GetFrustumPlanes(aspect_ratio, planes_array); + + vtkSmartPointer planes = vtkSmartPointer::New(); + planes->SetFrustumPlanes(planes_array); + + vtkSmartPointer frustumSource = vtkSmartPointer::New(); + frustumSource->SetPlanes(planes); + + vtkSmartPointer extract_edges = vtkSmartPointer::New(); + extract_edges->SetInputConnection(frustumSource->GetOutputPort()); + extract_edges->Update(); + + return extract_edges->GetOutput(); + } + + static vtkSmartPointer projectImage(double fovy, double far_end_height, const Mat &image, double scale, const Color &color) + { float aspect_ratio = float(image.cols)/float(image.rows); // Create the vtk image @@ -832,66 +854,47 @@ namespace cv { namespace viz { namespace 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 flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); - flipFilter->Update(); + if(image.channels() == 1) + { + double gray = color[2] * 0.299 + color[1] * 0.578 + color[0] * 0.144; + vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, gray); + } + else + { + 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[0], plane_center[1], plane_center[2]); + plane->SetCenter(plane_center.val); plane->SetNormal(0.0, 0.0, 1.0); vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); - transform->Translate(plane_center[0], plane_center[1], plane_center[2]); + 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(flipFilter->GetOutputPort()); + texture->SetInputConnection(vtk_image->GetProducerPort()); - vtkSmartPointer texturePlane = vtkSmartPointer::New(); - texturePlane->SetInputConnection(plane->GetOutputPort()); + 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); - 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 planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = - vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); - - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); + vtkSmartPointer frustum = createFrustum(aspect_ratio, fovy, scale); // Frustum needs to be textured or else it can't be combined with image vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(filter->GetOutputPort()); + 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); @@ -903,35 +906,12 @@ namespace cv { namespace viz { namespace vtkSmartPointer planeMapper = vtkSmartPointer::New(); planeMapper->SetInputConnection(appendFilter->GetOutputPort()); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(planeMapper); actor->SetTexture(texture); - } - static vtkSmartPointer createFrustum(double aspect_ratio, double fovy, double scale) - { - vtkSmartPointer camera = vtkSmartPointer::New(); - 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(1e-9, scale); - - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); - - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - - vtkSmartPointer extract_edges = vtkSmartPointer::New(); - extract_edges->SetInputConnection(frustumSource->GetOutputPort()); - extract_edges->Update(); - - return extract_edges->GetOutput(); + return actor; } - }; }}} @@ -994,8 +974,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, do double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI; double far_end_height = 2.00 * c_y * scale / f_y; - vtkSmartPointer actor = vtkSmartPointer::New(); - CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); + vtkSmartPointer actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color); WidgetAccessor::setProp(*this, actor); } @@ -1005,8 +984,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, const Mat &image, do double fovy = fov[1] * 180.0 / CV_PI; double far_end_height = 2.0 * scale * tan(fov[1] * 0.5); - vtkSmartPointer actor = vtkSmartPointer::New(); - CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); + vtkSmartPointer actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color); WidgetAccessor::setProp(*this, actor); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 4fd0dc4fc4..4f37f32212 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -199,6 +199,33 @@ TEST(Viz, DISABLED_show_trajectory_reposition) } + +TEST(Viz, show_camera_positions) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat chs[3]; split(lena, chs); + Mat gray = 0.114 * chs[0] + 0.58 * chs[1] + 0.3 * chs[2]; + + Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); + + Affine3d poses[2]; + for(int i = 0; i < 2; ++i) + { + Vec3d pose = 5 * Vec3d(sin(3.14 + 2.7 + i*60 * CV_PI/180), 0.4 - i*0.3, cos(3.14 + 2.7 + i*60 * CV_PI/180)); + poses[i] = makeCameraPose(pose, Vec3d(0.0, 0.0, 0.0), Vec3d(0.0, -0.1, 0.0)); + } + + Viz3d viz("show_camera_positions"); + viz.showWidget("sphe", WSphere(Point3d(0,0,0), 1.0)); + viz.showWidget("coos", WCoordinateSystem(1.5)); + viz.showWidget("pos1", WCameraPosition(0.75), poses[0]); + viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); + + viz.showWidget("pos3", WCameraPosition(0.75), poses[1]); + viz.showWidget("pos4", WCameraPosition(K, gray, 3, Color::indigo()), poses[1]); + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); From f37c31742ae6a94f8d4bd2f9cda0725ed39e5c3d Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 10 Jan 2014 01:57:11 +0400 Subject: [PATCH 59/91] created tests for images, created vtk/vtkImageMatSource, and switched all images to that class --- modules/viz/src/precomp.hpp | 2 + modules/viz/src/shapes.cpp | 41 ++++--- modules/viz/src/vizimpl.hpp | 63 ---------- modules/viz/src/vtk/vtkCloudMatSink.h | 2 +- modules/viz/src/vtk/vtkCloudMatSource.h | 2 +- modules/viz/src/vtk/vtkImageMatSource.cpp | 140 ++++++++++++++++++++++ modules/viz/src/vtk/vtkImageMatSource.h | 84 +++++++++++++ modules/viz/src/vtk/vtkOBJWriter.h | 2 +- modules/viz/src/vtk/vtkTrajectorySource.h | 2 +- modules/viz/src/vtk/vtkXYZWriter.h | 6 +- modules/viz/test/test_precomp.hpp | 6 + modules/viz/test/tests_simple.cpp | 33 ++++- 12 files changed, 286 insertions(+), 97 deletions(-) create mode 100644 modules/viz/src/vtk/vtkImageMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkImageMatSource.h diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 425502d641..3b4e3619da 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -125,6 +125,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ @@ -137,6 +138,7 @@ #include #include #include +#include #include #include diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 422ea9be33..6f4392b0fd 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -617,15 +617,13 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) { CV_Assert(!image.empty() && image.depth() == CV_8U); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flip_filter = vtkSmartPointer::New(); flip_filter->SetFilteredAxis(1); // Vertical flip - flip_filter->SetInputConnection(vtk_image->GetProducerPort()); - flip_filter->Update(); + flip_filter->SetInputConnection(source->GetOutputPort()); // Scale the image based on the Rect vtkSmartPointer transform = vtkSmartPointer::New(); @@ -637,6 +635,7 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) image_reslice->SetOutputDimensionality(2); image_reslice->InterpolateOn(); image_reslice->AutoCropOutputOn(); + image_reslice->Update(); vtkSmartPointer image_mapper = vtkSmartPointer::New(); image_mapper->SetInputConnection(image_reslice->GetOutputPort()); @@ -661,13 +660,13 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) CV_Assert("This widget does not support overlay image." && mapper); // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); mapper->SetInputConnection(flipFilter->GetOutputPort()); @@ -686,14 +685,13 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size &size) { CV_Assert(!image.empty() && image.depth() == CV_8U); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); Vec3d plane_center(size.width * 0.5, size.height * 0.5, 0.0); @@ -735,13 +733,13 @@ cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Ve CV_Assert(!image.empty() && image.depth() == CV_8U); // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); vtkSmartPointer plane = vtkSmartPointer::New(); @@ -790,14 +788,13 @@ void cv::viz::WImage3D::setImage(const Mat &image) vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("This widget does not support 3D image." && actor); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); // Apply the texture @@ -850,8 +847,10 @@ namespace cv { namespace viz { namespace float aspect_ratio = float(image.cols)/float(image.rows); // Create the vtk image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); + source->Update(); + vtkSmartPointer vtk_image = source->GetOutput(); // Adjust a pixel of the vtk_image if(image.channels() == 1) diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 03d5c0325e..f9ccf09448 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -179,67 +179,4 @@ private: bool removeActorFromRenderer(const vtkSmartPointer &actor); }; -namespace cv -{ - namespace viz - { - struct color_tag {}; - struct gray_tag {}; - - inline Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } - inline Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } - - struct ConvertToVtkImage - { - struct Impl - { - typedef unsigned char uchar; - - static void copyImage(const Mat &source, vtkSmartPointer output, color_tag tag) - { - for (int y = 0; y < source.rows; ++y) - { - const uchar *srow = source.ptr(y); - for (int x = 0; x < source.cols; ++x, srow += source.channels()) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = fetchRgb(srow, tag); - } - output->Modified(); - } - - static void copyImage(const Mat &source, vtkSmartPointer output, gray_tag) - { - for (int y = 0; y < source.rows; ++y) - { - const uchar *srow = source.ptr(y); - for (int x = 0; x < source.cols; ++x) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; - } - output->Modified(); - } - }; - - static void convert(const Mat &image, vtkSmartPointer output) - { - // Create the vtk image - output->SetDimensions(image.cols, image.rows, 1); -#if VTK_MAJOR_VERSION <= 5 - output->SetNumberOfScalarComponents(image.channels()); - output->SetScalarTypeToUnsignedChar(); - output->AllocateScalars(); -#else - output->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); -#endif - switch(image.channels()) - { - case 1: Impl::copyImage(image, output, gray_tag()); break; - case 3: - case 4: Impl::copyImage(image, output, color_tag()); break; - default: - CV_Assert(!"Unsupported channel number"); - } - } - }; - } -} - #endif diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index 1d299f47ce..69262f247a 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -56,7 +56,7 @@ namespace cv { public: static vtkCloudMatSink *New(); - vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter); + vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 00e6adf1ee..a7f9fff89a 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -59,7 +59,7 @@ namespace cv { public: static vtkCloudMatSource *New(); - vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); + vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm) virtual int SetCloud(InputArray cloud); virtual int SetColorCloud(InputArray cloud, InputArray colors = noArray()); diff --git a/modules/viz/src/vtk/vtkImageMatSource.cpp b/modules/viz/src/vtk/vtkImageMatSource.cpp new file mode 100644 index 0000000000..2147039d71 --- /dev/null +++ b/modules/viz/src/vtk/vtkImageMatSource.cpp @@ -0,0 +1,140 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkImageMatSource); +}} + +cv::viz::vtkImageMatSource::vtkImageMatSource() +{ + this->SetNumberOfInputPorts(0); + this->ImageData = vtkImageData::New(); +} + +int cv::viz::vtkImageMatSource::RequestInformation(vtkInformation *, vtkInformationVector**, vtkInformationVector *outputVector) +{ + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->ImageData->GetExtent(), 6); + outInfo->Set(vtkDataObject::SPACING(), 1.0, 1.0, 1.0); + outInfo->Set(vtkDataObject::ORIGIN(), 0.0, 0.0, 0.0); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->ImageData->GetScalarType(), this->ImageData->GetNumberOfScalarComponents()); + return 1; +} + +int cv::viz::vtkImageMatSource::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *output = vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + output->ShallowCopy(this->ImageData); + return 1; +} + +void cv::viz::vtkImageMatSource::SetImage(InputArray _image) +{ + CV_Assert(_image.depth() == CV_8U && _image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4); + + Mat image = _image.getMat(); + + this->ImageData->SetDimensions(image.cols, image.rows, 1); +#if VTK_MAJOR_VERSION <= 5 + this->ImageData->SetNumberOfScalarComponents(std::min(3, image.channels())); + this->ImageData->SetScalarTypeToUnsignedChar(); + this->ImageData->AllocateScalars(); +#else + this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, std::min(3, image.channels())); +#endif + + switch(image.channels()) + { + case 1: copyGrayImage(image, this->ImageData); + case 3: copyRGBImage (image, this->ImageData); + case 4: copyRGBAImage(image, this->ImageData); + } + this->ImageData->Modified(); +} + +void cv::viz::vtkImageMatSource::copyGrayImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; + } +} + +void cv::viz::vtkImageMatSource::copyRGBImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x, srow += source.channels()) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec3b(srow[2], srow[1], srow[0]); + } +} + +void cv::viz::vtkImageMatSource::copyRGBAImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x, srow += source.channels()) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec4b(srow[2], srow[1], srow[0], srow[3]); + } +} diff --git a/modules/viz/src/vtk/vtkImageMatSource.h b/modules/viz/src/vtk/vtkImageMatSource.h new file mode 100644 index 0000000000..a4340346c1 --- /dev/null +++ b/modules/viz/src/vtk/vtkImageMatSource.h @@ -0,0 +1,84 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +#ifndef __vtkImageMatSource_h +#define __vtkImageMatSource_h + +namespace cv +{ + namespace viz + { + class vtkImageMatSource : public vtkImageAlgorithm + { + public: + static vtkImageMatSource *New(); + vtkTypeMacro(vtkImageMatSource,vtkImageAlgorithm); + + void SetImage(InputArray image); + + protected: + vtkImageMatSource(); + ~vtkImageMatSource() {} + + vtkSmartPointer ImageData; + + int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*); + int RequestData (vtkInformation*, vtkInformationVector**, vtkInformationVector*); + private: + vtkImageMatSource(const vtkImageMatSource&); // Not implemented. + void operator=(const vtkImageMatSource&); // Not implemented. + + static void copyGrayImage(const Mat &source, vtkSmartPointer output); + static void copyRGBImage (const Mat &source, vtkSmartPointer output); + static void copyRGBAImage(const Mat &source, vtkSmartPointer output); + }; + } +} + + +#endif + + diff --git a/modules/viz/src/vtk/vtkOBJWriter.h b/modules/viz/src/vtk/vtkOBJWriter.h index 9bf5403e43..f8889884d7 100644 --- a/modules/viz/src/vtk/vtkOBJWriter.h +++ b/modules/viz/src/vtk/vtkOBJWriter.h @@ -55,7 +55,7 @@ namespace cv { public: static vtkOBJWriter *New(); - vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter); + vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); vtkGetMacro(DecimalPrecision, int); diff --git a/modules/viz/src/vtk/vtkTrajectorySource.h b/modules/viz/src/vtk/vtkTrajectorySource.h index 9182509653..f6c9c77b9c 100644 --- a/modules/viz/src/vtk/vtkTrajectorySource.h +++ b/modules/viz/src/vtk/vtkTrajectorySource.h @@ -59,7 +59,7 @@ namespace cv { public: static vtkTrajectorySource *New(); - vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm); + vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm) virtual void SetTrajectory(InputArray trajectory); diff --git a/modules/viz/src/vtk/vtkXYZWriter.h b/modules/viz/src/vtk/vtkXYZWriter.h index bc49d10ef1..3db18b793b 100644 --- a/modules/viz/src/vtk/vtkXYZWriter.h +++ b/modules/viz/src/vtk/vtkXYZWriter.h @@ -55,11 +55,11 @@ namespace cv { public: static vtkXYZWriter *New(); - vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter); + vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); - vtkGetMacro(DecimalPrecision, int); - vtkSetMacro(DecimalPrecision, int); + vtkGetMacro(DecimalPrecision, int) + vtkSetMacro(DecimalPrecision, int) protected: vtkXYZWriter(); diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index e4fe78420c..1a5c4fe1cc 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -93,6 +93,12 @@ namespace cv } return result; } + + inline Mat make_gray(const Mat& image) + { + Mat chs[3]; split(image, chs); + return 0.114 * chs[0] + 0.58 * chs[1] + 0.3 * chs[2]; + } } #endif diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 4f37f32212..8ded955ed5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -198,15 +198,11 @@ TEST(Viz, DISABLED_show_trajectory_reposition) viz.spin(); } - - TEST(Viz, show_camera_positions) { - Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); - Mat chs[3]; split(lena, chs); - Mat gray = 0.114 * chs[0] + 0.58 * chs[1] + 0.3 * chs[2]; - Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); Affine3d poses[2]; for(int i = 0; i < 2; ++i) @@ -226,6 +222,31 @@ TEST(Viz, show_camera_positions) viz.spin(); } +TEST(Viz, show_overlay_image) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); + + Viz3d viz("show_overlay_image"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.spin(); +} + +TEST(Viz, show_image_3d) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); + + Viz3d viz("show_image_3d"); + viz.showWidget("coos", WCoordinateSystem(100)); + viz.showWidget("img1", WImage3D(lena, Size(lena.cols, lena.rows/2)), makeCameraPose(Vec3d(1.0, 1.0, 1.0), Vec3d::all(0.0), Vec3d(0.0, -1.0, 0.0))); + viz.showWidget("img2", WImage3D(Vec3d(1.0, -1.0, 1.0), Vec3d(-1, 1, -1), Vec3d(0.0, -1.0, 0.0), gray, lena.size())); + + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); From e3ff28dacc312d86b236c2e32848b3cdc6fe138f Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 10 Jan 2014 19:57:16 +0400 Subject: [PATCH 60/91] refactored WImage3D --- modules/viz/doc/widget.rst | 34 ++++-- modules/viz/include/opencv2/viz/widgets.hpp | 15 ++- modules/viz/src/precomp.hpp | 45 +++++--- modules/viz/src/shapes.cpp | 119 +++++--------------- modules/viz/src/vizcore.cpp | 3 - modules/viz/src/vizimpl.cpp | 2 +- modules/viz/src/vizimpl.hpp | 2 +- modules/viz/src/vtk/vtkCloudMatSource.cpp | 1 + modules/viz/src/widget.cpp | 11 ++ modules/viz/test/tests_simple.cpp | 36 ++++-- 10 files changed, 133 insertions(+), 135 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index a8dcedd4b9..54b740b0b4 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -170,13 +170,16 @@ Base class of all 3D widgets. :: public: Widget3D() {} + //! widget position manipulation, i.e. place where it is rendered. void setPose(const Affine3d &pose); void updatePose(const Affine3d &pose); Affine3d getPose() const; + //! updates internal widget data, i.e. points, normals, etc. + void applyTransform(const Affine3d &transform); + void setColor(const Color &color); - private: - /* hidden */ + }; viz::Widget3D::setPose @@ -201,6 +204,15 @@ Returns the current pose of the widget. .. ocv:function:: Affine3d getWidgetPose() const + +viz::Widget3D::applyTransform +------------------------------- +Transforms internal widget data (i.e. points, normals) using the given transform. + +.. ocv:function:: void applyTransform(const Affine3d &transform); + + :param transform: Specified transformation to apply. + viz::Widget3D::setColor ----------------------- Sets the color of the widget. @@ -598,25 +610,25 @@ This 3D Widget represents an image in 3D space. :: class CV_EXPORTS WImage3D : public Widget3D { - public: - //! Creates 3D image at the origin - WImage3D(const Mat &image, const Size &size); - //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size); + public: + //! Creates 3D image at the origin + WImage3D(const Mat &image, const Size2d &size); + //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation + WImage3D(const Mat &image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); - void setImage(const Mat &image); - }; + void setImage(const Mat &image); + }; viz::WImage3D::WImage3D ----------------------- Constructs an WImage3D. -.. ocv:function:: WImage3D(const Mat &image, const Size &size) +.. ocv:function:: WImage3D(const Mat &image, const Size2d &size) :param image: BGR or Gray-Scale image. :param size: Size of the image. -.. ocv:function:: WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size) +.. ocv:function:: WImage3D(const Mat &image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector) :param position: Position of the image. :param normal: Normal of the plane that represents the image. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 4dde94df62..49a0512cc4 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -111,10 +111,14 @@ namespace cv public: Widget3D() {} + //! widget position manipulation, i.e. place where it is rendered void setPose(const Affine3d &pose); void updatePose(const Affine3d &pose); Affine3d getPose() const; + //! update internal widget data, i.e. points, normals, etc. + void applyTransform(const Affine3d &transform); + void setColor(const Color &color); }; @@ -172,7 +176,8 @@ namespace cv class CV_EXPORTS WCube : public Widget3D { public: - WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame = true, const Color &color = Color::white()); + WCube(const Point3d& min_point = Vec3d::all(-0.5), const Point3d& max_point = Vec3d::all(0.5), + bool wire_frame = true, const Color &color = Color::white()); }; class CV_EXPORTS WPolyLine : public Widget3D @@ -213,10 +218,12 @@ namespace cv class CV_EXPORTS WImage3D : public Widget3D { public: - //! Creates 3D image at the origin - WImage3D(const Mat &image, const Size &size); + //! Creates 3D image in a plane centered at the origin with normal orientaion along z-axis, + //! image x- and y-axes are oriented along x- and y-axes of 3d world + WImage3D(const Mat &image, const Size2d &size); + //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size); + WImage3D(const Mat &image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector); void setImage(const Mat &image); }; diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 3b4e3619da..98de7b7f6b 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -126,6 +126,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ @@ -175,6 +176,8 @@ namespace cv friend class Viz3d; }; + template inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); } + template inline bool isNan(const _Tp* data) { return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); @@ -187,10 +190,24 @@ namespace cv return vtkPolyData::SafeDownCast(mapper->GetInput()); } + inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) + { + vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); + vtk_matrix->DeepCopy(matrix.val); + return vtk_matrix; + } + + inline Color vtkcolor(const Color& color) + { + Color scaled_color = color * (1.0/255.0); + std::swap(scaled_color[0], scaled_color[2]); + return scaled_color; + } + struct VtkUtils { template - static void SetInputData(vtkSmartPointer filter, vtkPolyData *polydata) + static void SetInputData(vtkSmartPointer filter, vtkPolyData* polydata) { #if VTK_MAJOR_VERSION <= 5 filter->SetInput(polydata); @@ -238,23 +255,19 @@ namespace cv normals_generator->Update(); return normals_generator->GetOutput(); } - }; - inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) - { - vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); - vtk_matrix->DeepCopy(matrix.val); - return vtk_matrix; - } - - inline Color vtkcolor(const Color& color) - { - Color scaled_color = color * (1.0/255.0); - std::swap(scaled_color[0], scaled_color[2]); - return scaled_color; - } + static vtkSmartPointer TransformPolydata(vtkSmartPointer polydata, const Affine3d& pose) + { + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetMatrix(vtkmatrix(pose.matrix)); - template inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); } + vtkSmartPointer transform_filter = vtkSmartPointer::New(); + transform_filter->SetTransform(transform); + transform_filter->SetInputConnection(polydata->GetProducerPort()); + transform_filter->Update(); + return transform_filter->GetOutput(); + } + }; } } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 6f4392b0fd..9a9b2fccd1 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -294,18 +294,18 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCube::WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame, const Color &color) +cv::viz::WCube::WCube(const Point3d& min_point, const Point3d& max_point, bool wire_frame, const Color &color) { vtkSmartPointer cube; if (wire_frame) { cube = vtkSmartPointer::New(); - vtkOutlineSource::SafeDownCast(cube)->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); + vtkOutlineSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z); } else { cube = vtkSmartPointer::New(); - vtkCubeSource::SafeDownCast(cube)->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); + vtkCubeSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z); } cube->Update(); @@ -620,10 +620,9 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flip_filter = vtkSmartPointer::New(); - flip_filter->SetFilteredAxis(1); // Vertical flip flip_filter->SetInputConnection(source->GetOutputPort()); + flip_filter->SetFilteredAxis(1); // Scale the image based on the Rect vtkSmartPointer transform = vtkSmartPointer::New(); @@ -663,13 +662,11 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(source->GetOutputPort()); - flipFilter->Update(); + vtkSmartPointer flip_filter = vtkSmartPointer::New(); + flip_filter->SetInputConnection(source->GetOutputPort()); + flip_filter->SetFilteredAxis(1); - mapper->SetInputConnection(flipFilter->GetOutputPort()); + mapper->SetInputConnection(flip_filter->GetOutputPort()); } template<> cv::viz::WImageOverlay cv::viz::Widget::cast() @@ -681,104 +678,49 @@ template<> cv::viz::WImageOverlay cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// image 3D widget implementation -cv::viz::WImage3D::WImage3D(const Mat &image, const Size &size) +cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size) { CV_Assert(!image.empty() && image.depth() == CV_8U); vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(source->GetOutputPort()); - flipFilter->Update(); - - Vec3d plane_center(size.width * 0.5, size.height * 0.5, 0.0); + vtkSmartPointer texture = vtkSmartPointer::New(); + texture->SetInputConnection(source->GetOutputPort()); vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]); - plane->SetNormal(0.0, 0.0, 1.0); - - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(plane_center[0], plane_center[1], plane_center[2]); - transform->Scale(size.width, size.height, 1.0); - transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(plane->GetOutputPort()); - transform_filter->Update(); - - // Apply the texture - vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); + plane->SetOrigin(-0.5 * size.width, -0.5 * size.height, 0.0); + plane->SetPoint1( 0.5 * size.width, -0.5 * size.height, 0.0); + plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0); - vtkSmartPointer texturePlane = vtkSmartPointer::New(); - texturePlane->SetInputConnection(transform_filter->GetOutputPort()); + vtkSmartPointer textured_plane = vtkSmartPointer::New(); + textured_plane->SetInputConnection(plane->GetOutputPort()); - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(texturePlane->GetOutputPort()); + vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetInputConnection(textured_plane->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(planeMapper); + actor->SetMapper(mapper); actor->SetTexture(texture); + actor->GetProperty()->ShadingOff(); + actor->GetProperty()->LightingOff(); WidgetAccessor::setProp(*this, actor); } -cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size) +cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector) { CV_Assert(!image.empty() && image.depth() == CV_8U); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer source = vtkSmartPointer::New(); - source->SetImage(image); - - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(source->GetOutputPort()); - flipFilter->Update(); - - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(0.0, 0.0, 0.0); - plane->SetNormal(0.0, 0.0, 1.0); - // Compute the transformation matrix for drawing the camera frame in a scene Vec3d n = normalize(normal); Vec3d u = normalize(up_vector.cross(n)); Vec3d v = n.cross(u); + Affine3d pose = makeTransformToGlobal(u, v, n, center); - Affine3d pose = makeTransformToGlobal(u, v, n, position); - - // Apply the texture - vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); - - vtkSmartPointer texturePlane = vtkSmartPointer::New(); - texturePlane->SetInputConnection(plane->GetOutputPort()); - - // Apply the transform after texture mapping - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->SetMatrix(vtkmatrix(pose.matrix)); - transform->Scale(size.width, size.height, 1.0); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(texturePlane->GetOutputPort()); - transform_filter->Update(); - - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(transform_filter->GetOutputPort()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(planeMapper); - actor->SetTexture(texture); - - WidgetAccessor::setProp(*this, actor); + WImage3D image3d(image, size); + image3d.applyTransform(pose); + *this = image3d; } void cv::viz::WImage3D::setImage(const Mat &image) @@ -791,15 +733,8 @@ void cv::viz::WImage3D::setImage(const Mat &image) vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(source->GetOutputPort()); - flipFilter->Update(); - - // Apply the texture vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); + texture->SetInputConnection(source->GetOutputPort()); actor->SetTexture(texture); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index d00a22b4c5..21c7e0d700 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -305,6 +305,3 @@ void cv::viz::computeNormals(const Mesh& mesh, OutputArray _normals) - - - diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 5974cc6e03..dd568c9404 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -271,7 +271,7 @@ void cv::viz::Viz3d::VizImpl::removeAllWidgets() } ///////////////////////////////////////////////////////////////////////////////////////////// -bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(const vtkSmartPointer &actor) +bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer actor) { vtkProp* actor_to_remove = vtkProp::SafeDownCast(actor); diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index f9ccf09448..b6ae549270 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -176,7 +176,7 @@ private: /** \brief Boolean that holds whether or not the camera parameters were manually initialized*/ bool camera_set_; - bool removeActorFromRenderer(const vtkSmartPointer &actor); + bool removeActorFromRenderer(vtkSmartPointer actor); }; #endif diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index f1dabe66b9..7884f1a9a2 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -212,6 +212,7 @@ template void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total) { normals = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + normals->SetName("Normals"); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(total); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index a633f24ba6..6c1463b762 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -269,6 +269,17 @@ cv::Affine3d cv::viz::Widget3D::getPose() const return Affine3d(*actor->GetUserMatrix()->Element); } +void cv::viz::Widget3D::applyTransform(const Affine3d &transform) +{ + vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); + CV_Assert("Widget is not 3D actor." && actor); + + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); + CV_Assert("Widget doesn't have a polydata mapper" && mapper); + + VtkUtils::SetInputData(mapper, VtkUtils::TransformPolydata(mapper->GetInput(), transform)); +} + void cv::viz::Widget3D::setColor(const Color &color) { // Cast to actor instead of prop3d since prop3d doesn't provide getproperty diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 8ded955ed5..e31585b09b 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -229,22 +229,44 @@ TEST(Viz, show_overlay_image) Viz3d viz("show_overlay_image"); viz.showWidget("coos", WCoordinateSystem()); - viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.showWidget("cube", WCube(Vec3d::all(-0.5), Vec3d::all(0.5))); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 400), Size_(viz.getWindowSize()) * 0.5))); viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size_(viz.getWindowSize()) * 0.5))); - viz.spin(); + + int i = 0; + while(!viz.wasStopped()) + { + double a = ++i % 360; + Vec3d pose(sin(a * CV_PI/180), 0.7, cos(a * CV_PI/180)); + viz.setViewerPose(makeCameraPose(pose * 3, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); + + viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); + //viz.getWidget("img1").cast().setImage(gray); + viz.spinOnce(1, true); + } + //viz.spin(); } -TEST(Viz, show_image_3d) +TEST(Viz, DISABLED_show_image_3d) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); Mat gray = make_gray(lena); Viz3d viz("show_image_3d"); - viz.showWidget("coos", WCoordinateSystem(100)); - viz.showWidget("img1", WImage3D(lena, Size(lena.cols, lena.rows/2)), makeCameraPose(Vec3d(1.0, 1.0, 1.0), Vec3d::all(0.0), Vec3d(0.0, -1.0, 0.0))); - viz.showWidget("img2", WImage3D(Vec3d(1.0, -1.0, 1.0), Vec3d(-1, 1, -1), Vec3d(0.0, -1.0, 0.0), gray, lena.size())); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("cube", WCube(Vec3d::all(-0.5), Vec3d::all(0.5))); + viz.showWidget("arr0", WArrow(Vec3d(0.5, 0.0, 0.0), Vec3d(1.5, 0.0, 0.0), 0.009, Color::raspberry())); + viz.showWidget("img0", WImage3D(lena, Size2d(1.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(.5, 0.0, 0.0))); + viz.showWidget("arr1", WArrow(Vec3d(-0.5, -0.5, 0.0), Vec3d(0.2, 0.2, 0.0), 0.009, Color::raspberry())); + viz.showWidget("img1", WImage3D(gray, Size2d(1.0, 1.0), Vec3d(-0.5, -0.5, 0.0), Vec3d(1.0, 1.0, 0.0), Vec3d(0.0, 1.0, 0.0))); - viz.spin(); + int i = 0; + while(!viz.wasStopped()) + { + viz.getWidget("img0").cast().setImage(lena * pow(sin(i++*7.5*CV_PI/180) * 0.5 + 0.5, 1.0)); + viz.spinOnce(1, true); + } + //viz.spin(); } TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) From f930f2f19d115c89efb4790f342deb4f9814af1c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 16:44:01 +0400 Subject: [PATCH 61/91] simplification of cloud collection --- modules/viz/src/clouds.cpp | 9 +-------- modules/viz/src/precomp.hpp | 9 +++++++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index e7759e323d..9ea1d76fe8 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -112,15 +112,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co vtkSmartPointer source = vtkSmartPointer::New(); source->SetColorCloud(cloud, colors); - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->SetMatrix(pose.matrix.val); + vtkSmartPointer polydata = VtkUtils::TransformPolydata(source->GetOutputPort(), pose); - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetInputConnection(source->GetOutputPort()); - transform_filter->SetTransform(transform); - transform_filter->Update(); - - vtkSmartPointer polydata = transform_filter->GetOutput(); vtkSmartPointer actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 98de7b7f6b..df46f70481 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -256,17 +256,22 @@ namespace cv return normals_generator->GetOutput(); } - static vtkSmartPointer TransformPolydata(vtkSmartPointer polydata, const Affine3d& pose) + static vtkSmartPointer TransformPolydata(vtkSmartPointer algorithm_output_port, const Affine3d& pose) { vtkSmartPointer transform = vtkSmartPointer::New(); transform->SetMatrix(vtkmatrix(pose.matrix)); vtkSmartPointer transform_filter = vtkSmartPointer::New(); transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(polydata->GetProducerPort()); + transform_filter->SetInputConnection(algorithm_output_port); transform_filter->Update(); return transform_filter->GetOutput(); } + + static vtkSmartPointer TransformPolydata(vtkSmartPointer polydata, const Affine3d& pose) + { + return TransformPolydata(polydata->GetProducerPort(), pose); + } }; } } From a23f1447a8005c0d85a82b4afccd7c6e5bc0408b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 20:01:57 +0400 Subject: [PATCH 62/91] minor --- modules/viz/src/precomp.hpp | 8 +++-- modules/viz/src/shapes.cpp | 50 ++++++++++++++++++------------- modules/viz/test/tests_simple.cpp | 4 +-- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index df46f70481..98ab3ce63a 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -183,10 +183,14 @@ namespace cv return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); } + inline vtkSmartPointer getActor(const Widget3D& widget) + { + return vtkActor::SafeDownCast(WidgetAccessor::getProp(widget)); + } + inline vtkSmartPointer getPolyData(const Widget3D& widget) { - vtkSmartPointer prop = WidgetAccessor::getProp(widget); - vtkSmartPointer mapper = vtkActor::SafeDownCast(prop)->GetMapper(); + vtkSmartPointer mapper = getActor(widget)->GetMapper(); return vtkPolyData::SafeDownCast(mapper->GetInput()); } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 9a9b2fccd1..3295a52389 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -777,28 +777,34 @@ namespace cv { namespace viz { namespace return extract_edges->GetOutput(); } - static vtkSmartPointer projectImage(double fovy, double far_end_height, const Mat &image, double scale, const Color &color) + static vtkSmartPointer projectImage(vtkSmartPointer frustum, double far_end_height, const Mat &image, double scale, const Color &color) { - float aspect_ratio = float(image.cols)/float(image.rows); + Mat color_image = image; + if (color_image.channels() == 1) + { + color_image.create(image.size(), CV_8UC3); + Vec3b *drow = color_image.ptr(); + for(int y = 0; y < image.rows; ++y) + { + const unsigned char *srow = image.ptr(y); + const unsigned char *send = srow + image.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(image); + source->SetImage(color_image); source->Update(); vtkSmartPointer vtk_image = source->GetOutput(); - // Adjust a pixel of the vtk_image - if(image.channels() == 1) - { - double gray = color[2] * 0.299 + color[1] * 0.578 + color[0] * 0.144; - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, gray); - } - else - { - 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]); - } + 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); @@ -824,7 +830,7 @@ namespace cv { namespace viz { namespace transform_filter->SetInputConnection(texture_plane->GetOutputPort()); transform_filter->SetTransform(transform); - vtkSmartPointer frustum = createFrustum(aspect_ratio, fovy, scale); + // Frustum needs to be textured or else it can't be combined with image vtkSmartPointer frustum_texture = vtkSmartPointer::New(); @@ -901,14 +907,15 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, double scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); - 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; + + vtkSmartPointer frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); - vtkSmartPointer actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color); + vtkSmartPointer actor = CameraPositionUtils::projectImage(frustum, far_end_height, image, scale, color); WidgetAccessor::setProp(*this, actor); } @@ -917,8 +924,11 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, const Mat &image, do CV_Assert(!image.empty() && image.depth() == CV_8U); 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; + + vtkSmartPointer frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); - vtkSmartPointer actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color); + vtkSmartPointer actor = CameraPositionUtils::projectImage(frustum, far_end_height, image, scale, color); WidgetAccessor::setProp(*this, actor); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index e31585b09b..ea8a0b0383 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -174,7 +174,7 @@ TEST(Viz, DISABLED_show_trajectories) viz.showWidget("sub1", WTrajectory(sub1, WTrajectory::PATH, 0.2, Color::brown())); viz.showWidget("sub2", WTrajectory(sub2, WTrajectory::FRAMES, 0.2)); viz.showWidget("sub3", WTrajectory(sub3, WTrajectory::BOTH, 0.2, Color::green())); - viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3)); + viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3, Color::yellow())); viz.showWidget("sub5", WTrajectoryFrustums(sub5, Vec2d(0.78, 0.78), 0.15)); int i = 0; @@ -212,7 +212,7 @@ TEST(Viz, show_camera_positions) } Viz3d viz("show_camera_positions"); - viz.showWidget("sphe", WSphere(Point3d(0,0,0), 1.0)); + viz.showWidget("sphe", WSphere(Point3d(0,0,0), 1.0, 10, Color::orange_red())); viz.showWidget("coos", WCoordinateSystem(1.5)); viz.showWidget("pos1", WCameraPosition(0.75), poses[0]); viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); From e21f2a81fff4a21a5bf9ef6a3b71588da24e28d9 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 20:40:10 +0400 Subject: [PATCH 63/91] 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 54b740b0b4..ec4a858e2d 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 49a0512cc4..44cb500744 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 3295a52389..2067c5c9e4 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); } From cad9a786c4d64b9a4df0686e2f4cea345fea3f3c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 22:00:28 +0400 Subject: [PATCH 64/91] optimized Mat to vtkImageData conversion --- modules/viz/src/precomp.hpp | 1 + modules/viz/src/vtk/vtkImageMatSource.cpp | 37 ++++++++++++----------- modules/viz/test/tests_simple.cpp | 12 ++++---- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 98ab3ce63a..9c76d9dead 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -127,6 +127,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ diff --git a/modules/viz/src/vtk/vtkImageMatSource.cpp b/modules/viz/src/vtk/vtkImageMatSource.cpp index 2147039d71..54500cb4bc 100644 --- a/modules/viz/src/vtk/vtkImageMatSource.cpp +++ b/modules/viz/src/vtk/vtkImageMatSource.cpp @@ -44,15 +44,6 @@ #include "precomp.hpp" - -#include "vtkImageData.h" -#include "vtkImageProgressIterator.h" -#include "vtkMath.h" -#include "vtkInformation.h" -#include "vtkInformationVector.h" -#include "vtkObjectFactory.h" -#include "vtkStreamingDemandDrivenPipeline.h" - namespace cv { namespace viz { vtkStandardNewMacro(vtkImageMatSource); @@ -93,48 +84,60 @@ void cv::viz::vtkImageMatSource::SetImage(InputArray _image) this->ImageData->SetDimensions(image.cols, image.rows, 1); #if VTK_MAJOR_VERSION <= 5 - this->ImageData->SetNumberOfScalarComponents(std::min(3, image.channels())); + this->ImageData->SetNumberOfScalarComponents(image.channels()); this->ImageData->SetScalarTypeToUnsignedChar(); this->ImageData->AllocateScalars(); #else - this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, std::min(3, image.channels())); + this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); #endif switch(image.channels()) { - case 1: copyGrayImage(image, this->ImageData); - case 3: copyRGBImage (image, this->ImageData); - case 4: copyRGBAImage(image, this->ImageData); + case 1: copyGrayImage(image, this->ImageData); break; + case 3: copyRGBImage (image, this->ImageData); break; + case 4: copyRGBAImage(image, this->ImageData); break; } this->ImageData->Modified(); } void cv::viz::vtkImageMatSource::copyGrayImage(const Mat &source, vtkSmartPointer output) { + unsigned char* dptr = reinterpret_cast(output->GetScalarPointer()); + size_t elem_step = output->GetIncrements()[1]/sizeof(unsigned char); + for (int y = 0; y < source.rows; ++y) { + unsigned char* drow = dptr + elem_step * y; const unsigned char *srow = source.ptr(y); for (int x = 0; x < source.cols; ++x) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; + drow[x] = *srow++; } } void cv::viz::vtkImageMatSource::copyRGBImage(const Mat &source, vtkSmartPointer output) { + Vec3b* dptr = reinterpret_cast(output->GetScalarPointer()); + size_t elem_step = output->GetIncrements()[1]/sizeof(Vec3b); + for (int y = 0; y < source.rows; ++y) { + Vec3b* drow = dptr + elem_step * y; const unsigned char *srow = source.ptr(y); for (int x = 0; x < source.cols; ++x, srow += source.channels()) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec3b(srow[2], srow[1], srow[0]); + drow[x] = Vec3b(srow[2], srow[1], srow[0]); } } void cv::viz::vtkImageMatSource::copyRGBAImage(const Mat &source, vtkSmartPointer output) { + Vec4b* dptr = reinterpret_cast(output->GetScalarPointer()); + size_t elem_step = output->GetIncrements()[1]/sizeof(Vec4b); + for (int y = 0; y < source.rows; ++y) { + Vec4b* drow = dptr + elem_step * y; const unsigned char *srow = source.ptr(y); for (int x = 0; x < source.cols; ++x, srow += source.channels()) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec4b(srow[2], srow[1], srow[0], srow[3]); + drow[x] = Vec4b(srow[2], srow[1], srow[0], srow[3]); } } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ea8a0b0383..6bca255881 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -198,7 +198,7 @@ TEST(Viz, DISABLED_show_trajectory_reposition) viz.spin(); } -TEST(Viz, show_camera_positions) +TEST(Viz, DISABLED_show_camera_positions) { Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); @@ -216,7 +216,6 @@ TEST(Viz, show_camera_positions) viz.showWidget("coos", WCoordinateSystem(1.5)); viz.showWidget("pos1", WCameraPosition(0.75), poses[0]); viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); - viz.showWidget("pos3", WCameraPosition(0.75), poses[1]); viz.showWidget("pos4", WCameraPosition(K, gray, 3, Color::indigo()), poses[1]); viz.spin(); @@ -229,9 +228,10 @@ TEST(Viz, show_overlay_image) Viz3d viz("show_overlay_image"); viz.showWidget("coos", WCoordinateSystem()); - viz.showWidget("cube", WCube(Vec3d::all(-0.5), Vec3d::all(0.5))); - viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 400), Size_(viz.getWindowSize()) * 0.5))); - viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.showWidget("cube", WCube()); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 400), Size2d(viz.getWindowSize()) * 0.5))); + viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size2d(viz.getWindowSize()) * 0.5))); + viz.spin(); int i = 0; while(!viz.wasStopped()) @@ -254,7 +254,7 @@ TEST(Viz, DISABLED_show_image_3d) Viz3d viz("show_image_3d"); viz.showWidget("coos", WCoordinateSystem()); - viz.showWidget("cube", WCube(Vec3d::all(-0.5), Vec3d::all(0.5))); + viz.showWidget("cube", WCube()); viz.showWidget("arr0", WArrow(Vec3d(0.5, 0.0, 0.0), Vec3d(1.5, 0.0, 0.0), 0.009, Color::raspberry())); viz.showWidget("img0", WImage3D(lena, Size2d(1.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(.5, 0.0, 0.0))); viz.showWidget("arr1", WArrow(Vec3d(-0.5, -0.5, 0.0), Vec3d(0.2, 0.2, 0.0), 0.009, Color::raspberry())); From d90a068e0e725ff0c23c9379f3c3aac1350da0a5 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 22:13:45 +0400 Subject: [PATCH 65/91] fixed bug with setImage --- modules/viz/include/opencv2/viz/widgets.hpp | 1 - modules/viz/src/shapes.cpp | 31 +++++++++++++-------- modules/viz/test/tests_simple.cpp | 15 ++++++---- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 44cb500744..455c965578 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -211,7 +211,6 @@ namespace cv { public: WImageOverlay(const Mat &image, const Rect &rect); - void setImage(const Mat &image); }; diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 2067c5c9e4..5dffbfa0ee 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -616,21 +616,17 @@ cv::String cv::viz::WText::getText() const cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) { CV_Assert(!image.empty() && image.depth() == CV_8U); - vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - vtkSmartPointer flip_filter = vtkSmartPointer::New(); - flip_filter->SetInputConnection(source->GetOutputPort()); - flip_filter->SetFilteredAxis(1); - - // Scale the image based on the Rect + // Scale the image based on the Rect, and flip to match y-ais orientation vtkSmartPointer transform = vtkSmartPointer::New(); transform->Scale(image.cols/(double)rect.width, image.rows/(double)rect.height, 1.0); + transform->RotateX(180); vtkSmartPointer image_reslice = vtkSmartPointer::New(); image_reslice->SetResliceTransform(transform); - image_reslice->SetInputConnection(flip_filter->GetOutputPort()); + image_reslice->SetInputConnection(source->GetOutputPort()); image_reslice->SetOutputDimensionality(2); image_reslice->InterpolateOn(); image_reslice->AutoCropOutputOn(); @@ -657,16 +653,29 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) vtkImageMapper *mapper = vtkImageMapper::SafeDownCast(actor->GetMapper()); CV_Assert("This widget does not support overlay image." && mapper); + \ + Vec6i extent; + mapper->GetInput()->GetExtent(extent.val); + Size size(extent[1], extent[3]); // Create the vtk image and set its parameters based on input image vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - vtkSmartPointer flip_filter = vtkSmartPointer::New(); - flip_filter->SetInputConnection(source->GetOutputPort()); - flip_filter->SetFilteredAxis(1); + // Scale the image based on the Rect, and flip to match y-ais orientation + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->Scale(image.cols/(double)size.width, image.rows/(double)size.height, 1.0); + transform->RotateX(180); + + vtkSmartPointer image_reslice = vtkSmartPointer::New(); + image_reslice->SetResliceTransform(transform); + image_reslice->SetInputConnection(source->GetOutputPort()); + image_reslice->SetOutputDimensionality(2); + image_reslice->InterpolateOn(); + image_reslice->AutoCropOutputOn(); + image_reslice->Update(); - mapper->SetInputConnection(flip_filter->GetOutputPort()); + mapper->SetInputConnection(image_reslice->GetOutputPort()); } template<> cv::viz::WImageOverlay cv::viz::Widget::cast() diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 6bca255881..ff35bd4169 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -221,17 +221,22 @@ TEST(Viz, DISABLED_show_camera_positions) viz.spin(); } -TEST(Viz, show_overlay_image) +TEST(Viz, DISABLED_show_overlay_image) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); Mat gray = make_gray(lena); + Size2d half_lsize = Size2d(lena.size()) * 0.5; + Viz3d viz("show_overlay_image"); + Size vsz = viz.getWindowSize(); + viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); - viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 400), Size2d(viz.getWindowSize()) * 0.5))); - viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size2d(viz.getWindowSize()) * 0.5))); - viz.spin(); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(10, 10), half_lsize))); + viz.showWidget("img2", WImageOverlay(gray, Rect(Point(vsz.width-10-lena.cols/2, 10), half_lsize))); + viz.showWidget("img3", WImageOverlay(gray, Rect(Point(10, vsz.height-10-lena.rows/2), half_lsize))); + viz.showWidget("img5", WImageOverlay(lena, Rect(Point(vsz.width-10-lena.cols/2, vsz.height-10-lena.rows/2), half_lsize))); int i = 0; while(!viz.wasStopped()) @@ -239,9 +244,7 @@ TEST(Viz, show_overlay_image) double a = ++i % 360; Vec3d pose(sin(a * CV_PI/180), 0.7, cos(a * CV_PI/180)); viz.setViewerPose(makeCameraPose(pose * 3, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); - viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); - //viz.getWidget("img1").cast().setImage(gray); viz.spinOnce(1, true); } //viz.spin(); From 1449823bcd5a1fd396bd90426fdf046fb232e4ac Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 22:43:58 +0400 Subject: [PATCH 66/91] implemented showImage --- .../viz/launching_viz/launching_viz.rst | 2 +- modules/viz/doc/viz3d.rst | 11 ++++++++++ modules/viz/doc/widget.rst | 20 +++++++++---------- modules/viz/include/opencv2/viz.hpp | 3 +++ modules/viz/include/opencv2/viz/viz3d.hpp | 2 ++ modules/viz/include/opencv2/viz/widgets.hpp | 10 +++++----- modules/viz/src/shapes.cpp | 17 +++++++++------- modules/viz/src/viz3d.cpp | 11 ++++++++++ modules/viz/src/vizcore.cpp | 7 +++++++ modules/viz/test/tests_simple.cpp | 14 +++++++++++++ 10 files changed, 74 insertions(+), 23 deletions(-) diff --git a/doc/tutorials/viz/launching_viz/launching_viz.rst b/doc/tutorials/viz/launching_viz/launching_viz.rst index 0bf31977d1..a507a7f27a 100644 --- a/doc/tutorials/viz/launching_viz/launching_viz.rst +++ b/doc/tutorials/viz/launching_viz/launching_viz.rst @@ -43,7 +43,7 @@ You can download the code from :download:`here <../../../../samples/cpp/tutorial cout << "First event loop is over" << endl; /// Access window via its name - viz::Viz3d sameWindow = viz::get("Viz Demo"); + viz::Viz3d sameWindow = viz::getWindowByName("Viz Demo"); /// Start event loop sameWindow.spin(); diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 9d4bb674d3..ec5b16e718 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -102,6 +102,8 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar void setWidgetPose(const String &id, const Affine3d &pose); void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; + + void showImage(InputArray image, const Size& window_size = Size(-1, -1)); void setCamera(const Camera &camera); Camera getCamera() const; @@ -182,6 +184,15 @@ Removes all widgets from the window. .. ocv:function:: void removeAllWidgets() +viz::Viz3d::showImage +--------------------- +Removed all widgets and displays image scaled to whole window area. + +.. ocv:function:: void showImage(InputArray image, const Size& window_size = Size(-1, -1)); + + :param image: Image to be displayed. + :param size: Size of Viz3d window. Default value means no change. + viz::Viz3d::setWidgetPose ------------------------- Sets pose of a widget in the window. diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index ec4a858e2d..c286339c21 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -580,16 +580,16 @@ This 2D Widget represents an image overlay. :: class CV_EXPORTS WImageOverlay : public Widget2D { public: - WImageOverlay(const Mat &image, const Rect &rect); + WImageOverlay(InputArray image, const Rect &rect); - void setImage(const Mat &image); + void setImage(InputArray image); }; viz::WImageOverlay::WImageOverlay --------------------------------- Constructs an WImageOverlay. -.. ocv:function:: WImageOverlay(const Mat &image, const Rect &rect) +.. ocv:function:: WImageOverlay(InputArray image, const Rect &rect) :param image: BGR or Gray-Scale image. :param rect: Image is scaled and positioned based on rect. @@ -598,7 +598,7 @@ viz::WImageOverlay::setImage ---------------------------- Sets the image content of the widget. -.. ocv:function:: void setImage(const Mat &image) +.. ocv:function:: void setImage(InputArray image) :param image: BGR or Gray-Scale image. @@ -612,23 +612,23 @@ This 3D Widget represents an image in 3D space. :: { public: //! Creates 3D image at the origin - WImage3D(const Mat &image, const Size2d &size); + WImage3D(InputArray image, const Size2d &size); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Mat &image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); + WImage3D(InputArray image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); - void setImage(const Mat &image); + void setImage(InputArray image); }; viz::WImage3D::WImage3D ----------------------- Constructs an WImage3D. -.. ocv:function:: WImage3D(const Mat &image, const Size2d &size) +.. ocv:function:: WImage3D(InputArray image, const Size2d &size) :param image: BGR or Gray-Scale image. :param size: Size of the image. -.. ocv:function:: WImage3D(const Mat &image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector) +.. ocv:function:: WImage3D(InputArray image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector) :param position: Position of the image. :param normal: Normal of the plane that represents the image. @@ -640,7 +640,7 @@ viz::WImage3D::setImage ----------------------- Sets the image content of the widget. -.. ocv:function:: void setImage(const Mat &image) +.. ocv:function:: void setImage(InputArray image) :param image: BGR or Gray-Scale image. diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 9b1f21a8d5..32e32a7a3b 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -66,6 +66,9 @@ namespace cv //! Unregisters all Viz windows from internal database. After it 'getWindowByName()' will create new windows instead getting existing from the database. CV_EXPORTS void unregisterAllWindows(); + //! Displays image in specified window + CV_EXPORTS Viz3d imshow(const String& window_name, InputArray image, const Size& window_size = Size(-1, -1)); + //! checks float value for Nan inline bool isNan(float x) { diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 7cd27eb616..4ffb6b3c5a 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -75,6 +75,8 @@ namespace cv Widget getWidget(const String &id) const; void removeAllWidgets(); + void showImage(InputArray image, const Size& window_size = Size(-1, -1)); + void setWidgetPose(const String &id, const Affine3d &pose); void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 455c965578..8ab95c92a4 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -210,8 +210,8 @@ namespace cv class CV_EXPORTS WImageOverlay : public Widget2D { public: - WImageOverlay(const Mat &image, const Rect &rect); - void setImage(const Mat &image); + WImageOverlay(InputArray image, const Rect &rect); + void setImage(InputArray image); }; class CV_EXPORTS WImage3D : public Widget3D @@ -219,12 +219,12 @@ namespace cv public: //! Creates 3D image in a plane centered at the origin with normal orientaion along z-axis, //! image x- and y-axes are oriented along x- and y-axes of 3d world - WImage3D(const Mat &image, const Size2d &size); + WImage3D(InputArray image, const Size2d &size); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Mat &image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector); + WImage3D(InputArray image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector); - void setImage(const Mat &image); + void setImage(InputArray image); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 5dffbfa0ee..611b1c3f95 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -613,15 +613,16 @@ cv::String cv::viz::WText::getText() const /////////////////////////////////////////////////////////////////////////////////////////////// /// image overlay widget implementation -cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) +cv::viz::WImageOverlay::WImageOverlay(InputArray image, const Rect &rect) { CV_Assert(!image.empty() && image.depth() == CV_8U); vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); + Size sz = image.size(); // Scale the image based on the Rect, and flip to match y-ais orientation vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Scale(image.cols/(double)rect.width, image.rows/(double)rect.height, 1.0); + transform->Scale(sz.width/(double)rect.width, sz.height/(double)rect.height, 1.0); transform->RotateX(180); vtkSmartPointer image_reslice = vtkSmartPointer::New(); @@ -640,11 +641,12 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(image_mapper); actor->SetPosition(rect.x, rect.y); + actor->GetProperty()->SetDisplayLocationToForeground(); WidgetAccessor::setProp(*this, actor); } -void cv::viz::WImageOverlay::setImage(const Mat &image) +void cv::viz::WImageOverlay::setImage(InputArray image) { CV_Assert(!image.empty() && image.depth() == CV_8U); @@ -661,10 +663,11 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) // Create the vtk image and set its parameters based on input image vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); + Size sz = image.size(); // Scale the image based on the Rect, and flip to match y-ais orientation vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Scale(image.cols/(double)size.width, image.rows/(double)size.height, 1.0); + transform->Scale(sz.width/(double)size.width, sz.height/(double)size.height, 1.0); transform->RotateX(180); vtkSmartPointer image_reslice = vtkSmartPointer::New(); @@ -687,7 +690,7 @@ template<> cv::viz::WImageOverlay cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// image 3D widget implementation -cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size) +cv::viz::WImage3D::WImage3D(InputArray image, const Size2d &size) { CV_Assert(!image.empty() && image.depth() == CV_8U); @@ -717,7 +720,7 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size) WidgetAccessor::setProp(*this, actor); } -cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector) +cv::viz::WImage3D::WImage3D(InputArray image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector) { CV_Assert(!image.empty() && image.depth() == CV_8U); @@ -732,7 +735,7 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size, const Vec3d &c *this = image3d; } -void cv::viz::WImage3D::setImage(const Mat &image) +void cv::viz::WImage3D::setImage(InputArray image) { CV_Assert(!image.empty() && image.depth() == CV_8U); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 33d851d642..a886322471 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -112,6 +112,17 @@ void cv::viz::Viz3d::showWidget(const String &id, const Widget &widget, const Af void cv::viz::Viz3d::removeWidget(const String &id) { impl_->removeWidget(id); } cv::viz::Widget cv::viz::Viz3d::getWidget(const String &id) const { return impl_->getWidget(id); } void cv::viz::Viz3d::removeAllWidgets() { impl_->removeAllWidgets(); } + + +void cv::viz::Viz3d::showImage(InputArray image, const Size& window_size) +{ + removeAllWidgets(); + if (window_size.width > 0 && window_size.height > 0) + setWindowSize(window_size); + + showWidget("showImage", WImageOverlay(image, Rect(Point(0,0), getWindowSize()))); +} + void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3d &pose) { impl_->setWidgetPose(id, pose); } void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3d &pose) { impl_->updateWidgetPose(id, pose); } cv::Affine3d cv::viz::Viz3d::getWidgetPose(const String &id) const { return impl_->getWidgetPose(id); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 21c7e0d700..a553f8d721 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -122,6 +122,13 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) cv::viz::Viz3d cv::viz::getWindowByName(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } +cv::viz::Viz3d cv::viz::imshow(const String& window_name, InputArray image, const Size& window_size) +{ + Viz3d viz = getWindowByName(window_name); + viz.showImage(image, window_size); + return viz; +} + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write clouds. Supported formats: ply, stl, xyz, obj diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ff35bd4169..bb3f2009eb 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -250,6 +250,20 @@ TEST(Viz, DISABLED_show_overlay_image) //viz.spin(); } + +TEST(Viz, DISABLED_show_image_method) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + + Viz3d viz("show_image_method"); + viz.showImage(lena); + viz.spinOnce(1500, true); + viz.showImage(lena, lena.size()); + viz.spinOnce(1500, true); + + cv::viz::imshow("show_image_method", make_gray(lena)).spin(); +} + TEST(Viz, DISABLED_show_image_3d) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); From dac27c99138ac2a578bbf2fd650b18b0704ccf5c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 23:07:30 +0400 Subject: [PATCH 67/91] refactored arrow --- modules/viz/src/shapes.cpp | 17 ++++------------- modules/viz/test/tests_simple.cpp | 11 +++++++++++ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 611b1c3f95..6e0371a3fe 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -192,22 +192,13 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness Vec3d zvec = normalized(xvec.cross(arbitrary)); Vec3d yvec = zvec.cross(xvec); - Affine3d pose = makeTransformToGlobal(xvec, yvec, zvec); + Matx33d R = makeTransformToGlobal(xvec, yvec, zvec).rotation(); + Affine3d transform_with_scale(R * length, startPoint); - // Apply the transforms - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Translate(startPoint.val); - transform->Concatenate(vtkmatrix(pose.matrix)); - transform->Scale(length, length, length); - - // Transform the polydata - vtkSmartPointer transformPD = vtkSmartPointer::New(); - transformPD->SetTransform(transform); - transformPD->SetInputConnection(arrow_source->GetOutputPort()); - transformPD->Update(); + vtkSmartPointer polydata = VtkUtils::TransformPolydata(arrow_source->GetOutputPort(), transform_with_scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, transformPD->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index bb3f2009eb..4d9b1cfd13 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -277,6 +277,8 @@ TEST(Viz, DISABLED_show_image_3d) viz.showWidget("arr1", WArrow(Vec3d(-0.5, -0.5, 0.0), Vec3d(0.2, 0.2, 0.0), 0.009, Color::raspberry())); viz.showWidget("img1", WImage3D(gray, Size2d(1.0, 1.0), Vec3d(-0.5, -0.5, 0.0), Vec3d(1.0, 1.0, 0.0), Vec3d(0.0, 1.0, 0.0))); + viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + int i = 0; while(!viz.wasStopped()) { @@ -286,6 +288,15 @@ TEST(Viz, DISABLED_show_image_3d) //viz.spin(); } +TEST(Viz, show_simple_widgets) +{ + Viz3d viz("show_simple_widgets"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("cube", WCube()); + viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); From c0cc5512285caf038dd329f54f1e43a921aded6b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 23:29:28 +0400 Subject: [PATCH 68/91] refactored circle --- modules/viz/doc/widget.rst | 27 ++++++++++--- modules/viz/include/opencv2/viz/widgets.hpp | 6 ++- modules/viz/src/precomp.hpp | 6 +++ modules/viz/src/shapes.cpp | 43 +++++++++++---------- modules/viz/test/tests_simple.cpp | 4 +- 5 files changed, 58 insertions(+), 28 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index c286339c21..f98039bbf6 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -349,23 +349,38 @@ viz::WCircle This 3D Widget defines a circle. :: - class CV_EXPORTS WCircle : public Widget3D + class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); + //! creates default planar circle centred at origin with plane normal along z-axis + WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); + + //! creates repositioned circle + WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); }; viz::WCircle::WCircle ------------------------------- -Constructs a WCircle. +Constructs default planar circle centred at origin with plane normal along z-axis -.. ocv:function:: WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()) +.. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); - :param pt: Center of the circle. - :param radius: Radius of the circle. + :param radius: Radius of the circle. :param thickness: Thickness of the circle. :param color: :ocv:class:`Color` of the circle. +viz::WCircle::WCircle +------------------------------- +Constructs repositioned planar circle. + +.. ocv:function:: WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); + + :param radius: Radius of the circle. + :param center: Center of the circle. + :param normal: Normal of the plane in which the circle lies. + :param thickness: Thickness of the circle. + :param color: :ocv:class:`Color` of the circle. + viz::WCylinder -------------- .. ocv:class:: WCylinder diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 8ab95c92a4..c58595635e 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -164,7 +164,11 @@ namespace cv class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3d& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); + //! creates default circle centred at origin with normal along z-axis + WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); + + //! creates repositioned circle + WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); }; class CV_EXPORTS WCylinder : public Widget3D diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 9c76d9dead..bc91191d17 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -209,6 +209,12 @@ namespace cv return scaled_color; } + inline Vec3d get_random_vec(double from = -10.0, double to = 10.0) + { + RNG& rng = theRNG(); + return Vec3d(rng.uniform(from, to), rng.uniform(from, to), rng.uniform(from, to)); + } + struct VtkUtils { template diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 6e0371a3fe..6731087c03 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -182,18 +182,17 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness arrow_source->SetTipRadius(thickness * 3.0); arrow_source->SetTipLength(thickness * 10.0); - RNG rng = theRNG(); - Vec3d arbitrary(rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0)); - Vec3d startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); + Vec3d arbitrary = get_random_vec(); + Vec3d start_point(pt1.x, pt1.y, pt1.z), end_point(pt2.x, pt2.y, pt2.z); - double length = norm(endPoint - startPoint); + double length = norm(end_point - start_point); - Vec3d xvec = normalized(endPoint - startPoint); + Vec3d xvec = normalized(end_point - start_point); Vec3d zvec = normalized(xvec.cross(arbitrary)); Vec3d yvec = zvec.cross(xvec); Matx33d R = makeTransformToGlobal(xvec, yvec, zvec).rotation(); - Affine3d transform_with_scale(R * length, startPoint); + Affine3d transform_with_scale(R * length, start_point); vtkSmartPointer polydata = VtkUtils::TransformPolydata(arrow_source->GetOutputPort(), transform_with_scale); @@ -216,32 +215,36 @@ template<> cv::viz::WArrow cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// circle widget implementation -cv::viz::WCircle::WCircle(const Point3d& pt, double radius, double thickness, const Color& color) +cv::viz::WCircle::WCircle(double radius, double thickness, const Color &color) { vtkSmartPointer disk = vtkSmartPointer::New(); - // Maybe the resolution should be lower e.g. 50 or 25 - disk->SetCircumferentialResolution(50); + disk->SetCircumferentialResolution(30); disk->SetInnerRadius(radius - thickness); disk->SetOuterRadius(radius + thickness); - - // Set the circle origin - vtkSmartPointer t = vtkSmartPointer::New(); - t->Identity(); - t->Translate(pt.x, pt.y, pt.z); - - vtkSmartPointer tf = vtkSmartPointer::New(); - tf->SetTransform(t); - tf->SetInputConnection(disk->GetOutputPort()); - tf->Update(); + disk->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, tf->GetOutput()); + VtkUtils::SetInputData(mapper, disk->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); + actor->GetProperty()->LightingOff(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); setColor(color); + +} + +cv::viz::WCircle::WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness, const Color &color) +{ + Vec3d arbitrary = get_random_vec(); + Vec3d zvec = normalized(normal); + Vec3d xvec = normalized(zvec.cross(arbitrary)); + Vec3d yvec = zvec.cross(xvec); + + WCircle circle(radius, thickness, color); + circle.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center)); + *this = circle; } template<> cv::viz::WCircle cv::viz::Widget::cast() diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 4d9b1cfd13..794019432f 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -293,7 +293,9 @@ TEST(Viz, show_simple_widgets) Viz3d viz("show_simple_widgets"); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); - viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + viz.showWidget("arro", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + viz.showWidget("cir1", WCircle(0.5, 0.01, Color::bluberry())); + viz.showWidget("cir2", WCircle(0.5, Point3d(0.5, 0.0, 0.0), Vec3d(1.0, 0.0, 0.0), 0.01, Color::apricot())); viz.spin(); } From 08f50314cb0b8ca484c2e91f28f4eb58807e7605 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 23:40:56 +0400 Subject: [PATCH 69/91] updated cylinder and cube --- modules/viz/doc/widget.rst | 6 +++--- modules/viz/include/opencv2/viz/widgets.hpp | 4 ++-- modules/viz/src/shapes.cpp | 21 ++++++++++++++------- modules/viz/test/tests_simple.cpp | 3 +++ 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index f98039bbf6..474e0f2fb5 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -390,7 +390,7 @@ This 3D Widget defines a cylinder. :: class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3d& axis_point1, const Point3d& axis_point2, double radius, int numsides = 30, const Color &color = Color::white()); }; viz::WCylinder::WCylinder @@ -399,8 +399,8 @@ Constructs a WCylinder. .. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()) - :param pt_on_axis: A point on the axis of the cylinder. - :param axis_direction: Direction of the axis of the cylinder. + :param axis_point1: A point1 on the axis of the cylinder. + :param axis_point2: A point2 on the axis of the cylinder. :param radius: Radius of the cylinder. :param numsides: Resolution of the cylinder. :param color: :ocv:class:`Color` of the cylinder. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index c58595635e..3ebcd35c9e 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -164,7 +164,7 @@ namespace cv class CV_EXPORTS WCircle : public Widget3D { public: - //! creates default circle centred at origin with normal along z-axis + //! creates default planar circle centred at origin with plane normal along z-axis WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); //! creates repositioned circle @@ -174,7 +174,7 @@ namespace cv class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3d& axis_point1, const Point3d& axis_point2, double radius, int numsides = 30, const Color &color = Color::white()); }; class CV_EXPORTS WCube : public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 6731087c03..89e3cd38b1 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -256,17 +256,16 @@ template<> cv::viz::WCircle cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCylinder::WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides, const Color &color) +cv::viz::WCylinder::WCylinder(const Point3d& axis_point1, const Point3d& axis_point2, double radius, int numsides, const Color &color) { - const Point3d pt2 = pt_on_axis + axis_direction; vtkSmartPointer line = vtkSmartPointer::New(); - line->SetPoint1(pt_on_axis.x, pt_on_axis.y, pt_on_axis.z); - line->SetPoint2(pt2.x, pt2.y, pt2.z); + line->SetPoint1(axis_point1.x, axis_point1.y, axis_point1.z); + line->SetPoint2(axis_point2.x, axis_point2.y, axis_point2.z); vtkSmartPointer tuber = vtkSmartPointer::New(); tuber->SetInputConnection(line->GetOutputPort()); - tuber->SetRadius(radius); tuber->SetNumberOfSides(numsides); + tuber->SetRadius(radius); tuber->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -290,16 +289,24 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() cv::viz::WCube::WCube(const Point3d& min_point, const Point3d& max_point, bool wire_frame, const Color &color) { + double bounds[6]; + bounds[0] = std::min(min_point.x, max_point.x); + bounds[1] = std::max(min_point.x, max_point.x); + bounds[2] = std::min(min_point.y, max_point.y); + bounds[3] = std::max(min_point.y, max_point.y); + bounds[4] = std::min(min_point.z, max_point.z); + bounds[5] = std::max(min_point.z, max_point.z); + vtkSmartPointer cube; if (wire_frame) { cube = vtkSmartPointer::New(); - vtkOutlineSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z); + vtkOutlineSource::SafeDownCast(cube)->SetBounds(bounds); } else { cube = vtkSmartPointer::New(); - vtkCubeSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z); + vtkCubeSource::SafeDownCast(cube)->SetBounds(bounds); } cube->Update(); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 794019432f..f250d03a09 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -293,9 +293,12 @@ TEST(Viz, show_simple_widgets) Viz3d viz("show_simple_widgets"); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); + viz.showWidget("cub0", WCube(Vec3d::all(-1.0), Vec3d::all(-0.5), false, Color::indigo())); viz.showWidget("arro", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); viz.showWidget("cir1", WCircle(0.5, 0.01, Color::bluberry())); viz.showWidget("cir2", WCircle(0.5, Point3d(0.5, 0.0, 0.0), Vec3d(1.0, 0.0, 0.0), 0.01, Color::apricot())); + + viz.showWidget("cyl0", WCylinder(Vec3d(-0.5, 0.5, -0.5), Vec3d(0.5, 0.5, -0.5), 0.125, 30, Color::brown())); viz.spin(); } From bb891f05702ef08f04d090a763af03063022b902 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 00:05:59 +0400 Subject: [PATCH 70/91] added cone implementation --- modules/viz/doc/widget.rst | 42 ++++++++++++++++++++- modules/viz/include/opencv2/viz/widgets.hpp | 11 ++++++ modules/viz/src/precomp.hpp | 1 + modules/viz/src/shapes.cpp | 40 ++++++++++++++++++++ modules/viz/test/tests_simple.cpp | 2 + 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 474e0f2fb5..5b72adbd59 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -349,7 +349,7 @@ viz::WCircle This 3D Widget defines a circle. :: - class CV_EXPORTS WCircle : public Widget3D + class CV_EXPORTS WCircle : public Widget3D { public: //! creates default planar circle centred at origin with plane normal along z-axis @@ -381,6 +381,46 @@ Constructs repositioned planar circle. :param thickness: Thickness of the circle. :param color: :ocv:class:`Color` of the circle. + +viz::WCone +----------------- +.. ocv:class:: WCone + +This 3D Widget defines a cone. :: + + class CV_EXPORTS WCone : public Widget3D + { + public: + //! create default cone, oriented along x-axis with center of its base located at origin + WCone(double lenght, double radius, int resolution = 6.0, const Color &color = Color::white()); + + //! creates repositioned cone + WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()); + }; + +viz::WCone::WCone +------------------------------- +Constructs default cone oriented along x-axis with center of its base located at origin + +.. ocv:function:: WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()); + + :param length: Length of the cone. + :param radius: Radius of the cone. + :param resolution: Resolution of the cone. + :param color: :ocv:class:`Color` of the cone. + +viz::WCone::WCone +------------------------------- +Constructs repositioned planar cone. + +.. ocv:function:: WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()); + + :param radius: Radius of the cone. + :param center: Center of the cone base. + :param tip: Tip of the cone. + :param resolution: Resolution of the cone. + :param color: :ocv:class:`Color` of the cone. + viz::WCylinder -------------- .. ocv:class:: WCylinder diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 3ebcd35c9e..f745e54848 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -171,6 +171,16 @@ namespace cv WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); }; + class CV_EXPORTS WCone : public Widget3D + { + public: + //! create default cone, oriented along x-axis with center of its base located at origin + WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()); + + //! creates repositioned cone + WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()); + }; + class CV_EXPORTS WCylinder : public Widget3D { public: @@ -341,6 +351,7 @@ namespace cv template<> CV_EXPORTS WCylinder Widget::cast(); template<> CV_EXPORTS WArrow Widget::cast(); template<> CV_EXPORTS WCircle Widget::cast(); + template<> CV_EXPORTS WCone Widget::cast(); template<> CV_EXPORTS WCube Widget::cast(); template<> CV_EXPORTS WCoordinateSystem Widget::cast(); template<> CV_EXPORTS WPolyLine Widget::cast(); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index bc91191d17..4b963661d4 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -127,6 +127,7 @@ #include #include #include +#include #include #if !defined(_WIN32) || defined(__CYGWIN__) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 89e3cd38b1..5e76286c82 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -253,6 +253,46 @@ template<> cv::viz::WCircle cv::viz::Widget::cast() return static_cast(widget); } +/////////////////////////////////////////////////////////////////////////////////////////////// +/// WCone widget implementation + +cv::viz::WCone::WCone(double length, double radius, int resolution, const Color &color) +{ + vtkSmartPointer cone_source = vtkSmartPointer::New(); + cone_source->SetCenter(length*0.5, 0.0, 0.0); + cone_source->SetHeight(length); + cone_source->SetRadius(radius); + cone_source->SetResolution(resolution); + cone_source->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, cone_source->GetOutput()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); + setColor(color); +} + +cv::viz::WCone::WCone(double radius, const Point3d& center, const Point3d& tip, int resolution, const Color &color) +{ + Vec3d arbitrary = get_random_vec(); + Vec3d xvec = normalized(Vec3d(tip - center)); + Vec3d zvec = normalized(xvec.cross(arbitrary)); + Vec3d yvec = zvec.cross(xvec); + + WCone circle(norm(tip - center), radius, resolution, color); + circle.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center)); + *this = circle; +} + +template<> cv::viz::WCone cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} + /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index f250d03a09..58e909f5fb 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -299,6 +299,8 @@ TEST(Viz, show_simple_widgets) viz.showWidget("cir2", WCircle(0.5, Point3d(0.5, 0.0, 0.0), Vec3d(1.0, 0.0, 0.0), 0.01, Color::apricot())); viz.showWidget("cyl0", WCylinder(Vec3d(-0.5, 0.5, -0.5), Vec3d(0.5, 0.5, -0.5), 0.125, 30, Color::brown())); + viz.showWidget("con0", WCone(0.25, 0.125, 6, Color::azure())); + viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); viz.spin(); } From 53b8218652536d58dd71eb8690fff263b6122b9a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 00:31:45 +0400 Subject: [PATCH 71/91] addeed test for text 2d/3d --- modules/viz/include/opencv2/viz/widgets.hpp | 3 ++- modules/viz/src/shapes.cpp | 11 ++++++++--- modules/viz/test/tests_simple.cpp | 21 +++++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index f745e54848..75f9670f36 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -206,7 +206,7 @@ namespace cv class CV_EXPORTS WText : public Widget2D { public: - WText(const String &text, const Point2i &pos, int font_size = 20, const Color &color = Color::white()); + WText(const String &text, const Point &pos, int font_size = 20, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -215,6 +215,7 @@ namespace cv class CV_EXPORTS WText3D : public Widget3D { public: + //! creates text label in 3D. If face_camera = false, text plane normal is oriented along z-axis. Use widget pose to orient it properly WText3D(const String &text, const Point3d &position, double text_scale = 1., bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 5e76286c82..2e36a6d096 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -135,8 +135,12 @@ cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color) Vec3d p_center; plane->GetOrigin(p_center.val); + + vtkSmartPointer filter = PlaneUtils::setSize(p_center, plane->GetOutputPort(), size); + filter->Update(); + vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); + VtkUtils::SetInputData(mapper, filter->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -571,6 +575,7 @@ cv::viz::WText3D::WText3D(const String &text, const Point3d &position, double te actor->SetMapper(mapper); actor->SetPosition(position.x, position.y, position.z); actor->SetScale(text_scale); + actor->GetProperty()->LightingOff(); WidgetAccessor::setProp(*this, actor); } @@ -579,7 +584,7 @@ cv::viz::WText3D::WText3D(const String &text, const Point3d &position, double te void cv::viz::WText3D::setText(const String &text) { - vtkFollower *actor = vtkFollower::SafeDownCast(WidgetAccessor::getProp(*this)); + vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("This widget does not support text." && actor); // Update text source @@ -613,7 +618,7 @@ template<> cv::viz::WText3D cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// text widget implementation -cv::viz::WText::WText(const String &text, const Point2i &pos, int font_size, const Color &color) +cv::viz::WText::WText(const String &text, const Point &pos, int font_size, const Color &color) { vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetPosition(pos.x, pos.y); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 58e909f5fb..fe5cf33a05 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -291,6 +291,7 @@ TEST(Viz, DISABLED_show_image_3d) TEST(Viz, show_simple_widgets) { Viz3d viz("show_simple_widgets"); + viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); viz.showWidget("cub0", WCube(Vec3d::all(-1.0), Vec3d::all(-0.5), false, Color::indigo())); @@ -301,6 +302,26 @@ TEST(Viz, show_simple_widgets) viz.showWidget("cyl0", WCylinder(Vec3d(-0.5, 0.5, -0.5), Vec3d(0.5, 0.5, -0.5), 0.125, 30, Color::brown())); viz.showWidget("con0", WCone(0.25, 0.125, 6, Color::azure())); viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); + + viz.showWidget("text2d", WText("Simple text", Point(20, 20), 20, Color::green())); + + viz.showWidget("text3d", WText3D("Simple 3D text", Point3d( 0.5, 0.5, 0.5), 0.125, false, Color::green())); + + viz.spinOnce(1500, true); + viz.getWidget("text2d").cast().setText("New simple text"); + viz.getWidget("text3d").cast().setText("Updated text 3D"); + viz.spin(); +} + +TEST(Viz, show_follower) +{ + Viz3d viz("show_follower"); + + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("cube", WCube()); + viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); + viz.spinOnce(1500, true); + //viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); viz.spin(); } From 658f4a7d386cb2fd421494921944c592960ebd87 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 14:58:22 +0400 Subject: [PATCH 72/91] refactoed plane --- modules/viz/doc/widget.rst | 25 ++++++++++------- modules/viz/include/opencv2/viz/widgets.hpp | 7 +++-- modules/viz/src/shapes.cpp | 30 +++++++++++++++++++++ modules/viz/test/tests_simple.cpp | 6 +++-- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 5b72adbd59..bec5188a32 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -274,25 +274,30 @@ This 3D Widget defines a finite plane. :: class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); - WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); + //! created default plane with center point at origin and normal oriented along z-axis + WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); + + //! repositioned plane + WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); }; viz::WPlane::WPlane ------------------- -Constructs a WPlane. +Constructs a default plane with center point at origin and normal oriented along z-axis. -.. ocv:function:: WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()) +.. ocv:function:: WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); - :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. - :param size: Size of the plane. + :param size: Size of the plane :param color: :ocv:class:`Color` of the plane. -.. ocv:function:: WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()) +viz::WPlane::WPlane +Constructs a repositioned plane + +.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); - :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. - :param pt: Position of the plane. - :param size: Size of the plane. + :param center: Center of the plane + :param normal: Plane normal orientation + :param new_plane_yaxis: Up-vector. New orientation of plane y-axis. :param color: :ocv:class:`Color` of the plane. viz::WSphere diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 75f9670f36..f740a6210b 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -145,8 +145,11 @@ namespace cv class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); - WPlane(const Vec4d& coefs, const Point3d& pt, double size = 1.0, const Color &color = Color::white()); + //! created default plane with center point at origin and normal oriented along z-axis + WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); + + //! repositioned plane + WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); }; class CV_EXPORTS WSphere : public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 2e36a6d096..468022f978 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -125,6 +125,36 @@ namespace cv { namespace viz { namespace }; }}} +cv::viz::WPlane::WPlane(const Size2d& size, const Color &color) +{ + vtkSmartPointer plane = vtkSmartPointer::New(); + plane->SetOrigin(-0.5 * size.width, -0.5 * size.height, 0.0); + plane->SetPoint1( 0.5 * size.width, -0.5 * size.height, 0.0); + plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0); + plane->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, plane->GetOutput()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + actor->GetProperty()->LightingOff(); + + WidgetAccessor::setProp(*this, actor); + setColor(color); +} + +cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis, const Size2d& size, const Color &color) +{ + Vec3d zvec = normalize(normal); + Vec3d xvec = normalize(new_plane_yaxis.cross(zvec)); + Vec3d yvec = zvec.cross(xvec); + + WPlane plane(size, color); + plane.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center)); + *this = plane; +} + cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index fe5cf33a05..85cdeacf1b 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -304,16 +304,18 @@ TEST(Viz, show_simple_widgets) viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); viz.showWidget("text2d", WText("Simple text", Point(20, 20), 20, Color::green())); - viz.showWidget("text3d", WText3D("Simple 3D text", Point3d( 0.5, 0.5, 0.5), 0.125, false, Color::green())); + viz.showWidget("plane1", WPlane(Size2d(0.25, 0.75))); + viz.showWidget("plane2", WPlane(Vec3d(0.5, -0.5, -0.5), Vec3d(0.0, 1.0, 1.0), Vec3d(1.0, 1.0, 0.0), Size2d(1.0, 0.5), Color::gold())); + viz.spinOnce(1500, true); viz.getWidget("text2d").cast().setText("New simple text"); viz.getWidget("text3d").cast().setText("Updated text 3D"); viz.spin(); } -TEST(Viz, show_follower) +TEST(Viz, DISABLED_show_follower) { Viz3d viz("show_follower"); From e2ef558c8a85cc3258a87c0d525f286a37704097 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 15:22:26 +0400 Subject: [PATCH 73/91] refactored WGrid --- modules/viz/doc/widget.rst | 35 +++--- modules/viz/include/opencv2/viz/widgets.hpp | 13 +- modules/viz/src/shapes.cpp | 129 ++++---------------- modules/viz/test/tests_simple.cpp | 2 + 4 files changed, 55 insertions(+), 124 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index bec5188a32..13409974f6 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -291,13 +291,14 @@ Constructs a default plane with center point at origin and normal oriented along :param color: :ocv:class:`Color` of the plane. viz::WPlane::WPlane +------------------- Constructs a repositioned plane -.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); +.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); :param center: Center of the plane :param normal: Plane normal orientation - :param new_plane_yaxis: Up-vector. New orientation of plane y-axis. + :param new_yaxis: Up-vector. New orientation of plane y-axis. :param color: :ocv:class:`Color` of the plane. viz::WSphere @@ -388,7 +389,7 @@ Constructs repositioned planar circle. viz::WCone ------------------ +------------------------------- .. ocv:class:: WCone This 3D Widget defines a cone. :: @@ -527,28 +528,32 @@ This 3D Widget defines a grid. :: class CV_EXPORTS WGrid : public Widget3D { public: - //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - //! Creates grid based on the plane equation - WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + //! Creates grid at the origin and normal oriented along z-axis + WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); + + //! Creates repositioned grid + WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, + const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); }; viz::WGrid::WGrid --------------------------- Constructs a WGrid. -.. ocv:function:: WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()) +.. ocv:function:: WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); - :param dimensions: Number of columns and rows, respectively. - :param spacing: Size of each column and row, respectively. + :param cells: Number of cell columns and rows, respectively. + :param cells_spacing: Size of each cell, respectively. :param color: :ocv:class:`Color` of the grid. -.. ocv:function: WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()) +.. ocv:function: WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, Vec2i &cells, const Vec2d &cells_spacing, const Color &color; - :param coeffs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. - :param dimensions: Number of columns and rows, respectively. - :param spacing: Size of each column and row, respectively. - :param color: :ocv:class:`Color` of the grid. + :param center: Center of the grid + :param normal: Grid normal orientation + :param new_yaxis: Up-vector. New orientation of grid y-axis. + :param cells: Number of cell columns and rows, respectively. + :param cells_spacing: Size of each cell, respectively. + :param color: :ocv:class:`Color` of the grid.. viz::WText3D ------------ diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index f740a6210b..ec17f6576f 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -149,7 +149,8 @@ namespace cv WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); //! repositioned plane - WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); + WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, + const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); }; class CV_EXPORTS WSphere : public Widget3D @@ -257,10 +258,12 @@ namespace cv class CV_EXPORTS WGrid : public Widget3D { public: - //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - //! Creates grid based on the plane equation - WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + //! Creates grid at the origin and normal oriented along z-axis + WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); + + //! Creates repositioned grid + WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, + const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); }; class CV_EXPORTS WCameraPosition : public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 468022f978..7124d40215 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -144,10 +144,10 @@ cv::viz::WPlane::WPlane(const Size2d& size, const Color &color) setColor(color); } -cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis, const Size2d& size, const Color &color) +cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Size2d& size, const Color &color) { Vec3d zvec = normalize(normal); - Vec3d xvec = normalize(new_plane_yaxis.cross(zvec)); + Vec3d xvec = normalize(new_yaxis.cross(zvec)); Vec3d yvec = zvec.cross(xvec); WPlane plane(size, color); @@ -155,51 +155,6 @@ cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& *this = plane; } -cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color) -{ - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetNormal(coefs[0], coefs[1], coefs[2]); - double norm = cv::norm(Vec3d(coefs.val)); - plane->Push(-coefs[3] / norm); - - Vec3d p_center; - plane->GetOrigin(p_center.val); - - - vtkSmartPointer filter = PlaneUtils::setSize(p_center, plane->GetOutputPort(), size); - filter->Update(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, filter->GetOutput()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); - setColor(color); -} - -cv::viz::WPlane::WPlane(const Vec4d& coefs, const Point3d& pt, double size, const Color &color) -{ - vtkSmartPointer plane = vtkSmartPointer::New(); - Point3d coefs3(coefs[0], coefs[1], coefs[2]); - double norm_sqr = 1.0 / coefs3.dot(coefs3); - plane->SetNormal(coefs[0], coefs[1], coefs[2]); - - double t = coefs3.dot(pt) + coefs[3]; - Vec3d p_center = pt - coefs3 * t * norm_sqr; - plane->SetCenter(p_center[0], p_center[1], p_center[2]); - - vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); - setColor(color); -} - template<> cv::viz::WPlane cv::viz::Widget::cast() { Widget3D widget = this->cast(); @@ -500,38 +455,26 @@ template<> cv::viz::WPolyLine cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// grid widget implementation -namespace cv { namespace viz { namespace -{ - struct GridUtils - { - static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2f &spacing) - { - // Create the grid using image data - vtkSmartPointer grid = vtkSmartPointer::New(); - - // Add 1 to dimensions because in ImageData dimensions is the number of lines - // - however here it means number of cells - grid->SetDimensions(dimensions[0]+1, dimensions[1]+1, 1); - grid->SetSpacing(spacing[0], spacing[1], 0.); - - // Set origin of the grid to be the middle of the grid - grid->SetOrigin(dimensions[0] * spacing[0] * (-0.5), dimensions[1] * spacing[1] * (-0.5), 0); - - // Extract the edges so we have the grid - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(grid->GetProducerPort()); - filter->Update(); - return filter->GetOutput(); - } - }; -}}} -cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec2i &cells, const Vec2d &cells_spacing, const Color &color) { - vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); + vtkSmartPointer grid_data = vtkSmartPointer::New(); + + // Add 1 to dimensions because in ImageData dimensions is the number of lines + // - however here it means number of cells + grid_data->SetDimensions(cells[0]+1, cells[1]+1, 1); + grid_data->SetSpacing(cells_spacing[0], cells_spacing[1], 0.); + + // Set origin of the grid to be the middle of the grid + grid_data->SetOrigin(cells[0] * cells_spacing[0] * (-0.5), cells[1] * cells_spacing[1] * (-0.5), 0); + + // Extract the edges so we have the grid + vtkSmartPointer extract_edges = vtkSmartPointer::New(); + extract_edges->SetInputConnection(grid_data->GetProducerPort()); + extract_edges->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, grid); + VtkUtils::SetInputData(mapper, extract_edges->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -540,37 +483,15 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color setColor(color); } -cv::viz::WGrid::WGrid(const Vec4d &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Vec2i &cells, const Vec2d &cells_spacing, const Color &color) { - vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); - - // Estimate the transform to set the normal based on the coefficients - Vec3d normal(coefs[0], coefs[1], coefs[2]); - Vec3d up_vector(0.0, 1.0, 0.0); // Just set as default - double push_distance = -coefs[3]/cv::norm(Vec3d(coefs.val)); - Vec3d n = normalize(normal); - Vec3d u = normalize(up_vector.cross(n)); - Vec3d v = n.cross(u); - - Affine3d pose = makeTransformToGlobal(u, v, n, n * push_distance); - - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->SetMatrix(vtkmatrix(pose.matrix)); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(grid->GetProducerPort()); - transform_filter->Update(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, transform_filter->GetOutput()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); + Vec3d zvec = normalize(normal); + Vec3d xvec = normalize(new_yaxis.cross(zvec)); + Vec3d yvec = zvec.cross(xvec); - WidgetAccessor::setProp(*this, actor); - setColor(color); + WGrid grid(cells, cells_spacing, color); + grid.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center)); + *this = grid; } template<> cv::viz::WGrid cv::viz::Widget::cast() diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 85cdeacf1b..db105d7936 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -309,6 +309,8 @@ TEST(Viz, show_simple_widgets) viz.showWidget("plane1", WPlane(Size2d(0.25, 0.75))); viz.showWidget("plane2", WPlane(Vec3d(0.5, -0.5, -0.5), Vec3d(0.0, 1.0, 1.0), Vec3d(1.0, 1.0, 0.0), Size2d(1.0, 0.5), Color::gold())); + viz.showWidget("grid1", WGrid(Vec2i(7,7), Vec2d::all(0.75), Color::gray()), Affine3d().translate(Vec3d(0.0, 0.0, -1.0))); + viz.spinOnce(1500, true); viz.getWidget("text2d").cast().setText("New simple text"); viz.getWidget("text3d").cast().setText("Updated text 3D"); From d7c30281a587b6b136668e50cb37a6ee15389ca1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 15:46:03 +0400 Subject: [PATCH 74/91] set background texture method --- modules/viz/include/opencv2/viz/viz3d.hpp | 2 + modules/viz/src/shapes.cpp | 23 --------- modules/viz/src/viz3d.cpp | 13 ++--- modules/viz/src/vizimpl.cpp | 58 +++++++++++++++++++++++ modules/viz/src/vizimpl.hpp | 5 ++ modules/viz/test/tests_simple.cpp | 13 +++-- 6 files changed, 78 insertions(+), 36 deletions(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 4ffb6b3c5a..daebc5d0cc 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -99,6 +99,8 @@ namespace cv void setWindowPosition(const Point& window_position); void setFullScreen(bool mode = true); void setBackgroundColor(const Color& color = Color::black()); + void setBackgroundTexture(InputArray image = noArray()); + void setBackgroundMeshLab(); void spin(); void spinOnce(int time = 1, bool force_redraw = false); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 7124d40215..92ab3400be 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -102,29 +102,6 @@ template<> cv::viz::WSphere cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// plane widget implementation -namespace cv { namespace viz { namespace -{ - struct PlaneUtils - { - template - static vtkSmartPointer setSize(const Vec<_Tp, 3> ¢er, vtkSmartPointer poly_data_port, double size) - { - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(center[0], center[1], center[2]); - transform->Scale(size, size, size); - transform->Translate(-center[0], -center[1], -center[2]); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetInputConnection(poly_data_port); - transform_filter->SetTransform(transform); - transform_filter->Update(); - - return transform_filter; - } - }; -}}} - cv::viz::WPlane::WPlane(const Size2d& size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index a886322471..7a63435136 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -113,15 +113,7 @@ void cv::viz::Viz3d::removeWidget(const String &id) { impl_->removeWidget(id); } cv::viz::Widget cv::viz::Viz3d::getWidget(const String &id) const { return impl_->getWidget(id); } void cv::viz::Viz3d::removeAllWidgets() { impl_->removeAllWidgets(); } - -void cv::viz::Viz3d::showImage(InputArray image, const Size& window_size) -{ - removeAllWidgets(); - if (window_size.width > 0 && window_size.height > 0) - setWindowSize(window_size); - - showWidget("showImage", WImageOverlay(image, Rect(Point(0,0), getWindowSize()))); -} +void cv::viz::Viz3d::showImage(InputArray image, const Size& window_size) { impl_->showImage(image, window_size); } void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3d &pose) { impl_->setWidgetPose(id, pose); } void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3d &pose) { impl_->updateWidgetPose(id, pose); } @@ -146,6 +138,9 @@ void cv::viz::Viz3d::setWindowPosition(const Point& window_position) { impl_->se void cv::viz::Viz3d::setFullScreen(bool mode) { impl_->setFullScreen(mode); } void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } +void cv::viz::Viz3d::setBackgroundTexture(InputArray image) { impl_->setBackgroundTexture(image); } +void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } + void cv::viz::Viz3d::setRenderingProperty(const String &id, int property, double value) { getWidget(id).setRenderingProperty(property, value); } double cv::viz::Viz3d::getRenderingProperty(const String &id, int property) { return getWidget(id).getRenderingProperty(property); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index dd568c9404..5e497afb79 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -269,6 +269,15 @@ void cv::viz::Viz3d::VizImpl::removeAllWidgets() widget_actor_map_->clear(); renderer_->RemoveAllViewProps(); } +///////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::showImage(InputArray image, const Size& window_size) +{ + removeAllWidgets(); + if (window_size.width > 0 && window_size.height > 0) + setWindowSize(window_size); + + showWidget("showImage", WImageOverlay(image, Rect(Point(0,0), getWindowSize()))); +} ///////////////////////////////////////////////////////////////////////////////////////////// bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer actor) @@ -295,6 +304,55 @@ void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) renderer_->SetBackground(c.val); } +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) +{ + if (image.empty()) + { + renderer_->SetBackgroundTexture(0); + renderer_->TexturedBackgroundOff(); + return; + } + + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); + + vtkSmartPointer image_flip = vtkSmartPointer::New(); + image_flip->SetFilteredAxis(1); // Vertical flip + image_flip->SetInputConnection(source->GetOutputPort()); + + vtkSmartPointer texture = vtkSmartPointer::New(); + texture->SetInputConnection(image_flip->GetOutputPort()); + //texture->Update(); + + renderer_->SetBackgroundTexture(texture); + renderer_->TexturedBackgroundOn(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() +{ + static Color up(2, 1, 1), down(240, 120, 120); + static Mat meshlab_texture; + + if (meshlab_texture.empty()) + { + meshlab_texture.create(2048, 2048, CV_8UC4); + + for (int y = 0; y < meshlab_texture.rows; ++y) + { + double alpha = (y+1)/(double)meshlab_texture.rows; + Vec4b color = up * (1 - alpha) + down * alpha; + + Vec4b *row = meshlab_texture.ptr(y); + for(int x = 0; x < meshlab_texture.cols; ++x) + row[x] = color; + } + + } + setBackgroundTexture(meshlab_texture); +} + ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera) { diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index b6ae549270..e7534ea70a 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -62,6 +62,8 @@ public: Widget getWidget(const String &id) const; void removeAllWidgets(); + void showImage(InputArray image, const Size& window_size); + void setWidgetPose(const String &id, const Affine3d &pose); void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; @@ -109,6 +111,9 @@ public: String getWindowName() const; void setBackgroundColor(const Color& color); + void setBackgroundTexture(InputArray image); + void setBackgroundMeshLab(); + void spin(); void spinOnce(int time = 1, bool force_redraw = false); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index db105d7936..a4f566eba5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -57,7 +57,7 @@ TEST(Viz, DISABLED_show_cloud_bluberry) viz.spin(); } -TEST(Viz, DISABLED_show_cloud_random_color) +TEST(Viz, show_cloud_random_color) { Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); @@ -67,6 +67,7 @@ TEST(Viz, DISABLED_show_cloud_random_color) Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); Viz3d viz("show_cloud_random_color"); + viz.setBackgroundMeshLab(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, colors), pose); viz.spin(); @@ -229,6 +230,7 @@ TEST(Viz, DISABLED_show_overlay_image) Size2d half_lsize = Size2d(lena.size()) * 0.5; Viz3d viz("show_overlay_image"); + viz.setBackgroundMeshLab(); Size vsz = viz.getWindowSize(); viz.showWidget("coos", WCoordinateSystem()); @@ -264,12 +266,13 @@ TEST(Viz, DISABLED_show_image_method) cv::viz::imshow("show_image_method", make_gray(lena)).spin(); } -TEST(Viz, DISABLED_show_image_3d) +TEST(Viz, show_image_3d) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); Mat gray = make_gray(lena); Viz3d viz("show_image_3d"); + viz.setBackgroundMeshLab(); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); viz.showWidget("arr0", WArrow(Vec3d(0.5, 0.0, 0.0), Vec3d(1.5, 0.0, 0.0), 0.009, Color::raspberry())); @@ -291,6 +294,7 @@ TEST(Viz, DISABLED_show_image_3d) TEST(Viz, show_simple_widgets) { Viz3d viz("show_simple_widgets"); + viz.setBackgroundMeshLab(); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); @@ -317,15 +321,16 @@ TEST(Viz, show_simple_widgets) viz.spin(); } -TEST(Viz, DISABLED_show_follower) +TEST(Viz, show_follower) { Viz3d viz("show_follower"); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); + viz.setBackgroundMeshLab(); viz.spinOnce(1500, true); - //viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); + viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); viz.spin(); } From b0ca93b22ca359ddb596e7eb7831d46b0b38c7c2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 15:56:54 +0400 Subject: [PATCH 75/91] by default enabled tests vtk --- CMakeLists.txt | 2 +- modules/viz/test/tests_simple.cpp | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 171046774a..7f9b1de9ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,7 @@ endif() OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O" ON IF IOS) OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa" OFF IF APPLE ) -OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" OFF IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" ON IF (NOT IOS) ) OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library support" ON IF (NOT IOS) ) OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" OFF IF (NOT IOS) ) diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index a4f566eba5..5a685bb592 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -45,7 +45,7 @@ using namespace cv; using namespace cv::viz; -TEST(Viz, DISABLED_show_cloud_bluberry) +TEST(Viz, show_cloud_bluberry) { Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); @@ -73,7 +73,7 @@ TEST(Viz, show_cloud_random_color) viz.spin(); } -TEST(Viz, DISABLED_show_cloud_masked) +TEST(Viz, show_cloud_masked) { Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); @@ -90,7 +90,7 @@ TEST(Viz, DISABLED_show_cloud_masked) viz.spin(); } -TEST(Viz, DISABLED_show_cloud_collection) +TEST(Viz, show_cloud_collection) { Mat cloud = readCloud(get_dragon_ply_file_path()); @@ -105,7 +105,7 @@ TEST(Viz, DISABLED_show_cloud_collection) viz.spin(); } -TEST(Viz, DISABLED_show_mesh) +TEST(Viz, show_mesh) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); @@ -117,7 +117,7 @@ TEST(Viz, DISABLED_show_mesh) viz.spin(); } -TEST(Viz, DISABLED_show_mesh_random_colors) +TEST(Viz, show_mesh_random_colors) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); @@ -131,7 +131,7 @@ TEST(Viz, DISABLED_show_mesh_random_colors) viz.spin(); } -TEST(Viz, DISABLED_show_polyline) +TEST(Viz, show_polyline) { Mat polyline(1, 32, CV_64FC3); for(size_t i = 0; i < polyline.total(); ++i) @@ -143,7 +143,7 @@ TEST(Viz, DISABLED_show_polyline) viz.spin(); } -TEST(Viz, DISABLED_show_sampled_normals) +TEST(Viz, show_sampled_normals) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); computeNormals(mesh, mesh.normals); @@ -157,7 +157,7 @@ TEST(Viz, DISABLED_show_sampled_normals) viz.spin(); } -TEST(Viz, DISABLED_show_trajectories) +TEST(Viz, show_trajectories) { std::vector path = generate_test_trajectory(), sub0, sub1, sub2, sub3, sub4, sub5; @@ -189,7 +189,7 @@ TEST(Viz, DISABLED_show_trajectories) //viz.spin(); } -TEST(Viz, DISABLED_show_trajectory_reposition) +TEST(Viz, show_trajectory_reposition) { std::vector path = generate_test_trajectory(); @@ -199,7 +199,7 @@ TEST(Viz, DISABLED_show_trajectory_reposition) viz.spin(); } -TEST(Viz, DISABLED_show_camera_positions) +TEST(Viz, show_camera_positions) { Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); @@ -222,7 +222,7 @@ TEST(Viz, DISABLED_show_camera_positions) viz.spin(); } -TEST(Viz, DISABLED_show_overlay_image) +TEST(Viz, show_overlay_image) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); Mat gray = make_gray(lena); @@ -253,7 +253,7 @@ TEST(Viz, DISABLED_show_overlay_image) } -TEST(Viz, DISABLED_show_image_method) +TEST(Viz, show_image_method) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); From 3086095837e01f96ac43d40c11c813aa8fd206b2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 16:40:41 +0400 Subject: [PATCH 76/91] improved background gradient --- modules/viz/include/opencv2/viz/viz3d.hpp | 1 + modules/viz/src/viz3d.cpp | 1 + modules/viz/src/vizimpl.cpp | 39 +++++++++-------------- modules/viz/src/vizimpl.hpp | 2 +- modules/viz/test/test_viz3d.cpp | 3 +- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index daebc5d0cc..b9712ef3e4 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -100,6 +100,7 @@ namespace cv void setFullScreen(bool mode = true); void setBackgroundColor(const Color& color = Color::black()); void setBackgroundTexture(InputArray image = noArray()); + void setBackgroundGradient(const Color& up, const Color& down); void setBackgroundMeshLab(); void spin(); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 7a63435136..503359f013 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -137,6 +137,7 @@ void cv::viz::Viz3d::saveScreenshot(const String &file) { impl_->saveScreenshot( void cv::viz::Viz3d::setWindowPosition(const Point& window_position) { impl_->setWindowPosition(window_position); } void cv::viz::Viz3d::setFullScreen(bool mode) { impl_->setFullScreen(mode); } void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } +void cv::viz::Viz3d::setBackgroundGradient(const Color& up, const Color& down) { impl_->setBackgroundGradient(up, down); } void cv::viz::Viz3d::setBackgroundTexture(InputArray image) { impl_->setBackgroundTexture(image); } void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 5e497afb79..61a0a01f62 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -302,6 +302,21 @@ void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) { Color c = vtkcolor(color); renderer_->SetBackground(c.val); + renderer_->GradientBackgroundOff(); +} + +void cv::viz::Viz3d::VizImpl::setBackgroundGradient(const Color& up, const Color& down) +{ + Color vtkup = vtkcolor(up), vtkdown = vtkcolor(down); + renderer_->SetBackground(vtkdown.val); + renderer_->SetBackground2(vtkup.val); + renderer_->GradientBackgroundOn(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() +{ + setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -329,30 +344,6 @@ void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) renderer_->TexturedBackgroundOn(); } -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() -{ - static Color up(2, 1, 1), down(240, 120, 120); - static Mat meshlab_texture; - - if (meshlab_texture.empty()) - { - meshlab_texture.create(2048, 2048, CV_8UC4); - - for (int y = 0; y < meshlab_texture.rows; ++y) - { - double alpha = (y+1)/(double)meshlab_texture.rows; - Vec4b color = up * (1 - alpha) + down * alpha; - - Vec4b *row = meshlab_texture.ptr(y); - for(int x = 0; x < meshlab_texture.cols; ++x) - row[x] = color; - } - - } - setBackgroundTexture(meshlab_texture); -} - ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera) { diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index e7534ea70a..11b8490a1f 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -110,7 +110,7 @@ public: void setFullScreen(bool mode); String getWindowName() const; void setBackgroundColor(const Color& color); - + void setBackgroundGradient(const Color& up, const Color& down); void setBackgroundTexture(InputArray image); void setBackgroundMeshLab(); diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index aec326508e..1fd1d4a338 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -51,8 +51,9 @@ TEST(Viz_viz3d, develop) //theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); cv::viz::Viz3d viz("abc"); - viz.setBackgroundColor(cv::viz::Color::mlab()); + viz.setBackgroundMeshLab(); viz.showWidget("coo", cv::viz::WCoordinateSystem(1)); + viz.showWidget("cloud", cv::viz::WCloud(cloud)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); From 74206e015956737d97b3a115f2de62e6e39a45df Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 18:05:07 +0400 Subject: [PATCH 77/91] added painted cloud widget --- modules/viz/include/opencv2/viz/widgets.hpp | 14 ++++ modules/viz/src/clouds.cpp | 84 +++++++++++++++++++-- modules/viz/src/precomp.hpp | 2 + modules/viz/test/test_viz3d.cpp | 4 +- modules/viz/test/tests_simple.cpp | 16 +++- 5 files changed, 113 insertions(+), 7 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index ec17f6576f..2c49b9d0e2 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -323,6 +323,19 @@ namespace cv WCloud(InputArray cloud, const Color &color = Color::white()); }; + class CV_EXPORTS WPaintedCloud: public Widget3D + { + public: + //! Paint cloud with default gradient between cloud bounds points + WPaintedCloud(InputArray cloud); + + //! Paint cloud with default gradient between given points + WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2); + + //! Paint cloud with gradient specified by given colors between given points + WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2, const Color& c1, const Color c2); + }; + class CV_EXPORTS WCloudCollection : public Widget3D { public: @@ -372,6 +385,7 @@ namespace cv template<> CV_EXPORTS WTrajectoryFrustums Widget::cast(); template<> CV_EXPORTS WTrajectorySpheres Widget::cast(); template<> CV_EXPORTS WCloud Widget::cast(); + template<> CV_EXPORTS WPaintedCloud Widget::cast(); template<> CV_EXPORTS WCloudCollection Widget::cast(); template<> CV_EXPORTS WCloudNormals Widget::cast(); template<> CV_EXPORTS WMesh Widget::cast(); diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 9ea1d76fe8..d5283d430b 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -72,15 +72,90 @@ cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors) } cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) +{ + WCloud cloud_widget(cloud, Mat(cloud.size(), CV_8UC3, color)); + *this = cloud_widget; +} + + +template<> cv::viz::WCloud cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Painted Cloud Widget implementation + +cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud) { vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetCloud(cloud); cloud_source->Update(); + Vec6d bounds(cloud_source->GetOutput()->GetPoints()->GetBounds()); + + WPaintedCloud cloud_widget(cloud, Vec3d(bounds[0], bounds[2], bounds[4]), Vec3d(bounds[1], bounds[3], bounds[5])); + *this = cloud_widget; +} + +cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2) +{ + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetCloud(cloud); + + vtkSmartPointer elevation = vtkSmartPointer::New(); + elevation->SetInputConnection(cloud_source->GetOutputPort()); + elevation->SetLowPoint(p1.x, p1.y, p1.z); + elevation->SetHighPoint(p2.x, p2.y, p2.z); + elevation->SetScalarRange(0.0, 1.0); + elevation->Update(); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, cloud_source->GetOutput()); + VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); + mapper->ImmediateModeRenderingOff(); + mapper->ScalarVisibilityOn(); + mapper->SetColorModeToMapScalars(); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); +} + +cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2, const Color& c1, const Color c2) +{ + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetCloud(cloud); + + vtkSmartPointer elevation = vtkSmartPointer::New(); + elevation->SetInputConnection(cloud_source->GetOutputPort()); + elevation->SetLowPoint(p1.x, p1.y, p1.z); + elevation->SetHighPoint(p2.x, p2.y, p2.z); + elevation->SetScalarRange(0.0, 1.0); + elevation->Update(); + + Color vc1 = vtkcolor(c1), vc2 = vtkcolor(c2); + vtkSmartPointer color_transfer = vtkSmartPointer::New(); + color_transfer->SetColorSpaceToRGB(); + color_transfer->AddRGBPoint(0.0, vc1[0], vc1[1], vc1[2]); + color_transfer->AddRGBPoint(1.0, vc2[0], vc2[1], vc2[2]); + color_transfer->SetScaleToLinear(); + color_transfer->Build(); + + //if in future some need to replace color table with real scalars, then this can be done usine next calls: + //vtkDataArray *float_scalars = vtkPolyData::SafeDownCast(elevation->GetOutput())->GetPointData()->GetArray("Elevation"); + //vtkSmartPointer polydata = cloud_source->GetOutput(); + //polydata->GetPointData()->SetScalars(color_transfer->MapScalars(float_scalars, VTK_COLOR_MODE_DEFAULT, 0)); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); mapper->ImmediateModeRenderingOff(); - mapper->ScalarVisibilityOff(); + mapper->ScalarVisibilityOn(); + mapper->SetColorModeToMapScalars(); + mapper->SetLookupTable(color_transfer); vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->SetInterpolationToFlat(); @@ -88,13 +163,12 @@ cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } -template<> cv::viz::WCloud cv::viz::Widget::cast() +template<> cv::viz::WPaintedCloud cv::viz::Widget::cast() { Widget3D widget = this->cast(); - return static_cast(widget); + return static_cast(widget); } /////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 4b963661d4..d5f969a495 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -128,6 +128,8 @@ #include #include #include +#include +#include #include #if !defined(_WIN32) || defined(__CYGWIN__) diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 1fd1d4a338..66ec25db81 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -53,7 +53,9 @@ TEST(Viz_viz3d, develop) cv::viz::Viz3d viz("abc"); viz.setBackgroundMeshLab(); viz.showWidget("coo", cv::viz::WCoordinateSystem(1)); - viz.showWidget("cloud", cv::viz::WCloud(cloud)); + //viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0))); + //viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), cv::viz::Color::green(), cv::viz::Color::red())); + viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 5a685bb592..3e25399b25 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -95,7 +95,7 @@ TEST(Viz, show_cloud_collection) Mat cloud = readCloud(get_dragon_ply_file_path()); WCloudCollection ccol; - ccol.addCloud(cloud, Color::white(), Affine3d().translate(Vec3d(0, 0, 0)).rotate(Vec3d(1.57, 0, 0))); + ccol.addCloud(cloud, Color::white(), Affine3d().translate(Vec3d(0, 0, 0)).rotate(Vec3d(CV_PI/2, 0, 0))); ccol.addCloud(cloud, Color::blue(), Affine3d().translate(Vec3d(1, 0, 0))); ccol.addCloud(cloud, Color::red(), Affine3d().translate(Vec3d(2, 0, 0))); @@ -105,6 +105,20 @@ TEST(Viz, show_cloud_collection) viz.spin(); } +TEST(Viz, show_painted_clouds) +{ + Mat cloud = readCloud(get_dragon_ply_file_path()); + + Viz3d viz("show_painted_clouds"); + viz.setBackgroundMeshLab(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("cloud1", WPaintedCloud(cloud), Affine3d(Vec3d(0.0, -CV_PI/2, 0.0), Vec3d(-1.5, 0.0, 0.0))); + viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); + viz.showWidget("cloud3", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), Color::blue(), Color::red())); + viz.showWidget("arrow", WArrow(Vec3d(0.0, 1.0, -1.0), Vec3d(0.0, 1.0, 1.0), 0.009, Color::raspberry())); + viz.spin(); +} + TEST(Viz, show_mesh) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); From 625c35a9f9eccc73d37a353ec042c4c9ca77f9d6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 13 Jan 2014 00:46:24 +0400 Subject: [PATCH 78/91] added support of texture for mesh --- modules/viz/include/opencv2/viz.hpp | 5 +++ modules/viz/include/opencv2/viz/types.hpp | 2 + modules/viz/src/clouds.cpp | 33 ++++++++++++-- modules/viz/src/vizcore.cpp | 2 + modules/viz/src/vtk/vtkCloudMatSource.cpp | 54 ++++++++++++++++++++++- modules/viz/src/vtk/vtkCloudMatSource.h | 9 +++- 6 files changed, 99 insertions(+), 6 deletions(-) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 32e32a7a3b..89810d5472 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -98,6 +98,11 @@ namespace cv CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray(), bool binary = false); CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Read mesh. Only ply format is supported now + + CV_EXPORTS Mesh readMesh (const String& file); + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 01ddd0289e..cdd89d3a0f 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -113,6 +113,8 @@ namespace cv //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud. Mat polygons; + Mat texture, tcoords; + //! Loads mesh from a given ply file static Mesh load(const String& file); }; diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index d5283d430b..ff81775465 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -95,8 +95,25 @@ cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud) Vec6d bounds(cloud_source->GetOutput()->GetPoints()->GetBounds()); - WPaintedCloud cloud_widget(cloud, Vec3d(bounds[0], bounds[2], bounds[4]), Vec3d(bounds[1], bounds[3], bounds[5])); - *this = cloud_widget; + vtkSmartPointer elevation = vtkSmartPointer::New(); + elevation->SetInputConnection(cloud_source->GetOutputPort()); + elevation->SetLowPoint(bounds[0], bounds[2], bounds[4]); + elevation->SetHighPoint(bounds[1], bounds[3], bounds[5]); + elevation->SetScalarRange(0.0, 1.0); + elevation->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); + mapper->ImmediateModeRenderingOff(); + mapper->ScalarVisibilityOn(); + mapper->SetColorModeToMapScalars(); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); } cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2) @@ -329,7 +346,7 @@ cv::viz::WMesh::WMesh(const Mesh &mesh) CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1); vtkSmartPointer source = vtkSmartPointer::New(); - source->SetColorCloud(mesh.cloud, mesh.colors); + source->SetColorCloudNormalsTCoords(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords); source->Update(); Mat lookup_buffer(1, mesh.cloud.total(), CV_32SC1); @@ -394,6 +411,16 @@ cv::viz::WMesh::WMesh(const Mesh &mesh) actor->GetProperty()->ShadingOff(); actor->SetMapper(mapper); + if (!mesh.texture.empty()) + { + vtkSmartPointer image_source = vtkSmartPointer::New(); + image_source->SetImage(mesh.texture); + + vtkSmartPointer texture = vtkSmartPointer::New(); + texture->SetInputConnection(image_source->GetOutputPort()); + actor->SetTexture(texture); + } + WidgetAccessor::setProp(*this, actor); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index a553f8d721..ee74f2a123 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -205,6 +205,8 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray n return cloud; } +cv::viz::Mesh cv::viz::readMesh(const String& file) { return Mesh::load(file); } + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 7884f1a9a2..9a341b78ca 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -128,7 +128,34 @@ int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArr else if (normals.depth() == CV_64F && cloud.depth() == CV_64F) filterNanNormalsCopy(normals, cloud, total); else - CV_Assert(!"Unsupported normals type"); + CV_Assert(!"Unsupported normals/cloud type"); + + return total; +} + +int cv::viz::vtkCloudMatSource::SetColorCloudNormalsTCoords(InputArray _cloud, InputArray _colors, InputArray _normals, InputArray _tcoords) +{ + int total = SetColorCloudNormals(_cloud, _colors, _normals); + + if (_tcoords.empty()) + return total; + + CV_Assert(_tcoords.depth() == CV_32F || _tcoords.depth() == CV_64F); + CV_Assert(_tcoords.channels() == 2 && _tcoords.size() == _cloud.size()); + + Mat cloud = _cloud.getMat(); + Mat tcoords = _tcoords.getMat(); + + if (tcoords.depth() == CV_32F && cloud.depth() == CV_32F) + filterNanTCoordsCopy(tcoords, cloud, total); + else if (tcoords.depth() == CV_32F && cloud.depth() == CV_64F) + filterNanTCoordsCopy(tcoords, cloud, total); + else if (tcoords.depth() == CV_64F && cloud.depth() == CV_32F) + filterNanTCoordsCopy(tcoords, cloud, total); + else if (tcoords.depth() == CV_64F && cloud.depth() == CV_64F) + filterNanTCoordsCopy(tcoords, cloud, total); + else + CV_Assert(!"Unsupported tcoords/cloud type"); return total; } @@ -146,6 +173,9 @@ int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), if (normals) output->GetPointData()->SetNormals(normals); + if (tcoords) + output->GetPointData()->SetTCoords(tcoords); + return 1; } @@ -232,3 +262,25 @@ void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, normals->SetTuple(pos++, srow); } } + +template +void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total) +{ + typedef Vec<_Tn, 2> Vec2; + tcoords = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + tcoords->SetName("TextureCoordinates"); + tcoords->SetNumberOfComponents(2); + tcoords->SetNumberOfTuples(total); + + int pos = 0; + for (int y = 0; y < mask.rows; ++y) + { + const Vec2* srow = _tcoords.ptr(y); + const Vec2* send = srow + _tcoords.cols; + const _Msk* mrow = mask.ptr<_Msk>(y); + + for (; srow != send; ++srow, mrow += mask.channels()) + if (!isNan(mrow)) + tcoords->SetTuple(pos++, srow->val); + } +} diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index a7f9fff89a..56bd93e066 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -62,8 +62,9 @@ namespace cv vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm) virtual int SetCloud(InputArray cloud); - virtual int SetColorCloud(InputArray cloud, InputArray colors = noArray()); - virtual int SetColorCloudNormals(InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray()); + virtual int SetColorCloud(InputArray cloud, InputArray colors); + virtual int SetColorCloudNormals(InputArray cloud, InputArray colors, InputArray normals); + virtual int SetColorCloudNormalsTCoords(InputArray cloud, InputArray colors, InputArray normals, InputArray tcoords); protected: vtkCloudMatSource(); @@ -75,6 +76,7 @@ namespace cv vtkSmartPointer vertices; vtkSmartPointer scalars; vtkSmartPointer normals; + vtkSmartPointer tcoords; private: vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. void operator=(const vtkCloudMatSource&); // Not implemented. @@ -84,6 +86,9 @@ namespace cv template void filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total); + + template + void filterNanTCoordsCopy(const Mat& tcoords, const Mat& mask, int total); }; } } From e472d45d999bf3bcab5b5c7afe051d5854ef0d56 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 13 Jan 2014 13:30:34 +0400 Subject: [PATCH 79/91] updated mesh reading (texture support) --- modules/viz/include/opencv2/viz.hpp | 5 +- modules/viz/src/precomp.hpp | 1 + modules/viz/src/types.cpp | 118 ++++++++++-------------- modules/viz/src/vtk/vtkCloudMatSink.cpp | 25 ++++- modules/viz/src/vtk/vtkCloudMatSink.h | 4 +- 5 files changed, 76 insertions(+), 77 deletions(-) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 89810d5472..a532ba7831 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -99,9 +99,10 @@ namespace cv CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); /////////////////////////////////////////////////////////////////////////////////////////////// - /// Read mesh. Only ply format is supported now + /// Reads mesh. Only ply format is supported now. The function tries to read texture from png-file, + /// and in case of faulure, just leaves the texture field empty. - CV_EXPORTS Mesh readMesh (const String& file); + CV_EXPORTS Mesh readMesh(const String& file); /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index d5f969a495..bf154e76ed 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -122,6 +122,7 @@ #include #include #include +#include #include #include #include diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 09a2f4d0f3..bf61432cb6 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -57,80 +57,56 @@ cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, c //////////////////////////////////////////////////////////////////// /// cv::viz::Mesh3d -namespace cv { namespace viz { namespace +cv::viz::Mesh cv::viz::Mesh::load(const String& file) { - struct MeshUtils + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(file.c_str()); + reader->Update(); + + vtkSmartPointer polydata = reader->GetOutput(); + CV_Assert("File does not exist or file format is not supported." && polydata); + + Mesh mesh; + vtkSmartPointer sink = vtkSmartPointer::New(); + sink->SetOutput(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords); + sink->SetInputConnection(reader->GetOutputPort()); + sink->Write(); + + // Now handle the polygons + + vtkSmartPointer polygons = polydata->GetPolys(); + mesh.polygons.create(1, polygons->GetSize(), CV_32SC1); + int* poly_ptr = mesh.polygons.ptr(); + + polygons->InitTraversal(); + vtkIdType nr_cell_points, *cell_points; + while (polygons->GetNextCell(nr_cell_points, cell_points)) { - static Mesh loadMesh(const String &file) - { - Mesh mesh; - - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName(file.c_str()); - reader->Update(); - - vtkSmartPointer poly_data = reader->GetOutput(); - CV_Assert("File does not exist or file format is not supported." && poly_data); - - vtkSmartPointer mesh_points = poly_data->GetPoints(); - vtkIdType nr_points = mesh_points->GetNumberOfPoints(); - - mesh.cloud.create(1, nr_points, CV_32FC3); - - Vec3f *mesh_cloud = mesh.cloud.ptr(); - for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) - { - Vec3d point; - mesh_points->GetPoint(i, point.val); - mesh_cloud[i] = point; - } - - // Then the color information, if any - vtkUnsignedCharArray* poly_colors = 0; - if (poly_data->GetPointData()) - poly_colors = vtkUnsignedCharArray::SafeDownCast(poly_data->GetPointData()->GetScalars()); - - if (poly_colors && (poly_colors->GetNumberOfComponents() == 3)) - { - mesh.colors.create(1, nr_points, CV_8UC3); - Vec3b *mesh_colors = mesh.colors.ptr(); - - for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) - { - Vec3b point_color; - poly_colors->GetTupleValue(i, point_color.val); - - std::swap(point_color[0], point_color[2]); // RGB -> BGR - mesh_colors[i] = point_color; - } - } - else - mesh.colors.release(); - - // Now handle the polygons - vtkIdType* cell_points; - vtkIdType nr_cell_points; - vtkCellArray * mesh_polygons = poly_data->GetPolys(); - mesh_polygons->InitTraversal(); - - mesh.polygons.create(1, mesh_polygons->GetSize(), CV_32SC1); - - int* polygons = mesh.polygons.ptr(); - while (mesh_polygons->GetNextCell(nr_cell_points, cell_points)) - { - *polygons++ = nr_cell_points; - for (int i = 0; i < nr_cell_points; ++i) - *polygons++ = static_cast(cell_points[i]); - } - - return mesh; - } - }; -}}} + *poly_ptr++ = nr_cell_points; + for (vtkIdType i = 0; i < nr_cell_points; ++i) + *poly_ptr++ = (int)cell_points[i]; + } -cv::viz::Mesh cv::viz::Mesh::load(const String& file) -{ - return MeshUtils::loadMesh(file); + String::size_type pos = file.find_last_of('.'); + String png = (pos == String::npos) ? file : file.substr(0, pos+1) + "png"; + + vtkSmartPointer png_reader = vtkSmartPointer::New(); + + if (png_reader->CanReadFile(png.c_str())) + { + png_reader->SetFileName(png.c_str()); + png_reader->Update(); + vtkSmartPointer imagedata = png_reader->GetOutput(); + + Size sz(imagedata->GetDimensions()[0], imagedata->GetDimensions()[1]); + int channels = imagedata->GetNumberOfScalarComponents(); + CV_Assert(imagedata->GetScalarType() == VTK_UNSIGNED_CHAR); + + void *ptr = imagedata->GetScalarPointer(0,0,0); + Mat(sz, CV_8UC(channels), ptr).copyTo(mesh.texture); + } + + return mesh; } //////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp index cf1eb46482..09ef0cca99 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -52,11 +52,12 @@ namespace cv { namespace viz cv::viz::vtkCloudMatSink::vtkCloudMatSink() {} cv::viz::vtkCloudMatSink::~vtkCloudMatSink() {} -void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals) +void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals, OutputArray _tcoords) { cloud = _cloud; colors = _colors; normals = _normals; + tcoords = _tcoords; } void cv::viz::vtkCloudMatSink::WriteData() @@ -120,12 +121,32 @@ void cv::viz::vtkCloudMatSink::WriteData() Mat buffer(cloud.size(), CV_64FC(channels)); Vec3d *cptr = buffer.ptr(); for(size_t i = 0; i < buffer.total(); ++i) - *cptr++ = Vec3d(scalars_data->GetTuple(i)); + *cptr++ = Vec3d(normals_data->GetTuple(i)); buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F); } else normals.release(); + + vtkSmartPointer coords_data = input->GetPointData() ? input->GetPointData()->GetTCoords() : 0; + + if (tcoords.needed() && coords_data) + { + int vtktype = coords_data->GetDataType(); + + CV_Assert(vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE); + CV_Assert(cloud.total() == (size_t)coords_data->GetNumberOfTuples()); + + Mat buffer(cloud.size(), CV_64FC2); + Vec2d *cptr = buffer.ptr(); + for(size_t i = 0; i < buffer.total(); ++i) + *cptr++ = Vec2d(coords_data->GetTuple(i)); + + buffer.convertTo(tcoords, vtktype == VTK_FLOAT ? CV_32F : CV_64F); + + } + else + tcoords.release(); } void cv::viz::vtkCloudMatSink::PrintSelf(ostream& os, vtkIndent indent) diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index 69262f247a..3af9e6544a 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -59,7 +59,7 @@ namespace cv vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); - void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); + void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray(), OutputArray tcoords = noArray()); protected: vtkCloudMatSink(); @@ -67,7 +67,7 @@ namespace cv void WriteData(); - _OutputArray cloud, colors, normals; + _OutputArray cloud, colors, normals, tcoords; private: vtkCloudMatSink(const vtkCloudMatSink&); // Not implemented. From 8d327fa497123f2b2281bd0407253787be67bea1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 13 Jan 2014 22:42:49 +0400 Subject: [PATCH 80/91] updated for compatibility with VTK6.0 --- cmake/OpenCVDetectVTK.cmake | 4 ++-- modules/viz/src/clouds.cpp | 4 ++-- modules/viz/src/precomp.hpp | 28 +++++++++++++++++++++++++++- modules/viz/src/shapes.cpp | 24 ++++++++++++------------ modules/viz/src/widget.cpp | 1 + modules/viz/test/tests_simple.cpp | 2 +- 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/cmake/OpenCVDetectVTK.cmake b/cmake/OpenCVDetectVTK.cmake index f0d28d552a..ef9aa8043c 100644 --- a/cmake/OpenCVDetectVTK.cmake +++ b/cmake/OpenCVDetectVTK.cmake @@ -2,7 +2,7 @@ if(NOT WITH_VTK OR ANDROID OR IOS) return() endif() -find_package(VTK 6.0 QUIET COMPONENTS vtkRenderingCore vtkInteractionWidgets vtkInteractionStyle vtkIOLegacy vtkIOPLY vtkRenderingFreeType vtkRenderingLOD vtkFiltersTexture NO_MODULE) +find_package(VTK 6.0 QUIET COMPONENTS vtkRenderingCore vtkInteractionWidgets vtkInteractionStyle vtkIOLegacy vtkIOPLY vtkRenderingFreeType vtkRenderingLOD vtkFiltersTexture vtkIOExport NO_MODULE) if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) find_package(VTK 5.10 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) @@ -18,4 +18,4 @@ if(VTK_FOUND) else() set(HAVE_VTK OFF) message(STATUS "VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or set $VTK_DIR enviroment variable to VTK install subdirectory with VTKConfig.cmake file (for windows)") -endif() \ No newline at end of file +endif() diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index ff81775465..b8567dd66a 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -230,8 +230,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co CV_Assert("Cloud Widget without data" && currdata); vtkSmartPointer append_filter = vtkSmartPointer::New(); - append_filter->AddInputConnection(currdata->GetProducerPort()); - append_filter->AddInputConnection(polydata->GetProducerPort()); + VtkUtils::AddInputData(append_filter, currdata); + VtkUtils::AddInputData(append_filter, polydata); append_filter->Update(); VtkUtils::SetInputData(mapper, append_filter->GetOutput()); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index bf154e76ed..7440f1ee81 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -230,6 +230,25 @@ namespace cv filter->SetInputData(polydata); #endif } + template + static void SetSourceData(vtkSmartPointer filter, vtkPolyData* polydata) + { + #if VTK_MAJOR_VERSION <= 5 + filter->SetSource(polydata); + #else + filter->SetSourceData(polydata); + #endif + } + + template + static void SetInputData(vtkSmartPointer filter, vtkImageData* polydata) + { + #if VTK_MAJOR_VERSION <= 5 + filter->SetInput(polydata); + #else + filter->SetInputData(polydata); + #endif + } template static void AddInputData(vtkSmartPointer filter, vtkPolyData *polydata) @@ -285,7 +304,14 @@ namespace cv static vtkSmartPointer TransformPolydata(vtkSmartPointer polydata, const Affine3d& pose) { - return TransformPolydata(polydata->GetProducerPort(), pose); + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetMatrix(vtkmatrix(pose.matrix)); + + vtkSmartPointer transform_filter = vtkSmartPointer::New(); + VtkUtils::SetInputData(transform_filter, polydata); + transform_filter->SetTransform(transform); + transform_filter->Update(); + return transform_filter->GetOutput(); } }; } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 92ab3400be..323482fa4b 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -355,7 +355,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) polydata->GetPointData()->SetScalars(colors); vtkSmartPointer tube_filter = vtkSmartPointer::New(); - tube_filter->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(tube_filter, polydata); tube_filter->SetRadius(axes->GetScaleFactor() / 50.0); tube_filter->SetNumberOfSides(6); tube_filter->Update(); @@ -447,7 +447,7 @@ cv::viz::WGrid::WGrid(const Vec2i &cells, const Vec2d &cells_spacing, const Colo // Extract the edges so we have the grid vtkSmartPointer extract_edges = vtkSmartPointer::New(); - extract_edges->SetInputConnection(grid_data->GetProducerPort()); + VtkUtils::SetInputData(extract_edges, grid_data); extract_edges->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -854,13 +854,13 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, InputArray _image, d // Frustum needs to be textured or else it can't be combined with image vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(frustum->GetProducerPort()); + VtkUtils::SetInputData(frustum_texture, frustum); 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()); + VtkUtils::AddInputData(append_filter, plane); vtkSmartPointer actor = getActor(image_widget); actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort()); @@ -886,13 +886,13 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, InputArray _image, d // Frustum needs to be textured or else it can't be combined with image vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(frustum->GetProducerPort()); + VtkUtils::SetInputData(frustum_texture, frustum); 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()); + VtkUtils::AddInputData(append_filter, plane); vtkSmartPointer actor = getActor(image_widget); actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort()); @@ -917,7 +917,7 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca { Mat points = vtkTrajectorySource::ExtractPoints(_path); vtkSmartPointer polydata = getPolyData(WPolyLine(points, color)); - append_filter->AddInputConnection(polydata->GetProducerPort()); + VtkUtils::AddInputData(append_filter, polydata); } if (display_mode & WTrajectory::FRAMES) @@ -929,7 +929,7 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); - tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + VtkUtils::SetSourceData(tensor_glyph, glyph); tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues tensor_glyph->ThreeGlyphsOff(); tensor_glyph->SymmetricOff(); @@ -968,7 +968,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33 vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); - tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + VtkUtils::SetSourceData(tensor_glyph, glyph); tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues tensor_glyph->ThreeGlyphsOff(); tensor_glyph->SymmetricOff(); @@ -994,7 +994,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); - tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + VtkUtils::SetSourceData(tensor_glyph, glyph); tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues tensor_glyph->ThreeGlyphsOff(); tensor_glyph->SymmetricOff(); @@ -1046,7 +1046,7 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_le vtkSmartPointer polydata = sphere_source->GetOutput(); polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); - append_filter->AddInputConnection(polydata->GetProducerPort()); + VtkUtils::AddInputData(append_filter, polydata); if (i > 0) { @@ -1064,7 +1064,7 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_le line_source->Update(); vtkSmartPointer polydata = line_source->GetOutput(); polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); - append_filter->AddInputConnection(polydata->GetProducerPort()); + VtkUtils::AddInputData(append_filter, polydata); } } append_filter->Update(); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 6c1463b762..33b467ebc7 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -276,6 +276,7 @@ void cv::viz::Widget3D::applyTransform(const Affine3d &transform) vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); CV_Assert("Widget doesn't have a polydata mapper" && mapper); + mapper->Update(); VtkUtils::SetInputData(mapper, VtkUtils::TransformPolydata(mapper->GetInput(), transform)); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 3e25399b25..7f91c899b5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -113,7 +113,7 @@ TEST(Viz, show_painted_clouds) viz.setBackgroundMeshLab(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("cloud1", WPaintedCloud(cloud), Affine3d(Vec3d(0.0, -CV_PI/2, 0.0), Vec3d(-1.5, 0.0, 0.0))); - viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); + viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, -0.75, -1.0), Vec3d(0.0, 0.75, 0.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); viz.showWidget("cloud3", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), Color::blue(), Color::red())); viz.showWidget("arrow", WArrow(Vec3d(0.0, 1.0, -1.0), Vec3d(0.0, 1.0, 1.0), 0.009, Color::raspberry())); viz.spin(); From ffad7b699c0676a758233fe4e4fb9aaa5754eb18 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 14 Jan 2014 01:01:51 +0400 Subject: [PATCH 81/91] added test for textured mesh --- modules/viz/include/opencv2/viz.hpp | 3 +- modules/viz/include/opencv2/viz/types.hpp | 2 +- modules/viz/src/types.cpp | 20 ------------- modules/viz/test/test_viz3d.cpp | 15 ---------- modules/viz/test/tests_simple.cpp | 36 +++++++++++++++++++++++ 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index a532ba7831..bf44a2c039 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -99,8 +99,7 @@ namespace cv CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); /////////////////////////////////////////////////////////////////////////////////////////////// - /// Reads mesh. Only ply format is supported now. The function tries to read texture from png-file, - /// and in case of faulure, just leaves the texture field empty. + /// Reads mesh. Only ply format is supported now and no texture load support CV_EXPORTS Mesh readMesh(const String& file); diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index cdd89d3a0f..e61c837bec 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -115,7 +115,7 @@ namespace cv Mat texture, tcoords; - //! Loads mesh from a given ply file + //! Loads mesh from a given ply file (no texture load support for now) static Mesh load(const String& file); }; diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index bf61432cb6..2e32a63279 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -73,7 +73,6 @@ cv::viz::Mesh cv::viz::Mesh::load(const String& file) sink->Write(); // Now handle the polygons - vtkSmartPointer polygons = polydata->GetPolys(); mesh.polygons.create(1, polygons->GetSize(), CV_32SC1); int* poly_ptr = mesh.polygons.ptr(); @@ -87,25 +86,6 @@ cv::viz::Mesh cv::viz::Mesh::load(const String& file) *poly_ptr++ = (int)cell_points[i]; } - String::size_type pos = file.find_last_of('.'); - String png = (pos == String::npos) ? file : file.substr(0, pos+1) + "png"; - - vtkSmartPointer png_reader = vtkSmartPointer::New(); - - if (png_reader->CanReadFile(png.c_str())) - { - png_reader->SetFileName(png.c_str()); - png_reader->Update(); - vtkSmartPointer imagedata = png_reader->GetOutput(); - - Size sz(imagedata->GetDimensions()[0], imagedata->GetDimensions()[1]); - int channels = imagedata->GetNumberOfScalarComponents(); - CV_Assert(imagedata->GetScalarType() == VTK_UNSIGNED_CHAR); - - void *ptr = imagedata->GetScalarPointer(0,0,0); - Mat(sz, CV_8UC(channels), ptr).copyTo(mesh.texture); - } - return mesh; } diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 66ec25db81..bdfda6d9be 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -47,19 +47,11 @@ TEST(Viz_viz3d, develop) { cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); - //cv::viz::Mesh3d mesh = cv::viz::Mesh3d::load(get_dragon_ply_file_path()); - //theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); - cv::viz::Viz3d viz("abc"); viz.setBackgroundMeshLab(); viz.showWidget("coo", cv::viz::WCoordinateSystem(1)); - //viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0))); - //viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), cv::viz::Color::green(), cv::viz::Color::red())); viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud)); - //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); - //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); - //---->>>>> //std::vector gt, es; //cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); @@ -67,12 +59,5 @@ TEST(Viz_viz3d, develop) //cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); //---->>>>> - //theRNG().fill(colors, cv::RNG::UNIFORM, 0, 255); - //viz.showWidget("c", cv::viz::WCloud(cloud, colors)); - //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); - - //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); - //viz.showWidget("s", cv::viz::WSphere(Point3f(0,0,0), 1)); - //viz.showWidget("d", cv::viz::WCircle(Point3f(0,0,0), 1)); viz.spin(); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 7f91c899b5..ec475580e5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -145,6 +145,42 @@ TEST(Viz, show_mesh_random_colors) viz.spin(); } +TEST(Viz, show_textured_mesh) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + + std::vector points; + std::vector tcoords; + std::vector polygons; + for(size_t i = 0; i < 64; ++i) + { + double angle = CV_PI/2 * i/64.0; + points.push_back(Vec3d(0.00, cos(angle), sin(angle))*0.75); + points.push_back(Vec3d(1.57, cos(angle), sin(angle))*0.75); + tcoords.push_back(Vec2d(0.0, i/64.0)); + tcoords.push_back(Vec2d(1.0, i/64.0)); + } + + for(size_t i = 0; i < points.size()/2-1; ++i) + { + int polys[] = {3, 2*i, 2*i+1, 2*i+2, 3, 2*i+1, 2*i+2, 2*i+3}; + polygons.insert(polygons.end(), polys, polys + sizeof(polys)/sizeof(polys[0])); + } + + cv::viz::Mesh mesh; + mesh.cloud = Mat(points, true).reshape(3, 1); + mesh.tcoords = Mat(tcoords, true).reshape(2, 1); + mesh.polygons = Mat(polygons, true).reshape(1, 1); + mesh.texture = lena; + + Viz3d viz("show_textured_mesh"); + viz.setBackgroundMeshLab(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("mesh", WMesh(mesh)); + viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); + viz.spin(); +} + TEST(Viz, show_polyline) { Mat polyline(1, 32, CV_64FC3); From 57d5ad5131d400c349f5edf97cabb95ea3960b65 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 18 Jan 2014 17:19:17 +0400 Subject: [PATCH 82/91] minor iteractor refactoring --- modules/viz/src/interactor_style.cpp | 63 +++++++--------------------- 1 file changed, 16 insertions(+), 47 deletions(-) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index c2583f9363..42858f1057 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -275,7 +275,7 @@ void cv::viz::InteractorStyle::OnKeyDown() for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) { - vtkActor* apart = reinterpret_cast (path->GetLastNode()->GetViewProp()); + vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); apart->GetProperty()->SetRepresentationToPoints(); } break; @@ -328,7 +328,7 @@ void cv::viz::InteractorStyle::OnKeyDown() for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) { - vtkActor* apart = reinterpret_cast (path->GetLastNode()->GetViewProp()); + vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); float psize = apart->GetProperty()->GetPointSize(); if (psize < 63.0f) apart->GetProperty()->SetPointSize(psize + 1.0f); @@ -347,7 +347,7 @@ void cv::viz::InteractorStyle::OnKeyDown() for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) { - vtkActor* apart = static_cast(path->GetLastNode()->GetViewProp()); + vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); float psize = apart->GetProperty()->GetPointSize(); if (psize > 1.0f) apart->GetProperty()->SetPointSize(psize - 1.0f); @@ -386,13 +386,11 @@ void cv::viz::InteractorStyle::OnKeyDown() else { AnimState = VTKIS_ANIM_ON; - vtkAssemblyPath *path = NULL; Interactor->GetPicker()->Pick(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1], 0.0, CurrentRenderer); - vtkAbstractPropPicker *picker; - if ((picker = vtkAbstractPropPicker::SafeDownCast(Interactor->GetPicker()))) - path = picker->GetPath(); - if (path != NULL) - Interactor->FlyTo(CurrentRenderer, picker->GetPickPosition()); + vtkSmartPointer picker = vtkAbstractPropPicker::SafeDownCast(Interactor->GetPicker()); + if (picker) + if (picker->GetPath()) + Interactor->FlyTo(CurrentRenderer, picker->GetPickPosition()); AnimState = VTKIS_ANIM_OFF; } break; @@ -402,22 +400,14 @@ void cv::viz::InteractorStyle::OnKeyDown() { if (alt) { - int stereo_render = Interactor->GetRenderWindow()->GetStereoRender(); - if (!stereo_render) + vtkSmartPointer window = Interactor->GetRenderWindow(); + if (!window->GetStereoRender()) { - if (stereo_anaglyph_mask_default_) - { - Interactor->GetRenderWindow()->SetAnaglyphColorMask(4, 3); - stereo_anaglyph_mask_default_ = false; - } - else - { - Interactor->GetRenderWindow()->SetAnaglyphColorMask(2, 5); - stereo_anaglyph_mask_default_ = true; - } + static Vec2i default_mask(4, 3), alternative_mask(2, 5); + window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? default_mask.val : alternative_mask.val); + stereo_anaglyph_mask_default_ = !stereo_anaglyph_mask_default_; } - Interactor->GetRenderWindow()->SetStereoRender(!stereo_render); - Interactor->GetRenderWindow()->Render(); + window->SetStereoRender(!window->GetStereoRender()); Interactor->Render(); } else @@ -429,7 +419,6 @@ void cv::viz::InteractorStyle::OnKeyDown() { vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); cam->SetParallelProjection(!cam->GetParallelProjection()); - CurrentRenderer->SetActiveCamera(cam); CurrentRenderer->Render(); break; } @@ -443,27 +432,19 @@ void cv::viz::InteractorStyle::OnKeyDown() break; } - static WidgetActorMap::iterator it = widget_actor_map_->begin(); + WidgetActorMap::iterator it = widget_actor_map_->begin(); // it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault. - bool found_transformation = false; - - for (size_t idx = 0; idx < widget_actor_map_->size(); ++idx, ++it) + for (; it != widget_actor_map_->end(); ++it) { - if (it == widget_actor_map_->end()) - it = widget_actor_map_->begin(); - vtkProp3D * actor = vtkProp3D::SafeDownCast(it->second); if (actor && actor->GetUserMatrix()) - { - found_transformation = true; break; - } } vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); // if a valid transformation was found, use it otherwise fall back to default view point. - if (found_transformation) + if (it != widget_actor_map_->end()) { vtkMatrix4x4* m = vtkProp3D::SafeDownCast(it->second)->GetUserMatrix(); @@ -506,11 +487,8 @@ void cv::viz::InteractorStyle::OnKeyDown() } KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); - // Check if there is a keyboard callback registered if (keyboardCallback_) keyboardCallback_(event, keyboard_callback_cookie_); - - renderer_->Render(); Interactor->Render(); } @@ -518,10 +496,8 @@ void cv::viz::InteractorStyle::OnKeyDown() void cv::viz::InteractorStyle::OnKeyUp() { KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); - // Check if there is a keyboard callback registered if (keyboardCallback_) keyboardCallback_(event, keyboard_callback_cookie_); - Superclass::OnKeyUp(); } @@ -603,7 +579,6 @@ void cv::viz::InteractorStyle::OnMouseWheelForward() { Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers()); - // If a mouse callback registered, call it! if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetRepeatCount() && mouseCallback_) @@ -619,11 +594,9 @@ void cv::viz::InteractorStyle::OnMouseWheelForward() cam->SetViewAngle(opening_angle); cam->Modified(); - CurrentRenderer->SetActiveCamera(cam); CurrentRenderer->ResetCameraClippingRange(); CurrentRenderer->Modified(); CurrentRenderer->Render(); - renderer_->Render(); Interactor->Render(); } else @@ -635,7 +608,6 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() { Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers()); - // If a mouse callback registered, call it! if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); @@ -652,11 +624,9 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() cam->SetViewAngle(opening_angle); cam->Modified(); - CurrentRenderer->SetActiveCamera(cam); CurrentRenderer->ResetCameraClippingRange(); CurrentRenderer->Modified(); CurrentRenderer->Render(); - renderer_->Render(); Interactor->Render(); } else @@ -668,6 +638,5 @@ void cv::viz::InteractorStyle::OnTimer() { CV_Assert("Interactor style not initialized." && init_); CV_Assert("Renderer has not been set." && renderer_); - renderer_->Render(); Interactor->Render(); } From 16281027af498e3e63ed270cfde7b826480c6885 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 18 Jan 2014 21:43:10 +0400 Subject: [PATCH 83/91] resolved problem with multiple spin()/spinOnce() --- modules/viz/doc/viz3d.rst | 16 -- modules/viz/include/opencv2/viz/viz3d.hpp | 3 - modules/viz/src/interactor_style.cpp | 7 +- modules/viz/src/interactor_style.hpp | 2 - modules/viz/src/viz3d.cpp | 3 - modules/viz/src/vizimpl.cpp | 186 ++++++++++------------ modules/viz/src/vizimpl.hpp | 88 +++------- modules/viz/test/tests_simple.cpp | 21 +-- 8 files changed, 113 insertions(+), 213 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index ec5b16e718..5b361ad84e 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -134,8 +134,6 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar void setRenderingProperty(const String &id, int property, double value); double getRenderingProperty(const String &id, int property); - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); void setRepresentation(int representation); private: @@ -425,20 +423,6 @@ Returns rendering property of a widget. * **SHADING_GOURAUD** * **SHADING_PHONG** -viz::Viz3d::setDesiredUpdateRate --------------------------------- -Sets desired update rate of the window. - -.. ocv:function:: void setDesiredUpdateRate(double rate) - - :param rate: Desired update rate. The default is 30. - -viz::Viz3d::getDesiredUpdateRate --------------------------------- -Returns desired update rate of the window. - -.. ocv:function:: double getDesiredUpdateRate() - viz::Viz3d::setRepresentation ----------------------------- Sets geometry representation of the widgets to surface, wireframe or points. diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index b9712ef3e4..090c8b14e5 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -113,9 +113,6 @@ namespace cv void setRenderingProperty(const String &id, int property, double value); double getRenderingProperty(const String &id, int property); - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); - void setRepresentation(int representation); private: diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 42858f1057..75003a2b66 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -220,8 +220,6 @@ int cv::viz::InteractorStyle::getModifiers() void cv::viz::InteractorStyle::OnKeyDown() { CV_Assert("Interactor style not initialized. Please call Initialize() before continuing" && init_); - CV_Assert("No renderer given! Use SetRendererCollection() before continuing." && renderer_); - FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); // Save the initial windows width/height @@ -403,8 +401,8 @@ void cv::viz::InteractorStyle::OnKeyDown() vtkSmartPointer window = Interactor->GetRenderWindow(); if (!window->GetStereoRender()) { - static Vec2i default_mask(4, 3), alternative_mask(2, 5); - window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? default_mask.val : alternative_mask.val); + static Vec2i red_blue(4, 3), magenta_green(2, 5); + window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? red_blue.val : magenta_green.val); stereo_anaglyph_mask_default_ = !stereo_anaglyph_mask_default_; } window->SetStereoRender(!window->GetStereoRender()); @@ -637,6 +635,5 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() void cv::viz::InteractorStyle::OnTimer() { CV_Assert("Interactor style not initialized." && init_); - CV_Assert("Renderer has not been set." && renderer_); Interactor->Render(); } diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 583860911a..8d01697a87 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -63,7 +63,6 @@ namespace cv virtual void Initialize(); void setWidgetActorMap(const Ptr& actors) { widget_actor_map_ = actors; } - void setRenderer(vtkSmartPointer& renderer) { renderer_ = renderer; } void registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); @@ -73,7 +72,6 @@ namespace cv /** \brief Set to true after initialization is complete. */ bool init_; - vtkSmartPointer renderer_; Ptr widget_actor_map_; Vec2i win_size_; diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 503359f013..237ef87c9d 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -145,7 +145,4 @@ void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } void cv::viz::Viz3d::setRenderingProperty(const String &id, int property, double value) { getWidget(id).setRenderingProperty(property, value); } double cv::viz::Viz3d::getRenderingProperty(const String &id, int property) { return getWidget(id).getRenderingProperty(property); } -void cv::viz::Viz3d::setDesiredUpdateRate(double rate) { impl_->setDesiredUpdateRate(rate); } -double cv::viz::Viz3d::getDesiredUpdateRate() { return impl_->getDesiredUpdateRate(); } - void cv::viz::Viz3d::setRepresentation(int representation) { impl_->setRepresentation(representation); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 61a0a01f62..e66b53823c 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -46,25 +46,17 @@ #include "precomp.hpp" ///////////////////////////////////////////////////////////////////////////////////////////// -cv::viz::Viz3d::VizImpl::VizImpl(const String &name) - : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) +cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); + + // Create render window window_ = vtkSmartPointer::New(); + window_name_ = VizStorage::generateWindowName(name); - // Set the window size as 1/2 of the screen size cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); window_->AddRenderer(renderer_); - - // Create the interactor style - style_->Initialize(); - style_->setRenderer(renderer_); - style_->setWidgetActorMap(widget_actor_map_); - style_->UseTimersOn(); - - interactor_ = vtkSmartPointer::New(); - window_->AlphaBitPlanesOff(); window_->PointSmoothingOff(); window_->LineSmoothingOff(); @@ -72,37 +64,89 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) window_->SwapBuffersOn(); window_->SetStereoTypeToAnaglyph(); - interactor_->SetRenderWindow(window_); - interactor_->SetInteractorStyle(style_); - interactor_->SetDesiredUpdateRate(24.0); + // Create the interactor style + style_ = vtkSmartPointer::New(); + style_->setWidgetActorMap(widget_actor_map_); + style_->UseTimersOn(); + style_->Initialize(); - // Initialize and create timer, also create window - interactor_->Initialize(); - timer_id_ = interactor_->CreateRepeatingTimer(5000L); + timer_callback_ = vtkSmartPointer::New(); + exit_callback_ = vtkSmartPointer::New(); + exit_callback_->viz = this; +} - exit_main_loop_timer_callback_ = vtkSmartPointer::New(); - exit_main_loop_timer_callback_->viz_ = this; - exit_main_loop_timer_callback_->right_timer_id = -1; - interactor_->AddObserver(vtkCommand::TimerEvent, exit_main_loop_timer_callback_); +///////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::TimerCallback::Execute(vtkObject* caller, unsigned long event_id, void* cookie) +{ + if (event_id == vtkCommand::TimerEvent && timer_id == *reinterpret_cast(cookie)) + { + vtkSmartPointer interactor = vtkRenderWindowInteractor::SafeDownCast(caller); + interactor->TerminateApp(); + } +} - exit_callback_ = vtkSmartPointer::New(); - exit_callback_->viz_ = this; - interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_); +void cv::viz::Viz3d::VizImpl::ExitCallback::Execute(vtkObject*, unsigned long event_id, void*) +{ + if (event_id == vtkCommand::ExitEvent) + { + viz->interactor_->TerminateApp(); + viz->interactor_ = 0; + } +} - resetStoppedFlag(); +///////////////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////// - String window_name = VizStorage::generateWindowName(name); - window_->SetWindowName(window_name.c_str()); +bool cv::viz::Viz3d::VizImpl::wasStopped() const +{ + bool stopped = spin_once_state_ ? interactor_ == 0 : false; + spin_once_state_ &= !stopped; + return stopped; +} + +void cv::viz::Viz3d::VizImpl::close() +{ + if (!interactor_) + return; + interactor_->GetRenderWindow()->Finalize(); + interactor_->TerminateApp(); // This tends to close the window... } ///////////////////////////////////////////////////////////////////////////////////////////// -cv::viz::Viz3d::VizImpl::~VizImpl() +void cv::viz::Viz3d::VizImpl::spin() { - if (interactor_) - interactor_->DestroyTimer(timer_id_); - if (renderer_) - renderer_->Clear(); + interactor_ = vtkSmartPointer::New(); + interactor_->SetRenderWindow(window_); + interactor_->SetInteractorStyle(style_); + window_->Render(); + window_->SetWindowName(window_name_.c_str()); + interactor_->Start(); + interactor_ = 0; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) +{ + if (interactor_ == 0) + { + spin_once_state_ = true; + interactor_ = vtkSmartPointer::New(); + interactor_->SetRenderWindow(window_); + interactor_->SetInteractorStyle(style_); + interactor_->AddObserver(vtkCommand::TimerEvent, timer_callback_); + interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_); + window_->Render(); + window_->SetWindowName(window_name_.c_str()); + } + + vtkSmartPointer local = interactor_; + + if (force_redraw) + local->Render(); + + timer_callback_->timer_id = local->CreateOneShotTimer(std::max(1, time)); + local->Start(); + local->DestroyTimer(timer_callback_->timer_id); + } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -208,19 +252,6 @@ cv::Affine3d cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const return Affine3d(*actor->GetUserMatrix()->Element); } -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setDesiredUpdateRate(double rate) -{ - if (interactor_) - interactor_->SetDesiredUpdateRate(rate); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -double cv::viz::Viz3d::VizImpl::getDesiredUpdateRate() -{ - return interactor_ ? interactor_->GetDesiredUpdateRate() : 0.0; -} - ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::saveScreenshot(const String &file) { style_->saveScreenshot(file.c_str()); } @@ -231,37 +262,6 @@ void cv::viz::Viz3d::VizImpl::registerMouseCallback(MouseCallback callback, void void cv::viz::Viz3d::VizImpl::registerKeyboardCallback(KeyboardCallback callback, void* cookie) { style_->registerKeyboardCallback(callback, cookie); } -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::spin() -{ - resetStoppedFlag(); - window_->Render(); - interactor_->Start(); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) -{ - resetStoppedFlag(); - - if (time <= 0) - time = 1; - - if (force_redraw) - interactor_->Render(); - - double s_now_ = cv::getTickCount() / cv::getTickFrequency(); - if (s_lastDone_ > s_now_) - s_lastDone_ = s_now_; - - if ((s_now_ - s_lastDone_) > (1.0 / interactor_->GetDesiredUpdateRate())) - { - exit_main_loop_timer_callback_->right_timer_id = interactor_->CreateRepeatingTimer(time); - interactor_->Start(); - interactor_->DestroyTimer(exit_main_loop_timer_callback_->right_timer_id); - s_lastDone_ = s_now_; - } -} ////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::removeAllWidgets() @@ -282,18 +282,15 @@ void cv::viz::Viz3d::VizImpl::showImage(InputArray image, const Size& window_siz ///////////////////////////////////////////////////////////////////////////////////////////// bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer actor) { - vtkProp* actor_to_remove = vtkProp::SafeDownCast(actor); - vtkPropCollection* actors = renderer_->GetViewProps(); actors->InitTraversal(); vtkProp* current_actor = NULL; while ((current_actor = actors->GetNextProp()) != NULL) - { - if (current_actor != actor_to_remove) - continue; - renderer_->RemoveActor(actor); - return true; - } + if (current_actor == actor) + { + renderer_->RemoveActor(actor); + return true; + } return false; } @@ -313,11 +310,8 @@ void cv::viz::Viz3d::VizImpl::setBackgroundGradient(const Color& up, const Colo renderer_->GradientBackgroundOn(); } -////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() -{ - setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); -} +{ setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); } ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) @@ -512,14 +506,8 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation) } ////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) -{ - if (window_) - window_->SetFullScreen(mode); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_ ? window_->GetWindowName() : ""; } +cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_name_; } +void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) { window_->SetFullScreen(mode); } void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } -cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); } +cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(Point(Vec2i(window_->GetSize()))); } diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 11b8490a1f..1b9abea64d 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -55,7 +55,13 @@ public: int ref_counter; VizImpl(const String &name); - virtual ~VizImpl(); + virtual ~VizImpl() {}; + + bool wasStopped() const; + void close(); + + void spin(); + void spinOnce(int time = 1, bool force_redraw = false); void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); @@ -68,26 +74,6 @@ public: void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); - - /** \brief Returns true when the user tried to close the window */ - bool wasStopped() const { return interactor_ ? stopped_ : true; } - - /** \brief Set the stopped flag back to false */ - void resetStoppedFlag() { if (interactor_) stopped_ = false; } - - /** \brief Stop the interaction and close the visualizaton window. */ - void close() - { - stopped_ = true; - if (interactor_) - { - interactor_->GetRenderWindow()->Finalize(); - interactor_->TerminateApp(); // This tends to close the window... - } - } - void setRepresentation(int representation); void setCamera(const Camera &camera); @@ -114,72 +100,36 @@ public: void setBackgroundTexture(InputArray image); void setBackgroundMeshLab(); - void spin(); - void spinOnce(int time = 1, bool force_redraw = false); - void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); void registerMouseCallback(MouseCallback callback, void* cookie = 0); private: - vtkSmartPointer interactor_; - - struct ExitMainLoopTimerCallback : public vtkCommand + struct TimerCallback : public vtkCommand { - static ExitMainLoopTimerCallback* New() { return new ExitMainLoopTimerCallback; } - virtual void Execute(vtkObject* vtkNotUsed(caller), unsigned long event_id, void* call_data) - { - if (event_id != vtkCommand::TimerEvent) - return; - - int timer_id = *reinterpret_cast(call_data); - if (timer_id != right_timer_id) - return; - - // Stop vtk loop and send notification to app to wake it up - viz_->interactor_->TerminateApp(); - } - int right_timer_id; - VizImpl* viz_; + static TimerCallback* New() { return new TimerCallback; } + virtual void Execute(vtkObject* caller, unsigned long event_id, void* cookie); + int timer_id; }; struct ExitCallback : public vtkCommand { static ExitCallback* New() { return new ExitCallback; } - virtual void Execute(vtkObject*, unsigned long event_id, void*) - { - if (event_id == vtkCommand::ExitEvent) - { - viz_->stopped_ = true; - viz_->interactor_->GetRenderWindow()->Finalize(); - viz_->interactor_->TerminateApp(); - } - } - VizImpl* viz_; + virtual void Execute(vtkObject*, unsigned long event_id, void*); + VizImpl* viz; }; - /** \brief Set to false if the interaction loop is running. */ - bool stopped_; - - double s_lastDone_; + mutable bool spin_once_state_; + vtkSmartPointer interactor_; - /** \brief Global timer ID. Used in destructor only. */ - int timer_id_; + vtkSmartPointer window_; + String window_name_; - /** \brief Callback object enabling us to leave the main loop, when a timer fires. */ - vtkSmartPointer exit_main_loop_timer_callback_; + vtkSmartPointer timer_callback_; vtkSmartPointer exit_callback_; vtkSmartPointer renderer_; - vtkSmartPointer window_; - - /** \brief The render window interactor style. */ vtkSmartPointer style_; - - /** \brief Internal list with actor pointers and name IDs for all widget actors */ - cv::Ptr widget_actor_map_; - - /** \brief Boolean that holds whether or not the camera parameters were manually initialized*/ - bool camera_set_; + Ptr widget_actor_map_; bool removeActorFromRenderer(vtkSmartPointer actor); }; diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ec475580e5..dad4aacca5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -236,7 +236,7 @@ TEST(Viz, show_trajectories) viz.setViewerPose(makeCameraPose(pose * 7.5, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); viz.spinOnce(20, true); } - //viz.spin(); + viz.spin(); } TEST(Viz, show_trajectory_reposition) @@ -299,7 +299,7 @@ TEST(Viz, show_overlay_image) viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } - //viz.spin(); + viz.spin(); } @@ -338,7 +338,7 @@ TEST(Viz, show_image_3d) viz.getWidget("img0").cast().setImage(lena * pow(sin(i++*7.5*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } - //viz.spin(); + viz.spin(); } TEST(Viz, show_simple_widgets) @@ -365,7 +365,7 @@ TEST(Viz, show_simple_widgets) viz.showWidget("grid1", WGrid(Vec2i(7,7), Vec2d::all(0.75), Color::gray()), Affine3d().translate(Vec3d(0.0, 0.0, -1.0))); - viz.spinOnce(1500, true); + viz.spin(); viz.getWidget("text2d").cast().setText("New simple text"); viz.getWidget("text3d").cast().setText("Updated text 3D"); viz.spin(); @@ -379,18 +379,7 @@ TEST(Viz, show_follower) viz.showWidget("cube", WCube()); viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); viz.setBackgroundMeshLab(); - viz.spinOnce(1500, true); - viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); - viz.spin(); -} - -TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) -{ - Mesh mesh = Mesh::load(get_dragon_ply_file_path()); - - Viz3d viz("spin_twice"); - viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("mesh", WMesh(mesh)); viz.spin(); + viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); viz.spin(); } From d7ca0bb757c38d4f54f5c8e565f211fdaa7dab66 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 18 Jan 2014 22:25:40 +0400 Subject: [PATCH 84/91] merged background color with background gradient methods, updated tests to show description of scene --- modules/viz/include/opencv2/viz/types.hpp | 4 +++ modules/viz/include/opencv2/viz/viz3d.hpp | 3 +-- modules/viz/src/shapes.cpp | 6 +++-- modules/viz/src/viz3d.cpp | 3 +-- modules/viz/src/vizimpl.cpp | 30 ++++++++++++----------- modules/viz/src/vizimpl.hpp | 3 +-- modules/viz/test/test_viz3d.cpp | 3 ++- modules/viz/test/tests_simple.cpp | 25 ++++++++++++++++--- 8 files changed, 51 insertions(+), 26 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index e61c837bec..3c3571b83c 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -102,6 +102,8 @@ namespace cv static Color turquoise(); static Color celestial_blue(); static Color amethyst(); + + static Color not_set(); }; class CV_EXPORTS Mesh @@ -229,4 +231,6 @@ inline cv::viz::Color cv::viz::Color::turquoise() { return Color(208, 224, inline cv::viz::Color cv::viz::Color::celestial_blue() { return Color(208, 151, 73); } inline cv::viz::Color cv::viz::Color::amethyst() { return Color(204, 102, 153); } +inline cv::viz::Color cv::viz::Color::not_set() { return Color(-1, -1, -1); } + #endif diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 090c8b14e5..a83d8e8fc3 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -98,9 +98,8 @@ namespace cv void saveScreenshot(const String &file); void setWindowPosition(const Point& window_position); void setFullScreen(bool mode = true); - void setBackgroundColor(const Color& color = Color::black()); + void setBackgroundColor(const Color& color = Color::black(), const Color& color2 = Color::not_set()); void setBackgroundTexture(InputArray image = noArray()); - void setBackgroundGradient(const Color& up, const Color& down); void setBackgroundMeshLab(); void spin(); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 323482fa4b..9011d0b18a 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -549,12 +549,14 @@ template<> cv::viz::WText3D cv::viz::Widget::cast() cv::viz::WText::WText(const String &text, const Point &pos, int font_size, const Color &color) { vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetPosition(pos.x, pos.y); + actor->SetDisplayPosition(pos.x, pos.y); actor->SetInput(text.c_str()); + actor->GetProperty()->SetDisplayLocationToForeground(); + vtkSmartPointer tprop = actor->GetTextProperty(); tprop->SetFontSize(font_size); - tprop->SetFontFamilyToArial(); + tprop->SetFontFamilyToCourier(); tprop->SetJustificationToLeft(); tprop->BoldOn(); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 237ef87c9d..2d4aefc0bb 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -136,8 +136,7 @@ cv::String cv::viz::Viz3d::getWindowName() const { return impl_->getWindowName() void cv::viz::Viz3d::saveScreenshot(const String &file) { impl_->saveScreenshot(file); } void cv::viz::Viz3d::setWindowPosition(const Point& window_position) { impl_->setWindowPosition(window_position); } void cv::viz::Viz3d::setFullScreen(bool mode) { impl_->setFullScreen(mode); } -void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } -void cv::viz::Viz3d::setBackgroundGradient(const Color& up, const Color& down) { impl_->setBackgroundGradient(up, down); } +void cv::viz::Viz3d::setBackgroundColor(const Color& color, const Color& color2) { impl_->setBackgroundColor(color, color2); } void cv::viz::Viz3d::setBackgroundTexture(InputArray image) { impl_->setBackgroundTexture(image); } void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index e66b53823c..e50666ec8c 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -143,10 +143,9 @@ void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) if (force_redraw) local->Render(); - timer_callback_->timer_id = local->CreateOneShotTimer(std::max(1, time)); + timer_callback_->timer_id = local->CreateRepeatingTimer(std::max(1, time)); local->Start(); local->DestroyTimer(timer_callback_->timer_id); - } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -295,23 +294,26 @@ bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer a } ////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) +void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color, const Color& color2) { - Color c = vtkcolor(color); - renderer_->SetBackground(c.val); - renderer_->GradientBackgroundOff(); -} + Color c = vtkcolor(color), c2 = vtkcolor(color2); + bool gradient = color2[0] >= 0 && color2[1] >= 0 && color2[2] >= 0; -void cv::viz::Viz3d::VizImpl::setBackgroundGradient(const Color& up, const Color& down) -{ - Color vtkup = vtkcolor(up), vtkdown = vtkcolor(down); - renderer_->SetBackground(vtkdown.val); - renderer_->SetBackground2(vtkup.val); - renderer_->GradientBackgroundOn(); + if (gradient) + { + renderer_->SetBackground(c2.val); + renderer_->SetBackground2(c.val); + renderer_->GradientBackgroundOn(); + } + else + { + renderer_->SetBackground(c.val); + renderer_->GradientBackgroundOff(); + } } void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() -{ setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); } +{ setBackgroundColor(Color(2, 1, 1), Color(240, 120, 120)); } ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 1b9abea64d..11e22ee5d1 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -95,8 +95,7 @@ public: void setWindowSize(const Size& window_size); void setFullScreen(bool mode); String getWindowName() const; - void setBackgroundColor(const Color& color); - void setBackgroundGradient(const Color& up, const Color& down); + void setBackgroundColor(const Color& color, const Color& color2); void setBackgroundTexture(InputArray image); void setBackgroundMeshLab(); diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index bdfda6d9be..45d3cdc3cf 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -43,7 +43,7 @@ using namespace cv; -TEST(Viz_viz3d, develop) +TEST(Viz_viz3d, DISABLED_develop) { cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); @@ -59,5 +59,6 @@ TEST(Viz_viz3d, develop) //cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); //---->>>>> + viz.spin(); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index dad4aacca5..46f0e59b53 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -54,6 +54,8 @@ TEST(Viz, show_cloud_bluberry) Viz3d viz("show_cloud_bluberry"); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry()), pose); + + viz.showWidget("text2d", WText("Bluberry cloud", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -70,6 +72,7 @@ TEST(Viz, show_cloud_random_color) viz.setBackgroundMeshLab(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, colors), pose); + viz.showWidget("text2d", WText("Random color cloud", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -87,6 +90,7 @@ TEST(Viz, show_cloud_masked) Viz3d viz("show_cloud_masked"); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud), pose); + viz.showWidget("text2d", WText("Nan masked cloud", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -100,8 +104,10 @@ TEST(Viz, show_cloud_collection) ccol.addCloud(cloud, Color::red(), Affine3d().translate(Vec3d(2, 0, 0))); Viz3d viz("show_cloud_collection"); + viz.setBackgroundColor(Color::mlab()); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("ccol", ccol); + viz.showWidget("text2d", WText("Cloud collection", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -116,6 +122,7 @@ TEST(Viz, show_painted_clouds) viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, -0.75, -1.0), Vec3d(0.0, 0.75, 0.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); viz.showWidget("cloud3", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), Color::blue(), Color::red())); viz.showWidget("arrow", WArrow(Vec3d(0.0, 1.0, -1.0), Vec3d(0.0, 1.0, 1.0), 0.009, Color::raspberry())); + viz.showWidget("text2d", WText("Painted clouds", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -128,6 +135,7 @@ TEST(Viz, show_mesh) Viz3d viz("show_mesh"); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("mesh", WMesh(mesh), pose); + viz.showWidget("text2d", WText("Just mesh", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -142,6 +150,7 @@ TEST(Viz, show_mesh_random_colors) viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("mesh", WMesh(mesh), pose); viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); + viz.showWidget("text2d", WText("Random color mesh", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -178,6 +187,7 @@ TEST(Viz, show_textured_mesh) viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("mesh", WMesh(mesh)); viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); + viz.showWidget("text2d", WText("Textured mesh", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -190,6 +200,7 @@ TEST(Viz, show_polyline) Viz3d viz("show_polyline"); viz.showWidget("polyline", WPolyLine(Mat(polyline), Color::apricot())); viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("text2d", WText("Polyline", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -204,6 +215,7 @@ TEST(Viz, show_sampled_normals) viz.showWidget("mesh", WMesh(mesh), pose); viz.showWidget("normals", WCloudNormals(mesh.cloud, mesh.normals, 30, 0.1f, Color::green()), pose); viz.setRenderingProperty("normals", LINE_WIDTH, 2.0); + viz.showWidget("text2d", WText("Cloud or mesh normals", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -227,6 +239,7 @@ TEST(Viz, show_trajectories) viz.showWidget("sub3", WTrajectory(sub3, WTrajectory::BOTH, 0.2, Color::green())); viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3, Color::yellow())); viz.showWidget("sub5", WTrajectoryFrustums(sub5, Vec2d(0.78, 0.78), 0.15)); + viz.showWidget("text2d", WText("Different kinds of supported trajectories", Point(20, 20), 20, Color::green())); int i = 0; while(!viz.wasStopped()) @@ -236,6 +249,7 @@ TEST(Viz, show_trajectories) viz.setViewerPose(makeCameraPose(pose * 7.5, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); viz.spinOnce(20, true); } + viz.resetCamera(); viz.spin(); } @@ -246,6 +260,7 @@ TEST(Viz, show_trajectory_reposition) Viz3d viz("show_trajectory_reposition_to_origin"); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("sub3", WTrajectory(Mat(path).rowRange(0, path.size()/3), WTrajectory::BOTH, 0.2, Color::brown()), path.front().inv()); + viz.showWidget("text2d", WText("Trajectory resposition to origin", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -269,6 +284,7 @@ TEST(Viz, show_camera_positions) viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); viz.showWidget("pos3", WCameraPosition(0.75), poses[1]); viz.showWidget("pos4", WCameraPosition(K, gray, 3, Color::indigo()), poses[1]); + viz.showWidget("text2d", WText("Camera positions with images", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -289,6 +305,7 @@ TEST(Viz, show_overlay_image) viz.showWidget("img2", WImageOverlay(gray, Rect(Point(vsz.width-10-lena.cols/2, 10), half_lsize))); viz.showWidget("img3", WImageOverlay(gray, Rect(Point(10, vsz.height-10-lena.rows/2), half_lsize))); viz.showWidget("img5", WImageOverlay(lena, Rect(Point(vsz.width-10-lena.cols/2, vsz.height-10-lena.rows/2), half_lsize))); + viz.showWidget("text2d", WText("Overlay images", Point(20, 20), 20, Color::green())); int i = 0; while(!viz.wasStopped()) @@ -299,7 +316,6 @@ TEST(Viz, show_overlay_image) viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } - viz.spin(); } @@ -332,6 +348,8 @@ TEST(Viz, show_image_3d) viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + viz.showWidget("text2d", WText("Images in 3D", Point(20, 20), 20, Color::green())); + int i = 0; while(!viz.wasStopped()) { @@ -357,7 +375,7 @@ TEST(Viz, show_simple_widgets) viz.showWidget("con0", WCone(0.25, 0.125, 6, Color::azure())); viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); - viz.showWidget("text2d", WText("Simple text", Point(20, 20), 20, Color::green())); + viz.showWidget("text2d", WText("Different simple widgets", Point(20, 20), 20, Color::green())); viz.showWidget("text3d", WText3D("Simple 3D text", Point3d( 0.5, 0.5, 0.5), 0.125, false, Color::green())); viz.showWidget("plane1", WPlane(Size2d(0.25, 0.75))); @@ -366,7 +384,7 @@ TEST(Viz, show_simple_widgets) viz.showWidget("grid1", WGrid(Vec2i(7,7), Vec2d::all(0.75), Color::gray()), Affine3d().translate(Vec3d(0.0, 0.0, -1.0))); viz.spin(); - viz.getWidget("text2d").cast().setText("New simple text"); + viz.getWidget("text2d").cast().setText("Different simple widgets (updated)"); viz.getWidget("text3d").cast().setText("Updated text 3D"); viz.spin(); } @@ -378,6 +396,7 @@ TEST(Viz, show_follower) viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); + viz.showWidget("text2d", WText("Follower: text always facing camera", Point(20, 20), 20, Color::green())); viz.setBackgroundMeshLab(); viz.spin(); viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); From 7410593d55d09524cff5e9cd6584fa68a95a2996 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 00:13:47 +0400 Subject: [PATCH 85/91] fixed warnigns and compiler errors for Ubuntu --- modules/viz/src/clouds.cpp | 4 +- modules/viz/src/shapes.cpp | 6 +-- modules/viz/src/vtk/vtkCloudMatSource.cpp | 48 +++++++++++------------ modules/viz/src/vtk/vtkImageMatSource.cpp | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index b8567dd66a..4b84e8e9e1 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -219,7 +219,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co mapper->ImmediateModeRenderingOff(); VtkUtils::SetInputData(mapper, polydata); - actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); + actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); actor->SetMapper(mapper); @@ -236,7 +236,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co VtkUtils::SetInputData(mapper, append_filter->GetOutput()); - actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); + actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); } void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, const Affine3d &pose) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 9011d0b18a..cc3a51ce44 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1064,9 +1064,9 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_le line_source->SetPoint1(curr.val); line_source->SetPoint2(lend.val); line_source->Update(); - vtkSmartPointer polydata = line_source->GetOutput(); - polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); - VtkUtils::AddInputData(append_filter, polydata); + vtkSmartPointer polydata_ = line_source->GetOutput(); + polydata_->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata_->GetNumberOfCells(), c)); + VtkUtils::AddInputData(append_filter, polydata_); } } append_filter->Update(); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 9a341b78ca..e950a0d638 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -116,17 +116,17 @@ int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArr CV_Assert(_normals.channels() == 3 || _normals.channels() == 4); CV_Assert(_normals.size() == _cloud.size()); - Mat cloud = _cloud.getMat(); - Mat normals = _normals.getMat(); - - if (normals.depth() == CV_32F && cloud.depth() == CV_32F) - filterNanNormalsCopy(normals, cloud, total); - else if (normals.depth() == CV_32F && cloud.depth() == CV_64F) - filterNanNormalsCopy(normals, cloud, total); - else if (normals.depth() == CV_64F && cloud.depth() == CV_32F) - filterNanNormalsCopy(normals, cloud, total); - else if (normals.depth() == CV_64F && cloud.depth() == CV_64F) - filterNanNormalsCopy(normals, cloud, total); + Mat c = _cloud.getMat(); + Mat n = _normals.getMat(); + + if (n.depth() == CV_32F && c.depth() == CV_32F) + filterNanNormalsCopy(n, c, total); + else if (n.depth() == CV_32F && c.depth() == CV_64F) + filterNanNormalsCopy(n, c, total); + else if (n.depth() == CV_64F && c.depth() == CV_32F) + filterNanNormalsCopy(n, c, total); + else if (n.depth() == CV_64F && c.depth() == CV_64F) + filterNanNormalsCopy(n, c, total); else CV_Assert(!"Unsupported normals/cloud type"); @@ -143,17 +143,17 @@ int cv::viz::vtkCloudMatSource::SetColorCloudNormalsTCoords(InputArray _cloud, I CV_Assert(_tcoords.depth() == CV_32F || _tcoords.depth() == CV_64F); CV_Assert(_tcoords.channels() == 2 && _tcoords.size() == _cloud.size()); - Mat cloud = _cloud.getMat(); - Mat tcoords = _tcoords.getMat(); - - if (tcoords.depth() == CV_32F && cloud.depth() == CV_32F) - filterNanTCoordsCopy(tcoords, cloud, total); - else if (tcoords.depth() == CV_32F && cloud.depth() == CV_64F) - filterNanTCoordsCopy(tcoords, cloud, total); - else if (tcoords.depth() == CV_64F && cloud.depth() == CV_32F) - filterNanTCoordsCopy(tcoords, cloud, total); - else if (tcoords.depth() == CV_64F && cloud.depth() == CV_64F) - filterNanTCoordsCopy(tcoords, cloud, total); + Mat cl = _cloud.getMat(); + Mat tc = _tcoords.getMat(); + + if (tc.depth() == CV_32F && cl.depth() == CV_32F) + filterNanTCoordsCopy(tc, cl, total); + else if (tc.depth() == CV_32F && cl.depth() == CV_64F) + filterNanTCoordsCopy(tc, cl, total); + else if (tc.depth() == CV_64F && cl.depth() == CV_32F) + filterNanTCoordsCopy(tc, cl, total); + else if (tc.depth() == CV_64F && cl.depth() == CV_64F) + filterNanTCoordsCopy(tc, cl, total); else CV_Assert(!"Unsupported tcoords/cloud type"); @@ -241,7 +241,7 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, co template void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total) { - normals = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + normals = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New(); normals->SetName("Normals"); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(total); @@ -267,7 +267,7 @@ template void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total) { typedef Vec<_Tn, 2> Vec2; - tcoords = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + tcoords = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New(); tcoords->SetName("TextureCoordinates"); tcoords->SetNumberOfComponents(2); tcoords->SetNumberOfTuples(total); diff --git a/modules/viz/src/vtk/vtkImageMatSource.cpp b/modules/viz/src/vtk/vtkImageMatSource.cpp index 54500cb4bc..58a5642d46 100644 --- a/modules/viz/src/vtk/vtkImageMatSource.cpp +++ b/modules/viz/src/vtk/vtkImageMatSource.cpp @@ -78,7 +78,7 @@ int cv::viz::vtkImageMatSource::RequestData(vtkInformation*, vtkInformationVecto void cv::viz::vtkImageMatSource::SetImage(InputArray _image) { - CV_Assert(_image.depth() == CV_8U && _image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4); + CV_Assert(_image.depth() == CV_8U && (_image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4)); Mat image = _image.getMat(); From 0d12fb0346b016f4207a4feaf37f6fe9767c48ac Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 01:55:40 +0400 Subject: [PATCH 86/91] implemented workaround of a problem with x-server for ubuntu --- modules/viz/src/precomp.hpp | 1 + modules/viz/src/vizimpl.cpp | 41 ++++++++++++++++++++++++++----------- modules/viz/src/vizimpl.hpp | 2 ++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 7440f1ee81..de5346ebfc 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index e50666ec8c..64222b49c4 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -45,24 +45,18 @@ #include "precomp.hpp" + ///////////////////////////////////////////////////////////////////////////////////////////// -cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), widget_actor_map_(new WidgetActorMap) +cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), + window_position_(Vec2i(std::numeric_limits::min())), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); + window_name_ = VizStorage::generateWindowName(name); // Create render window window_ = vtkSmartPointer::New(); - window_name_ = VizStorage::generateWindowName(name); - cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); - window_->AddRenderer(renderer_); - window_->AlphaBitPlanesOff(); - window_->PointSmoothingOff(); - window_->LineSmoothingOff(); - window_->PolygonSmoothingOff(); - window_->SwapBuffersOn(); - window_->SetStereoTypeToAnaglyph(); // Create the interactor style style_ = vtkSmartPointer::New(); @@ -111,9 +105,32 @@ void cv::viz::Viz3d::VizImpl::close() interactor_->TerminateApp(); // This tends to close the window... } +void cv::viz::Viz3d::VizImpl::recreateRenderWindow() +{ + //recreating is workaround for Ubuntu -- a crash in x-server + Vec2i window_size(window_->GetSize()); + int fullscreen = window_->GetFullScreen(); + + window_ = vtkSmartPointer::New(); + if (window_position_[0] != std::numeric_limits::min()) //also workaround + window_->SetPosition(window_position_.val); + + window_->SetSize(window_size.val); + window_->SetFullScreen(fullscreen); + window_->AddRenderer(renderer_); + window_->AlphaBitPlanesOff(); + window_->PointSmoothingOff(); + window_->LineSmoothingOff(); + window_->PolygonSmoothingOff(); + window_->SwapBuffersOn(); + window_->SetStereoTypeToAnaglyph(); +} + + ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::spin() { + recreateRenderWindow(); interactor_ = vtkSmartPointer::New(); interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); @@ -129,6 +146,7 @@ void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) if (interactor_ == 0) { spin_once_state_ = true; + recreateRenderWindow(); interactor_ = vtkSmartPointer::New(); interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); @@ -400,7 +418,6 @@ void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3d &pose) camera.SetViewUp(up_vec.val); renderer_->ResetCameraClippingRange(); - renderer_->Render(); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -510,6 +527,6 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation) ////////////////////////////////////////////////////////////////////////////////////////////// cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_name_; } void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) { window_->SetFullScreen(mode); } -void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } +void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_position_ = position; window_->SetPosition(position.x, position.y); } void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(Point(Vec2i(window_->GetSize()))); } diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 11e22ee5d1..9eb918af68 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -122,6 +122,7 @@ private: vtkSmartPointer window_; String window_name_; + Vec2i window_position_; vtkSmartPointer timer_callback_; vtkSmartPointer exit_callback_; @@ -131,6 +132,7 @@ private: Ptr widget_actor_map_; bool removeActorFromRenderer(vtkSmartPointer actor); + void recreateRenderWindow(); }; #endif From 8f15a8abdb93e5ca02d7c810766737ec35238e9e Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 02:16:59 +0400 Subject: [PATCH 87/91] disabled Ubuntu workaround code for Windows --- modules/viz/src/vizimpl.cpp | 21 +++++++++++++++------ modules/viz/test/tests_simple.cpp | 3 +++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 64222b49c4..32c717c4f1 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -57,6 +57,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), window_ = vtkSmartPointer::New(); cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); + window_->AddRenderer(renderer_); // Create the interactor style style_ = vtkSmartPointer::New(); @@ -107,6 +108,7 @@ void cv::viz::Viz3d::VizImpl::close() void cv::viz::Viz3d::VizImpl::recreateRenderWindow() { +#if !defined _MSC_VER //recreating is workaround for Ubuntu -- a crash in x-server Vec2i window_size(window_->GetSize()); int fullscreen = window_->GetFullScreen(); @@ -118,12 +120,7 @@ void cv::viz::Viz3d::VizImpl::recreateRenderWindow() window_->SetSize(window_size.val); window_->SetFullScreen(fullscreen); window_->AddRenderer(renderer_); - window_->AlphaBitPlanesOff(); - window_->PointSmoothingOff(); - window_->LineSmoothingOff(); - window_->PolygonSmoothingOff(); - window_->SwapBuffersOn(); - window_->SetStereoTypeToAnaglyph(); +#endif } @@ -134,6 +131,12 @@ void cv::viz::Viz3d::VizImpl::spin() interactor_ = vtkSmartPointer::New(); interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); + window_->AlphaBitPlanesOff(); + window_->PointSmoothingOff(); + window_->LineSmoothingOff(); + window_->PolygonSmoothingOff(); + window_->SwapBuffersOn(); + window_->SetStereoTypeToAnaglyph(); window_->Render(); window_->SetWindowName(window_name_.c_str()); interactor_->Start(); @@ -152,6 +155,12 @@ void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) interactor_->SetInteractorStyle(style_); interactor_->AddObserver(vtkCommand::TimerEvent, timer_callback_); interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_); + window_->AlphaBitPlanesOff(); + window_->PointSmoothingOff(); + window_->LineSmoothingOff(); + window_->PolygonSmoothingOff(); + window_->SwapBuffersOn(); + window_->SetStereoTypeToAnaglyph(); window_->Render(); window_->SetWindowName(window_name_.c_str()); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 46f0e59b53..aae468ed9e 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -316,6 +316,8 @@ TEST(Viz, show_overlay_image) viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } + viz.showWidget("text2d", WText("Overlay images (stopped)", Point(20, 20), 20, Color::green())); + viz.spin(); } @@ -356,6 +358,7 @@ TEST(Viz, show_image_3d) viz.getWidget("img0").cast().setImage(lena * pow(sin(i++*7.5*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } + viz.showWidget("text2d", WText("Images in 3D (stopped)", Point(20, 20), 20, Color::green())); viz.spin(); } From d29c3d2f0db141d0e2423cdda3b6a10f41f414e3 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 03:03:05 +0400 Subject: [PATCH 88/91] fixed documentation warnings --- modules/viz/doc/viz3d.rst | 4 ++-- modules/viz/doc/widget.rst | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 5b361ad84e..f0e57e5fa5 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -35,7 +35,7 @@ Constructs camera pose from position, focal_point and up_vector (see gluLookAt() This function returns pose of the camera in global coordinate frame. viz::getWindowByName --------- +-------------------- Retrieves a window by its name. .. ocv:function:: Viz3d getWindowByName(const String &window_name) @@ -186,7 +186,7 @@ viz::Viz3d::showImage --------------------- Removed all widgets and displays image scaled to whole window area. -.. ocv:function:: void showImage(InputArray image, const Size& window_size = Size(-1, -1)); +.. ocv:function:: void showImage(InputArray image, const Size& window_size = Size(-1, -1)) :param image: Image to be displayed. :param size: Size of Viz3d window. Default value means no change. diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 13409974f6..543daab5f7 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -209,7 +209,7 @@ viz::Widget3D::applyTransform ------------------------------- Transforms internal widget data (i.e. points, normals) using the given transform. -.. ocv:function:: void applyTransform(const Affine3d &transform); +.. ocv:function:: void applyTransform(const Affine3d &transform) :param transform: Specified transformation to apply. @@ -285,7 +285,7 @@ viz::WPlane::WPlane ------------------- Constructs a default plane with center point at origin and normal oriented along z-axis. -.. ocv:function:: WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); +.. ocv:function:: WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()) :param size: Size of the plane :param color: :ocv:class:`Color` of the plane. @@ -294,7 +294,7 @@ viz::WPlane::WPlane ------------------- Constructs a repositioned plane -.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); +.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()) :param center: Center of the plane :param normal: Plane normal orientation @@ -369,7 +369,7 @@ viz::WCircle::WCircle ------------------------------- Constructs default planar circle centred at origin with plane normal along z-axis -.. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); +.. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()) :param radius: Radius of the circle. :param thickness: Thickness of the circle. @@ -379,7 +379,7 @@ viz::WCircle::WCircle ------------------------------- Constructs repositioned planar circle. -.. ocv:function:: WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); +.. ocv:function:: WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()) :param radius: Radius of the circle. :param center: Center of the circle. @@ -408,7 +408,7 @@ viz::WCone::WCone ------------------------------- Constructs default cone oriented along x-axis with center of its base located at origin -.. ocv:function:: WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()); +.. ocv:function:: WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()) :param length: Length of the cone. :param radius: Radius of the cone. @@ -419,7 +419,7 @@ viz::WCone::WCone ------------------------------- Constructs repositioned planar cone. -.. ocv:function:: WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()); +.. ocv:function:: WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()) :param radius: Radius of the cone. :param center: Center of the cone base. @@ -540,7 +540,7 @@ viz::WGrid::WGrid --------------------------- Constructs a WGrid. -.. ocv:function:: WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); +.. ocv:function:: WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()) :param cells: Number of cell columns and rows, respectively. :param cells_spacing: Size of each cell, respectively. @@ -823,7 +823,7 @@ Constructs a WTrajectory. * PATH & FRAMES : Displays both poly line and coordinate frames. viz::WTrajectoryFrustums ----------------- +------------------------ .. ocv:class:: WTrajectoryFrustums This 3D Widget represents a trajectory. :: @@ -838,7 +838,7 @@ This 3D Widget represents a trajectory. :: }; viz::WTrajectoryFrustums::WTrajectoryFrustums ------------------------------ +--------------------------------------------- Constructs a WTrajectoryFrustums. .. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()) @@ -877,7 +877,7 @@ viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- Constructs a WTrajectorySpheres. -.. ocv:function:: WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white()); +.. ocv:function:: WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white()) :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param line_length: Max length of the lines which point to previous position @@ -1012,7 +1012,7 @@ Constructs a WMesh. :param mesh: :ocv:class:`Mesh` object that will be displayed. -.. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); +.. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()) :param cloud: Points of the mesh object. :param polygons: Points of the mesh object. From 4e180070669008247920276ce057a69e5c8b428a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 03:22:45 +0400 Subject: [PATCH 89/91] fixed white spaces --- modules/viz/doc/viz3d.rst | 6 +-- modules/viz/doc/widget.rst | 47 +++++++++++------------ modules/viz/src/vizcore.cpp | 4 -- modules/viz/src/vtk/vtkCloudMatSource.cpp | 2 +- modules/viz/src/vtk/vtkImageMatSource.h | 2 - 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index f0e57e5fa5..d0e24ae8e7 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -102,7 +102,7 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar void setWidgetPose(const String &id, const Affine3d &pose); void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; - + void showImage(InputArray image, const Size& window_size = Size(-1, -1)); void setCamera(const Camera &camera); @@ -474,7 +474,7 @@ This class wraps mesh attributes, and it can load a mesh from a ``ply`` file. :: public: Mat cloud, colors, normals; - + //! Raw integer list of the form: (n,id1,id2,...,idn, n,id1,id2,...,idn, ...) //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud. Mat polygons; @@ -522,7 +522,7 @@ Constructs a KeyboardEvent. :param symbol: Name of the key. :param code: Code of the key. :param modifiers: Signals if ``alt``, ``ctrl`` or ``shift`` are pressed or their combination. - + viz::MouseEvent --------------- diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 543daab5f7..9ed28a775c 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -207,7 +207,7 @@ Returns the current pose of the widget. viz::Widget3D::applyTransform ------------------------------- -Transforms internal widget data (i.e. points, normals) using the given transform. +Transforms internal widget data (i.e. points, normals) using the given transform. .. ocv:function:: void applyTransform(const Affine3d &transform) @@ -293,7 +293,7 @@ Constructs a default plane with center point at origin and normal oriented along viz::WPlane::WPlane ------------------- Constructs a repositioned plane - + .. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()) :param center: Center of the plane @@ -371,7 +371,7 @@ Constructs default planar circle centred at origin with plane normal along z-axi .. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()) - :param radius: Radius of the circle. + :param radius: Radius of the circle. :param thickness: Thickness of the circle. :param color: :ocv:class:`Color` of the circle. @@ -385,9 +385,9 @@ Constructs repositioned planar circle. :param center: Center of the circle. :param normal: Normal of the plane in which the circle lies. :param thickness: Thickness of the circle. - :param color: :ocv:class:`Color` of the circle. - - + :param color: :ocv:class:`Color` of the circle. + + viz::WCone ------------------------------- .. ocv:class:: WCone @@ -410,8 +410,8 @@ Constructs default cone oriented along x-axis with center of its base located at .. ocv:function:: WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()) - :param length: Length of the cone. - :param radius: Radius of the cone. + :param length: Length of the cone. + :param radius: Radius of the cone. :param resolution: Resolution of the cone. :param color: :ocv:class:`Color` of the cone. @@ -421,12 +421,12 @@ Constructs repositioned planar cone. .. ocv:function:: WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()) - :param radius: Radius of the cone. + :param radius: Radius of the cone. :param center: Center of the cone base. :param tip: Tip of the cone. :param resolution: Resolution of the cone. - :param color: :ocv:class:`Color` of the cone. - + :param color: :ocv:class:`Color` of the cone. + viz::WCylinder -------------- .. ocv:class:: WCylinder @@ -675,14 +675,14 @@ This 3D Widget represents an image in 3D space. :: class CV_EXPORTS WImage3D : public Widget3D { - public: - //! Creates 3D image at the origin - WImage3D(InputArray image, const Size2d &size); - //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(InputArray image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); + public: + //! Creates 3D image at the origin + WImage3D(InputArray image, const Size2d &size); + //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation + WImage3D(InputArray image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); - void setImage(InputArray image); - }; + void setImage(InputArray image); + }; viz::WImage3D::WImage3D ----------------------- @@ -1001,7 +1001,7 @@ This 3D Widget defines a mesh. :: { public: WMesh(const Mesh &mesh); - WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); + WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); }; viz::WMesh::WMesh @@ -1011,11 +1011,10 @@ Constructs a WMesh. .. ocv:function:: WMesh(const Mesh &mesh) :param mesh: :ocv:class:`Mesh` object that will be displayed. - + .. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()) :param cloud: Points of the mesh object. - :param polygons: Points of the mesh object. - :param colors: Point colors. - :param normals: Point normals. - + :param polygons: Points of the mesh object. + :param colors: Point colors. + :param normals: Point normals. diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index ee74f2a123..29d4b4688f 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -310,7 +310,3 @@ void cv::viz::computeNormals(const Mesh& mesh, OutputArray _normals) else _normals.release(); } - - - - diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index e950a0d638..74d01bbd01 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -265,7 +265,7 @@ void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, template void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total) -{ +{ typedef Vec<_Tn, 2> Vec2; tcoords = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New(); tcoords->SetName("TextureCoordinates"); diff --git a/modules/viz/src/vtk/vtkImageMatSource.h b/modules/viz/src/vtk/vtkImageMatSource.h index a4340346c1..db0c093ed8 100644 --- a/modules/viz/src/vtk/vtkImageMatSource.h +++ b/modules/viz/src/vtk/vtkImageMatSource.h @@ -80,5 +80,3 @@ namespace cv #endif - - From 4cc8f7012be67571daac483ca101987bd39c7314 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 08:47:07 +0400 Subject: [PATCH 90/91] closing window --- modules/viz/include/opencv2/viz/viz3d.hpp | 1 + modules/viz/src/viz3d.cpp | 1 + modules/viz/src/vizimpl.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index a83d8e8fc3..7cb7d0ceaf 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -105,6 +105,7 @@ namespace cv void spin(); void spinOnce(int time = 1, bool force_redraw = false); bool wasStopped() const; + void close(); void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); void registerMouseCallback(MouseCallback callback, void* cookie = 0); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 2d4aefc0bb..56f978c0ea 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -101,6 +101,7 @@ void cv::viz::Viz3d::release() void cv::viz::Viz3d::spin() { impl_->spin(); } void cv::viz::Viz3d::spinOnce(int time, bool force_redraw) { impl_->spinOnce(time, force_redraw); } bool cv::viz::Viz3d::wasStopped() const { return impl_->wasStopped(); } +void cv::viz::Viz3d::close() { impl_->close(); } void cv::viz::Viz3d::registerKeyboardCallback(KeyboardCallback callback, void* cookie) { impl_->registerKeyboardCallback(callback, cookie); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 32c717c4f1..5fa49e2f96 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -104,6 +104,7 @@ void cv::viz::Viz3d::VizImpl::close() return; interactor_->GetRenderWindow()->Finalize(); interactor_->TerminateApp(); // This tends to close the window... + interactor_ = 0; } void cv::viz::Viz3d::VizImpl::recreateRenderWindow() From ac035b9b8e77ea6590995ab4651b90b3c6ae9593 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 20 Jan 2014 15:17:35 +0400 Subject: [PATCH 91/91] review comments --- modules/core/include/opencv2/core/affine.hpp | 16 +++---- modules/viz/src/precomp.cpp | 46 -------------------- 2 files changed, 8 insertions(+), 54 deletions(-) delete mode 100644 modules/viz/src/precomp.cpp diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 0ee6fabe9b..8a54762924 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -55,9 +55,9 @@ namespace cv { public: typedef T float_type; - typedef cv::Matx Mat3; - typedef cv::Matx Mat4; - typedef cv::Vec Vec3; + typedef Matx Mat3; + typedef Matx Mat4; + typedef Vec Vec3; Affine3(); @@ -70,11 +70,11 @@ namespace cv //Rodrigues vector Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); - //Combines all contructors above. Supports 4x4, 3x3, 1x3, 3x1 sizes of data matrix - explicit Affine3(const cv::Mat& data, const Vec3& t = Vec3::all(0)); + //Combines all contructors above. Supports 4x4, 3x4, 3x3, 1x3, 3x1 sizes of data matrix + explicit Affine3(const Mat& data, const Vec3& t = Vec3::all(0)); //From 16th element array - Affine3(const float_type* vals); + explicit Affine3(const float_type* vals); static Affine3 Identity(); @@ -134,8 +134,8 @@ namespace cv typedef Affine3 Affine3f; typedef Affine3 Affine3d; - static cv::Vec3f operator*(const cv::Affine3f& affine, const cv::Vec3f& vector); - static cv::Vec3d operator*(const cv::Affine3d& affine, const cv::Vec3d& vector); + static Vec3f operator*(const Affine3f& affine, const Vec3f& vector); + static Vec3d operator*(const Affine3d& affine, const Vec3d& vector); template class DataType< Affine3<_Tp> > { diff --git a/modules/viz/src/precomp.cpp b/modules/viz/src/precomp.cpp deleted file mode 100644 index 631a300da2..0000000000 --- a/modules/viz/src/precomp.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -// Authors: -// * Ozan Tonkal, ozantonkal@gmail.com -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -//M*/ - -#include "precomp.hpp"