diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 65ad10aacc..49b36a9b2f 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -92,6 +92,12 @@ namespace cv { return isNan(p.x) || isNan(p.y) || isNan(p.z); } + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Read/write clouds. Supported formats: ply, stl, xyz, obj + + CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray()); + CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = cv::noArray()); + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 8549acafdb..555da22d0f 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -69,9 +69,8 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) colors = colors.reshape(colors.channels(), 1); } - vtkSmartPointer cloud_source = vtkSmartPointer::New(); - cloud_source->SetCloud(cloud); - cloud_source->SetColors(colors, cloud); + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetColorCloud(cloud, colors); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(cloud_source->GetOutputPort()); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 7741dc7df5..6b2c1478e1 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -113,16 +114,31 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif #include -#include -#include +#include +#include #include #include #include #include + namespace cv { namespace viz diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index dd998e7d92..5a1a7a8fe2 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -161,6 +161,118 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Read/write clouds. Supported formats: ply, stl, xyz, obj + +void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors) +{ + CV_Assert(file.size() > 4 && "Extention is required"); + String extention = file.substr(file.size()-4); + + Mat cloud = _cloud.getMat(); + Mat colors = _colors.getMat(); + + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetColorCloud(cloud, colors); + + vtkSmartPointer writer; + if (extention == ".xyz") + { + writer = vtkSmartPointer::New(); + vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".ply") + { + writer = vtkSmartPointer::New(); + vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".obj") + { + writer = vtkSmartPointer::New(); + vtkOBJWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".stl") + { + writer = vtkSmartPointer::New(); + vtkSTLWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else + CV_Assert(!"Unsupported format"); + + writer->SetInputConnection(source->GetOutputPort()); + writer->Write(); +} + +cv::Mat cv::viz::readCloud(const String& file, OutputArray colors) +{ + CV_Assert(file.size() > 4 && "Extention is required"); + String extention = file.substr(file.size()-4); + + vtkSmartPointer reader; + if (extention == ".xyz") + { + reader = vtkSmartPointer::New(); + vtkSimplePointsReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".ply") + { + reader = vtkSmartPointer::New(); + CV_Assert(vtkPLYReader::CanReadFile(file.c_str())); + vtkPLYReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".obj") + { + reader = vtkSmartPointer::New(); + vtkOBJReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".stl") + { + reader = vtkSmartPointer::New(); + vtkSTLReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else + CV_Assert(!"Unsupported format"); + + reader->Update(); + vtkSmartPointer poly_data = reader->GetOutput(); + vtkSmartPointer points = poly_data->GetPoints(); + + int vtktype = points->GetDataType(); + CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); + + Mat cloud(1, points->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); + Vec3d *ddata = cloud.ptr(); + Vec3f *fdata = cloud.ptr(); + + if (cloud.depth() == CV_32F) + for(size_t i = 0; i < cloud.total(); ++i) + *fdata++ = Vec3d(points->GetPoint(i)); + + if (cloud.depth() == CV_64F) + for(size_t i = 0; i < cloud.total(); ++i) + *ddata++ = Vec3d(points->GetPoint(i)); + + vtkSmartPointer scalars = poly_data->GetPointData() ? poly_data->GetPointData()->GetScalars() : 0; + + if (colors.needed() && scalars) + { + int channels = scalars->GetNumberOfComponents(); + int vtktype = scalars->GetDataType(); + + CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented"); + CV_Assert(cloud.total() == (size_t)scalars->GetNumberOfTuples()); + Mat buffer(cloud.size(), CV_64FC(channels)); + Vec3d *cptr = buffer.ptr(); + for(size_t i = 0; i < colors.total(); ++i) + *cptr++ = Vec3d(scalars->GetTuple(i)); + + buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); + } + else + colors.release(); + + return cloud; +} /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.cpp b/modules/viz/src/vtk/vtkCloudColorMatSource.cpp deleted file mode 100644 index 8979873eb3..0000000000 --- a/modules/viz/src/vtk/vtkCloudColorMatSource.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -// Authors: -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -//M*/ - -#include "precomp.hpp" - -namespace cv { namespace viz -{ - vtkStandardNewMacro(vtkCloudColorMatSource); - - struct IsNotNan - { - template - bool operator()(const _Tp* data) const - { - return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); - } - }; -}} - -cv::viz::vtkCloudColorMatSource::vtkCloudColorMatSource() { SetNumberOfInputPorts(0); } -cv::viz::vtkCloudColorMatSource::~vtkCloudColorMatSource() {} - -void cv::viz::vtkCloudColorMatSource::SetCloud(const Mat& cloud) -{ - CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); - CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); - - int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) - : filterNanCopy(cloud, VTK_DOUBLE); - - vertices = vtkSmartPointer::New(); - vertices->Allocate(vertices->EstimateSize(1, total)); - vertices->InsertNextCell(total); - for(int i = 0; i < total; ++i) - vertices->InsertCellPoint(i); -} - -void cv::viz::vtkCloudColorMatSource::SetColors(const Mat &colors, const Mat &cloud_mask) -{ - CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); - CV_Assert(cloud_mask.depth() == CV_32F || cloud_mask.depth() == CV_64F); - CV_Assert(colors.size() == cloud_mask.size()); - - if (cloud_mask.depth() == CV_32F) - filterNanCopy(colors, cloud_mask); - else if (cloud_mask.depth() == CV_64F) - filterNanCopy(colors, cloud_mask); -} - -int cv::viz::vtkCloudColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) -{ - vtkInformation *outInfo = outputVector->GetInformationObject(0); - vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); - - output->SetPoints(points); - output->SetVerts(vertices); - output->GetPointData()->SetScalars(scalars); - return 1; -} - -template -int cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& source, int dataType) -{ - CV_DbgAssert(DataType<_Tp>::depth == source.depth()); - points = vtkSmartPointer::New(); - points->SetDataType(dataType); - points->Allocate(source.total()); - points->SetNumberOfPoints(source.total()); - - int cn = source.channels(); - int total = 0; - for (int y = 0; y < source.rows; ++y) - { - const _Tp* srow = source.ptr<_Tp>(y); - const _Tp* send = srow + source.cols * cn; - - for (; srow != send; srow += cn) - if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) - points->SetPoint(total++, srow); - } - points->SetNumberOfPoints(total); - points->Squeeze(); - return total; -} - -template -void cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& colors, const Mat& mask) -{ - Mat buffer(colors.size(), CV_8UC3); - Vec3b* pos = buffer.ptr(); - - int s_chs = colors.channels(); - int m_chs = mask.channels(); - - _NanPred pred; - - for (int y = 0; y < colors.rows; ++y) - { - const unsigned char* srow = colors.ptr(y); - const unsigned char* send = srow + colors.cols * colors.channels(); - const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); - - if (colors.channels() == 1) - { - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[0], srow[0], srow[0]); - } - else - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[2], srow[1], srow[0]); - - } - - int total = pos - buffer.ptr(); - Vec3b* array = new Vec3b[total]; - std::copy(buffer.ptr(), pos, array); - - scalars = vtkSmartPointer::New(); - scalars->SetName("colors"); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(total); - scalars->SetArray(array->val, total * 3, 0); -} - - diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index a27653a4f6..f533361bca 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -47,6 +47,14 @@ namespace cv { namespace viz { vtkStandardNewMacro(vtkCloudMatSource); + + struct IsNotNan + { + template bool operator()(const _Tp* data) const + { + return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); + } + }; }} cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } @@ -67,6 +75,22 @@ void cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) vertices->InsertCellPoint(i); } +void cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) +{ + vtkCloudMatSource::SetCloud(cloud); + + if (colors.empty()) + return; + + CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); + CV_Assert(colors.size() == cloud.size()); + + if (cloud.depth() == CV_32F) + filterNanColorsCopy(colors, cloud); + else if (cloud.depth() == CV_64F) + filterNanColorsCopy(colors, cloud); +} + int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { vtkInformation *outInfo = outputVector->GetInformationObject(0); @@ -74,6 +98,8 @@ int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), output->SetPoints(points); output->SetVerts(vertices); + if (scalars) + output->GetPointData()->SetScalars(scalars); return 1; } @@ -103,3 +129,45 @@ int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) } +template +void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& colors, const Mat& mask) +{ + Mat buffer(colors.size(), CV_8UC3); + Vec3b* pos = buffer.ptr(); + + int s_chs = colors.channels(); + int m_chs = mask.channels(); + + _NanPred pred; + + for (int y = 0; y < colors.rows; ++y) + { + const unsigned char* srow = colors.ptr(y); + const unsigned char* send = srow + colors.cols * colors.channels(); + const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); + + if (colors.channels() == 1) + { + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[0], srow[0], srow[0]); + } + else + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[2], srow[1], srow[0]); + + } + + int total = pos - buffer.ptr(); + Vec3b* array = new Vec3b[total]; + std::copy(buffer.ptr(), pos, array); + + scalars = vtkSmartPointer::New(); + scalars->SetName("colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(array->val, total * 3, 0); +} + + diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 6a8dbebd16..876ab994f6 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -62,6 +62,7 @@ namespace cv vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); virtual void SetCloud(const Mat& cloud); + virtual void SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); protected: vtkCloudMatSource(); @@ -71,11 +72,15 @@ namespace cv vtkSmartPointer points; vtkSmartPointer vertices; + vtkSmartPointer scalars; private: vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. void operator=(const vtkCloudMatSource&); // Not implemented. template int filterNanCopy(const Mat& source, int dataType); + + template + void filterNanColorsCopy(const Mat& colors, const Mat& mask); }; } } diff --git a/modules/viz/src/vtk/vtkColorMatSource.cpp b/modules/viz/src/vtk/vtkColorMatSource.cpp deleted file mode 100644 index aa09a2d49d..0000000000 --- a/modules/viz/src/vtk/vtkColorMatSource.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -// Authors: -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -//M*/ - -#include "precomp.hpp" - -namespace cv { namespace viz -{ - vtkStandardNewMacro(vtkColorMatSource); - - struct IsNotNan - { - template - bool operator()(const _Tp* data) const - { - return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); - } - }; - - struct AllOk - { - template - bool operator()(const _Tp*) const { return true; } - }; -}} - -cv::viz::vtkColorMatSource::vtkColorMatSource() { SetNumberOfInputPorts(0); } -cv::viz::vtkColorMatSource::~vtkColorMatSource() {} - -void cv::viz::vtkColorMatSource::SetColors(const Mat &colors, const Mat& mask) -{ - CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); - CV_Assert(mask.empty() || mask.depth() == CV_32F || mask.depth() == CV_64F); - - if (!mask.empty() && mask.depth() == CV_32F) - filterNanCopy(colors, mask); - else if (!mask.empty() && mask.depth() == CV_64F) - filterNanCopy(colors, mask); - else /* mask.empty() */ - filterNanCopy(colors, mask); -} - -int cv::viz::vtkColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) -{ - vtkInformation *outInfo = outputVector->GetInformationObject(0); - vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); - - output->GetPointData()->SetScalars(scalars); - - return 1; -} - -template -void cv::viz::vtkColorMatSource::filterNanCopy(const Mat& colors, const Mat& cloud_mask) -{ - Mat buffer(colors.size(), CV_8UC3); - Vec3b* pos = buffer.ptr(); - - int s_chs = colors.channels(); - int m_chs = cloud_mask.channels(); - - _NanPred pred; - - for (int y = 0; y < colors.rows; ++y) - { - const unsigned char* srow = colors.ptr(y); - const unsigned char* send = srow + colors.cols * colors.channels(); - const _Msk* mrow = cloud_mask.empty() ? 0 : cloud_mask.ptr<_Msk>(y); - - if (colors.channels() == 1) - { - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[0], srow[0], srow[0]); - } - else - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[2], srow[1], srow[0]); - - } - - int total = pos - buffer.ptr(); - Vec3b* array = new Vec3b[total]; - std::copy(buffer.ptr(), pos, array); - - scalars = vtkSmartPointer::New(); - scalars->SetName("colors"); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(total); - scalars->SetArray(array->val, total * 3, 0); -} diff --git a/modules/viz/src/vtk/vtkOBJWriter.cpp b/modules/viz/src/vtk/vtkOBJWriter.cpp new file mode 100644 index 0000000000..452ad19a7a --- /dev/null +++ b/modules/viz/src/vtk/vtkOBJWriter.cpp @@ -0,0 +1,241 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkOBJWriter); +}} + +cv::viz::vtkOBJWriter::vtkOBJWriter() +{ + std::ofstream fout; // only used to extract the default precision + this->DecimalPrecision = fout.precision(); + this->FileName = NULL; + this->FileType = VTK_ASCII; +} + +cv::viz::vtkOBJWriter::~vtkOBJWriter(){} + +void cv::viz::vtkOBJWriter::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + std::ostream *outfilep = this->OpenVTKFile(); + if (!outfilep) + return; + + std::ostream& outfile = *outfilep; + + //write header + outfile << "# wavefront obj file written by the visualization toolkit" << std::endl << std::endl; + outfile << "mtllib NONE" << std::endl << std::endl; + + // write out the points + for (int i = 0; i < input->GetNumberOfPoints(); i++) + { + Vec3d p; + input->GetPoint(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "v " << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + + const int idStart = 1; + + // write out the point data + vtkSmartPointer normals = input->GetPointData()->GetNormals(); + if(normals) + { + for (int i = 0; i < normals->GetNumberOfTuples(); i++) + { + Vec3d p; + normals->GetTuple(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "vn " << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + } + + vtkSmartPointer tcoords = input->GetPointData()->GetTCoords(); + if (tcoords) + { + for (int i = 0; i < tcoords->GetNumberOfTuples(); i++) + { + Vec2d p; + tcoords->GetTuple(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "vt " << p[0] << " " << p[1] << std::endl; + } + } + + // write out a group name and material + outfile << std::endl << "g grp" << idStart << std::endl; + outfile << "usemtl mtlNONE" << std::endl; + + // write out verts if any + if (input->GetNumberOfVerts() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetVerts(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "p "; + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << " "; + outfile << std::endl; + } + } + + // write out lines if any + if (input->GetNumberOfLines() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetLines(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "l "; + if (tcoords) + { + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << "/" << index[i] + idStart << " "; + } + else + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << " "; + + outfile << std::endl; + } + } + + // write out polys if any + if (input->GetNumberOfPolys() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetPolys(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "f "; + for (int i = 0; i < npts; i++) + { + if (normals) + { + if (tcoords) + outfile << index[i] + idStart << "/" << index[i] + idStart << "/" << index[i] + idStart << " "; + else + outfile << index[i] + idStart << "//" << index[i] + idStart << " "; + } + else + { + if (tcoords) + outfile << index[i] + idStart << " " << index[i] + idStart << " "; + else + outfile << index[i] + idStart << " "; + } + } + outfile << std::endl; + } + } + + // write out tstrips if any + if (input->GetNumberOfStrips() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetStrips(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + for (int i = 2, i1, i2; i < npts; ++i) + { + if (i % 2) + { + i1 = i - 1; + i2 = i - 2; + } + else + { + i1 = i - 1; + i2 = i - 2; + } + + if(normals) + { + if (tcoords) + { + outfile << "f " << index[i1] + idStart << "/" << index[i1] + idStart << "/" << index[i1] + idStart << " " + << index[i2]+ idStart << "/" << index[i2] + idStart << "/" << index[i2] + idStart << " " + << index[i] + idStart << "/" << index[i] + idStart << "/" << index[i] + idStart << std::endl; + } + else + { + outfile << "f " << index[i1] + idStart << "//" << index[i1] + idStart << " " << index[i2] + idStart + << "//" << index[i2] + idStart << " " << index[i] + idStart << "//" << index[i] + idStart << std::endl; + } + } + else + { + if (tcoords) + { + outfile << "f " << index[i1] + idStart << "/" << index[i1] + idStart << " " << index[i2] + idStart + << "/" << index[i2] + idStart << " " << index[i] + idStart << "/" << index[i] + idStart << std::endl; + } + else + outfile << "f " << index[i1] + idStart << " " << index[i2] + idStart << " " << index[i] + idStart << std::endl; + } + } /* for (int i = 2; i < npts; ++i) */ + } + } /* if (input->GetNumberOfStrips() > 0) */ + + this->CloseVTKFile(outfilep); + + // Delete the file if an error occurred + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + unlink(this->FileName); + } +} + +void cv::viz::vtkOBJWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + Superclass::PrintSelf(os, indent); + os << indent << "DecimalPrecision: " << DecimalPrecision << "\n"; +} diff --git a/modules/viz/src/vtk/vtkColorMatSource.h b/modules/viz/src/vtk/vtkOBJWriter.h similarity index 71% rename from modules/viz/src/vtk/vtkColorMatSource.h rename to modules/viz/src/vtk/vtkOBJWriter.h index d1650faad8..9bf5403e43 100644 --- a/modules/viz/src/vtk/vtkColorMatSource.h +++ b/modules/viz/src/vtk/vtkOBJWriter.h @@ -42,39 +42,36 @@ // //M*/ -#ifndef __vtkColorMatSource_h -#define __vtkColorMatSource_h +#ifndef __vtkOBJWriter_h +#define __vtkOBJWriter_h -#include -#include -#include +#include namespace cv { namespace viz { - class vtkColorMatSource : public vtkPolyDataAlgorithm + class vtkOBJWriter : public vtkPolyDataWriter { public: - static vtkColorMatSource *New(); - vtkTypeMacro(vtkColorMatSource,vtkPolyDataAlgorithm); - - virtual void SetColors(const Mat &colors, const Mat &cloud_mask = Mat()); + static vtkOBJWriter *New(); + vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + vtkGetMacro(DecimalPrecision, int); + vtkSetMacro(DecimalPrecision, int); protected: - vtkColorMatSource(); - ~vtkColorMatSource(); + vtkOBJWriter(); + ~vtkOBJWriter(); - int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void WriteData(); - vtkSmartPointer scalars; - private: - vtkColorMatSource(const vtkColorMatSource&); // Not implemented. - void operator=(const vtkColorMatSource&); // Not implemented. + int DecimalPrecision; - template - void filterNanCopy(const Mat& colors, const Mat& mask); + private: + vtkOBJWriter(const vtkOBJWriter&); // Not implemented. + void operator=(const vtkOBJWriter&); // Not implemented. }; } } diff --git a/modules/viz/src/vtk/vtkXYZWriter.cpp b/modules/viz/src/vtk/vtkXYZWriter.cpp new file mode 100644 index 0000000000..4518a0103a --- /dev/null +++ b/modules/viz/src/vtk/vtkXYZWriter.cpp @@ -0,0 +1,93 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkXYZWriter); +}} + +cv::viz::vtkXYZWriter::vtkXYZWriter() +{ + std::ofstream fout; // only used to extract the default precision + this->DecimalPrecision = fout.precision(); +} + +void cv::viz::vtkXYZWriter::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + // OpenVTKFile() will report any errors that happen + ostream *outfilep = this->OpenVTKFile(); + if (!outfilep) + return; + + ostream &outfile = *outfilep; + + for(vtkIdType i = 0; i < input->GetNumberOfPoints(); ++i) + { + Vec3d p; + input->GetPoint(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + + // Close the file + this->CloseVTKFile(outfilep); + + // Delete the file if an error occurred + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + unlink(this->FileName); + } +} + +void cv::viz::vtkXYZWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "DecimalPrecision: " << this->DecimalPrecision << "\n"; +} diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.h b/modules/viz/src/vtk/vtkXYZWriter.h similarity index 65% rename from modules/viz/src/vtk/vtkCloudColorMatSource.h rename to modules/viz/src/vtk/vtkXYZWriter.h index 0aa5b87a3e..bc49d10ef1 100644 --- a/modules/viz/src/vtk/vtkCloudColorMatSource.h +++ b/modules/viz/src/vtk/vtkXYZWriter.h @@ -42,47 +42,37 @@ // //M*/ -#ifndef __vtkCloudColorMatSource_h -#define __vtkCloudColorMatSource_h +#ifndef __vtkXYZWriter_h +#define __vtkXYZWriter_h -#include -#include -#include -#include -#include +#include "vtkPolyDataWriter.h" namespace cv { namespace viz { - class vtkCloudColorMatSource : public vtkPolyDataAlgorithm + class vtkXYZWriter : public vtkPolyDataWriter { public: - static vtkCloudColorMatSource *New(); - vtkTypeMacro(vtkCloudColorMatSource,vtkPolyDataAlgorithm); + static vtkXYZWriter *New(); + vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); - virtual void SetCloud(const Mat& cloud); - virtual void SetColors(const Mat &colors, const Mat &cloud_mask); + vtkGetMacro(DecimalPrecision, int); + vtkSetMacro(DecimalPrecision, int); protected: - vtkCloudColorMatSource(); - ~vtkCloudColorMatSource(); + vtkXYZWriter(); + ~vtkXYZWriter(){} - int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void WriteData(); - vtkSmartPointer points; - vtkSmartPointer vertices; - vtkSmartPointer scalars; - private: - vtkCloudColorMatSource(const vtkCloudColorMatSource&); // Not implemented. - void operator=(const vtkCloudColorMatSource&); // Not implemented. - - template int filterNanCopy(const Mat& source, int dataType); + int DecimalPrecision; - template - void filterNanCopy(const Mat& colors, const Mat& mask); + private: + vtkXYZWriter(const vtkXYZWriter&); // Not implemented. + void operator=(const vtkXYZWriter&); // Not implemented. }; } } - #endif diff --git a/modules/viz/test/test_tutorial3.cpp b/modules/viz/test/test_tutorial3.cpp index 6c63763dfd..12eca311c1 100644 --- a/modules/viz/test/test_tutorial3.cpp +++ b/modules/viz/test/test_tutorial3.cpp @@ -3,28 +3,6 @@ using namespace cv; using namespace std; -/** - * @function cvcloud_load - * @brief load bunny.ply - */ -Mat cvcloud_load() -{ - Mat cloud(1, 20000, CV_32FC3); - ifstream ifs("d:/cloud_dragon.ply"); - - string str; - for(size_t i = 0; i < 12; ++i) - getline(ifs, str); - - Point3f* data = cloud.ptr(); - //float dummy1, dummy2; - for(size_t i = 0; i < 20000; ++i) - ifs >> data[i].x >> data[i].y >> data[i].z;// >> dummy1 >> dummy2; - - //cloud *= 5.0f; - return cloud; -} - /** * @function main */ @@ -47,7 +25,7 @@ void tutorial3(bool camera_pov) Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos); /// Create a cloud widget. - Mat bunny_cloud = cvcloud_load(); + Mat bunny_cloud = viz::readCloud("d:/cloud_dragon.ply"); viz::WCloud cloud_widget(bunny_cloud, viz::Color::green()); /// Pose of the widget in camera frame