写的代码太多了,我也不记得哪个写过哪个没有写过,好惨,找了半天才找到,既然如此,就记录一下咯
一样的先申明一哈哈,ccPointCloud是cloudcompare软件里面自带的类型,就是存所有点的,反正都把它转成pcl的类型进行处理
//格式转换:ccPointCloud to pcl:PointCloud
void ccPointCloud2PointCloud(ccPointCloud *input,pcl::PointCloud<pcl::PointXYZ>::Ptr output)
{
long npts=input->size();
output->reserve(npts+1);
for(long i=0;i<npts;i++)
{
const CCVector3* P_Residual = input->getPoint(i);
pcl::PointXYZ *p =new pcl::PointXYZ;
p->x = P_Residual->x;
p->y = P_Residual->y;
p->z = P_Residual->z;
output->push_back(*p);
delete []p;
}
}
//基于种子填充算法进行空间连通性聚类,判断每个类的密度
void ConnectedComponentAnalysis_filtering(ccPointCloud *input,ccPointCloud *output,ccPointCloud *output_1,double Td,double Th,int k,int longdis,double fitering_density)
{
//输入点云数量
long npts=input->size();
//将点云数据类型转换为pcl可处理的pcl::PointCloud<pcl::PointXYZ>::Ptr类型
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_r(new pcl::PointCloud<pcl::PointXYZ>());
ccPointCloud2PointCloud(input,cloud_r);
//声明一个容器,作为栈存储满足条件的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_l(new pcl::PointCloud<pcl::PointXYZ>());
//对输入的点云数据创建k-d树
pcl::KdTreeFLANN<pcl::PointXYZ> tree_b;
tree_b.setInputCloud(cloud_r);
//对每个点云给一个标记lable,初始值为0
int *flag=new int[npts+1];
for(int i=0;i<npts;i++)
flag[i]=0;
output->reserve(npts+1);
output_1->reserve(npts+1);
int lable=1;//标记值
double dis,dh;//距离和高差
for(long i=0;i<npts;i++)
{
//对于每一个点,若标记值为0,则搜索邻近区域
if(flag[i]==0)
{
//当前点入栈并标记
pcl::PointXYZ pts_add=cloud_r->at(i);
cloud_l->push_back(pts_add);
flag[i]=lable;
std::vector<int> pointIdxNKNSearch(k);//用来存储k个点
std::vector<float> pointNKNSquaredDistance(k);//用来存储每个点到样点的距离
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_output(new pcl::PointCloud<pcl::PointXYZ>());
//如果栈不为空,搜索当前点的k个邻近点,如果满足距离和高差均小于阈值且没有被标记,则进栈并标记
while(!cloud_l->empty())
{
//指向栈底的数据
pcl::PointCloud<pcl::PointXYZ>::iterator index=cloud_l->begin();
pcl::PointXYZ pt_now;
pt_now.x = index->x;
pt_now.y = index->y;
pt_now.z = index->z;
//在数据删除之前存储
cloud_output->push_back(pt_now);
cloud_l->erase(index);
if(tree_b.nearestKSearch(pt_now,k, pointIdxNKNSearch, pointNKNSquaredDistance)>0)
{
int closet_point=0;
for(long j=0;(j<k);j++)
{
//对所有邻近点,判断如果满足距离和高差均小于阈值且没有被标记,则进栈并标记
pcl::PointXYZ pp=cloud_r->points[pointIdxNKNSearch[j]];
dis=sqrt(pointNKNSquaredDistance[j]);
dh=fabs(pt_now.z-pp.z);
//这里聚类的时候我设置了各种五花八门的条件,反正根据自己的要求设置条件就可以了
if(dh<Th && dis<Td && flag[pointIdxNKNSearch[j]]==0 )//&& fabs(pp.z-h_ave)<5
{
cloud_l->push_back(pp);
flag[pointIdxNKNSearch[j]]=lable;
}
}
}
}
if(cloud_output->size()<10)
continue;
ccPointCloud *cc_linepts=new ccPointCloud;
PointCloud2ccPointCloud(cloud_output,cc_linepts);
//对不同直线赋予不同的颜色属性
int col[3];
col[0] = int(float(255)*float(rand())/float(RAND_MAX));
col[1] = int(float(255)*float(rand())/float(RAND_MAX));
col[2] = int(float(255)*float(rand())/float(RAND_MAX));
cc_linepts->setRGBColor(col[0],col[1],col[2]);
*output_1+=cc_linepts;
delete[]cc_linepts;
cc_linepts=NULL;
lable++;
}
}
delete[]flag;
}
就是用了一个栈吧,进站出站,原理来说还是很简单的,尽管当时写的时候想了好久才搞明白,反正当初师兄跟我也是这么说的,结果图:就是这个样子了,不同的颜色就是不同的类别,只是这个类别是根据连通性来分的