+ add region growing, segmentation and ransac algorithms to Reen module
This commit is contained in:
parent
1ec066553e
commit
8a76f2c13e
|
@ -44,7 +44,10 @@
|
|||
#include "ApproxSurface.h"
|
||||
#include "BSplineFitting.h"
|
||||
#include "SurfaceTriangulation.h"
|
||||
#include "RegionGrowing.h"
|
||||
#include "SampleConsensus.h"
|
||||
#if defined(HAVE_PCL_FILTERS)
|
||||
#include <pcl/filters/passthrough.h>
|
||||
#include <pcl/filters/voxel_grid.h>
|
||||
#include <pcl/point_types.h>
|
||||
#endif
|
||||
|
@ -92,6 +95,16 @@ public:
|
|||
"filterVoxelGrid(dim)."
|
||||
);
|
||||
#endif
|
||||
#if defined(HAVE_PCL_SEGMENTATION)
|
||||
add_keyword_method("regionGrowingSegmentation",&Module::regionGrowingSegmentation,
|
||||
"regionGrowingSegmentation()."
|
||||
);
|
||||
#endif
|
||||
#if defined(HAVE_PCL_SEGMENTATION)
|
||||
add_keyword_method("sampleConsensus",&Module::sampleConsensus,
|
||||
"sampleConsensus()."
|
||||
);
|
||||
#endif
|
||||
initialize("This module is the ReverseEngineering module."); // register with Python
|
||||
}
|
||||
|
||||
|
@ -572,6 +585,74 @@ Mesh.show(m)
|
|||
return Py::asObject(new Points::PointsPy(points_sample));
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_PCL_SEGMENTATION)
|
||||
Py::Object regionGrowingSegmentation(const Py::Tuple& args, const Py::Dict& kwds)
|
||||
{
|
||||
PyObject *pts;
|
||||
PyObject *vec = 0;
|
||||
int ksearch=5;
|
||||
|
||||
static char* kwds_segment[] = {"Points", "KSearch", "Normals", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!|iO", kwds_segment,
|
||||
&(Points::PointsPy::Type), &pts,
|
||||
&ksearch, &vec))
|
||||
throw Py::Exception();
|
||||
|
||||
Points::PointKernel* points = static_cast<Points::PointsPy*>(pts)->getPointKernelPtr();
|
||||
|
||||
std::list<std::vector<int> > clusters;
|
||||
RegionGrowing segm(*points, clusters);
|
||||
if (vec) {
|
||||
Py::Sequence list(vec);
|
||||
std::vector<Base::Vector3f> normals;
|
||||
normals.reserve(list.size());
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
Base::Vector3d v = Py::Vector(*it).toVector();
|
||||
normals.push_back(Base::convertTo<Base::Vector3f>(v));
|
||||
}
|
||||
segm.perform(normals);
|
||||
}
|
||||
else {
|
||||
segm.perform(ksearch);
|
||||
}
|
||||
|
||||
Py::List lists;
|
||||
for (std::list<std::vector<int> >::iterator it = clusters.begin(); it != clusters.end(); ++it) {
|
||||
Py::Tuple tuple(it->size());
|
||||
for (std::size_t i = 0; i < it->size(); i++) {
|
||||
tuple.setItem(i, Py::Long((*it)[i]));
|
||||
}
|
||||
lists.append(tuple);
|
||||
}
|
||||
|
||||
return lists;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_PCL_SEGMENTATION)
|
||||
Py::Object sampleConsensus(const Py::Tuple& args, const Py::Dict& kwds)
|
||||
{
|
||||
PyObject *pts;
|
||||
|
||||
static char* kwds_sample[] = {"Points", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!", kwds_sample,
|
||||
&(Points::PointsPy::Type), &pts))
|
||||
throw Py::Exception();
|
||||
|
||||
Points::PointKernel* points = static_cast<Points::PointsPy*>(pts)->getPointKernelPtr();
|
||||
|
||||
std::vector<float> parameters;
|
||||
SampleConsensus sample(*points);
|
||||
double probability = sample.perform(parameters);
|
||||
|
||||
Py::Dict dict;
|
||||
Py::Tuple tuple(parameters.size());
|
||||
for (std::size_t i = 0; i < parameters.size(); i++)
|
||||
tuple.setItem(i, Py::Float(parameters[i]));
|
||||
dict.setItem(Py::String("Probability"), Py::Float(probability));
|
||||
|
||||
return dict;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
} // namespace Reen
|
||||
|
||||
|
|
|
@ -16,6 +16,14 @@ if (PCL_FILTERS_FOUND AND PCL_FEATURES_FOUND)
|
|||
add_definitions(-DHAVE_PCL_FILTERS)
|
||||
endif ()
|
||||
|
||||
if (PCL_SEGMENTATION_FOUND AND PCL_FEATURES_FOUND)
|
||||
add_definitions(-DHAVE_PCL_SEGMENTATION)
|
||||
endif ()
|
||||
|
||||
if (PCL_SAMPLE_CONSENSUS_FOUND)
|
||||
add_definitions(-DHAVE_PCL_SAMPLE_CONSENSUS)
|
||||
endif ()
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${Boost_INCLUDE_DIRS}
|
||||
|
@ -42,6 +50,8 @@ set(Reen_LIBS
|
|||
${PCL_FILTERS_LIBRARIES}
|
||||
${PCL_SEARCH_LIBRARIES}
|
||||
${PCL_SURFACE_LIBRARIES}
|
||||
${PCL_SEGMENTATION_LIBRARIES}
|
||||
${PCL_SAMPLE_CONSENSUS_LIBRARIES}
|
||||
${QT_QTCORE_LIBRARY}
|
||||
)
|
||||
|
||||
|
@ -51,6 +61,10 @@ SET(Reen_SRCS
|
|||
ApproxSurface.h
|
||||
BSplineFitting.cpp
|
||||
BSplineFitting.h
|
||||
RegionGrowing.cpp
|
||||
RegionGrowing.h
|
||||
SampleConsensus.cpp
|
||||
SampleConsensus.h
|
||||
SurfaceTriangulation.cpp
|
||||
SurfaceTriangulation.h
|
||||
PreCompiled.cpp
|
||||
|
|
147
src/Mod/ReverseEngineering/App/RegionGrowing.cpp
Normal file
147
src/Mod/ReverseEngineering/App/RegionGrowing.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "RegionGrowing.h"
|
||||
#include <Mod/Points/App/Points.h>
|
||||
#include <Base/Exception.h>
|
||||
|
||||
#if defined(HAVE_PCL_FILTERS)
|
||||
#include <pcl/filters/passthrough.h>
|
||||
#include <pcl/point_types.h>
|
||||
#endif
|
||||
#if defined(HAVE_PCL_SEGMENTATION)
|
||||
#include <pcl/search/search.h>
|
||||
#include <pcl/search/kdtree.h>
|
||||
#include <pcl/features/normal_3d.h>
|
||||
#include <pcl/segmentation/region_growing.h>
|
||||
#include <pcl/filters/extract_indices.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace Reen;
|
||||
using pcl::PointXYZ;
|
||||
using pcl::PointNormal;
|
||||
using pcl::PointCloud;
|
||||
|
||||
RegionGrowing::RegionGrowing(const Points::PointKernel& pts, std::list<std::vector<int> >& clusters)
|
||||
: myPoints(pts)
|
||||
, myClusters(clusters)
|
||||
{
|
||||
}
|
||||
|
||||
void RegionGrowing::perform(int ksearch)
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
|
||||
cloud->reserve(myPoints.size());
|
||||
for (Points::PointKernel::const_iterator it = myPoints.begin(); it != myPoints.end(); ++it) {
|
||||
cloud->push_back(pcl::PointXYZ(it->x, it->y, it->z));
|
||||
}
|
||||
|
||||
//normal estimation
|
||||
pcl::search::Search<pcl::PointXYZ>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> > (new pcl::search::KdTree<pcl::PointXYZ>);
|
||||
pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
|
||||
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
|
||||
normal_estimator.setSearchMethod (tree);
|
||||
normal_estimator.setInputCloud (cloud);
|
||||
normal_estimator.setKSearch (ksearch);
|
||||
normal_estimator.compute (*normals);
|
||||
|
||||
// pass through
|
||||
pcl::IndicesPtr indices (new std::vector <int>);
|
||||
pcl::PassThrough<pcl::PointXYZ> pass;
|
||||
pass.setInputCloud (cloud);
|
||||
pass.setFilterFieldName ("z");
|
||||
pass.setFilterLimits (0.0, 1.0);
|
||||
pass.filter (*indices);
|
||||
|
||||
pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
|
||||
reg.setMinClusterSize (50);
|
||||
reg.setMaxClusterSize (1000000);
|
||||
reg.setSearchMethod (tree);
|
||||
reg.setNumberOfNeighbours (30);
|
||||
reg.setInputCloud (cloud);
|
||||
//reg.setIndices (indices);
|
||||
reg.setInputNormals (normals);
|
||||
reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
|
||||
reg.setCurvatureThreshold (1.0);
|
||||
|
||||
std::vector <pcl::PointIndices> clusters;
|
||||
reg.extract (clusters);
|
||||
|
||||
for (std::vector<pcl::PointIndices>::iterator it = clusters.begin (); it != clusters.end (); ++it) {
|
||||
myClusters.push_back(std::vector<int>());
|
||||
myClusters.back().swap(it->indices);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionGrowing::perform(const std::vector<Base::Vector3f>& myNormals)
|
||||
{
|
||||
if (myPoints.size() != myNormals.size())
|
||||
throw Base::RuntimeError("Number of points doesn't match with number of normals");
|
||||
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
|
||||
cloud->reserve(myPoints.size());
|
||||
for (Points::PointKernel::const_iterator it = myPoints.begin(); it != myPoints.end(); ++it) {
|
||||
cloud->push_back(pcl::PointXYZ(it->x, it->y, it->z));
|
||||
}
|
||||
|
||||
pcl::search::Search<pcl::PointXYZ>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> > (new pcl::search::KdTree<pcl::PointXYZ>);
|
||||
tree->setInputCloud (cloud);
|
||||
|
||||
pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
|
||||
normals->reserve(myNormals.size());
|
||||
for (std::vector<Base::Vector3f>::const_iterator it = myNormals.begin(); it != myNormals.end(); ++it) {
|
||||
normals->push_back(pcl::Normal(it->x, it->y, it->z));
|
||||
}
|
||||
|
||||
// pass through
|
||||
pcl::IndicesPtr indices (new std::vector <int>);
|
||||
pcl::PassThrough<pcl::PointXYZ> pass;
|
||||
pass.setInputCloud (cloud);
|
||||
pass.setFilterFieldName ("z");
|
||||
pass.setFilterLimits (0.0, 1.0);
|
||||
pass.filter (*indices);
|
||||
|
||||
pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
|
||||
reg.setMinClusterSize (50);
|
||||
reg.setMaxClusterSize (1000000);
|
||||
reg.setSearchMethod (tree);
|
||||
reg.setNumberOfNeighbours (30);
|
||||
reg.setInputCloud (cloud);
|
||||
//reg.setIndices (indices);
|
||||
reg.setInputNormals (normals);
|
||||
reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
|
||||
reg.setCurvatureThreshold (1.0);
|
||||
|
||||
std::vector <pcl::PointIndices> clusters;
|
||||
reg.extract (clusters);
|
||||
|
||||
for (std::vector<pcl::PointIndices>::iterator it = clusters.begin (); it != clusters.end (); ++it) {
|
||||
myClusters.push_back(std::vector<int>());
|
||||
myClusters.back().swap(it->indices);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_PCL_SEGMENTATION
|
||||
|
56
src/Mod/ReverseEngineering/App/RegionGrowing.h
Normal file
56
src/Mod/ReverseEngineering/App/RegionGrowing.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef REEN_REGIONGROWING_H
|
||||
#define REEN_REGIONGROWING_H
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
namespace Points {class PointKernel;}
|
||||
|
||||
namespace Reen {
|
||||
|
||||
class RegionGrowing
|
||||
{
|
||||
public:
|
||||
RegionGrowing(const Points::PointKernel&, std::list<std::vector<int> >&);
|
||||
/** \brief Set the number of k nearest neighbors to use for the normal estimation.
|
||||
* \param[in] k the number of k-nearest neighbors
|
||||
*/
|
||||
void perform(int ksearch);
|
||||
/** \brief Pass the normals to the points given in the constructor.
|
||||
* \param[in] normals the normals to the given points.
|
||||
*/
|
||||
void perform(const std::vector<Base::Vector3f>& normals);
|
||||
|
||||
private:
|
||||
const Points::PointKernel& myPoints;
|
||||
std::list<std::vector<int> >& myClusters;
|
||||
};
|
||||
|
||||
} // namespace Reen
|
||||
|
||||
#endif // REEN_REGIONGROWING_H
|
||||
|
76
src/Mod/ReverseEngineering/App/SampleConsensus.cpp
Normal file
76
src/Mod/ReverseEngineering/App/SampleConsensus.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "SampleConsensus.h"
|
||||
#include <Mod/Points/App/Points.h>
|
||||
#include <Base/Exception.h>
|
||||
|
||||
#if defined(HAVE_PCL_SAMPLE_CONSENSUS)
|
||||
#include <pcl/point_types.h>
|
||||
#include <pcl/sample_consensus/ransac.h>
|
||||
#include <pcl/sample_consensus/sac_model_plane.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace Reen;
|
||||
using pcl::PointXYZ;
|
||||
using pcl::PointNormal;
|
||||
using pcl::PointCloud;
|
||||
|
||||
SampleConsensus::SampleConsensus(const Points::PointKernel& pts)
|
||||
: myPoints(pts)
|
||||
{
|
||||
}
|
||||
|
||||
double SampleConsensus::perform(std::vector<float>& parameters)
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
|
||||
cloud->reserve(myPoints.size());
|
||||
for (Points::PointKernel::const_iterator it = myPoints.begin(); it != myPoints.end(); ++it) {
|
||||
cloud->push_back(pcl::PointXYZ(it->x, it->y, it->z));
|
||||
}
|
||||
|
||||
cloud->width = int (cloud->points.size ());
|
||||
cloud->height = 1;
|
||||
cloud->is_dense = true;
|
||||
|
||||
// created RandomSampleConsensus object and compute the appropriated model
|
||||
pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr
|
||||
model_p (new pcl::SampleConsensusModelPlane<pcl::PointXYZ> (cloud));
|
||||
|
||||
pcl::RandomSampleConsensus<pcl::PointXYZ> ransac (model_p);
|
||||
ransac.setDistanceThreshold (.01);
|
||||
ransac.computeModel();
|
||||
//ransac.getInliers(inliers);
|
||||
//ransac.getModel (model);
|
||||
Eigen::VectorXf model_p_coefficients;
|
||||
ransac.getModelCoefficients (model_p_coefficients);
|
||||
for (int i=0; i<model_p_coefficients.size(); i++)
|
||||
parameters.push_back(model_p_coefficients[i]);
|
||||
|
||||
return ransac.getProbability();
|
||||
}
|
||||
|
||||
#endif // HAVE_PCL_SAMPLE_CONSENSUS
|
||||
|
47
src/Mod/ReverseEngineering/App/SampleConsensus.h
Normal file
47
src/Mod/ReverseEngineering/App/SampleConsensus.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef REEN_SAMPLECONSENSUS_H
|
||||
#define REEN_SAMPLECONSENSUS_H
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
#include <vector>
|
||||
|
||||
namespace Points {class PointKernel;}
|
||||
|
||||
namespace Reen {
|
||||
|
||||
class SampleConsensus
|
||||
{
|
||||
public:
|
||||
SampleConsensus(const Points::PointKernel&);
|
||||
double perform(std::vector<float>& parameters);
|
||||
|
||||
private:
|
||||
const Points::PointKernel& myPoints;
|
||||
};
|
||||
|
||||
} // namespace Reen
|
||||
|
||||
#endif // REEN_SAMPLECONSENSUS_H
|
||||
|
Loading…
Reference in New Issue
Block a user