ViSP  2.8.0
histogram.cpp
1 /****************************************************************************
2  *
3  * $Id: histogram.cpp 4323 2013-07-18 09:24:01Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Example of Histogram manipulation.
36  *
37  * Author:
38  * Fabien Spindler
39  *
40  *****************************************************************************/
41 
51 #include <visp/vpDebug.h>
52 #include <visp/vpImage.h>
53 #include <visp/vpImageIo.h>
54 #include <visp/vpHistogram.h>
55 #include <visp/vpParseArgv.h>
56 #include <visp/vpIoTools.h>
57 
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <sstream>
61 #include <iomanip>
62 
63 // List of allowed command line options
64 #define GETOPTARGS "i:o:h"
65 
84 void usage(const char *name, const char *badparam, std::string ipath,
85  std::string opath, std::string user)
86 {
87  fprintf(stdout, "\n\
88 Read an image on the disk, display it using X11, display some\n\
89 features (line, circle, caracters) in overlay and finaly write \n\
90 the image and the overlayed features in an image on the disk.\n\
91 \n\
92 SYNOPSIS\n\
93  %s [-i <input image path>] [-o <output histogram path>]\n\
94  [-h]\n\
95 ", name);
96 
97  fprintf(stdout, "\n\
98 OPTIONS: Default\n\
99  -i <input image path> %s\n\
100  Set image input path.\n\
101  From this path read \"ViSP-images/Klimt/Klimt.pgm\"\n\
102  image.\n\
103  Setting the VISP_INPUT_IMAGE_PATH environment\n\
104  variable produces the same behaviour than using\n\
105  this option.\n\
106 \n\
107  -o <output histogram path> %s\n\
108  From this directory, creates the \"%s\"\n\
109  subdirectory depending on the username, where \n\
110  \"histogram.txt\" is saved.\n\
111 \n\
112  -h\n\
113  Print the help.\n\n",
114  ipath.c_str(), opath.c_str(), user.c_str());
115 
116  if (badparam) {
117  fprintf(stderr, "ERROR: \n" );
118  fprintf(stderr, "\nBad parameter [%s]\n", badparam);
119  }
120 
121 }
135 bool getOptions(int argc, const char **argv,
136  std::string &ipath, std::string &opath,
137  std::string user)
138 {
139  const char *optarg;
140  int c;
141  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg)) > 1) {
142 
143  switch (c) {
144  case 'i': ipath = optarg; break;
145  case 'o': opath = optarg; break;
146  case 'h': usage(argv[0], NULL, ipath, opath, user); return false; break;
147 
148  default:
149  usage(argv[0], optarg, ipath, opath, user); return false; break;
150  }
151  }
152 
153  if ((c == 1) || (c == -1)) {
154  // standalone param or error
155  usage(argv[0], NULL, ipath, opath, user);
156  std::cerr << "ERROR: " << std::endl;
157  std::cerr << " Bad argument " << optarg << std::endl << std::endl;
158  return false;
159  }
160 
161  return true;
162 }
163 
164 int
165 main(int argc, const char ** argv)
166 {
167  std::string env_ipath;
168  std::string opt_ipath;
169  std::string opt_opath;
170  std::string ipath;
171  std::string opath;
172  std::string filename;
173  std::string username;
174 
175  // Get the VISP_IMAGE_PATH environment variable value
176  char *ptenv = getenv("VISP_INPUT_IMAGE_PATH");
177  if (ptenv != NULL)
178  env_ipath = ptenv;
179  // std::cout << "env_ipath: " << env_ipath << std::endl;
180 
181  // Set the default input path
182  if (! env_ipath.empty())
183  ipath = env_ipath;
184 
185  // Set the default output path
186 #ifdef WIN32
187  opt_opath = "C:/temp";
188 #else
189  opt_opath = "/tmp";
190 #endif
191 
192  // Get the user login name
193  vpIoTools::getUserName(username);
194 
195  // Read the command line options
196  if (getOptions(argc, argv, opt_ipath, opt_opath, username) == false) {
197  exit (-1);
198  }
199 
200  // Get the option values
201  if (!opt_ipath.empty())
202  ipath = opt_ipath;
203  if (!opt_opath.empty())
204  opath = opt_opath;
205 
206  // Append to the output path string, the login name of the user
207  std::string dirname = opath + vpIoTools::path("/") + username;
208 
209  // Test if the output path exist. If no try to create it
210  if (vpIoTools::checkDirectory(dirname) == false) {
211  try {
212  // Create the dirname
213  vpIoTools::makeDirectory(dirname);
214  }
215  catch (...) {
216  usage(argv[0], NULL, ipath, opath, username);
217  std::cerr << std::endl
218  << "ERROR:" << std::endl;
219  std::cerr << " Cannot create " << dirname << std::endl;
220  std::cerr << " Check your -o " << opath << " option " << std::endl;
221  exit(-1);
222  }
223  }
224 
225  // Compare ipath and env_ipath. If they differ, we take into account
226  // the input path comming from the command line option
227  if (opt_ipath.empty()) {
228  if (ipath != env_ipath) {
229  std::cout << std::endl
230  << "WARNING: " << std::endl;
231  std::cout << " Since -i <visp image path=" << ipath << "> "
232  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
233  << " we skip the environment variable." << std::endl;
234  }
235  }
236 
237  // Test if an input path is set
238  if (opt_ipath.empty() && env_ipath.empty()){
239  usage(argv[0], NULL, ipath, opath, username);
240  std::cerr << std::endl
241  << "ERROR:" << std::endl;
242  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
243  << std::endl
244  << " environment variable to specify the location of the " << std::endl
245  << " image path where test images are located." << std::endl << std::endl;
246  exit(-1);
247  }
248 
249  // Create a grey level image
251 
252  // Load a grey image from the disk
253  filename = ipath;
254  if (opt_ipath.empty())
255  filename += vpIoTools::path("/ViSP-images/Klimt/Klimt.pgm");
256 
257  std::cout << "Read: " << filename << std::endl;
258  vpImageIo::read(I, filename) ;
259 
260  unsigned char distance = 60;
261  vpHistogram h;
262 
263  // Computes the histogram from the image
264  h.calculate(I);
265 
266  // Save the histogram
267  filename = dirname + vpIoTools::path("/histogram.txt");
268  std::cout << "Save the histogram in: " << filename << std::endl;
269  h.write(filename);
270 
271  // Smooth the histogram
272  h.smooth();
273  // Save the histogram
274  filename = dirname + vpIoTools::path("/histogram_smoothed.txt");
275  std::cout << "Save the smoothed histogram in: " << filename << std::endl;
276  h.write(filename);
277 
278  std::list<vpHistogramPeak> peaks;
279  unsigned int nbpeaks = 0;
280 
281  // get all the histogram peaks
282  nbpeaks = h.getPeaks(peaks);
283 
284  vpTRACE("List of peaks");
285  vpTRACE("Nb peaks: %d", nbpeaks);
286  if (nbpeaks) {
287  for(std::list<vpHistogramPeak>::const_iterator it = peaks.begin(); it != peaks.end(); ++it)
288  {
289  vpHistogramPeak p = *it;
290  vpTRACE("Peak: gray level: %d value: %d", p.getLevel(), p.getValue());
291  }
292  }
293 
294  // sort all the histogram peaks list to have the highest peak at the
295  // beginning of the list, the smallest at the end.
296  nbpeaks = h.sort(peaks);
297 
298  vpTRACE("Sorted list of peaks");
299  vpTRACE("Nb peaks: %d", nbpeaks);
300  if (nbpeaks) {
301  for(std::list<vpHistogramPeak>::const_iterator it = peaks.begin(); it != peaks.end(); ++it)
302  {
303  vpHistogramPeak p = *it;
304  vpTRACE("Peak: gray level: %d value: %d", p.getLevel(), p.getValue());
305  }
306  }
307 
308  // Get the two highest histogram peaks. peak1 is the highest
309  vpHistogramPeak peak1, peak2;
310  nbpeaks = h.getPeaks(distance, peak1, peak2);
311  if (nbpeaks != 2) {
312  std::cout << "Not a bimodal histogram..." << std::endl;
313  }
314  else {
315  vpTRACE("Bimodal histogram: main peak1: %d-%d second peak2: %d-%d",
316  peak1.getLevel(), peak1.getValue(),
317  peak2.getLevel(), peak2.getValue());
318  }
319 
320  // Get the valey between the two highest peaks
321  vpHistogramValey valey;
322  if (h.getValey(peak1, peak2, valey) == false) {
323  vpTRACE("No valey found...");
324  }
325  else {
326  vpTRACE("Valey: %d-%d", valey.getLevel(), valey.getValue());
327  }
328 
329 
330  vpHistogramValey valeyl, valeyr;
331 
332  {
333  // Search the two valeys around peak1
334  unsigned ret = h.getValey(distance, peak1, valeyl, valeyr);
335  if (ret == 0x00) {
336  vpTRACE("No left and right valey for peak %d-%d...",
337  peak1.getLevel(), peak1.getValue());
338  }
339  else if (ret == 0x10) {
340  vpTRACE("No right valey for peak %d-%d...",
341  peak1.getLevel(), peak1.getValue());
342  vpTRACE("Left valey: %d-%d", valeyl.getLevel(), valeyl.getValue());
343  }
344  else if (ret == 0x01) {
345  vpTRACE("No left valey for peak %d-%d...",
346  peak1.getLevel(), peak1.getValue());
347  vpTRACE("Right valey: %d-%d", valeyr.getLevel(), valeyr.getValue());
348  }
349  else if (ret == 0x11) {
350  vpTRACE("Left valey: %d-%d", valeyl.getLevel(), valeyl.getValue());
351  vpTRACE("Right valey: %d-%d", valeyr.getLevel(), valeyr.getValue());
352  }
353  }
354  {
355  // Search the two valeys around peak2
356  unsigned ret = h.getValey(distance, peak2, valeyl, valeyr);
357  if (ret == 0x00) {
358  vpTRACE("No left and right valey for peak %d-%d...",
359  peak2.getLevel(), peak2.getValue());
360  }
361  else if (ret == 0x10) {
362  vpTRACE("No right valey for peak %d-%d...",
363  peak2.getLevel(), peak2.getValue());
364  vpTRACE("Left valey: %d-%d", valeyl.getLevel(), valeyl.getValue());
365  }
366  else if (ret == 0x01) {
367  vpTRACE("No left valey for peak %d-%d...",
368  peak2.getLevel(), peak2.getValue());
369  vpTRACE("Right valey: %d-%d", valeyr.getLevel(), valeyr.getValue());
370  }
371  else if (ret == 0x11) {
372  vpTRACE("Left valey: %d-%d", valeyl.getLevel(), valeyl.getValue());
373  vpTRACE("Right valey: %d-%d", valeyr.getLevel(), valeyr.getValue());
374  }
375  }
376 
378  // get the valey between the two highest peaks. Here we don't know
379  // which of peakl or peakr is the highest.
380  vpHistogramPeak peakl, peakr;
381  if (h.getPeaks(distance, peakl, peakr, valey) == false) {
382  std::cout << "Not a bimodal histogram..." << std::endl;
383  }
384  else {
385  vpTRACE("Bimodal histogram: valey %d-%d for peakl: %d-%d peakr: %d-%d",
386  valey.getLevel(), valey.getValue(),
387  peakl.getLevel(), peakl.getValue(),
388  peakr.getLevel(), peakr.getValue());
389  }
390 
391 }
392 
393 
394 
395 /*
396  * Local variables:
397  * c-basic-offset: 2
398  * End:
399  */
void calculate(const vpImage< unsigned char > &I)
unsigned getPeaks(std::list< vpHistogramPeak > &peaks)
static bool checkDirectory(const char *dirname)
Definition: vpIoTools.cpp:335
#define vpTRACE
Definition: vpDebug.h:401
unsigned getValue() const
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:715
Class to compute a gray level image histogram.
Definition: vpHistogram.h:115
Declaration of the peak (maximum value) in a gray level image histogram.
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:79
unsigned char getLevel() const
static void makeDirectory(const char *dirname)
Definition: vpIoTools.cpp:404
void smooth(const unsigned int fsize=3)
unsigned getValue() const
static std::string getUserName()
Definition: vpIoTools.cpp:140
unsigned sort(std::list< vpHistogramPeak > &peaks)
unsigned char getLevel() const
bool write(const std::string &filename)
static void read(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:277
Declaration of the valey (minimum value) in a gray level image histogram.
unsigned getValey(std::list< vpHistogramValey > &valey)