3
votes

I want to create a method to blur a 24 bit image using 3x3 Gaussian kernel.

I was given the following things.

The 3x3 Gaussian kernel:

http://i.stack.imgur.com/YAEQR.png

A is the original image and B is the resulting image.

B(i,j) =
1/16 * A(i-1,j-1) +1/8 * A(i,j-1) +1/16 * A(i+1,j-1) +1/8 * A(i-1,j) +1/4 * A(i,j) +1/8 *A(i+1,j) +1/16 * A(i-1,j+1) +1/8 * A(i,j+1) +1/16 * A(i+1,j+1)  

The method:

public static BufferedImage gaussianBlur(Image img)

where img is a reference variable of an input image.
The returned value is an address of an object of the resulting image.

Should I divided the image into 9 parts to implement this method?

2
Why would you do that?Oliver Charlesworth
What you have to take into account is to use the old values of the image and not the new ones.RamonBoza

2 Answers

11
votes

You don't need to divide it to 9 parts. At least, I don't see a good reason to do this.

But you'd better be careful during this process, remember to copy image data to somewhere and always use this data for computation for new image, avoid to use new image data to compute new image.


Also, I don't understand why you need to write your own function to Gaussian blur a image. This can be easily be done as follows:

float[] matrix = {
    1/16f, 1/8f, 1/16f, 
    1/8f, 1/4f, 1/8f, 
    1/16f, 1/8f, 1/16f, 
};

BufferedImageOp op = new ConvolveOp( new Kernel(3, 3, matrix) );
blurredImage = op.filter(sourceImage, destImage);
0
votes

Don't divide it into parts. what if you have big image. what you should do is to first write a function that checks if the filter is within the image bounds. in C it would be some thing like this:

int filterWithinImage(Matrix m1, Matrix m2, int i, int j) {
  int b; //min number of pixels that the center of the filter needs to be
         // away from any border of the image to be inbounds


  /***********************odd size filter only*************************/
  //when filter size is odd there is well defined convenient center
  // of the filter
  if (isOdd(m2.height) && isOdd(m2.width)) {
    //to check the bounds subtract 1 from the width and divide by 2
    b = (m2.width - 1) / 2;
    //look at the left border
    if ((j - b)<0) return 0;
    //top border
    if ((i - b)<0) return 0;
    //right border
    if ((j + b)>(m1.width-1)) return 0;
    //bottom border
    if ((i + b)>(m1.height -1)) return 0;
  }
  return 1;
}

than write separate function for calculating the intensities:

double calculateValue(Matrix m1,Matrix m2,int imagei, int imagej) {
  double out = 0;//return value
  int i, j, fli, flj; //for iterating over the filter
  int b = (m2.height -1) / 2;//max number that we add to the center coordinates
                            //to get to the edge of the filter
  fli = 0; flj = 0;
  for(i = imagei - b; i < imagei + b +1; i++) {
    for(j = imagej - b; j < imagej + b +1; j++) {
          //    if (i == 599)
      //printf("calc func image i: %d,  image j %d, b %d,  filter i %d,  filter j %d\n",
      // i,j,b,fli,flj);      
      out += m1.map[i][j] * m2.map[fli][flj++];
    }
    fli++;
    flj=0;
  }
  return out;
}

then just write applyFilter m2 is the filter that you need to rotate 180 degrees. Matrix applyFilter(Matrix m1, Matrix m2) { int x,y; //rotate filter first Matrix rotFilter = createMatrix(m2.height,m2.width); for (x = 0; x < m2.height; x++) for (y = 0; y < m2.width; y++) { rotFilter.map[y][x] = m2.map[m2.height-y-1][m2.width-x-1]; }

  Matrix mOut = createMatrix(m1.height, m1.width);
  int i,j;
  for (i = 0; i < m1.height; i++) {
    for (j = 0; j < m1.width; j++) {
      if (!filterWithinImage(m1,rotFilter,i,j)) { //filter is out of bounds
    mOut.map[i][j] = 0;
      }
      else {
    mOut.map[i][j] = calculateValue(m1,rotFilter,i,j);
      }
    }
  }
  return mOut;
}

this is a general approach that would have to modified to fit java data structures, but the algorithms are the same.