imager is an R package for image processing that’s fairly fast and now quite powerful (if I may say so myself). It wraps a neat C++ library called CImg, by David Tschumperlé (CNRS). It took quite a bit of work, but imager is now on CRAN, so that installing it is as easy as:

install.packages("imager")

Here’s an example of using imager for max-filtering. A max-filter replaces each pixel value with the maximum value of its neighbours. Usually you’d write a loop, but we want to do things the R way (warning: this only works for small neighbourhoods, for reasons that will become obvious).

library(imager)
im <- load.image(system.file('extdata/parrots.png',package='imager'))
nhood <- expand.grid(dx=-2:2,dy=-2:2) #We want to include all pixels in a square 5x5 neighbourhood
im.s <- alply(nhood,1,function(d) imshift(im,d$dx,d$dy))

The result is a list of shifted versions of the image im (there are 5×5 = 25 different shifts, so you can imagine that you wouldn’t want to do this with a 20×20 neighbourhood and a large image!)
Now running a max (or min) filter is just a matter of calling pmax (or pmin):

max.filt <- do.call(pmax,im.s)
min.filt <- do.call(pmin,im.s)

Here’s our max-filtered image:

maxfilt

and here’s the min-filtered one:

minfilt