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

multi_localminmax.hxx VIGRA

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 
48 namespace vigra {
49 
50 
51 namespace 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 
71 namespace boost_graph {
72 
73 // Attempt without LValue propmaps, using only the free functions
74 // to access ReadablePropertyMap (input) and WritablePropertyMap (label)
75 template <class Graph, class T1Map, class T2Map, class Compare>
76 unsigned int
77 localMinMaxGraph(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 
121 namespace lemon_graph {
122 
123 template <class Graph, class T1Map, class T2Map, class Compare>
124 unsigned int
125 localMinMaxGraph(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 
162 template <class Graph, class T1Map, class T2Map, class Compare, class Equal>
163 unsigned int
164 extendedLocalMinMaxGraph(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 
221 template <unsigned int N, class T1, class C1,
222  class T2, class C2,
223  class Compare,
224  class EqualityFunctor>
225 unsigned int
226 localMinMax(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 
236  NeighborhoodType neighborhood = DirectNeighborhood;
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
264 template <unsigned int N, class T1, class C1, class T2, class C2>
265 inline unsigned int
266 localMinima(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 
277 template <unsigned int N, class T1, class S1,
278  class T2, class S2,
279  class EqualityFunctor>
280 inline unsigned int
281 extendedLocalMinima(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
299 template <unsigned int N, class T1, class C1, class T2, class C2>
300 inline unsigned int
301 localMaxima(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 
312 template <unsigned int N, class T1, class S1,
313  class T2, class S2,
314  class EqualityFunctor>
315 inline unsigned int
316 extendedLocalMaxima(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
std::pair< typename vigra::GridGraph< N, DirectedTag >::adjacency_iterator, typename vigra::GridGraph< N, DirectedTag >::adjacency_iterator > adjacent_vertices(typename vigra::GridGraph< N, DirectedTag >::vertex_descriptor const &v, vigra::GridGraph< N, DirectedTag > const &g)
Get a (begin, end) iterator pair for the neighbor vertices of vertex v in graph g (API: boost)...
Definition: multi_gridgraph.hxx:2863
void extendedLocalMinima(...)
Find local minimal regions (plateaus) in an array.
void localMinima(...)
Find local minima in an image or multi-dimensional array.
void put(vigra::MultiArrayView< N, T, Stride > &pmap, typename vigra::MultiArrayView< N, T, Stride >::difference_type const &k, U const &val)
Put value val at key k in the property map pmap (API: boost).
Definition: multi_gridgraph.hxx:3004
void localMaxima(...)
Find local maxima in an image or multi-dimensional array.
std::pair< typename vigra::GridGraph< N, DirectedTag >::vertex_iterator, typename vigra::GridGraph< N, DirectedTag >::vertex_iterator > vertices(vigra::GridGraph< N, DirectedTag > const &g)
Get a (begin, end) iterator pair for the vertices of graph g (API: boost).
Definition: multi_gridgraph.hxx:2840
use direct and indirect neighbors
Definition: multi_fwd.hxx:188
void extendedLocalMaxima(...)
Find local maximal regions in an array.
use only direct neighbors
Definition: multi_fwd.hxx:187
NeighborhoodType
Choose the neighborhood system in a dimension-independent way.
Definition: multi_fwd.hxx:186

© 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 (Fri May 19 2017)