Symmetric Nearest Neighbor Filter

The Symmetric Nearest Neighbor Filter or Symmetric NN filter is a non-linear edge preserving image processing filter. It is a very effective noise reduction technique that removes noise while maintaining sharp image edges. This graphic filter produce results very close to these of Median and Kuwahara filters.

How Symmetric NN Filter works?

Similar to the other image processing filters, the Symmetric NN filter works using a sliding window at each image pixel. At each position, we split the pixels under the window into pairs of opposite points. Each of these pairs we compare with the central pixel and we use the closest value as an overall window sum. Similar to mean filter, the resulting pixel value is the calculated average.

symmetric nearest neighbor pixels selection
Symmetric Nearest Neighbor pixel selection
green – central pixel; red – opposite pixels

Symmetric NN WebGL Fragment Shader (GLSL)

FivekoGFX (Fiveko Graphics) library uses a GPU version of Symmetric Nearest Neighbor filter. Due to this the Symmetric NN can run pretty fast as a tiny Fragment Shader  (OpenGL GLSL). Since the modern web browsers are capable of running OpenGL Shaders using WebGL it is possible to use this filter in online environment as well. Finally you are free to look at the below code fragment of our Symmetric NN filter.

precision mediump float;

// our texture
uniform sampler2D u_image;
uniform vec2 u_textureSize;
uniform int u_pixelsCount;
#define KERNEL_SIZE %kernelSize%

void main() {
	vec2 textCoord = gl_FragCoord.xy / u_textureSize;
	vec2 onePixel = vec2(1.0, 1.0) / u_textureSize;
	vec4 meanColor = vec4(0);
	vec4 v = texture2D(u_image, textCoord);
	int count = 0;
	for (int y = 0; y <= HALF_SIZE; y++){
		for (int x = -HALF_SIZE; x <= HALF_SIZE; x++){
			vec4 v1 = texture2D(u_image, textCoord + vec2(x, y) * onePixel);  
			vec4 v2 = texture2D(u_image, textCoord + vec2(-x, -y) * onePixel);
			vec4 d1 = abs(v - v1);
			vec4 d2 = abs(v - v2);
			vec4 rv = vec4(((d1[0] < d2[0]) ? v1[0] : v2[0]),
							((d1[1] < d2[1]) ? v1[1] : v2[1]),
							((d1[2] < d2[2]) ? v1[2] : v2[2]),1);
			meanColor += rv;
	gl_FragColor = meanColor / float(u_pixelsCount);

Visit FivekoGFX on GitHub for more image processing examples

Symmetric Nearest Neighbor Demo Application

Sigma: 3


Related Articles