在CGAL中使用Efficient_Ransac时遇到问题

问题描述 投票:0回答:1

我想使用CGAL的Efficient Ransac实现,但是每当我尝试设置自己的参数时,该算法就不再检测到任何形状。

这项工作与CGAL中的Polyfit implementation有关。我想微调平面检测,以查看其对算法的影响。当我使用标准调用ransac.detect()时,它可以正常工作。但是,当我要设置自己的parameters时,即使我手动将它们设置为默认值,也找不到任何平面。

这是我的代码,与this example密切相关

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/IO/read_xyz_points.h>
#include <CGAL/IO/Writer_OFF.h>
#include <CGAL/property_map.h> 
#include <CGAL/Surface_mesh.h>
#include <CGAL/Shape_detection/Efficient_RANSAC.h>
#include <CGAL/Polygonal_surface_reconstruction.h>

#ifdef CGAL_USE_SCIP

#include <CGAL/SCIP_mixed_integer_program_traits.h>
typedef CGAL::SCIP_mixed_integer_program_traits<double>         MIP_Solver;

#elif defined(CGAL_USE_GLPK)

#include <CGAL/GLPK_mixed_integer_program_traits.h>
typedef CGAL::GLPK_mixed_integer_program_traits<double>         MIP_Solver;

#endif

#if defined(CGAL_USE_GLPK) || defined(CGAL_USE_SCIP)
#include <CGAL/Timer.h>
#include <fstream>

typedef CGAL::Exact_predicates_inexact_constructions_kernel         Kernel;

typedef Kernel::Point_3                                             Point;
typedef Kernel::Vector_3                                            Vector;

// Point with normal, and plane index
typedef boost::tuple<Point, Vector, int>                            PNI;
typedef std::vector<PNI>                                            Point_vector;
typedef CGAL::Nth_of_tuple_property_map<0, PNI>                     Point_map;
typedef CGAL::Nth_of_tuple_property_map<1, PNI>                     Normal_map;
typedef CGAL::Nth_of_tuple_property_map<2, PNI>                     Plane_index_map;

typedef CGAL::Shape_detection::Efficient_RANSAC_traits<Kernel, Point_vector, Point_map, Normal_map>     Traits;

typedef CGAL::Shape_detection::Efficient_RANSAC<Traits>             Efficient_ransac;
typedef CGAL::Shape_detection::Plane<Traits>                        Plane;
typedef CGAL::Shape_detection::Point_to_shape_index_map<Traits>     Point_to_shape_index_map;

typedef CGAL::Polygonal_surface_reconstruction<Kernel>              Polygonal_surface_reconstruction;
typedef CGAL::Surface_mesh<Point>                                   Surface_mesh;


int main(int argc, char ** argv)
{
Point_vector points;

// Loads point set from a file.
const std::string &input_file = argv[1];
//const std::string input_file(input);
std::ifstream input_stream(input_file.c_str());
if (input_stream.fail()) {
    std::cerr << "failed open file \'" <<input_file << "\'" << std::endl;
    return EXIT_FAILURE;
}
std::cout << "Loading point cloud: " << input_file << "...";

CGAL::Timer t;
t.start();
if (!input_stream ||
    !CGAL::read_xyz_points(input_stream,
        std::back_inserter(points),
        CGAL::parameters::point_map(Point_map()).normal_map(Normal_map())))
{
    std::cerr << "Error: cannot read file " << input_file << std::endl;
    return EXIT_FAILURE;
}
else
    std::cout << " Done. " << points.size() << " points. Time: " << t.time() << " sec." << std::endl;

// Shape detection
Efficient_ransac ransac;
ransac.set_input(points);
ransac.add_shape_factory<Plane>();

std::cout << "Extracting planes...";
t.reset();

// Set parameters for shape detection.
Efficient_ransac::Parameters parameters;
// Set probability to miss the largest primitive at each iteration.
parameters.probability = 0.05;

// Detect shapes with at least 500 points.
parameters.min_points = 100;
// Set maximum Euclidean distance between a point and a shape.
parameters.epsilon = 0.01;

// Set maximum Euclidean distance between points to be clustered.
parameters.cluster_epsilon = 0.01;

// Set maximum normal deviation.
// 0.9 < dot(surface_normal, point_normal); 
parameters.normal_threshold = 0.9;   

// Detect shapes.
ransac.detect(parameters);
//ransac.detect();

Efficient_ransac::Plane_range planes = ransac.planes();
std::size_t num_planes = planes.size();

std::cout << " Done. " << num_planes << " planes extracted. Time: " << t.time() << " sec." << std::endl;

// Stores the plane index of each point as the third element of the tuple.
Point_to_shape_index_map shape_index_map(points, planes);
for (std::size_t i = 0; i < points.size(); ++i) {
    // Uses the get function from the property map that accesses the 3rd element of the tuple.
    int plane_index = get(shape_index_map, i);
    points[i].get<2>() = plane_index;
}

//////////////////////////////////////////////////////////////////////////

std::cout << "Generating candidate faces...";
t.reset();

Polygonal_surface_reconstruction algo(
    points,
    Point_map(),
    Normal_map(),
    Plane_index_map()
);

std::cout << " Done. Time: " << t.time() << " sec." << std::endl;

//////////////////////////////////////////////////////////////////////////

Surface_mesh model;

std::cout << "Reconstructing...";
t.reset();

if (!algo.reconstruct<MIP_Solver>(model)) {
    std::cerr << " Failed: " << algo.error_message() << std::endl;
    return EXIT_FAILURE;
}

const std::string& output_file(input_file+"_result.off");
std::ofstream output_stream(output_file.c_str());
if (output_stream && CGAL::write_off(output_stream, model))
    std::cout << " Done. Saved to " << output_file << ". Time: " << t.time() << " sec." << std::endl;
else {
    std::cerr << " Failed saving file." << std::endl;
    return EXIT_FAILURE;
}

//////////////////////////////////////////////////////////////////////////

// Also stores the candidate faces as a surface mesh to a file
Surface_mesh candidate_faces;
algo.output_candidate_faces(candidate_faces);
const std::string& candidate_faces_file(input_file+"_candidate_faces.off");
std::ofstream candidate_stream(candidate_faces_file.c_str());
if (candidate_stream && CGAL::write_off(candidate_stream, candidate_faces))
    std::cout << "Candidate faces saved to " << candidate_faces_file << "." << std::endl;

return EXIT_SUCCESS;
}


#else

int main(int, char**)
{
std::cerr << "This test requires either GLPK or SCIP.\n";
return EXIT_SUCCESS;
}

#endif  // defined(CGAL_USE_GLPK) || defined(CGAL_USE_SCIP)

启动后,我会收到以下消息:

Loading point cloud: Scene1/test.xyz... Done. 169064 points. Time: 0.428 sec.
Extracting planes... Done. 0 planes extracted. Time: 8.328 sec.
Generating candidate faces... Done. Time: 0.028 sec.
Reconstructing... Failed: at least 4 planes required to reconstruct a closed surface mesh (only 1 provided)

虽然在启动代码时具有此功能,但无参数的ransac检测功能:

Loading point cloud: Scene1/test.xyz... Done. 169064 points. Time: 0.448 sec.
Extracting planes... Done. 18 planes extracted. Time: 3.088 sec.
Generating candidate faces... Done. Time: 94.536 sec.
Reconstructing... Done. Saved to Scene1/test.xyz_result.off. Time: 30.28 sec.

有人可以帮我设置我自己的参数来检测神经形态吗?

c++ cgal ransac
1个回答
0
投票

但是,当我要设置自己的参数时,它根本找不到任何平面,即使我手动将它们设置为默认值。

请确保:“手动将它们设置为默认值”不是您在共享代码中所做的。

默认值为documented,为:

  • min_points的总点数的1%,在您的情况下应该为1700点左右,而不是100

  • epsiloncluster_epsilon的边界框对角线的1%。为此,显然我不知道这是否是您使用的(0.01),因为我无权访问您的点集,但是如果您想重现默认值,则应在某个点使用CGAL::Bbox_3对象] >

  • 如果使用这些值,没有理由不给出任何参数就表现不同(如果它不起作用,请告诉我,因为可能存在错误)。

© www.soinside.com 2019 - 2024. All rights reserved.