2

I am trying to create a guassian filter without using ConvolveOp. I am having a lot of problems trying to get this to work, i have gotten a grey scale filter to work, but for this one i am having problems finding the location of a pixels 8 neighbors, so i can apply the filter. here is what i have so far. Is this the right way to approach getting each of the pixels?

public class Gaussian implements Filter {


   public void filter(PixelImage pi) {
    Pixel[][] data = pi.getData();
    Pixel[][] original = data;


    int kernel_rows = 3;
    int kernel_cols = 3;

    // define kernel here (double loop), these are the 1/16, 2/16, etc...
    // values that you're multiplying the image pixels by
    double[][] kernel = {{1,2,1},
      {2,4,2},
      {1,2,1}};

    // iterate over each pixel in the image
    for (int row = 0; row < pi.getHeight(); row ++) {
      for (int col = 0; col < pi.getWidth(); col++) {
        // iterate over each pixel in the kernel
        for (int row_offset = 0 ; row_offset < kernel_rows ; row_offset++ ) {
          for (int col_offset = 0 ; col_offset < kernel_cols ; col_offset++ ) {

            // subtract by half the kernel size to center the kernel
            // on the pixel in question
            // ** you'll have to modify to account for boundary conditions **
            int row_index = row + row_offset - kernel_rows/2;
            int col_index = col + col_offset - kernel_cols/2;

            int r =0;
            int g =0;
            int b =0;




            r += (data[row_index][col_index].red * kernel[row_offset][col_offset])/16;
            g += (data[row_index][col_index].green * kernel[row_offset][col_offset])/16;
            b += (data[row_index][col_index].blue * kernel[row_offset][col_offset])/16;
            Pixel temp =new Pixel( r, g, b );
            original[row][col] = temp;
          }
        }
        data = original;
        pi.setData(data);

      }
    }
   }
}
CJ Powell
  • 35
  • 1
  • 11

1 Answers1

4

A convolution is essentially a quadruple nested loop: two to loop through the pixels in the image and, at each pixel, two to loop over the pixels in the kernel.

So you can clean up your code significantly with something like this:

   int kernel_rows = 3;
   int kernel_cols = 3;

   // define kernel here (double loop), these are the 1/16, 2/16, etc...
   // values that you're multiplying the image pixels by
   double[][] kernel = ... 

   // iterate over each pixel in the image
   // leave a kernel_rows/2 sized gap around the edge of the image
   // so that we don't run into IndexOutOfBounds exceptions
   // when performing the convolution
   for (int row = kernel_rows/2; row < pi.getHeight() - kernel_rows/2; row ++) {
     for (int col = kernel_cols/2; col < pi.getWidth() - kernel_cols/2; col++) {

       int r = 0;
       int g = 0;
       int b = 0;

       // iterate over each pixel in the kernel
       for (int row_offset = 0 ; row_offset < kernel_rows ; row_offset++ ) {
         for (int col_offset = 0 ; col_offset < kernel_cols ; col_offset++ ) {

           // subtract by half the kernel size to center the kernel
           // on the pixel in question
           int row_index = row + row_offset - kernel_row/2;
           int col_index = col + col_offset - kernel_cols/2

           r += data[row_index][col_index].red * kernel[row_offset][col_offset];
           g += data[row_index][col_index].green * kernel[row_offset][col_offset];
           b += data[row_index][col_index].blue * kernel[row_offset][col_offset];

         }
       }

     data[row][col] = new Pixel( r, g, b );

     }
   }
ulmangt
  • 5,343
  • 3
  • 23
  • 36
  • Ok so i edited the code above. I am getting the error that r, g,b are not initialized. I tried putting them before the loops, and even gave it a zero value initially. But i am still getting r not initialized. – CJ Powell Apr 14 '12 at 06:20
  • You'll have to initialize them all separately (edited code above). – ulmangt Apr 14 '12 at 15:30
  • Ok, so i think i got this, but i am still getting an index out of bounds exception. Is my kernel array setup properly? I know the rest of my code is good because i can get the other filters to work. Thank you so much for helping me with this! i have edited my code above. – CJ Powell Apr 15 '12 at 01:42
  • When you try to apply the kernel to the pixel at `(0,0)`, the index values `row_index` and `col_index` will be negative (centering the kernel on `(0,0)` extends it beyond the edge of the image. That's what my comment in the code about "modifying to account for boundary conditions" meant. – ulmangt Apr 15 '12 at 01:53
  • You could fix this by starting your outer loop at `1` and ending it at `kernel_rows-1` (just not calculate the convolution for the outer ring of pixels). Made some edits to the code above to indicate what I mean. Of course that's just one way to handle it. – ulmangt Apr 15 '12 at 01:56
  • Fanstatic, thank you so much for your help with this!! The processing on this is a little slow though, around 3 minutes to filter. I ended up refractoring this to get a faster method, but used this method for another photo filter. – CJ Powell Apr 16 '12 at 16:56
  • Ok, so with a little abstraction i sped up the processing time on this....THank You so much...i should of thought of that. – CJ Powell Apr 17 '12 at 04:25
  • I LOVE YOU SO MUCH! Could not get my head around convolution until now.YOU SIR ARE THE MAN! – torger Jan 03 '13 at 05:44