Reputation: 51
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:
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?
Upvotes: 5
Views: 46895
Reputation: 354
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.
Upvotes: 0
Reputation: 50667
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);
Upvotes: 12