mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
CloudViewer: no need to save texture on disk before rendering TextureMesh (opencv image to vtk texture directly)
This commit is contained in:
@@ -134,16 +134,20 @@ public:
|
||||
const pcl::PolygonMesh::Ptr & mesh,
|
||||
const Transform & pose = Transform::getIdentity());
|
||||
|
||||
// Only one texture per mesh is supported!
|
||||
bool addCloudTextureMesh(
|
||||
const std::string & id,
|
||||
const pcl::TextureMesh::Ptr & textureMesh,
|
||||
const cv::Mat & texture,
|
||||
const Transform & pose = Transform::getIdentity());
|
||||
|
||||
bool addOctomap(const OctoMap * octomap, unsigned int treeDepth = 0);
|
||||
void removeOctomap();
|
||||
|
||||
// Only one texture per mesh is supported!
|
||||
bool addTextureMesh (
|
||||
const pcl::TextureMesh &mesh,
|
||||
const cv::Mat & texture,
|
||||
const std::string &id = "texture",
|
||||
int viewport = 0);
|
||||
bool addOccupancyGridMap(
|
||||
@@ -269,8 +273,6 @@ public:
|
||||
void setGridCellCount(unsigned int count);
|
||||
void setGridCellSize(float size);
|
||||
|
||||
void setWorkingDirectory(const QString & path) {_workingDirectory = path;}
|
||||
|
||||
public slots:
|
||||
void setDefaultBackgroundColor(const QColor & color);
|
||||
void setBackgroundColor(const QColor & color);
|
||||
@@ -335,7 +337,6 @@ private:
|
||||
Transform _lastPose;
|
||||
std::list<std::string> _gridLines;
|
||||
QSet<Qt::Key> _keysPressed;
|
||||
QString _workingDirectory;
|
||||
QColor _defaultBgColor;
|
||||
QColor _currentBgColor;
|
||||
bool _frontfaceCulling;
|
||||
|
||||
@@ -96,6 +96,7 @@ SET(SRC_FILES
|
||||
./ParametersToolBox.cpp
|
||||
./DepthCalibrationDialog.cpp
|
||||
./3rdParty/QMultiComboBox.cpp
|
||||
./opencv/vtkImageMatSource.cpp
|
||||
|
||||
${moc_srcs}
|
||||
${moc_uis}
|
||||
|
||||
@@ -59,6 +59,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <vtkPNGReader.h>
|
||||
#include <vtkTIFFReader.h>
|
||||
#include <vtkOpenGLRenderWindow.h>
|
||||
#include <opencv/vtkImageMatSource.h>
|
||||
|
||||
#ifdef RTABMAP_OCTOMAP
|
||||
#include <rtabmap/core/OctoMap.h>
|
||||
@@ -138,7 +139,6 @@ CloudViewer::CloudViewer(QWidget *parent) :
|
||||
_gridCellSize(1),
|
||||
_lastCameraOrientation(0,0,0),
|
||||
_lastCameraPose(0,0,0),
|
||||
_workingDirectory("."),
|
||||
_defaultBgColor(Qt::black),
|
||||
_currentBgColor(Qt::black),
|
||||
_frontfaceCulling(false),
|
||||
@@ -638,6 +638,7 @@ bool CloudViewer::addCloudMesh(
|
||||
bool CloudViewer::addCloudTextureMesh(
|
||||
const std::string & id,
|
||||
const pcl::TextureMesh::Ptr & textureMesh,
|
||||
const cv::Mat & texture,
|
||||
const Transform & pose)
|
||||
{
|
||||
if(_addedClouds.contains(id))
|
||||
@@ -646,7 +647,7 @@ bool CloudViewer::addCloudTextureMesh(
|
||||
}
|
||||
|
||||
UDEBUG("Adding %s", id.c_str());
|
||||
if(this->addTextureMesh(*textureMesh, id))
|
||||
if(this->addTextureMesh(*textureMesh, texture, id))
|
||||
{
|
||||
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->SetLighting(_aSetLighting->isChecked());
|
||||
_visualizer->getCloudActorMap()->find(id)->second.actor->GetProperty()->SetEdgeVisibility(_aSetEdgeVisibility->isChecked());
|
||||
@@ -769,133 +770,13 @@ void CloudViewer::removeOctomap()
|
||||
#endif
|
||||
}
|
||||
|
||||
// Copied from PCL 1.8
|
||||
int textureFromTexMaterial (const pcl::TexMaterial& tex_mat,
|
||||
vtkTexture* vtk_tex)
|
||||
{
|
||||
if (tex_mat.tex_file == "")
|
||||
{
|
||||
PCL_WARN ("[PCLVisualizer::textureFromTexMaterial] No texture file given for material %s!\n",
|
||||
tex_mat.tex_name.c_str ());
|
||||
return (-1);
|
||||
}
|
||||
|
||||
boost::filesystem::path full_path (tex_mat.tex_file.c_str ());
|
||||
if (!boost::filesystem::exists (full_path))
|
||||
{
|
||||
boost::filesystem::path parent_dir = full_path.parent_path ();
|
||||
std::string upper_filename = tex_mat.tex_file;
|
||||
boost::to_upper (upper_filename);
|
||||
std::string real_name = "";
|
||||
|
||||
try
|
||||
{
|
||||
if (!boost::filesystem::exists (parent_dir))
|
||||
{
|
||||
PCL_WARN ("[PCLVisualizer::textureFromTexMaterial] Parent directory '%s' doesn't exist!\n",
|
||||
parent_dir.string ().c_str ());
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_directory (parent_dir))
|
||||
{
|
||||
PCL_WARN ("[PCLVisualizer::textureFromTexMaterial] Parent '%s' is not a directory !\n",
|
||||
parent_dir.string ().c_str ());
|
||||
return (-1);
|
||||
}
|
||||
|
||||
typedef std::vector<boost::filesystem::path> paths_vector;
|
||||
paths_vector paths;
|
||||
std::copy (boost::filesystem::directory_iterator (parent_dir),
|
||||
boost::filesystem::directory_iterator (),
|
||||
back_inserter (paths));
|
||||
|
||||
for (paths_vector::const_iterator it = paths.begin (); it != paths.end (); ++it)
|
||||
{
|
||||
if (boost::filesystem::is_regular_file (*it))
|
||||
{
|
||||
std::string name = it->string ();
|
||||
boost::to_upper (name);
|
||||
if (name == upper_filename)
|
||||
{
|
||||
real_name = it->string ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check texture file existence
|
||||
if (real_name == "")
|
||||
{
|
||||
PCL_WARN ("[PCLVisualizer::textureFromTexMaterial] Can not find texture file %s!\n",
|
||||
tex_mat.tex_file.c_str ());
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
catch (const boost::filesystem::filesystem_error& ex)
|
||||
{
|
||||
|
||||
PCL_WARN ("[PCLVisualizer::textureFromTexMaterial] Error %s when looking for file %s\n!",
|
||||
ex.what (), tex_mat.tex_file.c_str ());
|
||||
return (-1);
|
||||
}
|
||||
|
||||
//Save the real path
|
||||
full_path = real_name.c_str ();
|
||||
}
|
||||
|
||||
std::string extension = full_path.extension ().string ();
|
||||
//!!! nizar 20131206 : The list is far from being exhaustive I am afraid.
|
||||
if ((extension == ".jpg") || (extension == ".JPG"))
|
||||
{
|
||||
vtkSmartPointer<vtkJPEGReader> jpeg_reader = vtkSmartPointer<vtkJPEGReader>::New ();
|
||||
jpeg_reader->SetFileName (full_path.string ().c_str ());
|
||||
jpeg_reader->Update ();
|
||||
vtk_tex->SetInputConnection (jpeg_reader->GetOutputPort ());
|
||||
}
|
||||
else if ((extension == ".bmp") || (extension == ".BMP"))
|
||||
{
|
||||
vtkSmartPointer<vtkBMPReader> bmp_reader = vtkSmartPointer<vtkBMPReader>::New ();
|
||||
bmp_reader->SetFileName (full_path.string ().c_str ());
|
||||
bmp_reader->Update ();
|
||||
vtk_tex->SetInputConnection (bmp_reader->GetOutputPort ());
|
||||
}
|
||||
else if ((extension == ".pnm") || (extension == ".PNM"))
|
||||
{
|
||||
vtkSmartPointer<vtkPNMReader> pnm_reader = vtkSmartPointer<vtkPNMReader>::New ();
|
||||
pnm_reader->SetFileName (full_path.string ().c_str ());
|
||||
pnm_reader->Update ();
|
||||
vtk_tex->SetInputConnection (pnm_reader->GetOutputPort ());
|
||||
}
|
||||
else if ((extension == ".png") || (extension == ".PNG"))
|
||||
{
|
||||
vtkSmartPointer<vtkPNGReader> png_reader = vtkSmartPointer<vtkPNGReader>::New ();
|
||||
png_reader->SetFileName (full_path.string ().c_str ());
|
||||
png_reader->Update ();
|
||||
vtk_tex->SetInputConnection (png_reader->GetOutputPort ());
|
||||
}
|
||||
else if ((extension == ".tiff") || (extension == ".TIFF"))
|
||||
{
|
||||
vtkSmartPointer<vtkTIFFReader> tiff_reader = vtkSmartPointer<vtkTIFFReader>::New ();
|
||||
tiff_reader->SetFileName (full_path.string ().c_str ());
|
||||
tiff_reader->Update ();
|
||||
vtk_tex->SetInputConnection (tiff_reader->GetOutputPort ());
|
||||
}
|
||||
else
|
||||
{
|
||||
PCL_WARN ("[PCLVisualizer::textureFromTexMaterial] Unhandled image %s for material %s!\n",
|
||||
full_path.c_str (), tex_mat.tex_name.c_str ());
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
bool CloudViewer::addTextureMesh (
|
||||
const pcl::TextureMesh &mesh,
|
||||
const cv::Mat & image,
|
||||
const std::string &id,
|
||||
int viewport)
|
||||
{
|
||||
// Copied from PCL 1.8, modified to ignore vertex color
|
||||
// Copied from PCL 1.8, modified to ignore vertex color and accept only one material (loaded from memory instead of file)
|
||||
|
||||
pcl::visualization::CloudActorMap::iterator am_it = _visualizer->getCloudActorMap()->find (id);
|
||||
if (am_it != _visualizer->getCloudActorMap()->end ())
|
||||
@@ -911,6 +792,11 @@ bool CloudViewer::addTextureMesh (
|
||||
PCL_ERROR("[PCLVisualizer::addTextureMesh] No textures found!\n");
|
||||
return (false);
|
||||
}
|
||||
else if (mesh.tex_materials.size() > 1)
|
||||
{
|
||||
PCL_ERROR("[PCLVisualizer::addTextureMesh] only one material per mesh is supported!\n");
|
||||
return (false);
|
||||
}
|
||||
// polygons are mapped to texture materials
|
||||
if (mesh.tex_materials.size () != mesh.tex_polygons.size ())
|
||||
{
|
||||
@@ -951,31 +837,7 @@ bool CloudViewer::addTextureMesh (
|
||||
vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New ();
|
||||
bool has_color = false;
|
||||
vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New ();
|
||||
if (0)//(pcl::getFieldIndex(mesh.cloud, "rgba") != -1) ||
|
||||
//(pcl::getFieldIndex(mesh.cloud, "rgb") != -1))
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZRGB> cloud;
|
||||
pcl::fromPCLPointCloud2(mesh.cloud, cloud);
|
||||
if (cloud.points.size () == 0)
|
||||
{
|
||||
PCL_ERROR("[PCLVisualizer::addTextureMesh] Cloud is empty!\n");
|
||||
return (false);
|
||||
}
|
||||
pcl::visualization::PCLVisualizer::convertToVtkMatrix (cloud.sensor_origin_, cloud.sensor_orientation_, transformation);
|
||||
has_color = true;
|
||||
colors->SetNumberOfComponents (3);
|
||||
colors->SetName ("Colors");
|
||||
poly_points->SetNumberOfPoints (cloud.size ());
|
||||
for (std::size_t i = 0; i < cloud.points.size (); ++i)
|
||||
{
|
||||
const pcl::PointXYZRGB &p = cloud.points[i];
|
||||
poly_points->InsertPoint (i, p.x, p.y, p.z);
|
||||
const unsigned char color[3] = {p.r, p.g, p.b};
|
||||
colors->InsertNextTupleValue(color);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
|
||||
pcl::fromPCLPointCloud2 (mesh.cloud, *cloud);
|
||||
// no points --> exit
|
||||
@@ -991,7 +853,6 @@ bool CloudViewer::addTextureMesh (
|
||||
const pcl::PointXYZ &p = cloud->points[i];
|
||||
poly_points->InsertPoint (i, p.x, p.y, p.z);
|
||||
}
|
||||
}
|
||||
|
||||
//create polys from polyMesh.tex_polygons
|
||||
vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New ();
|
||||
@@ -1023,68 +884,13 @@ bool CloudViewer::addTextureMesh (
|
||||
vtkTextureUnitManager* tex_manager = vtkOpenGLRenderWindow::SafeDownCast (_visualizer->getRenderWindow())->GetTextureUnitManager ();
|
||||
if (!tex_manager)
|
||||
return (false);
|
||||
// Check if hardware support multi texture
|
||||
int texture_units = tex_manager->GetNumberOfTextureUnits ();
|
||||
if ((mesh.tex_materials.size () > 1) && (texture_units > 1))
|
||||
{
|
||||
if (texture_units < (int)mesh.tex_materials.size ())
|
||||
PCL_WARN ("[PCLVisualizer::addTextureMesh] GPU texture units %d < mesh textures %d!\n",
|
||||
texture_units, mesh.tex_materials.size ());
|
||||
// Load textures
|
||||
std::size_t last_tex_id = std::min (static_cast<int> (mesh.tex_materials.size ()), texture_units);
|
||||
int tu = vtkProperty::VTK_TEXTURE_UNIT_0;
|
||||
std::size_t tex_id = 0;
|
||||
while (tex_id < last_tex_id)
|
||||
{
|
||||
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New ();
|
||||
if (textureFromTexMaterial (mesh.tex_materials[tex_id], texture))
|
||||
{
|
||||
PCL_WARN ("[PCLVisualizer::addTextureMesh] Failed to load texture %s, skipping!\n",
|
||||
mesh.tex_materials[tex_id].tex_name.c_str ());
|
||||
continue;
|
||||
}
|
||||
// the first texture is in REPLACE mode others are in ADD mode
|
||||
if (tex_id == 0)
|
||||
texture->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_REPLACE);
|
||||
else
|
||||
texture->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);
|
||||
// add a texture coordinates array per texture
|
||||
vtkSmartPointer<vtkFloatArray> coordinates = vtkSmartPointer<vtkFloatArray>::New ();
|
||||
coordinates->SetNumberOfComponents (2);
|
||||
std::stringstream ss; ss << "TCoords" << tex_id;
|
||||
std::string this_coordinates_name = ss.str ();
|
||||
coordinates->SetName (this_coordinates_name.c_str ());
|
||||
|
||||
for (std::size_t t = 0 ; t < mesh.tex_coordinates.size (); ++t)
|
||||
{
|
||||
if (t == tex_id)
|
||||
for (std::size_t tc = 0; tc < mesh.tex_coordinates[t].size (); ++tc)
|
||||
coordinates->InsertNextTuple2 ((double)mesh.tex_coordinates[t][tc][0],
|
||||
(double)mesh.tex_coordinates[t][tc][1]);
|
||||
else
|
||||
for (std::size_t tc = 0; tc < mesh.tex_coordinates[t].size (); ++tc)
|
||||
coordinates->InsertNextTuple2 (-1.0, -1.0);
|
||||
}
|
||||
mapper->MapDataArrayToMultiTextureAttribute(tu,
|
||||
this_coordinates_name.c_str (),
|
||||
vtkDataObject::FIELD_ASSOCIATION_POINTS);
|
||||
polydata->GetPointData ()->AddArray (coordinates);
|
||||
actor->GetProperty ()->SetTexture(tu, texture);
|
||||
++tex_id;
|
||||
++tu;
|
||||
}
|
||||
} // end of multi texturing
|
||||
else
|
||||
{
|
||||
if ((mesh.tex_materials.size () > 1) && (texture_units < 2))
|
||||
PCL_WARN ("[PCLVisualizer::addTextureMesh] Your GPU doesn't support multi texturing. "
|
||||
"Will use first one only!\n");
|
||||
|
||||
|
||||
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New ();
|
||||
// fill vtkTexture from pcl::TexMaterial structure
|
||||
if (textureFromTexMaterial (mesh.tex_materials[0], texture))
|
||||
PCL_WARN ("[PCLVisualizer::addTextureMesh] Failed to create vtkTexture from %s!\n",
|
||||
mesh.tex_materials[0].tex_name.c_str ());
|
||||
vtkSmartPointer<vtkImageMatSource> cvImageToVtk = vtkSmartPointer<vtkImageMatSource>::New();
|
||||
cvImageToVtk->SetImage(image);
|
||||
cvImageToVtk->Update();
|
||||
texture->SetInputConnection(cvImageToVtk->GetOutputPort());
|
||||
|
||||
// set texture coordinates
|
||||
vtkSmartPointer<vtkFloatArray> coordinates = vtkSmartPointer<vtkFloatArray>::New ();
|
||||
@@ -1099,7 +905,6 @@ bool CloudViewer::addTextureMesh (
|
||||
polydata->GetPointData ()->SetTCoords(coordinates);
|
||||
// apply texture
|
||||
actor->SetTexture (texture);
|
||||
} // end of one texture
|
||||
|
||||
// set mapper
|
||||
actor->SetMapper (mapper);
|
||||
@@ -1175,10 +980,7 @@ bool CloudViewer::addOccupancyGridMap(
|
||||
|
||||
// default texture materials parameters
|
||||
pcl::TexMaterial material;
|
||||
// hack, can we read from memory?
|
||||
std::string tmpPath = (_workingDirectory+"/.tmp_map.png").toStdString();
|
||||
cv::imwrite(tmpPath, map8U);
|
||||
material.tex_file = tmpPath;
|
||||
material.tex_file = "";
|
||||
mesh->tex_materials.push_back(material);
|
||||
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||
@@ -1192,11 +994,8 @@ bool CloudViewer::addOccupancyGridMap(
|
||||
coordinates.push_back(Eigen::Vector2f(0,0));
|
||||
mesh->tex_coordinates.push_back(coordinates);
|
||||
|
||||
this->addTextureMesh(*mesh, "map");
|
||||
this->addTextureMesh(*mesh, map8U, "map");
|
||||
setCloudOpacity("map", opacity);
|
||||
|
||||
//removed tmp texture file
|
||||
QFile::remove(tmpPath.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -621,7 +621,6 @@ void ExportCloudsDialog::viewClouds(
|
||||
window->resize(QDesktopWidget().availableGeometry(this).size() * 0.7);
|
||||
|
||||
CloudViewer * viewer = new CloudViewer(window);
|
||||
viewer->setCameraLockZ(false);
|
||||
if(_ui->comboBox_pipeline->currentIndex() == 0)
|
||||
{
|
||||
viewer->setBackfaceCulling(true, false);
|
||||
@@ -644,19 +643,16 @@ void ExportCloudsDialog::viewClouds(
|
||||
|
||||
if(textureMeshes.size())
|
||||
{
|
||||
QString prefix = "tmp_textures";
|
||||
removeDirRecursively(workingDirectory+QDir::separator()+prefix);
|
||||
QDir(workingDirectory).mkdir(prefix);
|
||||
for(std::map<int, pcl::TextureMesh::Ptr>::iterator iter = textureMeshes.begin(); iter!=textureMeshes.end(); ++iter)
|
||||
for (std::map<int, pcl::TextureMesh::Ptr>::iterator iter = textureMeshes.begin(); iter != textureMeshes.end(); ++iter)
|
||||
{
|
||||
_progressDialog->appendText(tr("Viewing the mesh %1 (%2 polygons)...").arg(iter->first).arg(iter->second->tex_polygons.size()?iter->second->tex_polygons[0].size():0));
|
||||
_progressDialog->appendText(tr("Viewing the mesh %1 (%2 polygons)...").arg(iter->first).arg(iter->second->tex_polygons.size() ? iter->second->tex_polygons[0].size() : 0));
|
||||
_progressDialog->incrementStep();
|
||||
|
||||
pcl::TextureMesh::Ptr mesh = iter->second;
|
||||
|
||||
// As CloudViewer is not supporting more than one texture per mesh, merge them all by default
|
||||
cv::Mat globalTexture;
|
||||
if(mesh->tex_materials.size() > 1)
|
||||
if (mesh->tex_materials.size() > 1)
|
||||
{
|
||||
globalTexture = mergeTextures(*mesh, cachedSignatures);
|
||||
}
|
||||
@@ -665,7 +661,7 @@ void ExportCloudsDialog::viewClouds(
|
||||
// tex_coordinates should be linked to points, not
|
||||
// polygon vertices. Points linked to multiple different TCoords (different textures) should
|
||||
// be duplicated.
|
||||
for(unsigned int t=0; t<mesh->tex_coordinates.size(); ++t)
|
||||
for (unsigned int t = 0; t < mesh->tex_coordinates.size(); ++t)
|
||||
{
|
||||
UASSERT(mesh->tex_polygons[t].size());
|
||||
|
||||
@@ -674,15 +670,16 @@ void ExportCloudsDialog::viewClouds(
|
||||
|
||||
// make a cloud with as many points than polygon vertices
|
||||
unsigned int nPoints = mesh->tex_coordinates[t].size();
|
||||
UASSERT(nPoints== mesh->tex_polygons[t].size()*mesh->tex_polygons[t][0].vertices.size()); // assuming polygon size is constant!
|
||||
UASSERT(nPoints == mesh->tex_polygons[t].size()*mesh->tex_polygons[t][0].vertices.size()); // assuming polygon size is constant!
|
||||
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
|
||||
cloud->resize(nPoints);
|
||||
|
||||
unsigned int oi=0;
|
||||
for(unsigned int i=0; i<mesh->tex_polygons[t].size(); ++i)
|
||||
unsigned int oi = 0;
|
||||
for (unsigned int i = 0; i < mesh->tex_polygons[t].size(); ++i)
|
||||
{
|
||||
pcl::Vertices & vertices = mesh->tex_polygons[t][i];
|
||||
|
||||
for(unsigned int j=0; j<vertices.vertices.size(); ++j)
|
||||
{
|
||||
UASSERT(oi < cloud->size());
|
||||
@@ -695,77 +692,23 @@ void ExportCloudsDialog::viewClouds(
|
||||
pcl::toPCLPointCloud2(*cloud, mesh->cloud);
|
||||
}
|
||||
|
||||
// save tmp textures
|
||||
cv::Size imageSize;
|
||||
for(unsigned int i=0;i<mesh->tex_materials.size(); ++i)
|
||||
if (globalTexture.empty())
|
||||
{
|
||||
if(!mesh->tex_materials[i].tex_file.empty())
|
||||
{
|
||||
// absolute path
|
||||
QString fullPath = workingDirectory+QDir::separator()+prefix+QDir::separator()+QString(mesh->tex_materials[i].tex_file.c_str())+_ui->comboBox_meshingTextureFormat->currentText();
|
||||
if(!QFileInfo(fullPath).exists())
|
||||
{
|
||||
if(uIsInteger(mesh->tex_materials[i].tex_file, false))
|
||||
{
|
||||
int textureId = uStr2Int(mesh->tex_materials[i].tex_file);
|
||||
UASSERT(cachedSignatures.contains(textureId) && !cachedSignatures.value(textureId).sensorData().imageCompressed().empty());
|
||||
cv::Mat image;
|
||||
cachedSignatures.value(textureId).sensorData().uncompressDataConst(&image, 0);
|
||||
UASSERT(!image.empty());
|
||||
imageSize = image.size();
|
||||
if(_ui->groupBox_gain->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0)
|
||||
{
|
||||
_compensator->apply(textureId, image);
|
||||
}
|
||||
UASSERT(mesh->tex_materials.size()==1 &&
|
||||
!mesh->tex_materials[0].tex_file.empty() &&
|
||||
uIsInteger(mesh->tex_materials[0].tex_file, false));
|
||||
|
||||
if(!cv::imwrite(fullPath.toStdString(), image))
|
||||
{
|
||||
_progressDialog->appendText(tr("Failed saving texture \"%1\" to \"%2\".")
|
||||
.arg(mesh->tex_materials[i].tex_file.c_str()).arg(fullPath), Qt::darkRed);
|
||||
_progressDialog->setAutoClose(false);
|
||||
}
|
||||
}
|
||||
else if(imageSize.height && imageSize.width)
|
||||
{
|
||||
// make a blank texture
|
||||
cv::Mat image = cv::Mat::ones(imageSize, CV_8UC1)*255;
|
||||
cv::imwrite(fullPath.toStdString(), image);
|
||||
}
|
||||
else if(!globalTexture.empty())
|
||||
{
|
||||
if(!cv::imwrite(fullPath.toStdString(), globalTexture))
|
||||
{
|
||||
_progressDialog->appendText(tr("Failed saving texture \"%1\" to \"%2\".")
|
||||
.arg(mesh->tex_materials[i].tex_file.c_str()).arg(fullPath), Qt::darkRed);
|
||||
_progressDialog->setAutoClose(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UWARN("Ignored texture %s (no image size set yet)", mesh->tex_materials[i].tex_file.c_str());
|
||||
}
|
||||
}
|
||||
mesh->tex_materials[i].tex_file=fullPath.toStdString();
|
||||
int textureId = uStr2Int(mesh->tex_materials[0].tex_file);
|
||||
UASSERT(cachedSignatures.contains(textureId) && !cachedSignatures.value(textureId).sensorData().imageCompressed().empty());
|
||||
cachedSignatures.value(textureId).sensorData().uncompressDataConst(&globalTexture, 0);
|
||||
UASSERT(!globalTexture.empty());
|
||||
if (_ui->groupBox_gain->isChecked() && _compensator && _compensator->getIndex(textureId) >= 0)
|
||||
{
|
||||
_compensator->apply(textureId, globalTexture);
|
||||
}
|
||||
}
|
||||
|
||||
bool isRGB = false;
|
||||
for(unsigned int i=0; i<mesh->cloud.fields.size(); ++i)
|
||||
{
|
||||
if(mesh->cloud.fields[i].name.compare("rgb") == 0)
|
||||
{
|
||||
isRGB=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isRGB)
|
||||
{
|
||||
viewer->addCloudTextureMesh(uFormat("mesh%d",iter->first), mesh, iter->first>0?poses.at(iter->first):Transform::getIdentity());
|
||||
}
|
||||
else
|
||||
{
|
||||
viewer->addCloudTextureMesh(uFormat("mesh%d",iter->first), mesh, iter->first>0?poses.at(iter->first):Transform::getIdentity());
|
||||
}
|
||||
viewer->addCloudTextureMesh(uFormat("mesh%d",iter->first), mesh, globalTexture, iter->first>0?poses.at(iter->first):Transform::getIdentity());
|
||||
_progressDialog->appendText(tr("Viewing the mesh %1 (%2 polygons)... done.").arg(iter->first).arg(mesh->tex_polygons.size()?mesh->tex_polygons[0].size():0));
|
||||
QApplication::processEvents();
|
||||
}
|
||||
@@ -1038,7 +981,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
.arg(assembledCloud->size())
|
||||
.arg(_ui->doubleSpinBox_voxelSize_assembled->value()));
|
||||
QApplication::processEvents();
|
||||
int before = assembledCloud->size();
|
||||
unsigned int before = assembledCloud->size();
|
||||
assembledCloud = util3d::voxelize(
|
||||
assembledCloud,
|
||||
_ui->doubleSpinBox_voxelSize_assembled->value());
|
||||
@@ -1221,7 +1164,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
std::vector<std::set<int> > neighbors;
|
||||
std::vector<std::set<int> > vertexToPolygons;
|
||||
util3d::createPolygonIndexes(polygons,
|
||||
iter->second->size(),
|
||||
(int)iter->second->size(),
|
||||
neighbors,
|
||||
vertexToPolygons);
|
||||
std::list<std::list<int> > clusters = util3d::clusterPolygons(
|
||||
@@ -1237,7 +1180,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
}
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
int before = polygons.size();
|
||||
int before = (int)polygons.size();
|
||||
polygons = filteredPolygons;
|
||||
|
||||
if(oi == 0)
|
||||
@@ -1575,7 +1518,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
}
|
||||
}
|
||||
filteredPolygons.resize(oi);
|
||||
int before = mesh->polygons.size();
|
||||
int before = (int)mesh->polygons.size();
|
||||
mesh->polygons = filteredPolygons;
|
||||
|
||||
_progressDialog->appendText(tr("Filtered %1 polygons.").arg(before-oi));
|
||||
@@ -1665,7 +1608,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
textureMesh->tex_coordinates.resize(1);
|
||||
|
||||
//tex_coordinates should be linked to polygon vertices
|
||||
int polygonSize = textureMesh->tex_polygons[0][0].vertices.size();
|
||||
int polygonSize = (int)textureMesh->tex_polygons[0][0].vertices.size();
|
||||
textureMesh->tex_coordinates[0].resize(polygonSize*textureMesh->tex_polygons[0].size());
|
||||
for(unsigned int i=0; i<textureMesh->tex_polygons[0].size(); ++i)
|
||||
{
|
||||
@@ -1723,7 +1666,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
QApplication::processEvents();
|
||||
|
||||
// concatenate all polygons
|
||||
int totalSize = 0;
|
||||
unsigned int totalSize = 0;
|
||||
for(unsigned int t=0; t<textureMesh->tex_polygons.size(); ++t)
|
||||
{
|
||||
totalSize+=textureMesh->tex_polygons[t].size();
|
||||
@@ -1742,7 +1685,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
||||
std::vector<std::set<int> > neighbors;
|
||||
std::vector<std::set<int> > vertexToPolygons;
|
||||
util3d::createPolygonIndexes(allPolygons,
|
||||
textureMesh->cloud.data.size()/textureMesh->cloud.point_step,
|
||||
(int)textureMesh->cloud.data.size()/textureMesh->cloud.point_step,
|
||||
neighbors,
|
||||
vertexToPolygons);
|
||||
std::list<std::list<int> > clusters = util3d::clusterPolygons(
|
||||
@@ -2066,8 +2009,8 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
|
||||
}
|
||||
|
||||
clouds.insert(std::make_pair(iter->first, std::make_pair(cloud, indices)));
|
||||
points = cloud->size();
|
||||
totalIndices = indices->size();
|
||||
points = (int)cloud->size();
|
||||
totalIndices = (int)indices->size();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -519,7 +519,6 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
||||
_ui->statsToolBox->setNewFigureMaxItems(50);
|
||||
_ui->statsToolBox->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
|
||||
_ui->graphicsView_graphView->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
|
||||
_cloudViewer->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
|
||||
_cloudViewer->setBackfaceCulling(true, false);
|
||||
_preferencesDialog->loadWidgetState(_cloudViewer);
|
||||
|
||||
@@ -1017,25 +1016,10 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
|
||||
mesh_material.tex_illum = 1;
|
||||
|
||||
mesh_material.tex_name = "material_odom";
|
||||
|
||||
QDir dir(_preferencesDialog->getWorkingDirectory());
|
||||
ExportCloudsDialog::removeDirRecursively(_preferencesDialog->getWorkingDirectory()+QDir::separator()+"tmp_textures");
|
||||
dir.mkdir("tmp_textures");
|
||||
|
||||
std::string tmpDirectory = dir.filePath("tmp_textures").toStdString();
|
||||
mesh_material.tex_file = uFormat("%s/%s.png", tmpDirectory.c_str(), "texture_odom");
|
||||
if(!cv::imwrite(mesh_material.tex_file, odom.data().imageRaw()))
|
||||
{
|
||||
UERROR("Cannot save texture of image odom");
|
||||
}
|
||||
else
|
||||
{
|
||||
UINFO("Saved temporary texture: \"%s\"", mesh_material.tex_file.c_str());
|
||||
}
|
||||
|
||||
mesh_material.tex_file = "";
|
||||
textureMesh->tex_materials.push_back(mesh_material);
|
||||
|
||||
if(!_cloudViewer->addCloudTextureMesh("cloudOdom", textureMesh, _odometryCorrection))
|
||||
if(!_cloudViewer->addCloudTextureMesh("cloudOdom", textureMesh, odom.data().imageRaw(), _odometryCorrection))
|
||||
{
|
||||
UERROR("Adding cloudOdom to viewer failed!");
|
||||
}
|
||||
@@ -2613,28 +2597,15 @@ std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> MainWindow::c
|
||||
tex_name << "material_" << nodeId;
|
||||
tex_name >> mesh_material.tex_name;
|
||||
|
||||
QDir dir(_preferencesDialog->getWorkingDirectory());
|
||||
ExportCloudsDialog::removeDirRecursively(_preferencesDialog->getWorkingDirectory()+QDir::separator()+"tmp_textures");
|
||||
dir.mkdir("tmp_textures");
|
||||
|
||||
std::string tmpDirectory = dir.filePath("tmp_textures").toStdString();
|
||||
mesh_material.tex_file = uFormat("%s/%s%d.png", tmpDirectory.c_str(), "texture_", nodeId);
|
||||
mesh_material.tex_file = "";
|
||||
if(_preferencesDialog->gainCompensation() && compensator.getIndex(0) >= 0)
|
||||
{
|
||||
compensator.apply(0, image);
|
||||
}
|
||||
if(!cv::imwrite(mesh_material.tex_file, image))
|
||||
{
|
||||
UERROR("Cannot save texture of image %d", nodeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINFO("Saved temporary texture: \"%s\"", mesh_material.tex_file.c_str());
|
||||
}
|
||||
|
||||
textureMesh->tex_materials.push_back(mesh_material);
|
||||
|
||||
if(!_cloudViewer->addCloudTextureMesh(cloudName, textureMesh, pose))
|
||||
if(!_cloudViewer->addCloudTextureMesh(cloudName, textureMesh, image, pose))
|
||||
{
|
||||
UERROR("Adding texture mesh %d to viewer failed!", nodeId);
|
||||
}
|
||||
@@ -3528,7 +3499,6 @@ void MainWindow::applyPrefSettings(const rtabmap::ParametersMap & parameters, bo
|
||||
{
|
||||
_ui->statsToolBox->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
|
||||
_ui->graphicsView_graphView->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
|
||||
_cloudViewer->setWorkingDirectory(_preferencesDialog->getWorkingDirectory());
|
||||
}
|
||||
|
||||
if(_state != kIdle && parametersModified.size())
|
||||
|
||||
147
guilib/src/opencv/vtkImageMatSource.cpp
Normal file
147
guilib/src/opencv/vtkImageMatSource.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*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 "vtkImageMatSource.h"
|
||||
#include <vtkImageData.h>
|
||||
#include <vtkInformation.h>
|
||||
#include <vtkInformationVector.h>
|
||||
#include <vtkStreamingDemandDrivenPipeline.h>
|
||||
#include <vtkObjectFactory.h>
|
||||
|
||||
namespace rtabmap {
|
||||
vtkStandardNewMacro(vtkImageMatSource);
|
||||
}
|
||||
|
||||
rtabmap::vtkImageMatSource::vtkImageMatSource()
|
||||
{
|
||||
this->SetNumberOfInputPorts(0);
|
||||
this->ImageData = vtkSmartPointer<vtkImageData>::New();
|
||||
}
|
||||
|
||||
int rtabmap::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 rtabmap::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 rtabmap::vtkImageMatSource::SetImage(cv::InputArray _image)
|
||||
{
|
||||
CV_Assert(_image.depth() == CV_8U && (_image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4));
|
||||
|
||||
cv::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 rtabmap::vtkImageMatSource::copyGrayImage(const cv::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>(source.rows-(y+1)); // vertical flip for texturing
|
||||
for (int x = 0; x < source.cols; ++x)
|
||||
drow[x] = *srow++;
|
||||
}
|
||||
}
|
||||
|
||||
void rtabmap::vtkImageMatSource::copyRGBImage(const cv::Mat &source, vtkSmartPointer<vtkImageData> output)
|
||||
{
|
||||
cv::Vec3b* dptr = reinterpret_cast<cv::Vec3b*>(output->GetScalarPointer());
|
||||
size_t elem_step = output->GetIncrements()[1]/sizeof(cv::Vec3b);
|
||||
|
||||
for (int y = 0; y < source.rows; ++y)
|
||||
{
|
||||
cv::Vec3b* drow = dptr + elem_step * y;
|
||||
const unsigned char *srow = source.ptr<unsigned char>(source.rows - (y + 1)); // vertical flip for texturing
|
||||
for (int x = 0; x < source.cols; ++x, srow += source.channels())
|
||||
drow[x] = cv::Vec3b(srow[2], srow[1], srow[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void rtabmap::vtkImageMatSource::copyRGBAImage(const cv::Mat &source, vtkSmartPointer<vtkImageData> output)
|
||||
{
|
||||
cv::Vec4b* dptr = reinterpret_cast<cv::Vec4b*>(output->GetScalarPointer());
|
||||
size_t elem_step = output->GetIncrements()[1]/sizeof(cv::Vec4b);
|
||||
|
||||
for (int y = 0; y < source.rows; ++y)
|
||||
{
|
||||
cv::Vec4b* drow = dptr + elem_step * y;
|
||||
const unsigned char *srow = source.ptr<unsigned char>(source.rows - (y + 1)); // vertical flip for texturing
|
||||
for (int x = 0; x < source.cols; ++x, srow += source.channels())
|
||||
drow[x] = cv::Vec4b(srow[2], srow[1], srow[0], srow[3]);
|
||||
}
|
||||
}
|
||||
81
guilib/src/opencv/vtkImageMatSource.h
Normal file
81
guilib/src/opencv/vtkImageMatSource.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*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 RTABMAP__vtkImageMatSource_h
|
||||
#define RTABMAP__vtkImageMatSource_h
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <vtkImageAlgorithm.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
|
||||
namespace rtabmap
|
||||
{
|
||||
class vtkImageMatSource : public vtkImageAlgorithm
|
||||
{
|
||||
public:
|
||||
static vtkImageMatSource *New();
|
||||
vtkTypeMacro(vtkImageMatSource, vtkImageAlgorithm);
|
||||
|
||||
void SetImage(cv::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 cv::Mat &source, vtkSmartPointer<vtkImageData> output);
|
||||
static void copyRGBImage(const cv::Mat &source, vtkSmartPointer<vtkImageData> output);
|
||||
static void copyRGBAImage(const cv::Mat &source, vtkSmartPointer<vtkImageData> output);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user