嵌套for循环以替换数组中的单元格

时间:2017-08-30 22:22:29

标签: python arrays for-loop

我有一个蒙面图像,我试图用另一个数组中的值替换该图像中的蒙板像素。我使用嵌套for循环:

import scipy.ndimage as ndi
import matplotlib.pyplot as plt
import numpy as np  

#   Generate random image and mask
np.random.seed(seed=5)                      #   To use the same random numbers
h, w = 10, 10
mask = np.random.randint(2, size=(h, w))    #   Generate a h x w array of 
                                            #   random integers from 0 - 1
img = np.random.rand(h, w)                  #   Generate a h x w array of 
                                            #   random floats
img_masked = np.where(mask, img, np.nan)    #   Mask the img array and replace
                                            #   invalid values with nan's

#   Use generic filter to compute nan-excluding median of masked image
size = 3
img_masked_median = ndi.generic_filter(img_masked, np.nanmedian, size=size)

new_img = np.ones_like(img_masked)
#   Use a for loop to look at each pixel in the masked, unfiltered image
height, width = img_masked.shape
for y in range(height):
    for x in range(width):
        if img_masked[x, y] != []:
            new_img[x, y] = img[x, y]
        else:
            new_img[x, y] = img_masked_median[x, y]

#   Plot results in 4x4 grid
fig, ax = plt.subplots(nrows=2, ncols=2)
ax[0,0].imshow(img)
ax[0,0].set_title('img')
ax[0,1].imshow(img_masked_median)
ax[0,1].set_title('img_masked_median')
ax[1,0].imshow(img_masked)
ax[1,0].set_title('img_masked')
ax[1,1].imshow(new_img)
ax[1,1].set_title('new_img')
plt.show()

过滤器工作正常,现在我只想将img中的任何蒙版像素替换为img_masked_median中的相应像素。 目前,循环只生成img_masked_median的副本。如果我将第24行的条件改为

if img_masked[x, y] != np.nan:

现在它生成了img的副本 为什么for循环没有正确替换像素?

1 个答案:

答案 0 :(得分:0)

初始版本的问题是img_masked[x, y]肯定永远不会是[],因为那是空列表 - img_masked的元素是numpy浮点数,而不是列表。

如果您将支票更改为if img_masked[x, y] != np.nan,则会遇到np.nan不等于自己的问题:

>>> np.nan == np.nan
False

这两种技术的问题在于,第一个if始终为True,因此您始终使用旧img填充new_img。我强烈建议在查找这样的错误时在每个分支中添加一些print - 它会清楚地表明分支无法正常工作。

要获得一致的结果,请使用np.isnan

#   Use a for loop to look at each pixel in the masked, unfiltered image
height, width = img_masked.shape
for y in range(height):
    for x in range(width):
        if np.isnan(img_masked[x, y]):
            new_img[x, y] = img[x, y]
        else:
            new_img[x, y] = img_masked_median[x, y]