我有2张288x288 ndarray
s形式的灰度图像。每个ndarray
中的值只有numpy.float32
个数字,范围从0.0到255.0。对于每个ndarray
,我创建了一个numpy.ma.MaskedArray
对象,如下所示:
def bool_row(row):
return [value == 183. for value in row]
mask = [bool_row(row) for row in nd_array_1]
masked_array_1 = ma.masked_array(nd_array_1, mask=mask)
值183.
表示图像中的“垃圾”。所有5张图片中都有一些“垃圾”。我想取屏蔽图像的中位数,其中取每个点的中位数应忽略任何屏蔽值。结果将是没有垃圾的正确图像。
当我尝试:
ma.median([masked_array_1, masked_array_2, masked_array_3, masked_array_4, masked_array_5], axis=0)
我得到的似乎是中位数,除了忽略掩盖的值,它将它们视为183.
,因此结果只有来自所有图片的叠加垃圾。当我只取两张蒙面图像的中位数时:
ma.median([masked_array_1, masked_array_2], axis=0)
看起来它开始做正确的事情,但是即使两个蒙版数组都包含183.
,也会放置MaskedConstant
的值。
我可以做类似以下的事情,但我觉得有可能让ma.median
按预期行事:
unmasked_array_12 = ma.median([masked_array_1, masked_array_2], axis=0)
mask = [bool_row(row) for row in unmasked_array_12]
masked_array_12 = ma.masked_array(unmasked_array_12, mask=mask)
unmasked_array_123 = ma.median([masked_array_12, masked_array_3], axis=0)
mask = [bool_row(row) for row in unmasked_array_123]
masked_array_123 = ma.masked_array(unmasked_array_123, mask=mask)
...
如何在不诉诸上述不愉快的情况下让ma.median
按预期工作?
答案 0 :(得分:3)
我怀疑问题在于ma.median
如何处理非数组参数。它可能是将列表转换为普通的numpy数组,而不检查列表元素的类型。
考虑以下带有1-D数组的示例:
In [64]: a = ma.array([1, 2, -10, 3, -10, -10], mask=[0,0,1,0,1,1])
In [65]: b = ma.array([1, 2, -10, -10, 4, -10], mask=[0,0,1,1,0,1])
In [66]: a
Out[66]:
masked_array(data = [1 2 -- 3 -- --],
mask = [False False True False True True],
fill_value = 999999)
In [67]: b
Out[67]:
masked_array(data = [1 2 -- -- 4 --],
mask = [False False True True False True],
fill_value = 999999)
以下内容不正确 - 似乎忽略了面具:
In [68]: ma.median([a, b])
Out[68]: -4.5
In [69]: ma.median([a, b], axis=0)
Out[69]:
masked_array(data = [ 1. 2. -10. -3.5 -3. -10. ],
mask = False,
fill_value = 1e+20)
但是,如果我首先使用ma.array
创建一个新的蒙版数组,ma.median
会正确处理它:
In [70]: c = ma.array([a, b])
In [71]: c
Out[71]:
masked_array(data =
[[1 2 -- 3 -- --]
[1 2 -- -- 4 --]],
mask =
[[False False True False True True]
[False False True True False True]],
fill_value = 999999)
In [72]: ma.median(c)
Out[72]: 2.0
In [73]: ma.median(c, axis=0)
Out[73]:
masked_array(data = [1.0 2.0 -- 3.0 4.0 --],
mask = [False False True False False True],
fill_value = 1e+20)
因此,为了解决您的问题,它可能就像替换它一样简单:
ma.median([masked_array_1, masked_array_2, masked_array_3, masked_array_4, masked_array_5], axis=0)
用这个:
stacked = ma.array([masked_array_1, masked_array_2, masked_array_3, masked_array_4, masked_array_5])
ma.median(stacked, axis=0)
答案 1 :(得分:0)
在计算中位数时,你可以使用以下方法去除所有183个值:
masked_arrays=[masked_array_1, masked_array_2, masked_array_3]
no_junk_arrays=[[x for x in masked_array if x is not 183] for masked_array in masked_arrays]
ma.median(no_junk_arrays)
例如
>>> masked_array_1 = [1,183,4]
>>> masked_array_2 = [1,183,2]
>>> masked_array_3 = [2,183,2]
>>> masked_arrays=[masked_array_1,masked_array_2,masked_array_3]
>>> no_junk_arrays=[[x for x in masked_array if x is not 183] for masked_array in masked_arrays]
>>> no_junk_arrays
[[1, 4], [1, 2], [2, 2]]
答案 2 :(得分:0)
如果你发现要调用的numpy函数的聪明序列,我相信它可以完成。但它也可以天真地完成:
def merge(a1, a2):
result = []
for x, y in zip(a1, a2):
if x == 183:
x = y
result.append(x)
return result
array_1 = [1, 183, 2]
array_2 = [1, 183, 183]
array_3 = [183, 4, 2]
print merge(merge(array_1, array_2), array_3)
如果结果运行得太慢,你可以在PyPy而不是CPython上尝试相同的代码。
答案 3 :(得分:0)
如果您追求的是为每个像素提取非纳米值,您可以按照以下方式进行操作:
stacked_imgs = np.dstack((img1, img2, img3))
mask = stacked_imgs == 183
# Find the first False, i.e. non-183 entry, along stack axis
index = np.argmin(mask, axis=-1)
correct_image = stacked_image[..., index]
如果给定像素的所有非183条目总是相同的,这将为您提供您所追求的结果。