自学内容网 自学内容网

无人机避障——4D毫米波雷达点云滤波去噪(四)

噪声的来源:

对于4D毫米波雷达的前后两帧点云数据进行去噪,可以采用多种方法。首先,需要了解点云数据的噪声来源,可能是由于硬件限制、环境干扰或目标本身的反射特性等因素造成的。噪声点通常包括漂移点、孤立点、冗余点和混杂点等。

参考学习:

十种滤波算法的Python实现_控制十个数据,先进先出-CSDN博客

去噪方法可以分为传统方法和基于深度学习的方法:

以4D毫米波的平面和三维点云为例: 

点云效果如下:

 

滤波测试结果:

中值平均滤波法:

中值平均滤波法(Median Mean Filter)是一种常见的信号处理滤波方法,结合了中值滤波和均值滤波的特点。它的基本思想是对信号进行中值滤波和均值滤波的结合,以平衡两种滤波方法的优缺点。

这种滤波方法的步骤通常包括:

  1. 对信号进行中值滤波,以消除噪声对信号的影响。
  2. 对中值滤波后的信号再进行均值滤波,以保留信号的整体特征
结果:

左边是4D雷达点云,右边是滤波之后的效果

pre为10 

pre为5 

改变左边雷达点云,观察右边滤波效果。

[注意]:得看看平面的效果!!!

pre = 10

pre = 5

结论:

有一定的去噪能力,但是感觉滤波能力还不太够

代码: 
def adjust_array_size(points, per):
    """
    调整数组的大小,使其长度为 per 的倍数。

    参数:
    points (numpy.ndarray): 输入的点数组。
    per (int): 每个分组的大小。

    返回:
    numpy.ndarray: 调整大小后的点数组。
    """
    num_points = len(points)  # 获取点数组的长度
    print('调整之前点的数目:',num_points)
    remainder = num_points % per  # 计算点数组长度对 per 的余数
    print('remainder:',remainder)
    if remainder != 0:  # 如果余数不为零,说明需要调整数组大小
        points = points[:-remainder]  # 删除多余的点
        print("删除")

    return points  # 返回调整后的点数组

def MedianAverage3D(points, per):
    """
    对三维点数组进行中值平均去噪。

    参数:
    points (numpy.ndarray): 输入的三维点数组。
    per (int): 每个分组的大小。

    返回:
    numpy.ndarray: 去噪后的点数组。
    """
    points = adjust_array_size(points, per)  # 调整点数组的大小,使其长度为 per 的倍数
    
    num_points = len(points)  # 获取调整后点数组的长度
    num_groups = num_points // per  # 计算分组的数量
    
    # 确保 points 数组的大小是 per 的倍数
    if num_points != num_groups * per:
        raise ValueError(f"The number of points ({num_points}) is not a multiple of per ({per}).")
    
    points_reshaped = points.reshape((num_groups, per, 3))  # 将点数组重塑为 (num_groups, per, 3) 的形状

    denoised_points = np.zeros((num_points, 3))  # 初始化去噪后的点数组

    for i in range(num_groups):  # 遍历每个分组
        for j in range(3):  # 遍历每个通道(x, y, z)
            channel = points_reshaped[i, :, j]  # 获取当前分组的当前通道数据
            # print('channel:',channel)
            # 检查数组大小,确保在删除最大值和最小值后仍然有数据点
            if len(channel) > 2:
                # 检查 channel 中的元素是否都相同
            
                if np.all(channel == channel[0]):
                    # 如果所有元素都相同,则不进行删除操作
                    # print("运行到这1!!!")
                    denoised_points[i*per:(i+1)*per, j] = channel[0]
                    
                else:
                    # print("运行到这2!!!")
                    max_indices = np.where(channel == channel.max())[0]
                    min_indices = np.where(channel == channel.min())[0]
                    # print("max_indices1:",max_indices)
                    # print("min_indices1:",min_indices)                 
                    # 合并需要删除的索引
                    indices_to_delete = np.unique(np.concatenate((max_indices, min_indices)))                    
                    # 删除最大值和最小值
                    channel = np.delete(channel, indices_to_delete)
                    
                    # 如果删除后数组大小为零,则使用原始数据
                    if len(channel) == 0:
                        channel = points_reshaped[i, :, j]
                    
                    denoised_points[i*per:(i+1)*per, j] = np.mean(channel)  # 计算剩余数据的均值,并赋值给去噪后的点数组
            else:
                denoised_points[i*per:(i+1)*per, j] = np.mean(channel)  # 如果数据点不足,直接使用均值

    return denoised_points  # 返回去噪后的点数组

递推平均滤波法:

递推平均滤波(也称为移动平均滤波或滑动平均滤波)是一种常用的信号处理技术,用于减少数据中的随机噪声,平滑数据序列。以下是递推平均滤波的特点以及它的优缺点:

 特点:
1. **简单易实现**:递推平均滤波的算法简单,容易在硬件或软件中实现。
2. **时域滤波**:它在时域内对信号进行处理,不需要像频域滤波那样进行傅里叶变换。
3. **局部平均**:通过对数据序列中相邻的一组数据点求平均值,实现局部平滑。
4. **递推计算**:每个点的平均值是基于前一个平均值和当前窗口的数据点计算的,这样可以减少计算量。

优点:
1. **去噪效果好**:对于随机噪声,递推平均滤波能够有效地减少数据的波动,使信号更加平滑。
2. **稳定性高**:由于是局部操作,对数据的局部变化不敏感,因此滤波结果比较稳定。
3. **实时处理**:适合于在线实时处理,因为每个新数据点的滤波结果可以快速计算出来。
4. **无需训练**:不需要像一些自适应滤波器那样进行训练或参数调整。

缺点:
1. **引入延迟**:由于需要考虑当前点和前面的点,所以滤波后的数据会有一定的时间延迟。
2. **边缘效应**:在数据序列的开始和结束部分,无法形成完整的窗口,这可能导致边缘处的数据不够平滑。
3. **不能消除周期性噪声**:如果噪声的周期与窗口大小相匹配,递推平均滤波可能无法有效去除这种噪声。
4. **信号失真**:对于非平稳信号,递推平均滤波可能会导致信号的波形失真,尤其是在信号的快速变化区域。
5. **参数依赖**:滤波效果依赖于窗口大小的选择,窗口太大可能导致信号过度平滑,失去细节;窗口太小则去噪效果不佳。

在使用递推平均滤波时,需要根据具体的应用场景和数据特性来选择合适的窗口大小。过大的窗口会消除信号中的重要细节,而过小的窗口则可能无法有效去除噪声。此外,对于非静态信号或非线性信号,递推平均滤波可能不是最佳选择,可能需要考虑更复杂的滤波方法。

结果:

pre = 15

pre = 10

pre = 5

结论:

去噪声比较弱,但是其有产生连续性规则性的点,肯定没法直接用的

代码:
# 递推平均滤波
def SlidingAverage(inputs, per):
    # 如果输入数组的行数不能被'per'整除,则去掉余数部分
    if inputs.shape[0] % per != 0:
        # 去掉不能整除的部分
        inputs = inputs[:inputs.shape[0] // per * per]
    
    # 初始化一个空数组来存储滤波后的结果
    filtered = np.zeros_like(inputs)
    
    # 遍历每个点,计算递推平均
    for i in range(inputs.shape[0]):
        # 计算当前点的起始索引
        start_idx = max(i - per + 1, 0)
        # 计算当前点的结束索引
        end_idx = i + 1
        # 计算窗口内的数据
        window = inputs[start_idx:end_idx]
        # 计算平均值
        filtered[i] = window.mean(axis=0)
    
    # 返回滤波后的数组
    return filtered

中值平均滤波+递推平均滤波法:

结果:

中值:pre = 10

+

递推:pre = 5

中值:pre = 15

+

递推:pre = 5

递推:pre = 5

+

中值:pre = 10

[注意]:这个数据可以用

递推:pre = 5

+

中值:pre =  5

递推:pre = 5

+

中值:pre =  7

递推:pre = 5

+

中值:pre =  13

递推:pre = 5

+

中值:pre =  15

结论:

能够具有一些效果。


原文地址:https://blog.csdn.net/weixin_45390670/article/details/142766373

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!