噪声的来源:
对于4D毫米波雷达的前后两帧点云数据进行去噪,可以采用多种方法。首先,需要了解点云数据的噪声来源,可能是由于硬件限制、环境干扰或目标本身的反射特性等因素造成的。噪声点通常包括漂移点、孤立点、冗余点和混杂点等。
参考学习:
十种滤波算法的Python实现_控制十个数据,先进先出-CSDN博客
去噪方法可以分为传统方法和基于深度学习的方法:
以4D毫米波的平面和三维点云为例:
点云效果如下:
滤波测试结果:
中值平均滤波法:
中值平均滤波法(Median Mean Filter)是一种常见的信号处理滤波方法,结合了中值滤波和均值滤波的特点。它的基本思想是对信号进行中值滤波和均值滤波的结合,以平衡两种滤波方法的优缺点。
这种滤波方法的步骤通常包括:
- 对信号进行中值滤波,以消除噪声对信号的影响。
- 对中值滤波后的信号再进行均值滤波,以保留信号的整体特征。
结果:
左边是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
结论:
能够具有一些效果。