Проблема при использовании Efficient_Ransac в CGAL - PullRequest
0 голосов
/ 15 октября 2019

Я хочу использовать реализацию CGAL Efficient Ransac , но всякий раз, когда я пытаюсь установить свои собственные параметры, алгоритм больше не обнаруживает никакой формы.

Эта работа связанак реализации Polyfit в CGAL. Я хочу точно настроить обнаружение самолета, чтобы увидеть, как оно влияет на алгоритм. Когда я использую стандартный вызов ransac.detect(), он работает отлично. Однако, когда я хочу установить свои собственные параметры , он просто не находит плоскость, даже если я установил для них вручную значения по умолчанию.

Вот мой код, тесно связанный с этот пример

#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.

Может ли кто-нибудь помочь мне установить мои собственные параметры для определения формы Ransac?

1 Ответ

0 голосов
/ 16 октября 2019

Однако, когда я хочу установить свои собственные параметры, он просто не находит никакой плоскости, даже если я устанавливаю их вручную на значения по умолчанию.

Просто чтобы быть уверенным:«установка вручную значений по умолчанию» - это не то, что вы делаете в коде, которым вы поделились.

Значения по умолчанию задокументированы как:

  • 1% от общего количества баллов для min_points, которое в вашем случае должно составлять около 1700 баллов, а не 100

  • 1% от диагонали ограничительной рамки для epsilon иcluster_epsilon. Для этого, очевидно, я не знаю, использовал ли это (0,01), поскольку у меня нет доступа к вашему набору точек, но если вы хотите воспроизвести значения по умолчанию, вы должны использовать CGAL::Bbox_3 объект в какой-то момент

Если вы используете эти значения, нет никаких причин, почему он должен вести себя иначе, чем без заданных параметров (если он не работает, то, пожалуйста, дайте мне знать, потому что естьможет быть ошибка).

...