Merge pull request #2173 from Nerei:viz

This commit is contained in:
Roman Donchenko 2014-01-20 18:05:11 +04:00 committed by OpenCV Buildbot
commit 9710b25c7d
45 changed files with 5219 additions and 4100 deletions

View File

@ -116,7 +116,7 @@ endif()
OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS) ) 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_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_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_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_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) ) OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" OFF IF (NOT IOS) )

View File

@ -2,7 +2,7 @@ if(NOT WITH_VTK OR ANDROID OR IOS)
return() return()
endif() 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) if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND)
find_package(VTK 5.10 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) find_package(VTK 5.10 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE)

View File

@ -43,7 +43,7 @@ You can download the code from :download:`here <../../../../samples/cpp/tutorial
cout << "First event loop is over" << endl; cout << "First event loop is over" << endl;
/// Access window via its name /// Access window via its name
viz::Viz3d sameWindow = viz::get("Viz Demo"); viz::Viz3d sameWindow = viz::getWindowByName("Viz Demo");
/// Start event loop /// Start event loop
sameWindow.spin(); sameWindow.spin();

View File

@ -55,9 +55,9 @@ namespace cv
{ {
public: public:
typedef T float_type; typedef T float_type;
typedef cv::Matx<float_type, 3, 3> Mat3; typedef Matx<float_type, 3, 3> Mat3;
typedef cv::Matx<float_type, 4, 4> Mat4; typedef Matx<float_type, 4, 4> Mat4;
typedef cv::Vec<float_type, 3> Vec3; typedef Vec<float_type, 3> Vec3;
Affine3(); Affine3();
@ -70,11 +70,11 @@ namespace cv
//Rodrigues vector //Rodrigues vector
Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0));
//Combines all contructors above. Supports 4x4, 3x3, 1x3, 3x1 sizes of data matrix //Combines all contructors above. Supports 4x4, 3x4, 3x3, 1x3, 3x1 sizes of data matrix
explicit Affine3(const cv::Mat& data, const Vec3& t = Vec3::all(0)); explicit Affine3(const Mat& data, const Vec3& t = Vec3::all(0));
//Euler angles //From 16th element array
Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t = Vec3::all(0)); explicit Affine3(const float_type* vals);
static Affine3 Identity(); static Affine3 Identity();
@ -87,9 +87,6 @@ namespace cv
//Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; //Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix;
void rotation(const Mat& data); void rotation(const Mat& data);
//Euler angles
void rotation(float_type alpha, float_type beta, float_type gamma);
void linear(const Mat3& L); void linear(const Mat3& L);
void translation(const Vec3& t); void translation(const Vec3& t);
@ -105,6 +102,9 @@ namespace cv
// a.rotate(R) is equivalent to Affine(R, 0) * a; // a.rotate(R) is equivalent to Affine(R, 0) * a;
Affine3 rotate(const Mat3& R) const; 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; // a.translate(t) is equivalent to Affine(E, t) * a;
Affine3 translate(const Vec3& t) const; Affine3 translate(const Vec3& t) const;
@ -113,6 +113,8 @@ namespace cv
template <typename Y> operator Affine3<Y>() const; template <typename Y> operator Affine3<Y>() const;
template <typename Y> Affine3<Y> cast() const;
Mat4 matrix; Mat4 matrix;
#if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H #if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H
@ -132,10 +134,26 @@ namespace cv
typedef Affine3<float> Affine3f; typedef Affine3<float> Affine3f;
typedef Affine3<double> Affine3d; typedef Affine3<double> Affine3d;
static cv::Vec3f operator*(const cv::Affine3f& affine, const cv::Vec3f& vector); static Vec3f operator*(const Affine3f& affine, const Vec3f& vector);
static cv::Vec3d operator*(const cv::Affine3d& affine, const cv::Vec3d& 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); data.copyTo(matrix);
return; 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); rotation(data);
translation(t); translation(t);
@ -187,13 +211,8 @@ cv::Affine3<T>::Affine3(const cv::Mat& data, const Vec3& t)
} }
template<typename T> inline template<typename T> inline
cv::Affine3<T>::Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t) cv::Affine3<T>::Affine3(const float_type* vals) : matrix(vals)
{ {}
rotation(alpha, beta, gamma);
translation(t);
matrix.val[12] = matrix.val[13] = matrix.val[14] = 0;
matrix.val[15] = 1;
}
template<typename T> inline template<typename T> inline
cv::Affine3<T> cv::Affine3<T>::Identity() 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"); 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 template<typename T> inline
void cv::Affine3<T>::linear(const Mat3& L) 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; 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 template<typename T> inline
cv::Affine3<T> cv::Affine3<T>::translate(const Vec3& t) const 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); 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 template<typename T> inline
cv::Affine3<T> cv::operator*(const cv::Affine3<T>& affine1, const cv::Affine3<T>& affine2) cv::Affine3<T> cv::operator*(const cv::Affine3<T>& affine1, const cv::Affine3<T>& affine2)
{ {

View File

@ -13,7 +13,7 @@ viz::makeTransformToGlobal
-------------------------- --------------------------
Takes coordinate frame data and builds transform to global coordinate frame. 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_x: X axis vector in global coordinate frame.
:param axis_y: Y 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). 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 position: Position of the camera in global coordinate frame.
:param focal_point: Focal point 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. This function returns pose of the camera in global coordinate frame.
viz::get viz::getWindowByName
-------- --------------------
Retrieves a window by its name. 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. :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 .. code-block:: cpp
/// window and window_2 are the same windows. /// window and window_2 are the same windows.
viz::Viz3d window = viz::get("myWindow"); viz::Viz3d window = viz::getWindowByName("myWindow");
viz::Viz3d window_2 = viz::get("Viz - myWindow"); viz::Viz3d window_2 = viz::getWindowByName("Viz - myWindow");
viz::isNan viz::isNan
---------- ----------
@ -94,19 +94,21 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar
Viz3d& operator=(const Viz3d&); Viz3d& operator=(const Viz3d&);
~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); void removeWidget(const String &id);
Widget getWidget(const String &id) const; Widget getWidget(const String &id) const;
void removeAllWidgets(); void removeAllWidgets();
void setWidgetPose(const String &id, const Affine3f &pose); void setWidgetPose(const String &id, const Affine3d &pose);
void updateWidgetPose(const String &id, const Affine3f &pose); void updateWidgetPose(const String &id, const Affine3d &pose);
Affine3f getWidgetPose(const String &id) const; Affine3d getWidgetPose(const String &id) const;
void showImage(InputArray image, const Size& window_size = Size(-1, -1));
void setCamera(const Camera &camera); void setCamera(const Camera &camera);
Camera getCamera() const; Camera getCamera() const;
Affine3f getViewerPose(); Affine3d getViewerPose();
void setViewerPose(const Affine3f &pose); void setViewerPose(const Affine3d &pose);
void resetCameraViewpoint (const String &id); void resetCameraViewpoint (const String &id);
void resetCamera(); 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); void setRenderingProperty(const String &id, int property, double value);
double getRenderingProperty(const String &id, int property); double getRenderingProperty(const String &id, int property);
void setDesiredUpdateRate(double rate);
double getDesiredUpdateRate();
void setRepresentation(int representation); void setRepresentation(int representation);
private: private:
@ -152,7 +152,7 @@ viz::Viz3d::showWidget
---------------------- ----------------------
Shows a widget in the window. 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 id: A unique id for the widget.
:param widget: The widget to be displayed in the window. :param widget: The widget to be displayed in the window.
@ -182,11 +182,20 @@ Removes all widgets from the window.
.. ocv:function:: void removeAllWidgets() .. 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 viz::Viz3d::setWidgetPose
------------------------- -------------------------
Sets pose of a widget in the window. 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 id: The id of the widget whose pose will be set.
:param pose: The new pose of the widget. :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. 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 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. :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. 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. :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. Returns the current pose of the viewer.
..ocv:function:: Affine3f getViewerPose() ..ocv:function:: Affine3d getViewerPose()
viz::Viz3d::setViewerPose viz::Viz3d::setViewerPose
------------------------- -------------------------
Sets pose of the viewer. 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. :param pose: The new pose of the viewer.
@ -414,20 +423,6 @@ Returns rendering property of a widget.
* **SHADING_GOURAUD** * **SHADING_GOURAUD**
* **SHADING_PHONG** * **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 viz::Viz3d::setRepresentation
----------------------------- -----------------------------
Sets geometry representation of the widgets to surface, wireframe or points. Sets geometry representation of the widgets to surface, wireframe or points.
@ -468,33 +463,33 @@ This class a represents BGR color. ::
static Color gray(); 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. :: This class wraps mesh attributes, and it can load a mesh from a ``ply`` file. ::
class CV_EXPORTS Mesh3d class CV_EXPORTS Mesh
{ {
public: 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; Mat polygons;
//! Loads mesh from a given ply file //! Loads mesh from a given ply file
static Mesh3d loadMesh(const String& file); static Mesh load(const String& file);
private:
/* hidden */
}; };
viz::Mesh3d::loadMesh viz::Mesh::load
--------------------- ---------------------
Loads a mesh from a ``ply`` file. 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 viz::KeyboardEvent
@ -506,40 +501,28 @@ This class represents a keyboard event. ::
class CV_EXPORTS KeyboardEvent class CV_EXPORTS KeyboardEvent
{ {
public: public:
static const unsigned int Alt = 1; enum { ALT = 1, CTRL = 2, SHIFT = 4 };
static const unsigned int Ctrl = 2; enum Action { KEY_UP = 0, KEY_DOWN = 1 };
static const unsigned int Shift = 4;
//! Create a keyboard event KeyboardEvent(Action action, const String& symbol, unsigned char code, int modifiers);
//! - 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);
bool isAltPressed () const; Action action;
bool isCtrlPressed () const; String symbol;
bool isShiftPressed () const; unsigned char code;
int modifiers;
unsigned char getKeyCode () const;
const String& getKeySym () const;
bool keyDown () const;
bool keyUp () const;
protected:
/* hidden */
}; };
viz::KeyboardEvent::KeyboardEvent viz::KeyboardEvent::KeyboardEvent
--------------------------------- ---------------------------------
Constructs a 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 viz::MouseEvent
--------------- ---------------
@ -553,26 +536,24 @@ This class represents a mouse event. ::
enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ; enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ;
enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ; 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; Type type;
MouseButton button; MouseButton button;
Point pointer; Point pointer;
unsigned int key_state; int modifiers;
}; };
viz::MouseEvent::MouseEvent viz::MouseEvent::MouseEvent
--------------------------- ---------------------------
Constructs a 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 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 button: Mouse button. This can be **NoButton**, **LeftButton**, **MiddleButton**, **RightButton**, **VScroll**.
:param p: Position of the event. :param p: Position of the event.
:param alt: If true, ``alt`` is pressed. :param modifiers: Signals if ``alt``, ``ctrl`` or ``shift`` are pressed or their combination.
:param ctrl: If true, ``ctrl`` is pressed.
:param shift: If true, ``shift`` is pressed.
viz::Camera viz::Camera
----------- -----------
@ -585,24 +566,24 @@ that can extract the intrinsic parameters from ``field of view``, ``intrinsic ma
class CV_EXPORTS Camera class CV_EXPORTS Camera
{ {
public: public:
Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size); Camera(double f_x, double f_y, double c_x, double c_y, const Size &window_size);
Camera(const Vec2f &fov, const Size &window_size); Camera(const Vec2d &fov, const Size &window_size);
Camera(const cv::Matx33f &K, const Size &window_size); Camera(const Matx33d &K, const Size &window_size);
Camera(const cv::Matx44f &proj, const Size &window_size); Camera(const Matx44d &proj, const Size &window_size);
inline const Vec2d & getClip() const { return clip_; } inline const Vec2d & getClip() const;
inline void setClip(const Vec2d &clip) { clip_ = clip; } 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); void setWindowSize(const Size &window_size);
inline const Vec2f & getFov() const { return fov_; } inline const Vec2d & getFov() const;
inline void setFov(const Vec2f & fov) { fov_ = fov; } inline void setFov(const Vec2d & fov);
inline const Vec2f & getPrincipalPoint() const { return principal_point_; } inline const Vec2d & getPrincipalPoint() const;
inline const Vec2f & getFocalLength() const { return focal_; } inline const Vec2d & getFocalLength() const;
void computeProjectionMatrix(Matx44f &proj) const; void computeProjectionMatrix(Matx44d &proj) const;
static Camera KinectCamera(const Size &window_size); static Camera KinectCamera(const Size &window_size);
@ -614,7 +595,7 @@ viz::Camera::Camera
------------------- -------------------
Constructs a 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_x: Horizontal focal length.
:param f_y: Vertical 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 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. :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 fov: Field of view (horizontal, vertical)
:param window_size: Size of the window. :param window_size: Size of the window.
Principal point is at the center of the window by default. 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 K: Intrinsic matrix of the camera.
:param window_size: Size of the window. This together with intrinsic matrix determines the field of view. :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 proj: Projection matrix of the camera.
:param window_size: Size of the window. This together with projection matrix determines the field of view. :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. 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. :param proj: Output projection matrix.

View File

@ -170,20 +170,23 @@ Base class of all 3D widgets. ::
public: public:
Widget3D() {} Widget3D() {}
void setPose(const Affine3f &pose); //! widget position manipulation, i.e. place where it is rendered.
void updatePose(const Affine3f &pose); void setPose(const Affine3d &pose);
Affine3f getPose() const; 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); void setColor(const Color &color);
private:
/* hidden */
}; };
viz::Widget3D::setPose viz::Widget3D::setPose
---------------------- ----------------------
Sets pose of the widget. 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. :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. 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. :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. 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 viz::Widget3D::setColor
----------------------- -----------------------
@ -262,27 +274,31 @@ This 3D Widget defines a finite plane. ::
class CV_EXPORTS WPlane : public Widget3D class CV_EXPORTS WPlane : public Widget3D
{ {
public: public:
WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white()); //! created default plane with center point at origin and normal oriented along z-axis
WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white()); WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white());
private:
/* hidden */ //! 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 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. :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
:param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. .. 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 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. :param color: :ocv:class:`Color` of the plane.
viz::WSphere viz::WSphere
@ -294,14 +310,14 @@ This 3D Widget defines a sphere. ::
class CV_EXPORTS WSphere : public Widget3D class CV_EXPORTS WSphere : public Widget3D
{ {
public: 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 viz::WSphere::WSphere
--------------------- ---------------------
Constructs a 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 center: Center of the sphere.
:param radius: Radius 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 class CV_EXPORTS WArrow : public Widget3D
{ {
public: 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 viz::WArrow::WArrow
----------------------------- -----------------------------
Constructs an 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 pt1: Start point of the arrow.
:param pt2: End 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 class CV_EXPORTS WCircle : public Widget3D
{ {
public: 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 viz::WCircle::WCircle
------------------------------- -------------------------------
Constructs a WCircle. Constructs default planar circle centred at origin with plane normal along z-axis
.. ocv:function:: WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white()) .. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white())
:param pt: Center of the circle.
:param radius: Radius of the circle. :param radius: Radius of the circle.
:param thickness: Thickness of the circle. :param thickness: Thickness of the circle.
:param color: :ocv:class:`Color` of the circle. :param color: :ocv:class:`Color` of the circle.
viz::WCircle::WCircle
-------------------------------
Constructs repositioned planar circle.
.. ocv:function:: WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white())
:param radius: Radius of the circle.
:param center: Center of the circle.
:param normal: Normal of the plane in which the circle lies.
:param thickness: Thickness of the circle.
:param color: :ocv:class:`Color` of the circle.
viz::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 viz::WCylinder
-------------- --------------
.. ocv:class:: WCylinder .. ocv:class:: WCylinder
@ -365,17 +436,17 @@ This 3D Widget defines a cylinder. ::
class CV_EXPORTS WCylinder : public Widget3D class CV_EXPORTS WCylinder : public Widget3D
{ {
public: 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 viz::WCylinder::WCylinder
----------------------------------- -----------------------------------
Constructs a 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_point1: A point1 on the axis of the cylinder.
:param axis_direction: Direction of the axis of the cylinder. :param axis_point2: A point2 on the axis of the cylinder.
:param radius: Radius of the cylinder. :param radius: Radius of the cylinder.
:param numsides: Resolution of the cylinder. :param numsides: Resolution of the cylinder.
:param color: :ocv:class:`Color` 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 class CV_EXPORTS WCoordinateSystem : public Widget3D
{ {
public: public:
WCoordinateSystem(float scale = 1.0); WCoordinateSystem(double scale = 1.0);
}; };
viz::WCoordinateSystem::WCoordinateSystem viz::WCoordinateSystem::WCoordinateSystem
--------------------------------------------------- ---------------------------------------------------
Constructs a 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. :param scale: Determines the size of the axes.
@ -437,9 +508,6 @@ This 3D Widget defines a poly line. ::
{ {
public: public:
WPolyLine(InputArray points, const Color &color = Color::white()); WPolyLine(InputArray points, const Color &color = Color::white());
private:
/* hidden */
}; };
viz::WPolyLine::WPolyLine viz::WPolyLine::WPolyLine
@ -460,30 +528,32 @@ This 3D Widget defines a grid. ::
class CV_EXPORTS WGrid : public Widget3D class CV_EXPORTS WGrid : public Widget3D
{ {
public: public:
//! Creates grid at the origin //! Creates grid at the origin and normal oriented along z-axis
WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), 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()); //! Creates repositioned grid
private: WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,
/* hidden */ const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white());
}; };
viz::WGrid::WGrid viz::WGrid::WGrid
--------------------------- ---------------------------
Constructs a 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 cells: Number of cell columns and rows, respectively.
:param spacing: Size of each column and row, respectively. :param cells_spacing: Size of each cell, respectively.
:param color: :ocv:class:`Color` of the grid. :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 center: Center of the grid
:param dimensions: Number of columns and rows, respectively. :param normal: Grid normal orientation
:param spacing: Size of each column and row, respectively. :param new_yaxis: Up-vector. New orientation of grid y-axis.
:param color: :ocv:class:`Color` of the grid. :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 viz::WText3D
------------ ------------
@ -494,7 +564,7 @@ This 3D Widget represents 3D text. The text always faces the camera. ::
class CV_EXPORTS WText3D : public Widget3D class CV_EXPORTS WText3D : public Widget3D
{ {
public: 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); void setText(const String &text);
String getText() const; String getText() const;
@ -504,7 +574,7 @@ viz::WText3D::WText3D
------------------------------- -------------------------------
Constructs a 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 text: Text content of the widget.
:param position: Position of the text. :param position: Position of the text.
@ -575,16 +645,16 @@ This 2D Widget represents an image overlay. ::
class CV_EXPORTS WImageOverlay : public Widget2D class CV_EXPORTS WImageOverlay : public Widget2D
{ {
public: 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 viz::WImageOverlay::WImageOverlay
--------------------------------- ---------------------------------
Constructs an 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 image: BGR or Gray-Scale image.
:param rect: Image is scaled and positioned based on rect. :param rect: Image is scaled and positioned based on rect.
@ -593,7 +663,7 @@ viz::WImageOverlay::setImage
---------------------------- ----------------------------
Sets the image content of the widget. 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. :param image: BGR or Gray-Scale image.
@ -607,23 +677,23 @@ This 3D Widget represents an image in 3D space. ::
{ {
public: public:
//! Creates 3D image at the origin //! 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 //! 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 viz::WImage3D::WImage3D
----------------------- -----------------------
Constructs an 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 image: BGR or Gray-Scale image.
:param size: Size of the 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 position: Position of the image.
:param normal: Normal of the plane that represents 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. 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. :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: public:
//! Creates camera coordinate frame (axes) at the origin //! 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 //! 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 //! 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 //! 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 //! 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 viz::WCameraPosition::WCameraPosition
@ -666,7 +736,7 @@ Constructs a WCameraPosition.
- **Display camera coordinate frame.** - **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. Creates camera coordinate frame at the origin.
@ -676,7 +746,7 @@ Constructs a WCameraPosition.
- **Display the viewing frustum.** - **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 K: Intrinsic matrix of the camera.
:param scale: Scale of the frustum. :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. 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 fov: Field of view of the camera (horizontal, vertical).
:param scale: Scale of the frustum. :param scale: Scale of the frustum.
@ -698,7 +768,7 @@ Constructs a WCameraPosition.
- **Display image on the far plane of the viewing frustum.** - **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 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. :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. 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 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. :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 class CV_EXPORTS WTrajectory : public Widget3D
{ {
public: 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 //! 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); WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white(),;
//! 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 */
}; };
viz::WTrajectory::WTrajectory viz::WTrajectory::WTrajectory
----------------------------- -----------------------------
Constructs a 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 path: List of poses on a trajectory. Takes std::vector<Affine<T>> with T == [float | double]
:param display_mode: Display mode. This can be DISPLAY_PATH, DISPLAY_FRAMES, DISPLAY_PATH & DISPLAY_FRAMES. :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH.
:param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected.
:param scale: Scale of the frames. Polyline is not affected. :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: Displays trajectory of the given path as follows:
* DISPLAY_PATH : Displays a poly line that represents the path. * PATH : Displays a poly line that represents the path.
* DISPLAY_FRAMES : Displays coordinate frames at each pose. * FRAMES : Displays coordinate frames at each pose.
* DISPLAY_PATH & DISPLAY_FRAMES : Displays both poly line and coordinate frames. * PATH & FRAMES : Displays both poly line and coordinate frames.
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) viz::WTrajectoryFrustums
------------------------
.. ocv:class:: WTrajectoryFrustums
:param path: List of poses on a trajectory. 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());
};
viz::WTrajectoryFrustums::WTrajectoryFrustums
---------------------------------------------
Constructs a WTrajectoryFrustums.
.. 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 K: Intrinsic matrix of the camera.
:param scale: Scale of the frustums. :param scale: Scale of the frustums.
:param color: :ocv:class:`Color` of the frustums. :param color: :ocv:class:`Color` of the frustums.
Displays frustums at each pose of the trajectory. 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 fov: Field of view of the camera (horizontal, vertical).
:param scale: Scale of the frustums. :param scale: Scale of the frustums.
:param color: :ocv:class:`Color` of the frustums. :param color: :ocv:class:`Color` of the frustums.
Displays frustums at each pose of the trajectory. 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 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. :: represent the direction from previous position to the current. ::
class CV_EXPORTS WSpheresTrajectory : public Widget3D class CV_EXPORTS WTrajectorySpheres : public Widget3D
{ {
public: public:
WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length = 0.05f, WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007,
float init_sphere_radius = 0.021, sphere_radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white());
Color &line_color = Color::white(), const Color &sphere_color = Color::white());
}; };
viz::WSpheresTrajectory::WSpheresTrajectory viz::WTrajectorySpheres::WTrajectorySpheres
------------------------------------------- -------------------------------------------
Constructs a WSpheresTrajectory. Constructs a WTrajectorySpheres.
.. ocv:function:: WSpheresTrajectory(const std::vector<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 path: List of poses on a trajectory. Takes std::vector<Affine<T>> with T == [float | double]
:param line_length: Length of the lines. :param line_length: Max length of the lines which point to previous position
:param init_sphere_radius: Radius of the first sphere which represents the initial position of the camera. :param sphere_radius: Radius of the spheres.
:param sphere_radius: Radius of the rest of the spheres. :param from: :ocv:class:`Color` for first sphere.
:param line_color: :ocv:class:`Color` of the lines. :param to: :ocv:class:`Color` for last sphere. Intermediate spheres will have interpolated color.
:param sphere_color: :ocv:class:`Color` of the spheres.
viz::WCloud viz::WCloud
----------- -----------
@ -818,9 +898,6 @@ This 3D Widget defines a point cloud. ::
WCloud(InputArray cloud, InputArray colors); WCloud(InputArray cloud, InputArray colors);
//! All points in cloud have the same color //! All points in cloud have the same color
WCloud(InputArray cloud, const Color &color = Color::white()); WCloud(InputArray cloud, const Color &color = Color::white());
private:
/* hidden */
}; };
viz::WCloud::WCloud viz::WCloud::WCloud
@ -855,12 +932,9 @@ This 3D Widget defines a collection of clouds. ::
WCloudCollection(); WCloudCollection();
//! Each point in cloud is mapped to a color in colors //! 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 //! All points in cloud have the same color
void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3f &pose = Affine3f::Identity()); void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3d &pose = Affine3d::Identity());
private:
/* hidden */
}; };
viz::WCloudCollection::WCloudCollection viz::WCloudCollection::WCloudCollection
@ -873,7 +947,7 @@ viz::WCloudCollection::addCloud
------------------------------- -------------------------------
Adds a cloud to the collection. 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 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. :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). 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 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. :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 class CV_EXPORTS WCloudNormals : public Widget3D
{ {
public: public:
WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); WCloudNormals(InputArray cloud, InputArray normals, int level = 100, double scale = 0.02f, const Color &color = Color::white());
private:
/* hidden */
}; };
viz::WCloudNormals::WCloudNormals viz::WCloudNormals::WCloudNormals
--------------------------------- ---------------------------------
Constructs a 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 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. :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 class CV_EXPORTS WMesh : public Widget3D
{ {
public: public:
WMesh(const Mesh3d &mesh); WMesh(const Mesh &mesh);
WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray());
private:
/* hidden */
}; };
viz::WMesh::WMesh viz::WMesh::WMesh
----------------- -----------------
Constructs a WMesh. Constructs a WMesh.
.. ocv:function:: WMesh(const Mesh3d &mesh) .. ocv:function:: WMesh(const Mesh &mesh)
:param mesh: :ocv:class:`Mesh3d` object that will be displayed. :param mesh: :ocv:class:`Mesh` object that will be displayed.
.. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray())
:param cloud: Points of the mesh object.
:param polygons: Points of the mesh object.
:param colors: Point colors.
:param normals: Point normals.

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#ifndef __OPENCV_VIZ_HPP__ #ifndef __OPENCV_VIZ_HPP__
@ -58,17 +55,20 @@ namespace cv
namespace viz namespace viz
{ {
//! takes coordiante frame data and builds transfrom to global coordinate frame //! 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) //! 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. //! 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(); 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 //! checks float value for Nan
inline bool isNan(float x) inline bool isNan(float x)
{ {
@ -91,6 +91,36 @@ namespace cv
template<typename _Tp> inline bool isNan(const Point3_<_Tp>& p) template<typename _Tp> inline bool isNan(const Point3_<_Tp>& p)
{ return isNan(p.x) || isNan(p.y) || isNan(p.z); } { 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 viz */
} /* namespace cv */ } /* namespace cv */

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#ifndef __OPENCV_VIZ_TYPES_HPP__ #ifndef __OPENCV_VIZ_TYPES_HPP__
@ -77,49 +74,99 @@ namespace cv
static Color white(); static Color white();
static Color gray(); 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: 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; Mat polygons;
//! Loads mesh from a given ply file Mat texture, tcoords;
static cv::viz::Mesh3d loadMesh(const String& file);
//! Loads mesh from a given ply file (no texture load support for now)
static Mesh load(const String& file);
};
class CV_EXPORTS Camera
{
public:
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);
const Vec2d & getClip() const { return clip_; }
void setClip(const Vec2d &clip) { clip_ = clip; }
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; }
const Vec2d& getPrincipalPoint() const { return principal_point_; }
const Vec2d& getFocalLength() const { return focal_; }
void computeProjectionMatrix(Matx44d &proj) const;
static Camera KinectCamera(const Size &window_size);
private: private:
struct loadMeshImpl; void init(double fx, double fy, double cx, double cy, const Size &window_size);
Vec2d clip_;
Vec2d fov_;
Size window_size_;
Vec2d principal_point_;
Vec2d focal_;
}; };
class CV_EXPORTS KeyboardEvent class CV_EXPORTS KeyboardEvent
{ {
public: public:
static const unsigned int Alt = 1; enum { NONE = 0, ALT = 1, CTRL = 2, SHIFT = 4 };
static const unsigned int Ctrl = 2; enum Action { KEY_UP = 0, KEY_DOWN = 1 };
static const unsigned int Shift = 4;
//! Create a keyboard event KeyboardEvent(Action action, const String& symbol, unsigned char code, int modifiers);
//! - Note that action is true if key is pressed, false if released
KeyboardEvent(bool action, const String& key_sym, unsigned char key, bool alt, bool ctrl, bool shift);
bool isAltPressed() const; Action action;
bool isCtrlPressed() const; String symbol;
bool isShiftPressed() const; unsigned char code;
int modifiers;
unsigned char getKeyCode() const;
const String& getKeySym() const;
bool keyDown() const;
bool keyUp() const;
protected:
bool action_;
unsigned int modifiers_;
unsigned char key_code_;
String key_sym_;
}; };
class CV_EXPORTS MouseEvent class CV_EXPORTS MouseEvent
@ -128,46 +175,12 @@ namespace cv
enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ; enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ;
enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ; 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; Type type;
MouseButton button; MouseButton button;
Point pointer; Point pointer;
unsigned int key_state; int modifiers;
};
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);
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);
private:
void init(float f_x, float f_y, float c_x, float c_y, const Size &window_size);
Vec2d clip_;
Vec2f fov_;
Size window_size_;
Vec2f principal_point_;
Vec2f focal_;
}; };
} /* namespace viz */ } /* namespace viz */
} /* namespace cv */ } /* 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(double _blue, double _green, double _red) : Scalar(_blue, _green, _red) {}
inline cv::viz::Color::Color(const Scalar& color) : Scalar(color) {} 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::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::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::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::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::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::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::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::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::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 #endif

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#ifndef __OPENCV_VIZ_VIZ3D_HPP__ #ifndef __OPENCV_VIZ_VIZ3D_HPP__
@ -64,6 +61,7 @@ namespace cv
class CV_EXPORTS Viz3d class CV_EXPORTS Viz3d
{ {
public: public:
typedef cv::viz::Color Color;
typedef void (*KeyboardCallback)(const KeyboardEvent&, void*); typedef void (*KeyboardCallback)(const KeyboardEvent&, void*);
typedef void (*MouseCallback)(const MouseEvent&, void*); typedef void (*MouseCallback)(const MouseEvent&, void*);
@ -72,19 +70,21 @@ namespace cv
Viz3d& operator=(const Viz3d&); Viz3d& operator=(const Viz3d&);
~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); void removeWidget(const String &id);
Widget getWidget(const String &id) const; Widget getWidget(const String &id) const;
void removeAllWidgets(); void removeAllWidgets();
void setWidgetPose(const String &id, const Affine3f &pose); void showImage(InputArray image, const Size& window_size = Size(-1, -1));
void updateWidgetPose(const String &id, const Affine3f &pose);
Affine3f getWidgetPose(const String &id) const; void setWidgetPose(const String &id, const Affine3d &pose);
void updateWidgetPose(const String &id, const Affine3d &pose);
Affine3d getWidgetPose(const String &id) const;
void setCamera(const Camera &camera); void setCamera(const Camera &camera);
Camera getCamera() const; Camera getCamera() const;
Affine3f getViewerPose(); Affine3d getViewerPose();
void setViewerPose(const Affine3f &pose); void setViewerPose(const Affine3d &pose);
void resetCameraViewpoint(const String &id); void resetCameraViewpoint(const String &id);
void resetCamera(); void resetCamera();
@ -96,13 +96,16 @@ namespace cv
void setWindowSize(const Size &window_size); void setWindowSize(const Size &window_size);
String getWindowName() const; String getWindowName() const;
void saveScreenshot(const String &file); void saveScreenshot(const String &file);
void setWindowPosition(int x, int y); void setWindowPosition(const Point& window_position);
void setFullScreen(bool mode); void setFullScreen(bool mode = true);
void setBackgroundColor(const Color& color = Color::black()); void setBackgroundColor(const Color& color = Color::black(), const Color& color2 = Color::not_set());
void setBackgroundTexture(InputArray image = noArray());
void setBackgroundMeshLab();
void spin(); void spin();
void spinOnce(int time = 1, bool force_redraw = false); void spinOnce(int time = 1, bool force_redraw = false);
bool wasStopped() const; bool wasStopped() const;
void close();
void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0);
void registerMouseCallback(MouseCallback 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); void setRenderingProperty(const String &id, int property, double value);
double getRenderingProperty(const String &id, int property); double getRenderingProperty(const String &id, int property);
void setDesiredUpdateRate(double rate);
double getDesiredUpdateRate();
void setRepresentation(int representation); void setRepresentation(int representation);
private: private:

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#ifndef __OPENCV_VIZ_WIDGET_ACCESSOR_HPP__ #ifndef __OPENCV_VIZ_WIDGET_ACCESSOR_HPP__

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#ifndef __OPENCV_VIZ_WIDGETS_HPP__ #ifndef __OPENCV_VIZ_WIDGETS_HPP__
@ -68,14 +65,14 @@ namespace cv
SHADING SHADING
}; };
enum RenderingRepresentationProperties enum RepresentationValues
{ {
REPRESENTATION_POINTS, REPRESENTATION_POINTS,
REPRESENTATION_WIREFRAME, REPRESENTATION_WIREFRAME,
REPRESENTATION_SURFACE REPRESENTATION_SURFACE
}; };
enum ShadingRepresentationProperties enum ShadingValues
{ {
SHADING_FLAT, SHADING_FLAT,
SHADING_GOURAUD, SHADING_GOURAUD,
@ -114,13 +111,15 @@ namespace cv
public: public:
Widget3D() {} Widget3D() {}
void setPose(const Affine3f &pose); //! widget position manipulation, i.e. place where it is rendered
void updatePose(const Affine3f &pose); void setPose(const Affine3d &pose);
Affine3f getPose() const; 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); void setColor(const Color &color);
private:
struct MatrixConverter;
}; };
@ -134,92 +133,94 @@ namespace cv
void setColor(const Color &color); void setColor(const Color &color);
}; };
/////////////////////////////////////////////////////////////////////////////
/// Simple widgets
class CV_EXPORTS WLine : public Widget3D class CV_EXPORTS WLine : public Widget3D
{ {
public: 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 class CV_EXPORTS WPlane : public Widget3D
{ {
public: public:
WPlane(const Vec4f& coefs, float size = 1.f, const Color &color = Color::white()); //! created default plane with center point at origin and normal oriented along z-axis
WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.f, const Color &color = Color::white()); WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white());
private:
struct SetSizeImpl; //! 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 class CV_EXPORTS WSphere : public Widget3D
{ {
public: 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 class CV_EXPORTS WArrow : public Widget3D
{ {
public: 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 class CV_EXPORTS WCircle : public Widget3D
{ {
public: 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 WCone : public Widget3D
{
public:
//! create default cone, oriented along x-axis with center of its base located at origin
WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white());
//! creates repositioned cone
WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white());
}; };
class CV_EXPORTS WCylinder : public Widget3D class CV_EXPORTS WCylinder : public Widget3D
{ {
public: 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());
}; };
class CV_EXPORTS WCube : public Widget3D class CV_EXPORTS WCube : public Widget3D
{ {
public: public:
WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, const Color &color = Color::white()); WCube(const Point3d& min_point = Vec3d::all(-0.5), const Point3d& max_point = Vec3d::all(0.5),
}; bool wire_frame = true, const Color &color = Color::white());
class CV_EXPORTS WCoordinateSystem : public Widget3D
{
public:
WCoordinateSystem(float scale = 1.f);
}; };
class CV_EXPORTS WPolyLine : public Widget3D class CV_EXPORTS WPolyLine : public Widget3D
{ {
public: public:
WPolyLine(InputArray points, const Color &color = Color::white()); WPolyLine(InputArray points, const Color &color = Color::white());
private:
struct CopyImpl;
}; };
class CV_EXPORTS WGrid : public Widget3D /////////////////////////////////////////////////////////////////////////////
/// Text and image widgets
class CV_EXPORTS WText : public Widget2D
{ {
public: public:
//! Creates grid at the origin WText(const String &text, const Point &pos, int font_size = 20, const Color &color = Color::white());
WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white());
//! Creates grid based on the plane equation
WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white());
private:
struct GridImpl;
};
class CV_EXPORTS WText3D : public Widget3D
{
public:
WText3D(const String &text, const Point3f &position, float text_scale = 1.f, bool face_camera = true, const Color &color = Color::white());
void setText(const String &text); void setText(const String &text);
String getText() const; String getText() const;
}; };
class CV_EXPORTS WText : public Widget2D class CV_EXPORTS WText3D : public Widget3D
{ {
public: 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); void setText(const String &text);
String getText() const; String getText() const;
@ -228,63 +229,91 @@ namespace cv
class CV_EXPORTS WImageOverlay : public Widget2D class CV_EXPORTS WImageOverlay : public Widget2D
{ {
public: public:
WImageOverlay(const Mat &image, const Rect &rect); WImageOverlay(InputArray image, const Rect &rect);
void setImage(InputArray image);
void setImage(const Mat &image);
}; };
class CV_EXPORTS WImage3D : public Widget3D class CV_EXPORTS WImage3D : public Widget3D
{ {
public: public:
//! Creates 3D image at the origin //! Creates 3D image in a plane centered at the origin with normal orientaion along z-axis,
WImage3D(const Mat &image, const Size &size); //! image x- and y-axes are oriented along x- and y-axes of 3d world
//! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation WImage3D(InputArray image, const Size2d &size);
WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size);
void setImage(const Mat &image); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation
WImage3D(InputArray image, const Size2d &size, const Vec3d &center, const Vec3d &normal, const Vec3d &up_vector);
void setImage(InputArray image);
};
/////////////////////////////////////////////////////////////////////////////
/// Compond widgets
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 class CV_EXPORTS WCameraPosition : public Widget3D
{ {
public: public:
//! Creates camera coordinate frame (axes) at the origin //! 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 //! 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 //! 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 //! 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 //! Creates frustum and display given image at the far plane
WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white());
private:
struct ProjectImage;
}; };
/////////////////////////////////////////////////////////////////////////////
/// Trajectories
class CV_EXPORTS WTrajectory : public Widget3D class CV_EXPORTS WTrajectory : public Widget3D
{ {
public: 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 //! Takes vector<Affine3<T>> and 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); WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white());
//! 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());
private:
struct ApplyPath;
}; };
class CV_EXPORTS WSpheresTrajectory: public Widget3D class CV_EXPORTS WTrajectoryFrustums : public Widget3D
{ {
public: public:
WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, //! Takes vector<Affine3<T>> and displays trajectory of the given path by frustums
float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); 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 WTrajectorySpheres: public Widget3D
{
public:
//! 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 class CV_EXPORTS WCloud: public Widget3D
{ {
public: public:
@ -292,9 +321,19 @@ namespace cv
WCloud(InputArray cloud, InputArray colors); WCloud(InputArray cloud, InputArray colors);
//! All points in cloud have the same color //! All points in cloud have the same color
WCloud(InputArray cloud, const Color &color = Color::white()); WCloud(InputArray cloud, const Color &color = Color::white());
};
private: class CV_EXPORTS WPaintedCloud: public Widget3D
struct CreateCloudWidget; {
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 class CV_EXPORTS WCloudCollection : public Widget3D
@ -303,32 +342,27 @@ namespace cv
WCloudCollection(); WCloudCollection();
//! Each point in cloud is mapped to a color in colors //! 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 //! All points in cloud have the same color
void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3f &pose = Affine3f::Identity()); void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3d &pose = Affine3d::Identity());
private:
struct CreateCloudWidget;
}; };
class CV_EXPORTS WCloudNormals : public Widget3D class CV_EXPORTS WCloudNormals : public Widget3D
{ {
public: public:
WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); WCloudNormals(InputArray cloud, InputArray normals, int level = 64, double scale = 0.1, const Color &color = Color::white());
private:
struct ApplyCloudNormals;
}; };
class CV_EXPORTS WMesh : public Widget3D class CV_EXPORTS WMesh : public Widget3D
{ {
public: public:
WMesh(const Mesh3d &mesh); WMesh(const Mesh &mesh);
WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray());
private:
struct CopyImpl;
}; };
/////////////////////////////////////////////////////////////////////////////
/// Utility exports
template<> CV_EXPORTS Widget2D Widget::cast<Widget2D>(); template<> CV_EXPORTS Widget2D Widget::cast<Widget2D>();
template<> CV_EXPORTS Widget3D Widget::cast<Widget3D>(); template<> CV_EXPORTS Widget3D Widget::cast<Widget3D>();
template<> CV_EXPORTS WLine Widget::cast<WLine>(); template<> CV_EXPORTS WLine Widget::cast<WLine>();
@ -337,6 +371,7 @@ namespace cv
template<> CV_EXPORTS WCylinder Widget::cast<WCylinder>(); template<> CV_EXPORTS WCylinder Widget::cast<WCylinder>();
template<> CV_EXPORTS WArrow Widget::cast<WArrow>(); template<> CV_EXPORTS WArrow Widget::cast<WArrow>();
template<> CV_EXPORTS WCircle Widget::cast<WCircle>(); template<> CV_EXPORTS WCircle Widget::cast<WCircle>();
template<> CV_EXPORTS WCone Widget::cast<WCone>();
template<> CV_EXPORTS WCube Widget::cast<WCube>(); template<> CV_EXPORTS WCube Widget::cast<WCube>();
template<> CV_EXPORTS WCoordinateSystem Widget::cast<WCoordinateSystem>(); template<> CV_EXPORTS WCoordinateSystem Widget::cast<WCoordinateSystem>();
template<> CV_EXPORTS WPolyLine Widget::cast<WPolyLine>(); template<> CV_EXPORTS WPolyLine Widget::cast<WPolyLine>();
@ -347,8 +382,10 @@ namespace cv
template<> CV_EXPORTS WImage3D Widget::cast<WImage3D>(); template<> CV_EXPORTS WImage3D Widget::cast<WImage3D>();
template<> CV_EXPORTS WCameraPosition Widget::cast<WCameraPosition>(); template<> CV_EXPORTS WCameraPosition Widget::cast<WCameraPosition>();
template<> CV_EXPORTS WTrajectory Widget::cast<WTrajectory>(); 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 WCloud Widget::cast<WCloud>();
template<> CV_EXPORTS WPaintedCloud Widget::cast<WPaintedCloud>();
template<> CV_EXPORTS WCloudCollection Widget::cast<WCloudCollection>(); template<> CV_EXPORTS WCloudCollection Widget::cast<WCloudCollection>();
template<> CV_EXPORTS WCloudNormals Widget::cast<WCloudNormals>(); template<> CV_EXPORTS WCloudNormals Widget::cast<WCloudNormals>();
template<> CV_EXPORTS WMesh Widget::cast<WMesh>(); template<> CV_EXPORTS WMesh Widget::cast<WMesh>();

View File

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

441
modules/viz/src/clouds.cpp Normal file
View File

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

View File

@ -48,20 +48,21 @@
#include "precomp.hpp" #include "precomp.hpp"
namespace cv { namespace viz
{
vtkStandardNewMacro(InteractorStyle)
}}
////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::InteractorStyle::Initialize() void cv::viz::InteractorStyle::Initialize()
{ {
modifier_ = cv::viz::InteractorStyle::KB_MOD_ALT;
// Set windows size (width, height) to unknown (-1) // Set windows size (width, height) to unknown (-1)
win_size_ = Vec2i(-1, -1); win_size_ = Vec2i(-1, -1);
win_pos_ = Vec2i(0, 0); win_pos_ = Vec2i(0, 0);
max_win_size_ = Vec2i(-1, -1); 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; init_ = true;
stereo_anaglyph_mask_default_ = true; stereo_anaglyph_mask_default_ = true;
@ -78,11 +79,37 @@ void cv::viz::InteractorStyle::Initialize()
void cv::viz::InteractorStyle::saveScreenshot(const String &file) void cv::viz::InteractorStyle::saveScreenshot(const String &file)
{ {
FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]);
wif_->SetInput(Interactor->GetRenderWindow());
wif_->Modified(); // Update the WindowToImageFilter vtkSmartPointer<vtkWindowToImageFilter> wif = vtkSmartPointer<vtkWindowToImageFilter>::New();
snapshot_writer_->Modified(); wif->SetInput(Interactor->GetRenderWindow());
snapshot_writer_->SetFileName(file.c_str());
snapshot_writer_->Write(); 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) else if (key.find("XF86ZoomOut") != String::npos)
zoomOut(); zoomOut();
int keymod = false; int keymod = Interactor->GetAltKey();
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;
}
switch (Interactor->GetKeyCode()) 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; } int cv::viz::InteractorStyle::getModifiers()
bool cv::viz::InteractorStyle::getShiftKey() { return Interactor->GetShiftKey()!= 0; } {
bool cv::viz::InteractorStyle::getControlKey() { return Interactor->GetControlKey()!= 0; } 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 void cv::viz::InteractorStyle::OnKeyDown()
cv::viz::InteractorStyle::OnKeyDown()
{ {
CV_Assert("Interactor style not initialized. Please call Initialize() before continuing" && init_); 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]); 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 // Save the initial windows width/height
if (win_size_[0] == -1 || win_size_[1] == -1) if (win_size_[0] == -1 || win_size_[1] == -1)
win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize());
bool alt = Interactor->GetAltKey() != 0;
// 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;
}
std::string key(Interactor->GetKeySym()); std::string key(Interactor->GetKeySym());
if (key.find("XF86ZoomIn") != std::string::npos) 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" " s, S : switch to a surface-based representation (where available)\n"
"\n" "\n"
" j, J : take a .PNG snapshot of the current window view\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" " 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" "\n"
" e, E : exit the interactor\n" " e, E : exit the interactor\n"
" q, Q : stop and call VTK's TerminateApp\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 + s, S : turn stereo mode on/off\n"
" ALT + f, F : switch between maximized window mode and original size\n" " ALT + f, F : switch between maximized window mode and original size\n"
"\n" "\n"
<< std::endl; << std::endl;
break; break;
} }
@ -261,66 +273,41 @@ cv::viz::InteractorStyle::OnKeyDown()
for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); )
for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) 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(); apart->GetProperty()->SetRepresentationToPoints();
} }
break; break;
} }
// Save a PNG snapshot with the current screen
// Save a PNG snapshot
case 'j': case 'J': case 'j': case 'J':
saveScreenshot(cv::format("screenshot-%d.png", (unsigned int)time(0))); break;
// Export scene as in obj or vrml format
case 'k': case 'K':
{ {
unsigned int t = static_cast<unsigned int>(time(0)); String format = alt ? "scene-%d.vrml" : "scene-%d";
String png_file = cv::format("screenshot-%d.png", t); exportScene(cv::format(format.c_str(), (unsigned int)time(0)));
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();
cout << "Screenshot (" << png_file.c_str() << ") and camera information (" << cam_file.c_str() << ") successfully captured." << endl;
break; break;
} }
// display current camera settings/parameters // display current camera settings/parameters
case 'c': case 'C': case 'c': case 'C':
{ {
vtkSmartPointer<vtkCamera> cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); vtkSmartPointer<vtkCamera> cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera();
Vec2d clip; Vec2d clip(cam->GetClippingRange());
Vec3d focal, pose, view; Vec3d focal(cam->GetFocalPoint()), pos(cam->GetPosition()), view(cam->GetViewUp());
cam->GetClippingRange(clip.val);
cam->GetFocalPoint(focal.val);
cam->GetPosition(pose.val);
cam->GetViewUp(view.val);
Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition());
Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); 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; break;
} }
case '=': case '=':
@ -339,7 +326,7 @@ cv::viz::InteractorStyle::OnKeyDown()
for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); )
for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) 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(); float psize = apart->GetProperty()->GetPointSize();
if (psize < 63.0f) if (psize < 63.0f)
apart->GetProperty()->SetPointSize(psize + 1.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 (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); )
for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) 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(); float psize = apart->GetProperty()->GetPointSize();
if (psize > 1.0f) if (psize > 1.0f)
apart->GetProperty()->SetPointSize(psize - 1.0f); apart->GetProperty()->SetPointSize(psize - 1.0f);
@ -369,7 +356,7 @@ cv::viz::InteractorStyle::OnKeyDown()
// Switch between maximize and original window size // Switch between maximize and original window size
case 'f': case 'F': case 'f': case 'F':
{ {
if (keymod) if (alt)
{ {
Vec2i screen_size(Interactor->GetRenderWindow()->GetScreenSize()); Vec2i screen_size(Interactor->GetRenderWindow()->GetScreenSize());
Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); Vec2i win_size(Interactor->GetRenderWindow()->GetSize());
@ -397,13 +384,11 @@ cv::viz::InteractorStyle::OnKeyDown()
else else
{ {
AnimState = VTKIS_ANIM_ON; AnimState = VTKIS_ANIM_ON;
vtkAssemblyPath *path = NULL;
Interactor->GetPicker()->Pick(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1], 0.0, CurrentRenderer); Interactor->GetPicker()->Pick(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1], 0.0, CurrentRenderer);
vtkAbstractPropPicker *picker; vtkSmartPointer<vtkAbstractPropPicker> picker = vtkAbstractPropPicker::SafeDownCast(Interactor->GetPicker());
if ((picker = vtkAbstractPropPicker::SafeDownCast(Interactor->GetPicker()))) if (picker)
path = picker->GetPath(); if (picker->GetPath())
if (path != NULL) Interactor->FlyTo(CurrentRenderer, picker->GetPickPosition());
Interactor->FlyTo(CurrentRenderer, picker->GetPickPosition());
AnimState = VTKIS_ANIM_OFF; AnimState = VTKIS_ANIM_OFF;
} }
break; break;
@ -411,24 +396,16 @@ cv::viz::InteractorStyle::OnKeyDown()
// 's'/'S' w/out ALT // 's'/'S' w/out ALT
case 's': case 'S': case 's': case 'S':
{ {
if (keymod) if (alt)
{ {
int stereo_render = Interactor->GetRenderWindow()->GetStereoRender(); vtkSmartPointer<vtkRenderWindow> window = Interactor->GetRenderWindow();
if (!stereo_render) if (!window->GetStereoRender())
{ {
if (stereo_anaglyph_mask_default_) static Vec2i red_blue(4, 3), magenta_green(2, 5);
{ window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? red_blue.val : magenta_green.val);
Interactor->GetRenderWindow()->SetAnaglyphColorMask(4, 3); stereo_anaglyph_mask_default_ = !stereo_anaglyph_mask_default_;
stereo_anaglyph_mask_default_ = false;
}
else
{
Interactor->GetRenderWindow()->SetAnaglyphColorMask(2, 5);
stereo_anaglyph_mask_default_ = true;
}
} }
Interactor->GetRenderWindow()->SetStereoRender(!stereo_render); window->SetStereoRender(!window->GetStereoRender());
Interactor->GetRenderWindow()->Render();
Interactor->Render(); Interactor->Render();
} }
else else
@ -440,43 +417,34 @@ cv::viz::InteractorStyle::OnKeyDown()
{ {
vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera(); vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera();
cam->SetParallelProjection(!cam->GetParallelProjection()); cam->SetParallelProjection(!cam->GetParallelProjection());
CurrentRenderer->SetActiveCamera(cam);
CurrentRenderer->Render(); CurrentRenderer->Render();
break; break;
} }
// Overwrite the camera reset // Overwrite the camera reset
case 'r': case 'R': case 'r': case 'R':
{ {
if (!keymod) if (!alt)
{ {
Superclass::OnKeyDown(); Superclass::OnKeyDown();
break; break;
} }
vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera(); WidgetActorMap::iterator it = widget_actor_map_->begin();
static WidgetActorMap::iterator it = widget_actor_map_->begin();
// it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault. // 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 (; it != widget_actor_map_->end(); ++it)
for (size_t idx = 0; idx < widget_actor_map_->size(); ++idx, ++it)
{ {
if (it == widget_actor_map_->end())
it = widget_actor_map_->begin();
vtkProp3D * actor = vtkProp3D::SafeDownCast(it->second); vtkProp3D * actor = vtkProp3D::SafeDownCast(it->second);
if (actor && actor->GetUserMatrix()) if (actor && actor->GetUserMatrix())
{
found_transformation = true;
break; break;
}
} }
vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera();
// if a valid transformation was found, use it otherwise fall back to default view point. // 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), cam->SetFocalPoint(m->GetElement(0, 3) - m->GetElement(0, 2),
m->GetElement(1, 3) - m->GetElement(1, 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()); KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers());
// Check if there is a keyboard callback registered
if (keyboardCallback_) if (keyboardCallback_)
keyboardCallback_(event, keyboard_callback_cookie_); keyboardCallback_(event, keyboard_callback_cookie_);
renderer_->Render();
Interactor->Render(); Interactor->Render();
} }
////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::InteractorStyle::OnKeyUp() void cv::viz::InteractorStyle::OnKeyUp()
{ {
KeyboardEvent event(false, Interactor->GetKeySym(), Interactor->GetKeyCode(), getAltKey(), getControlKey(), getShiftKey()); KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers());
// Check if there is a keyboard callback registered
if (keyboardCallback_) if (keyboardCallback_)
keyboardCallback_(event, keyboard_callback_cookie_); keyboardCallback_(event, keyboard_callback_cookie_);
Superclass::OnKeyUp(); Superclass::OnKeyUp();
} }
@ -540,9 +503,9 @@ void cv::viz::InteractorStyle::OnKeyUp()
void cv::viz::InteractorStyle::OnMouseMove() void cv::viz::InteractorStyle::OnMouseMove()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getAltKey(), getControlKey(), getShiftKey()); MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getModifiers());
if (mouseCallback_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnMouseMove(); Superclass::OnMouseMove();
} }
@ -551,9 +514,9 @@ void cv::viz::InteractorStyle::OnLeftButtonDown()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; 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_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnLeftButtonDown(); Superclass::OnLeftButtonDown();
} }
@ -561,9 +524,9 @@ void cv::viz::InteractorStyle::OnLeftButtonDown()
void cv::viz::InteractorStyle::OnLeftButtonUp() void cv::viz::InteractorStyle::OnLeftButtonUp()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getAltKey(), getControlKey(), getShiftKey()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getModifiers());
if (mouseCallback_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnLeftButtonUp(); Superclass::OnLeftButtonUp();
} }
@ -571,11 +534,10 @@ void cv::viz::InteractorStyle::OnLeftButtonUp()
void cv::viz::InteractorStyle::OnMiddleButtonDown() void cv::viz::InteractorStyle::OnMiddleButtonDown()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; 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_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnMiddleButtonDown(); Superclass::OnMiddleButtonDown();
} }
@ -583,9 +545,9 @@ void cv::viz::InteractorStyle::OnMiddleButtonDown()
void cv::viz::InteractorStyle::OnMiddleButtonUp() void cv::viz::InteractorStyle::OnMiddleButtonUp()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getAltKey(), getControlKey(), getShiftKey()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getModifiers());
if (mouseCallback_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnMiddleButtonUp(); Superclass::OnMiddleButtonUp();
} }
@ -593,11 +555,10 @@ void cv::viz::InteractorStyle::OnMiddleButtonUp()
void cv::viz::InteractorStyle::OnRightButtonDown() void cv::viz::InteractorStyle::OnRightButtonDown()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; 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_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnRightButtonDown(); Superclass::OnRightButtonDown();
} }
@ -605,9 +566,9 @@ void cv::viz::InteractorStyle::OnRightButtonDown()
void cv::viz::InteractorStyle::OnRightButtonUp() void cv::viz::InteractorStyle::OnRightButtonUp()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getAltKey(), getControlKey(), getShiftKey()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getModifiers());
if (mouseCallback_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
Superclass::OnRightButtonUp(); Superclass::OnRightButtonUp();
} }
@ -615,12 +576,11 @@ void cv::viz::InteractorStyle::OnRightButtonUp()
void cv::viz::InteractorStyle::OnMouseWheelForward() void cv::viz::InteractorStyle::OnMouseWheelForward()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getAltKey(), getControlKey(), getShiftKey()); MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers());
// If a mouse callback registered, call it!
if (mouseCallback_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
if (Interactor->GetRepeatCount() && mouseCallback_) if (Interactor->GetRepeatCount() && mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
if (Interactor->GetAltKey()) if (Interactor->GetAltKey())
{ {
@ -632,11 +592,9 @@ void cv::viz::InteractorStyle::OnMouseWheelForward()
cam->SetViewAngle(opening_angle); cam->SetViewAngle(opening_angle);
cam->Modified(); cam->Modified();
CurrentRenderer->SetActiveCamera(cam);
CurrentRenderer->ResetCameraClippingRange(); CurrentRenderer->ResetCameraClippingRange();
CurrentRenderer->Modified(); CurrentRenderer->Modified();
CurrentRenderer->Render(); CurrentRenderer->Render();
renderer_->Render();
Interactor->Render(); Interactor->Render();
} }
else else
@ -647,13 +605,12 @@ void cv::viz::InteractorStyle::OnMouseWheelForward()
void cv::viz::InteractorStyle::OnMouseWheelBackward() void cv::viz::InteractorStyle::OnMouseWheelBackward()
{ {
Vec2i p(Interactor->GetEventPosition()); Vec2i p(Interactor->GetEventPosition());
MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getAltKey(), getControlKey(), getShiftKey()); MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers());
// If a mouse callback registered, call it!
if (mouseCallback_) if (mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
if (Interactor->GetRepeatCount() && mouseCallback_) if (Interactor->GetRepeatCount() && mouseCallback_)
mouseCallback_(event, mouse_callback_cookie_); mouseCallback_(event, mouse_callback_cookie_);
if (Interactor->GetAltKey()) if (Interactor->GetAltKey())
{ {
@ -665,11 +622,9 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward()
cam->SetViewAngle(opening_angle); cam->SetViewAngle(opening_angle);
cam->Modified(); cam->Modified();
CurrentRenderer->SetActiveCamera(cam);
CurrentRenderer->ResetCameraClippingRange(); CurrentRenderer->ResetCameraClippingRange();
CurrentRenderer->Modified(); CurrentRenderer->Modified();
CurrentRenderer->Render(); CurrentRenderer->Render();
renderer_->Render();
Interactor->Render(); Interactor->Render();
} }
else else
@ -680,13 +635,5 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward()
void cv::viz::InteractorStyle::OnTimer() void cv::viz::InteractorStyle::OnTimer()
{ {
CV_Assert("Interactor style not initialized." && init_); CV_Assert("Interactor style not initialized." && init_);
CV_Assert("Renderer has not been set." && renderer_);
renderer_->Render();
Interactor->Render(); Interactor->Render();
} }
namespace cv { namespace viz
{
//Standard VTK macro for *New()
vtkStandardNewMacro(InteractorStyle)
}}

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#ifndef __OPENCV_VIZ_INTERACTOR_STYLE_H__ #ifndef __OPENCV_VIZ_INTERACTOR_STYLE_H__
@ -56,9 +53,6 @@ namespace cv
class InteractorStyle : public vtkInteractorStyleTrackballCamera class InteractorStyle : public vtkInteractorStyleTrackballCamera
{ {
public: public:
enum KeyboardModifier { KB_MOD_ALT, KB_MOD_CTRL, KB_MOD_SHIFT };
static InteractorStyle *New(); static InteractorStyle *New();
virtual ~InteractorStyle() {} virtual ~InteractorStyle() {}
@ -69,31 +63,21 @@ namespace cv
virtual void Initialize(); virtual void Initialize();
void setWidgetActorMap(const Ptr<WidgetActorMap>& actors) { widget_actor_map_ = actors; } 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 registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0);
void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0);
void saveScreenshot(const String &file); void saveScreenshot(const String &file);
void exportScene(const String &file);
/** \brief Change the default keyboard modified from ALT to a different special key.*/
inline void setKeyboardModifier(const KeyboardModifier &modifier) { modifier_ = modifier; }
private: private:
/** \brief Set to true after initialization is complete. */ /** \brief Set to true after initialization is complete. */
bool init_; bool init_;
vtkSmartPointer<vtkRenderer> renderer_;
Ptr<WidgetActorMap> widget_actor_map_; Ptr<WidgetActorMap> widget_actor_map_;
Vec2i win_size_; Vec2i win_size_;
Vec2i win_pos_; Vec2i win_pos_;
Vec2i max_win_size_; 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. */ /** \brief Interactor style internal method. Gets called whenever a key is pressed. */
virtual void OnChar(); 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. */ /** \brief True if we're using red-blue colors for anaglyphic stereo, false if magenta-green. */
bool stereo_anaglyph_mask_default_; bool stereo_anaglyph_mask_default_;
KeyboardModifier modifier_;
void (*keyboardCallback_)(const KeyboardEvent&, void*); void (*keyboardCallback_)(const KeyboardEvent&, void*);
void *keyboard_callback_cookie_; void *keyboard_callback_cookie_;
void (*mouseCallback_)(const MouseEvent&, void*); void (*mouseCallback_)(const MouseEvent&, void*);
void *mouse_callback_cookie_; void *mouse_callback_cookie_;
bool getAltKey(); int getModifiers();
bool getControlKey();
bool getShiftKey();
}; };
} }
} }

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#ifndef __OPENCV_VIZ_PRECOMP_HPP__ #ifndef __OPENCV_VIZ_PRECOMP_HPP__
@ -53,6 +50,8 @@
#include <ctime> #include <ctime>
#include <list> #include <list>
#include <vector> #include <vector>
#include <iomanip>
#include <limits>
#include <vtkAppendPolyData.h> #include <vtkAppendPolyData.h>
#include <vtkAssemblyPath.h> #include <vtkAssemblyPath.h>
@ -94,13 +93,13 @@
#include <vtkInteractorStyleTrackballCamera.h> #include <vtkInteractorStyleTrackballCamera.h>
#include <vtkProperty.h> #include <vtkProperty.h>
#include <vtkCamera.h> #include <vtkCamera.h>
#include <vtkObjectFactory.h>
#include <vtkPlanes.h> #include <vtkPlanes.h>
#include <vtkImageFlip.h> #include <vtkImageFlip.h>
#include <vtkRenderWindow.h> #include <vtkRenderWindow.h>
#include <vtkTextProperty.h> #include <vtkTextProperty.h>
#include <vtkProperty2D.h> #include <vtkProperty2D.h>
#include <vtkLODActor.h> #include <vtkLODActor.h>
#include <vtkActor.h>
#include <vtkTextActor.h> #include <vtkTextActor.h>
#include <vtkRenderWindowInteractor.h> #include <vtkRenderWindowInteractor.h>
#include <vtkMath.h> #include <vtkMath.h>
@ -110,12 +109,50 @@
#include <vtkPolyDataNormals.h> #include <vtkPolyDataNormals.h>
#include <vtkAlgorithmOutput.h> #include <vtkAlgorithmOutput.h>
#include <vtkImageMapper.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/core.hpp>
#include <opencv2/viz.hpp> #include <opencv2/viz.hpp>
#include <opencv2/viz/widget_accessor.hpp> #include <opencv2/viz/widget_accessor.hpp>
#include <opencv2/core/utility.hpp> #include <opencv2/core/utility.hpp>
namespace cv namespace cv
{ {
namespace viz namespace viz
@ -144,11 +181,145 @@ namespace cv
static VizMap storage; static VizMap storage;
friend class Viz3d; 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 "interactor_style.hpp"
#include "viz3d_impl.hpp" #include "vizimpl.hpp"
#endif #endif

File diff suppressed because it is too large Load Diff

1088
modules/viz/src/shapes.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -41,138 +41,63 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
/// cv::viz::KeyboardEvent /// Events
cv::viz::KeyboardEvent::KeyboardEvent(bool _action, const String& _key_sym, unsigned char key, bool alt, bool ctrl, bool shift) cv::viz::KeyboardEvent::KeyboardEvent(Action _action, const String& _symbol, unsigned char _code, int _modifiers)
: action_(_action), modifiers_(0), key_code_(key), key_sym_(_key_sym) : action(_action), symbol(_symbol), code(_code), modifiers(_modifiers) {}
{
if (alt)
modifiers_ = Alt;
if (ctrl) cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, const Point& _pointer, int _modifiers)
modifiers_ |= Ctrl; : type(_type), button(_button), pointer(_pointer), modifiers(_modifiers) {}
if (shift)
modifiers_ |= Shift;
}
bool cv::viz::KeyboardEvent::isAltPressed() const { return (modifiers_ & Alt) != 0; }
bool cv::viz::KeyboardEvent::isCtrlPressed() const { return (modifiers_ & Ctrl) != 0; }
bool cv::viz::KeyboardEvent::isShiftPressed() const { return (modifiers_ & Shift) != 0; }
unsigned char cv::viz::KeyboardEvent::getKeyCode() const { return key_code_; }
const cv::String& cv::viz::KeyboardEvent::getKeySym() const { return key_sym_; }
bool cv::viz::KeyboardEvent::keyDown() const { return action_; }
bool cv::viz::KeyboardEvent::keyUp() const { return !action_; }
////////////////////////////////////////////////////////////////////
/// cv::viz::MouseEvent
cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, const Point& _p, bool alt, bool ctrl, bool shift)
: type(_type), button(_button), pointer(_p), key_state(0)
{
if (alt)
key_state = KeyboardEvent::Alt;
if (ctrl)
key_state |= KeyboardEvent::Ctrl;
if (shift)
key_state |= KeyboardEvent::Shift;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
/// cv::viz::Mesh3d /// 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; *poly_ptr++ = nr_cell_points;
for (vtkIdType i = 0; i < nr_cell_points; ++i)
vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New(); *poly_ptr++ = (int)cell_points[i];
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;
} }
};
cv::viz::Mesh3d cv::viz::Mesh3d::loadMesh(const String& file) return mesh;
{
return loadMeshImpl::loadMesh(file);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
/// Camera implementation /// 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); CV_Assert(window_size.width > 0 && window_size.height > 0);
setClip(Vec2d(0.01, 1000.01)); // Default clipping 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)); 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); double f_x = K(0,0);
float f_y = K(1,1); double f_y = K(1,1);
float c_x = K(0,2); double c_x = K(0,2);
float c_y = K(1,2); double c_y = K(1,2);
init(f_x, f_y, c_x, c_y, window_size); 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); 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; double epsilon = 2.2204460492503131e-16;
if (fabs(left-right) < epsilon) principal_point_[0] = static_cast<float>(window_size.width) * 0.5f; principal_point_[0] = fabs(left-right) < epsilon ? window_size.width * 0.5 : (left * window_size.width) / (left - right);
else principal_point_[0] = (left * static_cast<float>(window_size.width)) / (left - right); principal_point_[1] = fabs(top-bottom) < epsilon ? window_size.height * 0.5 : (top * window_size.height) / (top - bottom);
focal_[0] = -near * principal_point_[0] / left;
if (fabs(top-bottom) < epsilon) principal_point_[1] = static_cast<float>(window_size.height) * 0.5f; focal_[0] = -near * principal_point_[0] / left;
else principal_point_[1] = (top * static_cast<float>(window_size.height)) / (top - bottom); focal_[1] = near * principal_point_[1] / top;
focal_[1] = near * principal_point_[1] / top;
setClip(Vec2d(near, far)); setClip(Vec2d(near, far));
fov_[0] = (atan2(principal_point_[0],focal_[0]) + atan2(window_size.width-principal_point_[0],focal_[0])); 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_[1] = atan2(principal_point_[1], focal_[1]) + atan2(window_size.height-principal_point_[1], focal_[1]);
window_size_ = window_size; window_size_ = window_size;
} }
void cv::viz::Camera::init(float f_x, float f_y, float c_x, float c_y, const Size &window_size) void cv::viz::Camera::init(double fx, double fy, double cx, double cy, const Size &window_size)
{ {
CV_Assert(window_size.width > 0 && window_size.height > 0); CV_Assert(window_size.width > 0 && window_size.height > 0);
setClip(Vec2d(0.01, 1000.01));// Default clipping setClip(Vec2d(0.01, 1000.01));// Default clipping
fov_[0] = (atan2(c_x,f_x) + atan2(window_size.width-c_x,f_x)); fov_[0] = atan2(cx, fx) + atan2(window_size.width - cx, fx);
fov_[1] = (atan2(c_y,f_y) + atan2(window_size.height-c_y,f_y)); fov_[1] = atan2(cy, fy) + atan2(window_size.height - cy, fy);
principal_point_[0] = c_x; principal_point_[0] = cx;
principal_point_[1] = c_y; principal_point_[1] = cy;
focal_[0] = f_x; focal_[0] = fx;
focal_[1] = f_y; focal_[1] = fy;
window_size_ = window_size; window_size_ = window_size;
} }
@ -254,7 +177,7 @@ void cv::viz::Camera::setWindowSize(const Size &window_size)
window_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 top = clip_[0] * principal_point_[1] / focal_[1];
double left = -clip_[0] * principal_point_[0] / focal_[0]; 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) cv::viz::Camera cv::viz::Camera::KinectCamera(const Size &window_size)
{ {
// Without distortion, RGB Camera Matx33d K(525.0, 0.0, 320.0, 0.0, 525.0, 240.0, 0.0, 0.0, 1.0);
// 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;
return Camera(K, window_size); return Camera(K, window_size);
} }

View File

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

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
@ -104,6 +101,7 @@ void cv::viz::Viz3d::release()
void cv::viz::Viz3d::spin() { impl_->spin(); } void cv::viz::Viz3d::spin() { impl_->spin(); }
void cv::viz::Viz3d::spinOnce(int time, bool force_redraw) { impl_->spinOnce(time, force_redraw); } void cv::viz::Viz3d::spinOnce(int time, bool force_redraw) { impl_->spinOnce(time, force_redraw); }
bool cv::viz::Viz3d::wasStopped() const { return impl_->wasStopped(); } 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) void cv::viz::Viz3d::registerKeyboardCallback(KeyboardCallback callback, void* cookie)
{ impl_->registerKeyboardCallback(callback, 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) void cv::viz::Viz3d::registerMouseCallback(MouseCallback callback, void* cookie)
{ impl_->registerMouseCallback(callback, 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); } 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); } 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::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); } void cv::viz::Viz3d::showImage(InputArray image, const Size& window_size) { impl_->showImage(image, window_size); }
cv::Affine3f cv::viz::Viz3d::getWidgetPose(const String &id) const { return impl_->getWidgetPose(id); }
void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3d &pose) { impl_->setWidgetPose(id, pose); }
void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3d &pose) { impl_->updateWidgetPose(id, pose); }
cv::Affine3d cv::viz::Viz3d::getWidgetPose(const String &id) const { return impl_->getWidgetPose(id); }
void cv::viz::Viz3d::setCamera(const Camera &camera) { impl_->setCamera(camera); } void cv::viz::Viz3d::setCamera(const Camera &camera) { impl_->setCamera(camera); }
cv::viz::Camera cv::viz::Viz3d::getCamera() const { return impl_->getCamera(); } cv::viz::Camera cv::viz::Viz3d::getCamera() const { return impl_->getCamera(); }
void cv::viz::Viz3d::setViewerPose(const Affine3f &pose) { impl_->setViewerPose(pose); } void cv::viz::Viz3d::setViewerPose(const Affine3d &pose) { impl_->setViewerPose(pose); }
cv::Affine3f cv::viz::Viz3d::getViewerPose() { return impl_->getViewerPose(); } cv::Affine3d cv::viz::Viz3d::getViewerPose() { return impl_->getViewerPose(); }
void cv::viz::Viz3d::resetCameraViewpoint(const String &id) { impl_->resetCameraViewpoint(id); } void cv::viz::Viz3d::resetCameraViewpoint(const String &id) { impl_->resetCameraViewpoint(id); }
void cv::viz::Viz3d::resetCamera() { impl_->resetCamera(); } 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); } 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(); } 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(); } 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::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::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); } 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); } 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); } void cv::viz::Viz3d::setRepresentation(int representation) { impl_->setRepresentation(representation); }

View File

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

312
modules/viz/src/vizcore.cpp Normal file
View File

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

View File

@ -41,94 +41,143 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew();
#if 1 || !defined __APPLE__
vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew()
{
return vtkRenderWindowInteractor::New();
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
cv::viz::Viz3d::VizImpl::VizImpl(const String &name) cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false),
: s_lastDone_(0.0), style_(vtkSmartPointer<cv::viz::InteractorStyle>::New()), widget_actor_map_(new WidgetActorMap) window_position_(Vec2i(std::numeric_limits<int>::min())), widget_actor_map_(new WidgetActorMap)
{ {
renderer_ = vtkSmartPointer<vtkRenderer>::New(); renderer_ = vtkSmartPointer<vtkRenderer>::New();
window_name_ = VizStorage::generateWindowName(name);
// Create a RendererWindow // Create render window
window_ = vtkSmartPointer<vtkRenderWindow>::New(); window_ = vtkSmartPointer<vtkRenderWindow>::New();
// Set the window size as 1/2 of the screen size
cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2;
window_->SetSize(window_size.val); window_->SetSize(window_size.val);
window_->AddRenderer(renderer_); window_->AddRenderer(renderer_);
// Create the interactor style // Create the interactor style
style_->Initialize(); style_ = vtkSmartPointer<InteractorStyle>::New();
style_->setRenderer(renderer_);
style_->setWidgetActorMap(widget_actor_map_); style_->setWidgetActorMap(widget_actor_map_);
style_->UseTimersOn(); style_->UseTimersOn();
style_->Initialize();
///////////////////////////////////////////////// timer_callback_ = vtkSmartPointer<TimerCallback>::New();
interactor_ = vtkSmartPointer<vtkRenderWindowInteractor>::Take(vtkRenderWindowInteractorFixNew()); exit_callback_ = vtkSmartPointer<ExitCallback>::New();
exit_callback_->viz = this;
}
/////////////////////////////////////////////////////////////////////////////////////////////
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();
}
}
void cv::viz::Viz3d::VizImpl::ExitCallback::Execute(vtkObject*, unsigned long event_id, void*)
{
if (event_id == vtkCommand::ExitEvent)
{
viz->interactor_->TerminateApp();
viz->interactor_ = 0;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
bool cv::viz::Viz3d::VizImpl::wasStopped() const
{
bool stopped = spin_once_state_ ? interactor_ == 0 : false;
spin_once_state_ &= !stopped;
return stopped;
}
void cv::viz::Viz3d::VizImpl::close()
{
if (!interactor_)
return;
interactor_->GetRenderWindow()->Finalize();
interactor_->TerminateApp(); // This tends to close the window...
interactor_ = 0;
}
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);
window_->SetSize(window_size.val);
window_->SetFullScreen(fullscreen);
window_->AddRenderer(renderer_);
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::spin()
{
recreateRenderWindow();
interactor_ = vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor_->SetRenderWindow(window_);
interactor_->SetInteractorStyle(style_);
window_->AlphaBitPlanesOff(); window_->AlphaBitPlanesOff();
window_->PointSmoothingOff(); window_->PointSmoothingOff();
window_->LineSmoothingOff(); window_->LineSmoothingOff();
window_->PolygonSmoothingOff(); window_->PolygonSmoothingOff();
window_->SwapBuffersOn(); window_->SwapBuffersOn();
window_->SetStereoTypeToAnaglyph(); window_->SetStereoTypeToAnaglyph();
window_->Render();
interactor_->SetRenderWindow(window_); window_->SetWindowName(window_name_.c_str());
interactor_->SetInteractorStyle(style_); interactor_->Start();
interactor_->SetDesiredUpdateRate(30.0); 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);
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_);
exit_callback_ = vtkSmartPointer<ExitCallback>::New();
exit_callback_->viz_ = this;
interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_);
resetStoppedFlag();
//////////////////////////////
String window_name = VizStorage::generateWindowName(name);
window_->SetWindowName(window_name.c_str());
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
cv::viz::Viz3d::VizImpl::~VizImpl() void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw)
{ {
if (interactor_) if (interactor_ == 0)
interactor_->DestroyTimer(timer_id_); {
if (renderer_) spin_once_state_ = true;
renderer_->Clear(); 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); WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id);
bool exists = wam_itr != widget_actor_map_->end(); 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 (actor)
{ {
// If the actor is 3D, apply pose // If the actor is 3D, apply pose
vtkSmartPointer<vtkMatrix4x4> matrix = convertToVtkMatrix(pose.matrix); vtkSmartPointer<vtkMatrix4x4> matrix = vtkmatrix(pose.matrix);
actor->SetUserMatrix(matrix); actor->SetUserMatrix(matrix);
actor->Modified(); 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); WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id);
bool exists = wam_itr != widget_actor_map_->end(); 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); vtkProp3D *actor = vtkProp3D::SafeDownCast(wam_itr->second);
CV_Assert("Widget is not 3D." && actor); CV_Assert("Widget is not 3D." && actor);
vtkSmartPointer<vtkMatrix4x4> matrix = convertToVtkMatrix(pose.matrix); vtkSmartPointer<vtkMatrix4x4> matrix = vtkmatrix(pose.matrix);
actor->SetUserMatrix(matrix); actor->SetUserMatrix(matrix);
actor->Modified(); 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); WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id);
bool exists = wam_itr != widget_actor_map_->end(); 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); setWidgetPose(id, pose);
return ; return ;
} }
Matx44f matrix_cv = convertToMatx(matrix); Affine3d updated_pose = pose * Affine3d(*matrix->Element);
Affine3f updated_pose = pose * Affine3f(matrix_cv); matrix = vtkmatrix(updated_pose.matrix);
matrix = convertToVtkMatrix(updated_pose.matrix);
actor->SetUserMatrix(matrix); actor->SetUserMatrix(matrix);
actor->Modified(); 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); WidgetActorMap::const_iterator wam_itr = widget_actor_map_->find(id);
bool exists = wam_itr != widget_actor_map_->end(); 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); vtkProp3D *actor = vtkProp3D::SafeDownCast(wam_itr->second);
CV_Assert("Widget is not 3D." && actor); CV_Assert("Widget is not 3D." && actor);
vtkSmartPointer<vtkMatrix4x4> matrix = actor->GetUserMatrix(); return Affine3d(*actor->GetUserMatrix()->Element);
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;
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
@ -258,37 +289,6 @@ void cv::viz::Viz3d::VizImpl::registerMouseCallback(MouseCallback callback, void
void cv::viz::Viz3d::VizImpl::registerKeyboardCallback(KeyboardCallback callback, void* cookie) void cv::viz::Viz3d::VizImpl::registerKeyboardCallback(KeyboardCallback callback, void* cookie)
{ style_->registerKeyboardCallback(callback, 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() void cv::viz::Viz3d::VizImpl::removeAllWidgets()
@ -296,50 +296,98 @@ void cv::viz::Viz3d::VizImpl::removeAllWidgets()
widget_actor_map_->clear(); widget_actor_map_->clear();
renderer_->RemoveAllViewProps(); renderer_->RemoveAllViewProps();
} }
/////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::showImage(InputArray image, const Size& window_size)
{
removeAllWidgets();
if (window_size.width > 0 && window_size.height > 0)
setWindowSize(window_size);
showWidget("showImage", WImageOverlay(image, Rect(Point(0,0), getWindowSize())));
}
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(const vtkSmartPointer<vtkProp> &actor) bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer<vtkProp> actor)
{ {
vtkProp* actor_to_remove = vtkProp::SafeDownCast(actor);
vtkPropCollection* actors = renderer_->GetViewProps(); vtkPropCollection* actors = renderer_->GetViewProps();
actors->InitTraversal(); actors->InitTraversal();
vtkProp* current_actor = NULL; vtkProp* current_actor = NULL;
while ((current_actor = actors->GetNextProp()) != NULL) while ((current_actor = actors->GetNextProp()) != NULL)
{ if (current_actor == actor)
if (current_actor != actor_to_remove) {
continue; renderer_->RemoveActor(actor);
renderer_->RemoveActor(actor); return true;
return true; }
}
return false; return false;
} }
////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color, const Color& color2)
{ {
Color c = vtkcolor(color); Color c = vtkcolor(color), c2 = vtkcolor(color2);
renderer_->SetBackground(c.val); bool gradient = color2[0] >= 0 && color2[1] >= 0 && color2[2] >= 0;
if (gradient)
{
renderer_->SetBackground(c2.val);
renderer_->SetBackground2(c.val);
renderer_->GradientBackgroundOn();
}
else
{
renderer_->SetBackground(c.val);
renderer_->GradientBackgroundOff();
}
}
void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab()
{ setBackgroundColor(Color(2, 1, 1), Color(240, 120, 120)); }
//////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image)
{
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) 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 // Set the intrinsic parameters of the camera
window_->SetSize(camera.getWindowSize().width, camera.getWindowSize().height); window_->SetSize(camera.getWindowSize().width, camera.getWindowSize().height);
double aspect_ratio = static_cast<double>(camera.getWindowSize().width)/static_cast<double>(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); camera.computeProjectionMatrix(proj_mat);
// Use the intrinsic parameters of the camera to simulate more realistically // 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)); vtkSmartPointer<vtkMatrix4x4> vtk_matrix = active_camera->GetProjectionTransformMatrix(aspect_ratio, -1.0, 1.0);
vtkTransform *transform = vtkTransform::New(); Matx44d old_proj_mat(*vtk_matrix->Element);
// This is a hack around not being able to set Projection Matrix // This is a hack around not being able to set Projection Matrix
transform->SetMatrix(convertToVtkMatrix(proj_mat * old_proj_mat.inv())); vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
active_camera.SetUserTransform(transform); transform->SetMatrix(vtkmatrix(proj_mat * old_proj_mat.inv()));
transform->Delete(); active_camera->SetUserTransform(transform);
renderer_->ResetCameraClippingRange(); renderer_->ResetCameraClippingRange();
renderer_->Render(); renderer_->Render();
@ -348,44 +396,42 @@ void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera)
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
cv::viz::Camera cv::viz::Viz3d::VizImpl::getCamera() const 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], Size window_size(renderer_->GetRenderWindow()->GetSize()[0],
renderer_->GetRenderWindow()->GetSize()[1]); renderer_->GetRenderWindow()->GetSize()[1]);
double aspect_ratio = window_size.width / (double)window_size.height; double aspect_ratio = window_size.width / (double)window_size.height;
Matx44f proj_matrix = convertToMatx(active_camera.GetProjectionTransformMatrix(aspect_ratio, -1.0f, 1.0f)); vtkSmartPointer<vtkMatrix4x4> proj_matrix = active_camera->GetProjectionTransformMatrix(aspect_ratio, -1.0f, 1.0f);
Camera camera(proj_matrix, window_size); return Camera(Matx44d(*proj_matrix->Element), window_size);
return camera;
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3f &pose) void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3d &pose)
{ {
vtkCamera& camera = *renderer_->GetActiveCamera(); vtkCamera& camera = *renderer_->GetActiveCamera();
// Position = extrinsic translation // Position = extrinsic translation
cv::Vec3f pos_vec = pose.translation(); cv::Vec3d pos_vec = pose.translation();
// Rotate the view vector // Rotate the view vector
cv::Matx33f rotation = pose.rotation(); cv::Matx33d rotation = pose.rotation();
cv::Vec3f y_axis(0.f, 1.f, 0.f); cv::Vec3d y_axis(0.0, 1.0, 0.0);
cv::Vec3f up_vec(rotation * y_axis); cv::Vec3d up_vec(rotation * y_axis);
// Compute the new focal point // Compute the new focal point
cv::Vec3f z_axis(0.f, 0.f, 1.f); cv::Vec3d z_axis(0.0, 0.0, 1.0);
cv::Vec3f focal_vec = pos_vec + rotation * z_axis; cv::Vec3d focal_vec = pos_vec + rotation * z_axis;
camera.SetPosition(pos_vec[0], pos_vec[1], pos_vec[2]); camera.SetPosition(pos_vec.val);
camera.SetFocalPoint(focal_vec[0], focal_vec[1], focal_vec[2]); camera.SetFocalPoint(focal_vec.val);
camera.SetViewUp(up_vec[0], up_vec[1], up_vec[2]); camera.SetViewUp(up_vec.val);
renderer_->ResetCameraClippingRange(); renderer_->ResetCameraClippingRange();
renderer_->Render();
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
cv::Affine3f cv::viz::Viz3d::VizImpl::getViewerPose() cv::Affine3d cv::viz::Viz3d::VizImpl::getViewerPose()
{ {
vtkCamera& camera = *renderer_->GetActiveCamera(); vtkCamera& camera = *renderer_->GetActiveCamera();
@ -397,20 +443,7 @@ cv::Affine3f cv::viz::Viz3d::VizImpl::getViewerPose()
Vec3d z_axis = normalized(focal - pos); Vec3d z_axis = normalized(focal - pos);
Vec3d x_axis = normalized(y_axis.cross(z_axis)); Vec3d x_axis = normalized(y_axis.cross(z_axis));
cv::Matx33d R; return makeTransformToGlobal(x_axis, y_axis, z_axis, pos);
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);
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
@ -426,10 +459,7 @@ void cv::viz::Viz3d::VizImpl::converTo3DRay(const Point3d &window_coord, Point3d
{ {
Vec4d world_pt; Vec4d world_pt;
vtkInteractorObserver::ComputeDisplayToWorld(renderer_, window_coord.x, window_coord.y, window_coord.z, world_pt.val); vtkInteractorObserver::ComputeDisplayToWorld(renderer_, window_coord.x, window_coord.y, window_coord.z, world_pt.val);
Vec3d cam_pos(renderer_->GetActiveCamera()->GetPosition());
vtkCamera &active_camera = *renderer_->GetActiveCamera();
Vec3d cam_pos;
active_camera.GetPosition(cam_pos.val);
origin = cam_pos; origin = cam_pos;
direction = normalize(Vec3d(world_pt.val) - 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) cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_name_; }
{ void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) { window_->SetFullScreen(mode); }
if (window_) void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_position_ = position; window_->SetPosition(position.x, position.y); }
window_->SetFullScreen(mode); 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()))); }
//////////////////////////////////////////////////////////////////////////////////////////////
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]); }

138
modules/viz/src/vizimpl.hpp Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -38,12 +38,42 @@
// the use of this software, even if advised of the possibility of such damage. // the use of this software, even if advised of the possibility of such damage.
// //
// Authors: // Authors:
// * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //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

View File

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

View File

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

View File

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

View File

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

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
@ -55,7 +52,6 @@ class cv::viz::Widget::Impl
{ {
public: public:
vtkSmartPointer<vtkProp> prop; vtkSmartPointer<vtkProp> prop;
Impl() : prop(0) {} Impl() : prop(0) {}
}; };
@ -63,13 +59,17 @@ cv::viz::Widget::Widget() : impl_( new Impl() ) { }
cv::viz::Widget::Widget(const Widget& other) : 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) cv::viz::Widget& cv::viz::Widget::operator=(const Widget& other)
{ {
if (!impl_) impl_ = new Impl(); if (!impl_)
if (other.impl_) impl_->prop = other.impl_->prop; impl_ = new Impl();
if (other.impl_)
impl_->prop = other.impl_->prop;
return *this; return *this;
} }
@ -84,45 +84,22 @@ cv::viz::Widget::~Widget()
cv::viz::Widget cv::viz::Widget::fromPlyFile(const String &file_name) 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(); vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();
reader->SetFileName(file_name.c_str()); 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(); vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
#if VTK_MAJOR_VERSION <= 5 mapper->SetInputConnection( reader->GetOutputPort() );
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->ImmediateModeRenderingOff(); mapper->ImmediateModeRenderingOff();
actor->SetNumberOfCloudPoints(int(std::max<vtkIdType>(1, data->GetNumberOfPoints() / 10))); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn(); actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper); actor->SetMapper(mapper);
Widget widget; Widget widget;
widget.impl_->prop = actor; WidgetAccessor::setProp(widget, actor);
return widget; return widget;
} }
@ -133,37 +110,15 @@ void cv::viz::Widget::setRenderingProperty(int property, double value)
switch (property) switch (property)
{ {
case POINT_SIZE: case POINT_SIZE: actor->GetProperty()->SetPointSize(float(value)); break;
{ case OPACITY: actor->GetProperty()->SetOpacity(value); break;
actor->GetProperty()->SetPointSize(float(value)); case LINE_WIDTH: actor->GetProperty()->SetLineWidth(float(value)); break;
actor->Modified(); case IMMEDIATE_RENDERING: actor->GetMapper()->SetImmediateModeRendering(int(value)); break;
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 FONT_SIZE: case FONT_SIZE:
{ {
vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor); vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor);
CV_Assert("Widget does not have text content." && text_actor); CV_Assert("Widget does not have text content." && text_actor);
vtkSmartPointer<vtkTextProperty> tprop = text_actor->GetTextProperty(); text_actor->GetTextProperty()->SetFontSize(int(value));
tprop->SetFontSize(int(value));
text_actor->Modified();
break; break;
} }
case REPRESENTATION: case REPRESENTATION:
@ -174,7 +129,6 @@ void cv::viz::Widget::setRenderingProperty(int property, double value)
case REPRESENTATION_WIREFRAME: actor->GetProperty()->SetRepresentationToWireframe(); break; case REPRESENTATION_WIREFRAME: actor->GetProperty()->SetRepresentationToWireframe(); break;
case REPRESENTATION_SURFACE: actor->GetProperty()->SetRepresentationToSurface(); break; case REPRESENTATION_SURFACE: actor->GetProperty()->SetRepresentationToSurface(); break;
} }
actor->Modified();
break; break;
} }
case SHADING: case SHADING:
@ -186,14 +140,11 @@ void cv::viz::Widget::setRenderingProperty(int property, double value)
{ {
if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals())
{ {
vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New(); vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
#if VTK_MAJOR_VERSION <= 5 CV_Assert("Can't set shading property for such type of widget" && mapper);
normals->SetInput(actor->GetMapper()->GetInput());
#else vtkSmartPointer<vtkPolyData> with_normals = VtkUtils::ComputeNormals(mapper->GetInput());
normals->SetInputData(actor->GetMapper()->GetInput()); VtkUtils::SetInputData(mapper, with_normals);
#endif
normals->Update();
vtkDataSetMapper::SafeDownCast(actor->GetMapper())->SetInputConnection(normals->GetOutputPort());
} }
actor->GetProperty()->SetInterpolationToGouraud(); actor->GetProperty()->SetInterpolationToGouraud();
break; break;
@ -202,27 +153,22 @@ void cv::viz::Widget::setRenderingProperty(int property, double value)
{ {
if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals())
{ {
vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New(); vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
#if VTK_MAJOR_VERSION <= 5 CV_Assert("Can't set shading property for such type of widget" && mapper);
normals->SetInput(actor->GetMapper()->GetInput());
#else vtkSmartPointer<vtkPolyData> with_normals = VtkUtils::ComputeNormals(mapper->GetInput());
normals->SetInputData(actor->GetMapper()->GetInput()); VtkUtils::SetInputData(mapper, with_normals);
#endif
normals->Update();
vtkDataSetMapper::SafeDownCast(actor->GetMapper())->SetInputConnection(normals->GetOutputPort());
} }
actor->GetProperty()->SetInterpolationToPhong(); actor->GetProperty()->SetInterpolationToPhong();
break; break;
} }
} }
actor->Modified();
break; break;
} }
default: default:
CV_Assert("setPointCloudRenderingProperties: Unknown property"); CV_Assert("setPointCloudRenderingProperties: Unknown property");
} }
actor->Modified();
} }
double cv::viz::Widget::getRenderingProperty(int property) const double cv::viz::Widget::getRenderingProperty(int property) const
@ -233,32 +179,16 @@ double cv::viz::Widget::getRenderingProperty(int property) const
double value = 0.0; double value = 0.0;
switch (property) switch (property)
{ {
case POINT_SIZE: case POINT_SIZE: value = actor->GetProperty()->GetPointSize(); break;
{ case OPACITY: value = actor->GetProperty()->GetOpacity(); break;
value = actor->GetProperty()->GetPointSize(); case LINE_WIDTH: value = actor->GetProperty()->GetLineWidth(); break;
break; case IMMEDIATE_RENDERING: value = actor->GetMapper()->GetImmediateModeRendering(); 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 FONT_SIZE: case FONT_SIZE:
{ {
vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor); vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor);
CV_Assert("Widget does not have text content." && text_actor); CV_Assert("Widget does not have text content." && text_actor);
vtkSmartPointer<vtkTextProperty> tprop = text_actor->GetTextProperty(); value = text_actor->GetTextProperty()->GetFontSize();;
value = tprop->GetFontSize();
break; break;
} }
case REPRESENTATION: case REPRESENTATION:
@ -303,38 +233,17 @@ void cv::viz::WidgetAccessor::setProp(Widget& widget, vtkSmartPointer<vtkProp> p
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/// widget3D implementation /// widget3D implementation
struct cv::viz::Widget3D::MatrixConverter void cv::viz::Widget3D::setPose(const Affine3d &pose)
{
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)
{ {
vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this));
CV_Assert("Widget is not 3D." && actor); CV_Assert("Widget is not 3D." && actor);
vtkSmartPointer<vtkMatrix4x4> matrix = convertToVtkMatrix(pose.matrix); vtkSmartPointer<vtkMatrix4x4> matrix = vtkmatrix(pose.matrix);
actor->SetUserMatrix(matrix); actor->SetUserMatrix(matrix);
actor->Modified(); 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)); vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this));
CV_Assert("Widget is not 3D." && actor); CV_Assert("Widget is not 3D." && actor);
@ -343,25 +252,33 @@ void cv::viz::Widget3D::updatePose(const Affine3f &pose)
if (!matrix) if (!matrix)
{ {
setPose(pose); setPose(pose);
return ; return;
} }
Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix);
Affine3f updated_pose = pose * Affine3f(matrix_cv); Affine3d updated_pose = pose * Affine3d(*matrix->Element);
matrix = MatrixConverter::convertToVtkMatrix(updated_pose.matrix); matrix = vtkmatrix(updated_pose.matrix);
actor->SetUserMatrix(matrix); actor->SetUserMatrix(matrix);
actor->Modified(); actor->Modified();
} }
cv::Affine3f cv::viz::Widget3D::getPose() const cv::Affine3d cv::viz::Widget3D::getPose() const
{ {
vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this));
CV_Assert("Widget is not 3D." && actor); CV_Assert("Widget is not 3D." && actor);
return Affine3d(*actor->GetUserMatrix()->Element);
}
vtkSmartPointer<vtkMatrix4x4> matrix = actor->GetUserMatrix(); void cv::viz::Widget3D::applyTransform(const Affine3d &transform)
Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix); {
return Affine3f(matrix_cv); 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) void cv::viz::Widget3D::setColor(const Color &color)

View File

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

View File

@ -1 +1,24 @@
#include "test_precomp.hpp" #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;
}

View File

@ -41,9 +41,6 @@
// * Ozan Tonkal, ozantonkal@gmail.com // * Ozan Tonkal, ozantonkal@gmail.com
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
// //
// OpenCV Viz module is complete rewrite of
// PCL visualization module (www.pointclouds.org)
//
//M*/ //M*/
#ifdef __GNUC__ #ifdef __GNUC__
@ -66,5 +63,42 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <string> #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 #endif

View File

@ -12,34 +12,34 @@ void tutorial2()
myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem());
/// Add line to represent (1,1,1) axis /// 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); axis.setRenderingProperty(viz::LINE_WIDTH, 4.0);
myWindow.showWidget("Line Widget", axis); myWindow.showWidget("Line Widget", axis);
/// Construct a cube widget /// 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); cube_widget.setRenderingProperty(viz::LINE_WIDTH, 4.0);
/// Display widget (update if already displayed) /// Display widget (update if already displayed)
myWindow.showWidget("Cube Widget", cube_widget); myWindow.showWidget("Cube Widget", cube_widget);
/// Rodrigues vector /// Rodrigues vector
Mat rot_vec = Mat::zeros(1,3,CV_32F); Vec3d rot_vec = Vec3d::all(0);
float translation_phase = 0.0, translation = 0.0; double translation_phase = 0.0, translation = 0.0;
while(!myWindow.wasStopped()) while(!myWindow.wasStopped())
{ {
/* Rotation using rodrigues */ /* Rotation using rodrigues */
/// Rotate around (1,1,1) /// Rotate around (1,1,1)
rot_vec.at<float>(0,0) += CV_PI * 0.01f; rot_vec[0] += CV_PI * 0.01;
rot_vec.at<float>(0,1) += CV_PI * 0.01f; rot_vec[1] += CV_PI * 0.01;
rot_vec.at<float>(0,2) += CV_PI * 0.01f; rot_vec[2] += CV_PI * 0.01;
/// Shift on (1,1,1) /// Shift on (1,1,1)
translation_phase += CV_PI * 0.01f; translation_phase += CV_PI * 0.01;
translation = sin(translation_phase); translation = sin(translation_phase);
/// Construct pose /// Construct pose
Affine3f pose(rot_vec, Vec3f(translation, translation, translation)); Affine3d pose(rot_vec, Vec3d(translation, translation, translation));
myWindow.setWidgetPose("Cube Widget", pose); 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(); tutorial2();
} }

View File

@ -3,28 +3,6 @@
using namespace cv; using namespace cv;
using namespace std; 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 * @function main
*/ */
@ -37,29 +15,29 @@ void tutorial3(bool camera_pov)
myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem());
/// Let's assume camera has the following properties /// 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 /// 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 /// We can get the transformation matrix from camera coordinate system to global using
/// - makeTransformToGlobal. We need the axes of the camera /// - 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. /// Create a cloud widget.
Mat bunny_cloud = cvcloud_load(); Mat dragon_cloud = viz::readCloud(get_dragon_ply_file_path());
viz::WCloud cloud_widget(bunny_cloud, viz::Color::green()); viz::WCloud cloud_widget(dragon_cloud, viz::Color::green());
/// Pose of the widget in camera frame /// 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 /// Pose of the widget in global frame
Affine3f cloud_pose_global = transform * cloud_pose; Affine3d cloud_pose_global = transform * cloud_pose;
/// Visualize camera frame /// Visualize camera frame
if (!camera_pov) if (!camera_pov)
{ {
viz::WCameraPosition cpw(0.5); // Coordinate axes 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", cpw, cam_pose);
myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose); myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
} }
@ -75,12 +53,12 @@ void tutorial3(bool camera_pov)
myWindow.spin(); myWindow.spin();
} }
TEST(Viz_viz3d, DISABLED_tutorial3_global_view) TEST(Viz, DISABLED_tutorial3_global_view)
{ {
tutorial3(false); tutorial3(false);
} }
TEST(Viz_viz3d, DISABLED_tutorial3_camera_view) TEST(Viz, DISABLED_tutorial3_camera_view)
{ {
tutorial3(true); tutorial3(true);
} }

View File

@ -41,141 +41,24 @@
//M*/ //M*/
#include "test_precomp.hpp" #include "test_precomp.hpp"
using namespace cv; using namespace cv;
static cv::Mat cvcloud_load() TEST(Viz_viz3d, DISABLED_develop)
{ {
cv::Mat cloud(1, 20000, CV_32FC3); cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path());
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)
{
if (event.keyDown())
{
if (event.getKeySym() == "space")
{
viz::Viz3d &viz = *((viz::Viz3d *) cookie);
constant_cam = !constant_cam;
if (constant_cam)
{
viz.showWidget("cam_1", cam_1);
viz.showWidget("cam_coordinate", cam_coordinates);
viz.showWidget("cam_text", viz::WText("Global View", Point2i(5,5), 28));
viz.resetCamera();
}
else
{
viz.showWidget("cam_text", viz::WText("Cam View", Point2i(5,5), 28));
viz.removeWidget("cam_1");
viz.removeWidget("cam_coordinate");
}
}
}
}
TEST(Viz_viz3d, develop)
{
cv::viz::Viz3d viz("abc"); 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"); //---->>>>> <to_test_in_future>
cv::viz::WMesh bunny_widget(bunny_mesh); //std::vector<cv::Affine3d> gt, es;
bunny_widget.setColor(cv::viz::Color::cyan()); //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>
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.spin();
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++]);
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
} }

View File

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