SMIL  0.9.1
DMorphoArrow.hpp
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 
30 #ifndef _D_MORPHO_ARROW_HPP
31 #define _D_MORPHO_ARROW_HPP
32 
33 #include "DMorphImageOperations.hpp"
34 #include "DMorphoHierarQ.hpp"
35 
36 namespace smil
37 {
45  template <class T_in, class lineFunction_T, class T_out=T_in>
46  class unaryMorphArrowImageFunction : public MorphImageFunction<T_in, lineFunction_T, T_out>
47  {
48  public:
50 
51  typedef Image<T_in> imageInType;
52  typedef typename ImDtTypes<T_in>::lineType lineInType;
53  typedef typename ImDtTypes<T_in>::sliceType sliceInType;
54  typedef typename ImDtTypes<T_in>::volType volInType;
55 
56  typedef Image<T_out> imageOutType;
57  typedef typename ImDtTypes<T_out>::lineType lineOutType;
58  typedef typename ImDtTypes<T_out>::sliceType sliceOutType;
59  typedef typename ImDtTypes<T_out>::volType volOutType;
60 
61  unaryMorphArrowImageFunction(T_in border=numeric_limits<T_in>::min(), T_out /*_initialValue*/ = ImDtTypes<T_out>::min())
63  {
64  }
65  virtual RES_T _exec_single(const imageInType &imIn, imageOutType &imOut, const StrElt &se);
66  };
67 
68 
69  template <class T_in, class lineFunction_T, class T_out>
71  {
72  ASSERT_ALLOCATED(&imIn);
73  ASSERT_SAME_SIZE(&imIn, &imOut);
74 
75  if ((void*)&imIn==(void*)&imOut)
76  {
77  Image<T_in> tmpIm = imIn;
78  return _exec_single(tmpIm, imOut, se);
79  }
80 
81  if (!areAllocated(&imIn, &imOut, NULL))
82  return RES_ERR_BAD_ALLOCATION;
83 
84  UINT sePtsNumber = se.points.size();
85  if (sePtsNumber==0)
86  return RES_OK;
87 
88  size_t nSlices = imIn.getSliceCount();
89  size_t nLines = imIn.getHeight();
90 
91  this->initialize(imIn, imOut, se);
92  this->lineLen = imIn.getWidth();
93 
94 
95  volInType srcSlices = imIn.getSlices();
96  volOutType destSlices = imOut.getSlices();
97 
98  int nthreads = Core::getInstance()->getNumberOfThreads();
99  typename ImDtTypes<T_in>::vectorType vec(this->lineLen);
100  typename ImDtTypes<T_in>::matrixType bufsIn(nthreads, typename ImDtTypes<T_in>::vectorType(this->lineLen));
101  typename ImDtTypes<T_out>::matrixType bufsOut(nthreads, typename ImDtTypes<T_out>::vectorType(this->lineLen));
102 
103  size_t l;
104 
105  for (size_t s=0;s<nSlices;s++)
106  {
107  lineInType *srcLines = srcSlices[s];
108  lineOutType *destLines = destSlices[s];
109 
110  #ifdef USE_OPEN_MP
111  #pragma omp parallel num_threads(nthreads)
112  #endif
113  {
114 
115  bool oddSe = se.odd, oddLine = 0;
116 
117  size_t x, y, z;
118  lineFunction_T arrowLineFunction;
119 
120  int tid = 0;
121 
122  #ifdef USE_OPEN_MP
123  tid = omp_get_thread_num();
124  #endif // _OPENMP
125  lineInType tmpBuf = bufsIn[tid].data();
126  lineOutType tmpBuf2 = bufsOut[tid].data();
127 
128  #ifdef USE_OPEN_MP
129  #pragma omp for
130  #endif // USE_OPEN_MP
131  for (l=0;l<nLines;l++)
132  {
133  lineInType lineIn = srcLines[l];
134  lineOutType lineOut = destLines[l];
135 
136  oddLine = oddSe && l%2;
137 
138  fillLine<T_out>(tmpBuf2, this->lineLen, T_out(0));
139 
140  for (UINT p=0;p<sePtsNumber;p++)
141  {
142  y = l + se.points[p].y;
143  x = - se.points[p].x - (oddLine && (y+1)%2);
144  z = s + se.points[p].z;
145 
146  arrowLineFunction.trueVal = (1UL << p);
147  this->_extract_translated_line(&imIn, x, y, z, tmpBuf);
148  arrowLineFunction._exec(lineIn, tmpBuf, this->lineLen, tmpBuf2);
149  }
150  copyLine<T_out>(tmpBuf2, this->lineLen, lineOut);
151  }
152  } // pragma omp parallel
153  }
154 
155  imOut.modified();
156 
157  return RES_OK;
158  }
159 
160 
161  template <class T_in, class T_out>
162  RES_T arrowLow(const Image<T_in> &imIn, Image<T_out> &imOut, const StrElt &se=DEFAULT_SE, T_in borderValue=numeric_limits<T_in>::min())
163  {
165  return iFunc(imIn, imOut, se);
166  }
167 
168  template <class T_in, class T_out>
169  RES_T arrowLowOrEqu(const Image<T_in> &imIn, Image<T_out> &imOut, const StrElt &se=DEFAULT_SE, T_in borderValue=numeric_limits<T_in>::min())
170  {
172  return iFunc(imIn, imOut, se);
173  }
174 
175  template <class T_in, class T_out>
176  RES_T arrowGrt(const Image<T_in> &imIn, Image<T_out> &imOut, const StrElt &se=DEFAULT_SE, T_in borderValue=numeric_limits<T_in>::min())
177  {
179  return iFunc(imIn, imOut, se);
180  }
181 
182  template <class T_in, class T_out>
183  RES_T arrowGrtOrEqu(const Image<T_in> &imIn, Image<T_out> &imOut, const StrElt &se=DEFAULT_SE, T_in borderValue=numeric_limits<T_in>::min())
184  {
186  return iFunc(imIn, imOut, se);
187  }
188 
189  template <class T_in, class T_out>
190  RES_T arrowEqu(const Image<T_in> &imIn, Image<T_out> &imOut, const StrElt &se=DEFAULT_SE, T_in borderValue=numeric_limits<T_in>::min())
191  {
193  return iFunc(imIn, imOut, se);
194  }
195 
205  template <class T_in, class T_out>
206  RES_T arrow(const Image<T_in> &imIn, const char *operation, Image<T_out> &imOut, const StrElt &se=DEFAULT_SE, T_in borderValue=numeric_limits<T_in>::min())
207  {
208  if (strcmp(operation, "==")==0)
209  return arrowEqu(imIn, imOut, se, borderValue);
210  else if (strcmp(operation, ">")==0)
211  return arrowGrt(imIn, imOut, se, borderValue);
212  else if (strcmp(operation, ">=")==0)
213  return arrowGrtOrEqu(imIn, imOut, se, borderValue);
214  else if (strcmp(operation, "<")==0)
215  return arrowLow(imIn, imOut, se, borderValue);
216  else if (strcmp(operation, "<=")==0)
217  return arrowLowOrEqu(imIn, imOut, se, borderValue);
218 
219  else return RES_ERR;
220  }
221 
226  template <class arrowT, class statutT, class outT, class containerType = STD_Queue<size_t> >
228 
229  protected:
230  containerType q;
231 
232  virtual bool testAndAssign (statutT &/*pS*/, outT &pO)
233  {
234  if (pO != propagationValue)
235  {
236  // pS = numeric_limits<statutT>::max();
237  pO = propagationValue;
238  return true;
239  }
240  return false;
241  }
242 
243  public:
244  outT propagationValue;
245 
246  typedef Image<arrowT> arrowIT;
247  typedef Image<statutT> statutIT;
248  typedef Image<outT> outIT;
249  typedef typename arrowIT::lineType arrowLT;
250  typedef typename statutIT::lineType statutLT;
251  typedef typename outIT::lineType outLT;
252 
253  arrowPropagate () {}
254  virtual ~arrowPropagate () {}
255 
256  RES_T _exec ( const Image<arrowT> &imArrow, Image<statutT> &imStatut, Image<outT> &imOut, const StrElt &se, const size_t &offset )
257  {
258  arrowLT arrowP = imArrow.getPixels ();
259  statutLT statutP = imStatut.getPixels ();
260  outLT outP = imOut.getPixels ();
261 
262  bool oddLine;
263  size_t size[3]; imArrow.getSize (size);
264  UINT sePtsNumber = se.points.size ();
265 
266  size_t x, x0, y, y0, z, z0;
267  arrowT arrow;
268 
269  size_t o, nb_o;
270 
271  q.push (offset);
272  do
273  {
274  o = q.front();
275  q.pop();
276  z0 = o / (size[1] * size[0]);
277  y0 = (o % (size[1]*size[0])) / size[0];
278  x0 = o % size[0];
279  oddLine = se.odd && y0%2;
280 
281  for (UINT p=0; p<sePtsNumber; ++p)
282  {
283  arrow = (1UL << p);
284  if (arrowP[o] & arrow)
285  {
286  x = x0 + se.points[p].x;
287  y = y0 + se.points[p].y;
288  z = z0 + se.points[p].z;
289  if (oddLine)
290  x += (y+1)%2;
291  nb_o = x + y*size[0] + z*size[1]*size[0];
292  if ( x < size[0] &&
293  y < size[1] &&
294  z < size[2])
295  if (testAndAssign (statutP[nb_o], outP[nb_o]))
296  q.push(nb_o);
297  }
298  }
299 
300  } while (!q.empty());
301  return RES_OK;
302  }
303  inline RES_T operator ()( const Image<arrowT> &imArrow, Image<statutT> &imStatut, Image<outT> &imOut, const StrElt &se, const size_t &offset )
304  {
305  return _exec (imArrow, imStatut, imOut, se, offset);
306  }
307  inline RES_T operator ()(const Image<arrowT> &imArrow, Image<outT> &imOut, const StrElt &se, const size_t &offset)
308  {
309  return _exec (imArrow, imOut, imOut, se, offset);
310  }
311  };
312 
313  template < class T1, class T2, class T_out=T2>
314  struct equSupLine3:public binaryLineFunctionBase < T1, T2, T_out>
315  {
316  equSupLine3 () :
317  trueVal ( ImDtTypes < T_out >::max ( ) ), falseVal ( 0 ) {}
318 
319  T_out trueVal, falseVal;
320 
322  typedef typename parentClass::lineType1 lineType1;
323  typedef typename parentClass::lineType2 lineType2;
324  typedef typename parentClass::lineOutType lineOutType;
325 
326  inline void operator () (const lineType1 lIn1,
327  const lineType2 lIn2,
328  const size_t size, lineOutType lOut )
329  {
330  return _exec ( lIn1, lIn2, size, lOut );
331  }
332  virtual void _exec ( const lineType1 lIn1,
333  const lineType2 lIn2,
334  const size_t size, lineOutType lOut )
335  {
336  T_out _trueVal ( trueVal ), _falseVal ( falseVal );
337 
338  for (size_t i = 0; i < size; i++)
339  {
340  lOut[i] += ( lIn1[i] == lIn2[i] ) ? _trueVal : _falseVal;
341  }
342  }
343  };
344 
345 
346  template < class T, class arrowT = UINT8 >
347  class arrowMinFunction : public MorphImageFunctionBase<T, arrowT>
348  {
349  public:
351 
352  typedef typename parentClass::imageInType imageInType;
353  typedef typename imageInType::lineType lineInType;
354  typedef typename imageInType::lineType sliceInType;
355  typedef typename imageInType::volType volInType;
356 
357  typedef typename parentClass::imageOutType imageArrowType;
358  typedef typename imageArrowType::lineType lineArrowType;
359  typedef typename imageArrowType::sliceType sliceArrowType;
360  typedef typename imageArrowType::volType volArrowType;
361 
362  arrowMinFunction ( T border = numeric_limits < T >::max ( ) ):borderValue ( border ), MorphImageFunctionBase < T, arrowT > ( )
363  {
364  }
365 
366  virtual RES_T _exec ( const imageInType & in,
367  imageArrowType & imOut, const StrElt & se );
368  private:
369  T borderValue;
370  size_t lineLen;
371 
372  };
373 
374 template < class T, class arrowT >
377  const StrElt & se )
378 {
379 
380  ASSERT_ALLOCATED ( &in, &arrow );
381  ASSERT_SAME_SIZE ( &in, &arrow );
382 
383  if ( !areAllocated ( &in, &arrow, NULL ) )
384  return RES_ERR_BAD_ALLOCATION;
385 
386  UINT sePtsNumber = se.points.size ( );
387 
388  if ( sePtsNumber == 0 )
389  return RES_OK;
390 
391  size_t nSlices = in.getSliceCount ( );
392  size_t nLines = in.getHeight ( );
393 
394  lineLen = in.getWidth ( );
395 
396  volInType srcSlices = in.getSlices ( );
397  volArrowType destSlices = arrow.getSlices ( );
398  lineInType *srcLines;
399  lineArrowType *destLines;
400 
401  bool oddSe = se.odd, oddLine = 0;
402 
403  #ifdef USE_OPEN_MP
404  #pragma omp parallel private(oddLine)
405  #endif // USE_OPEN_MP
406  {
407  T* borderBuf = ImDtTypes < T >::createLine ( lineLen );
408  T* cpBuf = ImDtTypes < T >::createLine ( lineLen );
409  T* minBuf = ImDtTypes < T >::createLine ( lineLen );
410  T* nullBuf = ImDtTypes < T >::createLine ( lineLen );
411  T* flagBuf = ImDtTypes < T >::createLine ( lineLen );
416 
417  fillLine < T > ( nullBuf, lineLen, arrowT ( 0 ) );
418  fillLine < T > ( borderBuf, lineLen, T ( borderValue ) );
419 
420  lineInType lineIn;
421  lineArrowType lineArrow;
422  size_t x, y, z;
423 
424  for ( size_t s = 0; s < nSlices; ++s )
425  {
426  srcLines = srcSlices[s];
427  destLines = destSlices[s];
428 
429  #ifdef USE_OPEN_MP
430  #pragma omp for
431  #endif // USE_OPEN_MP
432  for ( size_t l = 0; l < nLines; ++l )
433  {
434  oddLine = oddSe && l %2;
435 
436  lineIn = srcLines[l];
437  lineArrow = destLines[l];
438 
439  fillLine < arrowT > ( lineArrow, lineLen, arrowT ( 0 ) );
440  copyLine < T > ( lineIn, lineLen, minBuf );
441 
442  for ( UINT p = 0; p < sePtsNumber; ++p )
443  {
444  y = l + se.points[p].y;
445  x = -se.points[p].x - (oddLine && (y+1)%2);
446  z = s + se.points[p].z;
447 
448  _equSup.trueVal = ( 1UL << p );
449 
450 
451  if ( z >= nSlices || y >= nLines )
452  copyLine < T > ( borderBuf, lineLen, cpBuf );
453  else
454  shiftLine < T > ( srcLines[y], x, lineLen, cpBuf, borderValue );
455 
456  low._exec ( cpBuf, minBuf, lineLen, flagBuf );
457  inf._exec ( cpBuf, minBuf, lineLen, minBuf );
458  test._exec ( flagBuf, nullBuf, lineArrow, lineLen, lineArrow );
459  _equSup._exec ( cpBuf, minBuf, lineLen, lineArrow );
460 
461  }
462  }
463  }
464 
465  }
466 
467  return RES_OK;
468 }
469 
470  template < class T, class arrowT > RES_T arrowMin ( const Image < T > &im,
472  &arrow,
473  const StrElt & se,
474  T borderValue =
475  numeric_limits <
476  T >::max ( ) )
477  {
478  arrowMinFunction < T, arrowT > iFunc ( borderValue );
479  return iFunc ( im, arrow, se );
480  }
481 
482  template < class T, class arrowT = UINT8 >
484  {
485  public:
487  typedef typename parentClass::imageInType imageInType;
488  typedef typename imageInType::lineType lineInType;
489  typedef typename imageInType::lineType sliceInType;
490  typedef typename imageInType::volType volInType;
491  typedef typename parentClass::imageOutType imageArrowType;
492  typedef typename imageArrowType::lineType lineArrowType;
493  typedef typename imageArrowType::sliceType sliceArrowType;
494  typedef typename imageArrowType::volType volArrowType;
495 
496  arrowMinStepFunction ( T border = numeric_limits < T >::max ( ) ):borderValue ( border ), MorphImageFunctionBase < T, arrowT > ( )
497  {
498  borderValue = border;
499  }
500 
501  virtual RES_T _exec ( const imageInType & in,
502  imageArrowType & imOut, const StrElt & se );
503  private:
504  T borderValue;
505  size_t lineLen;
506 
507  };
508 
509  template < class T, class arrowT >
512  const StrElt & se )
513  {
514  ASSERT_ALLOCATED ( &in, &arrow );
515  ASSERT_SAME_SIZE ( &in, &arrow );
516 
517  if ( !areAllocated ( &in, &arrow, NULL ) )
518  return RES_ERR_BAD_ALLOCATION;
519 
520  StrElt cpSe = se.noCenter ();
521 
522  UINT sePtsNumber = cpSe.points.size ( );
523 
524  if ( sePtsNumber == 0 )
525  return RES_OK;
526 
527  size_t nSlices = in.getSliceCount ( );
528  size_t nLines = in.getHeight ( );
529  lineLen = in.getWidth ( );
530 
531  volInType srcSlices = in.getSlices ( );
532  volArrowType destSlices = arrow.getSlices ( );
533  lineInType *srcLines;
534  lineArrowType *destLines;
535 
536  bool oddSe = cpSe.odd, oddLine = 0;
537 
538  #ifdef USE_OPEN_MP
539  #pragma omp parallel private(oddLine)
540  #endif // USE_OPEN_MP
541  {
542  T* borderBuf = ImDtTypes < T >::createLine ( lineLen );
543  T* cpBuf = ImDtTypes < T >::createLine ( lineLen );
544  T* minBuf = ImDtTypes < T >::createLine ( lineLen );
545  T* nullBuf = ImDtTypes < T >::createLine ( lineLen );
546  T* flagBuf = ImDtTypes < T >::createLine ( lineLen );
552 
553  fillLine < T > ( nullBuf, lineLen, arrowT ( 0 ) );
554  fillLine < T > ( borderBuf, lineLen, T ( borderValue ) );
555  equ.trueVal = 0;
556  equ.falseVal = numeric_limits < T >::max ( );
557 
558  lineInType lineIn;
559  lineArrowType lineArrow;
560  size_t x, y, z, i;
561 
562  for ( size_t s = 0; s < nSlices; ++s )
563  {
564  srcLines = srcSlices[s];
565  destLines = destSlices[s];
566 
567  #ifdef USE_OPEN_MP
568  #pragma omp for
569  #endif // USE_OPEN_MP
570  for ( size_t l = 0; l < nLines; ++l )
571  {
572  oddLine = oddSe && l %2;
573 
574  lineIn = srcLines[l];
575  lineArrow = destLines[l];
576 
577  fillLine < arrowT > ( lineArrow, lineLen, arrowT ( 0 ) );
578  copyLine < T > ( borderBuf, lineLen, minBuf );
579 
580  for ( UINT p = 0; p < sePtsNumber; ++p )
581  {
582  y = l + cpSe.points[p].y;
583  x = -cpSe.points[p].x - (oddLine && (y+1)%2);
584  z = s + cpSe.points[p].z;
585 
586  _equSup.trueVal = ( 1UL << p );
587 
588 
589  if ( z >= nSlices || y >= nLines )
590  copyLine < T > ( borderBuf, lineLen, cpBuf );
591  else
592  shiftLine < T > ( srcLines[y], x, lineLen, cpBuf, borderValue );
593 
594  for (i=0; i<lineLen; ++i)
595  flagBuf[i] = cpBuf[i] >= lineIn[i] ? 255 : 0;
596  for (i=0; i<lineLen; ++i)
597  cpBuf[i] = flagBuf[i] ? cpBuf[i] : borderBuf[i];
598 
599  low._exec ( cpBuf, minBuf, lineLen, flagBuf );
600  inf._exec ( cpBuf, minBuf, lineLen, minBuf );
601  test._exec ( flagBuf, nullBuf, lineArrow, lineLen,
602  lineArrow );
603  _equSup._exec ( cpBuf, minBuf, lineLen, lineArrow );
604 
605  }
606  }
607  }
608  }
609 
610  return RES_OK;
611  }
612 
613  template < class T > RES_T arrowMinStep ( const Image < T > &im,
615  &arrow,
616  const StrElt & se,
617  T borderValue =
618  numeric_limits <
619  T >::max ( ) )
620  {
621  arrowMinStepFunction < T, T > iFunc ( borderValue );
622  return iFunc ( im, arrow, se );
623  }
624 
625 
628 } // namespace smil
629 
630 
631 #endif // _D_MORPHO_ARROW_HPP
632 
Definition: DMorphoArrow.hpp:483
Definition: DMorphoArrow.hpp:46
Definition: DColorConvert.h:38
Definition: DMorphImageOperations.hpp:133
vector< IntPoint > points
List of neighbor points.
Definition: DStructuringElement.h:125
RES_T equ(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Equality operator.
Definition: DImageArith.hpp:572
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:110
Definition: DMorphoArrow.hpp:347
Definition: DMorphoArrow.hpp:314
RES_T arrow(const Image< T_in > &imIn, const char *operation, Image< T_out > &imOut, const StrElt &se=DEFAULT_SE, T_in borderValue=numeric_limits< T_in >::min())
Arrow operator.
Definition: DMorphoArrow.hpp:206
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:91
Definition: DBaseImageOperations.hxx:39
RES_T low(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Lower operator.
Definition: DImageArith.hpp:692
Base structuring element.
Definition: DStructuringElement.h:51
virtual void modified()
Trigger modified event (allows to force display update)
Definition: DImage.hxx:223
Base morpho operator class.
Definition: DMorphImageOperations.hpp:54
Propagation Functor on a Arrow Image.
Definition: DMorphoArrow.hpp:227
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:87
Definition: DLineArith.hpp:262
Definition: DTypes.hpp:78
Definition: DLineArith.hpp:558
Definition: DLineArith.hpp:337
Definition: DLineArith.hpp:177
StrElt noCenter() const
Return the SE with no center.
Definition: DStructuringElement.cpp:127
Definition: DBaseLineOperations.hpp:109
RES_T inf(const Image< T > &imIn1, const T &value, Image< T > &imOut)
Inf of two images.
Definition: DImageArith.hpp:538
size_t getSliceCount() const
Get the number of slices(for 3D images)
Definition: DBaseImage.h:158
volType getSlices() const
Get an array containing the start offset of each slice.
Definition: DImage.hpp:118
RES_T test(const Image< T1 > &imIn1, const Image< T2 > &imIn2, const Image< T2 > &imIn3, Image< T2 > &imOut)
Test.
Definition: DImageArith.hpp:920