python 实现对三维点的高斯平滑(gaussion smooth), 主要是使用 Python中的 scipy.stats 这个统计函数。
函数说明
- scipy.stats.norm 属于统计函数,正常连续的随机变量,属于rv_continuous类的实例
其中,location(loc)关键字指定平均值。scale(scale)关键字指定标准偏差
- rvs(loc=0, scale=1, size=1, random_state=None) Random variates.
- pdf(x, loc=0, scale=1) 概率密度函数 Probability density function.
- logpdf(x, loc=0, scale=1) 概率密度函数的对数
- cdf(x, loc=0, scale=1) Cumulative distribution function累积分布函数
更多详细的说明,可以参考官网 scipy.stats.norm
示例代码:
import numpy as np
import scipy.stats as sta
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1)
x = np.linspace(sta.norm.ppf(0.01), sta.norm.ppf(0.99), 100)
ax.plot(x, sta.norm.pdf(x), 'r-', lw=5, alpha=0.6, label='norm pdf')
plt.show()
gaussian 平滑的函数
根据上面的一些函数,我们可以得到 gaussian 平滑的函数如下:
import numpy as np
import scipy.stats as sta
def gaussian_smooth_points(points, kernel_r, nsig=3):
""" 将 points 进行高斯平滑 """
smoothed_points = points.copy()
kernlen = kernel_r * 2 + 1
x = np.linspace(-nsig, nsig, kernlen + 1)
kern1d = np.diff(sta.norm.cdf(x))
kern1d = kern1d / kern1d.sum()
len_points = len(points)
for j in range(len_points):
if kernel_r < j < len_points - kernel_r:
sum_data = np.array([0.0, 0.0, 0.0], dtype=np.double)
for i in range(1, 2 * kernel_r + 1, 1):
idx = j + i - kernel_r - 1
sum_data += points[idx] * kern1d[i]
smoothed_points[j] = sum_data / (2 * kernel_r + 1)
return smoothed_points
if __name__ == '__main__':
points = [[1.0, 1.0, 1.0]] * 20
smoothed_points = gaussian_smooth_points(np.array(points), 3, 3)
print(smoothed_points)
结果如下:
[[1. 1. 1. ]
[1. 1. 1. ]
[1. 1. 1. ]
[1. 1. 1. ]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[0.14074968 0.14074968 0.14074968]
[1. 1. 1. ]
[1. 1. 1. ]
[1. 1. 1. ]]
其中,首尾的几个点,不够kernlen=3*2+1=7, 因此没有参与平滑。