Merge pull request #2173 from Nerei:viz

pull/2163/merge
Roman Donchenko 11 years ago committed by OpenCV Buildbot
commit 9710b25c7d
  1. 2
      CMakeLists.txt
  2. 4
      cmake/OpenCVDetectVTK.cmake
  3. 2
      doc/tutorials/viz/launching_viz/launching_viz.rst
  4. 77
      modules/core/include/opencv2/core/affine.hpp
  5. 169
      modules/viz/doc/viz3d.rst
  6. 334
      modules/viz/doc/widget.rst
  7. 44
      modules/viz/include/opencv2/viz.hpp
  8. 178
      modules/viz/include/opencv2/viz/types.hpp
  9. 30
      modules/viz/include/opencv2/viz/viz3d.hpp
  10. 5
      modules/viz/include/opencv2/viz/widget_accessor.hpp
  11. 209
      modules/viz/include/opencv2/viz/widgets.hpp
  12. 773
      modules/viz/src/cloud_widgets.cpp
  13. 441
      modules/viz/src/clouds.cpp
  14. 301
      modules/viz/src/interactor_style.cpp
  15. 24
      modules/viz/src/interactor_style.hpp
  16. 181
      modules/viz/src/precomp.hpp
  17. 1497
      modules/viz/src/shape_widgets.cpp
  18. 1088
      modules/viz/src/shapes.cpp
  19. 194
      modules/viz/src/types.cpp
  20. 165
      modules/viz/src/viz.cpp
  21. 31
      modules/viz/src/viz3d.cpp
  22. 368
      modules/viz/src/viz3d_impl.hpp
  23. 312
      modules/viz/src/vizcore.cpp
  24. 378
      modules/viz/src/vizimpl.cpp
  25. 138
      modules/viz/src/vizimpl.hpp
  26. 158
      modules/viz/src/vtk/vtkCloudMatSink.cpp
  27. 79
      modules/viz/src/vtk/vtkCloudMatSink.h
  28. 286
      modules/viz/src/vtk/vtkCloudMatSource.cpp
  29. 96
      modules/viz/src/vtk/vtkCloudMatSource.h
  30. 143
      modules/viz/src/vtk/vtkImageMatSource.cpp
  31. 82
      modules/viz/src/vtk/vtkImageMatSource.h
  32. 241
      modules/viz/src/vtk/vtkOBJWriter.cpp
  33. 40
      modules/viz/src/vtk/vtkOBJWriter.h
  34. 110
      modules/viz/src/vtk/vtkTrajectorySource.cpp
  35. 84
      modules/viz/src/vtk/vtkTrajectorySource.h
  36. 93
      modules/viz/src/vtk/vtkXYZWriter.cpp
  37. 78
      modules/viz/src/vtk/vtkXYZWriter.h
  38. 189
      modules/viz/src/widget.cpp
  39. 2
      modules/viz/test/test_main.cpp
  40. 23
      modules/viz/test/test_precomp.cpp
  41. 40
      modules/viz/test/test_precomp.hpp
  42. 20
      modules/viz/test/test_tutorial2.cpp
  43. 42
      modules/viz/test/test_tutorial3.cpp
  44. 141
      modules/viz/test/test_viz3d.cpp
  45. 407
      modules/viz/test/tests_simple.cpp

@ -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) )

@ -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()
endif()

@ -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();

@ -55,9 +55,9 @@ namespace cv
{
public:
typedef T float_type;
typedef cv::Matx<float_type, 3, 3> Mat3;
typedef cv::Matx<float_type, 4, 4> Mat4;
typedef cv::Vec<float_type, 3> Vec3;
typedef Matx<float_type, 3, 3> Mat3;
typedef Matx<float_type, 4, 4> Mat4;
typedef Vec<float_type, 3> 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));
//Euler angles
Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t = Vec3::all(0));
//From 16th element array
explicit Affine3(const float_type* vals);
static Affine3 Identity();
@ -87,9 +87,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);
@ -105,6 +102,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;
@ -113,6 +113,8 @@ namespace cv
template <typename Y> operator Affine3<Y>() const;
template <typename Y> Affine3<Y> cast() const;
Mat4 matrix;
#if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H
@ -132,10 +134,26 @@ namespace cv
typedef Affine3<float> Affine3f;
typedef Affine3<double> 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<typename _Tp> class DataType< Affine3<_Tp> >
{
public:
typedef Affine3<_Tp> value_type;
typedef Affine3<typename DataType<_Tp>::work_type> work_type;
typedef _Tp channel_type;
enum { generic_type = 0,
depth = DataType<channel_type>::depth,
channels = 16,
fmt = DataType<channel_type>::fmt + ((channels - 1) << 8),
type = CV_MAKETYPE(depth, channels)
};
typedef Vec<channel_type, channels> vec_type;
};
}
///////////////////////////////////////////////////////////////////////////////////
@ -179,6 +197,12 @@ cv::Affine3<T>::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);
@ -187,13 +211,8 @@ cv::Affine3<T>::Affine3(const cv::Mat& data, const Vec3& t)
}
template<typename T> inline
cv::Affine3<T>::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;
}
cv::Affine3<T>::Affine3(const float_type* vals) : matrix(vals)
{}
template<typename T> inline
cv::Affine3<T> cv::Affine3<T>::Identity()
@ -261,12 +280,6 @@ void cv::Affine3<T>::rotation(const cv::Mat& data)
CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1");
}
template<typename T> inline
void cv::Affine3<T>::rotation(float_type alpha, float_type beta, float_type gamma)
{
rotation(Vec3(alpha, beta, gamma));
}
template<typename T> inline
void cv::Affine3<T>::linear(const Mat3& L)
{
@ -382,6 +395,12 @@ cv::Affine3<T> cv::Affine3<T>::rotate(const Mat3& R) const
return result;
}
template<typename T> inline
cv::Affine3<T> cv::Affine3<T>::rotate(const Vec3& _rvec) const
{
return rotate(Affine3f(_rvec).rotation());
}
template<typename T> inline
cv::Affine3<T> cv::Affine3<T>::translate(const Vec3& t) const
{
@ -404,6 +423,12 @@ cv::Affine3<T>::operator Affine3<Y>() const
return Affine3<Y>(matrix);
}
template<typename T> template <typename Y> inline
cv::Affine3<Y> cv::Affine3<T>::cast() const
{
return Affine3<Y>(matrix);
}
template<typename T> inline
cv::Affine3<T> cv::operator*(const cv::Affine3<T>& affine1, const cv::Affine3<T>& affine2)
{

@ -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.
@ -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
----------
@ -94,19 +94,21 @@ 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 showImage(InputArray image, const Size& window_size = Size(-1, -1));
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();
@ -132,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:
@ -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.
@ -182,11 +182,20 @@ 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.
.. 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 +204,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 +213,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 +235,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.
@ -414,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.
@ -468,33 +463,33 @@ 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 loadMesh(const String& file);
private:
/* hidden */
static Mesh load(const String& file);
};
viz::Mesh3d::loadMesh
viz::Mesh::load
---------------------
Loads a mesh from a ``ply`` file.
.. ocv:function:: static Mesh3d loadMesh(const String& file)
.. ocv:function:: static Mesh load(const String& file)
:param file: File name.
:param file: File name (for no only PLY is supported)
viz::KeyboardEvent
@ -506,40 +501,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: 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.
: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.
viz::MouseEvent
---------------
@ -553,26 +536,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
-----------
@ -585,24 +566,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);
@ -614,7 +595,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.
@ -622,19 +603,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.
@ -643,7 +624,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.

@ -170,20 +170,23 @@ Base class of all 3D widgets. ::
public:
Widget3D() {}
void setPose(const Affine3f &pose);
void updatePose(const Affine3f &pose);
Affine3f getPose() const;
//! 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
----------------------
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 +194,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 +202,16 @@ viz::Widget3D::getPose
----------------------
Returns the current pose of the widget.
.. ocv:function:: Affine3f getWidgetPose() const
.. 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
-----------------------
@ -262,27 +274,31 @@ 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());
private:
/* hidden */
//! 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 Vec4f& coefs, float 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 Vec4f& coefs, const Point3f& pt, float 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_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_yaxis: Up-vector. New orientation of plane y-axis.
:param color: :ocv:class:`Color` of the plane.
viz::WSphere
@ -294,14 +310,14 @@ This 3D Widget defines a sphere. ::
class CV_EXPORTS WSphere : public Widget3D
{
public:
WSphere(const cv::Point3f &center, float radius, int sphere_resolution = 10, const Color &color = Color::white())
WSphere(const cv::Point3f &center, double radius, int sphere_resolution = 10, const Color &color = Color::white())
};
viz::WSphere::WSphere
---------------------
Constructs a WSphere.
.. ocv:function:: WSphere(const cv::Point3f &center, float radius, int sphere_resolution = 10, const Color &color = Color::white())
.. ocv:function:: WSphere(const cv::Point3f &center, 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 +333,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,20 +358,75 @@ 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());
//! 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(double radius, double thickness = 0.01, const Color &color = Color::white())
: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(const Point3f& pt, float radius, float 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 pt: Center of the circle.
: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::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
@ -365,17 +436,17 @@ 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 Point3d& axis_point1, const Point3d& axis_point2, 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.
: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.
@ -416,14 +487,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.
@ -437,9 +508,6 @@ This 3D Widget defines a poly line. ::
{
public:
WPolyLine(InputArray points, const Color &color = Color::white());
private:
/* hidden */
};
viz::WPolyLine::WPolyLine
@ -460,30 +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 Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white());
private:
/* hidden */
//! 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 Vec4f &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
------------
@ -494,7 +564,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 +574,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.
@ -575,16 +645,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.
@ -593,7 +663,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.
@ -607,23 +677,23 @@ This 3D Widget represents an image in 3D space. ::
{
public:
//! Creates 3D image at the origin
WImage3D(const Mat &image, const Size &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 Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size);
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 Size &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 Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size)
.. 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.
@ -635,7 +705,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.
@ -649,15 +719,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, InputArray image, 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, InputArray image, double scale = 1.0, const Color &color = Color::white());
};
viz::WCameraPosition::WCameraPosition
@ -666,7 +736,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 +746,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 +754,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 +768,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, 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.
@ -707,7 +777,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, 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.
@ -729,81 +799,91 @@ 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<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0);
//! Displays trajectory of the given path by frustums
WTrajectory(const std::vector<Affine3f> &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<Affine3f> &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white());
private:
/* hidden */
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(const std::vector<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0)
.. 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.
:param display_mode: Display mode. This can be DISPLAY_PATH, DISPLAY_FRAMES, DISPLAY_PATH & DISPLAY_FRAMES.
:param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected.
:param path: List of poses on a trajectory. Takes std::vector<Affine<T>> 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.
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.
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(InputArray path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white());
//! Displays trajectory of the given path by frustums
WTrajectoryFrustums(InputArray path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white());
};
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white())
viz::WTrajectoryFrustums::WTrajectoryFrustums
---------------------------------------------
Constructs a WTrajectoryFrustums.
:param path: List of poses on a trajectory.
.. ocv:function:: WTrajectoryFrustums(const std::vector<Affine3d> &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white())
:param path: List of poses on a trajectory. Takes std::vector<Affine<T>> 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.
Displays frustums at each pose of the trajectory.
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white())
.. ocv:function:: WTrajectoryFrustums(const std::vector<Affine3d> &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<Affine<T>> 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.
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<Affine3f> &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());
WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007,
const Color &from = Color::red(), const Color &to = Color::white());
};
viz::WSpheresTrajectory::WSpheresTrajectory
viz::WTrajectorySpheres::WTrajectorySpheres
-------------------------------------------
Constructs a WSpheresTrajectory.
Constructs a WTrajectorySpheres.
.. ocv:function:: WSpheresTrajectory(const std::vector<Affine3f> &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(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<Affine<T>> 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
-----------
@ -818,9 +898,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
@ -855,12 +932,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());
private:
/* hidden */
void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3d &pose = Affine3d::Identity());
};
viz::WCloudCollection::WCloudCollection
@ -873,7 +947,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.
@ -881,7 +955,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.
@ -900,17 +974,14 @@ 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());
private:
/* hidden */
WCloudNormals(InputArray cloud, InputArray normals, int level = 100, double scale = 0.02f, const Color &color = Color::white());
};
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.
@ -929,16 +1000,21 @@ 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.

@ -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__
@ -58,17 +55,20 @@ 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);
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();
//! 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)
{
@ -91,6 +91,36 @@ namespace cv
template<typename _Tp> inline bool isNan(const Point3_<_Tp>& p)
{ return isNan(p.x) || isNan(p.y) || isNan(p.z); }
///////////////////////////////////////////////////////////////////////////////////////////////
/// Read/write clouds. Supported formats: ply, xyz, obj and stl (readonly)
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());
///////////////////////////////////////////////////////////////////////////////////////////////
/// Reads mesh. Only ply format is supported now and no texture load support
CV_EXPORTS Mesh readMesh(const String& file);
///////////////////////////////////////////////////////////////////////////////////////////////
/// Read/write poses and trajectories
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");
//! takes vector<Affine3<T>> 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");
//! takes vector<Affine3<T>> 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 Mesh& mesh, OutputArray normals);
} /* namespace viz */
} /* namespace cv */

@ -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__
@ -77,97 +74,113 @@ 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();
static Color not_set();
};
class CV_EXPORTS Mesh3d
class CV_EXPORTS Mesh
{
public:
Mat cloud, colors, normals;
Mat cloud, colors;
//! 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 cv::viz::Mesh3d loadMesh(const String& file);
Mat texture, tcoords;
private:
struct loadMeshImpl;
//! Loads mesh from a given ply file (no texture load support for now)
static Mesh load(const String& file);
};
class CV_EXPORTS KeyboardEvent
class CV_EXPORTS Camera
{
public:
static const unsigned int Alt = 1;
static const unsigned int Ctrl = 2;
static const unsigned int Shift = 4;
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);
//! 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);
const Vec2d & getClip() const { return clip_; }
void setClip(const Vec2d &clip) { clip_ = clip; }
bool isAltPressed() const;
bool isCtrlPressed() const;
bool isShiftPressed() const;
const Size & getWindowSize() const { return window_size_; }
void setWindowSize(const Size &window_size);
const Vec2d& getFov() const { return fov_; }
void setFov(const Vec2d& fov) { fov_ = fov; }
unsigned char getKeyCode() const;
const Vec2d& getPrincipalPoint() const { return principal_point_; }
const Vec2d& getFocalLength() const { return focal_; }
const String& getKeySym() const;
bool keyDown() const;
bool keyUp() const;
void computeProjectionMatrix(Matx44d &proj) const;
protected:
static Camera KinectCamera(const Size &window_size);
private:
void init(double fx, double fy, double cx, double cy, const Size &window_size);
bool action_;
unsigned int modifiers_;
unsigned char key_code_;
String key_sym_;
Vec2d clip_;
Vec2d fov_;
Size window_size_;
Vec2d principal_point_;
Vec2d focal_;
};
class CV_EXPORTS MouseEvent
class CV_EXPORTS KeyboardEvent
{
public:
enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ;
enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ;
enum { NONE = 0, ALT = 1, CTRL = 2, SHIFT = 4 };
enum Action { KEY_UP = 0, KEY_DOWN = 1 };
MouseEvent(const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift);
KeyboardEvent(Action action, const String& symbol, unsigned char code, int modifiers);
Type type;
MouseButton button;
Point pointer;
unsigned int key_state;
Action action;
String symbol;
unsigned char code;
int modifiers;
};
class CV_EXPORTS Camera
class CV_EXPORTS MouseEvent
{
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);
inline const Vec2d & getClip() const { return clip_; }
inline void setClip(const Vec2d &clip) { clip_ = clip; }
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 Vec2f & getPrincipalPoint() const { return principal_point_; }
inline const Vec2f & getFocalLength() const { return focal_; }
void computeProjectionMatrix(Matx44f &proj) const;
static Camera KinectCamera(const Size &window_size);
enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ;
enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ;
private:
void init(float f_x, float f_y, float c_x, float c_y, const Size &window_size);
MouseEvent(const Type& type, const MouseButton& button, const Point& pointer, int modifiers);
Vec2d clip_;
Vec2f fov_;
Size window_size_;
Vec2f principal_point_;
Vec2f focal_;
Type type;
MouseButton button;
Point pointer;
int modifiers;
};
} /* namespace viz */
} /* namespace cv */
@ -180,15 +193,44 @@ 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(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(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, 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); }
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); }
inline cv::viz::Color cv::viz::Color::not_set() { return Color(-1, -1, -1); }
#endif

@ -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__
@ -64,6 +61,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*);
@ -72,19 +70,21 @@ 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 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;
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();
@ -96,13 +96,16 @@ 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 setBackgroundColor(const Color& color = Color::black());
void setWindowPosition(const Point& window_position);
void setFullScreen(bool mode = true);
void setBackgroundColor(const Color& color = Color::black(), const Color& color2 = Color::not_set());
void setBackgroundTexture(InputArray image = noArray());
void setBackgroundMeshLab();
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);
@ -110,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:

@ -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
#endif

@ -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__
@ -68,14 +65,14 @@ namespace cv
SHADING
};
enum RenderingRepresentationProperties
enum RepresentationValues
{
REPRESENTATION_POINTS,
REPRESENTATION_WIREFRAME,
REPRESENTATION_SURFACE
};
enum ShadingRepresentationProperties
enum ShadingValues
{
SHADING_FLAT,
SHADING_GOURAUD,
@ -114,13 +111,15 @@ namespace cv
public:
Widget3D() {}
void setPose(const Affine3f &pose);
void updatePose(const Affine3f &pose);
Affine3f getPose() const;
//! 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);
private:
struct MatrixConverter;
};
@ -134,92 +133,94 @@ namespace cv
void setColor(const Color &color);
};
/////////////////////////////////////////////////////////////////////////////
/// Simple widgets
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());
private:
struct SetSizeImpl;
//! 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_yaxis,
const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white());
};
class CV_EXPORTS WSphere : public Widget3D
{
public:
WSphere(const cv::Point3f &center, float radius, int sphere_resolution = 10, const Color &color = Color::white());
WSphere(const cv::Point3d &center, 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());
//! 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());
};
class CV_EXPORTS WCylinder : public Widget3D
class CV_EXPORTS WCone : public Widget3D
{
public:
WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white());
//! 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 WCube : public Widget3D
class CV_EXPORTS WCylinder : public Widget3D
{
public:
WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, 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 WCoordinateSystem : public Widget3D
class CV_EXPORTS WCube : public Widget3D
{
public:
WCoordinateSystem(float scale = 1.f);
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
{
public:
WPolyLine(InputArray points, const Color &color = Color::white());
private:
struct CopyImpl;
};
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());
private:
struct GridImpl;
};
/////////////////////////////////////////////////////////////////////////////
/// 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 Point &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 = 10, const Color &color = Color::white());
//! 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);
String getText() const;
@ -228,63 +229,91 @@ 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
{
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(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 Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size);
WImage3D(InputArray image, const Size2d &size, const Vec3d &center, const Vec3d &normal, const Vec3d &up_vector);
void setImage(InputArray image);
};
/////////////////////////////////////////////////////////////////////////////
/// Compond widgets
void setImage(const Mat &image);
class CV_EXPORTS WCoordinateSystem : public Widget3D
{
public:
WCoordinateSystem(double scale = 1.0);
};
class CV_EXPORTS WGrid : public Widget3D
{
public:
//! 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
{
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, InputArray image, 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());
private:
struct ProjectImage;
WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white());
};
/////////////////////////////////////////////////////////////////////////////
/// Trajectories
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<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.f);
//! Displays trajectory of the given path by frustums
WTrajectory(const std::vector<Affine3f> &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<Affine3f> &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white());
//! Takes vector<Affine3<T>> and displays trajectory of the given path either by coordinate frames or polyline
WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white());
};
private:
struct ApplyPath;
class CV_EXPORTS WTrajectoryFrustums : public Widget3D
{
public:
//! Takes vector<Affine3<T>> 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<Affine3<T>> 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 WSpheresTrajectory: public Widget3D
class CV_EXPORTS WTrajectorySpheres: public Widget3D
{
public:
WSpheresTrajectory(const std::vector<Affine3f> &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());
//! Takes vector<Affine3<T>> 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());
};
/////////////////////////////////////////////////////////////////////////////
/// Clouds
class CV_EXPORTS WCloud: public Widget3D
{
public:
@ -292,9 +321,19 @@ 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 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
@ -303,32 +342,27 @@ 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());
private:
struct CreateCloudWidget;
void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3d &pose = Affine3d::Identity());
};
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;
WCloudNormals(InputArray cloud, InputArray normals, int level = 64, double scale = 0.1, const Color &color = Color::white());
};
class CV_EXPORTS WMesh : public Widget3D
{
public:
WMesh(const Mesh3d &mesh);
private:
struct CopyImpl;
WMesh(const Mesh &mesh);
WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray());
};
/////////////////////////////////////////////////////////////////////////////
/// Utility exports
template<> CV_EXPORTS Widget2D Widget::cast<Widget2D>();
template<> CV_EXPORTS Widget3D Widget::cast<Widget3D>();
template<> CV_EXPORTS WLine Widget::cast<WLine>();
@ -337,6 +371,7 @@ namespace cv
template<> CV_EXPORTS WCylinder Widget::cast<WCylinder>();
template<> CV_EXPORTS WArrow Widget::cast<WArrow>();
template<> CV_EXPORTS WCircle Widget::cast<WCircle>();
template<> CV_EXPORTS WCone Widget::cast<WCone>();
template<> CV_EXPORTS WCube Widget::cast<WCube>();
template<> CV_EXPORTS WCoordinateSystem Widget::cast<WCoordinateSystem>();
template<> CV_EXPORTS WPolyLine Widget::cast<WPolyLine>();
@ -347,8 +382,10 @@ namespace cv
template<> CV_EXPORTS WImage3D Widget::cast<WImage3D>();
template<> CV_EXPORTS WCameraPosition Widget::cast<WCameraPosition>();
template<> CV_EXPORTS WTrajectory Widget::cast<WTrajectory>();
template<> CV_EXPORTS WSpheresTrajectory Widget::cast<WSpheresTrajectory>();
template<> CV_EXPORTS WTrajectoryFrustums Widget::cast<WTrajectoryFrustums>();
template<> CV_EXPORTS WTrajectorySpheres Widget::cast<WTrajectorySpheres>();
template<> CV_EXPORTS WCloud Widget::cast<WCloud>();
template<> CV_EXPORTS WPaintedCloud Widget::cast<WPaintedCloud>();
template<> CV_EXPORTS WCloudCollection Widget::cast<WCloudCollection>();
template<> CV_EXPORTS WCloudNormals Widget::cast<WCloudNormals>();
template<> CV_EXPORTS WMesh Widget::cast<WMesh>();

@ -1,773 +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
//
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace viz
{
template<typename _Tp> Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer<vtkPoints>& points);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Point Cloud Widget implementation
struct cv::viz::WCloud::CreateCloudWidget
{
static inline vtkSmartPointer<vtkPolyData> create(const Mat &cloud, vtkIdType &nr_points)
{
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New();
polydata->SetVerts(vertices);
vtkSmartPointer<vtkPoints> points = polydata->GetPoints();
vtkSmartPointer<vtkIdTypeArray> initcells;
nr_points = cloud.total();
if (!points)
{
points = vtkSmartPointer<vtkPoints>::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<float>(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<double>(points);
Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud);
nr_points = data_end - data_beg;
}
points->SetNumberOfPoints(nr_points);
// Update cells
vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData();
// If no init cells and cells has not been initialized...
if (!cells)
cells = vtkSmartPointer<vtkIdTypeArray>::New();
// If we have less values then we need to recreate the array
if (cells->GetNumberOfTuples() < nr_points)
{
cells = vtkSmartPointer<vtkIdTypeArray>::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_n(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<vtkIdTypeArray>::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.type() == CV_8UC3 && cloud.size() == colors.size());
if (cloud.isContinuous() && colors.isContinuous())
{
cloud.reshape(cloud.channels(), 1);
colors.reshape(colors.channels(), 1);
}
vtkIdType nr_points;
vtkSmartPointer<vtkPolyData> polydata = CreateCloudWidget::create(cloud, nr_points);
// Filter colors
Vec3b* colors_data = new Vec3b[nr_points];
NanFilter::copyColor(colors, colors_data, cloud);
vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::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<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
#if VTK_MAJOR_VERSION <= 5
mapper->SetInput(polydata);
#else
mapper->SetInputData(polydata);
#endif
Vec3d minmax(scalars->GetRange());
mapper->SetScalarRange(minmax.val);
mapper->SetScalarModeToUsePointData();
bool interpolation = (polydata && polydata->GetNumberOfCells() != polydata->GetNumberOfVerts());
mapper->SetInterpolateScalarsBeforeMapping(interpolation);
mapper->ScalarVisibilityOn();
mapper->ImmediateModeRenderingOff();
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
actor->SetNumberOfCloudPoints(int(std::max<vtkIdType>(1, polydata->GetNumberOfPoints() / 10)));
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
}
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<vtkPolyData> polydata = CreateCloudWidget::create(cloud, nr_points);
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::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->ImmediateModeRenderingOff();
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
actor->SetNumberOfCloudPoints(int(std::max<vtkIdType>(1, polydata->GetNumberOfPoints() / 10)));
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WCloud cv::viz::Widget::cast<cv::viz::WCloud>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WCloud&>(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Cloud Collection Widget implementation
struct cv::viz::WCloudCollection::CreateCloudWidget
{
static inline vtkSmartPointer<vtkPolyData> create(const Mat &cloud, vtkIdType &nr_points)
{
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New();
polydata->SetVerts(vertices);
vtkSmartPointer<vtkPoints> points = polydata->GetPoints();
vtkSmartPointer<vtkIdTypeArray> initcells;
nr_points = cloud.total();
if (!points)
{
points = vtkSmartPointer<vtkPoints>::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<float>(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<double>(points);
Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud);
nr_points = data_end - data_beg;
}
points->SetNumberOfPoints(nr_points);
// Update cells
vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData();
// If no init cells and cells has not been initialized...
if (!cells)
cells = vtkSmartPointer<vtkIdTypeArray>::New();
// If we have less values then we need to recreate the array
if (cells->GetNumberOfTuples() < nr_points)
{
cells = vtkSmartPointer<vtkIdTypeArray>::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_n(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<vtkIdTypeArray>::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<vtkLODActor> actor, vtkSmartPointer<vtkPolyData> poly_data, Vec3d& minmax)
{
vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper());
if (!mapper)
{
// This is the first cloud
vtkSmartPointer<vtkDataSetMapper> mapper_new = vtkSmartPointer<vtkDataSetMapper>::New();
#if VTK_MAJOR_VERSION <= 5
mapper_new->SetInputConnection(poly_data->GetProducerPort());
#else
mapper_new->SetInputData(poly_data);
#endif
mapper_new->SetScalarRange(minmax.val);
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<vtkIdType>(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<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::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<vtkIdType>(1, old_cloud_points+poly_data->GetNumberOfPoints() / 10)));
}
};
cv::viz::WCloudCollection::WCloudCollection()
{
// Just create the actor
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
WidgetAccessor::setProp(*this, actor);
}
void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, const Affine3f &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.type() == CV_8UC3 && cloud.size() == colors.size());
if (cloud.isContinuous() && colors.isContinuous())
{
cloud.reshape(cloud.channels(), 1);
colors.reshape(colors.channels(), 1);
}
vtkIdType nr_points;
vtkSmartPointer<vtkPolyData> polydata = CreateCloudWidget::create(cloud, nr_points);
// Filter colors
Vec3b* colors_data = new Vec3b[nr_points];
NanFilter::copyColor(colors, colors_data, cloud);
vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::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<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->PreMultiply();
transform->SetMatrix(convertToVtkMatrix(pose.matrix));
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
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));
CV_Assert("Incompatible widget type." && actor);
Vec3d minmax(scalars->GetRange());
CreateCloudWidget::createMapper(actor, transform_filter->GetOutput(), minmax);
}
void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &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<vtkPolyData> polydata = CreateCloudWidget::create(cloud, nr_points);
vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
scalars->SetNumberOfComponents(3);
scalars->SetNumberOfTuples(nr_points);
scalars->FillComponent(0, color[2]);
scalars->FillComponent(1, color[1]);
scalars->FillComponent(2, color[0]);
// Assign the colors
polydata->GetPointData()->SetScalars(scalars);
// Transform the poly data based on the pose
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->PreMultiply();
transform->SetMatrix(convertToVtkMatrix(pose.matrix));
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
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));
CV_Assert("Incompatible widget type." && actor);
Vec3d minmax(scalars->GetRange());
CreateCloudWidget::createMapper(actor, transform_filter->GetOutput(), minmax);
}
template<> cv::viz::WCloudCollection cv::viz::Widget::cast<cv::viz::WCloudCollection>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WCloudCollection&>(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Cloud Normals Widget implementation
struct cv::viz::WCloudNormals::ApplyCloudNormals
{
template<typename _Tp>
struct Impl
{
static vtkSmartPointer<vtkCellArray> applyOrganized(const Mat &cloud, const Mat& normals, double level, float scale, _Tp *&pts, vtkIdType &nr_normals)
{
vtkIdType point_step = static_cast<vtkIdType>(std::sqrt(level));
nr_normals = (static_cast<vtkIdType>((cloud.cols - 1) / point_step) + 1) *
(static_cast<vtkIdType>((cloud.rows - 1) / point_step) + 1);
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::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<vtkCellArray> applyUnorganized(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals)
{
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::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<typename _Tp>
static inline vtkSmartPointer<vtkCellArray> 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)
{
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());
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
vtkIdType nr_normals = 0;
if (cloud.depth() == CV_32F)
{
points->SetDataTypeToFloat();
vtkSmartPointer<vtkFloatArray> data = vtkSmartPointer<vtkFloatArray>::New();
data->SetNumberOfComponents(3);
float* pts = 0;
lines = ApplyCloudNormals::apply(cloud, normals, level, scale, pts, nr_normals);
data->SetArray(&pts[0], 2 * nr_normals * 3, 0);
points->SetData(data);
}
else
{
points->SetDataTypeToDouble();
vtkSmartPointer<vtkDoubleArray> data = vtkSmartPointer<vtkDoubleArray>::New();
data->SetNumberOfComponents(3);
double* pts = 0;
lines = ApplyCloudNormals::apply(cloud, normals, level, scale, pts, nr_normals);
data->SetArray(&pts[0], 2 * nr_normals * 3, 0);
points->SetData(data);
}
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(lines);
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
#if VTK_MAJOR_VERSION <= 5
mapper->SetInput(polyData);
#else
mapper->SetInputData(polyData);
#endif
mapper->SetColorModeToMapScalars();
mapper->SetScalarModeToUsePointData();
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WCloudNormals cv::viz::Widget::cast<cv::viz::WCloudNormals>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WCloudNormals&>(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Mesh Widget implementation
struct cv::viz::WMesh::CopyImpl
{
template<typename _Tp>
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.type() == CV_8UC3 && mesh.cloud.size() == mesh.colors.size()));
CV_Assert(!mesh.polygons.empty() && mesh.polygons.type() == CV_32SC1);
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkIdType nr_points = mesh.cloud.total();
Mat look_up_mat(1, nr_points, CV_32SC1);
int * look_up = look_up_mat.ptr<int>();
points->SetNumberOfPoints(nr_points);
// Copy data from cloud to vtkPoints
if (mesh.cloud.depth() == CV_32F)
{
points->SetDataTypeToFloat();
Vec3f *data_beg = vtkpoints_data<float>(points);
Vec3f *data_end = CopyImpl::copy(mesh.cloud, data_beg, look_up, mesh.cloud);
nr_points = data_end - data_beg;
}
else
{
points->SetDataTypeToDouble();
Vec3d *data_beg = vtkpoints_data<double>(points);
Vec3d *data_end = CopyImpl::copy(mesh.cloud, data_beg, look_up, mesh.cloud);
nr_points = data_end - data_beg;
}
vtkSmartPointer<vtkUnsignedCharArray> scalars;
if (!mesh.colors.empty())
{
Vec3b * colors_data = 0;
colors_data = new Vec3b[nr_points];
NanFilter::copyColor(mesh.colors, colors_data, mesh.cloud);
scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
scalars->SetNumberOfComponents(3);
scalars->SetNumberOfTuples(nr_points);
scalars->SetArray(colors_data->val, 3 * nr_points, 0);
}
points->SetNumberOfPoints(nr_points);
vtkSmartPointer<vtkPointSet> data;
if (mesh.polygons.size().area() > 1)
{
vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New();
const int * polygons = mesh.polygons.ptr<int>();
int idx = 0;
int poly_size = mesh.polygons.total();
for (int i = 0; i < poly_size; ++idx)
{
int n_points = polygons[i++];
cell_array->InsertNextCell(n_points);
for (int j = 0; j < n_points; ++j, ++idx)
cell_array->InsertCellPoint(look_up[polygons[i++]]);
}
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
cell_array->GetData()->SetNumberOfValues(idx);
cell_array->Squeeze();
polydata->SetStrips(cell_array);
polydata->SetPoints(points);
if (scalars)
polydata->GetPointData()->SetScalars(scalars);
data = polydata;
}
else
{
// Only one polygon
vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
const int * polygons = mesh.polygons.ptr<int>();
int n_points = polygons[0];
polygon->GetPointIds()->SetNumberOfIds(n_points);
for (int j = 1; j < n_points+1; ++j)
polygon->GetPointIds()->SetId(j, look_up[polygons[j]]);
vtkSmartPointer<vtkUnstructuredGrid> poly_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
poly_grid->Allocate(1, 1);
poly_grid->InsertNextCell(polygon->GetCellType(), polygon->GetPointIds());
poly_grid->SetPoints(points);
if (scalars)
poly_grid->GetPointData()->SetScalars(scalars);
data = poly_grid;
}
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
actor->GetProperty()->SetRepresentationToSurface();
actor->GetProperty()->BackfaceCullingOff(); // Backface culling is off for higher efficiency
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->EdgeVisibilityOff();
actor->GetProperty()->ShadingOff();
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::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);
}
template<> CV_EXPORTS cv::viz::WMesh cv::viz::Widget::cast<cv::viz::WMesh>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WMesh&>(widget);
}

@ -0,0 +1,441 @@
/*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"
///////////////////////////////////////////////////////////////////////////////////////////////
/// Point Cloud Widget implementation
cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors)
{
CV_Assert(!cloud.empty() && !colors.empty());
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New();
cloud_source->SetColorCloud(cloud, colors);
cloud_source->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, cloud_source->GetOutput());
mapper->SetScalarModeToUsePointData();
mapper->ImmediateModeRenderingOff();
mapper->SetScalarRange(0, 255);
mapper->ScalarVisibilityOn();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
}
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<cv::viz::WCloud>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WCloud&>(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Painted Cloud Widget implementation
cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud)
{
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New();
cloud_source->SetCloud(cloud);
cloud_source->Update();
Vec6d bounds(cloud_source->GetOutput()->GetPoints()->GetBounds());
vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::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<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput()));
mapper->ImmediateModeRenderingOff();
mapper->ScalarVisibilityOn();
mapper->SetColorModeToMapScalars();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::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)
{
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New();
cloud_source->SetCloud(cloud);
vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::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<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput()));
mapper->ImmediateModeRenderingOff();
mapper->ScalarVisibilityOn();
mapper->SetColorModeToMapScalars();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::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<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New();
cloud_source->SetCloud(cloud);
vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::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<vtkColorTransferFunction> color_transfer = vtkSmartPointer<vtkColorTransferFunction>::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<vtkPolyData> polydata = cloud_source->GetOutput();
//polydata->GetPointData()->SetScalars(color_transfer->MapScalars(float_scalars, VTK_COLOR_MODE_DEFAULT, 0));
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput()));
mapper->ImmediateModeRenderingOff();
mapper->ScalarVisibilityOn();
mapper->SetColorModeToMapScalars();
mapper->SetLookupTable(color_transfer);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
}
template<> cv::viz::WPaintedCloud cv::viz::Widget::cast<cv::viz::WPaintedCloud>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WPaintedCloud&>(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Cloud Collection Widget implementation
cv::viz::WCloudCollection::WCloudCollection()
{
// Just create the actor
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
WidgetAccessor::setProp(*this, actor);
}
void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, const Affine3d &pose)
{
vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New();
source->SetColorCloud(cloud, colors);
vtkSmartPointer<vtkPolyData> polydata = VtkUtils::TransformPolydata(source->GetOutputPort(), pose);
vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this));
CV_Assert("Incompatible widget type." && actor);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
if (!mapper)
{
// This is the first cloud
mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetScalarRange(0, 255);
mapper->SetScalarModeToUsePointData();
mapper->ScalarVisibilityOn();
mapper->ImmediateModeRenderingOff();
VtkUtils::SetInputData(mapper, polydata);
actor->SetNumberOfCloudPoints(std::max<vtkIdType>(1, polydata->GetNumberOfPoints()/10));
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper);
return;
}
vtkPolyData *currdata = vtkPolyData::SafeDownCast(mapper->GetInput());
CV_Assert("Cloud Widget without data" && currdata);
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
VtkUtils::AddInputData(append_filter, currdata);
VtkUtils::AddInputData(append_filter, polydata);
append_filter->Update();
VtkUtils::SetInputData(mapper, append_filter->GetOutput());
actor->SetNumberOfCloudPoints(std::max<vtkIdType>(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10));
}
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<cv::viz::WCloudCollection>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WCloudCollection&>(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Cloud Normals Widget implementation
cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, int level, double 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<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->SetDataType(cloud.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE);
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
int s_chs = cloud.channels();
int n_chs = normals.channels();
int total = 0;
for(int y = 0; y < cloud.rows; y += ystep)
{
if (cloud.depth() == CV_32F)
{
const float *srow = cloud.ptr<float>(y);
const float *send = srow + cloud.cols * s_chs;
const float *nrow = normals.ptr<float>(y);
for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs)
if (!isNan(srow) && !isNan(nrow))
{
Vec3f endp = Vec3f(srow) + Vec3f(nrow) * (float)scale;
points->InsertNextPoint(srow);
points->InsertNextPoint(endp.val);
lines->InsertNextCell(2);
lines->InsertCellPoint(total++);
lines->InsertCellPoint(total++);
}
}
else
{
const double *srow = cloud.ptr<double>(y);
const double *send = srow + cloud.cols * s_chs;
const double *nrow = normals.ptr<double>(y);
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<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(lines);
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
mapper->SetColorModeToMapScalars();
mapper->SetScalarModeToUsePointData();
VtkUtils::SetInputData(mapper, polyData);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WCloudNormals cv::viz::Widget::cast<cv::viz::WCloudNormals>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WCloudNormals&>(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Mesh Widget implementation
cv::viz::WMesh::WMesh(const Mesh &mesh)
{
CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1);
vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New();
source->SetColorCloudNormalsTCoords(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords);
source->Update();
Mat lookup_buffer(1, mesh.cloud.total(), CV_32SC1);
int *lookup = lookup_buffer.ptr<int>();
for(int y = 0, index = 0; y < mesh.cloud.rows; ++y)
{
int s_chs = mesh.cloud.channels();
if (mesh.cloud.depth() == CV_32F)
{
const float* srow = mesh.cloud.ptr<float>(y);
const float* send = srow + mesh.cloud.cols * s_chs;
for (; srow != send; srow += s_chs, ++lookup)
if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2]))
*lookup = index++;
}
if (mesh.cloud.depth() == CV_64F)
{
const double* srow = mesh.cloud.ptr<double>(y);
const double* send = srow + mesh.cloud.cols * s_chs;
for (; srow != send; srow += s_chs, ++lookup)
if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2]))
*lookup = index++;
}
}
lookup = lookup_buffer.ptr<int>();
vtkSmartPointer<vtkPolyData> polydata = source->GetOutput();
polydata->SetVerts(0);
const int * polygons = mesh.polygons.ptr<int>();
vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New();
int idx = 0;
size_t polygons_size = mesh.polygons.total();
for (size_t i = 0; i < polygons_size; ++idx)
{
int n_points = polygons[i++];
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<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetScalarModeToUsePointData();
mapper->ImmediateModeRenderingOff();
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::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();
actor->SetMapper(mapper);
if (!mesh.texture.empty())
{
vtkSmartPointer<vtkImageMatSource> image_source = vtkSmartPointer<vtkImageMatSource>::New();
image_source->SetImage(mesh.texture);
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(image_source->GetOutputPort());
actor->SetTexture(texture);
}
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<cv::viz::WMesh>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WMesh&>(widget);
}

@ -48,20 +48,21 @@
#include "precomp.hpp"
namespace cv { namespace viz
{
vtkStandardNewMacro(InteractorStyle)
}}
//////////////////////////////////////////////////////////////////////////////////////////////
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);
max_win_size_ = Vec2i(-1, -1);
// Create the image filter and PNG writer objects
wif_ = vtkSmartPointer<vtkWindowToImageFilter>::New();
snapshot_writer_ = vtkSmartPointer<vtkPNGWriter>::New();
snapshot_writer_->SetInputConnection(wif_->GetOutputPort());
init_ = true;
stereo_anaglyph_mask_default_ = true;
@ -78,11 +79,37 @@ 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<vtkWindowToImageFilter> wif = vtkSmartPointer<vtkWindowToImageFilter>::New();
wif->SetInput(Interactor->GetRenderWindow());
vtkSmartPointer<vtkPNGWriter> snapshot_writer = vtkSmartPointer<vtkPNGWriter>::New();
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<vtkExporter> exporter;
if (file.size() > 5 && file.substr(file.size() - 5) == ".vrml")
{
exporter = vtkSmartPointer<vtkVRMLExporter>::New();
vtkVRMLExporter::SafeDownCast(exporter)->SetFileName(file.c_str());
}
else
{
exporter = vtkSmartPointer<vtkOBJExporter>::New();
vtkOBJExporter::SafeDownCast(exporter)->SetFilePrefix(file.c_str());
}
exporter->SetInput(Interactor->GetRenderWindow());
exporter->Write();
cout << "Scene successfully exported (" << file.c_str() << ")" << endl;
}
//////////////////////////////////////////////////////////////////////////////////////////////
@ -121,13 +148,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())
{
@ -180,43 +201,32 @@ 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;
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()
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());
// 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 = Interactor->GetAltKey() != 0;
std::string key(Interactor->GetKeySym());
if (key.find("XF86ZoomIn") != std::string::npos)
@ -235,8 +245,10 @@ 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\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"
@ -249,7 +261,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;
}
@ -261,66 +273,41 @@ cv::viz::InteractorStyle::OnKeyDown()
for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); )
for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); )
{
vtkActor* apart = reinterpret_cast <vtkActor*>(path->GetLastNode()->GetViewProp());
vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp());
apart->GetProperty()->SetRepresentationToPoints();
}
break;
}
// Save a PNG snapshot with the current screen
case 'j': case 'J':
{
unsigned int t = static_cast<unsigned int>(time(0));
String png_file = cv::format("screenshot-%d.png", t);
String cam_file = cv::format("screenshot-%d.cam", t);
vtkSmartPointer<vtkCamera> 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();
// Save a PNG snapshot
case 'j': case 'J':
saveScreenshot(cv::format("screenshot-%d.png", (unsigned int)time(0))); break;
cout << "Screenshot (" << png_file.c_str() << ") and camera information (" << cam_file.c_str() << ") successfully captured." << endl;
// Export scene as in obj or vrml format
case 'k': case 'K':
{
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':
{
vtkSmartPointer<vtkCamera> cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera();
Vec2d clip;
Vec3d focal, pose, view;
cam->GetClippingRange(clip.val);
cam->GetFocalPoint(focal.val);
cam->GetPosition(pose.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;
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 '=':
@ -339,7 +326,7 @@ cv::viz::InteractorStyle::OnKeyDown()
for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); )
for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); )
{
vtkActor* apart = reinterpret_cast <vtkActor*>(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);
@ -358,7 +345,7 @@ cv::viz::InteractorStyle::OnKeyDown()
for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); )
for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); )
{
vtkActor* apart = static_cast<vtkActor*>(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);
@ -369,7 +356,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());
@ -397,13 +384,11 @@ 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<vtkAbstractPropPicker> picker = vtkAbstractPropPicker::SafeDownCast(Interactor->GetPicker());
if (picker)
if (picker->GetPath())
Interactor->FlyTo(CurrentRenderer, picker->GetPickPosition());
AnimState = VTKIS_ANIM_OFF;
}
break;
@ -411,24 +396,16 @@ 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)
vtkSmartPointer<vtkRenderWindow> 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 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_;
}
Interactor->GetRenderWindow()->SetStereoRender(!stereo_render);
Interactor->GetRenderWindow()->Render();
window->SetStereoRender(!window->GetStereoRender());
Interactor->Render();
}
else
@ -440,43 +417,34 @@ cv::viz::InteractorStyle::OnKeyDown()
{
vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera();
cam->SetParallelProjection(!cam->GetParallelProjection());
CurrentRenderer->SetActiveCamera(cam);
CurrentRenderer->Render();
break;
}
// Overwrite the camera reset
// Overwrite the camera reset
case 'r': case 'R':
{
if (!keymod)
if (!alt)
{
Superclass::OnKeyDown();
break;
}
vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera();
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<vtkCamera> 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())
{
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),
@ -516,23 +484,18 @@ cv::viz::InteractorStyle::OnKeyDown()
}
}
KeyboardEvent event(true, Interactor->GetKeySym(), Interactor->GetKeyCode(), getAltKey(), getControlKey(), getShiftKey());
// Check if there is a keyboard callback registered
KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers());
if (keyboardCallback_)
keyboardCallback_(event, keyboard_callback_cookie_);
renderer_->Render();
keyboardCallback_(event, keyboard_callback_cookie_);
Interactor->Render();
}
//////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::InteractorStyle::OnKeyUp()
{
KeyboardEvent event(false, Interactor->GetKeySym(), Interactor->GetKeyCode(), getAltKey(), getControlKey(), getShiftKey());
// Check if there is a keyboard callback registered
KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers());
if (keyboardCallback_)
keyboardCallback_(event, keyboard_callback_cookie_);
keyboardCallback_(event, keyboard_callback_cookie_);
Superclass::OnKeyUp();
}
@ -540,9 +503,9 @@ 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_);
mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnMouseMove();
}
@ -551,9 +514,9 @@ 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_);
mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnLeftButtonDown();
}
@ -561,9 +524,9 @@ 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_);
mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnLeftButtonUp();
}
@ -571,11 +534,10 @@ 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, getAltKey(), getControlKey(), getShiftKey());
MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers());
if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_);
mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnMiddleButtonDown();
}
@ -583,9 +545,9 @@ 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_);
mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnMiddleButtonUp();
}
@ -593,11 +555,10 @@ 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, getAltKey(), getControlKey(), getShiftKey());
MouseEvent event(type, MouseEvent::RightButton, p, getModifiers());
if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_);
mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnRightButtonDown();
}
@ -605,9 +566,9 @@ 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_);
mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnRightButtonUp();
}
@ -615,12 +576,11 @@ void cv::viz::InteractorStyle::OnRightButtonUp()
void cv::viz::InteractorStyle::OnMouseWheelForward()
{
Vec2i p(Interactor->GetEventPosition());
MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getAltKey(), getControlKey(), getShiftKey());
// If a mouse callback registered, call it!
MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers());
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())
{
@ -632,11 +592,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
@ -647,13 +605,12 @@ void cv::viz::InteractorStyle::OnMouseWheelForward()
void cv::viz::InteractorStyle::OnMouseWheelBackward()
{
Vec2i p(Interactor->GetEventPosition());
MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getAltKey(), getControlKey(), getShiftKey());
// If a mouse callback registered, call it!
MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers());
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())
{
@ -665,11 +622,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
@ -680,13 +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_);
renderer_->Render();
Interactor->Render();
}
namespace cv { namespace viz
{
//Standard VTK macro for *New()
vtkStandardNewMacro(InteractorStyle)
}}

@ -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__
@ -56,9 +53,6 @@ namespace cv
class InteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
enum KeyboardModifier { KB_MOD_ALT, KB_MOD_CTRL, KB_MOD_SHIFT };
static InteractorStyle *New();
virtual ~InteractorStyle() {}
@ -69,31 +63,21 @@ namespace cv
virtual void Initialize();
void setWidgetActorMap(const Ptr<WidgetActorMap>& actors) { widget_actor_map_ = actors; }
void setRenderer(vtkSmartPointer<vtkRenderer>& ren) { renderer_ = ren; }
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);
/** \brief Change the default keyboard modified from ALT to a different special key.*/
inline void setKeyboardModifier(const KeyboardModifier &modifier) { modifier_ = modifier; }
void exportScene(const String &file);
private:
/** \brief Set to true after initialization is complete. */
bool init_;
vtkSmartPointer<vtkRenderer> renderer_;
Ptr<WidgetActorMap> widget_actor_map_;
Vec2i win_size_;
Vec2i win_pos_;
Vec2i max_win_size_;
/** \brief A PNG writer for screenshot captures. */
vtkSmartPointer<vtkPNGWriter> snapshot_writer_;
/** \brief Internal window to image filter. Needed by \a snapshot_writer_. */
vtkSmartPointer<vtkWindowToImageFilter> wif_;
/** \brief Interactor style internal method. Gets called whenever a key is pressed. */
virtual void OnChar();
@ -121,17 +105,13 @@ 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_;
void (*mouseCallback_)(const MouseEvent&, void*);
void *mouse_callback_cookie_;
bool getAltKey();
bool getControlKey();
bool getShiftKey();
int getModifiers();
};
}
}

@ -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__
@ -53,6 +50,8 @@
#include <ctime>
#include <list>
#include <vector>
#include <iomanip>
#include <limits>
#include <vtkAppendPolyData.h>
#include <vtkAssemblyPath.h>
@ -94,13 +93,13 @@
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkProperty.h>
#include <vtkCamera.h>
#include <vtkObjectFactory.h>
#include <vtkPlanes.h>
#include <vtkImageFlip.h>
#include <vtkRenderWindow.h>
#include <vtkTextProperty.h>
#include <vtkProperty2D.h>
#include <vtkLODActor.h>
#include <vtkActor.h>
#include <vtkTextActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkMath.h>
@ -110,12 +109,50 @@
#include <vtkPolyDataNormals.h>
#include <vtkAlgorithmOutput.h>
#include <vtkImageMapper.h>
#include <vtkPoints.h>
#include <vtkInformation.h>
#include <vtkInformationVector.h>
#include <vtkObjectFactory.h>
#include <vtkPolyDataAlgorithm.h>
#include <vtkMergeFilter.h>
#include <vtkDataSetWriter.h>
#include <vtkErrorCode.h>
#include <vtkPLYWriter.h>
#include <vtkSTLWriter.h>
#include <vtkSimplePointsReader.h>
#include <vtkPLYReader.h>
#include <vtkOBJReader.h>
#include <vtkSTLReader.h>
#include <vtkPNGReader.h>
#include <vtkOBJExporter.h>
#include <vtkVRMLExporter.h>
#include <vtkTensorGlyph.h>
#include <vtkImageAlgorithm.h>
#include <vtkTransformFilter.h>
#include <vtkConeSource.h>
#include <vtkElevationFilter.h>
#include <vtkColorTransferFunction.h>
#include <vtkStreamingDemandDrivenPipeline.h>
#if !defined(_WIN32) || defined(__CYGWIN__)
# include <unistd.h> /* unlink */
#else
# include <io.h> /* unlink */
#endif
#include <vtk/vtkOBJWriter.h>
#include <vtk/vtkXYZWriter.h>
#include <vtk/vtkCloudMatSink.h>
#include <vtk/vtkCloudMatSource.h>
#include <vtk/vtkTrajectorySource.h>
#include <vtk/vtkImageMatSource.h>
#include <opencv2/core.hpp>
#include <opencv2/viz.hpp>
#include <opencv2/viz/widget_accessor.hpp>
#include <opencv2/core/utility.hpp>
namespace cv
{
namespace viz
@ -144,11 +181,145 @@ namespace cv
static VizMap storage;
friend class Viz3d;
};
template<typename _Tp> inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); }
template<typename _Tp> inline bool isNan(const _Tp* data)
{
return isNan(data[0]) || isNan(data[1]) || isNan(data[2]);
}
inline vtkSmartPointer<vtkActor> getActor(const Widget3D& widget)
{
return vtkActor::SafeDownCast(WidgetAccessor::getProp(widget));
}
inline vtkSmartPointer<vtkPolyData> getPolyData(const Widget3D& widget)
{
vtkSmartPointer<vtkMapper> mapper = getActor(widget)->GetMapper();
return vtkPolyData::SafeDownCast(mapper->GetInput());
}
inline vtkSmartPointer<vtkMatrix4x4> vtkmatrix(const cv::Matx44d &matrix)
{
vtkSmartPointer<vtkMatrix4x4> vtk_matrix = vtkSmartPointer<vtkMatrix4x4>::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;
}
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<class Filter>
static void SetInputData(vtkSmartPointer<Filter> filter, vtkPolyData* polydata)
{
#if VTK_MAJOR_VERSION <= 5
filter->SetInput(polydata);
#else
filter->SetInputData(polydata);
#endif
}
template<class Filter>
static void SetSourceData(vtkSmartPointer<Filter> filter, vtkPolyData* polydata)
{
#if VTK_MAJOR_VERSION <= 5
filter->SetSource(polydata);
#else
filter->SetSourceData(polydata);
#endif
}
template<class Filter>
static void SetInputData(vtkSmartPointer<Filter> filter, vtkImageData* polydata)
{
#if VTK_MAJOR_VERSION <= 5
filter->SetInput(polydata);
#else
filter->SetInputData(polydata);
#endif
}
template<class Filter>
static void AddInputData(vtkSmartPointer<Filter> filter, vtkPolyData *polydata)
{
#if VTK_MAJOR_VERSION <= 5
filter->AddInput(polydata);
#else
filter->AddInputData(polydata);
#endif
}
static vtkSmartPointer<vtkUnsignedCharArray> 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<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
scalars->SetName("Colors");
scalars->SetNumberOfComponents(3);
scalars->SetNumberOfTuples(size);
scalars->SetArray(color_data->val, size * 3, 0);
return scalars;
}
static vtkSmartPointer<vtkPolyData> ComputeNormals(vtkSmartPointer<vtkPolyData> polydata)
{
vtkSmartPointer<vtkPolyDataNormals> normals_generator = vtkSmartPointer<vtkPolyDataNormals>::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();
}
static vtkSmartPointer<vtkPolyData> TransformPolydata(vtkSmartPointer<vtkAlgorithmOutput> algorithm_output_port, const Affine3d& pose)
{
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->SetMatrix(vtkmatrix(pose.matrix));
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transform_filter->SetTransform(transform);
transform_filter->SetInputConnection(algorithm_output_port);
transform_filter->Update();
return transform_filter->GetOutput();
}
static vtkSmartPointer<vtkPolyData> TransformPolydata(vtkSmartPointer<vtkPolyData> polydata, const Affine3d& pose)
{
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->SetMatrix(vtkmatrix(pose.matrix));
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
VtkUtils::SetInputData(transform_filter, polydata);
transform_filter->SetTransform(transform);
transform_filter->Update();
return transform_filter->GetOutput();
}
};
}
}
#include "interactor_style.hpp"
#include "viz3d_impl.hpp"
#include "vizimpl.hpp"
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -41,138 +41,63 @@
// * 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"
////////////////////////////////////////////////////////////////////
/// cv::viz::KeyboardEvent
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;
/// Events
if (ctrl)
modifiers_ |= Ctrl;
if (shift)
modifiers_ |= Shift;
}
cv::viz::KeyboardEvent::KeyboardEvent(Action _action, const String& _symbol, unsigned char _code, int _modifiers)
: action(_action), symbol(_symbol), code(_code), modifiers(_modifiers) {}
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;
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
struct cv::viz::Mesh3d::loadMeshImpl
cv::viz::Mesh cv::viz::Mesh::load(const String& file)
{
static cv::viz::Mesh3d loadMesh(const String &file)
vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();
reader->SetFileName(file.c_str());
reader->Update();
vtkSmartPointer<vtkPolyData> polydata = reader->GetOutput();
CV_Assert("File does not exist or file format is not supported." && polydata);
Mesh mesh;
vtkSmartPointer<vtkCloudMatSink> sink = vtkSmartPointer<vtkCloudMatSink>::New();
sink->SetOutput(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords);
sink->SetInputConnection(reader->GetOutputPort());
sink->Write();
// Now handle the polygons
vtkSmartPointer<vtkCellArray> polygons = polydata->GetPolys();
mesh.polygons.create(1, polygons->GetSize(), CV_32SC1);
int* poly_ptr = mesh.polygons.ptr<int>();
polygons->InitTraversal();
vtkIdType nr_cell_points, *cell_points;
while (polygons->GetNextCell(nr_cell_points, cell_points))
{
Mesh3d mesh;
vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();
reader->SetFileName(file.c_str());
reader->Update();
vtkSmartPointer<vtkPolyData> poly_data = reader->GetOutput();
CV_Assert("File does not exist or file format is not supported." && poly_data);
vtkSmartPointer<vtkPoints> 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<Vec3f>();
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<cv::Vec3b>();
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<int>();
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<int>(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::Mesh3d cv::viz::Mesh3d::loadMesh(const String& file)
{
return loadMeshImpl::loadMesh(file);
return mesh;
}
////////////////////////////////////////////////////////////////////
/// 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(double fx, double fy, double cx, double 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)
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
@ -183,16 +108,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);
@ -205,34 +130,32 @@ 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<float>(window_size.width) * 0.5f;
else principal_point_[0] = (left * static_cast<float>(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<float>(window_size.height) * 0.5f;
else principal_point_[1] = (top * static_cast<float>(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 f_x, float f_y, float c_x, float c_y, 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(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;
}
@ -254,7 +177,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];
@ -278,13 +201,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;
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);
}

@ -1,165 +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
//
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/
#include "precomp.hpp"
cv::Affine3f cv::viz::makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin)
{
Affine3f::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);
}
cv::Affine3f cv::viz::makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& 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);
return makeTransformToGlobal(u, v, n, position);
}
vtkSmartPointer<vtkMatrix4x4> cv::viz::convertToVtkMatrix(const cv::Matx44f &m)
{
vtkSmartPointer<vtkMatrix4x4> vtk_matrix = vtkSmartPointer<vtkMatrix4x4>::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<vtkMatrix4x4>& 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<typename _Tp> Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer<vtkPoints>& points);
template<> Vec3f* vtkpoints_data<float>(vtkSmartPointer<vtkPoints>& points)
{
CV_Assert(points->GetDataType() == VTK_FLOAT);
vtkDataArray *data = points->GetData();
float *pointer = static_cast<vtkFloatArray*>(data)->GetPointer(0);
return reinterpret_cast<Vec3f*>(pointer);
}
template<> Vec3d* vtkpoints_data<double>(vtkSmartPointer<vtkPoints>& points)
{
CV_Assert(points->GetDataType() == VTK_DOUBLE);
vtkDataArray *data = points->GetData();
double *pointer = static_cast<vtkDoubleArray*>(data)->GetPointer(0);
return reinterpret_cast<Vec3d*>(pointer);
}
}}
///////////////////////////////////////////////////////////////////////////////////////////////
/// VizStorage implementation
cv::viz::VizMap cv::viz::VizStorage::storage;
void cv::viz::VizStorage::unregisterAll() { storage.clear(); }
cv::viz::Viz3d& cv::viz::VizStorage::get(const String &window_name)
{
String name = generateWindowName(window_name);
VizMap::iterator vm_itr = storage.find(name);
CV_Assert(vm_itr != storage.end());
return vm_itr->second;
}
void cv::viz::VizStorage::add(const Viz3d& window)
{
String window_name = window.getWindowName();
VizMap::iterator vm_itr = storage.find(window_name);
CV_Assert(vm_itr == storage.end());
storage.insert(std::make_pair(window_name, window));
}
bool cv::viz::VizStorage::windowExists(const String &window_name)
{
String name = generateWindowName(window_name);
return storage.find(name) != storage.end();
}
void cv::viz::VizStorage::removeUnreferenced()
{
for(VizMap::iterator pos = storage.begin(); pos != storage.end();)
if(pos->second.impl_->ref_counter == 1)
storage.erase(pos++);
else
++pos;
}
cv::String cv::viz::VizStorage::generateWindowName(const String &window_name)
{
String output = "Viz";
// Already is Viz
if (window_name == output)
return output;
String prefixed = output + " - ";
if (window_name.substr(0, prefixed.length()) == prefixed)
output = window_name; // Already has "Viz - "
else if (window_name.substr(0, output.length()) == output)
output = prefixed + window_name; // Doesn't have prefix
else
output = (window_name == "" ? output : prefixed + window_name);
return output;
}
cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); }
void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); }

@ -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"
@ -104,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); }
@ -111,18 +109,21 @@ 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::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); }
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(); }
@ -131,17 +132,17 @@ 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); }
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(); }
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); }

@ -1,368 +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
//
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/
#ifndef __OPENCV_VIZ_VIZ3D_IMPL_HPP__
#define __OPENCV_VIZ_VIZ3D_IMPL_HPP__
struct cv::viz::Viz3d::VizImpl
{
public:
typedef Viz3d::KeyboardCallback KeyboardCallback;
typedef Viz3d::MouseCallback MouseCallback;
int ref_counter;
VizImpl(const String &name);
virtual ~VizImpl();
void showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::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 setDesiredUpdateRate(double rate);
double getDesiredUpdateRate();
/** \brief Returns true when the user tried to close the window */
bool wasStopped() const { if (interactor_ != NULL) return (stopped_); else return true; }
/** \brief Set the stopped flag back to false */
void resetStoppedFlag() { if (interactor_ != NULL) 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);
Camera getCamera() const;
/** \brief Reset the camera to a given widget */
void resetCameraViewpoint(const String& id);
void resetCamera();
void setViewerPose(const Affine3f &pose);
Affine3f getViewerPose();
void convertToWindowCoordinates(const Point3d &pt, Point3d &window_coord);
void converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction);
void saveScreenshot(const String &file);
void setWindowPosition(int x, int y);
Size getWindowSize() const;
void setWindowSize(int xw, int yw);
void setFullScreen(bool mode);
String getWindowName() const;
void setBackgroundColor(const Color& color);
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<vtkRenderWindowInteractor> interactor_;
struct ExitMainLoopTimerCallback : 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<int*>(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_;
};
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_;
};
/** \brief Set to false if the interaction loop is running. */
bool stopped_;
double s_lastDone_;
/** \brief Global timer ID. Used in destructor only. */
int timer_id_;
/** \brief Callback object enabling us to leave the main loop, when a timer fires. */
vtkSmartPointer<ExitMainLoopTimerCallback> exit_main_loop_timer_callback_;
vtkSmartPointer<ExitCallback> exit_callback_;
vtkSmartPointer<vtkRenderer> renderer_;
vtkSmartPointer<vtkRenderWindow> window_;
/** \brief The render window interactor style. */
vtkSmartPointer<InteractorStyle> style_;
/** \brief Internal list with actor pointers and name IDs for all widget actors */
cv::Ptr<WidgetActorMap> widget_actor_map_;
/** \brief Boolean that holds whether or not the camera parameters were manually initialized*/
bool camera_set_;
bool removeActorFromRenderer(const vtkSmartPointer<vtkProp> &actor);
};
namespace cv
{
namespace viz
{
vtkSmartPointer<vtkMatrix4x4> convertToVtkMatrix(const cv::Matx44f &m);
cv::Matx44f convertToMatx(const vtkSmartPointer<vtkMatrix4x4>& vtk_matrix);
struct NanFilter
{
template<typename _Tp, typename _Msk>
struct Impl
{
typedef Vec<_Tp, 3> _Out;
static _Out* copy(const Mat& source, _Out* 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++ = _Out(srow);
}
return output;
}
static _Out* copyColor(const Mat& source, _Out* 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 = _Out(srow);
std::swap((*output)[0], (*output)[2]); // BGR -> RGB
++output;
}
}
return output;
}
};
template<typename _Tp>
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<_Tp, float>::copy, &NanFilter::Impl<_Tp, double>::copy };
return table[nan_mask.depth() - 5](source, output, nan_mask);
}
template<typename _Tp>
static inline Vec<_Tp, 3>* copyColor(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<_Tp, float>::copyColor, &NanFilter::Impl<_Tp, double>::copyColor };
return table[nan_mask.depth() - 5](source, output, nan_mask);
}
};
struct ApplyAffine
{
const Affine3f& affine_;
ApplyAffine(const Affine3f& affine) : affine_(affine) {}
template<typename _Tp> Point3_<_Tp> operator()(const Point3_<_Tp>& p) const { return affine_ * p; }
template<typename _Tp> 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&);
};
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<typename _Tp> inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); }
struct ConvertToVtkImage
{
struct Impl
{
static void copyImageMultiChannel(const Mat &image, vtkSmartPointer<vtkImageData> output)
{
int i_chs = image.channels();
for (int i = 0; i < image.rows; ++i)
{
const unsigned char * irows = image.ptr<unsigned char>(i);
for (int j = 0; j < image.cols; ++j, irows += i_chs)
{
unsigned char * vrows = static_cast<unsigned char *>(output->GetScalarPointer(j,i,0));
memcpy(vrows, irows, i_chs);
std::swap(vrows[0], vrows[2]); // BGR -> RGB
}
}
output->Modified();
}
static void copyImageSingleChannel(const Mat &image, vtkSmartPointer<vtkImageData> output)
{
for (int i = 0; i < image.rows; ++i)
{
const unsigned char * irows = image.ptr<unsigned char>(i);
for (int j = 0; j < image.cols; ++j, ++irows)
{
unsigned char * vrows = static_cast<unsigned char *>(output->GetScalarPointer(j,i,0));
*vrows = *irows;
}
}
output->Modified();
}
};
static void convert(const Mat &image, vtkSmartPointer<vtkImageData> 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
int i_chs = image.channels();
if (i_chs > 1)
{
// Multi channel images are handled differently because of BGR <-> RGB
Impl::copyImageMultiChannel(image, output);
}
else
{
Impl::copyImageSingleChannel(image, output);
}
}
};
}
}
#endif

@ -0,0 +1,312 @@
/*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"
cv::Affine3d cv::viz::makeTransformToGlobal(const Vec3d& axis_x, const Vec3d& axis_y, const Vec3d& axis_z, const Vec3d& origin)
{
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 Affine3d(R, origin);
}
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
Vec3d n = normalize(focal_point - position);
Vec3d u = normalize(y_dir.cross(n));
Vec3d v = n.cross(u);
return makeTransformToGlobal(u, v, n, position);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// VizStorage implementation
cv::viz::VizMap cv::viz::VizStorage::storage;
void cv::viz::VizStorage::unregisterAll() { storage.clear(); }
cv::viz::Viz3d& cv::viz::VizStorage::get(const String &window_name)
{
String name = generateWindowName(window_name);
VizMap::iterator vm_itr = storage.find(name);
CV_Assert(vm_itr != storage.end());
return vm_itr->second;
}
void cv::viz::VizStorage::add(const Viz3d& window)
{
String window_name = window.getWindowName();
VizMap::iterator vm_itr = storage.find(window_name);
CV_Assert(vm_itr == storage.end());
storage.insert(std::make_pair(window_name, window));
}
bool cv::viz::VizStorage::windowExists(const String &window_name)
{
String name = generateWindowName(window_name);
return storage.find(name) != storage.end();
}
void cv::viz::VizStorage::removeUnreferenced()
{
for(VizMap::iterator pos = storage.begin(); pos != storage.end();)
if(pos->second.impl_->ref_counter == 1)
storage.erase(pos++);
else
++pos;
}
cv::String cv::viz::VizStorage::generateWindowName(const String &window_name)
{
String output = "Viz";
// Already is Viz
if (window_name == output)
return output;
String prefixed = output + " - ";
if (window_name.substr(0, prefixed.length()) == prefixed)
output = window_name; // Already has "Viz - "
else if (window_name.substr(0, output.length()) == output)
output = prefixed + window_name; // Doesn't have prefix
else
output = (window_name == "" ? output : prefixed + window_name);
return output;
}
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
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);
vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New();
source->SetColorCloudNormals(cloud, colors, normals);
vtkSmartPointer<vtkWriter> writer;
if (extention == ".xyz")
{
writer = vtkSmartPointer<vtkXYZWriter>::New();
vtkXYZWriter::SafeDownCast(writer)->SetFileName(file.c_str());
}
else if (extention == ".ply")
{
writer = vtkSmartPointer<vtkPLYWriter>::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<vtkOBJWriter>::New();
vtkOBJWriter::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, OutputArray normals)
{
CV_Assert(file.size() > 4 && "Extention is required");
String extention = file.substr(file.size()-4);
vtkSmartPointer<vtkPolyDataAlgorithm> reader;
if (extention == ".xyz")
{
reader = vtkSmartPointer<vtkSimplePointsReader>::New();
vtkSimplePointsReader::SafeDownCast(reader)->SetFileName(file.c_str());
}
else if (extention == ".ply")
{
reader = vtkSmartPointer<vtkPLYReader>::New();
CV_Assert(vtkPLYReader::CanReadFile(file.c_str()));
vtkPLYReader::SafeDownCast(reader)->SetFileName(file.c_str());
}
else if (extention == ".obj")
{
reader = vtkSmartPointer<vtkOBJReader>::New();
vtkOBJReader::SafeDownCast(reader)->SetFileName(file.c_str());
}
else if (extention == ".stl")
{
reader = vtkSmartPointer<vtkSTLReader>::New();
vtkSTLReader::SafeDownCast(reader)->SetFileName(file.c_str());
}
else
CV_Assert(!"Unsupported format");
cv::Mat cloud;
vtkSmartPointer<vtkCloudMatSink> sink = vtkSmartPointer<vtkCloudMatSink>::New();
sink->SetInputConnection(reader->GetOutputPort());
sink->SetOutput(cloud, colors, normals);
sink->Write();
return cloud;
}
cv::viz::Mesh cv::viz::readMesh(const String& file) { return Mesh::load(file); }
///////////////////////////////////////////////////////////////////////////////////////////////
/// Read/write poses and trajectories
bool cv::viz::readPose(const String& file, Affine3d& pose, const String& tag)
{
FileStorage fs(file, FileStorage::READ);
if (!fs.isOpened())
return false;
Mat hdr(pose.matrix, false);
fs[tag] >> hdr;
if (hdr.empty() || hdr.cols != pose.matrix.cols || hdr.rows != pose.matrix.rows)
return 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);
}
void cv::viz::readTrajectory(OutputArray _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<Affine3d> traj;
for(int i = start; i < end; ++i)
{
Affine3d affine;
bool ok = readPose(cv::format(files_format.c_str(), i), affine, tag);
if (!ok)
break;
traj.push_back(affine);
}
Mat(traj).convertTo(_traj, _traj.depth());
}
void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int start, const String& tag)
{
if (_traj.kind() == _InputArray::STD_VECTOR_MAT)
{
std::vector<Mat>& v = *(std::vector<Mat>*)_traj.getObj();
for(size_t i = 0, index = max(0, start); i < v.size(); ++i, ++index)
{
Affine3d 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);
}
return;
}
if (_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();
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<Affine3f>(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<Affine3d>(i), tag);
}
CV_Assert(!"Unsupported array kind");
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Computing normals for mesh
void cv::viz::computeNormals(const Mesh& mesh, OutputArray _normals)
{
vtkSmartPointer<vtkPolyData> polydata = getPolyData(WMesh(mesh));
vtkSmartPointer<vtkPolyData> with_normals = VtkUtils::ComputeNormals(polydata);
vtkSmartPointer<vtkDataArray> generic_normals = with_normals->GetPointData()->GetNormals();
if(generic_normals)
{
Mat normals(1, generic_normals->GetNumberOfTuples(), CV_64FC3);
Vec3d *optr = normals.ptr<Vec3d>();
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();
}

@ -41,94 +41,143 @@
// * 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"
vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew();
#if 1 || !defined __APPLE__
vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew()
{
return vtkRenderWindowInteractor::New();
}
#endif
/////////////////////////////////////////////////////////////////////////////////////////////
cv::viz::Viz3d::VizImpl::VizImpl(const String &name)
: s_lastDone_(0.0), style_(vtkSmartPointer<cv::viz::InteractorStyle>::New()), widget_actor_map_(new WidgetActorMap)
cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false),
window_position_(Vec2i(std::numeric_limits<int>::min())), widget_actor_map_(new WidgetActorMap)
{
renderer_ = vtkSmartPointer<vtkRenderer>::New();
window_name_ = VizStorage::generateWindowName(name);
// Create a RendererWindow
// Create render window
window_ = vtkSmartPointer<vtkRenderWindow>::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
style_->Initialize();
style_->setRenderer(renderer_);
style_ = vtkSmartPointer<InteractorStyle>::New();
style_->setWidgetActorMap(widget_actor_map_);
style_->UseTimersOn();
style_->Initialize();
/////////////////////////////////////////////////
interactor_ = vtkSmartPointer<vtkRenderWindowInteractor>::Take(vtkRenderWindowInteractorFixNew());
timer_callback_ = vtkSmartPointer<TimerCallback>::New();
exit_callback_ = vtkSmartPointer<ExitCallback>::New();
exit_callback_->viz = this;
}
window_->AlphaBitPlanesOff();
window_->PointSmoothingOff();
window_->LineSmoothingOff();
window_->PolygonSmoothingOff();
window_->SwapBuffersOn();
window_->SetStereoTypeToAnaglyph();
/////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::TimerCallback::Execute(vtkObject* caller, unsigned long event_id, void* cookie)
{
if (event_id == vtkCommand::TimerEvent && timer_id == *reinterpret_cast<int*>(cookie))
{
vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkRenderWindowInteractor::SafeDownCast(caller);
interactor->TerminateApp();
}
}
interactor_->SetRenderWindow(window_);
interactor_->SetInteractorStyle(style_);
interactor_->SetDesiredUpdateRate(30.0);
void cv::viz::Viz3d::VizImpl::ExitCallback::Execute(vtkObject*, unsigned long event_id, void*)
{
if (event_id == vtkCommand::ExitEvent)
{
viz->interactor_->TerminateApp();
viz->interactor_ = 0;
}
}
// Initialize and create timer, also create window
interactor_->Initialize();
timer_id_ = interactor_->CreateRepeatingTimer(5000L);
/////////////////////////////////////////////////////////////////////////////////////////////
// Set a simple PointPicker
//vtkSmartPointer<vtkPointPicker> pp = vtkSmartPointer<vtkPointPicker>::New();
//pp->SetTolerance(pp->GetTolerance() * 2);
//interactor_->SetPicker(pp);
bool cv::viz::Viz3d::VizImpl::wasStopped() const
{
bool stopped = spin_once_state_ ? interactor_ == 0 : false;
spin_once_state_ &= !stopped;
return stopped;
}
exit_main_loop_timer_callback_ = vtkSmartPointer<ExitMainLoopTimerCallback>::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::close()
{
if (!interactor_)
return;
interactor_->GetRenderWindow()->Finalize();
interactor_->TerminateApp(); // This tends to close the window...
interactor_ = 0;
}
exit_callback_ = vtkSmartPointer<ExitCallback>::New();
exit_callback_->viz_ = this;
interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_);
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();
window_ = vtkSmartPointer<vtkRenderWindow>::New();
if (window_position_[0] != std::numeric_limits<int>::min()) //also workaround
window_->SetPosition(window_position_.val);
resetStoppedFlag();
window_->SetSize(window_size.val);
window_->SetFullScreen(fullscreen);
window_->AddRenderer(renderer_);
#endif
}
//////////////////////////////
String window_name = VizStorage::generateWindowName(name);
window_->SetWindowName(window_name.c_str());
/////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::spin()
{
recreateRenderWindow();
interactor_ = vtkSmartPointer<vtkRenderWindowInteractor>::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();
interactor_ = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////
cv::viz::Viz3d::VizImpl::~VizImpl()
void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw)
{
if (interactor_)
interactor_->DestroyTimer(timer_id_);
if (renderer_)
renderer_->Clear();
if (interactor_ == 0)
{
spin_once_state_ = true;
recreateRenderWindow();
interactor_ = vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor_->SetRenderWindow(window_);
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());
}
vtkSmartPointer<vtkRenderWindowInteractor> local = interactor_;
if (force_redraw)
local->Render();
timer_callback_->timer_id = local->CreateRepeatingTimer(std::max(1, time));
local->Start();
local->DestroyTimer(timer_callback_->timer_id);
}
/////////////////////////////////////////////////////////////////////////////////////////////
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();
@ -142,7 +191,7 @@ void cv::viz::Viz3d::VizImpl::showWidget(const String &id, const Widget &widget,
if (actor)
{
// If the actor is 3D, apply pose
vtkSmartPointer<vtkMatrix4x4> matrix = convertToVtkMatrix(pose.matrix);
vtkSmartPointer<vtkMatrix4x4> matrix = vtkmatrix(pose.matrix);
actor->SetUserMatrix(matrix);
actor->Modified();
}
@ -180,7 +229,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();
@ -189,13 +238,13 @@ void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3f &po
vtkProp3D *actor = vtkProp3D::SafeDownCast(wam_itr->second);
CV_Assert("Widget is not 3D." && actor);
vtkSmartPointer<vtkMatrix4x4> matrix = convertToVtkMatrix(pose.matrix);
vtkSmartPointer<vtkMatrix4x4> matrix = vtkmatrix(pose.matrix);
actor->SetUserMatrix(matrix);
actor->Modified();
}
/////////////////////////////////////////////////////////////////////////////////////////////
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();
@ -210,16 +259,15 @@ 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);
matrix = convertToVtkMatrix(updated_pose.matrix);
Affine3d updated_pose = pose * Affine3d(*matrix->Element);
matrix = vtkmatrix(updated_pose.matrix);
actor->SetUserMatrix(matrix);
actor->Modified();
}
/////////////////////////////////////////////////////////////////////////////////////////////
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();
@ -228,24 +276,7 @@ cv::Affine3f cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const
vtkProp3D *actor = vtkProp3D::SafeDownCast(wam_itr->second);
CV_Assert("Widget is not 3D." && actor);
vtkSmartPointer<vtkMatrix4x4> matrix = actor->GetUserMatrix();
Matx44f matrix_cv = convertToMatx(matrix);
return Affine3f(matrix_cv);
}
/////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::setDesiredUpdateRate(double rate)
{
if (interactor_)
interactor_->SetDesiredUpdateRate(rate);
}
/////////////////////////////////////////////////////////////////////////////////////////////
double cv::viz::Viz3d::VizImpl::getDesiredUpdateRate()
{
if (interactor_)
return interactor_->GetDesiredUpdateRate();
return 0.0;
return Affine3d(*actor->GetUserMatrix()->Element);
}
/////////////////////////////////////////////////////////////////////////////////////////////
@ -258,37 +289,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()
@ -296,50 +296,98 @@ void cv::viz::Viz3d::VizImpl::removeAllWidgets()
widget_actor_map_->clear();
renderer_->RemoveAllViewProps();
}
/////////////////////////////////////////////////////////////////////////////////////////////
bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(const vtkSmartPointer<vtkProp> &actor)
void cv::viz::Viz3d::VizImpl::showImage(InputArray image, const Size& window_size)
{
vtkProp* actor_to_remove = vtkProp::SafeDownCast(actor);
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<vtkProp> actor)
{
vtkPropCollection* actors = renderer_->GetViewProps();
actors->InitTraversal();
vtkProp* current_actor = NULL;
while ((current_actor = actors->GetNextProp()) != NULL)
if (current_actor == actor)
{
renderer_->RemoveActor(actor);
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color, const Color& color2)
{
Color c = vtkcolor(color), c2 = vtkcolor(color2);
bool gradient = color2[0] >= 0 && color2[1] >= 0 && color2[2] >= 0;
if (gradient)
{
if (current_actor != actor_to_remove)
continue;
renderer_->RemoveActor(actor);
return true;
renderer_->SetBackground(c2.val);
renderer_->SetBackground2(c.val);
renderer_->GradientBackgroundOn();
}
else
{
renderer_->SetBackground(c.val);
renderer_->GradientBackgroundOff();
}
return false;
}
void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab()
{ setBackgroundColor(Color(2, 1, 1), Color(240, 120, 120)); }
//////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color)
void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image)
{
Color c = vtkcolor(color);
renderer_->SetBackground(c.val);
if (image.empty())
{
renderer_->SetBackgroundTexture(0);
renderer_->TexturedBackgroundOff();
return;
}
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
source->SetImage(image);
vtkSmartPointer<vtkImageFlip> image_flip = vtkSmartPointer<vtkImageFlip>::New();
image_flip->SetFilteredAxis(1); // Vertical flip
image_flip->SetInputConnection(source->GetOutputPort());
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(image_flip->GetOutputPort());
//texture->Update();
renderer_->SetBackgroundTexture(texture);
renderer_->TexturedBackgroundOn();
}
/////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera)
{
vtkCamera& active_camera = *renderer_->GetActiveCamera();
vtkSmartPointer<vtkCamera> active_camera = renderer_->GetActiveCamera();
// Set the intrinsic parameters of the camera
window_->SetSize(camera.getWindowSize().width, camera.getWindowSize().height);
double aspect_ratio = static_cast<double>(camera.getWindowSize().width)/static_cast<double>(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<vtkMatrix4x4> 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<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->SetMatrix(vtkmatrix(proj_mat * old_proj_mat.inv()));
active_camera->SetUserTransform(transform);
renderer_->ResetCameraClippingRange();
renderer_->Render();
@ -348,44 +396,42 @@ void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera)
/////////////////////////////////////////////////////////////////////////////////////////////
cv::viz::Camera cv::viz::Viz3d::VizImpl::getCamera() const
{
vtkCamera& active_camera = *renderer_->GetActiveCamera();
vtkSmartPointer<vtkCamera> 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<vtkMatrix4x4> proj_matrix = active_camera->GetProjectionTransformMatrix(aspect_ratio, -1.0f, 1.0f);
return Camera(Matx44d(*proj_matrix->Element), window_size);
}
/////////////////////////////////////////////////////////////////////////////////////////////
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();
@ -397,20 +443,7 @@ cv::Affine3f 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::Affine3f(R, pos);
return makeTransformToGlobal(x_axis, y_axis, z_axis, pos);
}
/////////////////////////////////////////////////////////////////////////////////////////////
@ -426,10 +459,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);
}
@ -504,21 +534,9 @@ 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() : "");
}
//////////////////////////////////////////////////////////////////////////////////////////////
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); }
cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); }
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_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()))); }

@ -0,0 +1,138 @@
/*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*/
#ifndef __OPENCV_VIZ_VIZ3D_IMPL_HPP__
#define __OPENCV_VIZ_VIZ3D_IMPL_HPP__
struct cv::viz::Viz3d::VizImpl
{
public:
typedef Viz3d::KeyboardCallback KeyboardCallback;
typedef Viz3d::MouseCallback MouseCallback;
int ref_counter;
VizImpl(const String &name);
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);
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;
void setRepresentation(int representation);
void setCamera(const Camera &camera);
Camera getCamera() const;
/** \brief Reset the camera to a given widget */
void resetCameraViewpoint(const String& id);
void resetCamera();
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);
void saveScreenshot(const String &file);
void setWindowPosition(const Point& position);
Size getWindowSize() const;
void setWindowSize(const Size& window_size);
void setFullScreen(bool mode);
String getWindowName() const;
void setBackgroundColor(const Color& color, const Color& color2);
void setBackgroundTexture(InputArray image);
void setBackgroundMeshLab();
void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0);
void registerMouseCallback(MouseCallback callback, void* cookie = 0);
private:
struct TimerCallback : public vtkCommand
{
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*);
VizImpl* viz;
};
mutable bool spin_once_state_;
vtkSmartPointer<vtkRenderWindowInteractor> interactor_;
vtkSmartPointer<vtkRenderWindow> window_;
String window_name_;
Vec2i window_position_;
vtkSmartPointer<TimerCallback> timer_callback_;
vtkSmartPointer<ExitCallback> exit_callback_;
vtkSmartPointer<vtkRenderer> renderer_;
vtkSmartPointer<InteractorStyle> style_;
Ptr<WidgetActorMap> widget_actor_map_;
bool removeActorFromRenderer(vtkSmartPointer<vtkProp> actor);
void recreateRenderWindow();
};
#endif

@ -0,0 +1,158 @@
/*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, OutputArray _tcoords)
{
cloud = _cloud;
colors = _colors;
normals = _normals;
tcoords = _tcoords;
}
void cv::viz::vtkCloudMatSink::WriteData()
{
vtkPolyData *input = this->GetInput();
if (!input)
return;
vtkSmartPointer<vtkPoints> 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 = cloud.getMat().ptr<Vec3d>();
Vec3f *fdata = cloud.getMat().ptr<Vec3f>();
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<vtkDataArray> 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<Vec3d>();
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<vtkDataArray> 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<Vec3d>();
for(size_t i = 0; i < buffer.total(); ++i)
*cptr++ = Vec3d(normals_data->GetTuple(i));
buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F);
}
else
normals.release();
vtkSmartPointer<vtkDataArray> 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<Vec2d>();
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)
{
Superclass::PrintSelf(os, indent);
os << indent << "Cloud: " << cloud.needed() << "\n";
os << indent << "Colors: " << colors.needed() << "\n";
os << indent << "Normals: " << normals.needed() << "\n";
}

@ -0,0 +1,79 @@
/*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
#include <opencv2/core.hpp>
#include <vtkPolyDataWriter.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(), OutputArray tcoords = noArray());
protected:
vtkCloudMatSink();
~vtkCloudMatSink();
void WriteData();
_OutputArray cloud, colors, normals, tcoords;
private:
vtkCloudMatSink(const vtkCloudMatSink&); // Not implemented.
void operator=(const vtkCloudMatSink&); // Not implemented.
};
}
}
#endif

@ -0,0 +1,286 @@
/*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);
template<typename _Tp> struct VtkDepthTraits;
template<> struct VtkDepthTraits<float>
{
const static int data_type = VTK_FLOAT;
typedef vtkFloatArray array_type;
};
template<> struct VtkDepthTraits<double>
{
const static int data_type = VTK_DOUBLE;
typedef vtkDoubleArray array_type;
};
}}
cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); }
cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {}
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);
Mat cloud = _cloud.getMat();
int total = _cloud.depth() == CV_32F ? filterNanCopy<float>(cloud) : filterNanCopy<double>(cloud);
vertices = vtkSmartPointer<vtkCellArray>::New();
vertices->Allocate(vertices->EstimateSize(1, total));
vertices->InsertNextCell(total);
for(int i = 0; i < total; ++i)
vertices->InsertCellPoint(i);
return total;
}
int cv::viz::vtkCloudMatSource::SetColorCloud(InputArray _cloud, InputArray _colors)
{
int total = SetCloud(_cloud);
if (_colors.empty())
return total;
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<float>(colors, cloud, total);
else if (cloud.depth() == CV_64F)
filterNanColorsCopy<double>(colors, cloud, total);
return total;
}
int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArray _colors, InputArray _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());
Mat c = _cloud.getMat();
Mat n = _normals.getMat();
if (n.depth() == CV_32F && c.depth() == CV_32F)
filterNanNormalsCopy<float, float>(n, c, total);
else if (n.depth() == CV_32F && c.depth() == CV_64F)
filterNanNormalsCopy<float, double>(n, c, total);
else if (n.depth() == CV_64F && c.depth() == CV_32F)
filterNanNormalsCopy<double, float>(n, c, total);
else if (n.depth() == CV_64F && c.depth() == CV_64F)
filterNanNormalsCopy<double, double>(n, c, total);
else
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 cl = _cloud.getMat();
Mat tc = _tcoords.getMat();
if (tc.depth() == CV_32F && cl.depth() == CV_32F)
filterNanTCoordsCopy<float, float>(tc, cl, total);
else if (tc.depth() == CV_32F && cl.depth() == CV_64F)
filterNanTCoordsCopy<float, double>(tc, cl, total);
else if (tc.depth() == CV_64F && cl.depth() == CV_32F)
filterNanTCoordsCopy<double, float>(tc, cl, total);
else if (tc.depth() == CV_64F && cl.depth() == CV_64F)
filterNanTCoordsCopy<double, double>(tc, cl, total);
else
CV_Assert(!"Unsupported tcoords/cloud type");
return total;
}
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);
if (scalars)
output->GetPointData()->SetScalars(scalars);
if (normals)
output->GetPointData()->SetNormals(normals);
if (tcoords)
output->GetPointData()->SetTCoords(tcoords);
return 1;
}
template<typename _Tp>
int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& cloud)
{
CV_DbgAssert(DataType<_Tp>::depth == cloud.depth());
points = vtkSmartPointer<vtkPoints>::New();
points->SetDataType(VtkDepthTraits<_Tp>::data_type);
points->Allocate(cloud.total());
points->SetNumberOfPoints(cloud.total());
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 * s_chs;
for (; srow != send; srow += s_chs)
if (!isNan(srow))
points->SetPoint(total++, srow);
}
points->SetNumberOfPoints(total);
points->Squeeze();
return total;
}
template<typename _Msk>
void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total)
{
Vec3b* array = new Vec3b[total];
Vec3b* pos = array;
int s_chs = cloud_colors.channels();
int m_chs = mask.channels();
for (int y = 0; y < cloud_colors.rows; ++y)
{
const unsigned char* srow = cloud_colors.ptr<unsigned char>(y);
const unsigned char* send = srow + cloud_colors.cols * s_chs;
const _Msk* mrow = mask.ptr<_Msk>(y);
if (cloud_colors.channels() == 1)
{
for (; srow != send; srow += s_chs, mrow += m_chs)
if (!isNan(mrow))
*pos++ = Vec3b(srow[0], srow[0], srow[0]);
}
else
for (; srow != send; srow += s_chs, mrow += m_chs)
if (!isNan(mrow))
*pos++ = Vec3b(srow[2], srow[1], srow[0]);
}
scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
scalars->SetName("Colors");
scalars->SetNumberOfComponents(3);
scalars->SetNumberOfTuples(total);
scalars->SetArray(array->val, total * 3, 0);
}
template<typename _Tn, typename _Msk>
void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total)
{
normals = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New();
normals->SetName("Normals");
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);
}
}
template<typename _Tn, typename _Msk>
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");
tcoords->SetNumberOfComponents(2);
tcoords->SetNumberOfTuples(total);
int pos = 0;
for (int y = 0; y < mask.rows; ++y)
{
const Vec2* srow = _tcoords.ptr<Vec2>(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);
}
}

@ -0,0 +1,96 @@
/*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 <opencv2/core.hpp>
#include <vtkPolyDataAlgorithm.h>
#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
namespace cv
{
namespace viz
{
class vtkCloudMatSource : public vtkPolyDataAlgorithm
{
public:
static vtkCloudMatSource *New();
vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm)
virtual int SetCloud(InputArray cloud);
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();
~vtkCloudMatSource();
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
vtkSmartPointer<vtkPoints> points;
vtkSmartPointer<vtkCellArray> vertices;
vtkSmartPointer<vtkUnsignedCharArray> scalars;
vtkSmartPointer<vtkDataArray> normals;
vtkSmartPointer<vtkDataArray> tcoords;
private:
vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented.
void operator=(const vtkCloudMatSource&); // Not implemented.
template<typename _Tp> int filterNanCopy(const Mat& cloud);
template<typename _Msk> void filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total);
template<typename _Tn, typename _Msk>
void filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total);
template<typename _Tn, typename _Msk>
void filterNanTCoordsCopy(const Mat& tcoords, const Mat& mask, int total);
};
}
}
#endif

@ -0,0 +1,143 @@
/*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(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(image.channels());
this->ImageData->SetScalarTypeToUnsignedChar();
this->ImageData->AllocateScalars();
#else
this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels());
#endif
switch(image.channels())
{
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<vtkImageData> output)
{
unsigned char* dptr = reinterpret_cast<unsigned char*>(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<unsigned char>(y);
for (int x = 0; x < source.cols; ++x)
drow[x] = *srow++;
}
}
void cv::viz::vtkImageMatSource::copyRGBImage(const Mat &source, vtkSmartPointer<vtkImageData> output)
{
Vec3b* dptr = reinterpret_cast<Vec3b*>(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<unsigned char>(y);
for (int x = 0; x < source.cols; ++x, srow += source.channels())
drow[x] = Vec3b(srow[2], srow[1], srow[0]);
}
}
void cv::viz::vtkImageMatSource::copyRGBAImage(const Mat &source, vtkSmartPointer<vtkImageData> output)
{
Vec4b* dptr = reinterpret_cast<Vec4b*>(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<unsigned char>(y);
for (int x = 0; x < source.cols; ++x, srow += source.channels())
drow[x] = Vec4b(srow[2], srow[1], srow[0], srow[3]);
}
}

@ -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*/
#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<vtkImageData> 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<vtkImageData> output);
static void copyRGBImage (const Mat &source, vtkSmartPointer<vtkImageData> output);
static void copyRGBAImage(const Mat &source, vtkSmartPointer<vtkImageData> output);
};
}
}
#endif

@ -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<vtkDataArray> 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<vtkDataArray> 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";
}

@ -38,12 +38,42 @@
// 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
//
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/
#include "precomp.hpp"
#ifndef __vtkOBJWriter_h
#define __vtkOBJWriter_h
#include <vtkPolyDataWriter.h>
namespace cv
{
namespace viz
{
class vtkOBJWriter : public vtkPolyDataWriter
{
public:
static vtkOBJWriter *New();
vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter)
void PrintSelf(ostream& os, vtkIndent indent);
vtkGetMacro(DecimalPrecision, int);
vtkSetMacro(DecimalPrecision, int);
protected:
vtkOBJWriter();
~vtkOBJWriter();
void WriteData();
int DecimalPrecision;
private:
vtkOBJWriter(const vtkOBJWriter&); // Not implemented.
void operator=(const vtkOBJWriter&); // Not implemented.
};
}
}
#endif

@ -0,0 +1,110 @@
/*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.ptr<Affine3d>();
size_t total = traj.total();
points = vtkSmartPointer<vtkPoints>::New();
points->SetDataType(VTK_DOUBLE);
points->SetNumberOfPoints(total);
tensors = vtkSmartPointer<vtkDoubleArray>::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<Affine3d>();
const Affine3f* fpath = _traj.getMat().ptr<Affine3f>();
if (_traj.depth() == CV_32F)
for(int i = 0; i < points.cols; ++i)
points.at<Vec3f>(i) = fpath[i].translation();
if (_traj.depth() == CV_64F)
for(int i = 0; i < points.cols; ++i)
points.at<Vec3d>(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;
}

@ -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 <opencv2/core/mat.hpp>
#include <vtkPolyDataAlgorithm.h>
#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
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<vtkPoints> points;
vtkSmartPointer<vtkDoubleArray> tensors;
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
private:
vtkTrajectorySource(const vtkTrajectorySource&); // Not implemented.
void operator=(const vtkTrajectorySource&); // Not implemented.
};
}
}
#endif

@ -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";
}

@ -0,0 +1,78 @@
/*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 __vtkXYZWriter_h
#define __vtkXYZWriter_h
#include "vtkPolyDataWriter.h"
namespace cv
{
namespace viz
{
class vtkXYZWriter : public vtkPolyDataWriter
{
public:
static vtkXYZWriter *New();
vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter)
void PrintSelf(ostream& os, vtkIndent indent);
vtkGetMacro(DecimalPrecision, int)
vtkSetMacro(DecimalPrecision, int)
protected:
vtkXYZWriter();
~vtkXYZWriter(){}
void WriteData();
int DecimalPrecision;
private:
vtkXYZWriter(const vtkXYZWriter&); // Not implemented.
void operator=(const vtkXYZWriter&); // Not implemented.
};
}
}
#endif

@ -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<vtkProp> 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<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();
reader->SetFileName(file_name.c_str());
vtkSmartPointer<vtkDataSet> data = reader->GetOutput();
CV_Assert("File does not exist or file format is not supported." && data);
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
#if VTK_MAJOR_VERSION <= 5
mapper->SetInput(data);
#else
mapper->SetInputData(data);
#endif
vtkSmartPointer<vtkDataArray> scalars = data->GetPointData()->GetScalars();
if (scalars)
{
cv::Vec3d 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<vtkIdType>(1, data->GetNumberOfPoints() / 10)));
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::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<vtkTextProperty> 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:
@ -186,14 +140,11 @@ void cv::viz::Widget::setRenderingProperty(int property, double value)
{
if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals())
{
vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
#if VTK_MAJOR_VERSION <= 5
normals->SetInput(actor->GetMapper()->GetInput());
#else
normals->SetInputData(actor->GetMapper()->GetInput());
#endif
normals->Update();
vtkDataSetMapper::SafeDownCast(actor->GetMapper())->SetInputConnection(normals->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
CV_Assert("Can't set shading property for such type of widget" && mapper);
vtkSmartPointer<vtkPolyData> with_normals = VtkUtils::ComputeNormals(mapper->GetInput());
VtkUtils::SetInputData(mapper, with_normals);
}
actor->GetProperty()->SetInterpolationToGouraud();
break;
@ -202,27 +153,22 @@ void cv::viz::Widget::setRenderingProperty(int property, double value)
{
if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals())
{
vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
#if VTK_MAJOR_VERSION <= 5
normals->SetInput(actor->GetMapper()->GetInput());
#else
normals->SetInputData(actor->GetMapper()->GetInput());
#endif
normals->Update();
vtkDataSetMapper::SafeDownCast(actor->GetMapper())->SetInputConnection(normals->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
CV_Assert("Can't set shading property for such type of widget" && mapper);
vtkSmartPointer<vtkPolyData> with_normals = VtkUtils::ComputeNormals(mapper->GetInput());
VtkUtils::SetInputData(mapper, with_normals);
}
actor->GetProperty()->SetInterpolationToPhong();
break;
}
}
actor->Modified();
break;
}
default:
CV_Assert("setPointCloudRenderingProperties: Unknown property");
}
actor->Modified();
}
double cv::viz::Widget::getRenderingProperty(int property) const
@ -233,32 +179,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<vtkTextProperty> tprop = text_actor->GetTextProperty();
value = tprop->GetFontSize();
value = text_actor->GetTextProperty()->GetFontSize();;
break;
}
case REPRESENTATION:
@ -303,38 +233,17 @@ void cv::viz::WidgetAccessor::setProp(Widget& widget, vtkSmartPointer<vtkProp> p
///////////////////////////////////////////////////////////////////////////////////////////////
/// widget3D implementation
struct cv::viz::Widget3D::MatrixConverter
{
static Matx44f convertToMatx(const vtkSmartPointer<vtkMatrix4x4>& 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<vtkMatrix4x4> convertToVtkMatrix(const Matx44f& m)
{
vtkSmartPointer<vtkMatrix4x4> vtk_matrix = vtkSmartPointer<vtkMatrix4x4>::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)
void cv::viz::Widget3D::setPose(const Affine3d &pose)
{
vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this));
CV_Assert("Widget is not 3D." && actor);
vtkSmartPointer<vtkMatrix4x4> matrix = convertToVtkMatrix(pose.matrix);
vtkSmartPointer<vtkMatrix4x4> matrix = vtkmatrix(pose.matrix);
actor->SetUserMatrix(matrix);
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);
@ -343,25 +252,33 @@ void cv::viz::Widget3D::updatePose(const Affine3f &pose)
if (!matrix)
{
setPose(pose);
return ;
return;
}
Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix);
Affine3f updated_pose = pose * Affine3f(matrix_cv);
matrix = MatrixConverter::convertToVtkMatrix(updated_pose.matrix);
Affine3d updated_pose = pose * Affine3d(*matrix->Element);
matrix = vtkmatrix(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 Affine3d(*actor->GetUserMatrix()->Element);
}
vtkSmartPointer<vtkMatrix4x4> matrix = actor->GetUserMatrix();
Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix);
return Affine3f(matrix_cv);
void cv::viz::Widget3D::applyTransform(const Affine3d &transform)
{
vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
CV_Assert("Widget is not 3D actor." && actor);
vtkSmartPointer<vtkPolyDataMapper> 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));
}
void cv::viz::Widget3D::setColor(const Color &color)

@ -1,3 +1,3 @@
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")
CV_TEST_MAIN("viz")

@ -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;
}

@ -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__
@ -66,5 +63,42 @@
#include <iostream>
#include <fstream>
#include <string>
#include <limits>
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");
}
template<typename _Tp>
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;
}
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

@ -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<float>(0,0) += CV_PI * 0.01f;
rot_vec.at<float>(0,1) += CV_PI * 0.01f;
rot_vec.at<float>(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);
@ -48,7 +48,7 @@ void tutorial2()
}
TEST(Viz_viz3d, DISABLED_tutorial2_pose_of_widget)
TEST(Viz, DISABLED_tutorial2_pose_of_widget)
{
tutorial2();
}

@ -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<cv::Point3f>();
//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
*/
@ -37,29 +15,29 @@ 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);
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.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), 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 bunny_cloud = cvcloud_load();
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));
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)
{
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);
}
@ -75,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);
}

@ -41,141 +41,24 @@
//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::string str;
for(size_t i = 0; i < 11; ++i)
std::getline(ifs, str);
cv::Point3f* data = cloud.ptr<cv::Point3f>();
for(size_t i = 0; i < 20000; ++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)
TEST(Viz_viz3d, DISABLED_develop)
{
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");
}
}
}
}
cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path());
TEST(Viz_viz3d, develop)
{
cv::viz::Viz3d viz("abc");
viz.setBackgroundMeshLab();
viz.showWidget("coo", cv::viz::WCoordinateSystem(1));
viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud));
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<Affine3f> 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<Vec3f>(row) = Vec3f(downSample * float(col) / img.cols, 1.f-(downSample * float(row) / img.rows), 0.f);
colors[col].at<Vec3b>(row) = img.at<Vec3b>(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<viz::WCameraPosition>().setPose(cam_path[path_counter]);
cam_coordinates.cast<viz::WCameraPosition>().setPose(cam_path[path_counter++]);
//---->>>>> <to_test_in_future>
//std::vector<cv::Affine3d> gt, es;
//cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml");
//cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml");
//cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path());
//---->>>>> </to_test_in_future>
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
viz.spin();
}

@ -0,0 +1,407 @@
/*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, 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()), pose);
viz.showWidget("text2d", WText("Bluberry cloud", Point(20, 20), 20, Color::green()));
viz.spin();
}
TEST(Viz, 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);
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.showWidget("text2d", WText("Random color cloud", Point(20, 20), 20, Color::green()));
viz.spin();
}
TEST(Viz, show_cloud_masked)
{
Mat dragon_cloud = readCloud(get_dragon_ply_file_path());
Vec3f qnan = Vec3f::all(std::numeric_limits<float>::quiet_NaN());
for(size_t i = 0; i < dragon_cloud.total(); ++i)
if (i % 15 != 0)
dragon_cloud.at<Vec3f>(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), pose);
viz.showWidget("text2d", WText("Nan masked cloud", Point(20, 20), 20, Color::green()));
viz.spin();
}
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(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)));
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();
}
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.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();
}
TEST(Viz, show_mesh)
{
Mesh mesh = Mesh::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), pose);
viz.showWidget("text2d", WText("Just mesh", Point(20, 20), 20, Color::green()));
viz.spin();
}
TEST(Viz, show_mesh_random_colors)
{
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));
Viz3d viz("show_mesh_random_color");
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();
}
TEST(Viz, show_textured_mesh)
{
Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png"));
std::vector<Vec3d> points;
std::vector<Vec2d> tcoords;
std::vector<int> 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.showWidget("text2d", WText("Textured mesh", Point(20, 20), 20, Color::green()));
viz.spin();
}
TEST(Viz, show_polyline)
{
Mat polyline(1, 32, CV_64FC3);
for(size_t i = 0; i < polyline.total(); ++i)
polyline.at<Vec3d>(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.showWidget("text2d", WText("Polyline", Point(20, 20), 20, Color::green()));
viz.spin();
}
TEST(Viz, show_sampled_normals)
{
Mesh mesh = Mesh::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.showWidget("text2d", WText("Cloud or mesh normals", Point(20, 20), 20, Color::green()));
viz.spin();
}
TEST(Viz, show_trajectories)
{
std::vector<Affine3d> path = generate_test_trajectory<double>(), 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, 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())
{
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.resetCamera();
viz.spin();
}
TEST(Viz, show_trajectory_reposition)
{
std::vector<Affine3f> path = generate_test_trajectory<float>();
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();
}
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"));
Mat gray = make_gray(lena);
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, 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]);
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();
}
TEST(Viz, 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");
viz.setBackgroundMeshLab();
Size vsz = viz.getWindowSize();
viz.showWidget("coos", WCoordinateSystem());
viz.showWidget("cube", WCube());
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)));
viz.showWidget("text2d", WText("Overlay images", Point(20, 20), 20, Color::green()));
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<WImageOverlay>().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();
}
TEST(Viz, 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, 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()));
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.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())
{
viz.getWidget("img0").cast<WImage3D>().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();
}
TEST(Viz, show_simple_widgets)
{
Viz3d viz("show_simple_widgets");
viz.setBackgroundMeshLab();
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.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("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)));
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.spin();
viz.getWidget("text2d").cast<WText>().setText("Different simple widgets (updated)");
viz.getWidget("text3d").cast<WText3D>().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.showWidget("text2d", WText("Follower: text always facing camera", Point(20, 20), 20, Color::green()));
viz.setBackgroundMeshLab();
viz.spin();
viz.getWidget("t3d_2").cast<WText3D>().setText("Updated follower 3D");
viz.spin();
}
Loading…
Cancel
Save