【问题标题】:Numpy: Striding a multiple channel imageNumpy:跨越多通道图像
【发布时间】:2013-08-05 20:29:04
【问题描述】:

我在 numpy.我正在编写一些对多通道图像进行插值的代码。我将图像定义为 np.ndarray 类型的 3 维数组,形状为 [HEIGHT x WIDTH x CHANNELS]。我正在编写的 C++ 必须同时在 Matlab 和 Python 中工作。对于单通道图像,我的代码可以正常工作,而对于 Matlab 中的多通道图像,我的代码可以正常工作。

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

我的问题是,Matlab 通过一个接一个地堆叠连接通道来安排它的 3 维内存。这意味着,对于[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 中使用 stride 来纠正我的问题。但是,我完全没有想出合适的步幅模式。 因此,对于我的 [10, 10, 2] 数组示例,我该如何更改步幅,从(假设双打):

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

我可以像对 Matlab 数组那样索引的东西?

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

【问题讨论】:

    标签: python matlab numpy cython


    【解决方案1】:

    也许您可以使用函数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)
    

    【讨论】:

    • 很好,当然改变轴确实如你所展示的那样。不幸的是,我仍然无法完全纠正我的问题,因此求助于改变每个平台上的索引模式的宏。
    【解决方案2】:

    您可以在创建数组时指定 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)
    

    【讨论】:

    • 如果数组已经创建,可以使用np.asfortranarray。但是,这确实会复制数据-
    猜你喜欢
    • 1970-01-01
    • 2018-03-21
    • 2023-03-25
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多