[英]Applying circular filter to image in Python / Applying function to each element of numpy array
我有一个可以运行的Python代码,但运行速度很慢,我相信必须有一种更有效的方法。 想法是对图像应用滤镜。 过滤器是落在指定半径内的点的平均值。 输入是代表x,y的mx2
数组和代表m个观察点的坐标的mx1
数组z。
起作用的程序如下
import numpy as np
def haversine(point, xy_list):
earth_radius = 6378137.0
dlon = np.radians(xy_list[:,0]) - np.radians(point[0])
dlat = np.radians(xy_list[:,1]) - np.radians(point[1])
a = np.square(np.sin(dlat/2.0)) + np.cos(np.radians(point[0])) * np.cos(np.radians(xy_list[:,0])) * np.square(np.sin(dlon/2.0))
return 2 * earth_radius * np.arcsin(np.sqrt(a))
def circular_filter(xy, z, radius):
filtered = np.zeros(xy.shape[0])
for q in range(xy.shape[0]):
dist = haversine(xy[q,:],xy)
masked_z = np.ma.masked_where(dist>radius, z)
filtered[q] = masked_z.mean()
return filtered
x = np.random.uniform(low=-90, high=0, size=(1000,1)) # x represents longitude
y = np.random.uniform(low=0, high=90, size=(1000,1)) # y represents latitude
xy = np.hstack((x,y))
z = np.random.rand(1000,)
fitered_z = circular_filter(xy, z, radius=100.)
问题是每个数据集有600万个点,并且代码非常慢。 必须有一种方法可以更有效地做到这一点。 我考虑过使用快速的scipy.spatial.distance.cdist(),但是随后我不得不将数据重新投影到UTM,并且我想避免重新投影。 有什么建议么?
谢谢,雷尼尔
经过大量阅读搜索之后,我终于找到了使代码永久运行的原因。 这是因为我需要理解和应用过滤器内核的概念。 基本上,我意识到我的问题和这篇文章之间存在联系: 具有圆形窗口的Local Maxima
缺点:用户需要提供正确的EPSG代码,但我认为稍后可以找到解决方法。
好处:这是非常快速和高效的。
对我有用的是将经纬度长时间转换为UTM,以便我们可以创建一个循环内核并从scipy应用generic_filter。
import numpy as np
from pyproj import Proj, transform
from scipy.ndimage.filters import generic_filter
def circular_filter(tile, radius):
x, y = np.meshgrid(tile['lon'], tile['lat'])
x = x.reshape(x.size)
y = np.flipud(y.reshape(y.size))
z = tile['values'].reshape(tile['values'].size)
wgs84 = Proj(init='epsg:4326')
utm18N = Proj(init='epsg:26918')
x,y = transform(wgs84,utm18N,x,y)
dem_res = np.abs(x[1]-x[0]) # calculates the raster resolution, (original data is geoTiff read using gdal).
radius = int(np.ceil(radius/dem_res)) # user gives meters, but we figure out number of cells
print(radius)
kernel = np.zeros((2*radius+1, 2*radius+1))
y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
mask = x**2 + y**2 <= radius**2
kernel[mask] = 1
print('Commence circular filter.'); start = time.time()
tile['values'] = generic_filter(tile['values'], np.mean, footprint=kernel)
print('Took {:.3f} seconds'.format(time.time()-start))
我还从这里研究了群集技术: http : //geoffboeing.com/2014/08/clustering-to-reduce-spatial-data-set-size/
但是我意识到这些聚类技术的目的完全不同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.