优雅地迭代图像的平面 - 如果不止一个

时间:2015-04-29 09:40:27

标签: python numpy

我来自Matlab世界,我对Python比较陌生,所以我想我可能会从一个完全错误的角度来看待它。

无论如何,我经常发现自己要编写需要在图像的R,G,B平面上单独操作的代码,但需要足够通用,如果图像是灰度的,它仍然可以工作。现在我开始的非常聪明的方式是:

if im_in.ndim == 2:
  im_out = signal.convolve2d(im_in, filt, 'same')
else:
  im_out = np.empty_like(im_in)
  for kk in range(im_in.shape[2]):
    im_out[:,:,kk] = signal.convolve2d(im_in, filt, 'same')

别介意实际操作 - 我在这里使用signal.convolve2d作为示例。我们假设ndim在这里只能是2或3,为简单起见。

现在Matlab非常聪明的地方就是我可以在表示图像的3D数组的第三维上循环,而不管平面的数量。

上述明显的替代方案如下:

if im_in.ndim == 2:
  im_in.shape = (im_in.shape[0], im_in.shape[1], 1)

然后我可以循环第三维(就像上面的else情况一样),但在我看来这仍然是一个黑客,我必须重塑{{1在结束之前。是否有适当,优雅的方式来处理这种情况?

3 个答案:

答案 0 :(得分:3)

您可以使用numpy.atleast_3d()无条件地使用正确数量的维度获取输入数组的视图,然后迭代这些平面。这样做的好处是可以保存if语句而不修改输入图像。

答案 1 :(得分:0)

它并不比你自己的解决方案好多了(虽然我认为你的解决方案很好)但你可以在不使用if语句的情况下重塑你的图像:

oldshape = im_in.shape
im_in = reshape(im_in, (oldshape[0], oldshape[1], im_in.size/(oldshape[0]*oldshape[1])))

这样,图像的形状是一个三元素元组,您可以迭代im_in.shape[2]

答案 2 :(得分:0)

您可以自动化您的第一个解决方案(或者您使用的解决方案):

from functools import wraps

def rgb_seperate(f):
    @wraps(f)
    def seperate(array, *args, **kwargs):
        im_out = np.empty_like(im_in)
        if im_in.ndim == 2:
             im_out = f(array, *args, **kwargs))
        else:
             for kk in range(im_in.shape[2]):
                 im_out[:,:,kk] = f(array[:,:,kk], *args, **kwargs)
        return(im_out)

用法:

>>> rgb_seperate(signal.convolve2d)(im_in, filt, 'same')
[output]
>>>@rgb_seperate
>>>def operator(array, [someargs]):
>>>     ...
>>> operator(im_in, [someargs])
[output]

当然,这对于在内部使解决方案更好的方式没有帮助,但可能有助于它的使用。你不必每次都记得输入你的解决方案(不过你最终会解决它),但只能将它包装在rgb_seperate中。

相关问题