Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将函数应用于无循环的多维numpy数组_Python_Arrays_Numpy_Multidimensional Array_Raster - Fatal编程技术网

Python 将函数应用于无循环的多维numpy数组

Python 将函数应用于无循环的多维numpy数组,python,arrays,numpy,multidimensional-array,raster,Python,Arrays,Numpy,Multidimensional Array,Raster,我正在使用numpy处理光栅数据(从GDAL读取后),它表示高程。我的目标是使用numpy计算阵列中每个像素的水流方向,这主要是由给定像素与其8个相邻像素之间的高程差确定的 array([[[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]]]]) 我已经实现了滚动窗口技术,用每个像素及其邻域生成多维数组,其工作原理如下: def rolling_window(array, window_size): itemsize

我正在使用numpy处理光栅数据(从GDAL读取后),它表示高程。我的目标是使用numpy计算阵列中每个像素的水流方向,这主要是由给定像素与其8个相邻像素之间的高程差确定的

array([[[[ 0,  1,  2],
         [ 3,  4,  5],
         [ 6,  7,  8]]]])
我已经实现了滚动窗口技术,用每个像素及其邻域生成多维数组,其工作原理如下:

def rolling_window(array, window_size):
    itemsize = array.itemsize
    shape = (array.shape[0] - window_size + 1,
             array.shape[1] - window_size + 1,
             window_size, window_size)
    strides = (array.shape[1] * itemsize, itemsize,
               array.shape[1] * itemsize, itemsize)
    return np.lib.stride_tricks.as_strided(array, shape=shape, strides=strides)

array = np.arange(100)
array = array.reshape(10, 10)
w = rolling_window(array, 3)

# produces array with shape (8, 8, 3, 3) - edge cases are not currently dealt with.
因此,一系列3 x 3阵列,以1,1处的研究像素为中心,每个阵列位于光栅“行”阵列的另一个维度内,例如,从输入的一个像素开始,表示它的阵列可以如下所示,其中像素值4是研究像素,其他值是它的近邻

array([[[[ 0,  1,  2],
         [ 3,  4,  5],
         [ 6,  7,  8]]]])
使用此多维数组的当前方法的简化版本是以下函数:

def flow_dir(array):

    # Value to assign output based on element index.
    flow_idx_dict = {0: 32,
                     1: 64,
                     2: 128,
                     3: 16,
                     5: 1,
                     6: 8,
                     7: 4,
                     8: 2}

    # Generates the rolling window array as mentioned above.
    w = rolling_window(array, 3)

    # Iterate though each pixel array.
    for x, i in enumerate(w, 1):
        for y, j in enumerate(i, 1):
            j = j.flatten()

            # Centre pixel value after flattening.
            centre = j[4]

            # Some default values.
            idx = 4
            max_drop = 0

            # Iterate over pixel values in array.
            for count, px in enumerate(j):

                # Calculate difference between centre pixel and neighbour.
                drop = centre - px

                # Find the maximum difference pixel index.
                if count != 4:
                    if drop > max_drop:
                        max_drop = drop
                        idx = count

            # Assign a value from a dict, matching index to flow direction category.
            value = flow_idx_dict[idx]

            # Update each pixel in the input array with the flow direction.
            array[x, y] = value
    return array
可以理解,所有这些for循环和if语句都非常慢。我知道一定有一种矢量化的numpy方法可以做到这一点,但我正在努力找到我需要的确切函数,或者可能还不知道如何正确地实现它们。我尝试了np.apply_沿_轴、np.where、np.nditer和其他方法,但到目前为止没有任何效果。我想我需要的是:

  • 一种将函数应用于滚动窗口生成的每个像素阵列的方法,无需使用for循环来访问它们

  • 查找最大drop索引值,而不使用if语句和枚举

  • 能够批量更新输入数组,而不是单个元素


  • 我认为这里可以避免滚动窗口;与NX3X3相比,在NxN阵列上进行矢量化更容易、可读性更强

    考虑以下数据:

    array = np.array([[78, 72, 69, 71, 58, 49],
           [74, 67, 56, 49, 46, 50],
           [69, 53, 44, 37, 38, 48],
           [64, 58, 55, 22, 33, 24],
           [68, 61, 47, 21, 16, 19],
           [74, 53, 34, 12, 11, 12]])
    N=6
    
    首先,以这种方式计算8个渐变和代码:

    gradient = np.empty((8,N-2,N-2),dtype=np.float)
    code = np.empty(8,dtype=np.int)
    for k in range(8):
        theta = -k*np.pi/4
        code[k] = 2**k
        j, i = np.int(1.5*np.cos(theta)),-np.int(1.5*np.sin(theta))
        d = np.linalg.norm([i,j])
        gradient[k] = (array[1+i: N-1+i,1+j: N-1+j]-array[1: N-1,1: N-1])/d
    
    它很快,因为几乎没有外部环路(8)。
    (-gradient).argmax(轴=0)
    给出每个像素的流动方向

    最后,
    获取
    代码:

    direction = (-gradient).argmax(axis=0)
    result = code.take(direction)
    
    结果:

    array([[  2,   2,   4,   4],
           [  1,   2,   4,   8],
           [128,   1,   2,   4],
           [  2,   1,   4,   4]])
    

    您能否共享
    滚动窗口
    函数定义?另外,什么是
    flow\u idx\u dict
    ?你能添加可用于运行
    flow_dir
    的示例输入吗?我已经在滚动窗口和flow dict中添加了。np.arange(100)的示例被重塑为(10,10)就足够作为flow_dir的输入了,尽管实际上我的数组要大得多,并且它们的值更可变。因此,我将使用
    arr=np.arange(90)
    然后
    流动方向(arr)
    ?我想这会造成错误。你看过了吗?估计也一样。查看np.pad,使您能够反映边缘值,以帮助处理边缘影响。所以我假设,你只需要找到最小的差异(你的窗口-中间)就可以从字典中提取你的值,但不清楚你是单独使用基数,还是考虑重复,或者相反的最大下降。当然,你会很高兴避免滚动窗口,我的大脑是如何在空间分析背景下工作的,而不是数学或计算机科学。我认为这非常接近我所需要的,只是编码不像预期的那样,例如,给定一个[3,2,0]、[1,6,9]、[4,4,4]的窗口,中心像素(6)的输出是4(即南),但应该是128(NE),就像这里的方向编码一样。可能是因为渐变数组的一半数据被设置为零。我需要做一些编辑才能运行,但它仍然不在那里-对角线的渐变差仍然为零。对于那些,j,i是0,0,而不是-1,-1等等。我还发现argmax实际上是正确的函数,因为它是所追求的最大压降。忽略对角线,现在可以正常工作了,所以我认为需要进一步工作的只是分配I&j的行。问题是3/2,在我的Python2.7安装中返回1。将此更改为3/2.0解决了此问题。是的,我相信是这样,谢谢您抽出时间。使用1000 x 1000个单元的测试阵列,您的代码比迭代滚动窗口方法快大约100倍,完全满足我的要求。现在,我需要看看边缘盒和水槽。。。