点云的种子填充算法来聚个类

写的代码太多了,我也不记得哪个写过哪个没有写过,好惨,找了半天才找到,既然如此,就记录一下咯

一样的先申明一哈哈,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;
}

就是用了一个栈吧,进站出站,原理来说还是很简单的,尽管当时写的时候想了好久才搞明白,反正当初师兄跟我也是这么说的,结果图:就是这个样子了,不同的颜色就是不同的类别,只是这个类别是根据连通性来分的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章