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

multi_blocking.hxx VIGRA

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>
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;
59  typedef Point Shape;
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
Vector size() const
Definition: box.hxx:232
bool contains(Vector const &p) const
Definition: box.hxx:314
size_t numBlocks() const
total number of blocks
Definition: multi_blocking.hxx:225
Vector const & end() const
Definition: box.hxx:163
Definition: multi_blocking.hxx:49
Vector const & begin() const
Definition: box.hxx:143
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
void setEnd(Vector const &end)
Definition: box.hxx:190
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
bool containsVolumeBorder(const Block &block) const
does this block intersect with the volume border
Definition: multi_blocking.hxx:264
void setBegin(Vector const &begin)
Definition: box.hxx:182
void addBorder(VALUETYPE borderWidth)
Definition: box.hxx:260
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.1 (Fri May 19 2017)