我有一个DEM,我想对其进行平滑或概括以消除地形的极端情况(切掉峰和填谷)。理想情况下,我还希望控制“模糊性”的半径或水平。最后,我将需要一组从稍微模糊到真正模糊的栅格。(理论上,最模糊的是所有值的算术平均值的恒定栅格)。
我可以使用任何工具或方法(基于Esri,GDAL,GRASS)吗?我需要在家烘烤自己的高斯模糊例程吗?我可以使用低通滤波器(例如ArcGIS的filter),如果是这样,我是否需要运行多次以获取大半径的效果?
我有一个DEM,我想对其进行平滑或概括以消除地形的极端情况(切掉峰和填谷)。理想情况下,我还希望控制“模糊性”的半径或水平。最后,我将需要一组从稍微模糊到真正模糊的栅格。(理论上,最模糊的是所有值的算术平均值的恒定栅格)。
我可以使用任何工具或方法(基于Esri,GDAL,GRASS)吗?我需要在家烘烤自己的高斯模糊例程吗?我可以使用低通滤波器(例如ArcGIS的filter),如果是这样,我是否需要运行多次以获取大半径的效果?
Answers:
高斯模糊只是加权焦距平均值。您可以使用一系列短距离圆形邻域(未加权)来高精度地重新创建它:这是Central Limit定理的一个应用。
您有很多选择。“过滤器”太有限-仅适用于3 x 3邻域-因此请不要打扰。大型DEM的最佳选择是将计算在ArcGIS之外带入使用快速傅立叶变换的环境中:它们进行相同的焦点计算,但是(相比之下)它们执行起来非常快。(GRASS具有FFT模块。该模块用于图像处理,但如果可以将其以合理的精度重新缩放到0..255范围内,则可以将其投入DEM的使用。)除非至少有两个解决方案,值得考虑:
创建一组邻域权重,以近似于一个较大邻域的高斯模糊。使用此模糊的连续遍历来创建更平滑的DEM序列。
(权重计算为exp(-d ^ 2 /(2r)),其中d是距离(如果愿意,可以在单元格中),r是有效半径(也可以在单元格中)。必须在延伸的圆内计算至少达到3r。这样做之后,将每个权重除以它们的总和,这样最后它们就等于1。)
或者,忘记加权;只需反复执行循环焦点均值。我正是为了研究派生网格(如坡度和坡向)如何随DEM的分辨率变化而做的。
两种方法都将很好地工作,并且在经过前几遍之后,几乎没有什么选择,但是收益递减:n个连续聚焦装置(均使用相同的邻域大小)的有效半径仅为(大约)n乘以焦点均值半径的平方根。因此,对于大量的模糊,您将要从大半径的邻域重新开始。如果使用未加权的均值,则在DEM上运行5-6次。如果您使用的权重接近高斯,则只需要通过一遍:但是您必须创建权重矩阵。
这种方法确实具有DEM的算术平均值作为极限值。
我一直在探索SciPy的signal.convolve方法(基于本菜谱),并通过以下代码片段取得了非常不错的成功:
import numpy as np
from scipy.signal import fftconvolve
def gaussian_blur(in_array, size):
# expand in_array to fit edge of kernel
padded_array = np.pad(in_array, size, 'symmetric')
# build kernel
x, y = np.mgrid[-size:size + 1, -size:size + 1]
g = np.exp(-(x**2 / float(size) + y**2 / float(size)))
g = (g / g.sum()).astype(in_array.dtype)
# do the Gaussian blur
return fftconvolve(padded_array, g, mode='valid')
我在另一个通过GDAL读取/写入float32 GeoTIFF的函数中使用了此函数(无需重新缩放为0-255字节进行图像处理),并且我一直在尝试尝试像素大小(例如2、5、20),并且非常好的输出(在ArcGIS中以1:1像素和恒定的最小/最大范围可视化):
注意:此答案已更新为使用更快的基于FFT的signal.fft卷积处理功能。
如果时间不长且过于复杂,则可能是对MikeT出色答案的评论。我已经玩了很多,并根据他的功能制作了一个名为FFT卷积滤波器(尚未进入“实验”阶段)的QGIS插件。除了平滑外,该插件还可以通过从原始像素中减去平滑后的栅格来锐化边缘。
在此过程中,我对Mike的功能进行了一些升级:
def __gaussian_blur1d(self, in_array, size):
#check validity
try:
if 0 in in_array.shape:
raise Exception("Null array can't be processed!")
except TypeError:
raise Exception("Null array can't be processed!")
# expand in_array to fit edge of kernel
padded_array = np.pad(in_array, size, 'symmetric').astype(float)
# build kernel
x, y = np.mgrid[-size:size + 1, -size:size + 1]
g = np.exp(-(x**2 / float(size) + y**2 / float(size)))
g = (g / g.sum()).astype(float)
# do the Gaussian blur
out_array = fftconvolve(padded_array, g, mode='valid')
return out_array.astype(in_array.dtype)
有效性检查是不言而喻的,但重要的是强制转换为浮动并返回。在此之前,由于将值除以(g / g.sum()
),该函数使整数数组变为黑色(仅零)。
在QGIS中,使用Orfeo Toolbox图像过滤可以轻松获得良好的结果。这是合理的快速,批处理模式可以正常工作。可以使用高斯,均值或各向异性扩散。
请注意,Radius
是指像元数,而不是距离。
这是使用Smoothing(gaussian)的示例:
高斯模糊和炫酷动画的不错解决方案。关于上述Esri过滤器工具,基本上就是硬编码为3x3大小的Esri“焦点统计”工具。焦点统计工具为您提供了更多有关移动滤镜的形状,大小和要运行的统计信息的选项。 http://desktop.arcgis.com/en/arcmap/latest/tools/spatial-analyst-toolbox/focal-statistics.htm
您还可以制作一个“不规则”过滤器,在其中传递带有权重的自己的文本文件,以用于每个单元格。文本文件在过滤器区域中具有所需的行数,并且各列用空格分隔。我猜您应该始终使用奇数行和列,因此目标单元格位于中间。
我创建了一个Excel电子表格来播放不同的权重,然后将其复制/粘贴到此文件中。如果您调整公式,它应该达到与上面相同的结果。