Bilateral filter

We previously described how the Median filter is poor at performance and bilateral filter is a good supplement to it, to understand why we must look at how the filter works.

The bilateral function takes in a sigma this describes the intensity of the smoothing similar to Gaussian Blur and the kernel size. We then loop through each pixel, and we will subtract each of its neighbours with the current pixel, we will multiply this with a "weight" and set the current pixel to the mean of the value. That is a bit convoluted (ha!) but let's see the implementation.

Implementation

The Bilateral filter is implemented at src/smoothing/bilateral.c

void cv_apply_bilateral_filter(Image* img, float sigma, int kernSize) {
  /* ... */
  unsigned char* tempBytes = (unsigned char*)malloc(width * height * ch * sizeof(unsigned char));

  for (int i = 0; i < height; i++) {
	for (int j = 0; j < width; j++) {
  	unsigned char R = compute_bilateral_filter_for_channel(img, sigma, kernSize, j, i, 0);
  	unsigned char G = compute_bilateral_filter_for_channel(img, sigma, kernSize, j, i, 1);
  	unsigned char B = compute_bilateral_filter_for_channel(img, sigma, kernSize, j, i, 2);

  	tempBytes[(i * width + j) * ch + 0] = R;
  	tempBytes[(i * width + j) * ch + 1] = G;
  	tempBytes[(i * width + j) * ch + 2] = B;
	}
  }
  /* ... */
}

It's pretty apparent what we are doing here. Let's check the actual bilateral computation

So let's break down what's going on here

  • We loop through the neighbours of the centerValue

  • We then extract the difference of centre value and the current neighbour

  • From the difference we extract a rangeWeight this will define how "sharp" our smoothing is

  • totalWeightedSum is the sum of product of weight and current neighbour

  • totalSum is just the sum of the weights

  • We divide the above values and return it. This division is done to "normalise" the image so that it maintains the initial brightness or photometric symmetry, a fancier way to say that an image shares properties with its previous state.

From this we achieve the following result

Result

Original image
Bilateral filter of Sigma 3, Kernel size 9

The performance of this algorithm is a lot better than the one previously discussed.

Last updated