簡體   English   中英

在Python中將循環濾鏡應用於圖像/將函數應用於numpy數組的每個元素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM