# 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 – johnnymopo Nov 25 '15 at 17:27
• it is not a HW question – user65652 Nov 25 '15 at 17:53
• I'll create an answer if you try it first – johnnymopo Nov 25 '15 at 18:08

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 (From StackExchange GitHub):

% 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;

mInputImage = mInputImage(:, :, 1); %<! Assuring Single Channel Image

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

%% Parameters
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);


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 – Laurent Duval Nov 25 '15 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 Nov 25 '15 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 – Laurent Duval Nov 25 '15 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 Nov 25 '15 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. – user65652 Nov 26 '15 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.