vigra - vigra/contourcirculator.hxx Source File

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

contourcirculator.hxx |

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