How do I find and remove white specks from an image using SciPy/NumPy?

I have a series of images which serve as my raw data which I am trying to prepare for publication. These images have a series of white specks randomly throughout which I would like to replace with the average of some surrounding pixels.

I cannot post images, but the following code should produce a PNG that approximates the issue that I’m trying to correct:

import numpy as np
from scipy.misc import imsave

random_array = np.random.random_sample((512,512))

random_array[random_array < 0.999] *= 0.25

imsave('white_specs.png', random_array)

While this should produce an image with a similar distribution of the specks present in my raw data, my images do not have specks uniform in intensity, and some of the specks are more than a single pixel in size (though none of them are more than 2). Additionally, there are spots on my image that I do not want to alter that were intentionally saturated during data acquisition for the purpose of clarity when presented: these spots are approximately 10 pixels in diameter.

In principle, I could write something to look for pixels whose value exceeds a certain threshold then check them against the average of their nearest neighbors. However, I assume what I’m ultimately trying to achieve is not an uncommon action in image processing, and I very much suspect that there is some SciPy functionality that will do this without having to reinvent the wheel. My issue is that I am not familiar enough with the formal aspects/vocabulary of image processing to really know what I should be looking for. Can someone point me in the right direction?

Best answer

You could simply try a median filter with a small kernel size,

from scipy.ndimage import median_filter

filtered_array = median_filter(random_array, size=3)

which will remove the specks without noticeably changing the original image.

A median filter is well suited for such tasks since it will better preserve features in your original image with high spatial frequency, when compared for instance to a simple moving average filter.

By the way, if your images are experimental (i.e. noisy) applying a non-aggressive median filter (such as the one above) never hurts as it allows to attenuate the noise as well.