将滤镜应用于图像的正确方法是什么

时间:2013-12-27 03:15:21

标签: image-processing imagefilter

我想知道将滤镜应用于图像的正确方法是什么。我正在阅读的图像处理教科书只讨论过滤器的数学和理论方面,但并没有太多关注它的编程部分!

我想出了这个伪代码可以告诉我它是否正确,因为我将sobel边缘滤波器应用于图像并且我对输出不满意。我认为它检测到许多不必要的点作为边缘并错过了边缘的几个点。

Input image

Output image

int filter[][] = {{0d,-1d,0d},{-1d,8d,-1d},{0d,-1d,0d}};// I dont exactly remember the       //sobel filter
int total = 0;
for(int i = 2;i<image.getWidth()-2;i++)
    for(int j = 2;j<image.getHeight()-2;j++)
    {
        total = 0;

        for(int k = 0;k<3;k++)
            for(int l = 0;l<3;l++)
            {
                total += intensity(image.getRGB(i,j)) * filter[i+k][j+l];
            }

        if(total >= threshold){
        image.setRGB(i,j,WHITE);
    }
}

int intensity(int color)
{
    return (((color >> 16) & 0xFF) + ((color >> 8) & 0xFF) + color)/3;
}

4 个答案:

答案 0 :(得分:2)

两个问题:

(1)sober operator包括x方向和y方向 int filter[][] = {{1d,0d,-1d},{2d,0d,-2d},{1d,0d,-1d}};

int filter[][] = {{1d,2d,1d},{0d,0d,0d},{-1d,-2d,-1d}};

(2)卷积部分:

total += intensity(image.getRGB(i+k,j+l)) * filter[k][l];

答案 1 :(得分:1)

您的代码看起来并不安静。要将滤镜应用于图像,必须应用离散时间卷积算法http://en.wikipedia.org/wiki/Convolution

进行卷积时,您想要将3x3滤镜滑过图像,一次移动一个像素。在每一步中,将滤波器“像素”的值乘以该特定滤波器“像素”下的图像像素的对应值(滤波器下的9个像素都受影响)。结果的值应该在你去的时候加到一个新的结果图像上。

阈值处理是可选的......

以下是使用一些注释修改的代码:

int filter[][] = {{0d,-1d,0d},{-1d,8d,-1d},{0d,-1d,0d}};

//create a new array for the result image on the heap
int newImage[][][3] = ...

//initialize every element in the newImage to 0
for(int i = 0;i<image.getWidth()-1;i++)
    for(int j = 0;j<image.getHeight()-1;j++)
        for (int k = 0; k<3; k++)
        {
            newImage[i][j][k] = 0;
        }    

//Convolve the filter and the image
for(int i = 1;i<image.getWidth()-2;i++)
    for(int j = 1;j<image.getHeight()-2;j++)
    {
        for(int k = -1;k<2;k++)
            for(int l = -1;l<2;l++)
            {
                newImage[i+k][j+l][1] += getRed(image.getRGB(i+k ,j+l)) * filter[k+1][l+1];
                newImage[i+k][j+l][2] += getGreen(image.getRGB(i+k ,j+l)) * filter[k+1][l+1];
                newImage[i+k][j+l][3] += getBlue(image.getRGB(i+k ,j+l)) * filter[k+1][l+1];
            }
    }

int getRed(int color)
{
    ... 
}

int getBlue(int color)
{
    ...
}

int getGreen(int color)
{
    ...
}

请注意,上面的代码无法正确处理图像的边缘。如果你想让它绝对完美,你可以首先将滤镜滑动到屏幕外(因此第一个位置会将滤镜的右下角应用到图像的0,0像素。这样做真的很痛苦但是,通常更容易忽略边缘周围的2像素边界。

一旦你开始工作,你可以通过在水平方向和垂直方向上滑动Sobel滤波器来进行实验。您会注意到滤波器对垂直于行进方向(到滤波器)的线的作用最强。因此,为了获得最佳结果,请在水平方向和垂直方向上应用滤镜(使用相同的newImage)。这样你就可以同样很好地检测垂直线和水平线。 :)

答案 2 :(得分:1)

这里有一些严重的未定义行为。数组filter为3x3,但您使用i+kj+l的下标达到了图片的大小。看起来你错放了这个补充:

total += intensity(image.getRGB(i+k,j+l)) * filter[k][l];

答案 3 :(得分:0)

使用GPUImage,这对你来说非常好。