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

GeodesicRecEroImage.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  GeodesicRecEroImage.C
00030  * @brief Implementation of class qgar::GeodesicRecEroImage.
00031  *
00032  *        See file GeodesicRecEroImage.H for the interface.
00033  *
00034  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Mathieu Baeumler">Mathieu Baeumler</a>
00035  * @date  August 13, 2002  15:27
00036  * @since Qgar 2.0
00037  */
00038 
00039 
00040 
00041 // STD
00042 #include <queue>
00043 #include <sstream>
00044 // QGAR
00045 #include <qgarlib/DilatedImage.H>
00046 #include <qgarlib/GeodesicRecEroImage.H>
00047 #include <qgarlib/QgarErrorDomain.H>
00048 
00049 
00050 
00051 using namespace std;
00052 
00053 
00054 namespace qgar
00055 {
00056 
00057 // ---------------------------------------------------------------------
00058 // C O N S T R U C T O R S
00059 // ---------------------------------------------------------------------
00060 
00061 GeodesicRecEroImage::GeodesicRecEroImage(GreyLevelImage& aMarkImg,
00062                                          GreyLevelImage& aResImg)
00063   throw(QgarErrorDomain)
00064  : GreyLevelImage(aMarkImg)
00065 {
00066   if (   (aMarkImg.width()  != aResImg.width())
00067       || (aMarkImg.height() != aResImg.height()))
00068     {
00069       std::ostringstream os;
00070       os << "Marker image size ["
00071          << aMarkImg.width()
00072          << " X "
00073          << aMarkImg.height()
00074          << "] does not match result image size ["
00075          << aResImg.width()
00076          << " X "
00077          << aResImg.height()
00078          << "]";
00079       throw QgarErrorDomain(__FILE__, __LINE__,
00080                             "qgar::GeodesicRecEroImage::GeodesicRecEroImage(qgar::GreyLevelImage&, qgar::GreyLevelImage&)",
00081 
00082                             os.str());
00083     }
00084 
00085   perform(this, &aResImg);
00086 }
00087 
00088 // -------------------------------------------------------------------
00089 // G E O D E S I C   R E C O N S T R U C T I O N
00090 // -------------------------------------------------------------------
00091 
00092 void GeodesicRecEroImage::perform(GreyLevelImage* aMarkImg,
00093                                   GreyLevelImage* aResImg)
00094 {
00095   int width  = aMarkImg->width(); // just some shortcuts
00096   int height = aMarkImg->height();
00097 
00098   // first enqueue the boundaries of marker image.
00099 
00100   // as we have to compare marker and goal image in the same time,
00101   // we won't enqueue the pointers on marker's pixels, but their
00102   // indice in pixMap (which are the same in goal's pixMap)
00103   queue< long > boundary;
00104   
00105   long indice; // indice in the queue
00106   GreyLevelImage::value_type minimum; // local minimum
00107   GreyLevelImage::value_type* Jp;     // pointer on marker image
00108   GreyLevelImage::value_type* Ip;     // pointer on goal image
00109   GreyLevelImage::value_type* Jq;     // pointer on current marker boundary pixel
00110   GreyLevelImage::value_type* Iq;     // pointer on current goal boundary pixel
00111 
00112   GreyLevelImage::value_type* markerPixMap = aMarkImg->pPixMap(); // just some shortcuts
00113   GreyLevelImage::value_type* goalPixMap   = aResImg->pPixMap();
00114 
00115   int minK, minL; // limits of current pixel's neighborhood
00116   int maxK, maxL;
00117   
00118   /*** scan in raster order: ***/
00119 
00120   Jp = markerPixMap;
00121   Ip = goalPixMap;
00122 
00123   for (int i = 0; i < height; ++i)
00124     {
00125       for (int j = 0; j < width; ++j, ++Jp, ++Ip)
00126         {
00127           // point-wise maximum between min(p U Ng+(p)) and Ip
00128           minimum = *Jp;
00129           
00130           // after the first line
00131           if (i)
00132             {
00133               // first pixel
00134               if (!j)
00135                 {
00136                   Jq = Jp - width;
00137                   if (minimum > *Jq)
00138                     {
00139                       minimum = *Jq;
00140                     }
00141                   ++Jq;
00142                   if (minimum > *Jq)
00143                     {
00144                       minimum = *Jq;
00145                     }
00146                 }
00147               // last pixel
00148               else if (j == width - 1)
00149                 {
00150                   Jq = Jp - 1;
00151                   if (minimum > *Jq)
00152                     {
00153                       minimum = *Jq;
00154                     }
00155                   Jq -= width;
00156                   if (minimum > *Jq)
00157                     {
00158                       minimum = *Jq;
00159                     }
00160                   ++Jq;
00161                   if (minimum > *Jq)
00162                     {
00163                       minimum = *Jq;   
00164                     }
00165                 }
00166               // between these two pixels
00167               else
00168                 {
00169                   for (int k = -1; k < 1; ++k)
00170                     {
00171                       for (int l = -1 ; l < 1 - k; ++l)
00172                         {
00173                           Jq = Jp + k*width + l;
00174                           if (minimum > *Jq)
00175                             {
00176                               minimum = *Jq;
00177                             }
00178                         } // END for l
00179                     } // END for k
00180                 }
00181             } // END first pixel
00182           else if (j > 0)
00183             {
00184               Jq = Jp - 1;
00185               if (minimum > *Jq)
00186                 {
00187                   minimum = *Jq;
00188                 }
00189             }
00190       
00191           *Jp = (minimum > *Ip ? minimum : *Ip);
00192         } // END for j
00193     } // END for i
00194 
00195   /*** scan in anti-raster order: ***/
00196 
00197   --Jp;
00198   --Ip;
00199   for (int i = 0; i < height; ++i)
00200     {
00201       for (int j = 0; j < width; ++j, --Jp, --Ip)
00202         {
00203           // point-wise minimum between min(p U Ng-(p)) and Ip
00204           minimum = *Jp;
00205 
00206           // after the first line
00207           if (i != 0)
00208             {
00209               // first pixel
00210               if (j == 0)
00211                 {
00212                   Jq = Jp + width;
00213                   if (minimum > *Jq)
00214                     {
00215                       minimum = *Jq;
00216                     }
00217                   --Jq;
00218                   if (minimum > *Jq)
00219                     {
00220                       minimum = *Jq;
00221                     }
00222                   
00223                   *Jp = (minimum > *Ip ? minimum : *Ip);
00224                   Jq = Jp + width;
00225                   Iq = Ip + width;
00226 
00227                   if ((*Jq > *Jp) && (*Jq > *Iq))
00228                     {
00229                       boundary.push(Jp - markerPixMap);
00230                     }
00231                   else
00232                     {
00233                       --Iq;
00234                       --Iq;
00235                       if ((*Jq > *Jp) && (*Jq > *Iq))
00236                         {
00237                           boundary.push(Jp - markerPixMap);
00238                         }
00239                     }
00240                 } // END first pixel
00241 
00242               // last pixel
00243               else if (j == width - 1)
00244                 {
00245                   Jq = Jp + 1;
00246                   if (minimum > *Jq)
00247                     {
00248                       minimum = *Jq;
00249                     }
00250 
00251                   Jq += width;
00252                   if (minimum > *Jq)
00253                     {
00254                       minimum = *Jq;
00255                     }
00256 
00257                   --Jq;
00258                   if (minimum > *Jq)
00259                     {
00260                       minimum = *Jq; 
00261                     }
00262 
00263                   *Jp = (minimum > *Ip ? minimum : *Ip);
00264                   Jq = Jp + 1;
00265                   Iq = Ip + 1;
00266                   if ((*Jq > *Jp) && (*Jq > *Iq))
00267                     {
00268                       boundary.push(Jp - markerPixMap);
00269                     }
00270                   else
00271                     {
00272                       Iq += width;
00273                       Iq += width;
00274                       if ((*Jq > *Jp) && (*Jq > *Iq))
00275                         {
00276                           boundary.push(Jp - markerPixMap);
00277                         }
00278                       else
00279                         {
00280                           --Iq;
00281                           --Iq;
00282                           if ((*Jq > *Jp) && (*Jq > *Iq))
00283                             {
00284                               boundary.push(Jp - markerPixMap);
00285                             }
00286                         }
00287                     }
00288                 } // END last pixel
00289 
00290               // between these two pixels
00291               else
00292                 {
00293                   for (int k = 1; k > -1; --k)
00294                     {
00295                       for (int l = 1 ; l > -(1 + k); --l)
00296                         {
00297                           Jq = Jp + k*width + l;
00298                           if (minimum > *Jq)
00299                             {
00300                               minimum = *Jq;
00301                             }
00302                         } // END for l
00303                     } // END for k
00304 
00305                   *Jp = (minimum > *Ip ? minimum : *Ip);
00306 
00307                   for (int k = 1; k > -1; --k)
00308                     {
00309                       for (int l = 1 ; l > -(1 + k); --l)
00310                         {
00311                           indice = k*width + l;
00312                           Jq = Jp + indice;
00313                           Iq = Ip + indice;
00314                           if ((*Jq > *Jp) && (*Jq > *Iq))
00315                             {
00316                               boundary.push(Jp - markerPixMap);
00317                               // ---------------------------------------
00318                               // HORROR! HORROR! HORROR! HORROR! HORROR!
00319                               // ---------------------------------------
00320                               k = -1;
00321                               break;
00322                               // ---------------------------------------
00323                             }
00324 
00325                         } // END for l
00326                     } // END for k
00327                 }
00328             } // END if (i)
00329 
00330           else if (j > 0)
00331             {
00332               Jq = Jp + 1;
00333               if (minimum > *Jq)
00334                 {
00335                   minimum = *Jq;
00336                 }
00337 
00338               *Jp = (minimum > *Ip ? minimum : *Ip);
00339               Iq = Ip + 1;
00340               if ((*Jq > *Jp) && (*Jq > *Iq))
00341                 {
00342                   boundary.push(Jp - markerPixMap);
00343                 }
00344             }
00345           else
00346             {
00347               *Jp = (minimum > *Ip ? minimum : *Ip);
00348             }
00349 
00350         } // END for j
00351     } // END for i (end of scan)
00352   
00353   /*** propagation ***/
00354   
00355   //**** APPARENTLY NOT USED!
00356   //**** GreyLevelImage::value_type *minIndice = markerPixMap;
00357   //**** GreyLevelImage::value_type *maxIndice = minIndice + width*height - 1;
00358 
00359   while (!boundary.empty())
00360     {
00361       indice = boundary.front();
00362       boundary.pop();
00363     
00364       Jp = markerPixMap + indice;
00365       Ip = goalPixMap + indice;
00366 
00367       /*** definition of current pixel's neighborhood ***/
00368 
00369       // between the first and the last line
00370       if ( (Jp > markerPixMap + width - 1) && 
00371            (Jp < markerPixMap + (height - 1)*width) )
00372         {
00373           minK = -1;
00374           maxK = 2;
00375 
00376           // first pixel
00377           if ((Jp - markerPixMap) % width == 0)
00378             {
00379               minL = 0;
00380               maxL = 2;
00381             }
00382           // last pixel
00383           else if ((Jp - markerPixMap) % width == width - 1)
00384             {
00385               minL = -1;
00386               maxL = 1;
00387             }
00388           // between these two pixels
00389           else
00390             {
00391               minL = -1;
00392               maxL = 2;
00393             }
00394         }
00395       // first pixel
00396       else if (Jp == markerPixMap)
00397         {
00398           minK = minL = 0;
00399           maxK = maxL = 2;
00400         }
00401       // before last pixel of first line
00402       else if (Jp < markerPixMap + width - 1)
00403         {
00404           minK = 0;
00405           minL = -1;
00406           maxK = maxL = 2;
00407         }
00408     // last pixel of first line
00409       else if (Jp ==  markerPixMap + width - 1)
00410         {
00411           minK = 0;
00412           minL = -1;
00413           maxK = 2;
00414           maxL = 1;
00415         }
00416       // first pixel of last line
00417       else if (Jp == markerPixMap + (height - 1)*width)
00418         {
00419           minK = -1;
00420           minL = 0;
00421           maxK = 1;
00422           maxL = 2;
00423         }
00424       // before last pixel of last line
00425       else if (Jp < markerPixMap + height*width - 1)
00426         {
00427           minK = minL = -1;
00428           maxL = 2;
00429           maxK = 1;
00430         }
00431       // last pixel
00432       else
00433         {
00434           minL = minK = -1;
00435           maxL = maxK = 1;
00436         }
00437         
00438     for (int k = minK; k < maxK; ++k)
00439       {
00440         for (int l = minL ; l < maxL; ++l)
00441           {
00442             indice = k*width + l;
00443             Jq = Jp + indice;
00444             Iq = Ip + indice;
00445             
00446             if ( (*Jq > *Jp) && (*Iq != *Jq) )
00447               {
00448                 *Jq = (*Jp > *Iq ? *Jp : *Iq);
00449                 boundary.push(Jq - markerPixMap);
00450               }
00451          
00452           } // END for l
00453       } // END for k
00454 
00455   } // END while (end of propagation)
00456 }
00457 
00458 // ----------------------------------------------------------------------
00459 
00460 } // namespace qgar