I was wondering what the correct way would be to apply filter to a image. The image processing textbook that I am reading only talks about the mathematical and theoretical aspect of filters but doesn't talk much the programming part of it !

I came up with this pseudo code could some one tell me if it is correct cause I applied the sobel edge filter to a image and I am not satisfied with the output. I think it detected many unnecessary points as edges and missed out on several points along the edge.

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;
}
有帮助吗?

解决方案 2

Your code doesn't look quiet right to me. In order to apply the filter to the image you must apply the discrete time convolution algorithm http://en.wikipedia.org/wiki/Convolution.

When you do convolution you want to slide the 3x3 filter over the image, moving it one pixel at a time. At each step you multiply the value of the filter 'pixel' by the corresponding value of the image pixel which is under that particular filter 'pixel' (the 9 pixels under the filter are all affected). The values that result should be added up onto a new resulting image as you go.

Thresholding is optional...

The following is your code modified with some notes:

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)
{
    ...
}

Please note that the code above does not handle the edges of the image exactly right. If you wanted to make it absolutely perfect you'd start by sliding the filter mostly off screen (so the first position would apply the lower right corner of the filter to the image 0,0 pixel of the image. Doing this is really a pain though, so usually its easier just to ignore the 2 pixel border around the edges.

Once you've got that working you can experiment by sliding the Sobel filter in the horizontal and then the vertical directions. You will notice that the filter acts most strongly on lines which are perpendicular to the direction of travel (to the filter). So for the best results apply the filter in the horizontal and then the vertical direction (using the same newImage). That way you will detect vertical as well as horizontal lines equally well. :)

其他提示

Two issues:

(1) The sober operator includes x-direction and y-direction, they are int filter[][] = {{1d,0d,-1d},{2d,0d,-2d},{1d,0d,-1d}}; and

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

(2) The convolution part:

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

You have some serious undefined behavior going on here. The array filter is 3x3 but the subscripts you're using i+k and j+l are up to the size of the image. It looks like you've misplaced this addition:

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

Use GPUImage, it's quite good for you.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top