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

blockwise_convolution.hxx VIGRA

1 #ifndef VIGRA_BLOCKWISE_CONVOLUTION_HXX_
2 #define VIGRA_BLOCKWISE_CONVOLUTION_HXX_
3 
4 #include <vigra/overlapped_blocks.hxx>
5 #include <vigra/multi_convolution.hxx>
6 #include <vigra/blockify.hxx>
7 #include <vigra/multi_array.hxx>
8 
9 namespace vigra
10 {
11 
12 namespace blockwise_convolution_detail
13 {
14 
15 template <class DataArray, class OutputBlocksIterator, class KernelIterator>
16 void convolveImpl(const Overlaps<DataArray>& overlaps, OutputBlocksIterator output_blocks_begin, KernelIterator kit)
17 {
18  static const unsigned int N = DataArray::actual_dimension;
19  typedef typename MultiArrayShape<N>::type Shape;
20  typedef typename OutputBlocksIterator::value_type OutputBlock;
21 
22  Shape shape = overlaps.shape();
23  vigra_assert(shape == output_blocks_begin.shape(), "");
24 
25  MultiCoordinateIterator<N> it(shape);
26  MultiCoordinateIterator<N> end = it.getEndIterator();
27  for( ; it != end; ++it)
28  {
29  OutputBlock output_block = output_blocks_begin[*it];
30  OverlappingBlock<DataArray> data_block = overlaps[*it];
31  separableConvolveMultiArray(data_block.block, output_block, kit, data_block.inner_bounds.first, data_block.inner_bounds.second);
32  }
33 }
34 
35 template <class Shape, class KernelIterator>
36 std::pair<Shape, Shape> kernelOverlap(KernelIterator kit)
37 {
38  Shape before;
39  Shape after;
40 
41  for(unsigned int i = 0; i != Shape::static_size; ++i, ++kit)
42  {
43  // FIXME: is this correct?
44  before[i] = kit->right();
45  after[i] = -kit->left();
46  }
47  return std::make_pair(before, after);
48 }
49 
50 }
51 
52 
53 template <unsigned int N, class T1, class S1,
54  class T2, class S2,
55  class KernelIterator>
56 void separableConvolveBlockwise(MultiArrayView<N, T1, S1> source, MultiArrayView<N, T2, S2> dest, KernelIterator kit,
57  const typename MultiArrayView<N, T1, S1>::difference_type& block_shape =
58  typename MultiArrayView<N, T1, S1>::difference_type(128))
59 {
60  using namespace blockwise_convolution_detail;
61 
62  typedef typename MultiArrayView<N, T1, S1>::difference_type Shape;
63 
64  Shape shape = source.shape();
65  vigra_precondition(shape == dest.shape(), "shape mismatch of source and destination");
66 
67  std::pair<Shape, Shape> overlap = kernelOverlap<Shape, KernelIterator>(kit);
68  Overlaps<MultiArrayView<N, T2, S2> > overlaps(source, block_shape, overlap.first, overlap.second);
69 
70  MultiArray<N, MultiArrayView<N, T2, S2> > destination_blocks = blockify(dest, block_shape);
71 
72  convolveImpl(overlaps, destination_blocks.begin(), kit);
73 }
74 template <unsigned int N, class T1, class S1,
75  class T2, class S2,
76  class T3>
77 void separableConvolveBlockwise(MultiArrayView<N, T1, S1> source, MultiArrayView<N, T2, S2> dest, const Kernel1D<T3>& kernel,
78  const typename MultiArrayView<N, T1, S1>::difference_type& block_shape =
79  typename MultiArrayView<N, T1, S1>::difference_type(128))
80 {
81  std::vector<Kernel1D<T3> > kernels(N, kernel);
82  separableConvolveBlockwise(source, dest, kernels.begin(), block_shape);
83 }
84 
85 
86 /*******************************************************/
87 /* */
88 /* separableConvolveBlockwise */
89 /* */
90 /*******************************************************/
91 
92 /** \brief Separated convolution on ChunkedArrays.
93 
94  <b> Declarations:</b>
95 
96  \code
97  namespace vigra {
98  // apply each kernel from the sequence 'kernels' in turn
99  template <unsigned int N, class T1, class T2, class KernelIterator>
100  void separableConvolveBlockwise(const ChunkedArra<N, T1>& source, ChunkedArray<N, T2>& destination, KernelIterator kernels);
101  // apply the same kernel to all dimensions
102  template <unsigned int N, class T1, class T2, class T3>
103  void separableConvolveBlockwise(const ChunkedArra<N, T1>& source, ChunkedArray<N, T2>& destination, Kernel1D<T3> const & kernel);
104  }
105  \endcode
106 
107  This function computes a separated convolution for a given \ref ChunkedArray. For infinite precision T1, this is equivalent to
108  \ref separableConvolveMultiArray. In practice, floating point inaccuracies will make the result differ slightly.
109 */
110 doxygen_overloaded_function(template <...> void separableConvolveBlockwise)
111 
112 template <unsigned int N, class T1, class T2, class KernelIterator>
113 void separableConvolveBlockwise(const ChunkedArray<N, T1>& source, ChunkedArray<N, T2>& destination, KernelIterator kit)
114 {
115  using namespace blockwise_convolution_detail;
116 
117  typedef typename ChunkedArray<N, T1>::shape_type Shape;
118 
119  Shape shape = source.shape();
120  vigra_precondition(shape == destination.shape(), "shape mismatch of source and destination");
121 
122  std::pair<Shape, Shape> overlap = kernelOverlap<Shape, KernelIterator>(kit);
123  Shape block_shape = source.chunkShape();
124  vigra_precondition(block_shape == destination.chunkShape(), "chunk shapes do not match");
125  Overlaps<ChunkedArray<N, T1> > overlaps(source, block_shape, overlap.first, overlap.second);
126 
127  convolveImpl(overlaps, destination.chunk_begin(Shape(0), shape), kit);
128 }
129 template <unsigned int N, class T1, class T2, class T>
130 void separableConvolveBlockwise(const ChunkedArray<N, T1>& source, ChunkedArray<N, T2>& destination, const Kernel1D<T>& kernel)
131 {
132  std::vector<Kernel1D<T> > kernels(N, kernel);
133  separableConvolveBlockse(source, destination, kernels.begin());
134 }
135 
136 
137 }
138 
139 #endif
140 
void separableConvolveMultiArray(...)
Separated convolution on multi-dimensional arrays.
vigra::GridGraph< N, DirectedTag >::vertex_descriptor source(typename vigra::GridGraph< N, DirectedTag >::edge_descriptor const &e, vigra::GridGraph< N, DirectedTag > const &g)
Get a vertex descriptor for the start vertex of edge e in graph g (API: boost).
Definition: multi_gridgraph.hxx:2943
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.

© 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)