Added min polygon cluster size option (DbViewer and GUI export)

This commit is contained in:
matlabbe
2016-09-03 18:59:43 -04:00
parent 0848b03127
commit 7f2c118f8d
10 changed files with 602 additions and 284 deletions

View File

@@ -273,7 +273,7 @@ private:
}; };
///////////////////////// /////////////////////////
// CameraOpenNIPCL // CameraRealSense
///////////////////////// /////////////////////////
class RTABMAP_EXP CameraRealSense : class RTABMAP_EXP CameraRealSense :
public Camera public Camera

View File

@@ -0,0 +1,50 @@
/*
* util3d_surface.hpp
*
* Created on: Sep 3, 2016
* Author: mathieu
*/
#ifndef CORELIB_INCLUDE_RTABMAP_CORE_IMPL_UTIL3D_SURFACE_HPP_
#define CORELIB_INCLUDE_RTABMAP_CORE_IMPL_UTIL3D_SURFACE_HPP_
namespace rtabmap {
namespace util3d {
template<typename pointT>
std::vector<pcl::Vertices> normalizePolygonsSide(
const pcl::PointCloud<pointT> & cloud,
const std::vector<pcl::Vertices> & polygons,
const pcl::PointXYZ & viewPoint)
{
std::vector<pcl::Vertices> output(polygons.size());
for(unsigned int i=0; i<polygons.size(); ++i)
{
pcl::Vertices polygon = polygons[i];
Eigen::Vector3f v1 = cloud.at(polygon.vertices[1]).getVector3fMap() - cloud.at(polygon.vertices[0]).getVector3fMap();
Eigen::Vector3f v2 = cloud.at(polygon.vertices[2]).getVector3fMap() - cloud.at(polygon.vertices[0]).getVector3fMap();
Eigen::Vector3f n = (v1.cross(v2)).normalized();
Eigen::Vector3f p = Eigen::Vector3f(viewPoint.x, viewPoint.y, viewPoint.z) - cloud.at(polygon.vertices[1]).getVector3fMap();
float result = n.dot(p);
if(result < 0)
{
//reverse vertices order
int tmp = polygon.vertices[0];
polygon.vertices[0] = polygon.vertices[2];
polygon.vertices[2] = tmp;
}
output[i] = polygon;
}
return output;
}
}
}
#endif /* CORELIB_INCLUDE_RTABMAP_CORE_IMPL_UTIL3D_SURFACE_HPP_ */

View File

@@ -411,7 +411,6 @@ pcl::IndicesPtr RTABMAP_EXP normalFiltering(
* @param viewpoint from which viewpoint the normals should be estimated (see pcl::NormalEstimation). * @param viewpoint from which viewpoint the normals should be estimated (see pcl::NormalEstimation).
* @return the indices of the points which respect the normal constraint. * @return the indices of the points which respect the normal constraint.
*/ */
pcl::IndicesPtr RTABMAP_EXP normalFiltering( pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
@@ -434,6 +433,13 @@ pcl::IndicesPtr RTABMAP_EXP normalFiltering(
int normalKSearch, int normalKSearch,
const Eigen::Vector4f & viewpoint); const Eigen::Vector4f & viewpoint);
void RTABMAP_EXP colorMeanFiltering(
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloudRef,
const pcl::IndicesPtr & indicesRef,
float radiusSearch);
/** /**
* For convenience. * For convenience.
*/ */

View File

@@ -60,6 +60,10 @@ void RTABMAP_EXP createPolygonIndexes(
std::vector<std::set<int> > & neighborPolygons, std::vector<std::set<int> > & neighborPolygons,
std::vector<std::set<int> > & vertexPolygons); std::vector<std::set<int> > & vertexPolygons);
std::list<std::list<int> > RTABMAP_EXP clusterPolygons(
const std::vector<std::set<int> > & neighborPolygons,
int minClusterSize = 0);
std::vector<pcl::Vertices> RTABMAP_EXP organizedFastMesh( std::vector<pcl::Vertices> RTABMAP_EXP organizedFastMesh(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
double angleTolerance = M_PI/16, double angleTolerance = M_PI/16,
@@ -194,33 +198,11 @@ template<typename pointT>
std::vector<pcl::Vertices> normalizePolygonsSide( std::vector<pcl::Vertices> normalizePolygonsSide(
const pcl::PointCloud<pointT> & cloud, const pcl::PointCloud<pointT> & cloud,
const std::vector<pcl::Vertices> & polygons, const std::vector<pcl::Vertices> & polygons,
const pcl::PointXYZ & viewPoint = pcl::PointXYZ(0,0,0)) const pcl::PointXYZ & viewPoint = pcl::PointXYZ(0,0,0));
{
std::vector<pcl::Vertices> output(polygons.size());
for(unsigned int i=0; i<polygons.size(); ++i)
{
pcl::Vertices polygon = polygons[i];
Eigen::Vector3f v1 = cloud.at(polygon.vertices[1]).getVector3fMap() - cloud.at(polygon.vertices[0]).getVector3fMap();
Eigen::Vector3f v2 = cloud.at(polygon.vertices[2]).getVector3fMap() - cloud.at(polygon.vertices[0]).getVector3fMap();
Eigen::Vector3f n = (v1.cross(v2)).normalized();
Eigen::Vector3f p = Eigen::Vector3f(viewPoint.x, viewPoint.y, viewPoint.z) - cloud.at(polygon.vertices[1]).getVector3fMap();
float result = n.dot(p);
if(result < 0)
{
//reverse vertices order
int tmp = polygon.vertices[0];
polygon.vertices[0] = polygon.vertices[2];
polygon.vertices[2] = tmp;
}
output[i] = polygon;
}
return output;
}
} // namespace util3d } // namespace util3d
} // namespace rtabmap } // namespace rtabmap
#include "rtabmap/core/impl/util3d_surface.hpp"
#endif /* UTIL3D_SURFACE_H_ */ #endif /* UTIL3D_SURFACE_H_ */

View File

@@ -1555,6 +1555,45 @@ pcl::IndicesPtr normalFiltering(
return output; return output;
} }
void colorMeanFiltering(
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloudRef,
const pcl::IndicesPtr & indicesRef,
float radiusSearch)
{
UASSERT(radiusSearch>0.0f);
pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB>(false));
if(indicesRef->size())
{
tree->setInputCloud(cloudRef, indicesRef);
}
else
{
tree->setInputCloud(cloudRef);
}
for(unsigned int i=0; i<indices->size(); ++i)
{
std::vector<int> kIndices;
std::vector<float> kDistances;
pcl::PointXYZRGB & pt = cloud->at(indices->at(i));
if(tree->radiusSearch(pt, radiusSearch, kIndices, kDistances))
{
UASSERT(kIndices.size());
int r=0,g=0,b=0;
for(unsigned int j=0; j<kIndices.size(); ++j)
{
r+=cloudRef->at(kIndices.at(j)).r;
g+=cloudRef->at(kIndices.at(j)).g;
b+=cloudRef->at(kIndices.at(j)).b;
}
pt.r = (unsigned char)(r/kIndices.size());
pt.g = (unsigned char)(g/kIndices.size());
pt.b = (unsigned char)(b/kIndices.size());
}
}
}
std::vector<pcl::IndicesPtr> extractClusters( std::vector<pcl::IndicesPtr> extractClusters(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
float clusterTolerance, float clusterTolerance,

View File

@@ -100,6 +100,43 @@ void createPolygonIndexes(
} }
} }
std::list<std::list<int> > clusterPolygons(
const std::vector<std::set<int> > & neighborPolygons,
int minClusterSize)
{
std::set<int> polygonsChecked;
std::list<std::list<int> > clusters;
for(unsigned int i=0; i<neighborPolygons.size(); ++i)
{
if(polygonsChecked.find(i) == polygonsChecked.end())
{
std::list<int> currentCluster;
currentCluster.push_back(i);
polygonsChecked.insert(i);
for(std::list<int>::iterator iter=currentCluster.begin(); iter!=currentCluster.end(); ++iter)
{
// get neighbor polygons
std::set<int> neighbors = neighborPolygons[*iter];
for(std::set<int>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
{
if(polygonsChecked.insert(*jter).second)
{
currentCluster.push_back(*jter);
}
}
}
if(currentCluster.size() > minClusterSize)
{
clusters.push_back(currentCluster);
}
}
}
return clusters;
}
std::vector<pcl::Vertices> organizedFastMesh( std::vector<pcl::Vertices> organizedFastMesh(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
double angleTolerance, double angleTolerance,

View File

@@ -213,11 +213,16 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
connect(ui_->horizontalSlider_B, SIGNAL(sliderMoved(int)), this, SLOT(sliderBMoved(int))); connect(ui_->horizontalSlider_B, SIGNAL(sliderMoved(int)), this, SLOT(sliderBMoved(int)));
connect(ui_->spinBox_mesh_angleTolerance, SIGNAL(valueChanged(int)), this, SLOT(update3dView())); connect(ui_->spinBox_mesh_angleTolerance, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->spinBox_mesh_minClusterSize, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->spinBox_mesh_fillDepthHoles, SIGNAL(valueChanged(int)), this, SLOT(update3dView())); connect(ui_->spinBox_mesh_fillDepthHoles, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->spinBox_mesh_depthError, SIGNAL(valueChanged(int)), this, SLOT(update3dView())); connect(ui_->spinBox_mesh_depthError, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->checkBox_mesh_quad, SIGNAL(toggled(bool)), this, SLOT(update3dView())); connect(ui_->checkBox_mesh_quad, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
connect(ui_->spinBox_mesh_triangleSize, SIGNAL(valueChanged(int)), this, SLOT(update3dView())); connect(ui_->spinBox_mesh_triangleSize, SIGNAL(valueChanged(int)), this, SLOT(update3dView()));
connect(ui_->checkBox_showCloud, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
connect(ui_->checkBox_showMesh, SIGNAL(toggled(bool)), this, SLOT(update3dView())); connect(ui_->checkBox_showMesh, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
connect(ui_->checkBox_showScan, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
connect(ui_->checkBox_showMap, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
connect(ui_->checkBox_showGrid, SIGNAL(toggled(bool)), this, SLOT(update3dView()));
ui_->horizontalSlider_neighbors->setTracking(false); ui_->horizontalSlider_neighbors->setTracking(false);
ui_->horizontalSlider_loops->setTracking(false); ui_->horizontalSlider_loops->setTracking(false);
@@ -399,6 +404,7 @@ void DatabaseViewer::readSettings()
settings.beginGroup("mesh"); settings.beginGroup("mesh");
ui_->checkBox_mesh_quad->setChecked(settings.value("quad", ui_->checkBox_mesh_quad->isChecked()).toBool()); ui_->checkBox_mesh_quad->setChecked(settings.value("quad", ui_->checkBox_mesh_quad->isChecked()).toBool());
ui_->spinBox_mesh_angleTolerance->setValue(settings.value("angleTolerance", ui_->spinBox_mesh_angleTolerance->value()).toInt()); ui_->spinBox_mesh_angleTolerance->setValue(settings.value("angleTolerance", ui_->spinBox_mesh_angleTolerance->value()).toInt());
ui_->spinBox_mesh_minClusterSize->setValue(settings.value("minClusterSize", ui_->spinBox_mesh_minClusterSize->value()).toInt());
ui_->spinBox_mesh_fillDepthHoles->setValue(settings.value("fillDepthHolesSize", ui_->spinBox_mesh_fillDepthHoles->value()).toInt()); ui_->spinBox_mesh_fillDepthHoles->setValue(settings.value("fillDepthHolesSize", ui_->spinBox_mesh_fillDepthHoles->value()).toInt());
ui_->spinBox_mesh_depthError->setValue(settings.value("fillDepthHolesError", ui_->spinBox_mesh_depthError->value()).toInt()); ui_->spinBox_mesh_depthError->setValue(settings.value("fillDepthHolesError", ui_->spinBox_mesh_depthError->value()).toInt());
ui_->spinBox_mesh_triangleSize->setValue(settings.value("triangleSize", ui_->spinBox_mesh_triangleSize->value()).toInt()); ui_->spinBox_mesh_triangleSize->setValue(settings.value("triangleSize", ui_->spinBox_mesh_triangleSize->value()).toInt());
@@ -480,6 +486,7 @@ void DatabaseViewer::writeSettings()
settings.beginGroup("mesh"); settings.beginGroup("mesh");
settings.setValue("quad", ui_->checkBox_mesh_quad->isChecked()); settings.setValue("quad", ui_->checkBox_mesh_quad->isChecked());
settings.setValue("angleTolerance", ui_->spinBox_mesh_angleTolerance->value()); settings.setValue("angleTolerance", ui_->spinBox_mesh_angleTolerance->value());
settings.setValue("minClusterSize", ui_->spinBox_mesh_minClusterSize->value());
settings.setValue("fillDepthHolesSize", ui_->spinBox_mesh_fillDepthHoles->value()); settings.setValue("fillDepthHolesSize", ui_->spinBox_mesh_fillDepthHoles->value());
settings.setValue("fillDepthHolesError", ui_->spinBox_mesh_depthError->value()); settings.setValue("fillDepthHolesError", ui_->spinBox_mesh_depthError->value());
settings.setValue("triangleSize", ui_->spinBox_mesh_triangleSize->value()); settings.setValue("triangleSize", ui_->spinBox_mesh_triangleSize->value());
@@ -2470,9 +2477,7 @@ void DatabaseViewer::update(int value,
} }
// 3d view // 3d view
if(view3D->isVisible() && if(view3D->isVisible())
(!data.depthOrRightRaw().empty() ||
!data.laserScanRaw().empty()))
{ {
Transform pose = Transform::getIdentity(); Transform pose = Transform::getIdentity();
if(signatures.size()) if(signatures.size())
@@ -2483,11 +2488,14 @@ void DatabaseViewer::update(int value,
} }
view3D->removeAllFrustums(); view3D->removeAllFrustums();
view3D->removeCloud("0"); view3D->removeCloud("mesh");
view3D->removeCloud("1"); view3D->removeCloud("cloud");
view3D->removeCloud("scan");
view3D->removeCloud("map"); view3D->removeCloud("map");
view3D->removeCloud("ground"); view3D->removeCloud("ground");
view3D->removeCloud("obstacles"); view3D->removeCloud("obstacles");
if(ui_->checkBox_showCloud->isChecked() || ui_->checkBox_showMesh->isChecked())
{
if(!data.depthOrRightRaw().empty()) if(!data.depthOrRightRaw().empty())
{ {
if(!data.imageRaw().empty()) if(!data.imageRaw().empty())
@@ -2537,35 +2545,67 @@ void DatabaseViewer::update(int value,
ui_->checkBox_mesh_quad->isChecked(), ui_->checkBox_mesh_quad->isChecked(),
ui_->spinBox_mesh_triangleSize->value(), ui_->spinBox_mesh_triangleSize->value(),
viewpoint); viewpoint);
view3D->addCloudMesh("0", cloud, polygons, pose);
} if(ui_->spinBox_mesh_minClusterSize->value())
else
{ {
view3D->addCloud("0", cloud, pose); // filter polygons
std::vector<std::set<int> > neighbors;
std::vector<std::set<int> > vertexToPolygons;
util3d::createPolygonIndexes(polygons,
cloud->size(),
neighbors,
vertexToPolygons);
std::list<std::list<int> > clusters = util3d::clusterPolygons(
neighbors,
ui_->spinBox_mesh_minClusterSize->value());
std::vector<pcl::Vertices> filteredPolygons(polygons.size());
int oi=0;
for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
{
for(std::list<int>::iterator jter=iter->begin(); jter!=iter->end(); ++jter)
{
filteredPolygons[oi++] = polygons.at(*jter);
}
}
filteredPolygons.resize(oi);
polygons = filteredPolygons;
}
view3D->addCloudMesh("mesh", cloud, polygons, pose);
}
if(ui_->checkBox_showCloud->isChecked())
{
view3D->addCloud("cloud", cloud, pose);
} }
} }
view3D->updateCameraFrustums(pose, data.cameraModels()); view3D->updateCameraFrustums(pose, data.cameraModels());
} }
else else if(ui_->checkBox_showCloud->isChecked())
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud; pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
cloud = util3d::cloudFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters()); cloud = util3d::cloudFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters());
if(cloud->size()) if(cloud->size())
{ {
view3D->addCloud("0", cloud, pose); view3D->addCloud("cloud", cloud, pose);
view3D->updateCameraFrustum(pose, data.stereoCameraModel()); view3D->updateCameraFrustum(pose, data.stereoCameraModel());
} }
} }
} }
}
//add scan //add scan
if(ui_->checkBox_showScan->isChecked())
{
pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(data.laserScanRaw(), data.laserScanInfo().localTransform()); pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(data.laserScanRaw(), data.laserScanInfo().localTransform());
if(scan->size()) if(scan->size())
{ {
view3D->addCloud("1", scan, pose, Qt::yellow); view3D->addCloud("scan", scan, pose, Qt::yellow);
}
} }
//add occupancy grid //add occupancy grid
if(ui_->checkBox_showMap->isChecked() || ui_->checkBox_showGrid->isChecked())
{
std::map<int, std::pair<cv::Mat, cv::Mat> > localMaps; std::map<int, std::pair<cv::Mat, cv::Mat> > localMaps;
if(generatedLocalMaps_.find(data.id()) != generatedLocalMaps_.end()) if(generatedLocalMaps_.find(data.id()) != generatedLocalMaps_.end())
{ {
@@ -2580,6 +2620,8 @@ void DatabaseViewer::update(int value,
std::map<int, Transform> poses; std::map<int, Transform> poses;
poses.insert(std::make_pair(data.id(), Transform::getIdentity())); poses.insert(std::make_pair(data.id(), Transform::getIdentity()));
if(ui_->checkBox_showMap->isChecked())
{
float xMin=0.0f, yMin=0.0f; float xMin=0.0f, yMin=0.0f;
cv::Mat map8S = util3d::create2DMapFromOccupancyLocalMaps( cv::Mat map8S = util3d::create2DMapFromOccupancyLocalMaps(
poses, poses,
@@ -2592,7 +2634,10 @@ void DatabaseViewer::update(int value,
cv::Mat map8U = util3d::convertMap2Image8U(map8S); cv::Mat map8U = util3d::convertMap2Image8U(map8S);
view3D->addOccupancyGridMap(map8U, ui_->doubleSpinBox_gridCellSize->value(), xMin, yMin, 1); view3D->addOccupancyGridMap(map8U, ui_->doubleSpinBox_gridCellSize->value(), xMin, yMin, 1);
} }
}
if(ui_->checkBox_showGrid->isChecked())
{
// occupancy cloud // occupancy cloud
view3D->addCloud("ground", view3D->addCloud("ground",
util3d::laserScanToPointCloud(localMaps.begin()->second.first), util3d::laserScanToPointCloud(localMaps.begin()->second.first),
@@ -2605,9 +2650,11 @@ void DatabaseViewer::update(int value,
view3D->setCloudPointSize("ground", 5); view3D->setCloudPointSize("ground", 5);
view3D->setCloudPointSize("obstacles", 5); view3D->setCloudPointSize("obstacles", 5);
} }
}
}
view3D->update(); view3D->update();
} }
if(signatures.size()) if(signatures.size())
{ {
UASSERT(signatures.front() != 0 && signatures.size() == 1); UASSERT(signatures.front() != 0 && signatures.size() == 1);

View File

@@ -174,6 +174,7 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou
settings.setValue("mesh_radius", _ui->doubleSpinBox_gp3Radius->value()); settings.setValue("mesh_radius", _ui->doubleSpinBox_gp3Radius->value());
settings.setValue("mesh_mu", _ui->doubleSpinBox_gp3Mu->value()); settings.setValue("mesh_mu", _ui->doubleSpinBox_gp3Mu->value());
settings.setValue("mesh_decimation_factor", _ui->doubleSpinBox_meshDecimationFactor->value()); settings.setValue("mesh_decimation_factor", _ui->doubleSpinBox_meshDecimationFactor->value());
settings.setValue("mesh_min_cluster_size", _ui->spinBox_mesh_minClusterSize->value());
settings.setValue("mesh_texture", _ui->checkBox_textureMapping->isChecked()); settings.setValue("mesh_texture", _ui->checkBox_textureMapping->isChecked());
@@ -229,6 +230,7 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou
_ui->doubleSpinBox_gp3Radius->setValue(settings.value("mesh_radius", _ui->doubleSpinBox_gp3Radius->value()).toDouble()); _ui->doubleSpinBox_gp3Radius->setValue(settings.value("mesh_radius", _ui->doubleSpinBox_gp3Radius->value()).toDouble());
_ui->doubleSpinBox_gp3Mu->setValue(settings.value("mesh_mu", _ui->doubleSpinBox_gp3Mu->value()).toDouble()); _ui->doubleSpinBox_gp3Mu->setValue(settings.value("mesh_mu", _ui->doubleSpinBox_gp3Mu->value()).toDouble());
_ui->doubleSpinBox_meshDecimationFactor->setValue(settings.value("mesh_decimation_factor",_ui->doubleSpinBox_meshDecimationFactor->value()).toDouble()); _ui->doubleSpinBox_meshDecimationFactor->setValue(settings.value("mesh_decimation_factor",_ui->doubleSpinBox_meshDecimationFactor->value()).toDouble());
_ui->spinBox_mesh_minClusterSize->setValue(settings.value("mesh_min_cluster_size", _ui->spinBox_mesh_minClusterSize->value()).toInt());
_ui->checkBox_textureMapping->setChecked(settings.value("mesh_texture", _ui->checkBox_textureMapping->isChecked()).toBool()); _ui->checkBox_textureMapping->setChecked(settings.value("mesh_texture", _ui->checkBox_textureMapping->isChecked()).toBool());
@@ -752,6 +754,32 @@ bool ExportCloudsDialog::getExportedClouds(
_ui->checkBox_mesh_quad->isEnabled() && _ui->checkBox_mesh_quad->isChecked(), _ui->checkBox_mesh_quad->isEnabled() && _ui->checkBox_mesh_quad->isChecked(),
_ui->spinBox_mesh_triangleSize->value(), _ui->spinBox_mesh_triangleSize->value(),
viewpoint); viewpoint);
if(_ui->spinBox_mesh_minClusterSize->value())
{
// filter polygons
std::vector<std::set<int> > neighbors;
std::vector<std::set<int> > vertexToPolygons;
util3d::createPolygonIndexes(polygons,
iter->second->size(),
neighbors,
vertexToPolygons);
std::list<std::list<int> > clusters = util3d::clusterPolygons(
neighbors,
_ui->spinBox_mesh_minClusterSize->value());
std::vector<pcl::Vertices> filteredPolygons(polygons.size());
int oi=0;
for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
{
for(std::list<int>::iterator jter=iter->begin(); jter!=iter->end(); ++jter)
{
filteredPolygons[oi++] = polygons.at(*jter);
}
}
filteredPolygons.resize(oi);
polygons = filteredPolygons;
}
_progressDialog->appendText(tr("Mesh %1 created with %2 polygons (%3/%4).").arg(iter->first).arg(polygons.size()).arg(++i).arg(clouds.size())); _progressDialog->appendText(tr("Mesh %1 created with %2 polygons (%3/%4).").arg(iter->first).arg(polygons.size()).arg(++i).arg(clouds.size()));
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr denseCloud(new pcl::PointCloud<pcl::PointXYZRGBNormal>); pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr denseCloud(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
@@ -874,6 +902,32 @@ bool ExportCloudsDialog::getExportedClouds(
iter->second, iter->second,
_ui->doubleSpinBox_gp3Radius->value(), _ui->doubleSpinBox_gp3Radius->value(),
_ui->doubleSpinBox_gp3Mu->value()); _ui->doubleSpinBox_gp3Mu->value());
if(_ui->spinBox_mesh_minClusterSize->value())
{
// filter polygons
std::vector<std::set<int> > neighbors;
std::vector<std::set<int> > vertexToPolygons;
util3d::createPolygonIndexes(mesh->polygons,
mesh->cloud.height*mesh->cloud.width,
neighbors,
vertexToPolygons);
std::list<std::list<int> > clusters = util3d::clusterPolygons(
neighbors,
_ui->spinBox_mesh_minClusterSize->value());
std::vector<pcl::Vertices> filteredPolygons(mesh->polygons.size());
int oi=0;
for(std::list<std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
{
for(std::list<int>::iterator jter=iter->begin(); jter!=iter->end(); ++jter)
{
filteredPolygons[oi++] = mesh->polygons.at(*jter);
}
}
filteredPolygons.resize(oi);
mesh->polygons = filteredPolygons;
}
_progressDialog->appendText(tr("Mesh %1 created with %2 polygons (%3/%4).").arg(iter->first).arg(mesh->polygons.size()).arg(++i).arg(clouds.size())); _progressDialog->appendText(tr("Mesh %1 created with %2 polygons (%3/%4).").arg(iter->first).arg(mesh->polygons.size()).arg(++i).arg(clouds.size()));
QApplication::processEvents(); QApplication::processEvents();

View File

@@ -52,8 +52,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>202</width> <width>205</width>
<height>196</height> <height>208</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1"> <layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
@@ -210,8 +210,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>201</width> <width>203</width>
<height>196</height> <height>208</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1"> <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
@@ -484,7 +484,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1285</width> <width>1285</width>
<height>25</height> <height>22</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@@ -990,8 +990,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>333</width> <width>324</width>
<height>186</height> <height>188</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@@ -1125,9 +1125,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>-225</y>
<width>278</width> <width>280</width>
<height>383</height> <height>465</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@@ -1249,7 +1249,7 @@
<string>Organized Fast Mesh</string> <string>Organized Fast Mesh</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_13"> <layout class="QGridLayout" name="gridLayout_13">
<item row="2" column="1"> <item row="3" column="1">
<widget class="QLabel" name="label_14"> <widget class="QLabel" name="label_14">
<property name="text"> <property name="text">
<string>Triangle size</string> <string>Triangle size</string>
@@ -1263,39 +1263,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_mesh_quad">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Fill depth holes: size</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QSpinBox" name="spinBox_mesh_fillDepthHoles">
<property name="suffix">
<string> pix</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QSpinBox" name="spinBox_mesh_angleTolerance"> <widget class="QSpinBox" name="spinBox_mesh_angleTolerance">
<property name="suffix"> <property name="suffix">
@@ -1312,7 +1279,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QSpinBox" name="spinBox_mesh_triangleSize"> <widget class="QSpinBox" name="spinBox_mesh_triangleSize">
<property name="suffix"> <property name="suffix">
<string> pix</string> <string> pix</string>
@@ -1325,21 +1292,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="2" column="1">
<widget class="QLabel" name="label_13"> <widget class="QLabel" name="label_13">
<property name="text"> <property name="text">
<string>Quad</string> <string>Quad</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="5" column="1">
<widget class="QLabel" name="label_17"> <widget class="QLabel" name="label_17">
<property name="text"> <property name="text">
<string>Fill depth holes: error</string> <string>Fill depth holes: error</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="5" column="0">
<widget class="QSpinBox" name="spinBox_mesh_depthError"> <widget class="QSpinBox" name="spinBox_mesh_depthError">
<property name="suffix"> <property name="suffix">
<string> %</string> <string> %</string>
@@ -1352,9 +1319,78 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox_mesh_quad">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Fill depth holes: size</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QSpinBox" name="spinBox_mesh_fillDepthHoles">
<property name="suffix">
<string> pix</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Min cluster size</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSpinBox" name="spinBox_mesh_minClusterSize">
<property name="suffix">
<string/>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>999</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<spacer name="verticalSpacer_2"> <spacer name="verticalSpacer_2">
<property name="orientation"> <property name="orientation">
@@ -1375,8 +1411,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>289</width> <width>265</width>
<height>182</height> <height>126</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@@ -1475,8 +1511,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>289</width> <width>265</width>
<height>182</height> <height>168</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@@ -1698,6 +1734,18 @@
</property> </property>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="checkBox_showCloud">
<property name="text">
<string>Cloud</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="checkBox_showMesh"> <widget class="QCheckBox" name="checkBox_showMesh">
<property name="text"> <property name="text">
@@ -1708,6 +1756,51 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="checkBox_showScan">
<property name="text">
<string>Scan</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_showMap">
<property name="text">
<string>Map</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_showGrid">
<property name="text">
<string>Grid</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>

View File

@@ -23,9 +23,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>-860</y>
<width>778</width> <width>773</width>
<height>1318</height> <height>1463</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_13"> <layout class="QVBoxLayout" name="verticalLayout_13">
@@ -793,25 +793,6 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
<layout class="QVBoxLayout" name="verticalLayout_15"> <layout class="QVBoxLayout" name="verticalLayout_15">
<item> <item>
<layout class="QGridLayout" name="gridLayout_10" columnstretch="0,1"> <layout class="QGridLayout" name="gridLayout_10" columnstretch="0,1">
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_meshDecimationFactor">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>0.990000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLabel" name="label_170"> <widget class="QLabel" name="label_170">
<property name="text"> <property name="text">
@@ -839,6 +820,39 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_meshDecimationFactor">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>0.990000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Min polygon cluster size</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_mesh_minClusterSize">
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@@ -920,23 +934,11 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
<property name="title"> <property name="title">
<string>Organized Meshing</string> <string>Organized Meshing</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_17">
<item>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1"> <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
<item row="0" column="1"> <item row="2" column="1">
<widget class="QLabel" name="label_14"> <widget class="QLabel" name="label_15">
<property name="text"> <property name="text">
<string>Angle tolerance</string> <string>Triangle size</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_mesh_quad">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@@ -947,23 +949,13 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="1" column="0">
<widget class="QSpinBox" name="spinBox_mesh_triangleSize"> <widget class="QCheckBox" name="checkBox_mesh_quad">
<property name="suffix">
<string> pix</string>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>99</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_15">
<property name="text"> <property name="text">
<string>Triangle size</string> <string/>
</property>
<property name="checked">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@@ -986,7 +978,28 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Angle tolerance</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_mesh_triangleSize">
<property name="suffix">
<string> pix</string>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>99</number>
</property>
</widget>
</item>
</layout> </layout>
</widget>
</item> </item>
<item> <item>
<spacer name="verticalSpacer_8"> <spacer name="verticalSpacer_8">
@@ -995,7 +1008,7 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
@@ -1004,9 +1017,6 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</layout> </layout>
</widget> </widget>
</item> </item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer_9"> <spacer name="verticalSpacer_9">
<property name="orientation"> <property name="orientation">