Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleImageDiff.cpp

Example for difference calculation of images: Takes two RGB input images and calculates the difference between them. Should be used for images that were taken from the same viewpoint with different aperture/exposure to visualize the difference in the two images. If the images are bigger than 1024x256 the difference for each channel will be visualized in a diagram as well.NOTE THAT the first image should be the brighter one! If you don't stick to this, the diff image might be black due to (prevented) underflows!

Author
rwulff
/*
This file is part of the BIAS library (Basic ImageAlgorithmS).
Copyright (C) 2003-2009 (see file CONTACT for details)
Multimediale Systeme der Informationsverarbeitung
Institut fuer Informatik
Christian-Albrechts-Universitaet Kiel
BIAS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
BIAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with BIAS; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @example ExampleImageDiff.cpp
@relates Image
@brief Example for difference calculation of images:
Takes two RGB input images and calculates the difference between them.
Should be used for images that were taken from the same viewpoint with
different aperture/exposure to visualize the difference in the two
images.
If the images are bigger than 1024x256 the difference for each channel
will be visualized in a diagram as well.
NOTE THAT the first image should be the brighter one! If you don't stick
to this, the diff image might be black due to (prevented) underflows!
@ingroup g_examples
@author rwulff
*/
#include <Base/Image/Image.hh>
#include <Base/Image/ImageIO.hh>
#include <Base/ImageUtils/ImageDraw.hh>
using namespace BIAS;
using namespace std;
int main(int argc, char *argv[]) {
// check params
if (argc < 3) {
cout << "wrong parameter count!!" << endl << endl;
cout << "usage:" << endl;
cout << argv[0] << " " << "<brighter_image> <darker_image>" << endl;
return -1;
}
// load images (suppose that first image is the brighter one)
if (ImageIO::Load(argv[1], im1) != 0) {
cout << "image 1 could not be loaded!" << endl;
return -1;
}
else {
cout << "image 1 loaded!" << endl;
}
if (ImageIO::Load(argv[2], im2) != 0) {
cout << "image 2 could not be loaded!" << endl;
return -1;
}
else {
cout << "image 2 loaded!" << endl;
}
cout << "images loaded" << endl;
// ensure that input images have same size and RGB color model and init diffImage
BIASASSERT(im1.GetWidth() == im2.GetWidth() && im1.GetHeight() == im2.GetHeight());
Image<unsigned char> imDiff(im1);
// draw per-channel differences only if pictures are at least 1024x256
bool drawChannelDiffs = im1.GetWidth() >= 1024 && im1.GetHeight() >= 256;
// get image data
unsigned char *im1Data = im1.GetImageData();
unsigned char *im2Data = im2.GetImageData();
unsigned char *imDiffData = imDiff.GetImageData();
unsigned int offset = 0;
int diff = 0;
unsigned int gammaX, gammaY;
cout << "starting iteration..." << endl;
// iterate over pixels and draw difference image
for (unsigned int y = 0; y < im1.GetHeight(); y++) {
for (unsigned int x = 0; x < im1.GetWidth(); x++) {
offset = y*im1.GetWidth()*im1.GetChannelCount() + x*im1.GetChannelCount();
// produce difference image in gray-scale
diff = (int)im1Data[offset] - (int)im2Data[offset]
+ (int)im1Data[offset+1] - (int)im2Data[offset+1]
+ (int)im1Data[offset+2] - (int)im2Data[offset+2];
diff /= 3;
diff = diff < 0 ? 0 : diff;
diff = diff > 255 ? 255 : diff;
imDiffData[offset] = (unsigned char)diff;
imDiffData[offset+1] = (unsigned char)diff;
imDiffData[offset+2] = (unsigned char)diff;
// draw per-channel difference visualiziation
if (drawChannelDiffs) {
// red
gammaX = (unsigned int)im1Data[offset];
gammaY = 256 - (unsigned int)im2Data[offset];
imDiffData[gammaY*im1.GetWidth()*im1.GetChannelCount() + gammaX*im1.GetChannelCount()]
= 255;
// green
gammaX = (unsigned int)im1Data[offset+1] + 256;
gammaY = 256 - (unsigned int)im2Data[offset+1];
imDiffData[gammaY*im1.GetWidth()*im1.GetChannelCount() + gammaX*im1.GetChannelCount() + 1]
= 255;
// blue
gammaX = (unsigned int)im1Data[offset+2] + 512;
gammaY = 256 - (unsigned int)im2Data[offset+2];
imDiffData[gammaY*im1.GetWidth()*im1.GetChannelCount() + gammaX*im1.GetChannelCount() + 2]
= 255;
// arithmetic mean
gammaX = (unsigned int)im1Data[offset] + (unsigned int)im1Data[offset+1] + (unsigned int)im1Data[offset+2];
gammaX /= 3;
gammaX += 768;
gammaY = (unsigned int)im2Data[offset] + (unsigned int)im2Data[offset+1] + (unsigned int)im2Data[offset+2];
gammaY /= 3;
gammaY = 256 - gammaY;
offset = gammaY*im1.GetWidth()*im1.GetChannelCount() + gammaX*im1.GetChannelCount();
imDiffData[offset] = 255;
imDiffData[offset + 1] = 255;
imDiffData[offset + 2] = 255;
}
}
}
ImageIO::Save("diff.mip", imDiff);
cout << "done!" << endl;
return 0;
}