Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Histogram.C

Go to the documentation of this file.
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 /**
00029  * @file   Histogram.C
00030  * @brief  Implementation of class qgar::Histogram.
00031  *
00032  *         See file GreyLevelHistogram.H for the interface.
00033  *
00034  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a>
00035  * @date    December 5, 2003  14:58
00036  * @since   Qgar 2.1.1
00037  */
00038 
00039 
00040 
00041 // STD
00042 #include <sstream>
00043 #include <string>
00044 // QGAR
00045 #include <qgarlib/GenImage.H>
00046 #include <qgarlib/Histogram.H>
00047 #include <qgarlib/QgarErrorDomain.H>
00048 
00049 
00050 
00051 namespace qgar
00052 {
00053 
00054 // -------------------------------------------------------------------
00055 // -------------------------------------------------------------------
00056 // C O N S T R U C T O R S 
00057 // -------------------------------------------------------------------
00058 // -------------------------------------------------------------------
00059 
00060 
00061 // DEFAULT CONSTRUCTOR
00062 
00063 Histogram::Histogram()
00064 
00065  : _samplingRate(1),
00066    _lowerBnd(0),
00067    _upperBnd(0)
00068 
00069 {
00070   // VOID
00071 }
00072 
00073 
00074 // COPY CONSTRUCTOR
00075 
00076 Histogram::Histogram(const Histogram& aHistg)
00077 
00078   : _samplingRate(aHistg._samplingRate),
00079     _lowerBnd(aHistg._lowerBnd),
00080     _upperBnd(aHistg._upperBnd),
00081     _cells(aHistg._cells)
00082 
00083 {
00084   // VOID
00085 }
00086 
00087 
00088 // CONSTRUCT FROM BOUNDS AND SAMPLING RATE
00089 
00090 Histogram::Histogram(int aLowerBnd,
00091                      int anUpperBnd,
00092                      unsigned int aSampRate)
00093 
00094   throw(QgarErrorDomain)
00095 
00096   : _samplingRate(aSampRate),
00097     _lowerBnd(aLowerBnd),
00098     _upperBnd(anUpperBnd)
00099 
00100 {
00101   if (aSampRate == 0)
00102     {
00103       throw QgarErrorDomain(__FILE__, __LINE__,
00104                             "qgar::Histogram::Histogram(int, int, unsigned int)",
00105                             "Sampling rate is 0");
00106     }
00107 
00108   if (aLowerBnd > anUpperBnd)
00109     {
00110       std::ostringstream os;
00111       os << "Lower bound "
00112          << aLowerBnd
00113          << " is greater than upper bound "
00114          << anUpperBnd;
00115       throw QgarErrorDomain(__FILE__, __LINE__,
00116                             "qgar::Histogram::Histogram(int, int, unsigned int)",
00117                             os.str());
00118     }
00119 
00120   int size =   (anUpperBnd - aLowerBnd + 1) / aSampRate
00121              + ((((anUpperBnd - aLowerBnd + 1) % aSampRate) == 0) ? 0 : 1);
00122   
00123   for (int iCnt = 0; iCnt < size; ++iCnt)
00124     {
00125       _cells.push_back(0);
00126     }
00127 }
00128 
00129 
00130 // CONSTRUCT FROM A GREY-LEVEL IMAGE
00131 
00132 Histogram::Histogram(const GreyLevelImage& anImg,
00133                      int aLowerBnd,
00134                      int anUpperBnd,
00135                      unsigned int aSampRate)
00136 
00137   throw(QgarErrorDomain)
00138 
00139   : _samplingRate(aSampRate),
00140     _lowerBnd(aLowerBnd),
00141     _upperBnd(anUpperBnd)
00142 
00143 {
00144   if (aSampRate == 0)
00145     {
00146       throw QgarErrorDomain(__FILE__, __LINE__,
00147                             "void qgar::Histogram::Histogram(const qgar::GreyLevelImage&, int, int, unsigned int)",
00148                             "Sampling rate is 0");
00149     }
00150 
00151   if (aLowerBnd > anUpperBnd)
00152     {
00153       std::ostringstream os;
00154       os << "Lower bound "
00155          << aLowerBnd
00156          << " is greater than upper bound "
00157          << anUpperBnd;
00158       throw QgarErrorDomain(__FILE__, __LINE__,
00159                             "void qgar::Histogram::Histogram(const qgar::GreyLevelImage&, int, int, unsigned int)",
00160                             os.str());
00161     }
00162 
00163   // Initialize the cell vector
00164   int size =   (anUpperBnd - aLowerBnd + 1) / aSampRate
00165              + ((((anUpperBnd - aLowerBnd + 1) % aSampRate) == 0) ? 0 : 1);
00166 
00167   _cells.reserve((unsigned int) size);
00168 
00169   for (int iCnt = 0; iCnt < size; ++iCnt)
00170     {
00171       _cells.push_back(0);
00172     }
00173 
00174   // Compute frequencies
00175   GreyLevelImage::value_type* pimg = anImg.pPixMap();
00176   size = anImg.width() * anImg.height();
00177 
00178   for (int iCnt = 0 ; iCnt < size ; ++iCnt, ++pimg)
00179     {
00180       (*this)[*pimg] += 1;
00181     }
00182 }
00183 
00184 
00185 // -------------------------------------------------------------------
00186 // -------------------------------------------------------------------
00187 // D E S T R U C T O R
00188 // -------------------------------------------------------------------
00189 // -------------------------------------------------------------------
00190 
00191 
00192 Histogram::~Histogram()
00193 {
00194   // VOID
00195 }
00196 
00197 
00198 // -------------------------------------------------------------------
00199 // -------------------------------------------------------------------
00200 // A C C E S S
00201 // -------------------------------------------------------------------
00202 // -------------------------------------------------------------------
00203 
00204 
00205 // GET SAMPLE WITH MAXIMUM FREQUENCY
00206 
00207 int
00208 Histogram::maxSample()
00209 { 
00210   std::vector<int>::iterator
00211     itVec = std::max_element(_cells.begin(), _cells.end());
00212 
00213   return ((itVec - _cells.begin()) * _samplingRate) + _lowerBnd;
00214 }
00215 
00216 
00217 int
00218 Histogram::maxSample(int aBnd)
00219 { 
00220   std::vector<int>::iterator
00221     itVec = std::max_element(_cells.begin() + ((aBnd - _lowerBnd) / _samplingRate),
00222                              _cells.end());
00223 
00224   return ((itVec - _cells.begin()) * _samplingRate) + _lowerBnd;
00225 }
00226 
00227 
00228 // GET SAMPLE WITH MINIMUM FREQUENCY
00229 
00230 int
00231 Histogram::minSample()
00232 { 
00233   std::vector<int>::iterator
00234     itVec = std::min_element(_cells.begin(), _cells.end());
00235 
00236   return ((itVec - _cells.begin()) * _samplingRate) + _lowerBnd;
00237 }
00238 
00239 
00240 int
00241 Histogram::minSample(int aBnd)
00242 { 
00243   std::vector<int>::iterator
00244     itVec = std::min_element(_cells.begin() + ((aBnd - _lowerBnd) / _samplingRate),
00245                              _cells.end());
00246 
00247   return ((itVec - _cells.begin()) * _samplingRate) + _lowerBnd;
00248 }
00249 
00250 
00251 // -------------------------------------------------------------------
00252 // -------------------------------------------------------------------
00253 // O P E R A T O R S
00254 // -------------------------------------------------------------------
00255 // -------------------------------------------------------------------
00256 
00257 
00258 // ASSIGNMENT.
00259 
00260 Histogram&
00261 Histogram::operator=(const Histogram& aHistg)
00262 {
00263   // Are left hand side and right hand side different objects?
00264   if (this != &aHistg)
00265     {
00266       _cells        = aHistg._cells;
00267       _samplingRate = aHistg._samplingRate;
00268       _lowerBnd     = aHistg._lowerBnd;
00269       _upperBnd     = aHistg._upperBnd;
00270     }
00271   return *this;
00272 }
00273 
00274 
00275 // -------------------------------------------------------------------
00276 // -------------------------------------------------------------------
00277 // S M O O T H I N G
00278 // -------------------------------------------------------------------
00279 // -------------------------------------------------------------------
00280 
00281 
00282 // SMOOTH WITH A MOVING AVERAGE OF GIVEN WINDOW SIZE
00283 
00284 void
00285 Histogram::smooth(unsigned int aWidth)
00286 
00287   throw(QgarErrorDomain)
00288 
00289 {
00290   int csize = _cells.size();
00291   int wsize = aWidth;
00292 
00293   if ((wsize == 0) || (wsize >= csize))
00294     {
00295       std::ostringstream os;
00296       os << "Bad window size ("
00297          << aWidth
00298          << ") for histogram ["
00299          << _lowerBnd
00300          << ','
00301          << _upperBnd
00302          << "], using sampling rate "
00303          << _samplingRate;
00304       throw QgarErrorDomain(__FILE__, __LINE__,
00305                             "void qgar::Histogram::smooth(unsigned int)",
00306                             os.str());
00307     }
00308 
00309   std::vector<int> cellsCopy = _cells;
00310   int sum = 0;
00311 
00312   int idx = 0;
00313   for ( ; idx < (wsize / 2) ; ++idx)
00314     {
00315       sum += cellsCopy[idx];
00316       _cells[idx] = sum / (idx + 1);
00317     }
00318 
00319   int jdx = idx;
00320   for ( ; jdx < wsize ; ++jdx)
00321     {
00322       sum += cellsCopy[jdx];
00323     }
00324 
00325   int kdx = 0;
00326   for ( ; jdx < csize ; ++jdx, ++idx, ++kdx)
00327     {
00328       _cells[idx] = sum / wsize;
00329       sum += cellsCopy[jdx] - cellsCopy[kdx];
00330     }
00331 
00332   for (int denom = wsize ; idx < csize ; ++idx, ++kdx, --denom)
00333     {
00334       _cells[idx] = sum / denom;
00335       sum -= cellsCopy[kdx];
00336     }
00337 }
00338 
00339 
00340 // -------------------------------------------------------------------
00341 // -------------------------------------------------------------------
00342 // F R E Q U E N C I E S
00343 // -------------------------------------------------------------------
00344 // -------------------------------------------------------------------
00345 
00346 
00347 // ADD TO THE FREQUENCY OF A SAMPLE
00348 
00349 void
00350 Histogram::plus(int aSample, unsigned int anIncr)
00351 {
00352   _cells[sampIdx(aSample)] += anIncr;
00353 }
00354 
00355 
00356 // SUBTRACT TO THE FREQUENCY OF A SAMPLE
00357 
00358 void
00359 Histogram::minus(int aSample, unsigned int aDecr)
00360 {
00361   _cells[sampIdx(aSample)] -= aDecr;
00362 }
00363 
00364 
00365 // -------------------------------------------------------------------
00366 // -------------------------------------------------------------------
00367 // A C C E S S   T O   T H E   C E L L   V E C T O R   (P R I V A T E)
00368 // -------------------------------------------------------------------
00369 // -------------------------------------------------------------------
00370 
00371 
00372 // INDEX (IN THE CELL VECTOR) CORRESPONDING TO A SAMPLE
00373 
00374 int
00375 Histogram::sampIdx(int aSample) const
00376 
00377   throw(QgarErrorDomain)
00378 
00379 {
00380   if ((aSample < _lowerBnd) || (aSample > _upperBnd))
00381     {
00382       std::ostringstream os;
00383       os << "Sample "
00384          << aSample
00385          << " is out of bounds ["
00386          << _lowerBnd
00387          << ','
00388          << _upperBnd
00389          << ']';
00390       throw QgarErrorDomain(__FILE__, __LINE__,
00391                             "int qgar::Histogram::sampIdx(int)",
00392                             os.str());
00393     }
00394 
00395   return (aSample - _lowerBnd) / _samplingRate;
00396 }
00397 
00398 // -------------------------------------------------------------------
00399 // -------------------------------------------------------------------
00400 
00401 } // namespace qgar
00402