1 /************************************************************************/ 2 /* */ 3 /* Copyright 1998-2002 by Ullrich Koethe */ 4 /* Cognitive Systems Group, University of Hamburg, Germany */ 5 /* */ 6 /* This file is part of the VIGRA computer vision library. */ 7 /* ( Version 1.5.0, Dec 07 2006 ) */ 8 /* The VIGRA Website is */ 9 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ 10 /* Please direct questions, bug reports, and contributions to */ 11 /* koethe@informatik.uni-hamburg.de or */ 12 /* vigra@kogs1.informatik.uni-hamburg.de */ 13 /* */ 14 /* Permission is hereby granted, free of charge, to any person */ 15 /* obtaining a copy of this software and associated documentation */ 16 /* files (the "Software"), to deal in the Software without */ 17 /* restriction, including without limitation the rights to use, */ 18 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 19 /* sell copies of the Software, and to permit persons to whom the */ 20 /* Software is furnished to do so, subject to the following */ 21 /* conditions: */ 22 /* */ 23 /* The above copyright notice and this permission notice shall be */ 24 /* included in all copies or substantial portions of the */ 25 /* Software. */ 26 /* */ 27 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 28 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 29 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 30 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 31 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 32 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 33 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 34 /* OTHER DEALINGS IN THE SOFTWARE. */ 35 /* */ 36 /************************************************************************/ 37 38 39 #ifndef VIGRA_CONTOURCIRCULATOR_HXX 40 #define VIGRA_CONTOURCIRCULATOR_HXX 41 42 #include "pixelneighborhood.hxx" 43 44 namespace vigra 45 { 46 47 /** \addtogroup ImageIteratorAdapters 48 */ 49 //@{ 50 51 /********************************************************/ 52 /* */ 53 /* CrackContourCirculator */ 54 /* */ 55 /********************************************************/ 56 57 /** \brief Circulator that walks around a given region. 58 59 The circulator follows the <em>crack contour</em> of a given region. 60 Here, a region is an 8-connected component of pixels with the same 61 value, such as the regions in a label image. 62 The crack contour is located between the inside and outside 63 pixels, that is "on the crack" between the region and the background. 64 Thus, the circulator moves from pixel corner to pixel corner. By definition, 65 the first corner (where the circulator was initialized) gets the 66 coordinate (0,0), and calls to <tt>*circulator</tt> return the distance 67 of the current corner to the initial one. 68 69 The circulator can be used to calculate the area of a region (in pixels): 70 71 \code 72 // start with a pixel within the region, whose left neighbor is outside 73 // (see CrackContourCirculator constructor) 74 ImageIterator region_anchor = ...; 75 int area = 0; 76 77 // calculate area from following the crack contour of the region 78 CrackContourCirculator<ImageIterator> crack(region_anchor); 79 CrackContourCirculator<ImageIterator> crackend(crack); 80 do 81 { 82 area += crack.diff().x * crack.pos().y - 83 crack.diff().y * crack.pos().x; 84 } 85 while(++crack != crackend); 86 87 area /= 2; 88 std::cout << "Area of region " << *region_anchor << ": " << area << std::endl; 89 \endcode 90 91 <b>\#include</b> "<a href="contourcirculator_8hxx-source.html">vigra/contourcirculator.hxx</a>"<br> 92 Namespace: vigra 93 */ 94 template <class IMAGEITERATOR> 95 class CrackContourCirculator 96 { 97 typedef NeighborhoodCirculator<IMAGEITERATOR, EightNeighborCode> 98 NEIGHBORHOODCIRCULATOR; 99 typedef typename IMAGEITERATOR::value_type label_type; 100 101 protected: 102 NEIGHBORHOODCIRCULATOR neighborCirc_; 103 label_type label_; 104 Point2D pos_; 105 CrackContourCirculator(NEIGHBORHOODCIRCULATOR const & circ)106 CrackContourCirculator(NEIGHBORHOODCIRCULATOR const & circ) 107 : neighborCirc_(circ), 108 label_(*(circ.center())), 109 pos_(0, 0) 110 {} 111 112 public: 113 /** the circulator's value type 114 */ 115 typedef Point2D value_type; 116 117 /** the circulator's reference type (return type of <TT>*circ</TT>) 118 */ 119 typedef Point2D const & reference; 120 121 /** the circulator's pointer type (return type of <TT>operator-></TT>) 122 */ 123 typedef Point2D const * pointer; 124 125 /** the circulator tag 126 */ 127 typedef forward_circulator_tag iterator_category; 128 129 /** Initialize the circulator for a given region. 130 131 The image iterator <tt>in_the_region</tt> must refer 132 to a boundary pixel of the region to be analysed. The 133 direction code <tt>dir</tt> must point to a pixel outside the 134 region (the default assumes that the pixel left of the 135 given region pixel belongs to the background). 136 The first corner of the crack contour is the corner to the 137 right of this direction (i.e. the north west corner of 138 the region pixel, if the direction was West). 139 */ CrackContourCirculator(IMAGEITERATOR const & in_the_region,vigra::FourNeighborCode::Direction dir=vigra::FourNeighborCode::West)140 CrackContourCirculator(IMAGEITERATOR const & in_the_region, 141 vigra::FourNeighborCode::Direction dir = vigra::FourNeighborCode::West) 142 : neighborCirc_(in_the_region, EightNeighborCode::code(dir)), 143 label_(*in_the_region), 144 pos_(0, 0) 145 { 146 neighborCirc_.turnLeft(); 147 } 148 149 /** Move to the next crack corner of the contour (pre-increment). 150 */ operator ++()151 CrackContourCirculator & operator++() 152 { 153 pos_ += neighborCirc_.diff(); 154 155 neighborCirc_--; 156 157 if(*neighborCirc_ == label_) 158 { 159 neighborCirc_.moveCenterToNeighbor(); // TODO: simplify moveCenterToNeighbor()s 160 --neighborCirc_; 161 } 162 else 163 { 164 neighborCirc_.moveCenterToNeighbor(); // jump out 165 neighborCirc_ += 3; 166 if(*neighborCirc_ == label_) 167 { 168 neighborCirc_.moveCenterToNeighbor(); 169 neighborCirc_.turnRight(); 170 } 171 else 172 { 173 neighborCirc_.moveCenterToNeighbor(); 174 neighborCirc_.turnLeft(); 175 neighborCirc_.moveCenterToNeighbor(); 176 neighborCirc_.turnRight(); 177 } 178 } 179 180 return *this; 181 } 182 183 /** Move to the next crack corner of the contour (post-increment). 184 */ operator ++(int)185 CrackContourCirculator operator++(int) 186 { 187 CrackContourCirculator ret(*this); 188 ++(*this); 189 return ret; 190 } 191 192 /** equality 193 */ operator ==(CrackContourCirculator const & o) const194 bool operator==(CrackContourCirculator const & o) const 195 { 196 return neighborCirc_ == o.neighborCirc_; 197 } 198 199 /** inequality 200 */ operator !=(CrackContourCirculator const & o) const201 bool operator!=(CrackContourCirculator const & o) const 202 { 203 return neighborCirc_ != o.neighborCirc_; 204 } 205 206 /** Get the coordinate of the current corner 207 (relative to the first corner). 208 */ pos() const209 reference pos() const 210 { return pos_; } 211 212 /** Equivalent to pos() 213 */ operator *() const214 reference operator*() const 215 { return pos_; } 216 217 /** Access member of the current coordinate. 218 */ operator ->() const219 pointer operator->() const 220 { return &pos_; } 221 222 /** Access pixel to the right of the crack edge (outside of 223 * the region bounded by the crack contour we walk on). Note 224 * that after operator++, the iterator can still point to the 225 * same pixel (looking from another direction now). 226 */ outerPixel() const227 IMAGEITERATOR outerPixel() const 228 { return NEIGHBORHOODCIRCULATOR(neighborCirc_).turnRight().base(); } 229 230 /** Get the offset from the current corner of the contour 231 to the next one. 232 */ diff() const233 Diff2D const & diff() const 234 { return neighborCirc_.diff(); } 235 }; 236 237 //@} 238 239 } // namespace vigra 240 241 #endif /* VIGRA_CONTOURCIRCULATOR_HXX */ 242