分割聚类的细节

depth cluster

1.关于depth_cluster的列数选择

首先建立一个vector _col_angles把360/870的分隔度数放到vector里面

2.进入CloudProjection()函数

新建各种图,_depth_image/_xy_image/_z_image/_label_image
点云数据都放在

# 这个data每一个格子都保存list(list存的是点云的索引)
PointMatrix data = PointMatrix(_num_beams, PointColumn(32));
// vector < vector<list> > 点的Matrix
using PointMatrix = std::vector<PointColumn>;

# 实体点云在cloud里面
Cloud::Ptr cloud;
cloud = make_shared<Cloud>();
cloud->push_back(point_tem);

# data中点云为于深度图某行某列的计算
// 确定了列数
size_t bin_cols = this->ColFromAngle(temp_angle_cols);
found = upper_bound(vec.begin(), vec.end(), val) - vec.begin()// 查找[first, last)区域中第一个大于 val 的元素
// 先列再行
data[bin_cols][bin_rows].points().push_back(index);
3.CreateAngleImage()
// d_xy之差
float dx = fabs(_xy_image.at<float>(r, c) - _xy_image.at<float>(r - 1, c));

// d_z之差
float dz = fabs(_z_image.at<float>(r, c) - _z_image.at<float>(r - 1, c));
4.BFS搜索分割、聚类
  • 分割
  1. 队列的第一个点是满足angle<45,后续邻居点加入是看是否满足差值小于ground_remove_angle=5
  • 聚类
  1. 队列的第一个点是遍历整个非地面点云图,访问过的加visited标记, 在bfs外面加一个label = label + 1; // 聚类编号的增加
  2. 聚类邻居点是否加入阈值是看beta:
alpha=hres或vres // 同一行邻居点或者同一列邻居点
float beta = (std::atan2((d2 * sin(alpha * M_PI / 180.0)),(d1 - d2 * cos(alpha * M_PI / 180.0)))) *
180.0 / M_PI; // 聚类部分的阈值判断 beta为度数
fabs(beta) > angle_tollerance=8 # 大于这个角度为一类

在这里插入图片描述

cvc_cluster

1. 非地面点云(x,y,z)->(rou,theta,phi)

笛卡尔坐标转成极坐标系坐标+一个垂直角度方向上的度量

2.建立弯曲体素
  • 体素分割的分辨率是:
delta_rou=0.35(range)
delta_theta=1.2(300)
delta_phi=2(若是图达通就是40/2)
  • 每一个voxel有一个index编号
voxel_index=theta_id*rou_th(100m/0.35)+rou_id+
            phi_id*rou_th+theta_th(300)
  • 每一个体素存储的是点云的索引
Voxel vox;
vox.haspoint = true;
vox.index.push_back(i);
// (vector a).swap(veactor b)
将 myvector 容量缩减至目前数据量的大小
vox.index.swap(vox.index);
map_out.insert(make_pair(voxel_index, vox));
  • 遍历体素寻找邻居体素
// 在polar_index/range_index/azimuth_index(垂直角)的[-1 0 1]中寻找
neighborindex.push_back((px * (length + 1) + y) + z * (length + 1) * (width + 1));
// 寻找时continue的情况:
// 邻域的maxrange是50,阈值
// 即邻居体素的索引大于
if (y < 0 || y > round((50 - minrange) / deltaR))
{
  continue;
}
# 当遍历每个点,知道它的体素索引,找领域体素,如上所示
find_neighbors(polar_index, range_index, azimuth_index, neighborid);
# 得到的neighborid为邻域索引,还得去之前的map<voxel_index, Voxel>中去找,有这个voxel_index的才能被作为当前voxel的邻居voxel

* 当前点和邻居点聚类编号的更新
mergeClusters(cluster_indices, oc, nc);
# cluster_indices和点数一样size的vector
# oc、nc分别是本点和邻居点的id
# 若oc、nc都为-1,则current_cluster++编号
# 若oc、nc有一个为-1,以不为-1的更新
# 若oc、nc都不为-1,以后者更新id
for (int i = 0; i < cluster_indices.size(); i++)
{
  // 对所有聚类编号进行更新,以邻居点的id来更新
  if (cluster_indices[i] == idx1)
  {
    # 用查并集的思路来看,这个增加了复杂度,应该要看是idx1还是idx2的点数谁多来决定
    cluster_indices[i] = idx2;
  }
}
  • 提取同一id的聚类点云
# 点云都提取到这个map里面
std::unordered_map<uint16_t, Cloud> _obj_cluster;
// 聚类id已经出来,开始筛选
for (size_t i = 0; i < cluster_index.size(); i++)
{
  const auto point = _except_ground_cloud->points()[i];
  # 因为是map所以聚类编号相同即key值相同,那么这些点就被push_back()到一起了
  _obj_cluster[cluster_index.at(i)].push_back(point);
}

透视投影的方法

1. 数据预处理,即透视投影

这个主要是根据选型lidar横纵像素点的比例(FOV以及分辨率:具体如何计算的:每行和每列的点云的比例:65//0.17与40/0.13的比例=4:3),选择图像像素尺寸(1200900 800**600 400300),测试不同的像素尺寸
已知一个合适的像素尺寸,以及FOV,计算
1)三维转图像中心公制坐标(小孔成像投影, 相似三角形)
2)公制坐标转图像左上角坐标(平移)

而进行这个透视投影的前提是,lidar已经转到camera的坐标系了,如果没有的话,需要外参参数进行坐标转换,主要包含一个旋转矩阵(由绕x,y,z的旋转矩阵)和一个平移矩阵
这个坐标转换通过矩阵相乘的形式就可以完成,前提是:先化成其次坐标:欧几里得坐标->齐次坐标

齐次坐标的优点之一是,他们可以通过级联几个矩阵-矢量乘法来轻松组合多个变换

地面分割

在这里插入图片描述
过程描述:
1)依次遍历图像每一列,从上往下,搜索像素点A点(像素点A可能有多个点云)的下一个邻域点B(阈值为往下50格内),构建向量:
B A → = ( A 的 坐 标 − B 的 坐 标 ) \overrightarrow {BA}=(A的坐标-B的坐标) BA =(AB)
求向量BA与竖直向上z轴向量的夹角theta, 若theta<60,则像素点A点加入障碍物点集合,continue,继续遍历这一列的剩余点,直到图像上所有像素点都被遍历完,得到一个障碍物像素点集合,下一步就是对这个像素点集合进行聚类/连通域分析

连通域分析聚类

在这里插入图片描述
与障碍物像素点搜索过程中是纵向遍历每一列不同的是,在连通域分析中,遍历图像的每一行
1)对某一个像素点而言,分析它左右两边各8个像素格,上面2行的像素格(包含本格),对邻居点与本像素点的距离进行计算(是里面点云的坐标之间的欧几里得距离, 每个像素点保存一个最近的点,其他的点就舍弃了),如果:
d i s t = n o r m ( d i f f ) < c l u s t e r D i s t = 1 m dist=norm(diff)<clusterDist=1m dist=norm(diff)<clusterDist=1m
则(cy,cx)被视为与当前像素格(y,x)为一类
2)被视为一类,进行聚类编号的更新

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值