图像处理滤波器(五)——斑点滤波器(Speckle Removal Filter)

描述:斑点滤波器是本人自己翻译的,不是通俗叫法,您记住它叫Speckle Removal Filter 就可以了,它来自于Thomas R.Crimmins 的一篇文章“Geometric Filter for Speckle Reduction”中的"The 8-Hull Algorithm",这个算法主要应用于合成孔径雷达图像(synthetic aperture radar image)去减少斑点噪声(Speckle noise)。具体算法可以去看该处提到的文章我就不具体叙述,待会代码会很详细说明的。


Part of Codes:


  /**
   * Takes a 2d array of grey level values and applies the
   * Crimmins Speckle Reduction algorithm to it for a 
   * specified number of iterations.
   *
   * @param image the input image
   * @param width of the input image
   * @param height of the input image
   * @param iterations to be applied
   * @return the new Crimminsed image
   */
  public int [][] crimminsImage(int [][] image, int width,
			   int height, int iterations){
    int [][] image2 = (int [][]) image.clone();
    for(int its=0;its<iterations;++its){
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && image[i-1][j]>image[i][j]+1){
	    image2[i][j] = image[i][j] +1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width
	     && image2[i-1][j]>image2[i][j] && image2[i+1][j]>=image2[i][j]){
	    image[i][j] = image2[i][j] +1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i+1<width && i-1>=0
	     && image[i-1][j]>=image[i][j] && image[i+1][j]>image[i][j]){
	    image2[i][j] = image[i][j] +1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i+1<width && image2[i+1][j]>image2[i][j]+1){
	    image[i][j] = image2[i][j] +1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && image[i-1][j]<image[i][j]-1){
	    image2[i][j] = image[i][j] -1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width
	     && image2[i-1][j]<image2[i][j] && image2[i+1][j]<=image2[i][j]){
	    image[i][j] = image2[i][j] -1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i+1<width && i-1>=0
	     && image[i-1][j]<=image[i][j] && image[i+1][j]<image[i][j]){
	    image2[i][j] = image[i][j] -1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i+1<width && image2[i+1][j]<image2[i][j]-1){
	    image[i][j] = image2[i][j] -1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      
      
      
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(j-1>=0 && image[i][j-1]>image[i][j]+1){
	    image2[i][j] = image[i][j] +1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(j-1>=0 && j+1<height
	     && image2[i][j-1]>image2[i][j] && image2[i][j+1]>=image2[i][j]){
	    image[i][j] = image2[i][j] +1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(j+1<height && j-1>=0
	     && image[i][j-1]>=image[i][j] && image[i][j+1]>image[i][j]){
	    image2[i][j] = image[i][j] +1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(j+1<height && image2[i][j+1]>image2[i][j]+1){
	    image[i][j] = image2[i][j] +1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(j-1>=0 && image[i][j-1]<image[i][j]-1){
	    image2[i][j] = image[i][j] -1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(j-1>=0 && j+1<height
	     && image2[i][j-1]<image2[i][j] && image2[i][j+1]<=image2[i][j]){
	    image[i][j] = image2[i][j] -1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(j+1<height && j-1>=0
	     && image[i][j-1]<=image[i][j] && image[i][j+1]<image[i][j]){
	    image2[i][j] = image[i][j] -1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(j+1<height && image2[i][j+1]<image2[i][j]-1){
	    image[i][j] = image2[i][j] -1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      
      
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i+1<width && j-1>=0
	     && image[i+1][j-1]>image[i][j]+1){
	    image2[i][j] = image[i][j] +1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width && j-1>=0 && j+1<height
	     && image2[i+1][j-1]>image2[i][j]
	     && image2[i-1][j+1]>=image2[i][j]){
	    image[i][j] = image2[i][j] +1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width && j-1>=0 && j+1<height
	     && image[i+1][j-1]>=image[i][j]
	     && image[i-1][j+1]>image[i][j]){
	    image2[i][j] = image[i][j] +1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && j+1<height
	     && image2[i-1][j+1]>image2[i][j]+1){
	    image[i][j] = image2[i][j] +1;
	  }
	else image[i][j] = image2[i][j];
	}
      }


      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i+1<width && j-1>=0
	     && image[i+1][j-1]<image[i][j]-1){
	    image2[i][j] = image[i][j] -1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width && j-1>=0 && j+1<height
	     && image2[i+1][j-1]<image2[i][j]
	     && image2[i-1][j+1]<=image2[i][j]){
	    image[i][j] = image2[i][j] -1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width && j-1>=0 && j+1<height
	     && image[i+1][j-1]<=image[i][j]
	     && image[i-1][j+1]<image[i][j]){
	    image2[i][j] = image[i][j] -1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && j+1<height
	     && image2[i-1][j+1]<image2[i][j]-1){
	    image[i][j] = image2[i][j] -1;
	  }
	else image[i][j] = image2[i][j];
	}
      }

      



      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i+1<width && j+1<height
	     && image[i+1][j+1]>image[i][j]+1){
	    image2[i][j] = image[i][j] +1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width && j-1>=0 && j+1<height
	     && image2[i+1][j+1]>image2[i][j]
	     && image2[i-1][j-1]>=image2[i][j]){
	    image[i][j] = image2[i][j] +1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width && j-1>=0 && j+1<height
	     && image[i+1][j+1]>=image[i][j]
	     && image[i-1][j-1]>image[i][j]){
	    image2[i][j] = image[i][j] +1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && j-1>=0
	     && image2[i-1][j-1]>image2[i][j]+1){
	    image[i][j] = image2[i][j] +1;
	  }
	else image[i][j] = image2[i][j];
	}
      }

      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i+1<width && j+1<height
	     && image[i+1][j+1]<image[i][j]-1){
	    image2[i][j] = image[i][j] -1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width && j-1>=0 && j+1<height
	     && image2[i+1][j+1]<image2[i][j]
	     && image2[i-1][j-1]<=image2[i][j]){
	    image[i][j] = image2[i][j] -1;
	  }
	  else image[i][j] = image2[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && i+1<width && j-1>=0 && j+1<height
	     && image[i+1][j+1]<=image[i][j]
	     && image[i-1][j-1]<image[i][j]){
	    image2[i][j] = image[i][j] -1;
	  }
	  else image2[i][j] = image[i][j];
	}
      }
      for(int j=0;j<height;++j){
	for(int i=0;i<width;++i){
	  if(i-1>=0 && j-1>=0
	     && image2[i-1][j-1]<image2[i][j]-1){
	    image[i][j] = image2[i][j] -1;
	  }
	else image[i][j] = image2[i][j];
	}
      }
    }
    return image;
  }


  /**
   * Takes a 2d image and applies Crimmins to it.
   *
   * @param input the input image
   * @param width of the input image
   * @param height of the input image
   * @param iterations to be applied
   * @return the new image
   */
  public int [][] crimmins(int [][] input, int width, int height,
			   int iterations){
    int [][] output = new int [width][height];
    for(int j=0;j<height;++j){
      for(int i=0;i<width;++i){
	input[i][j] = (new Color(input[i][j])).getRed();
      }
    }
    output = crimminsImage(input,width,height,iterations);
    
    return output;
  }


Input Image:


Output Image :


一次迭代效果:

图像处理滤波器(五)——斑点滤波器(Speckle Removal Filter)_第1张图片


四次迭代效果:


图像处理滤波器(五)——斑点滤波器(Speckle Removal Filter)_第2张图片


八次迭代效果:





总结:本算法主要应用于处理椒盐噪声上,本算法在处理椒盐噪声的同时也相应的模糊了图像的细节,而且迭代次数越多,图像细节也越来越模糊。


你可能感兴趣的:(Algorithm,image,filter,input,output,图像处理)