我正在处理点云,即点的向量,作为计算的结果,其包含重复点(高达云的大小的10%).
我的实现是根据x,y和z值对这些点进行排序,然后使用该std::unique
函数.然而,生成的云仍然包含重复项,即使排序本身似乎有效.
这是至关重要的代码
bool comparePoint(pcl::PointXYZINormal p1, pcl::PointXYZINormal p2){ if (p1.x != p2.x) return p1.x > p2.x; else if (p1.y != p2.y) return p1.y > p2.y; else return p1.z > p2.z; } bool equalPoint(pcl::PointXYZINormal p1, pcl::PointXYZINormal p2){ if (p1.x == p2.x && p1.y == p2.y && p1.z == p2.z) return true; return false; } void KDsearch::cullDuplePoints(){ std::sort(points.begin(), points.end(), comparePoint); std::unique(points.begin(), points.end(), equalPoint); }
这里是输出pointcloud(x,y和z坐标)的部分提取:
1.96828 -535.09515 2794.8391 1.96627 -636.95264 2914.0366 1.96627 -636.95264 2914.0366 1.9651 108.77433 2350.9841 1.9651 108.77433 2350.9841 1.9642299 -206.19427 5618.4629 1.9642299 -206.19427 5618.4629 1.96386 -1880.3784 1346.0654
独特的不正常工作还是在我的平等条件下有错误?
点本身也包含普通坐标,但它们对于剔除并不重要,所以我没有在代码中使用它们.
std::unique
不移除任何东西,它只移动元素并返回修改后的集合中唯一间隔"过去"的迭代器.
(未指定过去返回迭代器的集合的实际内容.)
您需要明确删除重复项:
std::sort(points.begin(), points.end(), comparePoint); auto unique_end = std::unique(points.begin(), points.end(), equalPoint); points.erase(unique_end, points.end());
您还需要注意浮点比较.
你的问题是,比较浮点数是否相等总是一项艰难的工作.你可能会发现你的分数(例如)实际上是:
1.965100000001 108.77433 2350.9841 1.965099999999 108.77433 2350.9841
......那些不平等.
如果你想将点数视为"相等",如果它们在0.00001之内,则会出现"平等"条件不可传递的问题.(0.0000,0,0)"接近"(0.000009999,0,0)和(-0.00009999,0,0),但后两个点彼此"远".这是一般难以解决的问题.祝好运!
如果您对坐标的值有所了解(例如,它们以毫米为单位,并且值精确到100纳米),则可以舍入到最接近的100 nm,并存储很长的时间.所以:
struct IntPoint { const static double ScaleFactor = 10000; long long x,y,z; IntPoint(const pcl::PointXYZINormal &p) : x(llround(p.x*ScaleFactor )) , y(llround(p.y*ScaleFactor )) , z(llround(p.z*ScaleFactor )) {} };
将您的点云转换为IntPoint,然后您的sort + unique(+ erase)应该有效.