20200919:骨折十天了,走路膝盖疼,有点烦。
一、DBSCAN(Density-Based Spatial Clustering of Applications with Noise)
https://baike.baidu.com/item/DBSCAN/4864716?fr=aladdin
(省的某些人嫌弃我不讲原理)
二、代码
分享给有需要的人,代码质量勿喷。
//system
#include <iostream>
#include <memory>
#include <random>
#include <cstdlib>
#include <ctime>
#define xjRandom(a,b) (rand()%(b-a)+a)
//Eigen
#include "Eigen/Dense"
//Open3D
#include "Open3D/Open3D.h"
/* DBSCAN聚类 */
void testOpen3D::pcClusterDBSCAN(const QString &pcPath)
{
int width = 700, height = 500;
auto cloud_ptr = std::make_shared<open3d::geometry::PointCloud>();
if (!open3d::io::ReadPointCloud(pcPath.toStdString(), *cloud_ptr)) { return; }
open3d::visualization::DrawGeometries({ cloud_ptr }, "Point Cloud 1", width, height);
/***** 邻域半径,点数阈值。返回每个点的label:噪点是-1 *****/
std::vector<int> vLabel = cloud_ptr->ClusterDBSCAN(0.2, 5, false);
//根据聚类数 产生随机颜色
int maxLabel = -2;
for each (int l in vLabel)
{
if (l>= maxLabel)
{
maxLabel = l;
}
}
std::vector<Eigen::Vector3d> vColor;
vColor.reserve(1+maxLabel);
srand((int)time(0));// 产生随机种子——用于赋色
for (int i = 0; i <= maxLabel; i++)
{
double r = xjRandom(0, 200);
double g = xjRandom(100, 256/2);
double b = xjRandom(50/2, 250);
r /= 255.0;
g /= 255.0;
b /= 255.0;
Eigen::Vector3d c = { r,g,b };
vColor.push_back(c);
}
//给每个点根据聚类体赋色
std::vector<Eigen::Vector3d> pcColor;
pcColor.reserve(vLabel.size());
for (int i = 0; i < vLabel.size(); i++)
{
int label = vLabel[i];
if (label==-1)
{
Eigen::Vector3d c = { 0,0,0 };//噪点:-1 黑色
pcColor.push_back(c);
}
else
{
Eigen::Vector3d c = vColor[label];
pcColor.push_back(c);
}
}
//赋色
cloud_ptr->colors_ = pcColor;
open3d::visualization::DrawGeometries({ cloud_ptr }, "DBSCAN聚类", width, height);
}
三、结果