[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/contourcirculator.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*                                                                      */
00005 /*    This file is part of the VIGRA computer vision library.           */
00006 /*    The VIGRA Website is                                              */
00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
00008 /*    Please direct questions, bug reports, and contributions to        */
00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00010 /*        vigra@informatik.uni-hamburg.de                               */
00011 /*                                                                      */
00012 /*    Permission is hereby granted, free of charge, to any person       */
00013 /*    obtaining a copy of this software and associated documentation    */
00014 /*    files (the "Software"), to deal in the Software without           */
00015 /*    restriction, including without limitation the rights to use,      */
00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00017 /*    sell copies of the Software, and to permit persons to whom the    */
00018 /*    Software is furnished to do so, subject to the following          */
00019 /*    conditions:                                                       */
00020 /*                                                                      */
00021 /*    The above copyright notice and this permission notice shall be    */
00022 /*    included in all copies or substantial portions of the             */
00023 /*    Software.                                                         */
00024 /*                                                                      */
00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00033 /*                                                                      */
00034 /************************************************************************/
00035 
00036 
00037 #ifndef VIGRA_CONTOURCIRCULATOR_HXX
00038 #define VIGRA_CONTOURCIRCULATOR_HXX
00039 
00040 #include "pixelneighborhood.hxx"
00041 
00042 namespace vigra
00043 {
00044 
00045 /** \addtogroup ImageIteratorAdapters
00046  */
00047 //@{
00048 
00049 /********************************************************/
00050 /*                                                      */
00051 /*                CrackContourCirculator                */
00052 /*                                                      */
00053 /********************************************************/
00054 
00055 /** \brief Circulator that walks around a given region.
00056 
00057     The circulator follows the <em>crack contour</em> of a given region.
00058     Here, a region is an 8-connected component of pixels with the same
00059     value, such as the regions in a label image.
00060     The crack contour is located between the inside and outside
00061     pixels, that is "on the crack" between the region and the background.
00062     Thus, the circulator moves from pixel corner to pixel corner. By definition,
00063     the first corner (where the circulator was initialized) gets the
00064     coordinate (0,0), and calls to <tt>*circulator</tt> return the distance
00065     of the current corner to the initial one.
00066 
00067     The circulator can be used to calculate the area of a region (in pixels):
00068 
00069     \code
00070     // start with a pixel within the region, whose left neighbor is outside
00071     // (see CrackContourCirculator constructor)
00072     ImageIterator region_anchor = ...;
00073     int area = 0;
00074 
00075     // calculate area from following the crack contour of the region
00076     CrackContourCirculator<ImageIterator> crack(region_anchor);
00077     CrackContourCirculator<ImageIterator> crackend(crack);
00078     do
00079     {
00080         area += crack.diff().x * crack.pos().y -
00081                 crack.diff().y * crack.pos().x;
00082     }
00083     while(++crack != crackend);
00084 
00085     area /= 2;
00086     std::cout << "Area of region " << *region_anchor << ": " << area << std::endl;
00087     \endcode
00088 
00089     <b>\#include</b> <vigra/contourcirculator.hxx><br>
00090     Namespace: vigra
00091 */
00092 template <class IMAGEITERATOR>
00093 class CrackContourCirculator
00094 {
00095     typedef NeighborhoodCirculator<IMAGEITERATOR, EightNeighborCode>
00096             NEIGHBORHOODCIRCULATOR;
00097     typedef typename IMAGEITERATOR::value_type label_type;
00098 
00099 protected:
00100     NEIGHBORHOODCIRCULATOR neighborCirc_;
00101     label_type label_;
00102     Point2D pos_;
00103 
00104     CrackContourCirculator(NEIGHBORHOODCIRCULATOR const & circ)
00105         : neighborCirc_(circ),
00106           label_(*(circ.center())),
00107           pos_(0, 0)
00108     {}
00109 
00110 public:
00111         /** the circulator's value type
00112         */
00113     typedef Point2D value_type;
00114 
00115         /** the circulator's reference type (return type of <TT>*circ</TT>)
00116         */
00117     typedef Point2D const & reference;
00118 
00119         /** the circulator's pointer type (return type of <TT>operator-></TT>)
00120         */
00121     typedef Point2D const * pointer;
00122 
00123         /** the circulator tag
00124         */
00125     typedef forward_circulator_tag iterator_category;
00126 
00127         /** Initialize the circulator for a given region.
00128 
00129             The image iterator <tt>in_the_region</tt> must refer
00130             to a boundary pixel of the region to be analysed. The
00131             direction code <tt>dir</tt> must point to a pixel outside the
00132             region (the default assumes that the pixel left of the
00133             given region pixel belongs to the background).
00134             The first corner of the crack contour is the corner to the
00135             right of this direction (i.e. the north west corner of
00136             the region pixel, if the direction was West).
00137         */
00138     CrackContourCirculator(IMAGEITERATOR const & in_the_region,
00139                            vigra::FourNeighborCode::Direction dir = vigra::FourNeighborCode::West)
00140         : neighborCirc_(in_the_region, EightNeighborCode::code(dir)),
00141           label_(*in_the_region),
00142           pos_(0, 0)
00143     {
00144         neighborCirc_.turnLeft();
00145     }
00146 
00147         /** Move to the next crack corner of the contour (pre-increment).
00148         */
00149     CrackContourCirculator & operator++()
00150     {
00151         pos_ += neighborCirc_.diff();
00152 
00153         neighborCirc_--;
00154 
00155         if(*neighborCirc_ == label_)
00156         {
00157             neighborCirc_.moveCenterToNeighbor(); // TODO: simplify moveCenterToNeighbor()s
00158             --neighborCirc_;
00159         }
00160         else
00161         {
00162             neighborCirc_.moveCenterToNeighbor(); // jump out
00163             neighborCirc_ += 3;
00164             if(*neighborCirc_ == label_)
00165             {
00166                 neighborCirc_.moveCenterToNeighbor();
00167                 neighborCirc_.turnRight();
00168             }
00169             else
00170             {
00171                 neighborCirc_.moveCenterToNeighbor();
00172                 neighborCirc_.turnLeft();
00173                 neighborCirc_.moveCenterToNeighbor();
00174                 neighborCirc_.turnRight();
00175             }
00176         }
00177 
00178         return *this;
00179     }
00180 
00181         /** Move to the next crack corner of the contour (post-increment).
00182         */
00183     CrackContourCirculator operator++(int)
00184     {
00185         CrackContourCirculator ret(*this);
00186         ++(*this);
00187         return ret;
00188     }
00189 
00190         /** equality
00191         */
00192     bool operator==(CrackContourCirculator const & o) const
00193     {
00194         return neighborCirc_ == o.neighborCirc_;
00195     }
00196 
00197         /** inequality
00198         */
00199     bool operator!=(CrackContourCirculator const & o) const
00200     {
00201         return neighborCirc_ != o.neighborCirc_;
00202     }
00203 
00204         /** Get the coordinate of the current corner
00205             (relative to the first corner).
00206         */
00207     reference pos() const
00208         { return pos_; }
00209 
00210         /** Equivalent to pos()
00211         */
00212     reference operator*() const
00213         { return pos_; }
00214 
00215         /** Access member of the current coordinate.
00216         */
00217     pointer operator->() const
00218         { return &pos_; }
00219 
00220         /** Access pixel to the right of the crack edge (outside of
00221          * the region bounded by the crack contour we walk on). Note
00222          * that after operator++, the iterator can still point to the
00223          * same pixel (looking from another direction now).
00224          */
00225     IMAGEITERATOR outerPixel() const
00226         { return NEIGHBORHOODCIRCULATOR(neighborCirc_).turnRight().base(); }
00227 
00228         /** Get the offset from the current corner of the contour
00229             to the next one.
00230         */
00231     Diff2D const & diff() const
00232         { return neighborCirc_.diff(); }
00233 };
00234 
00235 //@}
00236 
00237 } // namespace vigra
00238 
00239 #endif /* VIGRA_CONTOURCIRCULATOR_HXX */

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Tue Nov 6 2012)