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 :)

#ifndef CANNY_ALGORITHM
#define CANNY_ALGORITHM
#define pi 3.14159

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));
}

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

for(int j=0;j<5;j++)
}

////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/////
///////////////////////////////////////

// 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

## 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
$$\frac{W - 1}{2}$$, where $$W$$ 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

> 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?

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.

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

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

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));
}

for(int j=0;j<5;j++) {
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);

// 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))

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

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

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));
}

for(int j=0;j<5;j++) {
else throw DivideByZero();
}

}

////Gaussian Blur algorithm
RgbImage gaussian(RgbImage imgRgb, int width, int height) {
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++) {
}

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") { }
};

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));
}

for(int j=0;j<5;j++) {
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++) {
}

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