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

multi_blocking.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 2015 by Thorsten Beier */
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_MULTI_BLOCKING_HXX
37 #define VIGRA_MULTI_BLOCKING_HXX
38
39 #include "vigra/tinyvector.hxx"
40 #include "vigra/box.hxx"
41 #include "vigra/multi_iterator.hxx"
42 #include "vigra/multi_convolution.hxx"
43 #include "vigra/transform_iterator.hxx"
44
45 namespace vigra{
46
47 // forward declaration
48 template<unsigned int DIM, class C>
49 class MultiBlocking;
50
51 /// \cond
52 namespace detail_multi_blocking{
53
54 template<unsigned int DIM, class C>
55 class BlockWithBorder{
56 public:
57 typedef C PointValue;
58 typedef TinyVector<PointValue, DIM> Point;
59 typedef Point Shape;
60 typedef Box<PointValue, DIM> Block;
61 typedef MultiCoordinateIterator< DIM> MultiCoordIter;
62
63 BlockWithBorder(const Block & core = Block(), const Block & border = Block())
64 : core_(core),
65 border_(border){
66 }
67
68 /// get the core block
69 const Block & core()const{
70 return core_;
71 }
72
73 Block localCore()const{
74 return core_-border_.begin();
75 }
76
77
78 const Block & border()const{
79 return border_;
80 }
81
82 bool operator == (const BlockWithBorder & rhs) const{
83 return core_ == rhs.core_ && border_ == rhs.border_;
84 }
85 bool operator != (const BlockWithBorder & rhs) const{
86 return core_ != rhs.core_ || border_ != rhs.border_;
87 }
88
89 private:
90 Block core_;
91 Block border_;
92 };
93
94 template<class VALUETYPE, unsigned int DIMENSION>
95 std::ostream& operator<< (std::ostream& stream, const BlockWithBorder<DIMENSION,VALUETYPE> & bwb) {
96 stream<<"["<<bwb.core()<<", "<<bwb.border()<<" ]";
97 return stream;
98 }
99
100
101 template<class MB>
102 class MultiCoordToBlockWithBoarder{
103 public:
104 typedef typename MB::Shape Shape;
105 typedef typename MB::BlockDesc BlockDesc;
106 typedef typename MB::BlockWithBorder result_type;
107 MultiCoordToBlockWithBoarder()
108 : mb_(NULL),
109 width_(){
110 }
111 MultiCoordToBlockWithBoarder(const MB & mb, const Shape & width)
112 : mb_(&mb),
113 width_(width){
114 }
115
116 result_type operator()(const BlockDesc & blockDesc)const{
117 return mb_->getBlockWithBorder(blockDesc, width_);
118 }
119 private:
120 const MB * mb_;
121 Shape width_;
122 };
123
124 template<class MB>
125 class MultiCoordToBlock{
126 public:
127 typedef typename MB::Shape Shape;
128 typedef typename MB::BlockDesc BlockDesc;
129 typedef typename MB::Block result_type;
130 MultiCoordToBlock()
131 : mb_(NULL){
132 }
133 MultiCoordToBlock(const MB & mb)
134 : mb_(&mb){
135 }
136
137 result_type operator()(const BlockDesc & blockDesc)const{
138 return mb_->getBlock(blockDesc);
139 }
140 private:
141 const MB * mb_;
142 };
143 }
144 /// \endcond
145
146
147 /**
148 MultiBlocking is used to split a image / volume / multiarray
149 into non-overlapping blocks.
150 These non overlapping blocks are called cores.
151 A border can be added to the core boxes.
152 These 'core+border' blocks are just called border.
153 The core block within the coordinate system
154 of the border block is called local core.
155 */
156 template<unsigned int DIM, class C = MultiArrayIndex>
157 class MultiBlocking{
158 public:
159 typedef MultiBlocking<DIM, C> SelfType;
160 friend class detail_multi_blocking::MultiCoordToBlock<SelfType>;
161 friend class detail_multi_blocking::MultiCoordToBlockWithBoarder<SelfType>;
162 typedef C PointValue;
163 typedef TinyVector<PointValue, DIM> Point;
164 typedef Point Shape;
165 typedef Point BlockDesc;
166 typedef Box<PointValue, DIM> Block;
167 typedef MultiCoordinateIterator< DIM> MultiCoordIter;
168 typedef detail_multi_blocking::BlockWithBorder<DIM, PointValue> BlockWithBorder;
169
170
171 // iterators
172 typedef detail_multi_blocking::MultiCoordToBlockWithBoarder<SelfType> CoordToBwb;
173 typedef detail_multi_blocking::MultiCoordToBlock<SelfType> CoordToB;
174 typedef EndAwareTransformIterator<CoordToBwb, MultiCoordIter> BlockWithBorderIter;
175 typedef EndAwareTransformIterator<CoordToB, MultiCoordIter> BlockIter;
176
177
178 MultiBlocking(const Shape & shape,
179 const Shape & blockShape,
180 const Shape & roiBegin = Shape(0),
181 const Shape & roiEnd = Shape(0)
182 )
183 : shape_(shape),
184 roiBlock_(roiBegin,roiEnd == Shape(0) ? shape : roiEnd),
185 blockShape_(blockShape),
186 blocksPerAxis_(vigra::SkipInitialization),
187 numBlocks_(1)
188 {
189 const Shape roiShape = roiBlock_.size();
190 blocksPerAxis_ = roiShape / blockShape_;
191
192
193 // blocking
194 for(size_t d=0; d<DIM; ++d){
195 if(blocksPerAxis_[d]*blockShape_[d] < roiShape[d] ){
196 ++blocksPerAxis_[d];
197 }
198 numBlocks_ *= blocksPerAxis_[d];
199 }
200
201 // total image border blocks
202 Shape beginCA(0),endCB(shape);
203 for(size_t d=0; d<DIM; ++d){
204 {
205 // fix coordinate d to zero
206 Shape endCA(shape);
207 endCA[d] = 1;
208 volumeBorderBlocks_.push_back(Block(beginCA,endCA));
209 }
210 {
211 // fix coordinate d to shape[dim]-1
212 Shape beginCB(shape);
213 beginCB[d] -= 1;
214 volumeBorderBlocks_.push_back(Block(beginCB,endCB));
215 }
216 }
217
218 insideVolBlock_.setBegin(Shape(1));
219 Shape insideVolBlockShapeEnd(shape);
220 insideVolBlockShapeEnd -= Shape(1);
221 insideVolBlock_.setEnd(insideVolBlockShapeEnd);
222 }
223
224 /// total number of blocks
225 size_t numBlocks()const{
226 return numBlocks_;
227 }
228
229 BlockWithBorderIter blockWithBorderBegin(const Shape & width)const{
230 return BlockWithBorderIter(MultiCoordIter(blocksPerAxis_),
231 CoordToBwb(*this, width));
232 }
233
234 BlockWithBorderIter blockWithBorderEnd(const Shape & width)const{
235 const MultiCoordIter beginIter(blocksPerAxis_);
236 return BlockWithBorderIter(beginIter.getEndIterator(),
237 CoordToBwb(*this, width));
238 }
239
240 Block blockDescToBlock(const BlockDesc & desc){
241 MultiCoordIter beginIter(blocksPerAxis_);
242 beginIter+=desc;
243 return *BlockIter(beginIter,CoordToB(*this));
244 }
245 BlockIter blockBegin()const{
246 return BlockIter(MultiCoordIter(blocksPerAxis_),CoordToB(*this));
247 }
248
249
250 BlockIter blockEnd()const{
251 const MultiCoordIter beginIter(blocksPerAxis_);
252 return BlockIter(beginIter.getEndIterator(),CoordToB(*this));
253 }
254
255
256 Block blockDescToBlock(const BlockDesc & blockDesc)const{
257 MultiCoordIter iter(blocksPerAxis_);
258 iter+=blockDesc;
259 return *BlockIter(iter,CoordToB(*this));
260 }
261
262
263 /// does this block intersect with the volume border
264 bool containsVolumeBorder(const Block & block) const {
265 return !insideVolBlock_.contains(block);
266 }
267
268
269 const Shape & roiBegin()const{
270 return roiBlock_.begin();
271 }
272
273 const Shape & roiEnd()const{
274 return roiBlock_.end();
275 }
276
277 const Shape & shape()const{
278 return shape_;
279 }
280
281 const Shape & blockShape()const{
282 return blockShape_;
283 }
284
285 const Shape & blocksPerAxis()const{
286 return blocksPerAxis_;
287 }
288
289 const std::vector<Block> & volumeBorderBlocks()const{
290 return volumeBorderBlocks_;
291 }
292
293
294 std::vector<UInt32> intersectingBlocks(
295 const Shape roiBegin,
296 const Shape roiEnd
297 )const{
298 size_t i=0;
299 std::vector<UInt32> iBlocks;
300 const Block testBlock(roiBegin, roiEnd);
301 for(BlockIter iter=blockBegin(); iter!=blockEnd(); ++iter){
302 if(testBlock.intersects(*iter)){
303 iBlocks.push_back(i);
304 }
305 ++i;
306 }
307 return iBlocks;
308 }
309
310
311
312 private:
313
314 /// get a block with border
315 BlockWithBorder getBlockWithBorder(const BlockDesc & blockDesc, const Shape & width )const{
316 const Point blockStart(blockDesc * blockShape_ + roiBlock_.begin());
317 const Point blockEnd(blockStart + blockShape_);
318 const Block core = Block(blockStart, blockEnd) & roiBlock_ ;
319 Block border = core;
320 border.addBorder(width);
321 border &= Block(shape_);
322 return BlockWithBorder( core, border );
323 }
324
325 /// get a block (without any overlap)
326 Block getBlock(const BlockDesc & blockDesc)const{
327 const Point blockStart(blockDesc * blockShape_ + roiBlock_.begin());
328 const Point blockEnd(blockStart + blockShape_);
329 return Block(blockStart, blockEnd) & roiBlock_;
330 }
331
332 Shape shape_; // total shape of the input volume
333 Block roiBlock_; // ROI in which to compute filters/algorithms
334 Shape blockShape_; // shape sub-block for each thread (without border pixels)
335 Shape blocksPerAxis_; // how many blocks are on each axis
336 size_t numBlocks_; // total number of blocks
337
338
339 std::vector<Block> volumeBorderBlocks_;
340 Block insideVolBlock_;
341 };
342
343 }
344
345 #endif // VIGRA_MULTI_BLOCKING_HXX
vigra::Box::size
Vector size() const
Definition: box.hxx:232
vigra::Box::contains
bool contains(Vector const &p) const
Definition: box.hxx:314
vigra::MultiBlocking::numBlocks
size_t numBlocks() const
total number of blocks
Definition: multi_blocking.hxx:225
vigra::Box::end
Vector const & end() const
Definition: box.hxx:163
vigra::MultiBlocking
Definition: multi_blocking.hxx:49
vigra::Box::begin
Vector const & begin() const
Definition: box.hxx:143
vigra::Box< PointValue, DIM >
vigra::operator!=
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
vigra::operator==
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
vigra::Box::setEnd
void setEnd(Vector const &end)
Definition: box.hxx:190
vigra::TinyVector
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
vigra::MultiBlocking::containsVolumeBorder
bool containsVolumeBorder(const Block &block) const
does this block intersect with the volume border
Definition: multi_blocking.hxx:264
vigra::Box::setBegin
void setBegin(Vector const &begin)
Definition: box.hxx:182
vigra::Box::addBorder
void addBorder(VALUETYPE borderWidth)
Definition: box.hxx:260
vigra::MultiCoordinateIterator
Iterate over a virtual array where each element contains its coordinate.
Definition: multi_fwd.hxx:157

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