问题描述
Python GIS开发人员的问题。我有一个高密度3D点云,每个像素最多可进行73次观察。使用SFM获得云。我正在将来自云的DEM融合为HSI图像中的新波段,以供将来分析。
我有一个代表8个波段的numpy数组(n点,最小z,最大z,和z ...)。我需要基于点云更改此数组的值。因此,我一次只能工作一个像素,因此很难将numpy向量化。
变量为: map_z =浮点数,平均海平面阵列上方单个云点的高度为8波段numpy阵列
array = np.full((nbands,2000,3000),np.nan,dtype=OUTPUT_RASTER_DTYPE)
我尝试了两个版本的代码。矢量化版本和Else If版本。
slice_arr = array[0:4,pixel_y,pixel_x]
slice_arr[0] = np.where(slice_arr[0] == 0,1,slice_arr[0] + 1)
slice_arr[1] = np.select([np.isnan(slice_arr[1]) == True,slice_arr[1] > map_z],[map_z,map_z],slice_arr[1])
slice_arr[2] = np.select([np.isnan(slice_arr[2]) == True,slice_arr[2] < map_z],slice_arr[2])
slice_arr[3] = np.where(np.isnan(slice_arr[3]) == True,map_z,slice_arr[3] + map_z)
array[0:4,pixel_x] = slice_arr
或
slice_arr = array[0:4,pixel_x] # Take a slice of the array
if slice_arr[0] == 0:
slice_arr[0] = 1
else:
slice_arr[0] = slice_arr[0] + 1
if np.isnan(slice_arr[1]) == True:
slice_arr[1] = map_z
elif slice_arr[1] > map_z:
slice_arr[1] = map_z
else:
pass
if np.isnan(slice_arr[2]) == True:
slice_arr[2] = map_z
elif slice_arr[2] < map_z:
slice_arr[2] = map_z
else:
pass
if np.isnan(slice_arr[3]) == True:
slice_arr[3] = map_z
else:
slice_arr[3] = slice_arr[3] + map_z
array[0:4,pixel_x] = slice_arr
很明显,If else版本的速度要快4倍,因为我一次只能操作一个像素。这是因为map_z是一个点云,我一次只能处理一个点,并且该点仅落在数组中的一个像素上。向量化应在更大的数组上进行。
是否有一种方法可以使用numpy来加速我的代码的这一部分? 如果数组(slice_arr)比(8,3000)大得多,对切片进行切片是否具有速度优势?
解决方法
最后,我能够提高If Else子句的速度,但可以将其放入函数中并使用numba。这样可以减少从2.33分钟开始的时间。到0.42分钟!!
from numba import jit
@jit(nopython=True)
def query_speed_up(slice_arr,map_z):
if slice_arr[0] == 0:
slice_arr[0] = 1
else:
slice_arr[0] = slice_arr[0] + 1
# min z
if np.isnan(slice_arr[1]) == True: # not is
slice_arr[1] = map_z
elif slice_arr[1] > map_z:
slice_arr[1] = map_z
else:
pass
# max z
if np.isnan(slice_arr[2]) == True: # not is
slice_arr[2] = map_z
elif slice_arr[2] < map_z:
slice_arr[2] = map_z
else:
pass
# sum z
if np.isnan(slice_arr[3]) == True: # not is
slice_arr[3] = map_z
else:
slice_arr[3] = slice_arr[3] + map_z
return slice_arr
slice_arr = array[0:4,pixel_y,pixel_x] # Take a slice of the array
jittest = query_speed_up(slice_arr,map_z)
array[0:4,pixel_x] = jittest