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

visit_border.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2013-2014 by Martin Bidlingmaier and 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 #ifndef VIGRA_VISIT_BORDER_HXX
37 #define VIGRA_VISIT_BORDER_HXX
38 
39 #include "multi_array.hxx"
40 
41 namespace vigra
42 {
43 
44 namespace visit_border_detail
45 {
46 
47 template <unsigned int K>
48 struct visit_border_impl
49 {
50  template <unsigned int N, class Data, class S1,
51  class Label, class S2,
52  class Shape, class Visitor>
53  static void exec(const MultiArrayView<N, Data, S1>& u_data, MultiArrayView<N, Label, S2> u_labels,
54  const MultiArrayView<N, Data, S1>& v_data, MultiArrayView<N, Label, S2> v_labels,
55  const Shape& block_difference, NeighborhoodType neighborhood, Visitor visitor)
56  {
57  static const unsigned int D = K - 1;
58  typedef visit_border_impl<D> next;
59 
60  if(block_difference[D] == -1)
61  {
62  MultiArrayIndex last = v_data.shape(D) - 1;
63  next::exec(u_data.bindAt(D, 0), u_labels.bindAt(D, 0),
64  v_data.bindAt(D, last), v_labels.bindAt(D, last),
65  block_difference, neighborhood, visitor);
66  }
67  else if(block_difference[D] == 1)
68  {
69  MultiArrayIndex last = u_data.shape(D) - 1;
70  next::exec(u_data.bindAt(D, last), u_labels.bindAt(D, last),
71  v_data.bindAt(D, 0), v_labels.bindAt(D, 0),
72  block_difference, neighborhood, visitor);
73  }
74  else if(block_difference[D] == 0)
75  {
76  next::exec(u_data, u_labels, v_data, v_labels, block_difference, neighborhood, visitor);
77  }
78  else
79  {
80  vigra_precondition(false, "invalid block difference");
81  }
82  }
83 };
84 
85 template <>
86 struct visit_border_impl<0>
87 {
88  template <class Data, class S1,
89  class Label, class S2,
90  class Shape, class Visitor>
91  static void exec(const MultiArrayView<0, Data, S1>& u_data, MultiArrayView<0, Label, S2> u_labels,
92  const MultiArrayView<0, Data, S1>& v_data, MultiArrayView<0, Label, S2> v_labels,
93  const Shape& block_difference, NeighborhoodType, Visitor visitor)
94  {
95  visitor(u_data(0), u_labels(0), v_data(0), v_labels(0), block_difference);
96  }
97  template <unsigned int N, class Data, class S1,
98  class Label, class S2,
99  class Shape, class Visitor>
100  static void exec(const MultiArrayView<N, Data, S1>& u_data, MultiArrayView<N, Label, S2> u_labels,
101  const MultiArrayView<N, Data, S1>& v_data, MultiArrayView<N, Label, S2> v_labels,
102  const Shape& block_difference, NeighborhoodType neighborhood, Visitor visitor)
103  {
104  if(neighborhood == DirectNeighborhood)
105  {
106  typedef typename MultiArrayView<N, Data, S1>::const_iterator DataIterator;
107  typedef typename MultiArrayView<N, Label, S2>::iterator LabelsIterator;
108 
109  DataIterator u_data_it = u_data.begin();
110  LabelsIterator u_labels_it = u_labels.begin();
111 
112  DataIterator v_data_it = v_data.begin();
113  LabelsIterator v_labels_it = v_labels.begin();
114 
115  for( ; u_data_it != u_data.end(); ++u_data_it, ++u_labels_it, ++v_data_it, ++v_labels_it)
116  {
117  visitor(*u_data_it, *u_labels_it, *v_data_it, *v_labels_it, block_difference);
118  }
119  }
120  else if(neighborhood == IndirectNeighborhood)
121  {
122  typedef GridGraph<N, undirected_tag> Graph;
123  typedef typename Graph::NodeIt GraphScanner;
124  typedef typename Graph::OutArcIt NeighborIterator;
125 
126  static const int global_dim_number = Shape::static_size;
127  TinyVector<unsigned int, N> dim_mapping; // mapping of every local dimension to their actual global dimension indices
128  int local_dims_pos = 0;
129  int global_dims_pos = 0;
130  for( ; global_dims_pos != global_dim_number; ++global_dims_pos)
131  {
132  if(block_difference[global_dims_pos] == 0)
133  {
134  vigra_assert(local_dims_pos != N, "");
135  dim_mapping[local_dims_pos] = global_dims_pos;
136  ++local_dims_pos;
137  }
138  }
139  vigra_assert(local_dims_pos == N, "");
140 
141  Graph graph(u_data.shape(), neighborhood);
142  Shape pixel_difference = block_difference;
143  for(GraphScanner node(graph); node != lemon::INVALID; ++node)
144  {
145  // compare neighbors that have have equal coordinates in all unbound dimensions
146  // their pixel-level difference is exactly block_difference
147  visitor(u_data[*node], u_labels[*node], v_data[*node], v_labels[*node], block_difference);
148  // now let unbound dimensions vary
149  for(NeighborIterator arc(graph, *node); arc != lemon::INVALID; ++arc)
150  {
151  for(int i = 0; i != N; ++i)
152  pixel_difference[dim_mapping[i]] = graph.target(*arc)[i] - (*node)[i];
153  visitor(u_data[*node], u_labels[*node], v_data[graph.target(*arc)], v_labels[graph.target(*arc)], pixel_difference);
154  }
155  }
156  }
157  }
158 };
159 
160 } // namespace visit_border_detail
161 
162 template <unsigned int N, class Data, class S1,
163  class Label, class S2,
164  class Shape, class Visitor>
165 inline void
166 visitBorder(const MultiArrayView<N, Data, S1>& u_data, MultiArrayView<N, Label, S2> u_labels,
167  const MultiArrayView<N, Data, S1>& v_data, MultiArrayView<N, Label, S2> v_labels,
168  const Shape& difference, NeighborhoodType neighborhood, Visitor visitor)
169 {
170  vigra_precondition(u_data.shape() == u_labels.shape() && v_data.shape() == v_labels.shape(),
171  "differing block shapes");
172  visit_border_detail::visit_border_impl<N>::exec(u_data, u_labels,
173  v_data, v_labels,
174  difference, neighborhood, visitor);
175 }
176 
177 } // namespace vigra
178 
179 #endif // VIGRA_VISIT_BORDER_HXX
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60
use direct and indirect neighbors
Definition: multi_fwd.hxx:188
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)