Numpy:跨越多频道图像

时间:2013-08-05 20:29:04

标签: python matlab numpy cython

我遇到了一些麻烦。我正在编写一些代码来执行多通道图像的插值。我将我的图像定义为np.ndarray类型的三维数组,其形状为[HEIGHT x WIDTH x CHANNELS]。我写的C ++必须在Matlab和Python中都能使用。对于单通道图像,我的代码工作正常,对于Matlab中的多通道图像,我的代码工作正常。

为了插入图像,我正在编写一种方法,在给定[M x N x P]数组的情况下,您可以提供一组XY个子像素坐标进行插值在图像内。这与scipy ndimage.map_coordinates的功能相同。不幸的是,我需要一种插值方法,在Matlab和Python中产生相同的结果,因此滚动我自己的插值代码。

我的问题是Matlab通过一个接一个地堆叠通道来安排它的三维记忆。这意味着,对于[10, 10, 2]图像,第一个100元素将是第一个通道,元素[100, 200]元素将是第二个通道。因此,要索引到Matlab连续内存,我的索引如下:

// i is the element of the indices array
// j is the current channel
// F is the image we are indexing
// F_MAX is M * N (the number of pixels per channel)
// N_ELEMS is the total number of elements in the indices array
// f_index is the index in the contiguous array equivalent to the x and y coordinate in the 2D image
for (size_t j = 0; j < N_CHANNELS; j++)
{
  out[i + j * N_ELEMS] = F[f_index + j * F_MAX];
}

我的问题是numpy沿着第3轴命令它是3维阵列。也就是说,给定[10, 10, 2]数组,前两个元素是索引[0, 0, 0][0, 0, 1]。在Matlab中,它们是索引[0, 0, 0][0, 1, 0]

我认为我可以通过使用numpy的步幅来纠正我的问题。但是,我完全没有提出适当的步幅模式。 因此,对于我的[10, 10, 2]数组示例,如何更改步幅(假设为双打):

>>> np.ones([10,10,2], dtype=np.float64).strides
(160, 16, 8)

可以像我对Matlab数组那样编入索引吗?

我应该提一下,我知道Matlab和numpy之间的主要/行主要区别。如上所述,我的方法适用于单通道图像,但索引错误超过1个通道。

2 个答案:

答案 0 :(得分:4)

也许你可以使用函数np.swapaxes,如下面的ipython示例所示:

In [1]: a = np.arange(2*2*2).reshape((2,2,2))

In [2]: a
Out[2]: 
array([[[0, 1],
        [2, 3]],

       [[4, 5],
        [6, 7]]])

In [3]: a.flatten()
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7])

In [4]: np.swapaxes(a,2,1).flatten()
Out[4]: array([0, 2, 1, 3, 4, 6, 5, 7])

编辑:

我认为只有在使用交换轴获取数组副本后内部存储器布局才会发生变化,请参阅:

In [6]: b = a.swapaxes(1,2)

In [7]: b.strides
Out[7]: (16, 4, 8)

In [8]: b = a.swapaxes(1,2).copy()

In [9]: b.strides
Out[9]: (16, 8, 4)

答案 1 :(得分:3)

您可以在创建阵列时指定Fortran顺序:

>>> a = np.ones((10,10,2),dtype=np.float64)
>>> a.strides
(160, 16, 8)
>>> b = np.ones((10,10,2),dtype=np.float64,order='f')
>>> b.strides
(8, 80, 800)