Python中的线条平滑算法?

3 投票
2 回答
13732 浏览
提问于 2025-04-17 17:42

我正在研究线条简化,这个技术可以用来从大规模地图生成小规模的道路网络地图。我使用了两种操作和两种算法。这些工作是用Python编程语言完成的,使用了shapefile库,主要处理二维的矢量数据。

操作包括:选择和淘汰。

在选择时,我设定了一些条件,比如选择所有宽度超过7米的道路,这些条件与道路的属性特征有关。

淘汰的方式也是类似,比如淘汰所有宽度小于5米的道路。

到目前为止,这些操作没有遇到太多问题。

在完成选择和淘汰操作后,我们会得到一个形状文件,里面包含符合条件的道路。

我使用了两种算法,分别是线条简化和线条平滑。

在线条简化方面,我使用了Douglas-Peucker算法。这个算法会处理矢量数据(坐标),根据设定的容差来去掉一些点。我也是用Python来实现这个算法。得到简化后的线条后,还需要进行一些编辑,比如线条平滑。

在平滑方面,我使用了高斯算法,但它返回了一些我不理解的错误,因为我在编程方面还是个新手。

import numpy

 ### This is the Gaussian data smoothing function I wrote ###  

def smoothListGaussian(list1,degree):  

     window=degree*2-1  

     weight=numpy.array([1.0]*window)
     print weight

     weightGauss=[]  

     for i in range(window):  

         i=i-degree+1  

         frac=i/float(window)  

         gauss=1/(numpy.exp((4*(frac))**2))  

         weightGauss.append(gauss)  

     print weightGauss
     weight=numpy.array(weightGauss)*weight
     print weight
     print len(list1)-window


     smoothed=[0.0]*(len(list1)-window)
     print smoothed

     for i in range(len(smoothed)):  

         smoothed[i]=sum(numpy.array(list1[i:i+window])*weight)/sum(weight)  

     return smoothed


a=[[78.03881018900006, 30.315651467000066], [78.044901609000078, 30.31512798600005], [78.04927981700007, 30.312510579000048], [78.050041244000056, 30.301755415000059], [78.072646124000073, 30.281720353000082], [78.07902308000007, 30.273344651000059]]

smoothListGaussian(a,3)

如果有任何想法,请告诉我。

或者如果有其他的Python算法可以用来平滑矢量数据中的线条,利用每个点的坐标,也请分享一下。

非常感谢大家的回答!

2 个回答

16

你可以通过以下代码来平滑路径:

from scipy.ndimage import gaussian_filter1d
import numpy as np
a=np.array([[78.03881018900006, 30.315651467000066],
 [78.044901609000078, 30.31512798600005], 
 [78.04927981700007, 30.312510579000048],
 [78.050041244000056, 30.301755415000059],
 [78.072646124000073, 30.281720353000082],
 [78.07902308000007, 30.273344651000059]])

x, y = a.T
t = np.linspace(0, 1, len(x))
t2 = np.linspace(0, 1, 100)

x2 = np.interp(t2, t, x)
y2 = np.interp(t2, t, y)
sigma = 10
x3 = gaussian_filter1d(x2, sigma)
y3 = gaussian_filter1d(y2, sigma)

x4 = np.interp(t, t2, x3)
y4 = np.interp(t, t2, y3)

plot(x, y, "o-", lw=2)
plot(x3, y3, "r", lw=2)
plot(x4, y4, "o", lw=2)

这里是结果:蓝色的点是原始数据,红色的曲线是经过平滑处理后的曲线,它包含了很多点。如果你想让点的数量和原始数据一样,可以从红色曲线中取样,得到绿色的点。

你可以设置 sigma 来改变 gaussian_filter1d() 的平滑程度。

enter image description here

1

我猜你是从这里拿的代码。你应该注意到,这段代码是针对一维数据点的,而不是多维数据点。

我对高斯平滑算法了解不多,但在简单看了一下你的代码后,我觉得你可能想要做的是这个(我不确定这样做是否能得到你想要的结果)。把你代码的最后部分替换成以下代码:

smoothed=[0.0,0.0]*(len(list1)-window)
print smoothed

for i in range(len(smoothed)):
    smoothing=[0.0,0.0]
    for e,w in zip(list1[i:i+window],weight):
        smoothing=smoothing+numpy.multiply(e,w)
    smoothed[i]=smoothing/sum(weight)

撰写回答