mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Refactored texture projection (avoid saving image on disk at this step)
This commit is contained in:
@@ -73,18 +73,18 @@ public:
|
|||||||
|
|
||||||
void apply(
|
void apply(
|
||||||
int id,
|
int id,
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud);
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud) const;
|
||||||
void apply(
|
void apply(
|
||||||
int id,
|
int id,
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
||||||
const pcl::IndicesPtr & indices);
|
const pcl::IndicesPtr & indices) const;
|
||||||
void apply(
|
void apply(
|
||||||
int id,
|
int id,
|
||||||
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
|
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
|
||||||
const pcl::IndicesPtr & indices);
|
const pcl::IndicesPtr & indices) const;
|
||||||
void apply(
|
void apply(
|
||||||
int id,
|
int id,
|
||||||
cv::Mat & image);
|
cv::Mat & image) const;
|
||||||
|
|
||||||
double getGain(int id) const;
|
double getGain(int id) const;
|
||||||
int getIndex(int id) const;
|
int getIndex(int id) const;
|
||||||
|
|||||||
@@ -136,8 +136,6 @@ pcl::TextureMesh::Ptr RTABMAP_EXP createTextureMesh(
|
|||||||
const pcl::PolygonMesh::Ptr & mesh,
|
const pcl::PolygonMesh::Ptr & mesh,
|
||||||
const std::map<int, Transform> & poses,
|
const std::map<int, Transform> & poses,
|
||||||
const std::map<int, CameraModel> & cameraModels,
|
const std::map<int, CameraModel> & cameraModels,
|
||||||
const std::map<int, cv::Mat> & images,
|
|
||||||
const std::string & tmpDirectory = ".",
|
|
||||||
int kNormalSearch = 20); // if mesh doesn't have normals, compute them with k neighbors
|
int kNormalSearch = 20); // if mesh doesn't have normals, compute them with k neighbors
|
||||||
|
|
||||||
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
|
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ void applyImpl(
|
|||||||
|
|
||||||
void GainCompensator::apply(
|
void GainCompensator::apply(
|
||||||
int id,
|
int id,
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud)
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud) const
|
||||||
{
|
{
|
||||||
pcl::IndicesPtr indices(new std::vector<int>);
|
pcl::IndicesPtr indices(new std::vector<int>);
|
||||||
apply(id, cloud, indices);
|
apply(id, cloud, indices);
|
||||||
@@ -383,7 +383,7 @@ void GainCompensator::apply(
|
|||||||
void GainCompensator::apply(
|
void GainCompensator::apply(
|
||||||
int id,
|
int id,
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
||||||
const pcl::IndicesPtr & indices)
|
const pcl::IndicesPtr & indices) const
|
||||||
{
|
{
|
||||||
UASSERT_MSG(uContains(idToIndex_, id), uFormat("id=%d idToIndex_.size()=%d", id, (int)idToIndex_.size()).c_str());
|
UASSERT_MSG(uContains(idToIndex_, id), uFormat("id=%d idToIndex_.size()=%d", id, (int)idToIndex_.size()).c_str());
|
||||||
applyImpl<pcl::PointXYZRGB>(idToIndex_.at(id), cloud, indices, gains_);
|
applyImpl<pcl::PointXYZRGB>(idToIndex_.at(id), cloud, indices, gains_);
|
||||||
@@ -391,7 +391,7 @@ void GainCompensator::apply(
|
|||||||
void GainCompensator::apply(
|
void GainCompensator::apply(
|
||||||
int id,
|
int id,
|
||||||
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
|
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
|
||||||
const pcl::IndicesPtr & indices)
|
const pcl::IndicesPtr & indices) const
|
||||||
{
|
{
|
||||||
UASSERT_MSG(uContains(idToIndex_, id), uFormat("id=%d idToIndex_.size()=%d", id, (int)idToIndex_.size()).c_str());
|
UASSERT_MSG(uContains(idToIndex_, id), uFormat("id=%d idToIndex_.size()=%d", id, (int)idToIndex_.size()).c_str());
|
||||||
applyImpl<pcl::PointXYZRGBNormal>(idToIndex_.at(id), cloud, indices, gains_);
|
applyImpl<pcl::PointXYZRGBNormal>(idToIndex_.at(id), cloud, indices, gains_);
|
||||||
@@ -399,7 +399,7 @@ void GainCompensator::apply(
|
|||||||
|
|
||||||
void GainCompensator::apply(
|
void GainCompensator::apply(
|
||||||
int id,
|
int id,
|
||||||
cv::Mat & image)
|
cv::Mat & image) const
|
||||||
{
|
{
|
||||||
UASSERT_MSG(uContains(idToIndex_, id), uFormat("id=%d idToIndex_.size()=%d", id, (int)idToIndex_.size()).c_str());
|
UASSERT_MSG(uContains(idToIndex_, id), uFormat("id=%d idToIndex_.size()=%d", id, (int)idToIndex_.size()).c_str());
|
||||||
cv::multiply(image, gains_(idToIndex_.at(id), 0), image);
|
cv::multiply(image, gains_(idToIndex_.at(id), 0), image);
|
||||||
|
|||||||
@@ -569,21 +569,16 @@ pcl::PolygonMesh::Ptr createMesh(
|
|||||||
|
|
||||||
pcl::texture_mapping::CameraVector createTextureCameras(
|
pcl::texture_mapping::CameraVector createTextureCameras(
|
||||||
const std::map<int, Transform> & poses,
|
const std::map<int, Transform> & poses,
|
||||||
const std::map<int, CameraModel> & cameraModels,
|
const std::map<int, CameraModel> & cameraModels)
|
||||||
const std::map<int, cv::Mat> & images,
|
|
||||||
const std::string & tmpDirectory)
|
|
||||||
{
|
{
|
||||||
UASSERT(poses.size() == cameraModels.size() && poses.size() == images.size());
|
UASSERT(poses.size() == cameraModels.size());
|
||||||
UASSERT(UDirectory::exists(tmpDirectory));
|
|
||||||
pcl::texture_mapping::CameraVector cameras(poses.size());
|
pcl::texture_mapping::CameraVector cameras(poses.size());
|
||||||
std::map<int, Transform>::const_iterator poseIter=poses.begin();
|
std::map<int, Transform>::const_iterator poseIter=poses.begin();
|
||||||
std::map<int, CameraModel>::const_iterator modelIter=cameraModels.begin();
|
std::map<int, CameraModel>::const_iterator modelIter=cameraModels.begin();
|
||||||
std::map<int, cv::Mat>::const_iterator imageIter=images.begin();
|
|
||||||
int oi=0;
|
int oi=0;
|
||||||
for(; poseIter!=poses.end(); ++poseIter, ++modelIter, ++imageIter)
|
for(; poseIter!=poses.end(); ++poseIter, ++modelIter)
|
||||||
{
|
{
|
||||||
UASSERT(poseIter->first == modelIter->first);
|
UASSERT(poseIter->first == modelIter->first);
|
||||||
UASSERT(poseIter->first == imageIter->first);
|
|
||||||
pcl::TextureMapping<pcl::PointXYZ>::Camera cam;
|
pcl::TextureMapping<pcl::PointXYZ>::Camera cam;
|
||||||
|
|
||||||
// transform into optical referential
|
// transform into optical referential
|
||||||
@@ -595,22 +590,17 @@ pcl::texture_mapping::CameraVector createTextureCameras(
|
|||||||
|
|
||||||
cam.pose = t.toEigen3f();
|
cam.pose = t.toEigen3f();
|
||||||
|
|
||||||
UASSERT(modelIter->second.fx()>0 && imageIter->second.rows>0 && imageIter->second.cols>0);
|
if(modelIter->second.imageHeight() <=0 || modelIter->second.imageWidth() <=0)
|
||||||
|
{
|
||||||
|
UERROR("Should have camera models with width/height set to create texture cameras!");
|
||||||
|
return pcl::texture_mapping::CameraVector();
|
||||||
|
}
|
||||||
|
|
||||||
|
UASSERT(modelIter->second.fx()>0 && modelIter->second.imageHeight()>0 && modelIter->second.imageWidth()>0);
|
||||||
cam.focal_length=modelIter->second.fx();
|
cam.focal_length=modelIter->second.fx();
|
||||||
cam.height=imageIter->second.rows;
|
cam.height=modelIter->second.imageHeight();
|
||||||
cam.width=imageIter->second.cols;
|
cam.width=modelIter->second.imageWidth();
|
||||||
|
cam.texture_file = uFormat("%d.png", poseIter->first);
|
||||||
|
|
||||||
std::string fileName = uFormat("%s/%s%d.png", tmpDirectory.c_str(), "texture_", poseIter->first);
|
|
||||||
if(!cv::imwrite(fileName, imageIter->second))
|
|
||||||
{
|
|
||||||
UERROR("Cannot save texture of image %d", poseIter->first);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UINFO("Saved temporary texture: \"%s\"", fileName.c_str());
|
|
||||||
}
|
|
||||||
cam.texture_file = fileName;
|
|
||||||
cameras[oi++] = cam;
|
cameras[oi++] = cam;
|
||||||
}
|
}
|
||||||
return cameras;
|
return cameras;
|
||||||
@@ -620,8 +610,6 @@ pcl::TextureMesh::Ptr createTextureMesh(
|
|||||||
const pcl::PolygonMesh::Ptr & mesh,
|
const pcl::PolygonMesh::Ptr & mesh,
|
||||||
const std::map<int, Transform> & poses,
|
const std::map<int, Transform> & poses,
|
||||||
const std::map<int, CameraModel> & cameraModels,
|
const std::map<int, CameraModel> & cameraModels,
|
||||||
const std::map<int, cv::Mat> & images,
|
|
||||||
const std::string & tmpDirectory,
|
|
||||||
int kNormalSearch)
|
int kNormalSearch)
|
||||||
{
|
{
|
||||||
pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh);
|
pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh);
|
||||||
@@ -636,9 +624,7 @@ pcl::TextureMesh::Ptr createTextureMesh(
|
|||||||
// create cameras
|
// create cameras
|
||||||
pcl::texture_mapping::CameraVector cameras = createTextureCameras(
|
pcl::texture_mapping::CameraVector cameras = createTextureCameras(
|
||||||
poses,
|
poses,
|
||||||
cameraModels,
|
cameraModels);
|
||||||
images,
|
|
||||||
tmpDirectory);
|
|
||||||
|
|
||||||
// Create materials for each texture (and one extra for occluded faces)
|
// Create materials for each texture (and one extra for occluded faces)
|
||||||
textureMesh->tex_materials.resize (cameras.size () + 1);
|
textureMesh->tex_materials.resize (cameras.size () + 1);
|
||||||
@@ -671,17 +657,7 @@ pcl::TextureMesh::Ptr createTextureMesh(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mesh_material.tex_file = tmpDirectory+UDirectory::separator()+"occluded.png";
|
mesh_material.tex_file = "occluded.png";
|
||||||
cv::Mat emptyImage;
|
|
||||||
if(i>0)
|
|
||||||
{
|
|
||||||
emptyImage = cv::Mat::ones(cameras[i-1].height,cameras[i-1].width, CV_8UC1)*255;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
emptyImage = cv::Mat::ones(480, 640, CV_8UC1)*255;
|
|
||||||
}
|
|
||||||
cv::imwrite(mesh_material.tex_file, emptyImage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textureMesh->tex_materials[i] = mesh_material;
|
textureMesh->tex_materials[i] = mesh_material;
|
||||||
|
|||||||
@@ -1056,6 +1056,7 @@ bool CloudViewer::addTextureMesh (
|
|||||||
coordinates->SetName (this_coordinates_name.c_str ());
|
coordinates->SetName (this_coordinates_name.c_str ());
|
||||||
|
|
||||||
for (std::size_t t = 0 ; t < mesh.tex_coordinates.size (); ++t)
|
for (std::size_t t = 0 ; t < mesh.tex_coordinates.size (); ++t)
|
||||||
|
{
|
||||||
if (t == tex_id)
|
if (t == tex_id)
|
||||||
for (std::size_t tc = 0; tc < mesh.tex_coordinates[t].size (); ++tc)
|
for (std::size_t tc = 0; tc < mesh.tex_coordinates[t].size (); ++tc)
|
||||||
coordinates->InsertNextTuple2 ((double)mesh.tex_coordinates[t][tc][0],
|
coordinates->InsertNextTuple2 ((double)mesh.tex_coordinates[t][tc][0],
|
||||||
@@ -1063,7 +1064,7 @@ bool CloudViewer::addTextureMesh (
|
|||||||
else
|
else
|
||||||
for (std::size_t tc = 0; tc < mesh.tex_coordinates[t].size (); ++tc)
|
for (std::size_t tc = 0; tc < mesh.tex_coordinates[t].size (); ++tc)
|
||||||
coordinates->InsertNextTuple2 (-1.0, -1.0);
|
coordinates->InsertNextTuple2 (-1.0, -1.0);
|
||||||
|
}
|
||||||
mapper->MapDataArrayToMultiTextureAttribute(tu,
|
mapper->MapDataArrayToMultiTextureAttribute(tu,
|
||||||
this_coordinates_name.c_str (),
|
this_coordinates_name.c_str (),
|
||||||
vtkDataObject::FIELD_ASSOCIATION_POINTS);
|
vtkDataObject::FIELD_ASSOCIATION_POINTS);
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ namespace rtabmap {
|
|||||||
|
|
||||||
ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
|
ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
_canceled(false)
|
_canceled(false),
|
||||||
|
_compensator(0)
|
||||||
{
|
{
|
||||||
_ui = new Ui_ExportCloudsDialog();
|
_ui = new Ui_ExportCloudsDialog();
|
||||||
_ui->setupUi(this);
|
_ui->setupUi(this);
|
||||||
@@ -161,6 +162,10 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
|
|||||||
ExportCloudsDialog::~ExportCloudsDialog()
|
ExportCloudsDialog::~ExportCloudsDialog()
|
||||||
{
|
{
|
||||||
delete _ui;
|
delete _ui;
|
||||||
|
if(_compensator)
|
||||||
|
{
|
||||||
|
delete _compensator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportCloudsDialog::updateMLSGrpVisibility()
|
void ExportCloudsDialog::updateMLSGrpVisibility()
|
||||||
@@ -174,13 +179,13 @@ void ExportCloudsDialog::updateMLSGrpVisibility()
|
|||||||
void ExportCloudsDialog::updateTexturingAvailability()
|
void ExportCloudsDialog::updateTexturingAvailability()
|
||||||
{
|
{
|
||||||
updateTexturingAvailability(_ui->checkBox_binary->isEnabled());
|
updateTexturingAvailability(_ui->checkBox_binary->isEnabled());
|
||||||
|
_ui->comboBox_meshingApproach->setCurrentIndex(_ui->checkBox_assemble->isChecked()?1:0);
|
||||||
|
_ui->comboBox_meshingApproach->setItemData(1, _ui->checkBox_assemble->isChecked()?1 | 32:0,Qt::UserRole - 1);
|
||||||
}
|
}
|
||||||
void ExportCloudsDialog::updateTexturingAvailability(bool isExporting)
|
void ExportCloudsDialog::updateTexturingAvailability(bool isExporting)
|
||||||
{
|
{
|
||||||
_ui->checkBox_textureMapping->setEnabled(!_ui->checkBox_assemble->isChecked() || isExporting);
|
_ui->checkBox_textureMapping->setEnabled(!_ui->checkBox_assemble->isChecked() || isExporting);
|
||||||
_ui->label_textureMapping->setEnabled(_ui->checkBox_textureMapping->isEnabled());
|
_ui->label_textureMapping->setEnabled(_ui->checkBox_textureMapping->isEnabled());
|
||||||
_ui->comboBox_meshingApproach->setCurrentIndex(_ui->checkBox_assemble->isChecked()?1:0);
|
|
||||||
_ui->comboBox_meshingApproach->setItemData(1, _ui->checkBox_assemble->isChecked()?1 | 32:0,Qt::UserRole - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportCloudsDialog::cancel()
|
void ExportCloudsDialog::cancel()
|
||||||
@@ -538,7 +543,7 @@ void ExportCloudsDialog::exportClouds(
|
|||||||
{
|
{
|
||||||
if(textureMeshes.size())
|
if(textureMeshes.size())
|
||||||
{
|
{
|
||||||
saveTextureMeshes(workingDirectory, poses, textureMeshes);
|
saveTextureMeshes(workingDirectory, poses, textureMeshes, cachedSignatures);
|
||||||
}
|
}
|
||||||
else if(meshes.size())
|
else if(meshes.size())
|
||||||
{
|
{
|
||||||
@@ -629,10 +634,61 @@ void ExportCloudsDialog::viewClouds(
|
|||||||
|
|
||||||
if(textureMeshes.size())
|
if(textureMeshes.size())
|
||||||
{
|
{
|
||||||
|
QString prefix = "tmp_textures";
|
||||||
|
removeDirRecursively(workingDirectory+QDir::separator()+prefix);
|
||||||
|
QDir(workingDirectory).mkdir(prefix);
|
||||||
|
cv::Size imageSize;
|
||||||
|
|
||||||
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();
|
_progressDialog->incrementStep();
|
||||||
|
|
||||||
|
// save tmp textures
|
||||||
|
for(unsigned int i=0;i<iter->second->tex_materials.size(); ++i)
|
||||||
|
{
|
||||||
|
if(!iter->second->tex_materials[i].tex_file.empty())
|
||||||
|
{
|
||||||
|
// absolute path
|
||||||
|
QString fullPath = workingDirectory+QDir::separator()+prefix+QDir::separator()+QString(iter->second->tex_materials[i].tex_file.c_str());
|
||||||
|
if(!QFileInfo(fullPath).exists())
|
||||||
|
{
|
||||||
|
std::list<std::string> values = uSplit(iter->second->tex_materials[i].tex_file, '.');
|
||||||
|
if(values.size() == 2 && uIsInteger(*values.begin(), false))
|
||||||
|
{
|
||||||
|
int textureId = uStr2Int(*values.begin());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!cv::imwrite(fullPath.toStdString(), image))
|
||||||
|
{
|
||||||
|
_progressDialog->appendText(tr("Failed saving texture \"%1\" to \"%2\".")
|
||||||
|
.arg(iter->second->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
|
||||||
|
{
|
||||||
|
UWARN("Ignored texture %s (no image size set yet)", iter->second->tex_materials[i].tex_file.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iter->second->tex_materials[i].tex_file=fullPath.toStdString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isRGB = false;
|
bool isRGB = false;
|
||||||
for(unsigned int i=0; i<iter->second->cloud.fields.size(); ++i)
|
for(unsigned int i=0; i<iter->second->cloud.fields.size(); ++i)
|
||||||
{
|
{
|
||||||
@@ -750,6 +806,11 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
_canceled = false;
|
_canceled = false;
|
||||||
_workingDirectory = workingDirectory;
|
_workingDirectory = workingDirectory;
|
||||||
enableRegeneration(cachedSignatures.size());
|
enableRegeneration(cachedSignatures.size());
|
||||||
|
if(_compensator)
|
||||||
|
{
|
||||||
|
delete _compensator;
|
||||||
|
_compensator = 0;
|
||||||
|
}
|
||||||
if(this->exec() == QDialog::Accepted)
|
if(this->exec() == QDialog::Accepted)
|
||||||
{
|
{
|
||||||
if(poses.empty())
|
if(poses.empty())
|
||||||
@@ -815,9 +876,11 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GainCompensator compensator(_ui->doubleSpinBox_gainRadius->value(), _ui->doubleSpinBox_gainOverlap->value(), _ui->doubleSpinBox_gainAlpha->value(), _ui->doubleSpinBox_gainBeta->value());
|
|
||||||
if(_ui->groupBox_gain->isChecked() && clouds.size() > 1)
|
if(_ui->groupBox_gain->isChecked() && clouds.size() > 1)
|
||||||
{
|
{
|
||||||
|
UASSERT(_compensator == 0);
|
||||||
|
_compensator = new GainCompensator(_ui->doubleSpinBox_gainRadius->value(), _ui->doubleSpinBox_gainOverlap->value(), _ui->doubleSpinBox_gainAlpha->value(), _ui->doubleSpinBox_gainBeta->value());
|
||||||
|
|
||||||
if(!_ui->checkBox_gainLinkedLocationsOnly->isChecked())
|
if(!_ui->checkBox_gainLinkedLocationsOnly->isChecked())
|
||||||
{
|
{
|
||||||
_progressDialog->appendText(tr("Full gain compensation of %1 clouds...").arg(clouds.size()));
|
_progressDialog->appendText(tr("Full gain compensation of %1 clouds...").arg(clouds.size()));
|
||||||
@@ -844,11 +907,11 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compensator.feed(clouds, allLinks);
|
_compensator->feed(clouds, allLinks);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
compensator.feed(clouds, links);
|
_compensator->feed(clouds, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
_progressDialog->appendText(tr("Applying gain compensation..."));
|
_progressDialog->appendText(tr("Applying gain compensation..."));
|
||||||
@@ -856,8 +919,8 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
{
|
{
|
||||||
if(jter!=clouds.end())
|
if(jter!=clouds.end())
|
||||||
{
|
{
|
||||||
double gain = compensator.getGain(jter->first);;
|
double gain = _compensator->getGain(jter->first);;
|
||||||
compensator.apply(jter->first, jter->second.first, jter->second.second);
|
_compensator->apply(jter->first, jter->second.first, jter->second.second);
|
||||||
|
|
||||||
_progressDialog->appendText(tr("Cloud %1 has gain %2").arg(jter->first).arg(gain));
|
_progressDialog->appendText(tr("Cloud %1 has gain %2").arg(jter->first).arg(gain));
|
||||||
_progressDialog->incrementStep();
|
_progressDialog->incrementStep();
|
||||||
@@ -1448,9 +1511,6 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
UDEBUG("texture mapping=%d", _ui->checkBox_textureMapping->isEnabled() && _ui->checkBox_textureMapping->isChecked()?1:0);
|
UDEBUG("texture mapping=%d", _ui->checkBox_textureMapping->isEnabled() && _ui->checkBox_textureMapping->isChecked()?1:0);
|
||||||
if(_ui->checkBox_textureMapping->isEnabled() && _ui->checkBox_textureMapping->isChecked())
|
if(_ui->checkBox_textureMapping->isEnabled() && _ui->checkBox_textureMapping->isChecked())
|
||||||
{
|
{
|
||||||
QDir dir(workingDirectory);
|
|
||||||
removeDirRecursively(workingDirectory+QDir::separator()+"tmp_textures");
|
|
||||||
dir.mkdir("tmp_textures");
|
|
||||||
int i=0;
|
int i=0;
|
||||||
for(std::map<int, pcl::PolygonMesh::Ptr>::iterator iter=meshes.begin();
|
for(std::map<int, pcl::PolygonMesh::Ptr>::iterator iter=meshes.begin();
|
||||||
iter!= meshes.end();
|
iter!= meshes.end();
|
||||||
@@ -1468,7 +1528,6 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
}
|
}
|
||||||
std::map<int, Transform> cameraPoses;
|
std::map<int, Transform> cameraPoses;
|
||||||
std::map<int, CameraModel> cameraModels;
|
std::map<int, CameraModel> cameraModels;
|
||||||
std::map<int, cv::Mat> images;
|
|
||||||
for(std::map<int, Transform>::iterator jter=cameras.begin(); jter!=cameras.end(); ++jter)
|
for(std::map<int, Transform>::iterator jter=cameras.begin(); jter!=cameras.end(); ++jter)
|
||||||
{
|
{
|
||||||
if(cachedSignatures.contains(jter->first))
|
if(cachedSignatures.contains(jter->first))
|
||||||
@@ -1483,20 +1542,10 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
{
|
{
|
||||||
model = s.sensorData().cameraModels()[0];
|
model = s.sensorData().cameraModels()[0];
|
||||||
}
|
}
|
||||||
cv::Mat image = s.sensorData().imageRaw();
|
if(!jter->second.isNull() && model.isValidForProjection() && !s.sensorData().imageCompressed().empty())
|
||||||
if(image.empty() && !s.sensorData().imageCompressed().empty())
|
|
||||||
{
|
|
||||||
s.sensorData().uncompressDataConst(&image, 0, 0, 0);
|
|
||||||
}
|
|
||||||
if(!jter->second.isNull() && model.isValidForProjection() && !image.empty())
|
|
||||||
{
|
{
|
||||||
cameraPoses.insert(std::make_pair(jter->first, jter->second));
|
cameraPoses.insert(std::make_pair(jter->first, jter->second));
|
||||||
cameraModels.insert(std::make_pair(jter->first, model));
|
cameraModels.insert(std::make_pair(jter->first, model));
|
||||||
if(_ui->groupBox_gain->isChecked() && compensator.getIndex(jter->first) >= 0)
|
|
||||||
{
|
|
||||||
compensator.apply(jter->first, image);
|
|
||||||
}
|
|
||||||
images.insert(std::make_pair(jter->first, image));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1563,17 +1612,7 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
tex_name << "material_" << iter->first;
|
tex_name << "material_" << iter->first;
|
||||||
tex_name >> mesh_material.tex_name;
|
tex_name >> mesh_material.tex_name;
|
||||||
|
|
||||||
std::string tmpDirectory = dir.filePath("tmp_textures").toStdString();
|
mesh_material.tex_file = uFormat("%d.png", iter->first);
|
||||||
mesh_material.tex_file = uFormat("%s/%s%d.png", tmpDirectory.c_str(), "texture_", iter->first);
|
|
||||||
if(!cv::imwrite(mesh_material.tex_file, images.at(iter->first)))
|
|
||||||
{
|
|
||||||
UERROR("Cannot save texture of image %d", iter->first);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UINFO("Saved temporary texture: \"%s\"", mesh_material.tex_file.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
textureMesh->tex_materials.push_back(mesh_material);
|
textureMesh->tex_materials.push_back(mesh_material);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1588,8 +1627,6 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
iter->second,
|
iter->second,
|
||||||
cameraPoses,
|
cameraPoses,
|
||||||
cameraModels,
|
cameraModels,
|
||||||
images,
|
|
||||||
dir.filePath("tmp_textures").toStdString(),
|
|
||||||
_ui->spinBox_normalKSearch->value());
|
_ui->spinBox_normalKSearch->value());
|
||||||
|
|
||||||
// Remove occluded polygons (polygons with no texture)
|
// Remove occluded polygons (polygons with no texture)
|
||||||
@@ -1684,6 +1721,14 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(!_ui->checkBox_binary->isEnabled() && // not enabled -> we are not exporting to file
|
||||||
|
textureMesh->tex_coordinates.size() == 2)
|
||||||
|
{
|
||||||
|
// Remove occluded texture to avoid doing multi-texturing (buggy)
|
||||||
|
textureMesh->tex_coordinates.pop_back();
|
||||||
|
textureMesh->tex_polygons.pop_back();
|
||||||
|
textureMesh->tex_materials.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
if(!_ui->checkBox_binary->isEnabled() && // not enabled -> we are not exporting to file
|
if(!_ui->checkBox_binary->isEnabled() && // not enabled -> we are not exporting to file
|
||||||
textureMesh->tex_coordinates.size())
|
textureMesh->tex_coordinates.size())
|
||||||
@@ -1699,7 +1744,8 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
#else
|
#else
|
||||||
std::vector<Eigen::Vector2f> tmpCoordinates = textureMesh->tex_coordinates[t];
|
std::vector<Eigen::Vector2f> tmpCoordinates = textureMesh->tex_coordinates[t];
|
||||||
#endif
|
#endif
|
||||||
textureMesh->tex_coordinates[t].resize(nPoints);
|
textureMesh->tex_coordinates[t].clear();
|
||||||
|
textureMesh->tex_coordinates[t].resize(nPoints, Eigen::Vector2f(-1.0f, -1.0f));
|
||||||
|
|
||||||
int polygonSize = textureMesh->tex_polygons[t][0].vertices.size();
|
int polygonSize = textureMesh->tex_polygons[t][0].vertices.size();
|
||||||
UASSERT(textureMesh->tex_polygons[t].size() == tmpCoordinates.size()/polygonSize);
|
UASSERT(textureMesh->tex_polygons[t].size() == tmpCoordinates.size()/polygonSize);
|
||||||
@@ -2274,7 +2320,8 @@ void ExportCloudsDialog::saveMeshes(
|
|||||||
void ExportCloudsDialog::saveTextureMeshes(
|
void ExportCloudsDialog::saveTextureMeshes(
|
||||||
const QString & workingDirectory,
|
const QString & workingDirectory,
|
||||||
const std::map<int, Transform> & poses,
|
const std::map<int, Transform> & poses,
|
||||||
const std::map<int, pcl::TextureMesh::Ptr> & meshes)
|
std::map<int, pcl::TextureMesh::Ptr> & meshes,
|
||||||
|
const QMap<int, Signature> & cachedSignatures)
|
||||||
{
|
{
|
||||||
if(meshes.size() == 1)
|
if(meshes.size() == 1)
|
||||||
{
|
{
|
||||||
@@ -2294,32 +2341,61 @@ void ExportCloudsDialog::saveTextureMeshes(
|
|||||||
path += ".obj";
|
path += ".obj";
|
||||||
}
|
}
|
||||||
|
|
||||||
pcl::TextureMesh mesh;
|
pcl::TextureMesh::Ptr mesh = meshes.begin()->second;
|
||||||
mesh.tex_coordinates = meshes.begin()->second->tex_coordinates;
|
|
||||||
mesh.tex_materials = meshes.begin()->second->tex_materials;
|
|
||||||
removeDirRecursively(QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+QFileInfo(path).baseName());
|
removeDirRecursively(QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+QFileInfo(path).baseName());
|
||||||
QDir(QFileInfo(path).absoluteDir().absolutePath()).mkdir(QFileInfo(path).baseName());
|
QDir(QFileInfo(path).absoluteDir().absolutePath()).mkdir(QFileInfo(path).baseName());
|
||||||
for(unsigned int i=0;i<meshes.begin()->second->tex_materials.size(); ++i)
|
cv::Size imageSize;
|
||||||
|
for(unsigned int i=0; i<mesh->tex_materials.size(); ++i)
|
||||||
{
|
{
|
||||||
QFileInfo info(mesh.tex_materials[i].tex_file.c_str());
|
if(!mesh->tex_materials[i].tex_file.empty())
|
||||||
QString fullPath = QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+QFileInfo(path).baseName()+QDir::separator()+info.fileName();
|
|
||||||
// relative path
|
|
||||||
mesh.tex_materials[i].tex_file=(QFileInfo(path).baseName()+QDir::separator()+info.fileName()).toStdString();
|
|
||||||
if(!QFile::copy(meshes.begin()->second->tex_materials[i].tex_file.c_str(), fullPath))
|
|
||||||
{
|
{
|
||||||
_progressDialog->appendText(tr("Failed copying texture \"%1\" to \"%2\".")
|
// absolute path
|
||||||
.arg(meshes.begin()->second->tex_materials[i].tex_file.c_str()).arg(fullPath), Qt::darkRed);
|
QString fullPath = QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+QFileInfo(path).baseName()+QDir::separator()+QString(mesh->tex_materials[i].tex_file.c_str());
|
||||||
_progressDialog->setAutoClose(false);
|
|
||||||
|
if(!QFileInfo(fullPath).exists())
|
||||||
|
{
|
||||||
|
std::list<std::string> values = uSplit(mesh->tex_materials[i].tex_file, '.');
|
||||||
|
if(values.size() == 2 && uIsInteger(*values.begin(), false))
|
||||||
|
{
|
||||||
|
int textureId = uStr2Int(*values.begin());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
UWARN("Ignored texture %s (no image size set yet)", mesh->tex_materials[i].tex_file.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// relative path
|
||||||
|
mesh->tex_materials[i].tex_file=(QFileInfo(path).baseName()+QDir::separator()+QString(mesh->tex_materials[i].tex_file.c_str())).toStdString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mesh.tex_polygons = meshes.begin()->second->tex_polygons;
|
|
||||||
mesh.cloud = meshes.begin()->second->cloud;
|
|
||||||
|
|
||||||
success = pcl::io::saveOBJFile(path.toStdString(), mesh) == 0;
|
success = pcl::io::saveOBJFile(path.toStdString(), *mesh) == 0;
|
||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
_progressDialog->incrementStep();
|
_progressDialog->incrementStep();
|
||||||
_progressDialog->appendText(tr("Saving the mesh (with %1 textures)... done.").arg(mesh.tex_materials.size()));
|
_progressDialog->appendText(tr("Saving the mesh (with %1 textures)... done.").arg(mesh->tex_materials.size()));
|
||||||
|
|
||||||
QMessageBox::information(this, tr("Save successful!"), tr("Mesh saved to \"%1\"").arg(path));
|
QMessageBox::information(this, tr("Save successful!"), tr("Mesh saved to \"%1\"").arg(path));
|
||||||
}
|
}
|
||||||
@@ -2345,41 +2421,69 @@ void ExportCloudsDialog::saveTextureMeshes(
|
|||||||
|
|
||||||
if(ok)
|
if(ok)
|
||||||
{
|
{
|
||||||
for(std::map<int, pcl::TextureMesh::Ptr>::const_iterator iter=meshes.begin(); iter!=meshes.end(); ++iter)
|
for(std::map<int, pcl::TextureMesh::Ptr>::iterator iter=meshes.begin(); iter!=meshes.end(); ++iter)
|
||||||
{
|
{
|
||||||
QString currentPrefix=prefix+QString::number(iter->first);
|
QString currentPrefix=prefix+QString::number(iter->first);
|
||||||
if(iter->second->tex_materials.size())
|
if(iter->second->tex_materials.size())
|
||||||
{
|
{
|
||||||
pcl::TextureMesh mesh;
|
pcl::TextureMesh::Ptr mesh = iter->second;
|
||||||
mesh.tex_coordinates = iter->second->tex_coordinates;
|
removeDirRecursively(path+QDir::separator()+currentPrefix);
|
||||||
mesh.tex_materials = iter->second->tex_materials;
|
|
||||||
QDir(path).rmdir(currentPrefix);
|
|
||||||
QDir(path).mkdir(currentPrefix);
|
QDir(path).mkdir(currentPrefix);
|
||||||
for(unsigned int i=0;i<iter->second->tex_materials.size(); ++i)
|
cv::Size imageSize;
|
||||||
|
for(unsigned int i=0;i<mesh->tex_materials.size(); ++i)
|
||||||
{
|
{
|
||||||
QFileInfo info(mesh.tex_materials[i].tex_file.c_str());
|
if(!mesh->tex_materials[i].tex_file.empty())
|
||||||
QString fullPath = path+QDir::separator()+currentPrefix+QDir::separator()+info.fileName();
|
|
||||||
// relative path
|
|
||||||
mesh.tex_materials[i].tex_file=(currentPrefix+QDir::separator()+info.fileName()).toStdString();
|
|
||||||
if(!QFile::copy(iter->second->tex_materials[i].tex_file.c_str(), fullPath) &&
|
|
||||||
info.fileName().compare("occluded.png") != 0)
|
|
||||||
{
|
{
|
||||||
_progressDialog->appendText(tr("Failed copying texture \"%1\" to \"%2\".")
|
// absolute path
|
||||||
.arg(iter->second->tex_materials[i].tex_file.c_str()).arg(fullPath), Qt::darkRed);
|
QString fullPath = path+QDir::separator()+currentPrefix+QDir::separator()+QString(mesh->tex_materials[i].tex_file.c_str());
|
||||||
_progressDialog->setAutoClose(false);
|
if(!QFileInfo(fullPath).exists())
|
||||||
|
{
|
||||||
|
std::list<std::string> values = uSplit(mesh->tex_materials[i].tex_file, '.');
|
||||||
|
if(values.size() == 2 && uIsInteger(*values.begin(), false))
|
||||||
|
{
|
||||||
|
int textureId = uStr2Int(*values.begin());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
UWARN("Ignored texture %s (no image size set yet)", mesh->tex_materials[i].tex_file.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// relative path
|
||||||
|
mesh->tex_materials[i].tex_file=(currentPrefix+QDir::separator()+QString(mesh->tex_materials[i].tex_file.c_str())).toStdString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mesh.tex_polygons = iter->second->tex_polygons;
|
|
||||||
pcl::PointCloud<pcl::PointNormal>::Ptr tmp(new pcl::PointCloud<pcl::PointNormal>);
|
pcl::PointCloud<pcl::PointNormal>::Ptr tmp(new pcl::PointCloud<pcl::PointNormal>);
|
||||||
pcl::fromPCLPointCloud2(iter->second->cloud, *tmp);
|
pcl::fromPCLPointCloud2(mesh->cloud, *tmp);
|
||||||
tmp = util3d::transformPointCloud(tmp, poses.at(iter->first));
|
tmp = util3d::transformPointCloud(tmp, poses.at(iter->first));
|
||||||
pcl::toPCLPointCloud2(*tmp, mesh.cloud);
|
pcl::toPCLPointCloud2(*tmp, mesh->cloud);
|
||||||
|
|
||||||
QString pathFile = path+QDir::separator()+QString("%1.%3").arg(currentPrefix).arg(suffix);
|
QString pathFile = path+QDir::separator()+QString("%1.%3").arg(currentPrefix).arg(suffix);
|
||||||
bool success =false;
|
bool success =false;
|
||||||
if(suffix == "obj")
|
if(suffix == "obj")
|
||||||
{
|
{
|
||||||
success = pcl::io::saveOBJFile(pathFile.toStdString(), mesh) == 0;
|
success = pcl::io::saveOBJFile(pathFile.toStdString(), *mesh) == 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2388,12 +2492,12 @@ void ExportCloudsDialog::saveTextureMeshes(
|
|||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
_progressDialog->appendText(tr("Saved mesh %1 (%2 textures) to %3.")
|
_progressDialog->appendText(tr("Saved mesh %1 (%2 textures) to %3.")
|
||||||
.arg(iter->first).arg(iter->second->tex_materials.size()-1).arg(pathFile));
|
.arg(iter->first).arg(mesh->tex_materials.size()).arg(pathFile));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_progressDialog->appendText(tr("Failed saving mesh %1 (%2 textures) to %3.")
|
_progressDialog->appendText(tr("Failed saving mesh %1 (%2 textures) to %3.")
|
||||||
.arg(iter->first).arg(iter->second->tex_materials.size()-1).arg(pathFile), Qt::darkRed);
|
.arg(iter->first).arg(mesh->tex_materials.size()).arg(pathFile), Qt::darkRed);
|
||||||
_progressDialog->setAutoClose(false);
|
_progressDialog->setAutoClose(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class QAbstractButton;
|
|||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
class ProgressDialog;
|
class ProgressDialog;
|
||||||
|
class GainCompensator;
|
||||||
|
|
||||||
class ExportCloudsDialog : public QDialog
|
class ExportCloudsDialog : public QDialog
|
||||||
{
|
{
|
||||||
@@ -112,7 +113,7 @@ private:
|
|||||||
std::map<int, pcl::TextureMesh::Ptr> & textureMeshes);
|
std::map<int, pcl::TextureMesh::Ptr> & textureMeshes);
|
||||||
void saveClouds(const QString & workingDirectory, const std::map<int, Transform> & poses, const std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & clouds, bool binaryMode = true);
|
void saveClouds(const QString & workingDirectory, const std::map<int, Transform> & poses, const std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & clouds, bool binaryMode = true);
|
||||||
void saveMeshes(const QString & workingDirectory, const std::map<int, Transform> & poses, const std::map<int, pcl::PolygonMesh::Ptr> & meshes, bool binaryMode = true);
|
void saveMeshes(const QString & workingDirectory, const std::map<int, Transform> & poses, const std::map<int, pcl::PolygonMesh::Ptr> & meshes, bool binaryMode = true);
|
||||||
void saveTextureMeshes(const QString & workingDirectory, const std::map<int, Transform> & poses, const std::map<int, pcl::TextureMesh::Ptr> & meshes);
|
void saveTextureMeshes(const QString & workingDirectory, const std::map<int, Transform> & poses, std::map<int, pcl::TextureMesh::Ptr> & textureMeshes, const QMap<int, Signature> & cachedSignatures);
|
||||||
|
|
||||||
void setSaveButton();
|
void setSaveButton();
|
||||||
void setOkButton();
|
void setOkButton();
|
||||||
@@ -124,6 +125,7 @@ private:
|
|||||||
ProgressDialog * _progressDialog;
|
ProgressDialog * _progressDialog;
|
||||||
QString _workingDirectory;
|
QString _workingDirectory;
|
||||||
bool _canceled;
|
bool _canceled;
|
||||||
|
GainCompensator * _compensator;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user