code: public static void process(GrayI input, GrayI output, int radius , int[] storage ) {
  
  		int w = 2*radius+1;
  		if( storage == null ) {
  			storage = new int[ w*w ];
  		} else if( storage.length < w*w ) {
  			throw new IllegalArgumentException("'storage' must be at least of length "+(w*w));
  		}
  
  		for( int y = 0; y < input.height; y++ ) {
  			int minI = y - radius;
  			int maxI = y + radius+1;
  
  			// bound the y-axius inside the image
  			if( minI < 0 ) minI = 0;
  			if( maxI > input.height ) maxI = input.height;
  
  			for( int x = 0; x < input.width; x++ ) {
  				int minJ = x - radius;
  				int maxJ = x + radius+1;
  
  				// bound the x-axis to be inside the image
  				if( minJ < 0 ) minJ = 0;
  				if( maxJ > input.width ) maxJ = input.width;
  
  				int index = 0;
  
  				for( int i = minI; i < maxI; i++ ) {
  					for( int j = minJ; j < maxJ; j++ ) {
  						storage[index++] = input.get(j,i);
  					}
  				}
  				
  				// use quick select to avoid sorting the whole list
  				int median = QuickSelect.select(storage, index / 2, index);
  				output.set(x,y, median );
  			}
  		}
  	}
docs: Performs a median filter.
  
  @param input Raw input image.
  @param output Filtered image.
  @param radius Size of the filter's region.
  @param storage Array used for storage.  If null a new array is declared internally.