In this application, different image quality measures are calculated for a distorted image with reference to an original image. To test the application, a set of 20 distorted images is included in this package. The list of Image Quality measures implemented in this package include,
1. Structural Content (SC)
2. Mean Square Error (MSE)
3. Peak Signal to Noise Ratio (PSNR in dB)
4. Normalized Cross-Correlation (NCC)
5. Average Difference (AD)
6. Maximum Difference (MD)
7. Normalized Absolute Error (NAE)
Refer "Reference.png" for the mathematical expressions implemented in this package.
Original images are kept in the folder "OriginalImages".
Distorted images are kept in the folder "DistortedImages".
Athi (2020). Image Quality Measures (https://www.mathworks.com/matlabcentral/fileexchange/25005-image-quality-measures), MATLAB Central File Exchange. Retrieved July 19, 2020.
function SC = StructuralContent(origImg, distImg)
origImg = double(origImg);
distImg = double(distImg);
SC = sum(sum(origImg .* origImg)) / sum(sum(distImg .* distImg));
function PSNR = PeakSignaltoNoiseRatio(origImg, distImg)
origImg = double(origImg);
distImg = double(distImg);
[M N] = size(origImg);
error = origImg - distImg;
MSE = sum(sum(error .* error)) / (M * N);
if(MSE > 0)
PSNR = 10*log(255*255/MSE) / log(10);
else
PSNR = 99;
end
Normalized Cross-Correlation (NCC)
function NK = NormalizedCrossCorrelation(origImg, distImg)
origImg = double(origImg);
distImg = double(distImg);
NK = sum(sum(origImg .* distImg)) / sum(sum(origImg .* origImg));
Normalized Absolute Error (NAE)
function NAE = NormalizedAbsoluteError(origImg, distImg)
origImg = double(origImg);
distImg = double(distImg);
error = origImg - distImg;
NAE = sum(sum(abs(error))) / sum(sum(origImg));
Average Difference (AD)
function AD = AverageDifference(origImg, distImg)
origImg = double(origImg);
distImg = double(distImg);
[M N] = size(origImg);
error = origImg - distImg;
AD = sum(sum(error)) / (M * N);
Maximum Difference (MD)
function MD = MaximumDifference(origImg, distImg)
origImg = double(origImg);
distImg = double(distImg);
error = origImg - distImg;
MD = max(max(error));
Mean Square Error (MSE)
function MSE = MeanSquareError(origImg, distImg)
origImg = double(origImg);
distImg = double(distImg);
[M N] = size(origImg);
error = origImg - distImg;
MSE = sum(sum(error .* error)) / (M * N);
Main__test case
clc;
clear all;
close all;
%Read Original & Distorted Images
origImg = imread('.\OriginalImages\Lena.bmp'); %读入图像
distImg = imread('.\DistortedImages\gaussian_noise_20.bmp');
%If the input image is rgb, convert it to gray image%转入灰度空间
noOfDim = ndims(origImg);
if(noOfDim == 3)
origImg = rgb2gray(origImg);
end
noOfDim = ndims(distImg);
if(noOfDim == 3)
distImg = rgb2gray(distImg);
end
%Size Validation 图像大小是否相同
origSiz = size(origImg);
distSiz = size(distImg);
sizErr = isequal(origSiz, distSiz);
if(sizErr == 0)
disp('Error: Original Image & Distorted Image should be of same dimensions');
return;
end
%Mean Square Error 计算均值平方误差
MSE = MeanSquareError(origImg, distImg);
disp('Mean Square Error = ');
disp(MSE);
%Peak Signal to Noise Ratio 计算图像峰值信噪比
PSNR = PeakSignaltoNoiseRatio(origImg, distImg);
disp('Peak Signal to Noise Ratio = ');
disp(PSNR);
%Normalized Cross-Correlation计算归一化互相关误差
NK = NormalizedCrossCorrelation(origImg, distImg);
disp('MNormalized Cross-Correlation = ');
disp(NK);
%Average Difference计算像素误差平均值
AD = AverageDifference(origImg, distImg);
disp('Average Difference = ');
disp(AD);
%Structural Content 计算结构内容
SC = StructuralContent(origImg, distImg);
disp('Structural Content = ');
disp(SC);
%Maximum Difference计算像素误差最大值
MD = MaximumDifference(origImg, distImg);
disp('Maximum Difference = ');
disp(MD);
%Normalized Absolute Error 归一化误差绝对值和
NAE = NormalizedAbsoluteError(origImg, distImg);
disp('Normalized Absolute Error = ');
disp(NAE);
测量两幅图像之间的差异
1. Mean squared error, MSE( above)均方误差
2. Root Mean squared error, RMSE(above)均方根误差
3. Peak signal to signal noise ratio, PSNR( above)
4. Mean absolute error, MAE
5. Signal to signal noise ratio, SNR
6. Universal Image Quality Index
7. Enhancement Measurement Error, EME
8. Pearson Correlation Coefficient
Cited as:https://uk.mathworks.com/matlabcentral/fileexchange/29500-image-error-measurements
2. Root Mean squared error, RMSE(above)均方根误差
function err = RMSE(signal1, signal2)
%RMSE Root Mean Squared Error
err = sum((signal1 - signal2).^2)/length(signal1); % MSE
err = sqrt(err); % RMSE
en
function [mse, rmse] = RMSE2(signal1, signal2)
originalRowSize = size(signal1,1);
originalColSize = size(signal1,2);
signal1 = signal1(:);
signal2 = signal2(:);
mse = sum((signal1 - signal2).^2)./(originalRowSize*originalColSize);
rmse = sqrt(mse);
end
3. Peak signal to signal noise ratio, PSNR( above)
function psnr_Value = PSNR(A,B)
% PSNR (Peak Signal to noise ratio)
if (size(A) ~= size(B))
error('The size of the 2 matrix are unequal')
psnr_Value = NaN;
return;
elseif (A == B)
disp('Images are identical: PSNR has infinite value')
psnr_Value = Inf;
return;
else
maxValue = double(max(A(:)));
% Calculate MSE, mean square error.
mseImage = (double(A) - double(B)) .^ 2;
[rows columns] = size(A);
mse = sum(mseImage(:)) / (rows * columns);
% Calculate PSNR (Peak Signal to noise ratio)
psnr_Value = 10 * log10( 256^2 / mse);
end
%4. Mean absolute error, MAE
function [mae] = meanAbsoluteError(signal1, signal2) 平均绝对误差
originalRowSize = size(signal1,1);
originalColSize = size(signal1,2);
signal1 = signal1(:);
signal2 = signal2(:);
mae = sum(abs(signal1 - signal2))/(originalRowSize*originalColSize);
end
%5. Signal to signal noise ratio, SNR
function snr_power = SNR(signal, noise)
% SNR (Signal to noise ratio)
[signalRowSize signalColSize] = size(signal);
[noiseRowSize noiseColSize] = size(noise);
signalAmp = signal(:);
noiseAmp = noise(:);
signalPower = sum(signalAmp.^2)/(signalRowSize*signalColSize); %信号
noisePower = sum(noiseAmp.^2)/(noiseRowSize*noiseColSize); %噪声
snr_power = 10*log10(signalPower/noisePower); %信号噪声比
end
%6-. Universal Image Quality Index
function [quality, quality_map] = imageQualityIndex (img1, img2, block_size)
% * Note: img_qi is renamed as imageQualityIndex
%
%Copyright (c) 2001 The University of Texas at Austin
%All Rights Reserved.
%
%Author : Zhou Wang
%Version : 1.0
%
%========================================================================
%This is an efficient implementation of the algorithm for calculating
%the universal image quality index proposed by Zhou Wang and Alan C.
%Bovik. Please refer to the paper "A Universal Image Quality Index"
%by Zhou Wang and Alan C. Bovik, published in IEEE Signal Processing
%Letters, 2001. In order to run this function, you must have Matlab's
%Image Processing Toobox.
%
%Input : an original image and a test image of the same size
%Output: (1) an overall quality index of the test image, with a value range of [-1, 1].
% (2) a quality map of the test image. The map has a smaller size than the input images. The actual size is img_size - BLOCK_SIZE + 1.
%Usage:
%
%1. Load the original and the test images into two matrices
% (say img1 and img2)
%
%2. Run this function in one of the two ways:
%
% % Choice 1 (suggested):
% [qi qi_map] = img_qi(img1, img2);
%
% % Choice 2:
% [qi qi_map] = img_qi(img1, img2, BLOCK_SIZE);
%
% The default BLOCK_SIZE is 8 (Choice 1). Otherwise, you can specify
% it by yourself (Choice 2).
%
%3. See the results:
%
% qi %Gives the over quality index.
% imshow((qi_map+1)/2) %Shows the quality map as an image.
%
%========================================================================
%未验证
if (nargin == 1 | nargin > 3)
quality = -Inf;
quality_map = -1*ones(size(img1));
return;
end
if (size(img1) ~= size(img2))
quality = -Inf;
quality_map = -1*ones(size(img1));
return;
end
if (nargin == 2) % sliding window, B by B
block_size = 8;
end
N = block_size.^2;
sum2_filter = ones(block_size);
img1_sq = img1.*img1;
img2_sq = img2.*img2;
img12 = img1.*img2;
img1_sum = filter2(sum2_filter, img1, 'valid');
img2_sum = filter2(sum2_filter, img2, 'valid');
img1_sq_sum = filter2(sum2_filter, img1_sq, 'valid');
img2_sq_sum = filter2(sum2_filter, img2_sq, 'valid');
img12_sum = filter2(sum2_filter, img12, 'valid');
img12_sum_mul = img1_sum.*img2_sum;
img12_sq_sum_mul = img1_sum.*img1_sum + img2_sum.*img2_sum;
numerator = 4*(N*img12_sum - img12_sum_mul).*img12_sum_mul;
denominator1 = N*(img1_sq_sum + img2_sq_sum) - img12_sq_sum_mul;
denominator = denominator1.*img12_sq_sum_mul;
quality_map = ones(size(denominator));
index = (denominator1 == 0) & (img12_sq_sum_mul ~= 0);
quality_map(index) = 2*img12_sum_mul(index)./img12_sq_sum_mul(index);
index = (denominator ~= 0);
quality_map(index) = numerator(index)./denominator(index);
quality = mean2(quality_map);
%7 -Enhancement Measurement Error, EME增强评价误差
% Call: eme(A,M,L)
% The 1st measure, EME, of enhancement calculation
% of the image X of size MxM by using blocks of size LxL用L*L的图块计算
%
function E=eme(X,M,L);
% L=5;
how_many=floor(M/L); %图像分多少块
E=0.;
B1=zeros(L);
m1=1;
for m=1:how_many %
n1=1;
for n=1:how_many
B1=X(m1:m1+L-1,n1:n1+L-1); %取图块
b_min=min(min(B1)); %当前图块的最小值
b_max=max(max(B1));%当前图块的最大值
if b_min>0
b_ratio=b_max/b_min;
E=E+20.*log(b_ratio); %累加结果
end;
n1=n1+L;
end;
m1=m1+L;
end;
E=(E/how_many)/how_many;
%8-Persons相关系数
function pcc = compute_PearsonCorrelationCoefficient (signal1, signal2)
originalRowSize = size(signal1,1);
originalColSize = size(signal1,2);
signal1 = signal1(:);
signal2 = signal2(:);
mean_signal1 = sum(signal1)/numel(signal1);
signal1 = signal1 - mean_signal1;
mean_signal2 = sum(signal2)/numel(signal2); %均值
signal2 = signal2 - mean_signal2; %偏差
pcc = sum(signal1.*signal2)/ (std(signal1)*std(signal2));
end
%8-其他相关系数
function imagePlot( imageData, plotRowSize, plotColSize,plotIndex, titleStr )
%IMAGEPLOT
subplot(plotRowSize, plotColSize, plotIndex);
imshow(imageData, []); title(titleStr);
end
usage_errorMeasurementsOfImages.m %主程序
%%
clear all; clc;
%% report format characters
newlineInAscii1 = [13 10];
spaceInInAscii = 32;
% for printing, newline causes much confusion in matlab and is provided here as an alternative
newline = char(newlineInAscii1);
spaceChar = char(spaceInInAscii);
%% plot parameters
plotIndex = 1;
plotRowSize = 1;
plotColSize = 2;
%% read the image
targetFolder = 'images';
IMG = 'lena.jpg'; % IMG : originalImage
IMG = strcat(targetFolder, '\', IMG);
IMG = imread(IMG);
IMG = rgb2gray(IMG);
IMG = double(IMG);
%% noise parameters
sigma = 0.05;
offset = 0.01;
erosionFilterSize = 2;
dilationFilterSize = 2;
mean = 0;
noiseTypeModes = {
'gaussian', % [1]
'salt & pepper', % [2]
'localvar', % [3]
'speckle', % [4] (multiplicative noise)
'poisson', % [5]
'motion blur', % [6]
'erosion', % [7]
'dilation', % [8]
% 'jpg compression blocking effect' % [9]
% [10] Interpolation/ resizing noise
};
noiseChosen = 2;
noiseTypeChosen = char(noiseTypeModes(noiseChosen));
originalImage = uint8(IMG);
%% plot original
titleStr = 'Original';
imagePlot( originalImage, plotRowSize, plotColSize, ...
plotIndex, titleStr );
plotIndex = plotIndex + 1;
%%
for i = 1:(plotRowSize*plotColSize)-1
IMG_aforeUpdated = double(IMG); % backup the previous state just in case it gets updated.
% returns the noise param updates for further corruption
% IMG may be updated as the noisy image for the next round
[IMG, noisyImage, titleStr, sigma, dilationFilterSize, erosionFilterSize] = ...
noisyImageGeneration(IMG, mean, sigma, offset, dilationFilterSize, erosionFilterSize, noiseTypeChosen);
imageQualityIndex_Value = imageQualityIndex(double(originalImage), double(noisyImage));
titleStr = [titleStr ',' newline 'IQI: ' num2str(imageQualityIndex_Value)];
imagePlot( noisyImage, plotRowSize, plotColSize, ...
plotIndex, titleStr );
plotIndex = plotIndex + 1;
end
if (~strcmp(char(class(noisyImage)), 'uint8'))
disp('noisyImage is NOT type: uint8');
end
%% PSNR
psnr_Value = PSNR(originalImage, noisyImage);
fprintf('PSNR = +%5.5f dB \n', psnr_Value);
%% RMSE
[mse, rmse] = RMSE2(double(originalImage), double(noisyImage));
fprintf('MSE = %5.5f \n', mse);
fprintf('RMSE = %5.5f \n', rmse);
%% Universal Quality Index
imageQualityIndex_Value = imageQualityIndex(double(originalImage), double(noisyImage));
fprintf('Universal Image Quality Index = %5.5f \n', imageQualityIndex_Value);
%% Enhancement : measure of enhance- ment, or measure of improvement
[M M] = size(originalImage);
L = 8;
EME_original = eme(double(originalImage),M,L);
EME_noisyImage = eme(double(noisyImage),M,L);
fprintf('EME (original image) = %5.5f \n', EME_original);
fprintf('EME (noisy image) = %5.5f \n', EME_noisyImage);
%% PearsonCorrelationCoefficient
pcc = compute_PearsonCorrelationCoefficient (double(originalImage), double(noisyImage));
fprintf('PearsonCorrelationCoefficient (originalImage vs noisyImage) = %5.5f \n', pcc);
pcc = compute_PearsonCorrelationCoefficient (double(originalImage), double(originalImage));
fprintf('PearsonCorrelationCoefficient (originalImage vs originalImage) = %5.5f \n', pcc);
%% Signal to signal noise ratio, SNR
noise = double(noisyImage) - double(originalImage); % assume additive noise
% check noise
noisyImageReconstructed = double(originalImage) + noise;
residue = noisyImageReconstructed - double(noisyImage);
if (sum(residue(:) ~= 0))
disp('The noise is NOT relevant.');
end
snr_power = SNR(originalImage, noise);
fprintf('SNR = %5.5f dB \n', snr_power);
%% Mean absolute error, MAE
mae = meanAbsoluteError(double(originalImage), double(noisyImage));
fprintf('MAE = %5.5f \n', mae);
%产生噪声函数
function [IMG, noisyImage, titleStr, sigmaUpdated, dilationFilterSizeUpdated, erosionFilterSizeUpdated] = ...
noisyImageGeneration(IMG, mean, sigma, offset, dilationFilterSize, erosionFilterSize, noiseType)
%NOISYIMAGEGENERATION
newlineInAscii1 = [13 10];
spaceInInAscii = 32;
% for printing, newline causes much confusion in matlab and is provided here as an alternative
newline = char(newlineInAscii1);
spaceChar = char(spaceInInAscii);
noiseTypeModes = {
'gaussian',
'salt & pepper',
'localvar',
'speckle',
'poisson',
'motion blur',
'erosion',
'dilation',
'jpg compression blocking effect'
};
switch (lower(noiseType))
case char(noiseTypeModes(1))
noisyImage = imnoise(uint8(IMG),'gaussian', mean, sigma);
%adds Gaussian white noise of mean M and variance V to image I. When unspecified, M and V default to 0 and
%0.01 respectively.
titleStr = ['Noisy image using Gaussian white noise', newline, 'with sigma =',num2str(sigma)];
sigma = sigma + offset;
case char(noiseTypeModes(2))
noisyImage = imnoise(uint8(IMG), 'salt & pepper', sigma);
%adds "salt and pepper" noise to the image I, where sigma is the noise density. This affects approximately
%sigma*numel(I) pixels. Default sigma = 0.05.
titleStr = ['Noisy image using Salt & Pepper noise', newline, 'with sigma =',num2str(sigma)];
sigma = sigma + offset;
case char(noiseTypeModes(3))
imageMask = abs(sigma*randn(size(IMG))); % non-negative
titleStr = ['Noisy image using Gaussian white noise ', newline, '(with noise mask) sigma =',num2str(sigma)];
% J = imnoise(I,'localvar', V) adds zero-mean, Gaussian white noise of local variance, V, to the image I.
% V is an array of the same size as I.
noisyImage = imnoise(uint8(IMG), 'localvar', imageMask);
sigma = sigma + offset;
case char(noiseTypeModes(4))
noisyImage = imnoise(uint8(IMG), 'speckle', sigma);
%adds multiplicative noise to the image I, using the equation J = I + n*I, where n is uniformly distributed random
%noise with mean 0 and variance V. The default for V is 0.04.
titleStr = ['Noisy Image using multiplicative noise', newline, 'with sigma = ', num2str(sigma)];
sigma = sigma + offset;
case char(noiseTypeModes(5))
noisyImage = imnoise(uint8(IMG), 'poisson');
titleStr = ['Noisy Image using poisson'];
IMG = noisyImage;
case char(noiseTypeModes(6))
PSF = fspecial('motion', 500*sigma, (500*sigma)-5);
noisyImage = imfilter(IMG, PSF, 'symmetric','conv'); % 'conv', 'circular');
titleStr = ['Noisy Image using motion noise', newline, 'with sigma = ', num2str(sigma)];
sigma = sigma + offset;
case char(noiseTypeModes(7))
erosionFilter = ones(erosionFilterSize, erosionFilterSize);
noisyImage = imerode(IMG, erosionFilter);
titleStr = ['Noisy image using Erosion with filter', newline, 'size =',num2str(erosionFilterSize)];
erosionFilterSize = erosionFilterSize + 1;
case char(noiseTypeModes(8))
dilationFilter = ones(dilationFilterSize, dilationFilterSize);
noisyImage = imerode(IMG, dilationFilter);
titleStr = ['Noisy image using Dilation with filter', newline, 'size =',num2str(dilationFilterSize)];
dilationFilterSize = dilationFilterSize + 1;
case char(noiseTypeModes(9))
dilationFilterSize = 9;
outputFolder = 'outputFiles';
outputFileTarget = 'tmp.jpg';
mkdir(outputFolder);
outputFileTarget = strcat(outputFolder, '\', outputFileTarget);
imwrite(IMG/255, outputFileTarget, 'quality', dilationFilterSize);
noisyImage = double(imread(outputFileTarget));
titleStr = ['Noisy image using jpg compression blocking effect,', newline, 'blocking factor =',num2str(dilationFilterSize)];
% dilationFilterSize = dilationFilterSize + 1;
IMG = noisyImage;
delete(outputFileTarget);
end % END of noise type choice
sigmaUpdated = sigma;
dilationFilterSizeUpdated = dilationFilterSize;
erosionFilterSizeUpdated = erosionFilterSize;
end