diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 89810d547..a532ba783 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -99,9 +99,10 @@ namespace cv CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); /////////////////////////////////////////////////////////////////////////////////////////////// - /// Read mesh. Only ply format is supported now + /// Reads mesh. Only ply format is supported now. The function tries to read texture from png-file, + /// and in case of faulure, just leaves the texture field empty. - CV_EXPORTS Mesh readMesh (const String& file); + CV_EXPORTS Mesh readMesh(const String& file); /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index d5f969a49..bf154e76e 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -122,6 +122,7 @@ #include #include #include +#include #include #include #include diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 09a2f4d0f..bf61432cb 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -57,80 +57,56 @@ cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, c //////////////////////////////////////////////////////////////////// /// cv::viz::Mesh3d -namespace cv { namespace viz { namespace -{ - struct MeshUtils - { - static Mesh loadMesh(const String &file) - { - Mesh mesh; - - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName(file.c_str()); - reader->Update(); - - vtkSmartPointer poly_data = reader->GetOutput(); - CV_Assert("File does not exist or file format is not supported." && poly_data); - - vtkSmartPointer 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(); - 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(); - - 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(); - 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(cell_points[i]); - } - - return mesh; - } - }; -}}} - cv::viz::Mesh cv::viz::Mesh::load(const String& file) { - return MeshUtils::loadMesh(file); + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(file.c_str()); + reader->Update(); + + vtkSmartPointer polydata = reader->GetOutput(); + CV_Assert("File does not exist or file format is not supported." && polydata); + + Mesh mesh; + vtkSmartPointer sink = vtkSmartPointer::New(); + sink->SetOutput(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords); + sink->SetInputConnection(reader->GetOutputPort()); + sink->Write(); + + // Now handle the polygons + + vtkSmartPointer polygons = polydata->GetPolys(); + mesh.polygons.create(1, polygons->GetSize(), CV_32SC1); + int* poly_ptr = mesh.polygons.ptr(); + + polygons->InitTraversal(); + vtkIdType nr_cell_points, *cell_points; + while (polygons->GetNextCell(nr_cell_points, cell_points)) + { + *poly_ptr++ = nr_cell_points; + for (vtkIdType i = 0; i < nr_cell_points; ++i) + *poly_ptr++ = (int)cell_points[i]; + } + + String::size_type pos = file.find_last_of('.'); + String png = (pos == String::npos) ? file : file.substr(0, pos+1) + "png"; + + vtkSmartPointer png_reader = vtkSmartPointer::New(); + + if (png_reader->CanReadFile(png.c_str())) + { + png_reader->SetFileName(png.c_str()); + png_reader->Update(); + vtkSmartPointer imagedata = png_reader->GetOutput(); + + Size sz(imagedata->GetDimensions()[0], imagedata->GetDimensions()[1]); + int channels = imagedata->GetNumberOfScalarComponents(); + CV_Assert(imagedata->GetScalarType() == VTK_UNSIGNED_CHAR); + + void *ptr = imagedata->GetScalarPointer(0,0,0); + Mat(sz, CV_8UC(channels), ptr).copyTo(mesh.texture); + } + + return mesh; } //////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp index cf1eb4648..09ef0cca9 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -52,11 +52,12 @@ namespace cv { namespace viz cv::viz::vtkCloudMatSink::vtkCloudMatSink() {} cv::viz::vtkCloudMatSink::~vtkCloudMatSink() {} -void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals) +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() @@ -120,12 +121,32 @@ void cv::viz::vtkCloudMatSink::WriteData() Mat buffer(cloud.size(), CV_64FC(channels)); Vec3d *cptr = buffer.ptr(); for(size_t i = 0; i < buffer.total(); ++i) - *cptr++ = Vec3d(scalars_data->GetTuple(i)); + *cptr++ = Vec3d(normals_data->GetTuple(i)); buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F); } else normals.release(); + + vtkSmartPointer 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(); + 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) diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index 69262f247..3af9e6544 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -59,7 +59,7 @@ namespace cv vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); - void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); + void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray(), OutputArray tcoords = noArray()); protected: vtkCloudMatSink(); @@ -67,7 +67,7 @@ namespace cv void WriteData(); - _OutputArray cloud, colors, normals; + _OutputArray cloud, colors, normals, tcoords; private: vtkCloudMatSink(const vtkCloudMatSink&); // Not implemented.