我有一个表示cloud mask for GIS data的mxN数值数组的布尔数据.我想通过向所有方向移动n个单元格来扩展遮罩.这是一种简单的方法来go 除我蒙版中的云阴影(云像素旁边). 这些数字数组通常在cloud mask for GIS data0xcloud mask for GIS data0和cloud mask for GIS data00xcloud mask for GIS data00像素之间.

我的问题类似于这个one,但有2个维度.

我非常简单但效率低下的解决方案如下所示:

def expand_for(arr, shiftx=1, shifty=1):
    arr_b = arr.copy().astype(bool)
    for i in range(arr.shape[0]):
        for j in range(arr.shape[1]):
            if(arr[i,j]):
                i_min, i_max = max(i-shifty, 0), min(i+shifty+1, arr.shape[0])
                j_min, j_max = max(j-shiftx, 0), min(j+shiftx+1, arr.shape[1])
                arr_b[i_min:i_max, j_min:j_max] = True
    return arr_b

另一种解决方案是:

def shift_array(arr, x, y):
    d, u, r, l = max(y, 0), max(-y, 0), max(x, 0), max(-x, 0)
    ret = np.pad(arr, ((d, u), (r, l)), mode='constant')
    return ret[u or None: -d or None, l or None: -r or None]

def expand_array(arr, shiftx=1, shifty=1):
    return np.dstack([shift_array(arr, x, y)
                      for x in range(-shiftx, shiftx + 1) for y in range(-shifty, shifty + 1)]).any(axis=2)

但复杂程度随着移位和移位的大小而增加.

下面是我想要做的一个非常简单的例子:

a = np.array([[0,0,0,0,0],
             [0,0,0,0,0],
             [0,0,1,0,0],
             [0,0,0,0,0],
             [0,0,0,0,0]])
expand_for(a, 1, 1)

>>> array([[False, False, False, False, False],
       [False,  True,  True,  True, False],
       [False,  True,  True,  True, False],
       [False,  True,  True,  True, False],
       [False, False, False, False, False]])

我一直在使用此代码生成更复杂的测试数据:

N = 100    # or 1000, 10000...
a = np.random.random((N,N))
a = (a < 0.30)*1

推荐答案

这可以使用CV2库来完成,方法是对数组应用dilation.例如:

import numpy as np

N = 10

# the initial array
a = np.zeros((N, N), dtype='uint8')
a[[2, 4, 9], [2, 4, 7]] = 1
print(a)

这提供了:

[[0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 1 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 1 0 0]]

将每个出现的1展开为1的3x3子数组:

import cv2

kernel = np.ones((3, 3), dtype='uint8')
out = cv2.dilate(a, kernel)
print(out)

结果是:

[[0 0 0 0 0 0 0 0 0 0]
 [0 1 1 1 0 0 0 0 0 0]
 [0 1 1 1 0 0 0 0 0 0]
 [0 1 1 1 1 1 0 0 0 0]
 [0 0 0 1 1 1 0 0 0 0]
 [0 0 0 1 1 1 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 1 1 1 0]
 [0 0 0 0 0 0 1 1 1 0]]

如果希望结果是布尔值的数组,则可以更改其数据类型:

out = out.astype('bool')

Python相关问答推荐

Python Pandas—时间序列—时间戳缺失时间精确在00:00

比Pandas 更好的 Select

如何根据rame中的列值分别分组值

mdates定位器在图表中显示不存在的时间间隔

Tensorflow tokenizer问题.num_words到底做了什么?

删除特定列后的所有列

如何获得满足掩码条件的第一行的索引?

文本溢出了Kivy的视区

使用xlsxWriter在EXCEL中为数据帧的各行上色

多索引数据帧到标准索引DF

奇怪的Base64 Python解码

更新包含整数范围的列表中的第一个元素

为什么fizzbuzz在两个数字的条件出现在一个数字的条件之后时不起作用?

如何在开始迭代自定义迭代器类时重置索引属性?

如果属性的类型是联合并使用默认值,为什么属性不能与类同名?

Pandas 滚动着进化的windows

从一组加速度数据到位置的集成

如何分解在某些行中为空,但在其他行中填充的pandas框架

基于直方图箱的样本数据

压平JSON后的Pandas 保留柱