C++ 是否有复制2D数组中存储的相邻像素值的算法?

C++ 是否有复制2D数组中存储的相邻像素值的算法?,c++,algorithm,image-processing,multidimensional-array,pixel,C++,Algorithm,Image Processing,Multidimensional Array,Pixel,我有一个二维灰度像素值数组,看起来像 255 250 250 250 235 251 255 201 255 250 250 250 235 251 255 151 255 250 250 250 235 251 255 151 255 250 250 250 235 251 255 151 255 250 250 250 235 251 255 151 在我在网上和其他帖子中看到的实现中,该程序将获得3x3窗口区域中的相邻像素 比如说, for (row = 1; row <= num

我有一个二维灰度像素值数组,看起来像

255 250 250 250 235 251 255 201
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
在我在网上和其他帖子中看到的实现中,该程序将获得3x3窗口区域中的相邻像素

比如说,

for (row = 1; row <= numRows; ++row)
{
    for (col = 1; col <= numCols; ++col)
    {
        //neighbor pixel values are stored in window including this pixel 
        window[0] = imageArr[row - 1][col - 1];
        window[1] = imageArr[row - 1][col];
        window[2] = imageArr[row - 1][col + 1];
        window[3] = imageArr[row][col - 1];
        window[4] = imageArr[row][col];
        window[5] = imageArr[row][col + 1];
        window[6] = imageArr[row + 1][col - 1];
        window[7] = imageArr[row + 1][col];
        window[8] = imageArr[row + 1][col + 1];
        
        // do something with window
    }
}

for(row=1;row我本来不打算回答这个问题,但现在我已经在评论中写了很多了,我也可以这样做了

一般建议是简化循环,将
视为窗口的左上角,而不是中心。这使数学变得简单(因此,任何阅读代码的人都会更清楚),尤其是对于大小均匀的窗口尺寸

假设窗口为正方形(尺寸
N
),这似乎是您的需求,则外部循环将变成:

for (int row = 0; row < numRows - N; ++row)
{
    for (int col = 0; col < numCols - N; ++col)
    {
        // TODO: copy window

        // Your window's "center" if you need it
        int cx = col + N/2;
        int cy = row + N/2;

        // TODO: Do something with window...
    }
}

如果需要,将其扩展到矩形窗口非常简单,这对您来说是一个很好的练习。可以进行各种优化,但我认为根据您当前的级别,这超出了范围,实际上我不想向初学者推广优化。最好学习如何编写简单、清晰的代码。

答案是肯定的:添加两个在窗口维度上工作的额外循环,并删除所有硬连接的重复代码。注意避免溢出。即使在这里的示例中,底部和右侧边缘在
imageArr
中也会索引到边界之外。我想您是想测试大小均匀的窗口的
等s很明显,窗口的中心点不是对称的,因此需要特别注意定义有效的操作空间。更干净的解决方案可能只使用一个循环和
std::copy\n
memcpy
,甚至
std::valarray
。感谢您的回复。您能进一步解释一下添加另一个网元是什么意思吗ted for loop?有像Eigen这样的库,可以让你从一个更大的数组中提取任意子数组。对于这样的东西很有用。或者,你可以使用模板函数从另一个数组中提取类似于
std::array
,给定中心行和列。我想是时候让你坐下来在纸上画一个网格了,然后沿上边缘和左边缘写入数字(基于0)以表示列和行索引。现在在其中某处绘制一个大小为N的“窗口”。将窗口视为一个图像,因此您当然会使用两个循环来遍历每个值。其局部左上角始终位于位置(0,0)。它在图像上下文中的左上角与
的值有关。我相信你会明白的。就我个人而言,我会避免你尝试在中心点上循环的所有额外数学运算。这只会使事情复杂化,并且不会增加任何内容。只需在范围内运行主循环
[0,numRows-N)
[0,numCols-N)
,内部两个循环都
[0,N)
。如果您需要知道窗口的中心点,那么它将是
行+N/2,列+N/2
。当然,如果
窗口是1D数组,则使用2D索引是常用的标准,并且在处理基于行的图像时可能会被烧死在您的大脑中:
窗口[y*N+x]
通常。谢谢你,先生。你给了我一个很好的学习例子。我使用的是你建议的图形纸哈哈。我现在的目标是实现矩形窗口:)是的,对此很抱歉。我经常建议有人使用图形纸,而他们忽略了建议。我对你想这样做印象深刻,这应该是你的默认方法无论什么时候你需要弄明白什么。总是把纸和笔放在手边。我总是在键盘旁放一本小册子,用来涂鸦、笔记和图表。我在一美元商店买了一大堆。因为这是一本书,我没有散页可以丢/弄得一团糟,有时我需要回顾几个月前我做过的事情。什么时候我用完了这本书,我开始买一本新的,把旧的放在书架上。
// Copy window
for (int y = 0; y < N; ++y)
{
    for (int x = 0; x < N ++x)
    {
        window[y * N + x] = imageArr[row + y][col + x];
    }
}