From c1b41caa7cec1bb42cfde238f0ba1ea7c178f1d2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev <no@email> Date: Tue, 31 Dec 2013 21:50:38 +0400 Subject: [PATCH] added vtkCloudMatSink, reworked cloud IO functions, added normals support --- modules/viz/include/opencv2/viz.hpp | 6 +- modules/viz/src/precomp.hpp | 1 + modules/viz/src/vizcore.cpp | 57 ++------- modules/viz/src/vtk/vtkCloudMatSink.cpp | 137 ++++++++++++++++++++++ modules/viz/src/vtk/vtkCloudMatSink.h | 76 ++++++++++++ modules/viz/src/vtk/vtkCloudMatSource.cpp | 2 +- modules/viz/test/test_viz3d.cpp | 7 +- 7 files changed, 233 insertions(+), 53 deletions(-) create mode 100644 modules/viz/src/vtk/vtkCloudMatSink.cpp create mode 100644 modules/viz/src/vtk/vtkCloudMatSink.h diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 49b36a9b2..cb399a8eb 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -93,10 +93,10 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// - /// Read/write clouds. Supported formats: ply, stl, xyz, obj + /// Read/write clouds. Supported formats: ply, xyz, obj and stl (readonly) - CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray()); - CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = cv::noArray()); + CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray(), bool binary = false); + CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 83b779dd8..b10e83ad5 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -132,6 +132,7 @@ #endif #include <vtk/vtkCloudMatSource.h> +#include <vtk/vtkCloudMatSink.h> #include <vtk/vtkOBJWriter.h> #include <vtk/vtkXYZWriter.h> diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 5a1a7a8fe..29f6be288 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -164,38 +164,36 @@ void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write clouds. Supported formats: ply, stl, xyz, obj -void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors) +void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors, InputArray _normals, bool binary) { CV_Assert(file.size() > 4 && "Extention is required"); String extention = file.substr(file.size()-4); Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); + Mat normals = _normals.getMat(); vtkSmartPointer<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(); + cv::Mat cloud; - 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)); - - 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 index 000000000..b96db385b --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -0,0 +1,137 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkCloudMatSink); +}} + +cv::viz::vtkCloudMatSink::vtkCloudMatSink() {} +cv::viz::vtkCloudMatSink::~vtkCloudMatSink() {} + +void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals) +{ + cloud = _cloud; + colors = _colors; + normals = _normals; +} + +void cv::viz::vtkCloudMatSink::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + vtkSmartPointer<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 index 000000000..e4a55f078 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -0,0 +1,76 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkCloudMatSink_h +#define __vtkCloudMatSink_h + +namespace cv +{ + namespace viz + { + class vtkCloudMatSink : public vtkPolyDataWriter + { + public: + static vtkCloudMatSink *New(); + vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); + + protected: + vtkCloudMatSink(); + ~vtkCloudMatSink(); + + void WriteData(); + + _OutputArray cloud, colors, normals; + + private: + vtkCloudMatSink(const vtkCloudMatSink&); // Not implemented. + void operator=(const vtkCloudMatSink&); // Not implemented. + }; + } +} + +#endif diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index b603a39b7..476e0d5ed 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -199,7 +199,7 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, co } scalars = vtkSmartPointer<vtkUnsignedCharArray>::New(); - scalars->SetName("colors"); + scalars->SetName("Colors"); scalars->SetNumberOfComponents(3); scalars->SetNumberOfTuples(total); scalars->SetArray(array->val, total * 3, 0); diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index ee9102399..99476f675 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -49,6 +49,7 @@ TEST(Viz_viz3d, develop) cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); + // for(size_t i = 0; i < cloud.total(); ++i) // { // if (i % 15 == 0) @@ -63,14 +64,12 @@ TEST(Viz_viz3d, develop) cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); - //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); cv::RNG rng; rng.fill(colors, cv::RNG::UNIFORM, 0, 255); - cv::viz::WCloud c(cloud, colors); - //cv::viz::WCloud c(cloud, cv::viz::Color::bluberry()); - viz.showWidget("c", c); + viz.showWidget("c", cv::viz::WCloud(cloud, colors)); + //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); //viz.showWidget("s", cv::viz::WSphere(Point3f(0,0,0), 1));