描述:之所以我把它翻译成最值滤波器,因为它的原理就是在卷积核区域内,中心点的值如果大于或小于附近值的最大值或最小值时,将大于最大值的赋值为最大值,将小于最小值的赋值为最小值,这就是Conservative Smoothing Filter
如下图所示:
这上面的图表明中间点150要换成127,简单点讲就是大于最大值的等于最大值,小于最小值的等于最小值,在最小值和最大值之间的值不变。
Code:
/** * Finds the maximum value from a 3x3 pixel neighbourhood overlaid with * a 3x3 kernel (on/off). The centre pixel of the kernel is ignored. * * @param input The 2D array of pixel values representing the image. * @param kernel The array representing the kernel. * @param w The width of the image. * @param h The height of the image. * @param x The x coordinate of the centre of the 3x3 neighbourhood. * @param y The y coordinate of the centre of the 3x3 neighbourhood. * @return The maximum value. */ public static int maxNeighbour(int [][] input, int [] kernel, int w, int h, int x, int y) { int [] neighbour = new int [9]; boolean [] neighbourPresent = new boolean [9]; int max; for(int j=0;j<3;++j){ for(int i=0;i<3;++i){ if((kernel[(3*j)+i]==1)&&(((x-1+i) > 0)&&((x-1+i) < w)&&((y-1+j) > 0)&&((y-1+j) < h))) { neighbour[(3*j)+i] = input[x-1+i][y-1+j]; neighbourPresent[(3*j)+i] = true; }else{ neighbour[(3*j)+i] = 0; neighbourPresent[(3*j)+i] = false; } } } max = 0; for(int i=0;i<9;++i){ if((neighbourPresent[i])&&(neighbour[i]>max)&&(i!=4)){ max = neighbour[i]; } } return max; } /** * Finds the minimum value from a 3x3 pixel neighbourhood overlaid with * a 3x3 kernel (on/off). The centre pixel of the kernel is ignored. * * @param input The 2D array of pixel values representing the image. * @param kernel The array representing the kernel. * @param w The width of the image. * @param h The height of the image. * @param x The x coordinate of the centre of the 3x3 neighbourhood. * @param y The y coordinate of the centre of the 3x3 neighbourhood. * @return The minimum value. */ public static int minNeighbour(int [][] input, int [] kernel, int w, int h, int x, int y) { int [] neighbour = new int [9]; boolean [] neighbourPresent = new boolean [9]; int min; for(int j=0;j<3;++j){ for(int i=0;i<3;++i){ if((kernel[(j*3)+i]==1)&&(((x-1+i) > 0)&&((x-1+i) < w)&&((y-1+j) > 0)&&((y-1+j) < h))){ neighbour[(3*j)+i] = input[x-1+i][y-1+j]; neighbourPresent[(3*j)+i] = true; }else{ neighbour[(3*j)+i] = 0; neighbourPresent[(3*j)+i] = false; } } } min = 255; for(int i=0;i<9;++i){ if((neighbourPresent[i])&&(neighbour[i]<min)&&(i!=4)){ min = neighbour[i]; } } return min; }
/** * Takes an image and a kernel and applies conservative smoothing to it. * * @param input The 1D array representing the image. * @param kernel The array representing the kernel. * @param width The width of the image. * @param height The height of the image. * @return The array representing the new smoothed image. */ public static int [] smooth_image (int [] input, int [] kernel, int width, int height) { int [][] inputArrays = new int [width][height]; int [][] outputArrays = new int [width][height]; inputArrays = generateInputArrays(input,width,height); for(int j=0;j<height;++j){ for(int i=0;i<width;++i){ int max = maxNeighbour(inputArrays,kernel,width,height,i,j); int min = minNeighbour(inputArrays,kernel,width,height,i,j); // compare to max/min if(emptyKernel(kernel)){ outputArrays[i][j]=inputArrays[i][j]; } else if(inputArrays[i][j]>max){ outputArrays[i][j]=max; }else if(inputArrays[i][j]<min){ outputArrays[i][j]=min; } else{ outputArrays[i][j]=inputArrays[i][j]; } } } return generateOutputArray(outputArrays,width,height); } public int [][] smooth(int [][] inputArrays, int [] kernel, int width, int height){ int [][] outputArrays = new int [width][height]; for(int j=0;j<height;++j){ for(int i=0;i<width;++i){ int max = maxNeighbour(inputArrays,kernel,width,height,i,j); int min = minNeighbour(inputArrays,kernel,width,height,i,j); //compare to max/min if(emptyKernel(kernel)){ outputArrays[i][j]=inputArrays[i][j]; } else if(inputArrays[i][j]>max){ outputArrays[i][j]=max; }else if(inputArrays[i][j]<min){ outputArrays[i][j]=min; } else{ outputArrays[i][j]=inputArrays[i][j]; } }} return outputArrays; } public int [] smoothImage (int [] input, int width, int height, int [] kernel, int kernelWidth, int kernelHeight) { int [] outputArray = new int [width*height]; int [][] inputArrays = new int [width][height]; int [][] outputArrays = new int [width][height]; for(int j=0;j<height;++j){ for(int i=0;i<width;++i){ inputArrays[i][j] = input[j*width+i]; } } outputArrays = smooth(inputArrays,kernel,width,height); for(int j=0;j<height;++j){ for(int i=0;i<width;++i){ outputArray[j*width+i] = outputArrays[i][j]; } } return outputArray; } }
Output Image:
总结:从效果来看还是比较理想的,之说以在这里举例含有椒盐噪声的图像进行试验,是为了更好的说明最值滤波器比前面三种滤波器对椒盐噪声有更好的处理效果,不信,您可以试试看。