What is the best algorithm to find difference between two images?

Dear Friends,
I'm working on a project where I have to compare two images and spot the relevant differences between then. The images are usually from product packages and we are trying to make sure nothing wrong happened in the printing process.
In this scenario one of the images is usually a digital version and the other one is a scanned version of what was printed.
I'm segmenting the images in small parts and trying histogram comparison between the parts. Unfortunately I`m getting to much false positives and if I increase the tolerance I lose some differences.
Am I doing a good approach? I'm a newby on computer vision and I wonder if histogram comparison is good for my project.
Regards, Felipe

6 Comments

imshowpair was my first attempt but it gave me tons of differences, take a look at the attached file bad-result-imshowpair.jpg.
The problem is that I'm comparing an image that was made on photoshop with an image that was digitized using an scanner.
Comparing the samples that I attached the goal is to find only the real 5 differences. The rest is only noise and quality loss and should be discarded.
I'm not sure if I can discard those minor differences with imshowpair, can I?
Thank you
I wrote/used two pieces of code ages ago for a task (it was mainly edge detection and comparing two pictures). I am pasting them down here, I hope a combination of them helps you with your problem:
clear all
close all
clc
% Read in a standard MATLAB gray scale image.
folder = fullfile(matlabroot, '/the specific folder');
baseFileName = 'image.png';
fullFileName = fullfile(folder, baseFileName);
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 1.
[rows columns numberOfColorBands] = size(grayImage);
% Display the original gray scale image.
subplot(2, 2, 1);
imshow(grayImage, []);
% title('Original Grayscale Image - Spatial Domain', 'FontSize', fontSize);
title('Original Grayscale Image - Spatial Domain');
% Enlarge figure to full screen.
% set(gcf, 'Position', get(0,'Screensize'));
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
set(gcf,'name','Edge Detection and ','numbertitle','off')
% Take the FFT.
fftImage = fft2(grayImage);
% Shift it and take log so we can see it easier.
centeredFFTImage = log(fftshift(real(fftImage)));
% Display the FFT image.
subplot(2, 2, 2);
imshow(centeredFFTImage, []);
% title('log(FFT Image) - Frequency Domain', 'FontSize', fontSize);
title('log(FFT Image) - Frequency Domain');
% Zero out the corners
window = 30;
fftImage(1:window, 1:window) = 0;
fftImage(end-window:end, 1:window) = 0;
fftImage(1:window, end-window:end) = 0;
fftImage(end-window:end, end-window:end) = 0;
% Display the filtered FFT image.
% Shift it and take log so we can see it easier.
centeredFFTImage = log(fftshift(real(fftImage)));
subplot(2, 2, 3);
imshow(centeredFFTImage, []);
% title('Filtered log(FFT Image) - Frequency Domain', 'FontSize', fontSize);
title('Filtered log(FFT Image) - Frequency Domain');
% Inverse FFT to get high pass filtered image.
output = ifft2(fftImage);
% Display the output.
subplot(2, 2, 4);
imshow(real(output), []);
% title('High Pass Filtered Image - Back in the Spatial Domain', 'FontSize', fontSize);
title('High Pass Filtered Image - Back in the Spatial Domain');
figure;
imhist(real(output))
% calculates the histogram for the intensity image I and displays a plot of the histogram. The number of bins in the histogram is determined by the image type.
and the second code:
clear all
close all
clc
% Importing the first image (reference):
Image = imread('image.png');
BW = im2uint8(Image);
[B,L,N,A] = bwboundaries(BW);
% Showing the boundaries:
figure, imshow(BW); hold on;
colors=['b' 'g' 'r' 'c' 'm' 'y'];
for k=1:length(B)
boundary = B{k};
cidx = mod(k,length(colors))+1;
plot(boundary(:,2), boundary(:,1),...
colors(cidx),'LineWidth',2);
% Randomize text position for better visibility
rndRow = ceil(length(boundary)/(mod(rand*k,7)+1));
col = boundary(rndRow,2); row = boundary(rndRow,1);
h = text(col+1, row-1, num2str(L(row,col)));
set(h,'Color',colors(cidx),...
'FontSize',14,'FontWeight','bold');
end
% figure; spy(A);
% Importing the second image:
BW1 = imread('image2.png');
[B1,L1,N1,A1] = bwboundaries(BW1);
% Showing the boundaries:
figure, imshow(BW1); hold on;
colors=['b' 'g' 'r' 'c' 'm' 'y'];
for y=1:length(B1)
boundary1 = B1{y};
cidx1 = mod(y,length(colors))+1;
plot(boundary1(:,2), boundary1(:,1),...
colors(cidx1),'LineWidth',2);
% Randomize text position for better visibility
rndRow1 = ceil(length(boundary1)/(mod(rand*y,7)+1));
col1 = boundary1(rndRow,2); row1 = boundary1(rndRow,1);
h1 = text(col1+1, row1-1, num2str(L(row1,col1)));
set(h1,'Color',colors(cidx1),...
'FontSize',14,'FontWeight','bold');
end
% figure; spy(A1);
% Resizing the second image to match the size of the first image:
[rowsA colsA RGBA]=size(BW);
[rowsB colsB RGBB]=size(BW1);
C=imresize(BW,[rowsB colsB]);
% Showing the images next to each other:
figure;
imshowpair(BW,C,'diff');
% The following two lines do the same thing that the function above does:
% K = imabsdiff(BW,C);
% figure, imshow(K,[])
% Showing the images on top of each other in black and white:
figure;
imshowpair(BW,C,'montage');
% Showing the images on top of each other:
figure;
imshowpair(BW,C,'blend','Scaling','joint');
% K = imabsdiff(BW,C);
% figure, imshow(K,[])
Amir, put your suggestions as a new "Answer" (further down this page) instead of here as a comment to his question. If he thinks your solution is the best and he accepts it you can get credit/reputation points for it.
thanks a lot Amir I will try mixing your code with mine.
hii felipe novais I have the same problem as you feel. My email id is akshaymarvaniya@gmail.com if you progress in this problem then send some information if it is possible then help me

Sign in to comment.

Answers (4)

OK, I am just copying and pasting my answer. Plus, in this code I have resized the pictures to get the same size images in order to compare them.
I wrote/used two pieces of code ages ago for a task (it was mainly edge detection and comparing two pictures). I am pasting them down here, I hope a combination of them helps you with your problem:
clear all
close all
clc
% Read in a standard MATLAB gray scale image.
folder = fullfile(matlabroot, '/the specific folder');
baseFileName = 'image.png';
fullFileName = fullfile(folder, baseFileName);
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 1.
[rows columns numberOfColorBands] = size(grayImage);
% Display the original gray scale image.
subplot(2, 2, 1);
imshow(grayImage, []);
% title('Original Grayscale Image - Spatial Domain', 'FontSize', fontSize);
title('Original Grayscale Image - Spatial Domain');
% Enlarge figure to full screen.
% set(gcf, 'Position', get(0,'Screensize'));
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
set(gcf,'name','Edge Detection and ','numbertitle','off')
% Take the FFT.
fftImage = fft2(grayImage);
% Shift it and take log so we can see it easier.
centeredFFTImage = log(fftshift(real(fftImage)));
% Display the FFT image.
subplot(2, 2, 2);
imshow(centeredFFTImage, []);
% title('log(FFT Image) - Frequency Domain', 'FontSize', fontSize);
title('log(FFT Image) - Frequency Domain');
% Zero out the corners
window = 30;
fftImage(1:window, 1:window) = 0;
fftImage(end-window:end, 1:window) = 0;
fftImage(1:window, end-window:end) = 0;
fftImage(end-window:end, end-window:end) = 0;
% Display the filtered FFT image.
% Shift it and take log so we can see it easier.
centeredFFTImage = log(fftshift(real(fftImage)));
subplot(2, 2, 3);
imshow(centeredFFTImage, []);
% title('Filtered log(FFT Image) - Frequency Domain', 'FontSize', fontSize);
title('Filtered log(FFT Image) - Frequency Domain');
% Inverse FFT to get high pass filtered image.
output = ifft2(fftImage);
% Display the output.
subplot(2, 2, 4);
imshow(real(output), []);
% title('High Pass Filtered Image - Back in the Spatial Domain', 'FontSize', fontSize);
title('High Pass Filtered Image - Back in the Spatial Domain');
figure;
imhist(real(output))
% calculates the histogram for the intensity image I and displays a plot of the histogram. The number of bins in the histogram is determined by the image type.
and the second code:
clear all
close all
clc
% Importing the first image (reference):
Image = imread('image.png');
BW = im2uint8(Image);
[B,L,N,A] = bwboundaries(BW);
% Showing the boundaries:
figure, imshow(BW); hold on;
colors=['b' 'g' 'r' 'c' 'm' 'y'];
for k=1:length(B)
boundary = B{k};
cidx = mod(k,length(colors))+1;
plot(boundary(:,2), boundary(:,1),...
colors(cidx),'LineWidth',2);
% Randomize text position for better visibility
rndRow = ceil(length(boundary)/(mod(rand*k,7)+1));
col = boundary(rndRow,2); row = boundary(rndRow,1);
h = text(col+1, row-1, num2str(L(row,col)));
set(h,'Color',colors(cidx),...
'FontSize',14,'FontWeight','bold');
end
% figure; spy(A);
% Importing the second image:
BW1 = imread('image2.png');
[B1,L1,N1,A1] = bwboundaries(BW1);
% Showing the boundaries:
figure, imshow(BW1); hold on;
colors=['b' 'g' 'r' 'c' 'm' 'y'];
for y=1:length(B1)
boundary1 = B1{y};
cidx1 = mod(y,length(colors))+1;
plot(boundary1(:,2), boundary1(:,1),...
colors(cidx1),'LineWidth',2);
% Randomize text position for better visibility
rndRow1 = ceil(length(boundary1)/(mod(rand*y,7)+1));
col1 = boundary1(rndRow,2); row1 = boundary1(rndRow,1);
h1 = text(col1+1, row1-1, num2str(L(row1,col1)));
set(h1,'Color',colors(cidx1),...
'FontSize',14,'FontWeight','bold');
end
% figure; spy(A1);
% Resizing the second image to match the size of the first image:
[rowsA colsA RGBA]=size(BW);
[rowsB colsB RGBB]=size(BW1);
C=imresize(BW,[rowsB colsB]);
% Showing the images next to each other:
figure;
imshowpair(BW,C,'diff');
% The following two lines do the same thing that the function above does:
% K = imabsdiff(BW,C);
% figure, imshow(K,[])
% Showing the images on top of each other in black and white:
figure;
imshowpair(BW,C,'montage');
% Showing the images on top of each other:
figure;
imshowpair(BW,C,'blend','Scaling','joint');
% K = imabsdiff(BW,C);
% figure, imshow(K,[])

3 Comments

In second codes i face one error plz hlep how to resolve it error:'imshowpair' for input arguments of type"uint8"????
You must have a version of MATLAB so old that the imshowpair() function isn't in it yet. It was introduced in R2012a.
... or you do not have the Image Processing Toolbox

Sign in to comment.

First of all make sure the images are scaled, registered, and histogram matched. Then subtract them.
The best algorithm to find differences between images is to first check that they are the same size and then to use ~= to find the places they differ. Every place that is not identical is a difference between the images.
If you care about some differences more than you care about others, then you are not looking for the best algorithm to find differences between images.

1 Comment

Your completely right, I'm sorry about the title. It gave a wrong idea of what my real problem really is.

Sign in to comment.

If it's all print you should try PyTesserract in python. Use the OCR and get the result as string for both the images and as you want to check if it is an exact match just compare the strings produced.

Categories

Find more on Convert Image Type in Help Center and File Exchange

Asked:

on 19 Jul 2015

Answered:

on 26 May 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!