In this tutorial, we’ll walk through the process of building a MATLAB application to apply MMSE and Adaptive Median Filter for noise reduction in grayscale images. We’ll also include a user-friendly GUI (Graphical User Interface) to control these operations.
Step 1: Creating the Main Application Framework
To begin, we create a main function named implementation
and set up the framework for the application. This includes creating two figures:
- A control figure where users can interact with buttons and inputs.
- A display figure to showcase images before and after processing.
Hereβs the initial code:
function implementation()
% Create the control figure
controlFig = figure('Name', 'MMSE Filter Controls', 'NumberTitle', 'off', ...
'Position', [100, 100, 400, 250], 'Resize', 'off', ...
'Color', [1, 1, 1]); % White background
% Create the display figure
displayFig = figure('Name', 'MMSE Filter Output', 'NumberTitle', 'off', ...
'Position', [550, 100, 800, 600], 'Resize', 'off', ...
'Color', [1, 1, 1]); % White background
% Axes for displaying images
ax1 = axes('Parent', displayFig, 'Position', [0.05, 0.55, 0.4, 0.4]);
title(ax1, 'Original Image');
ax2 = axes('Parent', displayFig, 'Position', [0.55, 0.55, 0.4, 0.4]);
title(ax2, 'Grayscale Image');
ax3 = axes('Parent', displayFig, 'Position', [0.05, 0.05, 0.4, 0.4]);
title(ax3, 'Noisy Image');
ax4 = axes('Parent', displayFig, 'Position', [0.55, 0.05, 0.4, 0.4]);
title(ax4, 'Filtered Image');
end
This creates a clean slate for the GUI with placeholders for the images.
Step 2: Adding User Controls
Next, we add interactive elements like buttons and input fields to the control figure. These elements allow users to load an image, select noise type, apply noise, and perform filtering operations.
Add the following code after the controlFig
definition:
% UI elements for user inputs
uicontrol('Style', 'pushbutton', 'String', 'Load Image', ...
'Position', [50, 200, 100, 30], ...
'Callback', @loadImage);
uicontrol('Style', 'text', 'String', 'Noise Type:', ...
'HorizontalAlignment', 'left', 'BackgroundColor', [1, 1, 1], ...
'Position', [50, 160, 70, 20]);
noiseTypePopup = uicontrol('Style', 'popupmenu', ...
'String', {'Gaussian', 'Salt & Pepper'}, ...
'Position', [130, 160, 100, 30]);
uicontrol('Style', 'text', 'String', 'Noise Variance:', ...
'HorizontalAlignment', 'left', 'BackgroundColor', [1, 1, 1], ...
'Position', [50, 120, 100, 20]);
noiseVarianceEdit = uicontrol('Style', 'edit', 'String', '0.01', ...
'Position', [160, 120, 70, 30]);
% Buttons for processing
uicontrol('Style', 'pushbutton', 'String', 'Apply Noise', ...
'Position', [50, 80, 200, 30], ...
'Callback', @applyNoise);
uicontrol('Style', 'pushbutton', 'String', 'Apply MMSE Filter', ...
'Position', [50, 40, 200, 30], ...
'Callback', @applyMMSEFilter);
uicontrol('Style', 'pushbutton', 'String', 'Apply Adaptive Median Filter', ...
'Position', [50, 10, 200, 30], ...
'Callback', @applyAdaptiveMedianFilter);
Step 3: Writing the Image Processing Functions
Letβs create the callbacks for the buttons. Start with the Load Image button:
function loadImage(~, ~)
[file, path] = uigetfile({'*.jpg;*.png;*.bmp', 'Image Files'});
if isequal(file, 0)
return;
end
originalImage = imread(fullfile(path, file));
% Display original and grayscale images
imshow(originalImage, 'Parent', ax1);
title(ax1, 'Original Image');
% Convert to grayscale
if size(originalImage, 3) == 3
grayscaleImage = rgb2gray(originalImage);
else
grayscaleImage = originalImage;
end
imshow(grayscaleImage, 'Parent', ax2);
title(ax2, 'Grayscale Image');
end
Step 4: Adding Noise to the Image
We now create the Apply Noise function:
function applyNoise(~, ~)
if isempty(grayscaleImage)
errordlg('Please load an image first!', 'Error');
return;
end
% Get user inputs for noise
noiseType = noiseTypePopup.Value;
noiseVariance = str2double(noiseVarianceEdit.String); % Convert to numeric
if isnan(noiseVariance) || noiseVariance < 0
errordlg('Please enter a valid noise variance!', 'Error');
return;
end
% Add noise
switch noiseType
case 1 % Gaussian noise
noisyImage = imnoise(grayscaleImage, 'gaussian', 0, noiseVariance);
case 2 % Salt & Pepper noise
noisyImage = imnoise(grayscaleImage, 'salt & pepper', noiseVariance);
end
imshow(noisyImage, 'Parent', ax3);
title(ax3, 'Noisy Image');
end
Step 5: Implementing the MMSE Filter
The MMSE Filter logic is applied as follows:
function applyMMSEFilter(~, ~)
if isempty(noisyImage)
errordlg('Please apply noise first!', 'Error');
return;
end
noiseVariance = str2double(noiseVarianceEdit.String); % Convert to numeric
if isnan(noiseVariance) || noiseVariance < 0
errordlg('Please enter a valid noise variance!', 'Error');
return;
end
% Apply MMSE
filteredImage = applyMMSE(noisyImage, noiseVariance);
imshow(filteredImage, 'Parent', ax4);
title(ax4, 'Filtered Image');
end
(This is just the function the implementation of both can be found in the full code attached below)
Step 6: Adaptive Median Filter
Finally, we implement the Adaptive Median Filter:
function applyAdaptiveMedianFilter(~, ~)
if isempty(noisyImage)
errordlg('Please apply noise first!', 'Error');
return;
end
filteredImage = adaptiveMedianFilter(noisyImage);
imshow(filteredImage, 'Parent', ax4);
title(ax4, 'Filtered Image (Adaptive Median)');
end
So now everything is setup, we have successfully built the GUI for the implementation of MMSE and Adaptive Median Filter to any image and also defined the functions in which image will be passed for processing, the logic of the MMSE and Adaptive Median Filter can be found below in the Complete Code.
Below is the full code of the Implementation.
Full Code
function implementation()
% Create the control figure
controlFig = figure('Name', 'MMSE Filter Controls', 'NumberTitle', 'off', ...
'Position', [100, 100, 400, 250], 'Resize', 'off', ...
'Color', [1, 1, 1]); % White background
% UI elements for user inputs
uicontrol('Style', 'pushbutton', 'String', 'Load Image', ...
'Position', [50, 200, 100, 30], ...
'Callback', @loadImage);
uicontrol('Style', 'text', 'String', 'Noise Type:', ...
'HorizontalAlignment', 'left', 'BackgroundColor', [1, 1, 1], ...
'Position', [50, 160, 70, 20]);
noiseTypePopup = uicontrol('Style', 'popupmenu', ...
'String', {'Gaussian', 'Salt & Pepper'}, ...
'Position', [130, 160, 100, 30]);
uicontrol('Style', 'text', 'String', 'Noise Variance:', ...
'HorizontalAlignment', 'left', 'BackgroundColor', [1, 1, 1], ...
'Position', [50, 120, 100, 20]);
noiseVarianceEdit = uicontrol('Style', 'edit', 'String', '0.01', ...
'Position', [160, 120, 70, 30]);
% Button to apply noise
uicontrol('Style', 'pushbutton', 'String', 'Apply Noise', ...
'Position', [50, 80, 200, 30], ...
'Callback', @applyNoise);
% Button to apply MMSE filter
uicontrol('Style', 'pushbutton', 'String', 'Apply MMSE Filter', ...
'Position', [50, 40, 200, 30], ...
'Callback', @applyMMSEFilter);
% Button to apply Adaptive Median Filter
uicontrol('Style', 'pushbutton', 'String', 'Apply Adaptive Median Filter', ...
'Position', [50, 10, 200, 30], ...
'Callback', @applyAdaptiveMedianFilter);
% Create the display figure
displayFig = figure('Name', 'MMSE Filter Output', 'NumberTitle', 'off', ...
'Position', [550, 100, 800, 600], 'Resize', 'off', ...
'Color', [1, 1, 1]); % White background
% Axes for displaying images
ax1 = axes('Parent', displayFig, 'Position', [0.05, 0.55, 0.4, 0.4]);
title(ax1, 'Original Image');
ax2 = axes('Parent', displayFig, 'Position', [0.55, 0.55, 0.4, 0.4]);
title(ax2, 'Grayscale Image');
ax3 = axes('Parent', displayFig, 'Position', [0.05, 0.05, 0.4, 0.4]);
title(ax3, 'Noisy Image');
ax4 = axes('Parent', displayFig, 'Position', [0.55, 0.05, 0.4, 0.4]);
title(ax4, 'Filtered Image');
% Variables to store image data
originalImage = [];
grayscaleImage = [];
noisyImage = [];
filteredImage = [];
% Function to load the image
function loadImage(~, ~)
[file, path] = uigetfile({'*.jpg;*.png;*.bmp', 'Image Files'});
if isequal(file, 0)
return;
end
originalImage = imread(fullfile(path, file));
% Display original and grayscale images
imshow(originalImage, 'Parent', ax1);
title(ax1, 'Original Image');
% Convert to grayscale
if size(originalImage, 3) == 3
grayscaleImage = rgb2gray(originalImage);
else
grayscaleImage = originalImage;
end
imshow(grayscaleImage, 'Parent', ax2);
title(ax2, 'Grayscale Image');
end
% Function to apply noise to the image
function applyNoise(~, ~)
if isempty(grayscaleImage)
errordlg('Please load an image first!', 'Error');
return;
end
% Get user inputs for noise
noiseType = noiseTypePopup.Value;
noiseVariance = str2double(noiseVarianceEdit.String); % Convert to numeric
% Check if the noise variance is valid
if isnan(noiseVariance) || noiseVariance < 0
errordlg('Please enter a valid noise variance!', 'Error');
return;
end
% Add noise to the image
switch noiseType
case 1 % Gaussian noise
noisyImage = imnoise(grayscaleImage, 'gaussian', 0, noiseVariance);
case 2 % Salt & Pepper noise
noisyImage = imnoise(grayscaleImage, 'salt & pepper', noiseVariance);
end
imshow(noisyImage, 'Parent', ax3);
title(ax3, 'Noisy Image');
disp('Noise applied successfully');
end
% Function to apply MMSE filter
function applyMMSEFilter(~, ~)
if isempty(noisyImage)
errordlg('Please apply noise first!', 'Error');
return;
end
% Get user inputs for noise variance
noiseVariance = str2double(noiseVarianceEdit.String); % Convert to numeric
% Check if the noise variance is valid
if isnan(noiseVariance) || noiseVariance < 0
errordlg('Please enter a valid noise variance!', 'Error');
return;
end
% Apply MMSE filter
filteredImage = applyMMSE(noisyImage, noiseVariance); % Pass numeric value
imshow(filteredImage, 'Parent', ax4);
title(ax4, 'Filtered Image');
% Show difference image in a new figure
diffImage = double(noisyImage) - double(filteredImage);
differenceFig = figure('Name', 'Difference Image', 'NumberTitle', 'off', ...
'Color', [1, 1, 1]); % White background
imshow(abs(diffImage), []); % Show absolute difference
title('Difference Image');
% Debugging outputs
disp('MMSE filter applied successfully');
disp(['Noise Variance: ', num2str(noiseVariance)]);
end
% Function to apply Adaptive Median Filter
function applyAdaptiveMedianFilter(~, ~)
if isempty(noisyImage)
errordlg('Please apply noise first!', 'Error');
return;
end
% Apply Adaptive Median Filter
filteredImage = adaptiveMedianFilter(noisyImage);
imshow(filteredImage, 'Parent', ax4);
title(ax4, 'Filtered Image (Adaptive Median)');
% Show difference image in a new figure
diffImage = double(noisyImage) - double(filteredImage);
differenceFig = figure('Name', 'Difference Image (Adaptive Median)', 'NumberTitle', 'off', ...
'Color', [1, 1, 1]); % White background
imshow(abs(diffImage), []); % Show absolute difference
title('Difference Image');
% Debugging outputs
disp('Adaptive Median Filter applied successfully');
end
% Function to apply MMSE filter
function outputImage = applyMMSE(noisyImg, noiseVariance)
[rows, cols] = size(noisyImg);
windowSize = 3; % Define the size of the local window
halfWindow = floor(windowSize / 2);
paddedImg = padarray(double(noisyImg), [halfWindow, halfWindow], 'symmetric');
outputImage = zeros(size(noisyImg));
% Process each pixel
for i = 1:rows
for j = 1:cols
% Extract local window
localWindow = paddedImg(i:i+2*halfWindow, j:j+2*halfWindow);
% Calculate local mean and variance
localMean = mean(localWindow(:));
localVariance = var(localWindow(:));
% Apply MMSE formula
if localVariance > 0
% Calculate the MMSE estimate
outputImage(i, j) = localMean + (noiseVariance / localVariance) * (noisyImg(i, j) - localMean);
else
outputImage(i, j) = localMean; % Avoid division by zero
end
end
end
% Ensure outputImage is within valid range [0, 255]
outputImage = min(max(outputImage, 0), 255);
outputImage = uint8(outputImage); % Convert to uint8
end
% Function to apply Adaptive Median Filter
function outputImage = adaptiveMedianFilter(noisyImg)
[rows, cols] = size(noisyImg);
windowSize = 3; % Define the size of the local window
halfWindow = floor(windowSize / 2);
paddedImg = padarray(double(noisyImg), [halfWindow, halfWindow], 'symmetric');
outputImage = zeros(size(noisyImg));
% Process each pixel
for i = 1:rows
for j = 1:cols
% Extract local window
localWindow = paddedImg(i:i+2*halfWindow, j:j+2*halfWindow);
% Calculate median and min/max
zMin = min(localWindow(:));
zMax = max(localWindow(:));
zMed = median(localWindow(:));
zxy = noisyImg(i, j);
% Apply Adaptive Median Filter logic
if zMin < zMed && zMed < zMax
if zMin < zxy && zxy < zMax
outputImage(i, j) = zxy; % Preserve the original value
else
outputImage(i, j) = zMed; % Replace with median
end
else
outputImage(i, j) = zMed; % Replace with median
end
end
end
% Ensure outputImage is within valid range [0, 255]
outputImage = min(max(outputImage, 0), 255);
outputImage = uint8(outputImage); % Convert to uint8
end
end
Here is another example of an Image where Adaptive Median Filtered worked better in comparison to MMSE filter
Learn More About Addition of Noise Add Noise to Image in MATLAB: A Comprehensive Guide π and about Gaussian Filter Apply Gaussian Filter in MATLAB: The Ultimate Guide ππ
Oh, and here are their respective difference images as well (Difference between Noisy and Filtered Image)
And with that you have successfully applied MMSE and Adaptive Median Filter to the image. If you have any comments or questions kindly leave them below.
Thus, that’s it now you have learned the working and application of MMSE and Adaptive Median Filter.