【问题标题】:Getting plane slices from array data从数组数据中获取平面切片
【发布时间】:2010-06-09 08:33:28
【问题描述】:

大家好,

我将 3d 网格数据(来自多个 TIF 图像)读入如下结构:

typedef struct VolumeData{
 int nx;
 int ny;
 int nz;
 unsigned char *data; // size is nx*ny*nz
}

现在我想从这个一维网格数据中获取平面切片:

例如:

unsigned char* getXYPlaneStack(VolumeData *vol,int z); 

 I could implement above function because the *data array stores image stack.

但是我很难沿着其他轴实现:

unsigned char* getYZPlaneStack(VolumeData *vol,int x);

unsigned char* getXZPlaneStack(VolumeData *vol,int y);

有什么简单的算法吗? 提前致谢。

【问题讨论】:

    标签: c algorithm 3d plane


    【解决方案1】:

    第二个和第三个函数都对您的数据集重新采样(它们基本上是在一个新的参考中表达您的图像)。

    所以他们必须重新组织数据:

    1. 为 YZ 创建一个大小为 ny*nz 的新数组,为 XZ 创建一个大小为 nx*nz 的新数组
    2. 用位于给定平面中的数据填充数组
    3. 返回指向新分配数组的指针

    (在这种情况下,调用者负责释放新分配的内存。)

    你的 YZ 平面算法是:

    // I assume this sorting order:
    //       Z ^          Slices are
    //        /           stacked along
    //       /            the Z axis
    //      +-------> X
    //      |
    //      |
    //    Y v
    
    // Assumes your data is stored in row major order:
    //          +-------> X        +---------> X
    // slice 0: | 0 1 2 | slice 1: | 6  7  8 | etc.
    //          | 3 4 5 |          | 9 10 11 |
    //        Y v                Y v
    // Assumes x is the column index, y the row index, z the slice index.
    // For example, you want element #9:
    // - col 0   -> x = 0
    // - row 1   -> y = 1
    // - slice 1 -> z = 1
    // I suggest you rename nx, ny, nz into nbCols, nbRows, nbSlices to make
    // things explicit
    index computeIndex(VolumeData *vol, int x, int y, int z)
    {
        int nx = vol->nx, // nb cols
            ny = vol->ny, // nb rows
            nz = vol->nz; // nb slices
        int index = nx*ny*z // size of one slice, multiplied by slice index
                  + nx*y    // size of one row (nb cols), multiplied by row index
                  + x;      // offset in row (column index)
        return index;
    }
    
    unsigned char* getYZPlaneStack(VolumeData *vol,int x)
    {
        int nx = vol->nx, // nb rows
            ny = vol->ny, // nb columns
            nz = vol->nz; // nb slices
        unsigned char *newData = new unsigned char[ny*nz];
        // Depth is now along the X axis
        //   +-----> Z
        //   |
        //   |
        // Y v
        for(int y = 0; y < ny; ++y)      // For each row
            for(int z = 0; z < nz; ++z ) // For each column
            {
                int i = computeIndex(vol, x, y, z);
                newData[nz*y+z] = vol->data[i];
            }
        return newData;
    }
    

    【讨论】:

      【解决方案2】:

      C 数组在内存中总是连续的。您所追求的似乎需要在后续元素的地址之间建立更复杂的关系,而不仅仅是添加元素的大小。

      我认为您要么必须进一步抽象它,以便获得一个函数(getAt() 或其他东西)来调用以索引到数组中,要么动态创建新切片并复制数据。

      【讨论】:

        【解决方案3】:

        这对于你提到的返回类型是不可能的。

        我会解释的。

        在第一个函数中,您返回一个指针,调用者期望连续打包数据的地址。这没关系,因为原始结构支持它。

        对于第二个函数,如果要返回连续打包平面的地址,则必须进行[1]重新排序,即复制到别处[2]分配内存,因为复制到别处,并且[ 3] 释放内存,因为在 2 中完成了分配。

        如果从性能的角度来看复制是可以接受的,最好的方法是使用智能对象来为您处理工作。 STL 的 std::vector 可能是最好的。

        如果您有非常大的数据或担心性能问题,那么您将不得不设计一种不同的方法而不复制数据。您必须实现自定义索引器 - 也就是说,避免您要求的转换。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-10-23
          • 2013-08-23
          • 2012-11-10
          • 2017-02-21
          • 2023-03-29
          • 2017-02-21
          • 2012-06-05
          相关资源
          最近更新 更多