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

GeodesicRecBinaryImage.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  GeodesicRecBinaryImage.C
00030  * @brief Implementation of class qgar::GeodesicRecBinaryImage.
00031  *
00032  *        See file GeodesicRecBinaryImage.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 6, 2002  17:20
00036  * @since    Qgar 2.0
00037  */
00038 
00039 
00040 
00041 // STD
00042 #include <queue>
00043 #include <sstream>
00044 // QGAR
00045 #include <qgarlib/GenImage.H>
00046 #include <qgarlib/GeodesicRecBinaryImage.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 GeodesicRecBinaryImage::GeodesicRecBinaryImage(BinaryImage& aMarkImg,
00062                                                BinaryImage& aResImg)
00063   throw(QgarErrorDomain)
00064   : BinaryImage(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::GeodesicRecBinaryImage::GeodesicRecBinaryImage(qgar::BinaryImage&, qgar::BinaryImage&)",
00081                             os.str());
00082     }
00083 
00084   perform(this, &aResImg);
00085 }
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 GeodesicRecBinaryImage::perform(BinaryImage* aMarkImg,
00093                                      BinaryImage* aResImg)
00094 {
00095 
00096   int width = aMarkImg->width();    // Just some shortcuts
00097   int height = aMarkImg->height();
00098 
00099   // first enqueue the boundaries of marker image.
00100 
00101   // as we have to compare marker and goal image in the same time,
00102   // we won't enqueue the pointers on marker's pixels, but their
00103   // indice in pixMap (which are the same in goal's pixMap)
00104   queue<long> boundary;
00105   
00106   long indice; // indice in the queue
00107 
00108   int i,j,k,l; // here we have four imbricated loop...
00109 
00110   BinaryImage::value_type* Jp; // pointer on marker image
00111   BinaryImage::value_type* Ip; // pointer on goal image
00112   BinaryImage::value_type* Jq; // pointer on current boundary pixel
00113   BinaryImage::value_type* Iq; // pointer on current goal boundary pixel
00114 
00115   BinaryImage::value_type* markerPixMap = aMarkImg->pPixMap(); // just some shortcuts
00116   BinaryImage::value_type* goalPixMap = aResImg->pPixMap();
00117  
00118   Jp = markerPixMap;
00119   Ip = goalPixMap;
00120 
00121   int minK, minL;
00122   int maxK, maxL;
00123 
00124   for (i = 0; i < height; ++i)
00125     {
00126 
00127       for (j = 0; j < width; ++j, ++Jp, ++Ip)
00128         {
00129       
00130           if (*Jp && *Ip)
00131             {
00132         
00133               // is this pixel in the boundary of marker image?
00134 
00135               /*** definition of current pixel's neighborhood ***/
00136 
00137               // between the first and the last line
00138               if ( (i > 0) && (i < height - 1) )
00139                 {
00140                   minK = -1;
00141                   maxK = 2;
00142 
00143                   // first pixel
00144                   if (!j)
00145                     {
00146                       minL = 0;
00147                       maxL = 2;
00148                     }
00149                   // between these two pixels
00150                   else if (j < width - 1)
00151                     {
00152                       minL = -1;
00153                       maxL = 2;
00154                     }
00155                   else
00156                     {
00157                       minL = -1;
00158                       maxL = 1;
00159                     }
00160                 }
00161               // first pixel
00162               else if (Jp == markerPixMap)
00163                 {
00164                   minK = 0;
00165                   minL = 0;
00166                   maxK = 2;
00167                   maxL = 2;
00168                 }
00169               // before last pixel of first line
00170               else if (Jp < markerPixMap + width - 1)
00171                 {
00172                   minK = 0;
00173                   minL = -1;
00174                   maxK = 2;
00175                   maxL = 2;
00176                 }
00177               // last pixel of first line
00178               else if (Jp ==  markerPixMap + width - 1)
00179                 {
00180                   minK = 0;
00181                   minL = -1;
00182                   maxK = 2;
00183                   maxL = 1;
00184                 }
00185               // first pixel of last line
00186               else if (!j)
00187                 {
00188                   minK = -1;
00189                   minL = 0;
00190                   maxK = 1;
00191                   maxL = 2;
00192                 }
00193               // before last pixel of last line
00194               else if (j < width - 1)
00195                 {
00196                   minK = -1;
00197                   minL = -1;
00198                   maxL = 2;
00199                   maxK = 1;
00200                 }
00201               // last pixel
00202               else
00203                 {
00204                   minL = -1;
00205                   minK = -1;
00206                   maxL = 1;
00207                   maxK = 1;
00208                 }
00209 
00210               for (k = minK; k < maxK; ++k)
00211                 {
00212                   for (l = minL ; l < maxL; ++l)
00213                     {
00214                       Jq = Jp + k*width + l;
00215           
00216                       if ( !*Jq )
00217                         {
00218                           boundary.push(Jp - markerPixMap);
00219                           k = 2;
00220                           break;
00221                         }
00222                     } // end for l
00223                 } // end for k
00224 
00225             } //endif
00226 
00227         }
00228     } // end of scan
00229   
00230 
00231   /*** propagation ***/
00232   
00233   //**** APPARENTLY NOT USED!
00234   //**** BinaryImage::value_type *minIndice = markerPixMap;
00235   //**** BinaryImage::value_type *maxIndice = minIndice + width*height - 1;
00236 
00237   while (!boundary.empty())
00238     {
00239       indice = boundary.front();
00240       boundary.pop();
00241     
00242       Jp = markerPixMap + indice;
00243       Ip = goalPixMap + indice;
00244 
00245       /*** definition of current pixel's neighborhood ***/
00246 
00247       // between the first and the last line
00248       if ( (Jp > markerPixMap + width - 1) && 
00249            (Jp < markerPixMap + (height - 1)*width) )
00250         {
00251           minK = -1;
00252           maxK = 2;
00253           
00254           // first pixel
00255           if ((Jp - markerPixMap) % width == 0)
00256             {
00257               minL = 0;
00258               maxL = 2;
00259             }
00260           // last pixel
00261           else if ((Jp - markerPixMap) % width == width - 1)
00262             {
00263               minL = -1;
00264               maxL = 1;
00265             }
00266           // between these two pixels
00267           else
00268             {
00269               minL = -1;
00270               maxL = 2;
00271             }
00272         }
00273       // first pixel
00274       else if (Jp == markerPixMap)
00275         {
00276           minK = minL = 0;
00277           maxK = maxL = 2;
00278         }
00279       // before last pixel of first line
00280       else if (Jp < markerPixMap + width - 1)
00281         {
00282           minK = 0;
00283           minL = -1;
00284           maxK = 2;
00285           maxL = 2;
00286         }
00287       // last pixel of first line
00288       else if (Jp ==  markerPixMap + width - 1)
00289         {
00290           minK = 0;
00291           minL = -1;
00292           maxK = 2;
00293           maxL = 1;
00294         }
00295       // first pixel of last line
00296       else if (Jp == markerPixMap + (height - 1)*width) 
00297         {
00298           minK = -1;
00299           minL = 0;
00300           maxK = 1;
00301           maxL = 2;
00302         }
00303       // before last pixel of last line
00304       else if (Jp < markerPixMap + height*width - 1)
00305         {
00306           minK = -1;
00307           minL = -1;
00308           maxL = 2;
00309           maxK = 1;
00310         }
00311       // last pixel
00312       else
00313         {
00314           minL = -1;
00315           minK = -1;
00316           maxL = 1;
00317           maxK = 1;
00318         }
00319       
00320       for (k = minK; k < maxK; ++k)
00321         {
00322           
00323           for (l = minL ; l < maxL; ++l)
00324             {
00325               indice = k*width + l;
00326               Jq = Jp + indice;
00327               Iq = Ip + indice;
00328               
00329               if ( (!*Jq) && *Iq )
00330                 {
00331                   *Jq = 1;
00332                   boundary.push(Jq - markerPixMap);
00333                 }
00334             } // END for l
00335         } // END for k
00336       
00337     }
00338   
00339 }
00340 
00341 // ----------------------------------------------------------------------
00342 
00343 } // namespace qgar