# Reducing Pepper Noise from an Image

For an image with pepper noise, presuming it is desirable to reduce the pepper noise, which operations, in which sequence, would you apply? Find an image, add pepper noise, and demonstrate your results.

• Any other homework questions? Low pass filter, the simplest is averaging neighbors - doesn't require any transforms Commented Nov 25, 2015 at 17:27
• it is not a HW question Commented Nov 25, 2015 at 17:53
• I'll create an answer if you try it first Commented Nov 25, 2015 at 18:08

## 2 Answers

Salt and Paper noise are better dealt and reduced using Median Filter.

The properties of the Salt and Pepper noise make it an outlier in almost any patch of the image.
Hence the best way to remove it is using a method robust to outliers.
Linear filters (Low Pass Filters) are basically weighted mean an hence very sensitive to Outliers which makes them less efficient in this case.

The Median is known and simple robust estimator and hence perform very well in this case.

The way to use it is simple, working by patches / windows. Iterate through the pixels of the image, for each pixel open a Window of its neighborhood controlled by the parameter which is the Window Radius.
For each window replace the value of the center pixel by the median of the window.

MATLAB Code:

% Image Salt and Pepper Noise Filtering
% See http://dsp.stackexchange.com/questions/27298

%% General Parameters and Initialization

clear();
close('all');

% set(0, 'DefaultFigureWindowStyle', 'docked');
defaultLooseInset = get(0, 'DefaultAxesLooseInset');
set(0, 'DefaultAxesLooseInset', [0.05, 0.05, 0.05, 0.05]);

titleFontSize   = 14;
axisFotnSize    = 12;
stringFontSize  = 12;

thinLineWidth   = 2;
normalLineWidth = 3;
thickLineWidth  = 4;

smallSizeData   = 36;
mediumSizeData  = 48;
bigSizeData     = 60;

randomNumberStream = RandStream('mlfg6331_64', 'NormalTransform', 'Ziggurat');
subStreamNumber = 57162;
set(randomNumberStream, 'Substream', subStreamNumber);
RandStream.setGlobalStream(randomNumberStream);

%% Constants
UNIT8_MIN_VALUE = 0;
UNIT8_MAX_VALUE = 255;

%% Loading Data

mInputImage = imread('../RawData/Image0001.png');
mInputImage = mInputImage(:, :, 1); %<! Assuring Single Channel Image

numRows = size(mInputImage, 1);
numCols = size(mInputImage, 2);
numPixels = numRows * numCols;

%% Parameters
winRadius           = 1; %<! Loacl Window Radius
noiseProbability    = 0.05; %<! Probability of a Pixel to be affected by noise

%% Generating Noisy Image

numNoisyPixels  = round(noiseProbability * numPixels);

vNoisyPixelsIdx         = randperm(numPixels, numNoisyPixels);
vPepperNoisyPixelsIdx   = vNoisyPixelsIdx(1:floor(numNoisyPixels / 2));
vSaltNoisyPixelsIdx     = vNoisyPixelsIdx((floor(numNoisyPixels / 2) + 1):numNoisyPixels);

mNoisyImage                         = mInputImage;
mNoisyImage(vPepperNoisyPixelsIdx)  = UNIT8_MAX_VALUE;
mNoisyImage(vSaltNoisyPixelsIdx)    = UNIT8_MIN_VALUE;

%% Image Median Filtering

mFilteredImage = mNoisyImage;

for iCol = 1:numCols
for jRow = 1:numRows
winFirstRowIdx  = max(1, (jRow - winRadius));
winLastRowIdx   = min(numRows, (jRow + winRadius));
winFirstColIdx  = max(1, (iCol - winRadius));
winLastColIdx   = min(numCols, (iCol + winRadius));

vRowsIdx = [winFirstRowIdx:winLastRowIdx];
vColsIdx = [winFirstColIdx:winLastColIdx];

mLocalWin = mFilteredImage(vRowsIdx, vColsIdx);

mFilteredImage(jRow, iCol) = median(mLocalWin(:));
end
end

%% Display Results

hFigure = figure('Position', [100, 100, 900, 550], 'Units', 'pixels');
set(hFigure, 'Colormap', gray(256));
hAxes   = axes();
set(hAxes, 'Units', 'pixels')
set(hAxes, 'Position', [50, 50, numCols, numRows]);
hImageObject = image(mInputImage);
set(get(hAxes, 'Title'), 'String', ['Input Image'], ...
'FontSize', titleFontSize);

hFigure = figure('Position', [100, 100, 900, 550], 'Units', 'pixels');
set(hFigure, 'Colormap', gray(256));
hAxes   = axes();
set(hAxes, 'Units', 'pixels')
set(hAxes, 'Position', [50, 50, numCols, numRows]);
hImageObject = image(mNoisyImage);
set(get(hAxes, 'Title'), 'String', ['Noisy Image'], ...
'FontSize', titleFontSize);

hFigure = figure('Position', [100, 100, 900, 550], 'Units', 'pixels');
set(hFigure, 'Colormap', gray(256));
hAxes   = axes();
set(hAxes, 'Units', 'pixels')
set(hAxes, 'Position', [50, 50, numCols, numRows]);
hImageObject = image(mFilteredImage);
set(get(hAxes, 'Title'), 'String', ['Filtered Image'], ...
'FontSize', titleFontSize);

%% Restore Defaults
set(0, 'DefaultFigureWindowStyle', 'normal');
set(0, 'DefaultAxesLooseInset', defaultLooseInset);


The full MATLAB code which implements the solution is at my Signal Processing StackExchange Q27298 - GitHub Repository (Look at the SignalProcessing\Q27298 folder).

Enjoy...

• Median-type filters for salt and pepper work great as long as the noise concentration is not too high. Otherwise, the noise tends to win Commented Nov 25, 2015 at 19:21
• @LaurentDuval, Well, all restoration methods will fail at certain point of low SNR. I'm not sure Median will fail before Wiener Filter for example.
– Royi
Commented Nov 25, 2015 at 20:00
• For sure. Just mentioned that more involved morphological filters, or involved median-type ones could be worth investigating, e.g. Denoising of salt-and-pepper noise corrupted image using modified directional-weighted-median filter, 2012 Commented Nov 25, 2015 at 20:09
• Well, I assumed those are the first stages in the area, hence this is basic point to start. Of course there might be better places to end :-).
– Royi
Commented Nov 25, 2015 at 21:07
• @Drazick , this is a very short answer, can you explain it in at least a paragraph please? or give me a good reference so I can look it up. Commented Nov 26, 2015 at 18:21

If the noise is really pepper (blacker dots), and not salt and pepper noise (whiter and blacker dots), a rank filter with low rank, could be a solution. Assume you have a $3\times 3$ window, with $9$ pixel values $p_{k \in [1,\ldots,9]}$. It is likely that if a black pixel falls into the window, it will have the smallest value. So if you sort the pixel values, you get a new set of indexed pixels $p_{\sigma(k) \in [1,\ldots,9]}$, with $p_{\sigma(1)}$ the lowest, and $p_{\sigma(9)}$ the highest. Then you can replace the central pixel of the window by the second, third or fourth lowest value $p_{\sigma(2)}$, $p_{\sigma(3)}$, or $p_{\sigma(4)}$ for instance. Would you choose the fifth lowest, you would get the median filter suggested by @Drazick, which is a special case of rank filters.

With pure pepper noise, rank filters with appropriate size and rank are likely to overestimate the image background a little less, depending on the level of pepper noise.

• can you answer my other question as well please? Commented Nov 27, 2015 at 16:50
• I did it a while ago Commented Nov 30, 2015 at 19:43
• can you answer this question for me please? dsp.stackexchange.com/questions/27510/compression-algorithm Commented Dec 5, 2015 at 14:08