ReverseEngineering: [skip ci] improve segmentation based on point clouds
This commit is contained in:
@@ -725,27 +725,92 @@ Mesh.show(m)
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_PCL_SAMPLE_CONSENSUS)
|
||||
/*
|
||||
import ReverseEngineering as reen
|
||||
import Points
|
||||
import Part
|
||||
|
||||
p = App.ActiveDocument.Points.Points
|
||||
data = p.Points
|
||||
n = reen.normalEstimation(p, 10)
|
||||
|
||||
model = reen.sampleConsensus(SacModel="Plane", Points=p)
|
||||
indices = model["Model"]
|
||||
param = model["Parameters"]
|
||||
|
||||
plane = Part.Plane()
|
||||
plane.Axis = param[0:3]
|
||||
plane.Position = -plane.Axis * param[3]
|
||||
|
||||
np = Points.Points()
|
||||
np.addPoints([data[i] for i in indices])
|
||||
Points.show(np)
|
||||
|
||||
# sort in descending order
|
||||
indices = list(indices)
|
||||
indices.sort(reverse=True)
|
||||
|
||||
# remove points of segment
|
||||
for i in indices:
|
||||
del data[i]
|
||||
del n[i]
|
||||
|
||||
p = Points.Points()
|
||||
p.addPoints(data)
|
||||
model = reen.sampleConsensus(SacModel="Cylinder", Points=p, Normals=n)
|
||||
indices = model["Model"]
|
||||
|
||||
np = Points.Points()
|
||||
np.addPoints([data[i] for i in indices])
|
||||
Points.show(np)
|
||||
*/
|
||||
Py::Object sampleConsensus(const Py::Tuple& args, const Py::Dict& kwds)
|
||||
{
|
||||
PyObject *pts;
|
||||
PyObject *vec = nullptr;
|
||||
const char* sacModelType = nullptr;
|
||||
|
||||
static char* kwds_sample[] = {"Points", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!", kwds_sample,
|
||||
&(Points::PointsPy::Type), &pts))
|
||||
static char* kwds_sample[] = {"SacModel", "Points", "Normals", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "sO!|O", kwds_sample,
|
||||
&sacModelType, &(Points::PointsPy::Type), &pts, &vec))
|
||||
throw Py::Exception();
|
||||
|
||||
Points::PointKernel* points = static_cast<Points::PointsPy*>(pts)->getPointKernelPtr();
|
||||
std::vector<Base::Vector3d> normals;
|
||||
if (vec) {
|
||||
Py::Sequence list(vec);
|
||||
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(v);
|
||||
}
|
||||
}
|
||||
|
||||
SampleConsensus::SacModel sacModel = SampleConsensus::SACMODEL_PLANE;
|
||||
if (sacModelType) {
|
||||
if (strcmp(sacModelType, "Cylinder") == 0)
|
||||
sacModel = SampleConsensus::SACMODEL_CYLINDER;
|
||||
else if (strcmp(sacModelType, "Sphere") == 0)
|
||||
sacModel = SampleConsensus::SACMODEL_SPHERE;
|
||||
else if (strcmp(sacModelType, "Cone") == 0)
|
||||
sacModel = SampleConsensus::SACMODEL_CONE;
|
||||
}
|
||||
|
||||
std::vector<float> parameters;
|
||||
SampleConsensus sample(*points);
|
||||
double probability = sample.perform(parameters);
|
||||
SampleConsensus sample(sacModel, *points, normals);
|
||||
std::vector<int> model;
|
||||
double probability = sample.perform(parameters, model);
|
||||
|
||||
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]));
|
||||
Py::Tuple data(model.size());
|
||||
for (std::size_t i = 0; i < model.size(); i++)
|
||||
data.setItem(i, Py::Long(model[i]));
|
||||
dict.setItem(Py::String("Probability"), Py::Float(probability));
|
||||
dict.setItem(Py::String("Parameters"), tuple);
|
||||
dict.setItem(Py::String("Model"), data);
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,12 @@
|
||||
|
||||
#if defined(HAVE_PCL_SAMPLE_CONSENSUS)
|
||||
#include <pcl/point_types.h>
|
||||
#include <pcl/features/normal_3d.h>
|
||||
#include <pcl/sample_consensus/ransac.h>
|
||||
#include <pcl/sample_consensus/sac_model_plane.h>
|
||||
#include <pcl/sample_consensus/sac_model_sphere.h>
|
||||
#include <pcl/sample_consensus/sac_model_cylinder.h>
|
||||
#include <pcl/sample_consensus/sac_model_cone.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace Reen;
|
||||
@@ -39,12 +43,14 @@ using pcl::PointXYZ;
|
||||
using pcl::PointNormal;
|
||||
using pcl::PointCloud;
|
||||
|
||||
SampleConsensus::SampleConsensus(const Points::PointKernel& pts)
|
||||
: myPoints(pts)
|
||||
SampleConsensus::SampleConsensus(SacModel sac, const Points::PointKernel& pts, const std::vector<Base::Vector3d>& nor)
|
||||
: mySac(sac)
|
||||
, myPoints(pts)
|
||||
, myNormals(nor)
|
||||
{
|
||||
}
|
||||
|
||||
double SampleConsensus::perform(std::vector<float>& parameters)
|
||||
double SampleConsensus::perform(std::vector<float>& parameters, std::vector<int>& model)
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
|
||||
cloud->reserve(myPoints.size());
|
||||
@@ -57,14 +63,67 @@ double SampleConsensus::perform(std::vector<float>& parameters)
|
||||
cloud->height = 1;
|
||||
cloud->is_dense = true;
|
||||
|
||||
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal> ());
|
||||
if (mySac == SACMODEL_CONE || mySac == SACMODEL_CYLINDER) {
|
||||
#if 0
|
||||
// Create search tree
|
||||
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree;
|
||||
tree.reset (new pcl::search::KdTree<PointXYZ> (false));
|
||||
tree->setInputCloud (cloud);
|
||||
|
||||
// Normal estimation
|
||||
int ksearch = 10;
|
||||
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;
|
||||
n.setInputCloud (cloud);
|
||||
n.setSearchMethod (tree);
|
||||
n.setKSearch (ksearch);
|
||||
n.compute (*normals);
|
||||
#else
|
||||
normals->reserve(myNormals.size());
|
||||
for (std::vector<Base::Vector3d>::const_iterator it = myNormals.begin(); it != myNormals.end(); ++it) {
|
||||
if (!boost::math::isnan(it->x) && !boost::math::isnan(it->y) && !boost::math::isnan(it->z))
|
||||
normals->push_back(pcl::Normal(it->x, it->y, it->z));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// created RandomSampleConsensus object and compute the appropriated model
|
||||
pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr
|
||||
model_p (new pcl::SampleConsensusModelPlane<pcl::PointXYZ> (cloud));
|
||||
pcl::SampleConsensusModel<pcl::PointXYZ>::Ptr model_p;
|
||||
switch (mySac) {
|
||||
case SACMODEL_PLANE:
|
||||
{
|
||||
model_p.reset(new pcl::SampleConsensusModelPlane<pcl::PointXYZ> (cloud));
|
||||
break;
|
||||
}
|
||||
case SACMODEL_SPHERE:
|
||||
{
|
||||
model_p.reset(new pcl::SampleConsensusModelSphere<pcl::PointXYZ> (cloud));
|
||||
break;
|
||||
}
|
||||
case SACMODEL_CONE:
|
||||
{
|
||||
pcl::SampleConsensusModelCone<pcl::PointXYZ, pcl::Normal>::Ptr model_c
|
||||
(new pcl::SampleConsensusModelCone<pcl::PointXYZ, pcl::Normal> (cloud));
|
||||
model_c->setInputNormals(normals);
|
||||
model_p = model_c;
|
||||
break;
|
||||
}
|
||||
case SACMODEL_CYLINDER:
|
||||
{
|
||||
pcl::SampleConsensusModelCylinder<pcl::PointXYZ, pcl::Normal>::Ptr model_c
|
||||
(new pcl::SampleConsensusModelCylinder<pcl::PointXYZ, pcl::Normal> (cloud));
|
||||
model_c->setInputNormals(normals);
|
||||
model_p = model_c;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Base::RuntimeError("Unsupported SAC model");
|
||||
}
|
||||
|
||||
pcl::RandomSampleConsensus<pcl::PointXYZ> ransac (model_p);
|
||||
ransac.setDistanceThreshold (.01);
|
||||
ransac.computeModel();
|
||||
//ransac.getInliers(inliers);
|
||||
ransac.getInliers(model);
|
||||
//ransac.getModel (model);
|
||||
Eigen::VectorXf model_p_coefficients;
|
||||
ransac.getModelCoefficients (model_p_coefficients);
|
||||
|
||||
@@ -34,11 +34,24 @@ namespace Reen {
|
||||
class SampleConsensus
|
||||
{
|
||||
public:
|
||||
SampleConsensus(const Points::PointKernel&);
|
||||
double perform(std::vector<float>& parameters);
|
||||
enum SacModel
|
||||
{
|
||||
SACMODEL_PLANE,
|
||||
SACMODEL_LINE,
|
||||
SACMODEL_CIRCLE2D,
|
||||
SACMODEL_CIRCLE3D,
|
||||
SACMODEL_SPHERE,
|
||||
SACMODEL_CYLINDER,
|
||||
SACMODEL_CONE,
|
||||
SACMODEL_TORUS,
|
||||
};
|
||||
SampleConsensus(SacModel sac, const Points::PointKernel&, const std::vector<Base::Vector3d>&);
|
||||
double perform(std::vector<float>& parameters, std::vector<int>& model);
|
||||
|
||||
private:
|
||||
SacModel mySac;
|
||||
const Points::PointKernel& myPoints;
|
||||
const std::vector<Base::Vector3d>& myNormals;
|
||||
};
|
||||
|
||||
} // namespace Reen
|
||||
|
||||
Reference in New Issue
Block a user