在C++中循环遍历一个3d索引的1d数组

Looping through a 3d-indexed 1d array in C++

本文关键字:3d 一个 索引 数组 1d C++ 循环 遍历      更新时间:2023-10-16

我创建了一个类,它通过将数据存储在1D数组中并重载() operator来模仿3D布尔数组。我已经尝试了我能找到和想到的每一种方法,例如,当这段代码:

bool operator()(unsigned x, unsigned y, unsigned z) const { return _data[_zSize*_ySize*x + y*_ySize + z]; }

允许我访问我需要的每一个元素(我知道(x,y,z)实际上在这里(z,y,x),但这不取决于我),当我试图遍历数组时,我遇到了问题。考虑一个深度为3、高度为4、宽度为5的3D数组,其中每个元素都初始化为false。当我尝试反转数组中的所有值时(其中sx()返回depthsy()-heightsz()-width

for (unsigned i = 0; i < x.sx(); ++i)
        for (unsigned j = 0; j < x.sy(); ++j)
            for (unsigned k = 0; k < x.sz(); ++k)
                x(i, j, k) = !x(i, j, k);

我得到以下结果(剩下的两个表面看起来相同):

11110
01110
01110
01111

因此,很明显,有些元素被访问和反转了两次。当我尝试不同的数组索引方法时,模式会发生变化。问题出在哪里?

正确的运算符是

bool operator()(unsigned x, unsigned y, unsigned z) const { 
     return _data[_zSize*_ySize*x + y*_zSize + z]; 
}

让我给出一个具有步长的泛化方法。假设您有一个3D阵列,并且访问是在(z,y,x)中完成的

通过这个索引,我假设矩阵维数为有z个平面,每个平面的大小是y,x,y宽,y高。

我们首先需要可视化三维结构以及我们将如何访问元素。

假设我们想要访问(3,4,1)

使用基于零的索引

这里,我们z=3,y=4,x=1,我们所需的平面是第4个平面,我们所需要的行是第4,所需要的元素是第1。

因此,进入所需平面:z*(平面大小)=z*(宽度*高度)

要转到所需行,行的y*sizeo=y*(高度)//或y*Row_bytes

要进入所需点,只需添加x*sizeof(一个点)//当每个点有3或4个值时,特定于多通道数据,例如Opencv 3通道数据。

因此,最终方程式将为

考虑3个通道数据,即每个大小为uchar的点3个值,

值=z*(宽*高)+y*(高)+x*(3*大小(uchar))

因此,一旦获得"值",就不会逐个提取每个像素值。

PS:3*sizeof(uchar)取代了OpenCV中常用的Vec3b版本,用于访问3通道uchar数据。