//*************************************************************************** #include <stdio.h> #include <stdlib.h> #include <math.h> #include "image.h" #include "matrix.h" #include "gaussian.h" //*************************************************************************** #define DOOG_OFFSET_FACTOR 4.0 //*************************************************************************** void FilteredImg(Matrix *Out, Matrix &Inp, FilterType filter, double sigma, double theta, int side) { int border = side; int height = Inp.nx; int width = Inp.ny; /* FFT2 */ int xs = (int) pow(2.0, ceil(log2((double)(height+2.0*border)))); int ys = (int) pow(2.0, ceil(log2((double)(width+2.0*border)))); Matrix IMG(xs,ys); int r1, r2, r3, r4; r1 = width+border; r2 = width+2*border; for (int h = 0; h < border; h++) { for (int w = 0; w < border; w++) IMG.p[h][w] = Inp.p[border-1-h][border-1-w]; for (int w = border; w < r1; w++) IMG.p[h][w] = Inp.p[border-1-h][w-border]; for (int w = r1; w < r2; w++) IMG.p[h][w] = Inp.p[border-1-h][2*width-w+border-1]; } r1 = height+border; r2 = width+border; r3 = width+2*border; for (int h = border; h < r1; h++) { for (int w = 0; w < border; w++) IMG.p[h][w] = Inp.p[h-border][border-1-w]; for (int w = border; w < r2; w++) IMG.p[h][w] = Inp.p[h-border][w-border]; for (int w = r2; w < r3; w++) IMG.p[h][w] = Inp.p[h-border][2*width-w+border-1]; } r1 = height+border; r2 = height+2*border; r3 = width+border; r4 = width+2*border; for (int h = r1; h < r2; h++) { for (int w = 0; w < border; w++) IMG.p[h][w] = Inp.p[2*height-h+border-1][border-1-w]; for (int w = border; w < r3; w++) IMG.p[h][w] = Inp.p[2*height-h+border-1][w-border]; for (int w = r3; w < r4; w++) IMG.p[h][w] = Inp.p[2*height-h+border-1][2*width-w+border-1]; } //IMG.WriteImage("PaddedInp.dbg", "gif"); Matrix F_real(xs,ys), F_imag(xs,ys), IMG_imag(xs,ys); MatrixFFT2D(&F_real, &F_imag, &IMG, &IMG_imag); // ----------- compute the GD filtered output ------------- Matrix Mask(2*side+1, 2*side+1); Matrix Padded(xs,ys), Padded_i(xs, ys); Matrix Tmp_1(xs,ys), Tmp_2(xs,ys); Matrix G_real(xs,ys), G_imag(xs,ys); switch(filter) { case GDmask: GD(&Mask, sigma, theta); break; case DOOGmask: DOOG(&Mask, sigma, theta); break; case GAUSSmask: Gaussian(&Mask, sigma, theta); break; default: cerr << "FilteredImg: Invalid filter type!!" << endl; exit(-1); break; } MatCopy(&Padded, &Mask, 0, 0, 0, 0, 2*side, 2*side); MatrixFFT2D(&G_real, &G_imag, &Padded, &Padded_i); //F_real.WriteFFTImage("PaddedOut.dbg", "gif"); //Padded.WriteImage("h.dbg", "gif"); //G_real.WriteImage("H.dbg", "gif"); // ^ stands for pixel by pixel multiplication Tmp_1 = G_real ^ F_real; Tmp_2 = G_imag ^ F_imag; IMG = Tmp_1 - Tmp_2; // ^ stands for pixel by pixel multiplication Tmp_1 = G_real ^ F_imag; Tmp_2 = G_imag ^ F_real; IMG_imag = Tmp_1 + Tmp_2; MatrixIFFT2D(&Tmp_1, &Tmp_2, &IMG, &IMG_imag); //Tmp_1.WriteImage("PaddedOut.dat"); MatCopy(Out, &Tmp_1, 0, 0, 2*border, 2*border, height+2*border-1, width+2*border-1); } //*************************************************************************** void Gaussian(Matrix *M, double sigma, double theta) { // a square mask (2*side+1)x(2*side+1) int side = (M->nx-1)/2; // Note: theta is meaningless in Gaussian() due to presence of // the term (x^2+y^2) which is rotation independent! for (int x = 0; x < 2*side+1; x++) { for (int y = 0; y < 2*side+1; y++) { M->p[x][y] = Gaussian((double) (x-side), (double) (y-side), sigma); } } } //*************************************************************************** void GD(Matrix *M, double sigma, double theta) { // a square mask (2*side+1)x(2*side+1) int side = (M->nx-1)/2; for (int x = 0; x < 2*side+1; x++) { for (int y = 0; y < 2*side+1; y++) { M->p[x][y] = GD((double) (x-side), (double) (y-side), sigma, theta); } } } //*************************************************************************** void DOOG(Matrix *M, double sigma, double theta) { // a square mask (2*side+1)x(2*side+1) int side = (M->nx-1)/2; for (int x = 0; x < 2*side+1; x++) { for (int y = 0; y < 2*side+1; y++) { M->p[x][y] = DOOG((double) (x-side), (double) (y-side), sigma, theta); } } } //*************************************************************************** // Derivative of Gaussian double GD(double x, double y, double sigma, double theta) { double xn = x*cos(theta)+y*sin(theta); double yn = -x*sin(theta)+y*cos(theta); return -xn/(sigma*sigma)*Gaussian(xn,yn,sigma); } //*************************************************************************** // Derivative of offset Gaussian double DOOG(double x, double y, double sigma, double theta) { double xn = x*cos(theta)+y*sin(theta); double yn = -x*sin(theta)+y*cos(theta); // d is the offset double d = DOOG_OFFSET_FACTOR*sigma; return (Gaussian(xn,yn,sigma) - Gaussian(xn+d,yn,sigma)); } //*************************************************************************** double Gaussian(double x, double y, double sigma) { // 0.39894228040143267794 = 1/sqrt(2*PI) return 0.39894228040143267794/sigma*exp(-(x*x+y*y)/(2.0*sigma*sigma)); } //***************************************************************************