如何使用矢量索引获得摩尔邻域

时间:2016-08-24 20:04:57

标签: algorithm

我在RcppC++ R)中有一个矩阵,它按列顺序存储在内存中。即,它看起来像:

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25

现在,我有一个for循环,从i = 125(请记住,它全部为零,但是为了方便,我只是说一个) 。

对于矩阵的每个元素,我想要它的摩尔邻域。对于不在边缘的元素,这很容易。因此,如果我们选择的索引为idx且方阵的大小为nrow,那么我们有

leftmid = idx - nrow 
lefttop = (idx - nrow) - 1
leftbot = (idx - nrow) + 1

rightmid = idx + nrow
righttop = (idx + nrow) - 1
rightbot = (idx + nrow) + 1

midtop = idx - 1
midbot = idx + 1

但我无法弄清楚如何处理边缘情况。例如,如果idx = 3,那么我想要邻居:

leftmid = 23
lefttop = 22
leftbot = 24

rightmid = 8
righttop = 7
rightbot = 9

midtop = 2
midbot = 4

在角落情况下也有点复杂。我的目标是减少时间。我目前正在使用双循环运行我的程序,但是速度慢于合理。我想将其更改为单个for循环以提高性能。

编辑:我意识到leftright边界可以通过模数获得。所以3 - 5 %% 25 = 23。但我仍然有顶边和底边的情况。

1 个答案:

答案 0 :(得分:0)

看起来你对“循环”边界条件感兴趣,其中矩阵具有环形拓扑,即顶部环绕到底部,右边环绕到左边。

使用四个循环进行迭代可能更容易,每个循环分别在行和列上,然后分别在邻域的行和列上循环。这样的事情应该有效:

int mooreNeighbors[3][3];
int nRows = 5;
int nCols = 5;

// Loop over the rows and columns of the matrix
for (int i = 0; i < nRows; ++i) {
    for (int j = 0; j < nCols; ++j) {

        // Loop over the cyclic Moore neighborhood
        for (int mnI = 0; mnI < 3; ++mnI) {
            for (int mnJ = 0; mnJ < 3; ++mnJ) {

                // Sub-matrix indices
                int subI = (i - mnI - 1) % nRows;
                int subJ = (j - mnJ - 1) % nCols;

                // Index into column-dominant matrix
                int idx = subI + subJ*nRows;

                mooreNeighbors[mnI][mnJ] = matrix[idx]; 
            }
        }
    }
}

我没有尝试过编译,但它应该接近正确和清晰,以纠正任何错误。把它想象成伪代码。

另外,我更倾向于清晰度而不是最优性。例如,您不必在最内层循环中执行所有操作。