Hello,
I'm researching in image processing and need to develop a Gabor filter in C++ and openCV. I found a good sample on which I'm basing my code. Problem is, while I've tried to emulate much as possible the other code, mine is not producing correct results. I changed a few things to suit my context but I don't see why it is not working! Please help, because I've labored on this for this last four days! I'll paste the three functions that are of concern, as well as the code I'm emulating below mine. Thanks in advance..!
(the following is the problematic code)
unsigned char *ideas::gabor(dataStructure *data)
{
int height=data->nRows, width=data->nCols;
float lambda=5.0; float bandwidth=01.0;
//float PI = (float) System::Math::PI;
#define PI 3.14159265358979323846
float sigma = (float) (1.0/PI * sqrt(log(2.0)/2.0) *
(pow(2.0f,bandwidth) + 1.0)/(pow(2.0f,bandwidth) - 1.0) * lambda);
//Gabor filter
int filterHalfWidth = (int) (4.0*sigma + 0.5); // half width of gaussian enveloppe
int filterWidth = 2*filterHalfWidth + 1;
float norm = 0.0f;
float *gx_r=new float[filterWidth], *gx_i=new float[filterWidth],
*gy=new float[filterWidth];// all of size [filterWidth]
initializeArray(gx_r,filterWidth); initializeArray(gx_i,filterWidth); initializeArray(gy,filterWidth);
for (int i = -filterHalfWidth; i <= filterHalfWidth; ++i) {
float g = (float) exp( -(i*i) / (2.0*sigma*sigma) );
gx_r[filterHalfWidth+i] = (float) (g * cos(2.0*PI/lambda * i + 0.0));
gx_i[filterHalfWidth+i] = (float) (g * cos(2.0*PI/lambda * i + PI/2.0));
gy[filterHalfWidth+i] = g; norm += g;
}
float toto=0.0f;
for (int y = 0; y < filterWidth; ++y){
gx_r[y] /= norm;
gx_i[y] /= norm;
gy[y] /= norm;
//printf("\n gx_r: %3.5f gx_i: %3.5f gy:%3.5f ",gx_r[y],gx_i[y],gy[y]);
toto+=(gx_r[y]+gx_i[y]+gy[y]);
}
printf("\n filterHalfWidth:%3.3f, filterWidth:%3.5f",filterHalfWidth, filterWidth);
printf("\n toto:%3.3f, sigma:%3.5f, norm:%3.5f, lambda:%3.5f \n",toto, sigma, norm, lambda);
float *real=new float[width*height]; real=convolve2D(data,gx_r,gy,filterHalfWidth);
float *imaginary=new float[width*height]; imaginary=convolve2D(data,gx_i,gy,filterHalfWidth);
float *finalImage=new float[width*height]; initializeArray(finalImage, width*height);
for (int i=0; i<width*height;i++) printf(" %f",real[i]);
////////////////////////////////////////
// Combine real and imaginary component ( out = r^2 + i^2 )
////////////////////////////////////////
float max = -1.0;
for (int y = filterHalfWidth; y < height-filterHalfWidth; ++y) {
for (int x = filterHalfWidth; x < width-filterHalfWidth; ++x) {
finalImage[y*width+x] = real[y*width+x]*real[y*width+x];
//finalImage[y*width+x] += imaginary[y*width+x]*imaginary[y*width+x];
if (finalImage[y*width+x] > max) max = finalImage[y*width+x];
}
//printf(" %f",real[y*width+x]);
}
unsigned char* out=new unsigned char[width*height];
initializeArray(out, width*height);
for (int y = 0; y < height; ++y)for (int x = 0; x < width; ++x) {
finalImage[y*width+x] = 255.0/max;
out[y*width+x] = (uchar) finalImage[y*width+x];
}
return out;
}
unsigned int var1=0;
float *ideas::convolve2D(dataStructure *data, const float* fX, const float* fY, int filterHalfWidth) {
int height=data->nRows, width=data->nCols;
double *tmp = new double[height*width]; initializeArray(tmp, height*width); double ttol=0;
for (int y = 0; y < height; ++y){
for (int x = filterHalfWidth; x < width-filterHalfWidth; ++x){
for (int i = -filterHalfWidth; i <= filterHalfWidth; ++i){
tmp[y*width+x] += ((int) data->data[y*width+(x-i)]) * fX[i+filterHalfWidth];
ttol+= (int) data->data[y*width+(x-i)] * fX[i+filterHalfWidth];
}
//printf(" %f",tmp[y*width+x]);
//ttol=0;
}
//printf("\n");
}
float *output=new float[height*width]; initializeArray(tmp, height*width);
for (int y = filterHalfWidth; y < height-filterHalfWidth; ++y)
for (int x = filterHalfWidth; x < width-filterHalfWidth; ++x)
for (int i = -filterHalfWidth; i <= filterHalfWidth; ++i)
output[y*width+x] += tmp[(y-i)*width+x] * fY[i+filterHalfWidth];
return output;
}
template <class t>
void ideas::initializeArray(t *arr, int size){
//arr = new t [size];
int i=0;
while (i<size) {
arr[i]= (t) 0; ++i;
}
}
(The following is what I'm trying to emulate)
#define M_PI 3.14159265358979323846
CImg<float> convolve2D(const CImg<float> &input, const CImg<float> &fX, const CImg<float> &fY);
int main(int argc, char **argv) {
////////////////////////////////////////
// read command line arguments
////////////////////////////////////////
string infile = "c:\\tit\\lena.bmp";
string outfile = "c:\\tit\\savedimage.jpg";
float lambda = 5.0;
float bandwidth = 1.0;
/*argstream as(argc, argv);
as >> parameter("i", infile, "infile ", true);
as >> parameter("o", outfile, "outfile ", false);
as >> parameter("l", lambda, "wavelength lambda [pixel]", false);
as >> parameter("b", bandwidth, "bandwidth [octaves]", false);
as >> help();
as.defaultErrorHandling();*/
////////////////////////////////////////
// load input image
////////////////////////////////////////
CImg<float> imgInput(infile.c_str());
const int width = imgInput.dimx();
const int height = imgInput.dimy();
if ( width == 0 || height == 0 ) {
cerr << "Error when loading input image." << endl;
return -1;
}
imgInput = imgInput.get_norm_pointwise(1)/(float)imgInput.dimv(); // to grey
cout << "Resolution: "<< width << " x " << height << endl;
////////////////////////////////////////
// calculate spread of spatial gaussian
// based on bandwidth
////////////////////////////////////////
float sigma = 1.0/M_PI * sqrt(log(2.0)/2.0) *
(pow(2.0f,bandwidth) + 1.0)/(pow(2.0f,bandwidth) - 1.0) * lambda;
////////////////////////////////////////
// Create separated Gabor filter for real and imaginary component
////////////////////////////////////////
int filterHalfWidth = (int) (4.0*sigma + 0.5); // half width of gaussian enveloppe
int filterWidth = 2*filterHalfWidth + 1;
float norm = 0.0f;
CImg<float> gx_r(filterWidth), gx_i(filterWidth), gy(filterWidth);
for (int i = -filterHalfWidth; i <= filterHalfWidth; ++i) {
float g = exp( -(i*i) / (2.0*sigma*sigma) );
gx_r[filterHalfWidth+i] = g * cos(2.0*M_PI/lambda * i + 0.0);
gx_i[filterHalfWidth+i] = g * cos(2.0*M_PI/lambda * i + M_PI/2.0);
gy[filterHalfWidth+i] = g;
norm += g;
}
// normalize the gaussian
for (int y = 0; y < filterWidth; ++y){
//printf("\n gx_r: %f gx_i: %f gy:%f ",gx_r[y],gx_i[y],gy[y]);
}
gx_r /= norm; gx_i /= norm; gy /= norm;
//printf("\n filterHalfWidth:%3.3f, filterWidth:%3.5f",filterHalfWidth, filterWidth);
printf("\n norm: %3.5f lambda: %3.5f sigma: %3.5f",norm, lambda,sigma);
////////////////////////////////////////
// 1. Convolve input image with gx_r and gy --> r_component
// 2. Convolve input image with gx_i and gy --> i_component
////////////////////////////////////////
CImg<float> r_component = convolve2D(imgInput, gx_r, gy);
CImg<float> i_component = convolve2D(imgInput, gx_i, gy);
for (int y = 0; y < height; ++y){for (int x = 0; x < width; ++x) {
printf(" r: %f, \t c: %f", r_component,i_component );
}printf("\n");}
////////////////////////////////////////
// Combine real and imaginary component ( out = r^2 + i^2 )
////////////////////////////////////////
CImg<float> imgOut(width, height, 1, 1); imgOut.fill(0.0f);
float max = -1.0;
for (int y = filterHalfWidth; y < height-filterHalfWidth; ++y) {
for (int x = filterHalfWidth; x < width-filterHalfWidth; ++x) {
imgOut(x,y) = r_component(x,y)*r_component(x,y);
imgOut(x,y) += i_component(x,y)*i_component(x,y);
if (imgOut(x,y) > max) max = imgOut(x,y);
}
}
////////////////////////////////////////
// display the filtered image
////////////////////////////////////////
imgOut *= 255.0/max; // scale output range to [0;255]
CImgl<float> (imgInput, imgOut).display ("Input Image and Normalized Gabor response",'y');
if (outfile.size() > 0) imgOut.save(outfile.c_str());
return 0;
}
CImg<float> convolve2D(const CImg<float> &input, const CImg<float> &fX, const CImg<float> &fY) {
const int width = input.dimx();
const int height = input.dimy();
int filterHalfWidth = (fX.dimx()-1) / 2;
CImg<float> tmp(width, height, 1, 1); tmp.fill(0.0f); float ttol=0;
for (int y = 0; y < height; ++y){
for (int x = filterHalfWidth; x < width-filterHalfWidth; ++x){
for (int i = -filterHalfWidth; i <= filterHalfWidth; ++i){
tmp(x,y) += input(x-i,y) * fX[i+filterHalfWidth];
ttol+= input(x-i,y) * fX[i+filterHalfWidth];
}
//printf(" %f",ttol);
//ttol=0;
}
//printf("\n");
}
CImg<float> output(width, height, 1, 1); output.fill(0.0f);
for (int y = filterHalfWidth; y < height-filterHalfWidth; ++y)
for (int x = filterHalfWidth; x < width-filterHalfWidth; ++x)
for (int i = -filterHalfWidth; i <= filterHalfWidth; ++i)
output(x,y) += tmp(x,y-i) * fY[i+filterHalfWidth];
return output;
}