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

multi_localminmax.hxx
1/************************************************************************/
2/* */
3/* Copyright 2012-2013 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_MULTI_LOCALMINMAX_HXX
38#define VIGRA_MULTI_LOCALMINMAX_HXX
39
40#include <vector>
41#include <functional>
42#include "multi_array.hxx"
43#include "localminmax.hxx"
44#include "multi_gridgraph.hxx"
45#include "multi_labeling.hxx"
46#include "metaprogramming.hxx"
47
48namespace vigra {
49
50
51namespace detail_local_minima{
52 template<class G>
53 struct NodeAtBorder{
54 template<class NODE_ITER>
55 static bool atBorder(const NODE_ITER &){
56 return false;
57 }
58 };
59
60 template<unsigned int DIM,class DTAG>
61 struct NodeAtBorder< GridGraph<DIM,DTAG> >{
62 template<class NODE_ITER>
63 static bool atBorder(const NODE_ITER & node ){
64 return node.atBorder();
65 }
66 };
67
68};
69
70
71namespace boost_graph {
72
73// Attempt without LValue propmaps, using only the free functions
74// to access ReadablePropertyMap (input) and WritablePropertyMap (label)
75template <class Graph, class T1Map, class T2Map, class Compare>
76unsigned int
77localMinMaxGraph(Graph const &g,
78 T1Map const &src,
79 T2Map &dest,
80 typename property_traits<T2Map>::value_type marker,
81 typename property_traits<T1Map const>::value_type threshold,
82 Compare const &compare,
83 bool allowAtBorder = true)
84{
85 typedef typename graph_traits<Graph>::vertex_iterator graph_scanner;
86 typedef typename graph_traits<Graph>::adjacency_iterator neighbor_iterator;
87
88 typedef typename property_traits<T1Map const>::value_type T1;
89
90 graph_scanner node, srcend;
91 neighbor_iterator arc, nbend;
92
93 unsigned int count = 0;
94 tie(node, srcend) = vertices(g);
95 for (; node != srcend; ++node)
96 {
97 const T1 current = get(src, *node);
98
99 if (!compare(current, threshold))
100 continue;
101
102 if(!allowAtBorder && node.atBorder())
103 continue;
104
105 tie(arc, nbend) = adjacent_vertices(*node, g);
106 for (;arc != nbend; ++arc)
107 if (!compare(current, get(src, *arc)))
108 break;
109
110 if (arc == nbend)
111 {
112 put(dest, *node, marker);
113 ++count;
114 }
115 }
116 return count;
117}
118
119} // namespace boost_graph
120
121namespace lemon_graph {
122
123template <class Graph, class T1Map, class T2Map, class Compare>
124unsigned int
125localMinMaxGraph(Graph const &g,
126 T1Map const &src,
127 T2Map &dest,
128 typename T2Map::value_type marker,
129 typename T1Map::value_type threshold,
130 Compare const &compare,
131 bool allowAtBorder = true)
132{
133 typedef typename Graph::NodeIt graph_scanner;
134 typedef typename Graph::OutArcIt neighbor_iterator;
135
136 unsigned int count = 0;
137 for (graph_scanner node(g); node != INVALID; ++node)
138 {
139 typename T1Map::value_type current = src[*node];
140
141 if (!compare(current, threshold))
142 continue;
143
144 if(!allowAtBorder && vigra::detail_local_minima::NodeAtBorder<Graph>::atBorder(node))
145 continue;
146
147 neighbor_iterator arc(g, *node);
148 for (; arc != INVALID; ++arc)
149 if (!compare(current, src[g.target(*arc)]))
150 break;
151
152 if (arc == INVALID)
153 {
154 dest[*node] = marker;
155 ++count;
156 }
157 }
158 return count;
159}
160
161
162template <class Graph, class T1Map, class T2Map, class Compare, class Equal>
163unsigned int
164extendedLocalMinMaxGraph(Graph const &g,
165 T1Map const &src,
166 T2Map &dest,
167 typename T2Map::value_type marker,
168 typename T1Map::value_type threshold,
169 Compare const &compare,
170 Equal const &equal,
171 bool allowAtBorder = true)
172{
173 typename Graph::template NodeMap<unsigned int> regions(g);
174
175 int max_region_label = labelGraph(g, src, regions, equal);
176
177 // assume that a region is a extremum until the opposite is proved
178 std::vector<unsigned char> isExtremum(max_region_label+1, (unsigned char)1);
179
180 typedef typename Graph::NodeIt graph_scanner;
181 typedef typename Graph::OutArcIt neighbor_iterator;
182
183 unsigned int count = max_region_label;
184 for (graph_scanner node(g); node != INVALID; ++node)
185 {
186 unsigned int label = regions[*node];
187
188 if(!isExtremum[label])
189 continue;
190
191 typename T1Map::value_type current = src[*node];
192
193 if (!compare(current, threshold) ||
194 (!allowAtBorder && vigra::detail_local_minima::NodeAtBorder<Graph>::atBorder(node) ))
195 {
196 isExtremum[label] = 0;
197 --count;
198 continue;
199 }
200
201 for (neighbor_iterator arc(g, *node); arc != INVALID; ++arc)
202 {
203 if (label != regions[g.target(*arc)] && compare(src[g.target(*arc)], current))
204 {
205 isExtremum[label] = 0;
206 --count;
207 break;
208 }
209 }
210 }
211 for (graph_scanner node(g); node != INVALID; ++node)
212 {
213 if(isExtremum[regions[*node]])
214 dest[*node] = marker;
215 }
216 return count;
217}
218
219} // namespace lemon_graph
220
221template <unsigned int N, class T1, class C1,
222 class T2, class C2,
223 class Compare,
224 class EqualityFunctor>
225unsigned int
226localMinMax(MultiArrayView<N, T1, C1> const & src,
227 MultiArrayView<N, T2, C2> dest,
228 T1 threshold,
229 Compare const & compare,
230 EqualityFunctor const & equal,
231 LocalMinmaxOptions const & options = LocalMinmaxOptions())
232{
233 vigra_precondition(src.shape() == dest.shape(),
234 "localMinMax(): shape mismatch between input and output.");
235
237
238 if(options.neigh == 0 || options.neigh == 2*N)
239 neighborhood = DirectNeighborhood;
240 else if(options.neigh == 1 || options.neigh == MetaPow<3, N>::value - 1)
241 neighborhood = IndirectNeighborhood;
242 else
243 vigra_precondition(false,
244 "localMinMax(): option object specifies invalid neighborhood type.");
245
246 T2 marker = (T2)options.marker;
247
248 GridGraph<N, undirected_tag> graph(src.shape(), neighborhood);
249 if(options.allow_plateaus)
250 return lemon_graph::extendedLocalMinMaxGraph(graph, src, dest, marker, threshold,
251 compare, equal, options.allow_at_border);
252 else
253 return lemon_graph::localMinMaxGraph(graph, src, dest, marker, threshold,
254 compare, options.allow_at_border);
255}
256
257/********************************************************/
258/* */
259/* localMinima */
260/* */
261/********************************************************/
262
263// documentation is in localminmax.hxx
264template <unsigned int N, class T1, class C1, class T2, class C2>
265inline unsigned int
266localMinima(MultiArrayView<N, T1, C1> const & src,
267 MultiArrayView<N, T2, C2> dest,
268 LocalMinmaxOptions const & options = LocalMinmaxOptions())
269{
270 T1 threshold = options.use_threshold
271 ? std::min(NumericTraits<T1>::max(), (T1)options.thresh)
272 : NumericTraits<T1>::max();
273 return localMinMax(src, dest, threshold, std::less<T1>(), std::equal_to<T1>(), options);
274}
275
276
277template <unsigned int N, class T1, class S1,
278 class T2, class S2,
279 class EqualityFunctor>
280inline unsigned int
281extendedLocalMinima(MultiArrayView<N, T1, S1> const & src,
282 MultiArrayView<N, T2, S2> dest,
283 EqualityFunctor const & equal,
284 LocalMinmaxOptions options = LocalMinmaxOptions())
285{
286 options.allowPlateaus();
287 T1 threshold = options.use_threshold
288 ? std::min(NumericTraits<T1>::max(), (T1)options.thresh)
289 : NumericTraits<T1>::max();
290 return localMinMax(src, dest, threshold, std::less<T1>(), equal, options);
291}
292/********************************************************/
293/* */
294/* localMaxima */
295/* */
296/********************************************************/
297
298// documentation is in localminmax.hxx
299template <unsigned int N, class T1, class C1, class T2, class C2>
300inline unsigned int
301localMaxima(MultiArrayView<N, T1, C1> const & src,
302 MultiArrayView<N, T2, C2> dest,
303 LocalMinmaxOptions const & options = LocalMinmaxOptions())
304{
305 T1 threshold = options.use_threshold
306 ? std::max(NumericTraits<T1>::min(), (T1)options.thresh)
307 : NumericTraits<T1>::min();
308 return localMinMax(src, dest, threshold, std::greater<T1>(), std::equal_to<T1>(), options);
309}
310
311
312template <unsigned int N, class T1, class S1,
313 class T2, class S2,
314 class EqualityFunctor>
315inline unsigned int
316extendedLocalMaxima(MultiArrayView<N, T1, S1> const & src,
317 MultiArrayView<N, T2, S2> dest,
318 EqualityFunctor const & equal,
319 LocalMinmaxOptions options = LocalMinmaxOptions())
320{
321 options.allowPlateaus();
322 T1 threshold = options.use_threshold
323 ? std::max(NumericTraits<T1>::min(), (T1)options.thresh)
324 : NumericTraits<T1>::min();
325 return localMinMax(src, dest, threshold, std::greater<T1>(), equal, options);
326}
327
328} // namespace vigra
329
330#endif // VIGRA_MULTI_LOCALMINMAX_HXX
LookupTag< TAG, A >::result_type get(A const &a)
Definition accumulator.hxx:2942
void extendedLocalMaxima(...)
Find local maximal regions in an array.
NeighborhoodType
Choose the neighborhood system in a dimension-independent way.
Definition multi_fwd.hxx:186
@ IndirectNeighborhood
use direct and indirect neighbors
Definition multi_fwd.hxx:188
@ DirectNeighborhood
use only direct neighbors
Definition multi_fwd.hxx:187
void localMinima(...)
Find local minima in an image or multi-dimensional array.
void extendedLocalMinima(...)
Find local minimal regions (plateaus) in an array.
void localMaxima(...)
Find local maxima in an image or multi-dimensional array.

© 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.11.1