00001 /*---------------------------------------------------------------------+ 00002 | Library QgarLib, graphics analysis and recognition | 00003 | Copyright (C) 2002 Qgar Project, LORIA | 00004 | | 00005 | This library is free software; you can redistribute it and/or | 00006 | modify it under the terms of the GNU Lesser General Public | 00007 | License version 2.1, as published by the Free Software Foundation. | 00008 | | 00009 | This library is distributed in the hope that it will be useful, | 00010 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 00011 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 00012 | See the GNU Lesser General Public License for more details. | 00013 | | 00014 | The GNU Lesser General Public License is included in the file | 00015 | LICENSE.LGPL, in the root directory of the Qgar packaging. See | 00016 | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. | 00017 | To receive a paper copy, write to the Free Software Foundation, | 00018 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | 00019 | | 00020 | Contact Project Qgar for any information: | 00021 | LORIA - équipe Qgar | 00022 | B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France | 00023 | email: qgar-contact@loria.fr | 00024 | http://www.qgar.org/ | 00025 *---------------------------------------------------------------------*/ 00026 00027 00028 #ifndef __HISTOGRAM_H_INCLUDED__ 00029 #define __HISTOGRAM_H_INCLUDED__ 00030 00031 00032 /** 00033 * @file Histogram.H 00034 * @brief Header file of class qgar::Histogram. 00035 * 00036 * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a> 00037 * @date December 5, 2003 14:58 00038 * @since Qgar 2.1.1 00039 */ 00040 00041 00042 // For RCS/CVS use: Do not delete 00043 /* $Id: Histogram.H,v 1.21 2005/10/14 17:05:47 masini Exp $ */ 00044 00045 00046 00047 // STD 00048 #include <vector> 00049 // STL 00050 #include <algorithm> 00051 #include <numeric> 00052 // QGAR 00053 #include <qgarlib/GenImage.H> 00054 #include <qgarlib/QgarErrorDomain.H> 00055 00056 00057 00058 namespace qgar 00059 { 00060 00061 00062 /** 00063 * @ingroup DS_HISTO 00064 * 00065 * @class Histogram Histogram.H "qgarlib/Histogram.H" 00066 * 00067 * @brief General representation of a histogram. 00068 * 00069 * A histogram records frequencies of <i>samples</i> in a vector 00070 * of <i>cells</i>. A sample is a value in the range 00071 * [ <b>lowerBnd</b>, <b>upperBnd</b> ]. Bounds may be negative. 00072 * A cell records the frequency of samples included in 00073 * [ sample, sample + <b>samplingRate</b> [; the default sampling rate 00074 * is <b>1</b>. For example, the cell at the lower bound records the frequency 00075 * of samples in [ <b>lowerBnd</b>, <b>lowerBnd</b> + <b>samplingRate</b> [. 00076 * 00077 * @warning 00078 * Frequencies may be negative. Function qgar::Histogram::minus, 00079 * that decrements a frequency, does not perform any check about the value 00080 * of the resulting frequency. 00081 * 00082 * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a>, 00083 * from previous work by karl Tombre 00084 * @date December 5, 2003 14:58 00085 * @since Qgar 2.1.1 00086 */ 00087 class Histogram 00088 { 00089 // ------------------------------------------------------------------- 00090 // P U B L I C M E M B E R S 00091 // ------------------------------------------------------------------- 00092 public: 00093 00094 /** @name Constructors */ 00095 // ============ 00096 //@{ 00097 00098 /** 00099 * @brief Default constructor. 00100 * 00101 * Sampling rate is set to <b>1</b>, lower and upper bounds 00102 * to <b>0</b>, and the vector of cells is empty. 00103 */ 00104 Histogram(); 00105 00106 /** 00107 * @brief Copy constructor. 00108 * @param aHistg a histogram 00109 */ 00110 Histogram(const Histogram& aHistg); 00111 00112 /** 00113 * @brief Construct from lower and upper bounds, and a sampling rate. 00114 * 00115 * All cells are set to <b>0</b>. 00116 * 00117 * @param aLowerBnd lower bound 00118 * @param anUpperBnd upper bound 00119 * @param aSampRate sampling rate, i.e. cell width (default <b>1</b>) 00120 * 00121 * @exception qgar::QgarErrorDomain 00122 * (sampling rate is 0; lower bound greater than upper bound) 00123 */ 00124 Histogram(int aLowerBnd, int anUpperBnd, unsigned int aSampRate = 1) 00125 throw(QgarErrorDomain); 00126 00127 /** 00128 * @brief Construct from a grey-level image. 00129 * 00130 * @param anImg a grey-level image 00131 * @param aLowerBnd lower bound (default <b>0</b>) 00132 * @param anUpperBnd upper bound (default <b>255</b>) 00133 * @param aSampRate sampling rate, i.e. cell width (default <b>1</b>) 00134 * 00135 * @exception qgar::QgarErrorDomain 00136 * (sampling rate is 0; lower bound greater than upper bound) 00137 */ 00138 Histogram(const GreyLevelImage& anImg, 00139 int aLowerBnd = 0, 00140 int anUpperBnd = 255, 00141 unsigned int aSampRate = 1) 00142 throw(QgarErrorDomain); 00143 00144 //@} 00145 00146 00147 /** @name Destructor */ 00148 // ========== 00149 //@{ 00150 00151 /** 00152 * @brief Virtual destructor. 00153 */ 00154 virtual ~Histogram(); 00155 00156 //@} 00157 00158 00159 /** @name Access */ 00160 // ====== 00161 //@{ 00162 00163 /** 00164 * @brief Get lower bound. 00165 */ 00166 inline int lowerBnd() const; 00167 00168 /** 00169 * @brief Get upper bound. 00170 */ 00171 inline int upperBnd() const; 00172 00173 /** 00174 * @brief Get cell width. 00175 */ 00176 inline int samplingRate() const; 00177 00178 //@} 00179 00180 00181 /** @name Frequencies */ 00182 // =========== 00183 //@{ 00184 00185 /** 00186 * @brief Add a given value (default <b>1</b>) to the frequency of a sample. 00187 * 00188 * @param aSample a sample 00189 * @param anIncr value to be added to the corresponding frequency 00190 */ 00191 void plus(int aSample, unsigned int anIncr = 1); 00192 00193 /** 00194 * @brief Subtract a given value (default <b>1</b>) 00195 * to the frequency of a sample. 00196 * 00197 * @param aSample a sample 00198 * @param aDecr value to be subtracted to the corresponding frequency 00199 * 00200 * @warning 00201 * The corresponding frequency may become negative: The function 00202 * does not perfom any check about the value of the frequency 00203 * after the subtraction. 00204 */ 00205 void minus(int aSample, unsigned int aDecr = 1); 00206 00207 /** 00208 * @brief Get sample with maximum frequency. 00209 * 00210 * If several samples have the same (maximum) frequency, 00211 * return the first sample starting from the lower bound. 00212 */ 00213 int maxSample(); 00214 00215 /** 00216 * @brief Get sample with maximum frequency 00217 * in [<b>aBnd</b>, <b>upperBnd</b>]. 00218 * 00219 * If several samples have the same (maximum) frequency, 00220 * return the first sample starting from <b>aBnd</b>. 00221 * 00222 * @param aBnd lower bound to start the search 00223 */ 00224 int maxSample(int aBnd); 00225 00226 /** 00227 * @brief Get sample with minimum frequency. 00228 * 00229 * If several samples have the same (minimum) frequency, 00230 * return the first sample starting from the lower bound. 00231 */ 00232 int minSample(); 00233 00234 /** 00235 * @brief Get sample with minimum frequency 00236 * in [<b>aBnd</b>, <b>upperBnd</b>]. 00237 * 00238 * If several samples have the same (minimum) frequency, 00239 * return the first sample starting from <b>aBnd</b>. 00240 * 00241 * @param aBnd lower bound to start the search 00242 */ 00243 int minSample(int aBnd); 00244 00245 //@} 00246 00247 00248 /** @name Operators */ 00249 // ========= 00250 //@{ 00251 00252 /** 00253 * @brief Return the frequency of a sample. 00254 * 00255 * @param aSample a sample 00256 * 00257 * @exception qgar::QgarErrorDomain 00258 * (sample out of bounds) 00259 */ 00260 inline int& operator[](int aSample) throw(QgarErrorDomain); 00261 00262 /** 00263 * @brief Assignment. 00264 * 00265 * @param aHistg a histogram 00266 */ 00267 Histogram& operator=(const Histogram& aHistg); 00268 00269 //@} 00270 00271 00272 /** @name Histogram transformations */ 00273 // ========================= 00274 //@{ 00275 00276 /** 00277 * @brief Transform into an accumulated histogram. 00278 */ 00279 inline void partialSum(); 00280 00281 /** 00282 * @brief Smooth by computing a simple average on a window of given size. 00283 * 00284 * @param aWidth width of smoothing window 00285 * 00286 * @exception qgar::QgarErrorDomain (bad window size) 00287 */ 00288 void smooth(unsigned int aWidth) throw(QgarErrorDomain); 00289 00290 //@} 00291 00292 // ------------------------------------------------------------------- 00293 // P R O T E C T E D M E M B E R S 00294 // ------------------------------------------------------------------- 00295 protected: 00296 00297 /** @name Representation of a histogram */ 00298 // ============================= 00299 //@{ 00300 00301 /** 00302 * @brief Sampling rate. 00303 * 00304 * It is the ``width'' of a cell of the cell vector. 00305 */ 00306 int _samplingRate; 00307 00308 /** 00309 * @brief Lower (non-sampled) bound. 00310 */ 00311 int _lowerBnd; 00312 00313 /** 00314 * @brief Upper (non-sampled) bound. 00315 */ 00316 int _upperBnd; 00317 00318 /** 00319 * @brief Vector of cells. 00320 */ 00321 std::vector<int> _cells; 00322 00323 //@} 00324 00325 00326 // ------------------------------------------------------------------- 00327 // P R I V A T E M E M B E R S 00328 // ------------------------------------------------------------------- 00329 private: 00330 00331 /** @name Access to the cell vector */ 00332 // ========================= 00333 //@{ 00334 00335 /** 00336 * @brief Index (in the cell vector) corresponding to a sample. 00337 * 00338 * @param aSample a sample 00339 * 00340 * @exception qgar::QgarErrorDomain (sample out of bounds) 00341 */ 00342 int sampIdx(int aSample) const throw(QgarErrorDomain); 00343 00344 //@} 00345 00346 // ------------------------------------------------------------------- 00347 }; // class Histogram 00348 00349 00350 00351 00352 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00353 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00354 // D E F I N I T I O N S O F I N L I N E F U N C T I O N 00355 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00356 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00357 00358 00359 // ====== 00360 // ACCESS 00361 // ====== 00362 00363 00364 // GET LOWER BOUND 00365 00366 inline int 00367 Histogram::lowerBnd() const 00368 { 00369 return _lowerBnd; 00370 } 00371 00372 00373 // GET UPPER BOUND 00374 00375 inline int 00376 Histogram::upperBnd() const 00377 { 00378 return _upperBnd; 00379 } 00380 00381 // GET SAMPLING RATE 00382 00383 inline int 00384 Histogram::samplingRate() const 00385 { 00386 return _samplingRate; 00387 } 00388 00389 00390 // ========= 00391 // OPERATORS 00392 // ========= 00393 00394 00395 // RETURN THE FREQUENCY OF A SAMPLE 00396 00397 int& 00398 Histogram::operator[](int aSample) 00399 00400 throw(QgarErrorDomain) 00401 00402 { 00403 return _cells[sampIdx(aSample)]; 00404 } 00405 00406 00407 // =============== 00408 // TRANSFORMATIONS 00409 // =============== 00410 00411 00412 // TRANSFORM INTO AN ACCUMULATED HISTOGRAM 00413 00414 void 00415 Histogram::partialSum() 00416 { 00417 std::partial_sum(_cells.begin(), _cells.end(), _cells.begin()); 00418 } 00419 00420 00421 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00422 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 00423 00424 00425 } // namespace qgar 00426 00427 00428 #endif /* __HISTOGRAM_H_INCLUDED__ */