numpy掩码数组填充值仍在访问中

2024-04-20 06:53:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将图像处理为一个蒙版数组来处理NoData区域。我想先在一维数组上做点测试。这是我的测试代码:

    a = np.array([0,1,4,3,4,-9999,33,34,-9999])
    am = np.ma.MaskedArray(a)
    am.mask = (am==-9999)

    z = np.arange(35)

    z[am]

我希望使用掩码数组索引z数组会成功,但我看到以下错误:

^{pr2}$

有人能评论一下如何正确编码吗?我可以成功地运行以下命令:

    z[a[a>0]]

实际上是一样的。在

谢谢!在


Tags: 区域错误npmask数组amarray图像处理
2条回答

一般来说,使用带标记的数组来编制索引是一个坏主意,正是因为在掩码值处应该发生的行为是未定义的。在

这样想:当我看你的数组a和你的数组z,我可以说“好,a[0] = 0所以z[a[0]]是有意义的。”如此类推,直到我遇到a[5] = -9999时,我可以说,“好吧,作为z的索引是没有意义的”,并且可以引发一个异常。在

实际上,当您天真地使用am作为索引集时,就会发生这种情况。。。它恢复为使用am.data,它包含原始值的所有。如果它试图使用类似[z[i] for i in am]的方法,您将遇到这样一个问题numpy.ma.core.MaskedConstant,这对于索引不是一个明智的值,不是为了获取值,也不是为了忽略获取值的请求。在

In [39]: l = [x for x in am]

In [40]: l
Out[40]: [0, 1, 4, 3, 4, masked, 33, 34, masked]

In [41]: type(l[-1])
Out[41]: numpy.ma.core.MaskedConstant

(事实上,如果您试图索引这些家伙中的一个,就会得到IndexError: arrays used as indices must be of integer (or boolean) type)。在

但是现在如果我在am.filled()中遇到了掩码值,会发生什么呢?在am.filled()的第5个索引处的条目将不是numpy.ma.core.MaskedConstant的实例,而是由您选择的填充值。如果这个填充值作为一个索引是有意义的,那么实际上您将通过在该索引处建立索引来获取一个值。以0为例。它看起来像一个无害的中性填充值,但实际上它代表一个有效的索引,因此您可以额外访问z的第0个条目:

^{pr2}$

这也不是面具应该做的!在

一种半途而废的方法是迭代am,并排除任何typenp.ma.core.MaskedConstant

In [45]: z[np.array([x for x in am if type(x) is not np.ma.core.MaskedConstant])]
Out[45]: array([ 0,  1,  4,  3,  4, 33, 34])

不过,更清楚地表达这一切的方法是首先使用简单的逻辑索引:

In [47]: z[a[a != -9999]]
Out[47]: array([ 0,  1,  4,  3,  4, 33, 34])

注意,像这样的逻辑索引对二维数组很有效,只要你愿意接受这样一个事实:一旦一个更高维的数组被逻辑索引,如果结果不再符合相同的规则二维形状,那么它将以1D的形式呈现,如下所示:

In [58]: a2 = np.array([[10, -9999, 13], [-9999, 1, 8], [1, 8, 1]])

In [59]: a2
Out[59]: 
array([[   10, -9999,    13],
       [-9999,     1,     8],
       [    1,     8,     1]])

In [60]: z2 = np.random.rand(3,3)

In [61]: z2[np.where(a2 != -9999)]
Out[61]: 
array([ 0.4739082 ,  0.13629442,  0.46547732,  0.87674102,  0.08753297,
        0.57109764,  0.39722408])

相反,如果您想要类似于掩码的效果,则可以将值设置为NaN(对于float数组):

In [66]: a2 = np.array([[10, -9999, 13], [-9999, 1, 8], [1, 8, 1]], dtype=np.float)

In [67]: a2
Out[67]: 
array([[  1.00000000e+01,  -9.99900000e+03,   1.30000000e+01],
       [ -9.99900000e+03,   1.00000000e+00,   8.00000000e+00],
       [  1.00000000e+00,   8.00000000e+00,   1.00000000e+00]])

In [68]: a2[np.where(a2 == -9999)] = np.NaN

In [69]: a2
Out[69]: 
array([[ 10.,  nan,  13.],
       [ nan,   1.,   8.],
       [  1.,   8.,   1.]])

这种使用NaN的掩蔽形式适用于NumPy中的大量矢量化数组计算,尽管首先将基于整数的图像数据转换为浮点,然后在最后安全地将其转换回原来的位置,这可能是一件痛苦的事。在

试试这个代码

a = np.array([0,1,4,3,4,-9999,33,34,-9999])
am = np.ma.MaskedArray(a)
am.mask = (am==-9999)
np.ma.set_fill_value(am, 0)

z = np.arange(35)

print z[am.filled()]

访问am将得到掩码数组,其中masked value引用原始值(它只是对原始数组的引用)。在设置fill峈u value之后调用am.filled()将掩码元素替换为am.filled返回的数组中的fill峎u值

相关问题 更多 >