// Authors: Unknown. Please, if you are the author of this file, or if you // know who are the authors of this file, let us know, so we can give the // adequate credits and/or get the adequate authorizations. #include "filter.h" /////////////////////////////////////////////////////////////// Build Gaussian filters float * directional_gauss_filter(float xsigma, float ysigma, float angle, int *kwidth, int *kheight) { int ksize = (int)(2.0 * 2.0 * MAX(xsigma, ysigma) + 1.0); float *kernel = new float[ksize*ksize]; float xsigma2 = xsigma*xsigma; float ysigma2 = ysigma*ysigma; int l2 = ksize/2; for(int y = -l2; y <= l2; y++) for(int x = -l2; x <= l2; x++) { float a = (float) angle * PI / 180.0f; float sina = sin(a); float cosa = cos(a); float ax = (float) x * cosa + (float) y * sina; float ay = -(float) x * sina + (float) y * cosa; kernel[(y+l2) * ksize + x + l2] = exp(-(ax*ax)/(2.0f*xsigma2) - (ay*ay)/(2.0f*ysigma2) ); } float sum=0.0; for(int i=0; i < ksize*ksize; i++) sum += kernel[i]; for(int i=0; i < ksize*ksize; i++) kernel[i] /= sum; *kwidth = ksize; *kheight = ksize; return kernel; } /* Convolution with a kernel */ /* No padding applied to the image */ void convol(float *u,float *v,int width,int height,float *kernel,int kwidth,int kheight) { // float S; // int K2,L2,m,n,kmin,kmax,lmin,lmax,l,k; int K2 = kwidth / 2; int L2 = kheight / 2; for(int y=0 ; y < height; y++) for (int x=0 ; x < width; x++) { float S = 0.0; // kmax = MIN(kwidth-1,n+K2); // kmin = MAX(0,1+n+K2-width); // lmax = MIN(kheight-1,m+L2); // lmin = MAX(0,1+m+L2-height); for (int l = -L2; l <= L2; l++) for (int k = -K2 ; k<= K2; k++) { int px=x+k; int py=y+l; if (px>=0 && px < width && py>=0 && py=0 && y0>=0 && x0 < width && y0 < height) { vector[count] = u[y0*width+x0]; index[count] = count; count++; } } quick_sort(vector,index,count); v[y*width+x] = vector[count/2]; } copy(v,u,width*height); } delete[] vector; delete[] index; } void remove_outliers(float *igray,float *ogray,int width, int height) { int bloc=1; int bsize = (2*bloc+1)*(2*bloc+1)-1; for(int x=bloc;xvalueg) countmax++; if (valueg0=0 && s=width2) s-=width2; if (s>=width) s = width2-1-s; sum += xkernel[i]*u[y*width+s]; break; } } tmp[y*width+x] = sum; } /* convolution along y axis */ org = ysize / 2; for (int y=height;y--;) for (int x=width;x--;) { sum=0.0; for (int i=ysize;i--;) { int s = y-i+org; switch(boundary) { case 0: if (s>=0 && s=height2) s-=height2; if (s>=height) s = height2-1-s; sum += ykernel[i]*tmp[s*width+x]; break; } } v[y*width+x] = sum; } free(tmp); } void gaussian_convolution(float *u, float *v, int width, int height, float sigma) { int ksize; float * kernel; ksize = (int)(2.0 * 4.0 * sigma + 1.0); kernel = gauss(1,sigma,&ksize); int boundary = 1; copy(u,v,width*height); horizontal_convolution(v, v, width, height, kernel, ksize, boundary); vertical_convolution(v, v, width, height, kernel, ksize, boundary); delete[] kernel; /*memcheck*/ } void gaussian_convolution(float *u, float *v, int width, int height, float sigma, int ksize) { float * kernel; kernel = gauss(1,sigma,&ksize); int boundary = 1; copy(u,v,width*height); horizontal_convolution(v, v, width, height, kernel, ksize, boundary); vertical_convolution(v, v, width, height, kernel, ksize, boundary); } void fast_separable_convolution(float *u, float *v, int width, int height,float * xkernel, int xsize,float *ykernel,int ysize,int boundary) { copy(u,v,width*height); horizontal_convolution(v, v, width, height, xkernel, xsize, boundary); vertical_convolution(v, v, width, height, ykernel, ysize, boundary); } /* Loop unrolling simply sums 5 multiplications at a time to allow the compiler to schedule operations better and avoid loop overhead. */ void buffer_convolution(float *buffer,float *kernel,int size,int ksize) { for (int i = 0; i < size; i++) { float sum = 0.0; float *bp = &buffer[i]; float *kp = &kernel[0]; /* Loop unrolling: do 5 multiplications at a time. */ // int k=0; for(int k = 0; k < ksize; k++) sum += *bp++ * *kp++; // for(;k + 4 < ksize; bp += 5, kp += 5, k += 5) // sum += bp[0] * kp[0] + bp[1] * kp[1] + bp[2] * kp[2] + // bp[3] * kp[3] + bp[4] * kp[4]; /* Do multiplications at a time on remaining items. */ // for(; k < ksize; bp++ , kp++, k++) sum += *bp * (*kp); buffer[i] = sum; } } /* Convolve image with the 1-D kernel vector along image rows. This is designed to be as efficient as possible. */ void horizontal_convolution(float *u, float *v, int width, int height, float *kernel, int ksize, int boundary) { int halfsize = ksize / 2; int buffersize = width + ksize; float *buffer = new float[buffersize]; for (int r = 0; r < height; r++) { /// symmetry int l = r*width; if (boundary == 1) for (int i = 0; i < halfsize; i++) buffer[i] = u[l + halfsize - 1 - i ]; else for (int i = 0; i < halfsize; i++) buffer[i] = 0.0; for (int i = 0; i < width; i++) buffer[halfsize + i] = u[l + i]; if (boundary == 1) for (int i = 0; i < halfsize; i++) buffer[i + width + halfsize] = u[l + width - 1 - i]; else for (int i = 0; i < halfsize; i++) buffer[i + width + halfsize] = 0.0; buffer_convolution(buffer, kernel, width, ksize); for (int c = 0; c < width; c++) v[r*width+c] = buffer[c]; } delete[] buffer; /*memcheck*/ } void vertical_convolution(float *u, float *v, int width, int height, float *kernel,int ksize, int boundary) { int halfsize = ksize / 2; int buffersize = height + ksize; float *buffer = new float[buffersize]; for (int c = 0; c < width; c++) { if (boundary == 1) for (int i = 0; i < halfsize; i++) buffer[i] = u[(halfsize-i-1)*width + c]; else for (int i = 0; i < halfsize; i++) buffer[i] = 0.0f; for (int i = 0; i < height; i++) buffer[halfsize + i] = u[i*width + c]; if (boundary == 1) for (int i = 0; i < halfsize; i++) buffer[halfsize + height + i] = u[(height - i - 1)*width+c]; else for (int i = 0; i < halfsize; i++) buffer[halfsize + height + i] = 0.0f; buffer_convolution(buffer, kernel, height, ksize); for (int r = 0; r < height; r++) v[r*width+c] = buffer[r]; } delete[] buffer; /*memcheck*/ } void heat(float *input, float *out, float step, int niter, float sigma, int width, int height) { int i,j,n,ksize,size,im,i1,j1,jm; float *kernel = NULL, *laplacian = NULL, *convolved = NULL; size = width*height; if (sigma > 0.0) kernel = gauss(0,sigma,&ksize); laplacian = (float *) malloc(size*sizeof(float)); convolved = (float *) malloc(size*sizeof(float)); for(n=0; n < niter; n++) { if (sigma > 0.0) { separable_convolution(input,convolved,width,height, kernel, ksize,kernel,ksize,1); for(i=0; i< size; i++) laplacian[i] = convolved[i] - input[i]; } else { for (i=0; i < width;i++) for (j=0; j< height ;j++) { if (j==0) jm=1; else jm=j-1; if (j==height-1) j1=height-2; else j1=j+1; if (i==0) im=1; else im=i-1; if (i==width-1) i1=width-2; else i1=i+1; laplacian[j*width + i] = - 4.0 * input[width*j+i] + input[width*j+im]+ input[width*j+i1]+input[width*jm + i] + input[width*j1 + i]; } } for(i=0; i < size; i++) out[i] = input[i] + step * laplacian[i]; copy(out,input,size); } free(laplacian); free(convolved); if (kernel) free(kernel); }