DGtalTools  0.9.4
2dCompImage.cpp
1 
30 #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>
35 
36 
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>
44 
45 #include <boost/program_options/options_description.hpp>
46 #include <boost/program_options/parsers.hpp>
47 #include <boost/program_options/variables_map.hpp>
49 using namespace std;
50 using namespace DGtal;
52 
56 
57 namespace po = boost::program_options;
58 
59 
107 getMAEstats(const Image2D & imageA, const Image2D &imageB, Image2DErr &imageMAE)
108 {
109  Statistic< int> stat(false);
110  for(auto const &point: imageA.domain())
111  {
112  unsigned int error = abs((imageA(point)-imageB(point)));
113  stat.addValue(error);
114  imageMAE.setValue(point, error);
115  }
116  stat.terminate();
117  return stat;
118 }
119 
120 
125 getMSEstats(const Image2D & imageA, const Image2D &imageB, Image2DErr &imageMSE)
126 {
127  Statistic< int> stat(false);
128  for(Image2D::Domain::ConstIterator it = imageA.domain().begin();
129  it!=imageA.domain().end(); it++)
130  {
131  int error = (imageA(*it)-imageB(*it))*(imageA(*it)-imageB(*it));
132  stat.addValue(error);
133  imageMSE.setValue(*it, error);
134  }
135  stat.terminate();
136  return stat;
137 }
138 
139 
140 
144 template<typename StatisticT>
145 void
146 displayStats(const StatisticT &aStat, const string &type)
147 {
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;
151 }
152 
153 
154 int main( int argc, char** argv )
155 {
156  // parse command line -------------------------------------------------------
157  po::options_description general_opt("Allowed options are");
158  general_opt.add_options()
159  ("help,h", "display this message")
160  ("imageA,a", po::value<std::string >(), "Input filename of image A." )
161  ("imageB,b", po::value<std::string >(), "Input filename of image B." )
162  ("imageError,e", po::value<std::string >(), "Output error image basename (will generate two images <basename>MSE.ppm and <basename>MAE.ppm)." )
163  ("setMaxColorValueMSE,S", po::value<int>(), "Set the maximal color value for the scale display of MSE (else the scale is set the maximal MSE value)." )
164  ("setMaxColorValueMAE,A", po::value<int>(), "Set the maximal color value for the scale display of MAE (else the scale is set from the maximal MAE value).");
165 
166 
167  bool parseOK=true;
168  po::variables_map vm;
169  try
170  {
171  po::store(po::parse_command_line(argc, argv, general_opt), vm);
172  }
173  catch(const std::exception& ex)
174  {
175  parseOK=false;
176  trace.info()<< "Error checking program options: "<< ex.what()<< endl;
177  }
178 
179 
180  // check if min arguments are given and tools description ------------------
181  po::notify(vm);
182  if( !parseOK || vm.count("help")|| argc<=1 || !vm.count("imageA")
183  || !vm.count("imageB") )
184  {
185  std::cout << "Usage: " << argv[0] << " --imageA <imageA>.pgm --imageB <imageB>.pgm -imageError <name> \n"
186  << "Compare images and displays differences (squared and absolute differences). \n"
187  << general_opt << "\n"
188  << "Typical use example:\n \t 2dCompImage -a imageA.pgm -b imageB.pgm -e errorImage -S 100 \n";
189  return 0;
190  }
191  if(!vm.count("imageA") || !vm.count("imageB"))
192  {
193  trace.error() << " The two images filename are needed to be defined" << endl;
194  return 0;
195  }
196 
197 
198  // recover the args -----------------------------------------------
199  string inputFileNameA = vm["imageA"].as<string>();
200  string inputFileNameB = vm["imageB"].as<string>();
201  string basenameOutput =vm["imageError"].as<string>();
202 
203 
204 
205  // Input images ----------------------------------------------------
206  Image2D imageA = GenericReader<Image2D>::import(inputFileNameA);
207  Image2D imageB = GenericReader<Image2D>::import(inputFileNameB);
208 
209 
210  Image2DErr imageErr (imageA.domain());
211 
212 
213  // Absolute Error between imageA and imageB -------------------------
214  Statistic<int> statMA = getMAEstats(imageA, imageB, imageErr);
215  int maxVal = statMA.max();
216  if(vm.count("setMaxColorValueMAE"))
217  {
218  maxVal = vm["setMaxColorValueMAE"].as<int>();
219  }
220  JetMap jmapMA(0, maxVal);
221  displayStats(statMA, "Absolute errror");
222  stringstream maeName; maeName << basenameOutput;
223  maeName << "MAE.ppm";
224  PPMWriter<Image2DErr, JetMap>::exportPPM(maeName.str(), imageErr, jmapMA);
225 
226 
227  // Squared Error between imageA and imageB -------------------------
228  Statistic<int> statSE = getMSEstats(imageA, imageB, imageErr);
229  maxVal = statMA.max();
230  if(vm.count("fixMaxColorValueMSE"))
231  {
232  maxVal = vm["fixMaxColorValueMSE"].as<int>();
233  }
234  JetMap jmapSE(0, maxVal);
235  displayStats(statSE, "Squared errror");
236  stringstream mseName; mseName << basenameOutput;
237  mseName << "MSE.ppm";
238  PPMWriter<Image2DErr, JetMap>::exportPPM(mseName.str(), imageErr, jmapSE);
239 
240 
241 
242  return 0;
243 }
244 
STL namespace.
MessageStream error
Trace trace(traceWriterTerm)
std::ostream & info()
const Domain & domain() const
std::vector< Value >::const_iterator ConstIterator
void setValue(const Point &aPoint, const Value &aValue)
T abs(const T &a)
std::ostream & error()