使用Numpy生成ASCII内核

时间:2012-03-05 01:33:00

标签: python matrix numpy geospatial arcgis

我正在使用ArcGIS焦点统计工具将空间自相关添加到随机栅格以模拟DEM中的错误。输入DEM的像素大小为1.5米,半变异函数的基石大约为2000米。我想确保在模型的输入中建模自相关的程度。

不幸的是,ArcGIS要求输入内核采用ASCII格式,第一行定义大小,后续行定义权重。

示例:

5 5
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1

我需要生成一个带有反距离权重的1333x1333内核,并立即转到python来完成此操作。是否有可能在numpy中生成矩阵并通过ring分配值?是否存在numpy中更好的编程工具来生成纯文本矩阵。

这类似于this question,但我需要有一个固定的中心值和下降环,如上例所示。

注意:我是学生,但这不是家庭作业......那些在几年前结束了。这是我正在研究的一个更大的研究项目的一部分,任何帮助(甚至只是在正确的方向上推动)将不胜感激。这项工作的重点不是编程内核,而是探索DEM中的错误。

2 个答案:

答案 0 :(得分:3)

我不确定是否有内置方式,但不应该很难推出自己的方式:

>>> def kernel_thing(N):
...   import numpy as np
...   n = N // 2 + 1
...   a = np.zeros((N, N), dtype=int)
...   for i in xrange(n):
...     a[i:N-i, i:N-i] += 1
...   return a
... 
>>> def kernel_to_string(a):
...   return '{} {}\n'.format(a.shape[0], a.shape[1]) + '\n'.join(' '.join(str(element) for element in row) for row in a)
... 
>>> print kernel_to_string(kernel_thing(5))
5 5
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
>>> print kernel_to_string(kernel_thing(6))
6 6
1 1 1 1 1 1
1 2 2 2 2 1
1 2 3 3 2 1
1 2 3 3 2 1
1 2 2 2 2 1
1 1 1 1 1 1
>>> print kernel_to_string(kernel_thing(17))
17 17
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
1 2 3 3 3 3 3 3 3 3 3 3 3 3 3 2 1
1 2 3 4 4 4 4 4 4 4 4 4 4 4 3 2 1
1 2 3 4 5 5 5 5 5 5 5 5 5 4 3 2 1
1 2 3 4 5 6 6 6 6 6 6 6 5 4 3 2 1
1 2 3 4 5 6 7 7 7 7 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 8 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 8 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 7 7 7 7 6 5 4 3 2 1
1 2 3 4 5 6 6 6 6 6 6 6 5 4 3 2 1
1 2 3 4 5 5 5 5 5 5 5 5 5 4 3 2 1
1 2 3 4 4 4 4 4 4 4 4 4 4 4 3 2 1
1 2 3 3 3 3 3 3 3 3 3 3 3 3 3 2 1
1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

答案 1 :(得分:2)

[Hmmph。 @wim击败了我,但我已经写了以下内容,所以无论如何我都会发布它。]简短版本:

import numpy

N = 5

# get grid coords
xx, yy = numpy.mgrid[0:N,0:N]
# get the distance weights
kernel = 1 + N//2 - numpy.maximum(abs(xx-N//2), abs(yy-N//2))

with open('kernel.out','w') as fp:
    # header
    fp.write("{} {}\n".format(N, N))
    # integer matrix output
    numpy.savetxt(fp, kernel, fmt="%d")

产生

~/coding$ python kernel.py 
~/coding$ cat kernel.out 
5 5
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1

魔术的详细解释:我们首先需要的是矩阵中每个条目的索引,为此我们可以使用mgrid

>>> import numpy
>>> N = 5
>>> xx, yy = numpy.mgrid[0:N,0:N]
>>> xx
array([[0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2],
       [3, 3, 3, 3, 3],
       [4, 4, 4, 4, 4]])
>>> yy
array([[0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]])

因此,成对,这些是5x5数组的每个元素的x和y坐标。中心位于N // 2,N // 2(其中//是截断分割),所以我们可以减去它以获得距离,并取绝对值,因为我们不关心标志:

>>> abs(xx-N//2)
array([[2, 2, 2, 2, 2],
       [1, 1, 1, 1, 1],
       [0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2]])
>>> abs(yy-N//2)
array([[2, 1, 0, 1, 2],
       [2, 1, 0, 1, 2],
       [2, 1, 0, 1, 2],
       [2, 1, 0, 1, 2],
       [2, 1, 0, 1, 2]])

现在看一下原始网格,看起来你想要两者的最大值:

>>> numpy.maximum(abs(xx-N//2), abs(yy-N//2))
array([[2, 2, 2, 2, 2],
       [2, 1, 1, 1, 2],
       [2, 1, 0, 1, 2],
       [2, 1, 1, 1, 2],
       [2, 2, 2, 2, 2]])

看起来不错但走错了路。不过我们可以反思:

>>> N//2 - numpy.maximum(abs(xx-N//2), abs(yy-N//2))
array([[0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0],
       [0, 1, 2, 1, 0],
       [0, 1, 1, 1, 0],
       [0, 0, 0, 0, 0]])

你想要1索引,看起来像是这样:

>>> 1 + N//2 - numpy.maximum(abs(xx-N//2), abs(yy-N//2))
array([[1, 1, 1, 1, 1],
       [1, 2, 2, 2, 1],
       [1, 2, 3, 2, 1],
       [1, 2, 2, 2, 1],
       [1, 1, 1, 1, 1]])

我们有它。其他一切都很无聊。