Hello,

I am trying to impliment a guassian blur filter in C++, but i cannot progress asi keep getting a Floating point exception every time i run it. I am unsure as to why, i have narrowed the error down to somewhere within the function gaussian_mask() which creates the gaussian mask.

Any help will be greatly appreciated :)

/Knad

#ifndef CANNY_ALGORITHM
#define CANNY_ALGORITHM
#define pi 3.14159

int mask[5][5];
int max =0;
double temp;

void gaussian_mask(int dev = 1) {
	for(int j=-2;j<3;j++)	// create the mask for gaussian filter
		for(int i=-2;i<3;i++) {
			temp = (1 / (dev * sqrt(2 * pi))) * exp(-(pow(i,2) + pow(j,2)) / 2 * pow(dev,2));
			mask[i + 2][-j + 2]=int(temp);
			}
	
	for(int i=0; i<5;i++)	//find max mask value for normalization
		for(int j=0;j<5;j++) {
			if(i==0 && j==0)
				max=mask[i][j];
			else if (mask[i][j]>max)  
				max=mask[i][j];
		}

	for(int i=0; i<5;i++) 	//normalize mask
		for(int j=0;j<5;j++)
			mask[i][j]=mask[i][j] / max;
}

////Convolve algorithm for mask (for multidimensional arrays we must define array size)
int convolve_gauss(BwImage imgGrey, int x, int y, int k[][5]) {
	int xx, yy, r=0;
	for(xx=-1;xx<=1;xx++)
		for(yy=-1;yy<=1;yy++)
			r+= imgGrey[x+xx][y+yy] * k[xx+1][yy+1];

	return r;
}//convolve gauss

////Main canny algorithm
IplImage* canny (IplImage* img) {

  int sx, sy;
  BwImage imgGrey (img);
  ///////////////////////////////////////
  ////ERROR APPEARS WHEN I CALL THIS/////
  ///////////////////////////////////////
  gaussian_mask();

  // get the image data
  int height    = img->height;
  int width     = img->width;

  //Gaussian Blur
  for(int x=1; x < width; x++)
	for(int y=1; y < height; y++) {
		sx = convolve_gauss(imgGrey, x, y, mask);		
		sy = convolve_gauss(imgGrey, x, y, mask);		
		imgGrey[x][y] = (sx+sy)/2;
	}

  return imgGrey.returnImg();
}

#endif

Recommended Answers

All 10 Replies

I don't know about your floating point error, but you are wasting a bit of time here. Because of the way this equation for generating the gaussian mask works, the maximum will always be at i = 2, j = 2 (in the way that you have defined it). More generally, the maximum will be at
[tex]\frac{W - 1}{2}[/tex], where [tex]W[/tex] is 5 in your case. Thus you don't have to go to the both of searching through all the elements to find it (as you do on lines 16-22) :-)

Thanks for the tip, i really should have realised that myself! Now justto get the thing to run without the exception

/Knad

> for(int x=1; x < width; x++)
Since your convolve involves looking at +/- 1 from the specified XY position, you're stepping off the right/bottom edge of your image and into big trouble.

> return imgGrey.returnImg();
What exactly is this returning?
Not a pointer to a local variable by any chance?

> mask[j]=mask[j] / max;
You might want to assert that max is NOT zero before you do this.

Hey, fixed those errors, and found that i was in fact dividing by 0, fixed by changing 'dev' to a float.

Can anyone help me with the actual function, it should be performing a gaussian blur, but its output is very odd...

Code and output attached.

/Knad

#ifndef CANNY_ALGORITHM
#define CANNY_ALGORITHM
#define pi 3.14159
#include <stdexcept>

class DivideByZero : public std::runtime_error {
public:
  DivideByZero() : std::runtime_error("DivideByZero") { }
};

float mask[5][5];

void gaussian_mask(float dev = 1.4) {
	for(int j=-2;j<3;j++)	// create the mask for gaussian filter
		for(int i=-2;i<3;i++) {
			mask[i + 2][-j + 2]=(1 / (dev * sqrt(2 * pi))) * exp(-(pow(i,2) + pow(j,2)) / 2 * pow(dev,2));
		}

	float max = mask[2][2];

	for(int i=0; i<5;i++) 	//normalize mask
		for(int j=0;j<5;j++) {
			if ( max != 0 ) mask[i][j]=mask[i][j] / max;
			else throw DivideByZero();
		}
}

////Convolve algorithm for mask (for multidimensional arrays we must define array size)
int convolve_gauss(BwImage imgGrey, int x, int y, float k[][5]) {
	float r=0;
	for(int xx=-2;xx<3;xx++)
		for(int yy=-2;yy<3;yy++)
			r+= imgGrey[x+xx][y+yy] * k[xx+2][yy+2];

	return int(r);
}//convolve gauss

////Main canny algorithm
IplImage* canny (IplImage* img) {

  int sx, sy;
  BwImage imgGrey (img);
  gaussian_mask();

  // get the image data
  int height    = img->height;
  int width     = img->width;

  //Gaussian Blur - start at 2 and and at -1 otherwise we will fall off image in convolve
  for(int x=2; x < width-1; x++)
	for(int y=2; y < height-1; y++) {
		sx = convolve_gauss(imgGrey, x, y, mask);		
		sy = convolve_gauss(imgGrey, x, y, mask);		
		imgGrey[x][y] = (sx+sy)/2;
	}

  //Returns imgGrey as IplImage* type (for display by openCV library)
  return imgGrey.returnImg();
}

#endif

> for(int x=2; x < width-1; x++)
It should have been (IMO)
for(int x=1; x < width-1; x++)

> return int(r);
I'm going to guess that you're losing an awful lot of precision with this cast.
Blur doesn't alter the image by that much, but truncating a float to an int could be huge.

for(int x=2; x < width-1; x++)
  for(int y=2; y < height-1; y++) {
    sx = convolve_gauss(imgGrey, x, y, mask);		
    sy = convolve_gauss(imgGrey, x, y, mask);		
    imgGrey[x][y] = (sx+sy)/2;
  }

I'm not sure why you calculate both sx and sy here? You pass exactly the same arguments to convolve_gauss() to calculate each of them, so they will be equal. This means that the (sx+sy)/2 part just gives the original sx (or sy , since they're both equal). Obviously this won't clean up you image any better, but it will save some precious processor time :)

Ok so i think i have tidied up the code ALOT, but i stil cannot seem to get a gaussian blur to work. I am just getting blank output, from what i can tell 'g' is returning as '0.0' every time, and i have no idea why!

Can anyone help?
( imgRgb[x][y].g means get/set the pixel at (x,y) on the green channel (i have a green image))

/Knad

#ifndef CANNY_ALGORITHM
#define CANNY_ALGORITHM
#define pi 3.14159
#include <stdexcept>

class DivideByZero : public std::runtime_error {
public:
  DivideByZero() : std::runtime_error("DivideByZero") { }
};

float mask[5][5];

void gaussian_mask(float dev = 1.4) {
	float mask[5][5];
	for(int j=-2;j<3;j++)	// create the mask for gaussian filter
		for(int i=-2;i<3;i++) {
			mask[i + 2][-j + 2]=(1 / (dev * sqrt(2 * pi))) * exp(-(pow(i,2) + pow(j,2)) / 2 * pow(dev,2));
		}

	float max = mask[2][2];

	for(int i=0; i<5;i++) 	//normalize mask
		for(int j=0;j<5;j++) {
			if ( max != 0 ) mask[i][j]=mask[i][j] / max;
			else throw DivideByZero();
		}
	
}

////Gaussian Blur algorithm
RgbImage gaussian(RgbImage imgRgb, int width, int height) {
	gaussian_mask();
	float g;	

	for(int x=2; x < width-1; x++)
		for(int y=2; y < height-1; y++) {
			g=0.0;
			for(int xx=-2;xx<3;xx++)
				for(int yy=-2;yy<3;yy++) {
					g+= imgRgb[x+xx][y+yy].g * mask[xx+2][yy+2];
				}
			
			imgRgb[x][y].g = (int)g;
			if(g != 0.0)
			std::cout << (int)g << std::endl;
		}
	return imgRgb;
}//convolve gauss

////Main canny algorithm
IplImage* canny (IplImage* img) {

  RgbImage imgRgb (img);
  // get the image data
  int height    = img->height;
  int width     = img->width;

  imgRgb = gaussian(imgRgb, width, height);

  //Returns imgRgb as IplImage* type (for display by openCV library)
  return imgRgb.returnImg();
}

#endif

Ok i found i was declaring 'mask' twice, the one in the function was taking over and then getting lost lol.

It now runs, but it it behaving like a gaussian NOISE filter, rather than Blur, not quite what i wanted lol! I assume there is just some minor error somewhere? Any ideas?

Thanks alot for all the help so far :)

Create a trivial image (3x3 seems to be the minimum size) and trace it through.

Here's a thought, are you copying the new "blurred" result into the old image, or a new image?
If you're writing to the old image, won't you end up blurring the same pixel multiple times?

It works :) final adjustment was to leave the original image alone and to put the new pixel values into a fresh one.
Final code (well not final, but it works :) ) if anyone is interested

//#ifndef CANNY_ALGORITHM
#define CANNY_ALGORITHM
#define pi 3.14159
#include <stdexcept>

class DivideByZero : public std::runtime_error {
public:
  DivideByZero() : std::runtime_error("DivideByZero") { }
};

float mask[5][5];

void gaussian_mask(float dev) {
	for(int j=-2;j<3;j++)	// create the mask for gaussian filter
		for(int i=-2;i<3;i++) {
			mask[i + 2][-j + 2]=(1 / (dev * sqrt(2 * pi))) * exp(-(pow(i,2) + pow(j,2)) / 2 * pow(dev,2));
		}

	float max = mask[2][2];

	for(int i=0; i<5;i++) 	//normalize mask
		for(int j=0;j<5;j++) {
			if ( max != 0 ) mask[i][j]=mask[i][j] / max;
			else throw DivideByZero();
		}
	
}

////Gaussian Blur algorithm
RgbImage gaussian(RgbImage imgRgb, int width, int height) {
	float r,g,b;	
	RgbImage output (cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,3));

	for(int x=2; x < width-1; x++)
		for(int y=2; y < height-1; y++) {
			r=0.0;g=0.0;b=0.0;
			for(int xx=-2;xx<3;xx++)
				for(int yy=-2;yy<3;yy++) {
					r+= imgRgb[x+xx][y+yy].r * mask[xx+2][yy+2];
					g+= imgRgb[x+xx][y+yy].g * mask[xx+2][yy+2];
					b+= imgRgb[x+xx][y+yy].b * mask[xx+2][yy+2];
				}
			
			output[x][y].r = (int)(r/5);
			output[x][y].g = (int)(g/5);
			output[x][y].b = (int)(b/5);
		}
	return output;
}//convolve gauss

////Main canny algorithm
IplImage* canny (IplImage* img, float dev = 1.4) {
  gaussian_mask(dev);  //Calculate gaussian mask
  RgbImage imgRgb (img);

  // get the image data
  int height    = img->height;
  int width     = img->width;

  imgRgb = gaussian(imgRgb, width, height);

  //Returns imgRgb as IplImage* type (for display by openCV library)
  return imgRgb.returnImg();
}

//#endif
commented: Glad you got there in the end :) +13
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.