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

vigra/contourcirculator.hxx

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