/*CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC*/ /* */ /* REMOVES NOISE OF AN IMAGE PRESERVING TEXTURE AND ENHANCING SHARPNESS */ /* USAGE: smoother image M smoothing sharpening */ /* smoother is the name of the executable */ /* image is the file name of the raw ppm image (with no .ppm) */ /* 2<=M<=128 is the local window size (8 is recommended) */ /* smoothing>=0 is the desired smoothing (150 is recommended) */ /* 1<=sharpness is the sharpness enhancement (1.1 is rec.) */ /* */ /* Copyright (c) 2000, Santiago I. Betelu */ /* Registration Number: TXu-966-423 */ /*CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC*/ #include #include #include #include /************************************************************************/ /* THIS ROUTINE SMOOTHES A TWO DIMENSIONAL IMAGE OF DIMENSIONS */ /* width x height STORED SEQUENTIALLY IN THE ARRAY inp[width * height]; */ /* THE COORDINATES (i,j) ARE IN inp[i*width+j]. */ /* colorlevel IS THE MAXIMUM PERMISIBLE INTENSITY VALUE OF THE IMAGE */ /* M IS THE SIZE OF THE LOCAL SMOOTHING WINDOW, WHICH HAS THE SIZE OF */ /* THE TEXTURE LENGTHSCALE (M=8 IS RECOMMENDED IF THE TEXTURE */ /* CHARACTERISTICS ARE UNKNOWN). */ /* smoothing IS THE DEGREE OF SMOOTHING, AND IS ABOUT 10 TIMES THE */ /* STANDARD DEVIATION OF THE NOISE. */ /* IF THE NOISE IS UNKNOWN, TRY TENTATIVELY WITH noise=1, 10, 100 ... */ /* FOR A FIZED VALUE sharpening=1.0. */ /* sharpening IS THE SHARPENING ENHANCEMENT. sharpening>1 */ /* SHARPENS THE IMAGE AND sharpening<1 BLURS IT. */ /************************************************************************/ void smooth(unsigned char inp[], int width, int height, int colorlevel, int &M, float smoothing, float sharpening, int compo); /***********************************************************************/ /* ANY STANDARD */ /* TWO DIMENSIONAL MxM NON-NORMALIZED COMPLEX FOURIER TRANSFORM OF */ /* THE TWO-DIMENSIONAL ARRAY window WITH REAL PART IN window[i][j] AND */ /* IMAGINARY PART IN window [i][j+M]. */ /* SIZE OF window IS 128x256. RETURNS THE RESULT IN THE SAME ARRAY. */ /* M= 2**logM AND direction=1 IS FORWARD TRANSFORM, direction=-1 IS */ /* THE INVERSE TRANSFORM */ /***********************************************************************/ void ft(float window[128][256], int M, int logM, int direction); /**********************************************************************/ /* ANY STANDARD */ /* FOURIER TRANSFORM FOR ARRAYS OF SIZE M=2**logM */ /* REAL PART IS STORED IN a[0], a[1], ... a[M-1] */ /* IMAGINARY PART IS IN a[M], a[M+1], ... a[2*M-1] */ /* RETURNS THE NON-NORMALIZED COMPLEX FOURIER TRANSFORM IN a[] */ /**********************************************************************/ void fastfourier(float a[], int M, int logM, int direction); /*********************************************************************/ /* MAIN READS AN IMAGE, FILTERS IT AND SAVES THE RESULT */ /*********************************************************************/ int main(int numberargs, char** args) { unsigned char *inp, *comp; int width,height,colorlevel,M,i; FILE *fp; char renglon[82],name[82]; float smoothing,sharpening; /* READS THE ARGUMENTS */ if(numberargs!=5){ printf("Arguments: \n"); printf(" image name (with no .ppm termination)"); printf(" window size (power of 2, rec 8)\n"); printf(" smoothing strength 0..infinity, (rec 150)\n"); printf(" sharpening, (rec 1.1)\n"); exit(1); } M=atoi(args[2]); if(M>128){ printf("M must be <=128 \n"); exit(1); } if(M==-1) printf("Copyright (c) 2000, Santiago I. Betelu, all rights reserved\n"); smoothing= atof(args[3]); sharpening= atof(args[4]); /* READS THE IMAGE */ strcpy(name,args[1]); strcat(name,".ppm"); fp = fopen(name, "r"); if (fp==NULL) { printf("Error opening file %s\n",name); return 0; } fgets(renglon, 82, fp); if(strncmp(renglon,"P6",2)==0){ fgets(renglon, 82, fp); while (renglon[0] == '#') fgets(renglon, 82, fp); sscanf(renglon, "%d %d\n", &width, &height); printf("width=%d height=%d ", width, height); fscanf(fp, "%d", &colorlevel); printf("max colorlevel is %d\n", colorlevel); fgets(renglon, 82, fp); } else { printf("the image is not in ppm format\n"); fclose(fp); } comp= new unsigned char[width*height]; inp= new unsigned char[3*width*height]; if (inp==NULL||comp==NULL) { printf("No enough memory\n"); fclose(fp); return 0; } fread(inp, sizeof(unsigned char), 3*width*height, fp); fclose(fp); /*END READING IMAGE */ for(i=0;i=height)i2= height-2-(i2-height); for(j1=0;j1=width)j2= width-2-(j2-width); window[i1][j1]=inp[i2*width+j2]; window[i1][j1+M]=0; } } ft(window,M,logM,1); /* COMPUTES SUPER-SIMPLYFIED PSEUDO-LOCAL WIENER FILTER */ q=smoothing*M*M+1.e-6; s=sharpening; /* ky0 IS TO AVOID PROCESSING kx=ky=0 */ ky0=1; for(kx=0; kx=0&&i2=0&&j2colorlevel)w=colorlevel; if(w<0)w=0; inp[in]=int(w); } } /******************************************************************/ void fastfourier(float f[], int M, int logM, int direction){ /* THIS FFT WORKS FOR ARRAYS f[0], f[1], ..., f[M-1]; M=2**logM */ int i,j,k,l,nl,halfnl,in; float ur,ui,wr,wi,tr,ti; const float pi=3.141592654; j=0; for(i=0;i