31 #include "DGtal/base/Common.h"
32 #include "DGtal/helpers/StdDefs.h"
33 #include <DGtal/io/readers/GenericReader.h>
34 #include <DGtal/io/writers/GenericWriter.h>
37 #include <DGtal/images/Image.h>
38 #include <DGtal/images/ImageContainerBySTLVector.h>
39 #include <DGtal/images/imagesSetsUtils/SetFromImage.h>
40 #include <DGtal/io/writers/PPMWriter.h>
41 #include <DGtal/math/Statistic.h>
42 #include "DGtal/io/colormaps/GradientColorMap.h"
43 #include <DGtal/math/Statistic.h>
50 using namespace DGtal;
53 typedef ImageContainerBySTLVector < Z2i::Domain, unsigned char > Image2D;
54 typedef ImageContainerBySTLVector < Z2i::Domain, unsigned int > Image2DErr;
55 typedef GradientColorMap<unsigned int, CMAP_JET, 1 > JetMap;
107 getMAEstats(
const Image2D & imageA,
const Image2D &imageB, Image2DErr &imageMAE)
109 Statistic< int> stat(
false);
110 for(
auto const &point: imageA.domain())
112 unsigned int error = abs((imageA(point)-imageB(point)));
113 stat.addValue(error);
114 imageMAE.setValue(point, error);
125 getMSEstats(
const Image2D & imageA,
const Image2D &imageB, Image2DErr &imageMSE)
127 Statistic< int> stat(
false);
128 for(Image2D::Domain::ConstIterator it = imageA.domain().begin();
129 it!=imageA.domain().end(); it++)
131 int error = (imageA(*it)-imageB(*it))*(imageA(*it)-imageB(*it));
132 stat.addValue(error);
133 imageMSE.setValue(*it, error);
144 template<
typename StatisticT>
146 displayStats(
const StatisticT &aStat,
const string &type)
148 std::cout <<
"# Stats on " << type <<
": mean max min unbiased_variance nb_samples " << std::endl;
149 std::cout << aStat.mean() <<
" " << aStat.max() <<
" " << aStat.min() <<
" "
150 <<
" " << aStat.unbiasedVariance() <<
" " << aStat.samples() << std::endl;
154 int main(
int argc,
char** argv )
159 std::string inputFileNameA;
160 std::string inputFileNameB;
161 std::string basenameOutput;
165 app.description(
"Compare images and displays differences (squared and absolute differences).\n Typical use example:\n \t 2dCompImage imageA.pgm imageB.pgm -e errorImage -S 100 \n");
166 app.add_option(
"-a,--imageA,1", inputFileNameA,
"Input filename of image A." )
168 ->check(CLI::ExistingFile);
169 app.add_option(
"-b,--imageB,2", inputFileNameA,
"Input filename of image B." )
171 ->check(CLI::ExistingFile);
174 app.add_option(
"--imageError,-e",basenameOutput,
"Output error image basename (will generate two images <basename>MSE.ppm and <basename>MAE.ppm).");
176 auto setMaxMSEOpt = app.add_option(
"--setMaxColorValueMSE,-S",maxValueMSE,
"Set the maximal color value for the scale display of MSE (else the scale is set the maximal MSE value).");
177 auto setMaxMAEOpt = app.add_option(
"--setMaxColorValueMAE,-A",maxValueMAE,
"Set the maximal color value for the scale display of MAE (else the scale is set from the maximal MAE value).");
180 app.get_formatter()->column_width(40);
181 CLI11_PARSE(app, argc, argv);
186 Image2D imageA = GenericReader<Image2D>::import(inputFileNameA);
187 Image2D imageB = GenericReader<Image2D>::import(inputFileNameB);
189 Image2DErr imageErr (imageA.domain());
193 Statistic<int> statMA = getMAEstats(imageA, imageB, imageErr);
194 int maxVal = statMA.max();
195 if(setMaxMAEOpt->count() > 0)
197 maxVal = maxValueMAE;
199 JetMap jmapMA(0, maxVal);
200 displayStats(statMA,
"Absolute errror");
201 stringstream maeName; maeName << basenameOutput;
202 maeName <<
"MAE.ppm";
203 PPMWriter<Image2DErr, JetMap>::exportPPM(maeName.str(), imageErr, jmapMA);
206 Statistic<int> statSE = getMSEstats(imageA, imageB, imageErr);
207 maxVal = statMA.max();
208 if(setMaxMSEOpt->count()>0)
210 maxVal = maxValueMSE;
212 JetMap jmapSE(0, maxVal);
213 displayStats(statSE,
"Squared error");
214 stringstream mseName; mseName << basenameOutput;
215 mseName <<
"MSE.ppm";
216 PPMWriter<Image2DErr, JetMap>::exportPPM(mseName.str(), imageErr, jmapSE);