Version française

The Image Processing Corner


Mean Shift filter
Previous 

The Mean Shift filter is an image smoothing by averaging, which preserves contours.

It has two parameters: a pixel neighborhood and an intensity value which corresponds to the minimum gradient of a contour.

The principle is to apply the following algorithm for each pixel, one after the other :

The result with a 9x9 pixel window and a contour gradient minimal intensity of 20 per channel is illustrated below. The first row gives the input noisy images, the second row gives the results and the third and fourth rows show a detail with colors which enhance contrast.

Click to enlarge. Click to kill. Click to enlarge. Click to kill. Click to enlarge. Click to kill. Click to enlarge. Click to kill.
Click to enlarge. Click to kill. Click to enlarge. Click to kill. Click to enlarge. Click to kill. Click to enlarge. Click to kill.

Click to enlarge. Click to kill. Click to enlarge. Click to kill. Click to enlarge. Click to kill. Click to enlarge. Click to kill.
Click to enlarge. Click to kill. Click to enlarge. Click to kill. Click to enlarge. Click to kill. Click to enlarge. Click to kill.
Gaussian (sigma=20)Uniform (+/-20)Salt and pepper (3%)Periodic (jpg)

Execution time on a AMD 1800+ for the 384x288 image: 0.95 seconds for gaussian and uniform noises, 0.49 seconds for "salt and pepper" and periodic noises.

First remark: this filter preserves contours which gradient exceeds Imin.

Second remark: results on gaussian and uniform noises are excellent, compared to the strong noise added.

Third remark: This filter is not adapted to the "salt and pepper" noise. Indeed, this kind of noise is considered as a contour and is not filtered.

The source code in C of the algorithm core is given below. Undeclared variables and image structure management are without ambiguity and must be added in order to compile the program.

// Loop on pixels for(int v=0; v<sizeV; ++v) { for(int u=0; u<sizeU; ++u) { // Compute mean box int uMin = utMax(u-halfWindowSize, 0); int uMax = utMin(u+halfWindowSize, sizeU-1); int vMin = utMax(v-halfWindowSize, 0); int vMax = utMin(v+halfWindowSize, sizeV-1); // Initialize pixel filtering int startOffset = u + v*sizeU; int currentR = bufferR[startOffset]; int currentG = bufferG[startOffset]; int currentB = bufferB[startOffset]; // Filter the pixel int iterationQty = 10; // Convergence with integers is not ensured while(iterationQty--) { // Compute mean inside noise sphere int qty = 0; int sumR = 0; int sumG = 0; int sumB = 0; meanIterationQty += 1; for(int v1=vMin; v1<=vMax; ++v1) { int offset = uMin + v1*sizeU; for(int i=1+uMax-uMin; i; --i, ++offset) { if(utAbs(currentR-(int)bufferR[offset])+ utAbs(currentG-(int)bufferG[offset])+ utAbs(currentB-(int)bufferB[offset])<noiseIntensity) { sumR += bufferR[offset]; sumG += bufferG[offset]; sumB += bufferB[offset]; qty += 1; } } } // Update the color int oldR = currentR; int oldG = currentG; int oldB = currentB; currentR = sumR/qty; currentG = sumG/qty; currentB = sumB/qty; // Check the convergence if(oldR==currentR && oldG==currentG && oldB==currentB) { break; } } // End of iterations on the pixel // Store the result for this pixel resultBufR[startOffset] = (unsigned char)currentR; resultBufG[startOffset] = (unsigned char)currentG; resultBufB[startOffset] = (unsigned char)currentB; } // End of loop on columns } // End of loop on rows

Previous 

visiteurs
Generated with webSitePP.py tool
Last updated on October 20, 2004