-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New tool 2dCompImage #313
New tool 2dCompImage #313
Changes from 5 commits
02d3736
c4ab7c5
82ea344
b4fa2fc
26f3dbb
dbf2ab6
f9042f1
fc6288f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
/** | ||
* This program 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 3 of the | ||
* License, or (at your option) any later version. | ||
* | ||
* This program 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 General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
**/ | ||
|
||
/** | ||
* @file | ||
* @ingroup visualisation | ||
* @author Bertrand Kerautret (\c kerautre@loria.fr ) | ||
* LORIA (CNRS, UMR 7503), University of Lorraine, France | ||
* | ||
* @date 2018/01/11 | ||
* | ||
* Source file of the tool 2dCompImage | ||
* | ||
* This file is part of the DGtal library/DGtalTools Project. | ||
*/ | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
#include "DGtal/base/Common.h" | ||
#include "DGtal/helpers/StdDefs.h" | ||
#include <DGtal/io/readers/GenericReader.h> | ||
#include <DGtal/io/writers/GenericWriter.h> | ||
|
||
|
||
#include <DGtal/images/Image.h> | ||
#include <DGtal/images/ImageContainerBySTLVector.h> | ||
#include <DGtal/images/imagesSetsUtils/SetFromImage.h> | ||
#include <DGtal/io/writers/PPMWriter.h> | ||
#include <DGtal/math/Statistic.h> | ||
#include "DGtal/io/colormaps/GradientColorMap.h" | ||
#include <DGtal/math/Statistic.h> | ||
|
||
#include <boost/program_options/options_description.hpp> | ||
#include <boost/program_options/parsers.hpp> | ||
#include <boost/program_options/variables_map.hpp> | ||
/////////////////////////////////////////////////////////////////////////////// | ||
using namespace std; | ||
using namespace DGtal; | ||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
typedef ImageContainerBySTLVector < Z2i::Domain, unsigned char > Image2D; | ||
typedef ImageContainerBySTLVector < Z2i::Domain, unsigned int > Image2DErr; | ||
typedef GradientColorMap<unsigned int, CMAP_JET, 1 > JetMap; | ||
|
||
namespace po = boost::program_options; | ||
|
||
|
||
/** | ||
@page Doc2dCompImage 2dCompImage | ||
|
||
@brief Computes and displays image comparisons (squared and absolute differences). | ||
|
||
|
||
@b Usage: 2dCompImage --imageA <imageA>.pgm --imageB <imageB>.pgm --imageError <name> | ||
|
||
@b Allowed @b options @b are : | ||
|
||
@code | ||
-h [ --help ] display this message | ||
-a [ --imageA ] arg Input filename of image A. | ||
-b [ --imageB ] arg Input filename of image B. | ||
-e [ --imageError ] arg Output error image basename (will generate | ||
two images <basename>MSE.ppm and | ||
<basename>MAE.ppm). | ||
-S [ --fixMaxColorValueMSE ] arg Fix the maximal color value for the scale | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix -> set? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes |
||
display of MSE (else the scale is set the | ||
maximal MSE value). | ||
-A [ --fixMaxColorValueMAE ] arg Fix the maximal color value for the scale | ||
display of MAE (else the scale is set from | ||
the maximal MAE value). | ||
@endcode | ||
|
||
@b Example: | ||
Typical use example: | ||
@code | ||
2dCompImage -a imageA.pgm -b imageB.pgm -e errorImage -S 100 | ||
@endcode | ||
|
||
You should obtain such a visualisation: | ||
@image html res2dCompImage.png "resulting visualisation of absolute error between two images." | ||
|
||
@see | ||
@ref 2dCompImage.cpp | ||
|
||
|
||
*/ | ||
|
||
|
||
|
||
|
||
/** | ||
* Compute statistics on the mean absolute difference between pixel values of image A and B. | ||
**/ | ||
Statistic< int> | ||
getMAEstats(const Image2D & imageA, const Image2D &imageB, Image2DErr &imageMAE) | ||
{ | ||
Statistic< int> stat(false); | ||
for(Image2D::Domain::ConstIterator it = imageA.domain().begin(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or more simply:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ;) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes thanks C++11 ;) |
||
it!=imageA.domain().end(); it++) | ||
{ | ||
unsigned int error = abs((imageA(*it)-imageB(*it))); | ||
stat.addValue(error); | ||
imageMAE.setValue(*it, error); | ||
} | ||
stat.terminate(); | ||
return stat; | ||
} | ||
|
||
|
||
/** | ||
* Compute statistics on the mean squared difference between pixel values of image A and B. | ||
**/ | ||
Statistic< int> | ||
getMSEstats(const Image2D & imageA, const Image2D &imageB, Image2DErr &imageMSE) | ||
{ | ||
Statistic< int> stat(false); | ||
for(Image2D::Domain::ConstIterator it = imageA.domain().begin(); | ||
it!=imageA.domain().end(); it++) | ||
{ | ||
int error = (imageA(*it)-imageB(*it))*(imageA(*it)-imageB(*it)); | ||
stat.addValue(error); | ||
imageMSE.setValue(*it, error); | ||
} | ||
stat.terminate(); | ||
return stat; | ||
} | ||
|
||
|
||
|
||
/** | ||
* Displays std statistics values | ||
**/ | ||
template<typename StatisticT> | ||
void | ||
displayStats(const StatisticT &aStat, const string &type) | ||
{ | ||
std::cout << "# Stats on " << type << ": mean max min unbiased_variance nb_samples " << std::endl; | ||
std::cout << aStat.mean() << " " << aStat.max() << " " << aStat.min() << " " | ||
<< " " << aStat.unbiasedVariance() << " " << aStat.samples() << std::endl; | ||
} | ||
|
||
|
||
int main( int argc, char** argv ) | ||
{ | ||
// parse command line ------------------------------------------------------- | ||
po::options_description general_opt("Allowed options are"); | ||
general_opt.add_options() | ||
("help,h", "display this message") | ||
("imageA,a", po::value<std::string >(), "Input filename of image A." ) | ||
("imageB,b", po::value<std::string >(), "Input filename of image B." ) | ||
("imageError,e", po::value<std::string >(), "Output error image basename (will generate two images <basename>MSE.ppm and <basename>MAE.ppm)." ) | ||
("fixMaxColorValueMSE,S", po::value<int>(), "Fix the maximal color value for the scale display of MSE (else the scale is set the maximal MSE value)." ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix -> set ? |
||
("fixMaxColorValueMAE,A", po::value<int>(), "Fix the maximal color value for the scale display of MAE (else the scale is set from the maximal MAE value)."); | ||
|
||
|
||
bool parseOK=true; | ||
po::variables_map vm; | ||
try | ||
{ | ||
po::store(po::parse_command_line(argc, argv, general_opt), vm); | ||
} | ||
catch(const std::exception& ex) | ||
{ | ||
parseOK=false; | ||
trace.info()<< "Error checking program options: "<< ex.what()<< endl; | ||
} | ||
|
||
|
||
// check if min arguments are given and tools description ------------------ | ||
po::notify(vm); | ||
if( !parseOK || vm.count("help")|| argc<=1 || !vm.count("imageA") | ||
|| !vm.count("imageB") ) | ||
{ | ||
std::cout << "Usage: " << argv[0] << "--imageA <imageA>.pgm --imageB <imageB>.pgm -imageError <name> \n" | ||
<< "Computes and displays image comparisons (squared and absolute differences). \n" | ||
<< general_opt << "\n" | ||
<< "Typical use example:\n \t 2dCompImage -a imageA.pgm -b imageB.pgm -e errorImage -S 100 \n"; | ||
return 0; | ||
} | ||
if(!vm.count("imageA") || !vm.count("imageB")) | ||
{ | ||
trace.error() << " The two images filename are needed to be defined" << endl; | ||
return 0; | ||
} | ||
|
||
|
||
// recover the args ----------------------------------------------- | ||
string inputFileNameA = vm["imageA"].as<string>(); | ||
string inputFileNameB = vm["imageB"].as<string>(); | ||
string basenameOutput =vm["imageError"].as<string>(); | ||
|
||
|
||
|
||
// Input images ---------------------------------------------------- | ||
Image2D imageA = GenericReader<Image2D>::import(inputFileNameA); | ||
Image2D imageB = GenericReader<Image2D>::import(inputFileNameB); | ||
|
||
|
||
Image2DErr imageErr (imageA.domain()); | ||
|
||
|
||
// Absolute Error between imageA and imageB ------------------------- | ||
Statistic<int> statMA = getMAEstats(imageA, imageB, imageErr); | ||
int maxVal = statMA.max(); | ||
if(vm.count("fixMaxColorValueMAE")) | ||
{ | ||
maxVal = vm["fixMaxColorValueMAE"].as<int>(); | ||
} | ||
JetMap jmapMA(0, maxVal); | ||
displayStats(statMA, "Absolute errror"); | ||
stringstream maeName; maeName << basenameOutput; | ||
maeName << "MAE.ppm"; | ||
PPMWriter<Image2DErr, JetMap>::exportPPM(maeName.str(), imageErr, jmapMA); | ||
|
||
|
||
// Squared Error between imageA and imageB ------------------------- | ||
Statistic<int> statSE = getMSEstats(imageA, imageB, imageErr); | ||
maxVal = statMA.max(); | ||
if(vm.count("fixMaxColorValueMSE")) | ||
{ | ||
maxVal = vm["fixMaxColorValueMSE"].as<int>(); | ||
} | ||
JetMap jmapSE(0, maxVal); | ||
displayStats(statSE, "Squared errror"); | ||
stringstream mseName; mseName << basenameOutput; | ||
mseName << "MSE.ppm"; | ||
PPMWriter<Image2DErr, JetMap>::exportPPM(mseName.str(), imageErr, jmapSE); | ||
|
||
|
||
|
||
return 0; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compare images and display differences (squared and absolute differences).
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes better thanks ;)