我正在写一个最大过滤器.这将用周围9个像素的最大通道强度替换每个像素RGB通道



这是我正在使用的代码。当我运行它时,它似乎不会改变图像中的任何东西,除了它的最后1/4。那部分变成了纯色。

    void maxFilter(pixel * data, int w, int h)
    {
    GLubyte tempRed;
    GLubyte tempGreen;
    GLubyte tempBlue;
    int i;
    int j;
    int k;
    int pnum = 0;
    int pnumWrite = 0;
    for(i = 0 ; i < (h - 2); i+=3) {
    for(j = 0 ; j < (w - 2); j+=3) {
        tempRed = 0;
        tempGreen = 0;
        tempBlue = 0;
        for (k = 0 ; k < 3 ; k++){
        if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
        if ((data[pnum].g) > tempGreen){tempGreen = (data[pnum + k].g);}
        if ((data[pnum].b) > tempBlue){tempBlue = (data[pnum + k].b);}
        if ((data[(pnum + w)].r) > tempRed){tempRed = (data[(pnum + w)].r);}
        if ((data[(pnum + w)].g) > tempGreen){tempGreen = (data[(pnum + w)].g);}
        if ((data[(pnum + w)].b) > tempBlue){tempBlue = (data[(pnum + w)].b);}
        if ((data[(pnum + 2 * w)].r) > tempRed){tempRed = (data[(pnum + 2 * w)].r);}
        if ((data[(pnum + 2 * w)].g) > tempGreen){tempGreen = (data[(pnum + 2 * w)].g);}
        if ((data[(pnum + 2 * w)].b) > tempBlue){tempBlue = (data[(pnum + 2 * w)].b);}
        pnum++;
        }
        pnumWrite = pnum - 3;
        for (k = 0 ; k < 3 ; k++){
            ((data[pnumWrite].r) = tempRed);
            ((data[pnumWrite].g) = tempGreen);
            ((data[pnumWrite].b) = tempBlue);
            ((data[(pnumWrite + w)].r) = tempRed);
            ((data[(pnumWrite + w)].g) = tempGreen);
            ((data[(pnumWrite + w)].b) = tempBlue);
            ((data[(pnumWrite + 2 * w)].r) = tempRed);
            ((data[(pnumWrite + 2 * w)].g) = tempGreen);
            ((data[(pnumWrite + 2 * w)].b) = tempBlue);
            pnumWrite++;
        }
        }
    }
    }

我可以看到该代码有几个问题——很难理解,一点也不!

我认为您的主要问题是循环(正如您可能想要的那样)运行h/3 * w/3次,对于图像中的每个3x3块运行一次。但是,对于每个块,pnum索引运行仅增加3,并且达到大约h*w/3的最大值,而不是预期的h*w。这意味着只有图像的前三分之一会受到过滤器的影响。(我怀疑你的画是"自下而上"完成的,所以这就是为什么你会看到最低部分的变化。我记得.bmp文件的结构是这样的,但也许还有其他的。)

"廉价"的解决方案是在正确的位置添加2*w,但没有人会再理解那个代码。我建议您重写索引,并在循环的每个循环中从ij显式计算pnum。为了可读性,这一点可以改进,但相当清晰。

还有一件小事:你有类似的代码

if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}

右边和左边的索引不同:这可能也会给你带来与预期不同的结果。

正如Jongware所指出的,写入输入数组总是很危险的——我相信,你的代码是为了避免这个问题,只对每个3x3块进行一次检查,但他关于单独输出数组的建议是非常明智的——你可能无论如何都不想要你的代码所带来的块状(你让每个3x3区块都是一种颜色,不是吗?),他的建议会让你避免这种情况。

最新更新