循环以从根本上更改3x3阵列元素网格

时间:2013-11-06 08:05:10

标签: c++ opencv

我正在尝试制作一个循环,我可以执行以下操作: -

x x x y y y y y
x x x y y y y y
x x x y y y y y
y y y y y y y y 
y y y y y y y y 

(顺便提一下,上面是8x5网格。)

  1. 抓住标记为x
  2. 的所有值
  3. 求和所有9 x值
  4. 将x值替换为刚刚找到的总和的值
  5. 然后将所有x值乘以1/9
  6. 然后转到下一个x值块,如下所示: -
  7. y y y x x x y y
    y y y x x x y y
    y y y x x x y y
    y y y y y y y y 
    y y y y y y y y 
    

    我试过这样做: -

    for(int j=0;j<image.rows;j++)
    {
        for (int i=0;i<image.cols;i++)
        {
            for (int y=0; y < 9; y++) {
                sum = image.at<uchar>(j,i) + sum;
                change = sum/9;
            }
            image.at<uchar>(j,i) = change;
        }
    }
    

    但它不起作用。

4 个答案:

答案 0 :(得分:2)

你是逐个像素地迭代图像,但为了做你想做的事,你需要按3x3像素的组进行迭代:

for(int j = 0; j < image.rows; j += 3)
{
    for (int i = 0; i < image.cols; i += 3)
    { 
        uchar sum = 0;
        for(int x = 0; x < 3; ++x) {
            for(int y = 0; y < 3; ++y) {
                sum += image.at<uchar>(j + x,i + y);
            }
        }
        sum  /= 9;

        for(int x = 0; x < 3; ++x) {
            for(int y = 0; y < 3; ++y) {
                image.at<uchar>(j + x,i + y) = sum ;
            }
        }
    }
}

您还需要处理图像尺寸不是3的倍数的情况。

答案 1 :(得分:2)

@zakinster已经为您提供了一个很好的解决方案,但我建议您使用OpenCV的功能来执行平均值或设置值的计算等操作,而不是使用循环。这将创建更短,更易读的解决方案。此外,当图像不是3的倍数时,你必须确保算法能够工作。对于这种情况,通常的C ++技巧是使用(x / 3 * 3)而不是x。

代码应如下所示:

for(int j=0; j<image.rows/3*3; j+=3)
    for(int i=0; i<image.cols/3*3; i+=3)
    {
        Mat tmp(image,Rect(i,j,3,3));
        tmp.setTo(mean(tmp));
    }

相同代码的更短但可读性更低的版本:

for(int j=0; j<image.rows/3*3; j+=3)
    for(int i=0; i<image.cols/3*3; i+=3)
        image(Rect(i,j,3,3)).setTo(mean(image(Rect(i,j,3,3))));

答案 2 :(得分:1)

    change = sum*(1/9);

1/9是整数除法,因此它将为零。请改用change = sum/9.0

答案 3 :(得分:0)

代码的问题在于你对变量y的内部循环永远不会改变值i或j。因此,第一次进入此循环时,您基本上将图像中的(0,0)处的值乘以9,然后除以9.

你将不得不找出一种基于y对i和j进行变换的方法,可能是编辑这一行:

sum = image.at<uchar>(j, i) + sum;

这样它可以处理用x标记的单元格。

然后,您需要修改在外部循环中更新i和j的方式。看起来您需要将j递增3才能跳过刚刚处理的块。

这将涉及一些想法,你需要考虑如何处理网格尺寸不是三的倍数的情况,但我首先要让内循环首先工作。