How do I implement a bilateral filter, given a gaussian filter?
A simple bilateral filter can be defined as
Inew (x,y) = Summation(j=y-n/2; j<=y+n/2)Summation(i=x-m/2; j<=x+m/2)w(i,j,x,y)I(i,j)
where common low-pass filter, such as a Gaussian filter, has a weight w(i,j,x,y) based on the distance from the center of the kernel (x,y) to each pixel (i,j). For the bilateral filter, the weight is determined based on two distances: an image space distance and a colorht space distance.
A simple C implementation is below
void convolution(uchar4 *_in, uchar4 *_out, int width, int height, int ~ halfkernelsize, float id, float cd)
{ 
  int kernelDim = 2*halfkernelsize+1;
  for(int y=0; y
  float sumWeight = 0;
  unsigned int ctrIdx = y*width + x;
  float ctrPix[3];
  ctrPix[0] = _in[ctrIdx].x;
  ctrPix[1] = _in[ctrIdx].y;
  ctrPix[2] = _in[ctrIdx].z;
  // neighborhood of current pixel
  int kernelStartX, kernelEndX, kernelStartY, kernelEndY;
  kernelStartX = x-halfkernelsize;
  kernelEndX   = x+halfkernelsize;
  kernelStartY = y-halfkernelsize;
  kernelEndY   = y+halfkernelsize; 
  for(int j= kernelStartY; j<= kernelEndY; j++)
    {       
      for(int i= kernelStartX; i<= kernelEndX; i++)
    {                       
      unsigned int idx = max(0, min(j, height-1))*width + max(0, min(i,width-1));
      float curPix[3];
      curPix[0] = _in[idx].x;
      curPix[1] = _in[idx].y;
      curPix[2] = _in[idx].z;
      float currWeight;
      // define bilateral filter kernel weights
      float imageDist = sqrt( (float)((i-x)*(i-x) + (j-y)*(j-y)) );
      float colorDist = sqrt( (float)( (curPix[0] - ctrPix[0])*(curPix[0] - ctrPix[0]) +
                       (curPix[1] - ctrPix[1])*(curPix[1] - ctrPix[1]) +
                       (curPix[2] - ctrPix[2])*(curPix[2] - ctrPix[2]) ) );
      currWeight = 1.0f/(exp((imageDist/id)*(imageDist/id)*0.5)*exp((colorDist/cd)*(colorDist/cd)*0.5));
      sumWeight += currWeight;
      _sum[0] += currWeight*curPix[0]; 
      _sum[1] += currWeight*curPix[1];
      _sum[2] += currWeight*curPix[2];
    }  
    }
  _sum[0] /= sumWeight;
  _sum[1] /= sumWeight;
  _sum[2] /= sumWeight;
  _out[ctrIdx].x = (int)(floor(_sum[0]));
  _out[ctrIdx].y = (int)(floor(_sum[1]));
  _out[ctrIdx].z = (int)(floor(_sum[2]));
  _out[ctrIdx].w = _in[ctrIdx].w;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With