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

blockwise_convolution.hxx
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>
36std::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*/
110doxygen_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
vigra::MultiArrayShape::type
TinyVector< MultiArrayIndex, N > type
Definition multi_shape.hxx:272
vigra::MultiArrayView::difference_type
MultiArrayShape< actual_dimension >::type difference_type
Definition multi_array.hxx:739
vigra::RGBValue
Class for a single RGB value.
Definition rgbvalue.hxx:128
vigra::TinyVector
Class for fixed size vectors.
Definition tinyvector.hxx:1008
vigra
vigra::separableConvolveMultiArray
void separableConvolveMultiArray(...)
Separated convolution on multi-dimensional arrays.

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