10 #include <Eigen/Dense>
15 #include <unordered_set>
40 const Eigen::Vector4d plane_model,
41 std::vector<size_t> &inliers,
42 double distance_threshold,
46 for (
size_t idx = 0; idx <
points.size(); ++idx) {
49 double distance = std::abs(plane_model.dot(point));
53 inliers.emplace_back(idx);
57 size_t inlier_num = inliers.size();
58 if (inlier_num == 0) {
62 result.fitness_ = (double)inlier_num / (
double)
points.size();
63 result.inlier_rmse_ = error / std::sqrt((
double)inlier_num);
69 const std::vector<Eigen::Vector3d> &
points,
70 const Eigen::Vector4d plane_model,
71 std::vector<size_t> &inliers,
72 double distance_threshold,
76 distance_threshold, error);
86 const std::vector<size_t> &inliers) {
88 for (
size_t idx : inliers) {
92 sum /=
static_cast<double>(inliers.size());
97 for (
size_t idx : inliers) {
112 if (det_x > det_y && det_x > det_z) {
113 abc =
CCVector3(det_x, xz * yz - xy * zz, xy * yz - xz * yy);
114 }
else if (det_y > det_z) {
115 abc =
CCVector3(xz * yz - xy * zz, det_y, xy * xz - yz * xx);
117 abc =
CCVector3(xy * yz - xz * yy, xy * xz - yz * xx, det_z);
123 return Eigen::Vector4d(0, 0, 0, 0);
126 double d =
static_cast<double>(-abc.
dot(centroid));
127 return Eigen::Vector4d(abc(0), abc(1), abc(2), d);
131 const std::vector<size_t> &inliers) {
140 const double distance_threshold ,
142 const int num_iterations )
const {
147 Eigen::Vector4d plane_model = Eigen::Vector4d(0, 0, 0, 0);
149 Eigen::Vector4d best_plane_model = Eigen::Vector4d(0, 0, 0, 0);
152 std::vector<size_t> inliers;
154 size_t num_points =
size();
155 std::vector<size_t> indices(num_points);
156 std::iota(std::begin(indices), std::end(indices), 0);
158 std::random_device rd;
159 std::mt19937 rng(rd());
164 "ransac_n should be set to higher than or equal to 3.");
165 return std::make_tuple(best_plane_model, inliers);
167 if (num_points < std::size_t(ransac_n)) {
169 "There must be at least 'ransac_n' points.");
170 return std::make_tuple(best_plane_model, inliers);
173 for (
int itr = 0; itr < num_iterations; itr++) {
174 for (std::size_t i = 0; i < std::size_t(ransac_n); ++i) {
175 std::swap(indices[i], indices[rng() % num_points]);
178 for (std::size_t idx = 0; idx < std::size_t(ransac_n); ++idx) {
179 inliers.emplace_back(indices[idx]);
185 getEigenPoint(inliers[1]),
186 getEigenPoint(inliers[2]));
187 if (plane_model.isZero(0)) {
194 getPoints(), plane_model, inliers, distance_threshold, error);
195 if (this_result.fitness_ >
result.fitness_ ||
197 std::abs(this_result.fitness_ -
result.fitness_)) &&
198 this_result.inlier_rmse_ <
result.inlier_rmse_)) {
200 best_plane_model = plane_model;
206 for (std::size_t idx = 0; idx <
size(); ++idx) {
207 Eigen::Vector4d point(m_points[idx](0), m_points[idx](1),
208 m_points[idx](2), 1);
209 double distance = std::abs(best_plane_model.dot(point));
211 if (
distance < distance_threshold) {
212 inliers.emplace_back(idx);
220 "RANSAC | Inliers: {:d}, Fitness: {:e}, RMSE: {:e}", inliers.size(),
222 return std::make_tuple(best_plane_model, inliers);
229 "[CropPointCloud::Crop] ccBBox either has zeros "
230 "size, or has wrong bounds.");
239 "[CropPointCloud::Crop] ecvOrientedBBox either has zeros "
240 "size, or has wrong bounds.");
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Type dot(const Vector3Tpl &v) const
Dot product.
Type norm() const
Returns vector norm.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
static std::vector< Eigen::Matrix< double, 3, 1 > > fromArrayContainer(const std::vector< Vector3Tpl< PointCoordinateType >> &container)
static Eigen::Vector4d ComputeTrianglePlane(const Eigen::Vector3d &p0, const Eigen::Vector3d &p1, const Eigen::Vector3d &p2)
std::tuple< Eigen::Vector4d, std::vector< size_t > > SegmentPlane(const double distance_threshold=0.01, const int ransac_n=3, const int num_iterations=100) const
Segment ccPointCloud plane using the RANSAC algorithm.
std::shared_ptr< ccPointCloud > Crop(const ccBBox &bbox) const
Function to crop ccPointCloud into output ccPointCloud.
std::vector< std::size_t > GetPointIndicesWithinBoundingBox(const std::vector< Eigen::Vector3d > &points) const
bool isValid() const
Returns whether bounding box is valid or not.
std::vector< size_t > GetPointIndicesWithinBoundingBox(const std::vector< Eigen::Vector3d > &points) const
Return indices to points that are within the bounding box.
Stores the current best result in the RANSAC algorithm.
virtual bool IsEmpty() const override
static double distance(T *pot1, T *pot2)
Eigen::Vector4d GetPlaneFromPoints(const std::vector< CCVector3 > &points, const std::vector< size_t > &inliers)
RANSACResult EvaluateRANSACBasedOnDistance(const std::vector< CCVector3 > &points, const Eigen::Vector4d plane_model, std::vector< size_t > &inliers, double distance_threshold, double error)
void SelectByIndex(benchmark::State &state, bool remove_duplicates, const core::Device &device)
Generic file read and write utility for python interface.
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.