added vtkCloudMatSink, reworked cloud IO functions, added normals support
authorAnatoly Baksheev <no@email>
Tue, 31 Dec 2013 17:50:38 +0000 (21:50 +0400)
committerAnatoly Baksheev <no@email>
Sun, 19 Jan 2014 14:38:44 +0000 (18:38 +0400)
modules/viz/include/opencv2/viz.hpp
modules/viz/src/precomp.hpp
modules/viz/src/vizcore.cpp
modules/viz/src/vtk/vtkCloudMatSink.cpp [new file with mode: 0644]
modules/viz/src/vtk/vtkCloudMatSink.h [new file with mode: 0644]
modules/viz/src/vtk/vtkCloudMatSource.cpp
modules/viz/test/test_viz3d.cpp

index 49b36a9..cb399a8 100644 (file)
@@ -93,10 +93,10 @@ namespace cv
 
 
         ///////////////////////////////////////////////////////////////////////////////////////////////
-        /// Read/write clouds. Supported formats: ply, stl, xyz, obj
+        /// Read/write clouds. Supported formats: ply, xyz, obj and stl (readonly)
 
-        CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray());
-        CV_EXPORTS Mat  readCloud (const String& file, OutputArray colors = cv::noArray());
+        CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray(), bool binary = false);
+        CV_EXPORTS Mat  readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray());
 
         ///////////////////////////////////////////////////////////////////////////////////////////////
         /// Read/write poses and trajectories
index 83b779d..b10e83a 100644 (file)
 #endif
 
 #include <vtk/vtkCloudMatSource.h>
+#include <vtk/vtkCloudMatSink.h>
 #include <vtk/vtkOBJWriter.h>
 #include <vtk/vtkXYZWriter.h>
 
index 5a1a7a8..29f6be2 100644 (file)
@@ -164,38 +164,36 @@ void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); }
 ///////////////////////////////////////////////////////////////////////////////////////////////
 /// Read/write clouds. Supported formats: ply, stl, xyz, obj
 
-void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors)
+void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors, InputArray _normals, bool binary)
 {
     CV_Assert(file.size() > 4 && "Extention is required");
     String extention = file.substr(file.size()-4);
 
     Mat cloud = _cloud.getMat();
     Mat colors = _colors.getMat();
+    Mat normals = _normals.getMat();
 
     vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New();
-    source->SetColorCloud(cloud, colors);
+    source->SetColorCloudNormals(cloud, colors, normals);
 
     vtkSmartPointer<vtkWriter> writer;
     if (extention == ".xyz")
     {
         writer = vtkSmartPointer<vtkXYZWriter>::New();
-        vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str());
+        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 if (extention == ".stl")
-    {
-        writer = vtkSmartPointer<vtkSTLWriter>::New();
-        vtkSTLWriter::SafeDownCast(writer)->SetFileName(file.c_str());
-    }
     else
         CV_Assert(!"Unsupported format");
 
@@ -203,7 +201,7 @@ void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colo
     writer->Write();
 }
 
-cv::Mat cv::viz::readCloud(const String& file, OutputArray colors)
+cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray normals)
 {
     CV_Assert(file.size() > 4 && "Extention is required");
     String extention = file.substr(file.size()-4);
@@ -233,43 +231,12 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors)
     else
         CV_Assert(!"Unsupported format");
 
-    reader->Update();
-    vtkSmartPointer<vtkPolyData> poly_data = reader->GetOutput();
-    vtkSmartPointer<vtkPoints> points = poly_data->GetPoints();
-
-    int vtktype = points->GetDataType();
-    CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE);
-
-    Mat cloud(1, points->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3);
-    Vec3d *ddata = cloud.ptr<Vec3d>();
-    Vec3f *fdata = cloud.ptr<Vec3f>();
-
-    if (cloud.depth() == CV_32F)
-        for(size_t i = 0; i < cloud.total(); ++i)
-            *fdata++ = Vec3d(points->GetPoint(i));
+    cv::Mat cloud;
 
-    if (cloud.depth() == CV_64F)
-        for(size_t i = 0; i < cloud.total(); ++i)
-            *ddata++ = Vec3d(points->GetPoint(i));
-
-    vtkSmartPointer<vtkDataArray> scalars = poly_data->GetPointData() ? poly_data->GetPointData()->GetScalars() : 0;
-
-    if (colors.needed() && scalars)
-    {
-        int channels = scalars->GetNumberOfComponents();
-        int vtktype = scalars->GetDataType();
-
-        CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented");
-        CV_Assert(cloud.total() == (size_t)scalars->GetNumberOfTuples());
-        Mat buffer(cloud.size(), CV_64FC(channels));
-        Vec3d *cptr = buffer.ptr<Vec3d>();
-        for(size_t i = 0; i < colors.total(); ++i)
-            *cptr++ = Vec3d(scalars->GetTuple(i));
-
-        buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ?  255.0 : 1.0);
-    }
-    else
-        colors.release();
+    vtkSmartPointer<vtkCloudMatSink> sink = vtkSmartPointer<vtkCloudMatSink>::New();
+    sink->SetInputConnection(reader->GetOutputPort());
+    sink->SetOutput(cloud, colors, normals);
+    sink->Write();
 
     return cloud;
 }
diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp
new file mode 100644 (file)
index 0000000..b96db38
--- /dev/null
@@ -0,0 +1,137 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+// Authors:
+//  * Anatoly Baksheev, Itseez Inc.  myname.mysurname <> mycompany.com
+//
+//M*/
+
+#include "precomp.hpp"
+
+namespace cv { namespace viz
+{
+    vtkStandardNewMacro(vtkCloudMatSink);
+}}
+
+cv::viz::vtkCloudMatSink::vtkCloudMatSink() {}
+cv::viz::vtkCloudMatSink::~vtkCloudMatSink() {}
+
+void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals)
+{
+    cloud = _cloud;
+    colors = _colors;
+    normals = _normals;
+}
+
+void cv::viz::vtkCloudMatSink::WriteData()
+{
+    vtkPolyData *input = this->GetInput();
+    if (!input)
+        return;
+
+    vtkSmartPointer<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 = (Vec3d*)cloud.getMat().ptr();
+        Vec3f *fdata = (Vec3f*)cloud.getMat().ptr();
+
+        if (cloud.depth() == CV_32F)
+            for(size_t i = 0; i < cloud.total(); ++i)
+                *fdata++ = Vec3d(points_Data->GetPoint(i));
+
+        if (cloud.depth() == CV_64F)
+            for(size_t i = 0; i < cloud.total(); ++i)
+                *ddata++ = Vec3d(points_Data->GetPoint(i));
+    }
+    else
+        cloud.release();
+
+    vtkSmartPointer<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(scalars_data->GetTuple(i));
+
+        buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F);
+    }
+    else
+        normals.release();
+}
+
+void cv::viz::vtkCloudMatSink::PrintSelf(ostream& os, vtkIndent indent)
+{
+  Superclass::PrintSelf(os, indent);
+  os << indent << "Cloud: " << cloud.needed() << "\n";
+  os << indent << "Colors: " << colors.needed() << "\n";
+  os << indent << "Normals: " << normals.needed() << "\n";
+}
diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h
new file mode 100644 (file)
index 0000000..e4a55f0
--- /dev/null
@@ -0,0 +1,76 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+// Authors:
+//  * Anatoly Baksheev, Itseez Inc.  myname.mysurname <> mycompany.com
+//
+//M*/
+
+#ifndef __vtkCloudMatSink_h
+#define __vtkCloudMatSink_h
+
+namespace cv
+{
+    namespace viz
+    {
+        class vtkCloudMatSink : public vtkPolyDataWriter
+        {
+        public:
+          static vtkCloudMatSink *New();
+          vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter);
+          void PrintSelf(ostream& os, vtkIndent indent);
+
+          void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray());
+
+        protected:
+          vtkCloudMatSink();
+          ~vtkCloudMatSink();
+
+          void WriteData();
+
+          _OutputArray cloud, colors, normals;
+
+        private:
+          vtkCloudMatSink(const vtkCloudMatSink&);  // Not implemented.
+          void operator=(const vtkCloudMatSink&);  // Not implemented.
+        };
+    }
+}
+
+#endif
index b603a39..476e0d5 100644 (file)
@@ -199,7 +199,7 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, co
     }
 
     scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
-    scalars->SetName("colors");
+    scalars->SetName("Colors");
     scalars->SetNumberOfComponents(3);
     scalars->SetNumberOfTuples(total);
     scalars->SetArray(array->val, total * 3, 0);
index ee91023..99476f6 100644 (file)
@@ -49,6 +49,7 @@ TEST(Viz_viz3d, develop)
 
     cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply");
 
+
 //    for(size_t i = 0; i < cloud.total(); ++i)
 //    {
 //        if (i % 15 == 0)
@@ -63,14 +64,12 @@ TEST(Viz_viz3d, develop)
     cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0));
 
     //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply"));
-
     //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1)));
 
     cv::RNG rng;
     rng.fill(colors, cv::RNG::UNIFORM, 0, 255);
-    cv::viz::WCloud c(cloud, colors);
-    //cv::viz::WCloud c(cloud, cv::viz::Color::bluberry());
-    viz.showWidget("c", c);
+    viz.showWidget("c", cv::viz::WCloud(cloud, colors));
+    //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry()));
 
     //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1)));
     //viz.showWidget("s", cv::viz::WSphere(Point3f(0,0,0), 1));