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

DericheGradientImage.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   DericheGradientImage.C
00030  * @brief  Implementation of class qgar::DericheGradientImage.
00031  *
00032  *         See file DericheGradientImage.H for the interface.
00033  *
00034  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Karl Tombre">Karl Tombre</a>
00035  * @date   July 3, 2001  11:35
00036  * @since  Qgar 1.0
00037  */
00038 
00039 
00040 // STL
00041 #include <cmath>
00042 // QGAR
00043 #include <qgarlib/DericheGradientImage.H>
00044 #include <qgarlib/GenImage.H>
00045 
00046 
00047 namespace qgar
00048 {
00049 
00050 
00051 // -------------------------------------------------------------------
00052 // C O N S T R U C T O R S
00053 // -------------------------------------------------------------------
00054 
00055 
00056 // CONSTRUCT FROM GIVEN GREY-LEVEL IMAGE
00057 
00058 DericheGradientImage::DericheGradientImage(const GreyLevelImage& img,
00059                                            float alpha,
00060                                            float w,
00061                                            int normalized)
00062 
00063     : AbstractGradientImage(img),
00064       _alpha(alpha),
00065       _w(w)
00066     
00067 {
00068   PRIVATEbuildDericheImage(normalized);
00069 }
00070 
00071 
00072 // CONSTRUCT FROM A FLOAT IMAGE
00073 
00074 DericheGradientImage::DericheGradientImage(const FloatImage& img,
00075                                            float alpha,
00076                                            float w,
00077                                            int normalized)
00078 
00079     : AbstractGradientImage(img),
00080       _alpha(alpha),
00081       _w(w)
00082 
00083   {
00084     PRIVATEbuildDericheImage(normalized);
00085   }
00086 
00087 
00088 // -------------------------------------------------------------------
00089 // A U X I L I A R I E S
00090 // -------------------------------------------------------------------
00091 
00092 
00093 void
00094 DericheGradientImage::PRIVATEbuildDericheImage(int normalized)
00095 {
00096   float c0 = _alpha * _alpha + _w * _w;
00097 
00098   // normalization coefficient for smoothing
00099   float k = (1 - 2 * (float) (exp((double) (- _alpha)) * cos((double) _w))
00100              + (float) exp((double) (-2 * _alpha))) * c0 /
00101     (2 * _alpha * (float) (exp((double) (- _alpha)) * sin((double) _w))
00102      + _w * (1 - (float) exp((double) (-2 * _alpha))));
00103 
00104   // normalization coefficient for derivation
00105   a0 = k * _w / c0;
00106   float c;
00107   if (normalized)
00108     c = k * c0;
00109   else
00110     c = (1 - 2 * (float) (exp((double)(-_alpha)) * cos((double) _w))
00111          + (float) exp((double) (-2 * _alpha))) /
00112       ((float) (exp((double) (-_alpha)) * sin((double) _w)));
00113 
00114   float c1 = k * _alpha / c0;
00115 
00116   // Derivation coefficients
00117   b1 = (-2.f) * (float) (exp((double) (-_alpha)) * cos((double) _w));
00118   b2 = (float) exp((double) (-2. * _alpha));
00119 
00120   // Smoothing coefficients
00121   a1 = (- a0 * (float) cos((double) _w) + c1 * (float) sin((double) _w)) * 
00122     (float) exp((double) (-_alpha));
00123   a2 = a1 - a0 * b1;
00124   a3 = (- a0) * b2;
00125 
00126   a = (- c) * (float) (exp((double) (- _alpha)) * sin((double) _w));
00127 
00128   // Filter in x
00129   dfilterX();
00130   // Filter in y
00131   dfilterY();
00132 
00133   // maybe set some lines and columns to 0 ???
00134 }
00135 
00136 
00137 
00138 // X FILTER
00139 // ========
00140 
00141 
00142 void
00143 DericheGradientImage::dfilterX()
00144 {
00145   float* mem = new float [_width];
00146   float* buff1 = new float [_width];
00147   float* buff2 = new float [_width];
00148   float* qstart = _dxImg.pPixMap();
00149   int i;
00150   int j;
00151 
00152   // Derive along x axis
00153   for (i = 0 ; i < _height ; ++i, qstart += _width)
00154     {
00155       // From left to right
00156       float* p = buff1;
00157       // Remember that _dxImg and _dyImg are initialized
00158       // with original values
00159       float* q = qstart;
00160       float* pmem = mem;
00161 
00162       // First two pixels
00163       *p = (*q);
00164       *pmem++ = a * (*q);
00165       ++p;
00166       ++q;
00167       *p = (*q);
00168       *pmem++ = a * (*q);
00169       ++p;
00170       ++q;
00171 
00172       // And loop on rest with recurrence formula
00173       for (j = 2 ; j < _width ; ++j, ++p, ++q, ++pmem)
00174         {
00175           *pmem = a * (*q);
00176           *p = (*(pmem - 1)) - b1 * (*(p-1)) - b2 * (*(p-2));
00177         }
00178 
00179       // From right to left
00180       p = buff2 + _width - 1;
00181       q = qstart + _width - 1;
00182       
00183       // Two last
00184       *p-- = (*q--);
00185       *p-- = (*q--);
00186       
00187       // And loop on rest with recurrence formula
00188       pmem = mem + _width - 3;
00189       for (j = _width - 3 ; j >= 0 ;  --j, --p, --pmem)
00190         {
00191           *p = (- *(pmem + 1)) - b1 * (*(p+1)) - b2 * (*(p+2));
00192         }
00193       
00194       // Sum the two results
00195       float* r = qstart;
00196       p = buff1;
00197       q = buff2;
00198       for (j = 0 ; j < _width ; ++j)
00199         {
00200           *r++ = (*p++) + *q++;
00201         }
00202     }
00203 
00204   delete [] mem;
00205   delete [] buff1;
00206   delete [] buff2;
00207 
00208   buff1 = new float [_height];
00209   buff2 = new float [_height];
00210 
00211   // Smooth along y axis
00212   qstart = _dxImg.pPixMap();
00213   for (j = 0 ; j < _width ; j++, qstart++)
00214     {
00215       // From top to bottom
00216       float* p = buff1;
00217       float* q = qstart;
00218 
00219       // First two
00220       *p = (*q);
00221       p++;
00222       q += _width;
00223       *p = (*q);
00224       p++;
00225       q += _width;
00226 
00227       // Loop with recurrence formula
00228       for (i = 2 ; i < _height ; i++, p++, q += _width)
00229         *p = a0 * (*q) + a1 * *(q - _width) - b1 * (*(p-1)) - b2 * (*(p-2));
00230 
00231       // From bottom to top
00232       p = buff2 + _height - 1;
00233       q = qstart + (_height - 1) * _width;
00234 
00235       // Two last
00236       *p = (*q);
00237       p--; q -= _width;
00238       *p = (*q);
00239       p--; q -= _width;
00240       
00241       // Loop on rest with recurrence formula
00242       for (i = _height - 3 ; i >= 0 ; i--, p--, q -= _width)
00243         *p = a2 * (*(q + _width)) + a3 * (*(q + (_width + _width)))
00244           - b1 * (*(p+1)) - b2 * (*(p+2));
00245 
00246       // Sum up the two results
00247       float* r = qstart;
00248       p = buff1;
00249       q = buff2;
00250       for (i = 0 ; i < _height ; i++, r += _width)
00251         *r = (*p++) + *q++;
00252     }
00253 
00254   delete [] buff1;
00255   delete [] buff2;
00256 }
00257 
00258 
00259 // Y FILTER
00260 // ========
00261 
00262 
00263 void
00264 DericheGradientImage::dfilterY()
00265 {
00266   float* mem = new float [_height];
00267   float* buff1 = new float [_height];
00268   float* buff2 = new float [_height];
00269   int i;
00270   int j;
00271 
00272   // Derive along y axis
00273   float* qstart = _dyImg.pPixMap();
00274 
00275   for (j = 0 ; j < _width ; ++j, ++qstart)
00276     {
00277       // From top to bottom
00278       float* p = buff1;
00279       // Remember that _dxImg and _dyImg are initialized
00280       // with original values
00281       float* q = qstart;
00282 
00283       float* pmem = mem;
00284 
00285       // First two
00286       *p = (*q);
00287       *pmem++ = a * (*q);
00288       ++p;
00289       q += _width;
00290       *p = (*q);
00291       *pmem++ = a * (*q);
00292       ++p;
00293       q += _width;
00294 
00295       // Loop with recurrence formula
00296       for (i = 2 ; i < _height ; ++i, ++p, q += _width, ++pmem)
00297         {
00298           *pmem = a * (*q);
00299           *p = (*(pmem - 1)) - b1 * (*(p-1)) - b2 * (*(p-2));
00300         }
00301 
00302       // From bottom to top
00303       p = buff2 + _height - 1;
00304       q = qstart + (_height - 1) * _width;
00305 
00306       // Two last
00307       *p = (*q);
00308       --p;
00309       q -= _width;
00310       *p = (*q);
00311       --p;
00312       q -= _width;
00313       
00314       // Loop on rest with recurrence formula
00315       pmem = mem + _height - 3;
00316       for (i = _height - 3 ; i >= 0 ;--i, --p, --pmem)
00317         {
00318           *p = (- *(pmem + 1)) - b1 * (*(p+1)) - b2 * (*(p+2));
00319         }
00320 
00321       // Sum up the two results
00322       float* r = qstart;
00323       p = buff1;
00324       q = buff2;
00325       for (i = 0 ; i < _height ; ++i, r += _width)
00326         {
00327           *r = (*p++) + *q++;
00328         }
00329     } // END for j
00330 
00331   delete [] mem;
00332   delete [] buff1;
00333   delete [] buff2;
00334 
00335   buff1 = new float [_width];
00336   buff2 = new float [_width];
00337 
00338   qstart = _dyImg.pPixMap();
00339   // Smooth along x axis
00340   for (i = 0 ; i < _height ; ++i, qstart += _width)
00341     {
00342       // From left to right
00343       float* p = buff1;
00344       float* q = qstart;
00345 
00346       // First two pixels
00347       *p++ = (*q++);
00348       *p++ = (*q++);
00349 
00350       // And loop on rest with recurrence formula
00351       for (j = 2 ; j < _width ; ++j, ++p, ++q)
00352         {
00353           *p = a0 * (*q) + a1 * (*(q - 1)) - b1 * (*(p-1)) - b2 * (*(p-2));
00354         }
00355 
00356       // From right to left
00357       p = buff2 + _width - 1;
00358       q = qstart + _width - 1;
00359       
00360       // Two last
00361       *p-- = (*q--);
00362       *p-- = (*q--);
00363       
00364       // And loop on rest with recurrence formula
00365       for (j = _width - 3 ; j >= 0 ;  --j, --p, --q)
00366         {
00367           *p = a2 * (*(q + 1)) + a3 * (*(q + 2)) - b1 * (*(p+1)) - b2 * (*(p+2));
00368         }
00369 
00370       // Sum the two results
00371       float* r = qstart;
00372       p = buff1;
00373       q = buff2;
00374       for (j = 0 ; j < _width ; ++j)
00375         {
00376           *r++ = (*p++) + *q++;
00377         }}
00378 
00379 
00380   delete [] buff1;
00381   delete [] buff2;
00382 }
00383 
00384 // -------------------------------------------------------------------
00385 
00386 } // namespace qgar