SMIL  0.9.1
DMorphoGeodesic.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_GEODESIC_HPP
31 #define _D_MORPHO_GEODESIC_HPP
32 
33 #include "DMorphImageOperations.hpp"
34 #include "DMorphoHierarQ.hpp"
35 #include "Base/include/private/DImageDraw.hpp"
36 #include "Base/include/private/DImageHistogram.hpp"
37 #include "Morpho/include/private/DMorphoBase.hpp"
38 
39 namespace smil
40 {
47  // Geodesy
48 
52  template <class T>
53  RES_T geoDil(const Image<T> &imIn, const Image<T> &imMask, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
54  {
55  ASSERT_ALLOCATED(&imIn, &imMask, &imOut);
56  ASSERT_SAME_SIZE(&imIn, &imMask, &imOut);
57 
58  ImageFreezer freeze(imOut);
59 
60  ASSERT((inf(imIn, imMask, imOut)==RES_OK));
61  StrElt tmpSE(se(1));
62 
63  for (UINT i=0;i<se.size;i++)
64  {
65  ASSERT((dilate<T>(imOut, imOut, tmpSE)==RES_OK));
66  ASSERT((inf(imOut, imMask, imOut)==RES_OK));
67  }
68  return RES_OK;
69  }
70 
74  template <class T>
75  RES_T geoEro(const Image<T> &imIn, const Image<T> &imMask, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
76  {
77  ASSERT_ALLOCATED(&imIn, &imMask, &imOut);
78  ASSERT_SAME_SIZE(&imIn, &imMask, &imOut);
79 
80  ImageFreezer freeze(imOut);
81 
82  ASSERT((sup(imIn, imMask, imOut)==RES_OK));
83  StrElt tmpSE(se(1));
84 
85  for (UINT i=0;i<se.size;i++)
86  {
87  ASSERT((erode(imOut, imOut, tmpSE)==RES_OK));
88  ASSERT((sup(imOut, imMask, imOut)==RES_OK));
89  }
90  return RES_OK;
91  }
92 
93  template <class T>
94  RES_T geoBuild(const Image<T> &imIn, const Image<T> &imMask, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
95  {
96  ASSERT_ALLOCATED(&imIn, &imMask, &imOut);
97  ASSERT_SAME_SIZE(&imIn, &imMask, &imOut);
98 
99  ImageFreezer freeze(imOut);
100 
101  ASSERT((inf(imIn, imMask, imOut)==RES_OK));
102 
103  double vol1 = vol(imOut), vol2;
104  while (true)
105  {
106  ASSERT((dilate<T>(imOut, imOut, se)==RES_OK));
107  ASSERT((inf(imOut, imMask, imOut)==RES_OK));
108  vol2 = vol(imOut);
109  if (vol2==vol1)
110  break;
111  vol1 = vol2;
112  }
113  return RES_OK;
114  }
115 
116  template <class T>
117  RES_T geoDualBuild(const Image<T> &imIn, const Image<T> &imMask, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
118  {
119  ASSERT_ALLOCATED(&imIn, &imMask, &imOut);
120  ASSERT_SAME_SIZE(&imIn, &imMask, &imOut);
121 
122  ImageFreezer freeze(imOut);
123 
124  ASSERT((sup(imIn, imMask, imOut)==RES_OK));
125 
126  double vol1 = vol(imOut), vol2;
127 
128  while (true)
129  {
130  ASSERT((erode(imOut, imOut, se)==RES_OK));
131  ASSERT((sup(imOut, imMask, imOut)==RES_OK));
132  vol2 = vol(imOut);
133  if (vol2==vol1)
134  break;
135  vol1 = vol2;
136  }
137  return RES_OK;
138  }
139 
140 
141 
142 
143 
144 
145  template <class T>
146  RES_T initBuildHierarchicalQueue(const Image<T> &imIn, HierarchicalQueue<T> &hq)
147  {
148  // Initialize the priority queue
149  hq.initialize(imIn);
150 
151  typename ImDtTypes<T>::lineType inPixels = imIn.getPixels();
152 
153  size_t s[3];
154 
155  imIn.getSize(s);
156  size_t offset = 0;
157 
158  for (size_t i=0;i<imIn.getPixelCount();i++)
159  {
160  hq.push(*inPixels, offset);
161  inPixels++;
162  offset++;
163  }
164 
165  // hq.printSelf();
166  return RES_OK;
167  }
168 
169  template <class T>
170  RES_T initBuildHierarchicalQueue(const Image<T> &imIn, HierarchicalQueue<T> &hq, const T noPushValue)
171  {
172  // Initialize the priority queue
173  hq.initialize(imIn);
174 
175  typename ImDtTypes<T>::lineType inPixels = imIn.getPixels();
176 
177  size_t s[3];
178 
179  imIn.getSize(s);
180  size_t offset = 0;
181 
182  for (size_t i=0;i<imIn.getPixelCount();i++)
183  {
184 
185  if (*inPixels != noPushValue) {
186  hq.push(*inPixels, offset);
187  }
188  inPixels++;
189  offset++;
190  }
191 
192  // hq.printSelf();
193  return RES_OK;
194  }
195 
196 
197 
198  template <class T, class operatorT>
199  RES_T processBuildHierarchicalQueue(Image<T> &imIn, const Image<T> &imMask, Image<UINT8> &imStatus, HierarchicalQueue<T> &hq, const StrElt &se)
200  {
201  typename ImDtTypes<T>::lineType inPixels = imIn.getPixels();
202  typename ImDtTypes<T>::lineType markPixels = imMask.getPixels();
203  typename ImDtTypes<UINT8>::lineType statPixels = imStatus.getPixels();
204 
205  vector<int> dOffsets;
206  operatorT oper;
207 
208  vector<IntPoint>::const_iterator it_start = se.points.begin();
209  vector<IntPoint>::const_iterator it_end = se.points.end();
210  vector<IntPoint>::const_iterator it;
211 
212  vector<size_t> tmpOffsets;
213 
214  size_t s[3];
215  imIn.getSize(s);
216 
217  // set an offset distance for each se point
218  for(it=it_start;it!=it_end;it++)
219  {
220  dOffsets.push_back(it->x + it->y*s[0] + it->z*s[0]*s[1]);
221  }
222 
223  vector<int>::iterator it_off_start = dOffsets.begin();
224  vector<int>::iterator it_off;
225 
226  size_t x0, y0, z0;
227  size_t curOffset;
228 
229  int x, y, z;
230  size_t nbOffset;
231  UINT8 nbStat;
232 
233  while(!hq.isEmpty())
234  {
235 
236  curOffset = hq.pop();
237 
238  // Give the point the label "FINAL" in the status image
239  statPixels[curOffset] = HQ_FINAL;
240 
241  imIn.getCoordsFromOffset(curOffset, x0, y0, z0);
242 
243 
244  bool oddLine = se.odd && (y0)%2;
245 
246  for(it=it_start,it_off=it_off_start;it!=it_end;it++,it_off++)
247  if (it->x!=0 || it->y!=0 || it->z!=0) // useless if x=0 & y=0 & z=0
248  {
249 
250  x = x0 + it->x;
251  y = y0 + it->y;
252  z = z0 + it->z;
253 
254  if (oddLine)
255  x += ((y+1)%2!=0);
256 
257  if (x>=0 && x<(int)s[0] && y>=0 && y<(int)s[1] && z>=0 && z<(int)s[2])
258  {
259  nbOffset = curOffset + *it_off;
260 
261  if (oddLine)
262  nbOffset += ((y+1)%2!=0);
263 
264  nbStat = statPixels[nbOffset];
265 
266  if (nbStat==HQ_CANDIDATE)
267  {
268  inPixels[nbOffset] = oper(inPixels[curOffset], markPixels[nbOffset]);
269  statPixels[nbOffset] = HQ_QUEUED;
270  hq.push(inPixels[nbOffset], nbOffset);
271  }
272 
273  }
274  }
275 
276  }
277  return RES_OK;
278  }
279 
280  template <class T>
281  struct minFunctor
282  {
283  inline T operator()(T a, T b) { return min(a, b); }
284  };
285 
286  template <class T>
287  struct maxFunctor
288  {
289  inline T operator()(T a, T b) { return max(a, b); }
290  };
291 
295  template <class T>
296  RES_T dualBuild(const Image<T> &imIn, const Image<T> &imMask, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
297  {
298 // if (isBinary(imIn) && isBinary(imMask))
299 // return dualBinBuild(imIn, imMask, imOut, se);
300 
301  ASSERT_ALLOCATED(&imIn, &imMask, &imOut);
302  ASSERT_SAME_SIZE(&imIn, &imMask, &imOut);
303 
304  ImageFreezer freeze(imOut);
305 
306  Image<UINT8> imStatus(imIn);
308 
309  // Make sure that imIn >= imMask
310  ASSERT((sup(imIn, imMask, imOut)==RES_OK));
311 
312  // Set all pixels in the status image to CANDIDATE
313  ASSERT((fill(imStatus, (UINT8)HQ_CANDIDATE)==RES_OK));
314 
315  // Initialize the PQ
316  initBuildHierarchicalQueue(imOut, pq);
317  processBuildHierarchicalQueue<T, maxFunctor<T> >(imOut, imMask, imStatus, pq, se);
318 
319  return RES_OK;
320  }
321 
325  template <class T>
326  RES_T build(const Image<T> &imIn, const Image<T> &imMask, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
327  {
328  if (isBinary(imIn) && isBinary(imMask))
329  return binBuild(imIn, imMask, imOut, se);
330 
331  ASSERT_ALLOCATED(&imIn, &imMask, &imOut);
332  ASSERT_SAME_SIZE(&imIn, &imMask, &imOut);
333 
334  ImageFreezer freeze(imOut);
335 
336  Image<UINT8> imStatus(imIn);
337 
338  // Reverse hierarchical queue (the highest token corresponds to the highest gray value)
339  HierarchicalQueue<T> rpq(true);
340 
341  // Make sure that imIn <= imMask
342  ASSERT((inf(imIn, imMask, imOut)==RES_OK));
343 
344  // Set all pixels in the status image to CANDIDATE
345  ASSERT((fill(imStatus, (UINT8)HQ_CANDIDATE)==RES_OK));
346 
347  // Initialize the PQ
348  initBuildHierarchicalQueue(imOut, rpq);
349  processBuildHierarchicalQueue<T, minFunctor<T> >(imOut, imMask, imStatus, rpq, se);
350 
351  return RES_OK;
352  }
353 
357  template <class T>
358  RES_T binBuild(const Image<T> &imIn, const Image<T> &imMask, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
359  {
360  ASSERT_ALLOCATED(&imIn, &imMask, &imOut);
361  ASSERT_SAME_SIZE(&imIn, &imMask, &imOut);
362  // T noPushValue = NUMERIC_LIMITS<T>::min();
363  //T maxValue = NUMERIC_LIMITS<T>::max();
364  ImageFreezer freeze(imOut);
365 
366  Image<UINT8> imStatus(imIn);
367 
368  // Reverse hierarchical queue (the highest token corresponds to the highest gray value)
369  HierarchicalQueue<T> rpq(true);
370 
371  // Make sure that imIn <= imMask
372  ASSERT((inf(imIn, imMask, imOut)==RES_OK));
373 
374  // make a status image with all foreground pixels as CANDIDATE, otherwise as FINAL
375  ASSERT(test(imMask, (UINT8)HQ_CANDIDATE, (UINT8)HQ_FINAL, imStatus)==RES_OK);
376 
377  // Initialize the PQ
378  initBuildHierarchicalQueue(imOut, rpq, imOut.getDataTypeMin());
379  processBuildHierarchicalQueue<T, minFunctor<T> >(imOut, imMask, imStatus, rpq, se);
380 
381  return RES_OK;
382  }
383 
384 // /**
385 // * Reconstruction (using hierarchical queues).
386 // */
387 // template <class T>
388 // RES_T dualBinBuild(const Image<T> &imIn, const Image<T> &imMask, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
389 // {
390 // ASSERT_ALLOCATED(&imIn, &imMask, &imOut);
391 // ASSERT_SAME_SIZE(&imIn, &imMask, &imOut);
392 // // T noPushValue = NUMERIC_LIMITS<T>::min();
393 // //T maxValue = NUMERIC_LIMITS<T>::max();
394 // ImageFreezer freeze(imOut);
395 //
396 // Image<UINT8> imStatus(imIn);
397 //
398 // HierarchicalQueue<T> rpq;
399 //
400 // // Make sure that imIn >= imMask
401 // ASSERT((sup(imIn, imMask, imOut)==RES_OK));
402 //
403 // // make a status image with all background pixels as CANDIDATE, otherwise as FINAL
404 // ASSERT(test(imMask, (UINT8)HQ_FINAL, (UINT8)HQ_CANDIDATE, imStatus)==RES_OK);
405 //
406 // // Initialize the PQ
407 // initBuildHierarchicalQueue(imOut, rpq, imOut.getDataTypeMin());
408 // processBuildHierarchicalQueue<T, maxFunctor<T> >(imOut, imMask, imStatus, rpq, se);
409 //
410 // return RES_OK;
411 // }
412 
413 
419  template <class T>
420  RES_T hBuild(const Image<T> &imIn, const T &height, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
421  {
422  ASSERT_ALLOCATED(&imIn, &imOut);
423  ASSERT_SAME_SIZE(&imIn, &imOut);
424 
425  if (&imIn==&imOut)
426  {
427  Image<T> tmpIm = imIn;
428  return hBuild(tmpIm, height, imOut, se);
429  }
430 
431  ImageFreezer freeze(imOut);
432 
433  ASSERT((sub(imIn, T(height), imOut)==RES_OK));
434  ASSERT((build(imOut, imIn, imOut, se)==RES_OK));
435 
436  return RES_OK;
437  }
438 
444  template <class T>
445  RES_T hDualBuild(const Image<T> &imIn, const T &height, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
446  {
447  ASSERT_ALLOCATED(&imIn, &imOut);
448  ASSERT_SAME_SIZE(&imIn, &imOut);
449 
450  if (&imIn==&imOut)
451  {
452  Image<T> tmpIm = imIn;
453  return hDualBuild(tmpIm, height, imOut, se);
454  }
455 
456  ImageFreezer freeze(imOut);
457 
458  ASSERT((add(imIn, T(height), imOut)==RES_OK));
459  ASSERT((dualBuild(imOut, imIn, imOut, se)==RES_OK));
460 
461  return RES_OK;
462  }
463 
469  template <class T>
470  RES_T buildOpen(const Image<T> &imIn, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
471  {
472  ASSERT_ALLOCATED(&imIn, &imOut);
473  ASSERT_SAME_SIZE(&imIn, &imOut);
474 
475  ImageFreezer freeze(imOut);
476 
477  Image<T> tmpIm(imIn);
478  ASSERT((erode(imIn, tmpIm, se)==RES_OK));
479  ASSERT((build(tmpIm, imIn, imOut, se)==RES_OK));
480 
481  return RES_OK;
482  }
483 
487  template <class T>
488  RES_T buildClose(const Image<T> &imIn, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
489  {
490  ASSERT_ALLOCATED(&imIn, &imOut);
491  ASSERT_SAME_SIZE(&imIn, &imOut);
492 
493  ImageFreezer freeze(imOut);
494 
495  Image<T> tmpIm(imIn);
496  ASSERT((dilate(imIn, tmpIm, se)==RES_OK));
497  ASSERT((dualBuild(tmpIm, imIn, imOut, se)==RES_OK));
498 
499  return RES_OK;
500  }
501 
505  template <class T>
506  RES_T fillHoles(const Image<T> &imIn, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
507  {
508  ASSERT_ALLOCATED(&imIn, &imOut);
509  ASSERT_SAME_SIZE(&imIn, &imOut);
510 
511  ImageFreezer freeze(imOut);
512 
513  Image<T> tmpIm(imIn);
514 
515  ASSERT((fill(tmpIm, numeric_limits<T>::max())==RES_OK));
516  ASSERT((drawRectangle(tmpIm, 0, 0, tmpIm.getWidth(), tmpIm.getHeight(), ImDtTypes<T>::min())==RES_OK));
517  ASSERT((dualBuild(tmpIm, imIn, imOut, se)==RES_OK));
518 
519  return RES_OK;
520  }
521 
525  template <class T>
526  RES_T levelPics(const Image<T> &imIn, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
527  {
528  ASSERT_ALLOCATED(&imIn, &imOut);
529  ASSERT_SAME_SIZE(&imIn, &imOut);
530 
531  ImageFreezer freeze(imOut);
532 
533  Image<T> tmpIm(imIn);
534  ASSERT((inv(imIn, tmpIm)==RES_OK));
535  ASSERT((fillHoles(tmpIm, imOut, se)==RES_OK));
536  ASSERT((inv(imOut, imOut)==RES_OK));
537 
538  // return res;
539  return RES_OK;
540  }
541 
542 
545 } // namespace smil
546 
547 
548 
549 #endif // _D_MORPHO_GEODESIC_HPP
550 
RES_T build(const Image< T > &imIn, const Image< T > &imMask, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Reconstruction (using hierarchical queues).
Definition: DMorphoGeodesic.hpp:326
RES_T geoEro(const Image< T > &imIn, const Image< T > &imMask, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Geodesic erosion.
Definition: DMorphoGeodesic.hpp:75
RES_T dilate(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE, T borderVal=ImDtTypes< T >::min())
Morphological grayscale dilation.
Definition: DMorphoBase.hpp:65
Definition: DColorConvert.h:38
RES_T sub(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Subtraction.
Definition: DImageArith.hpp:446
Definition: DBaseImage.h:235
double vol(const Image< T > &imIn)
Volume of an image.
Definition: DMeasures.hpp:96
vector< IntPoint > points
List of neighbor points.
Definition: DStructuringElement.h:125
RES_T drawRectangle(Image< T > &imOut, int x0, int y0, size_t width, size_t height, T value=ImDtTypes< T >::max(), bool fill=false, size_t zSlice=0)
Draw a rectangle.
Definition: DImageDraw.hpp:113
RES_T levelPics(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Dual hole filling.
Definition: DMorphoGeodesic.hpp:526
RES_T fillHoles(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Hole filling.
Definition: DMorphoGeodesic.hpp:506
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:110
RES_T inv(const Image< T > &imIn, Image< T > &imOut)
Invert an image.
Definition: DImageArith.hpp:375
bool isBinary(const Image< T > &imIn)
Test if an image is binary.
Definition: DMeasures.hpp:777
RES_T hDualBuild(const Image< T > &imIn, const T &height, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Dual h-Reconstuction.
Definition: DMorphoGeodesic.hpp:445
RES_T fill(Image< T > &imOut, const T &value)
Fill an image with a given value.
Definition: DImageArith.hpp:62
RES_T buildOpen(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Opening by reconstruction.
Definition: DMorphoGeodesic.hpp:470
RES_T sup(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Sup of two images.
Definition: DImageArith.hpp:505
RES_T add(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Addition.
Definition: DImageArith.hpp:393
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:91
RES_T hBuild(const Image< T > &imIn, const T &height, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Reconstruction (using hierarchical queues).
Definition: DMorphoGeodesic.hpp:420
Base structuring element.
Definition: DStructuringElement.h:51
Definition: DMorphoGeodesic.hpp:287
RES_T buildClose(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Closing by reconstruction.
Definition: DMorphoGeodesic.hpp:488
RES_T geoDil(const Image< T > &imIn, const Image< T > &imMask, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Geodesic dilation.
Definition: DMorphoGeodesic.hpp:53
Definition: DMorphoGeodesic.hpp:281
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:87
size_t getPixelCount() const
Get the number of pixels.
Definition: DBaseImage.h:150
RES_T binBuild(const Image< T > &imIn, const Image< T > &imMask, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Reconstruction (using hierarchical queues).
Definition: DMorphoGeodesic.hpp:358
Definition: DTypes.hpp:78
RES_T dualBuild(const Image< T > &imIn, const Image< T > &imMask, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Dual reconstruction (using hierarchical queues).
Definition: DMorphoGeodesic.hpp:296
Main Image class.
Definition: DQVtkViewer.hpp:44
RES_T erode(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE, T borderVal=ImDtTypes< T >::max())
Morphological grayscale erosion.
Definition: DMorphoBase.hpp:101
RES_T inf(const Image< T > &imIn1, const T &value, Image< T > &imOut)
Inf of two images.
Definition: DImageArith.hpp:538
void getCoordsFromOffset(size_t off, size_t &x, size_t &y, size_t &z) const
Get x,y(,z) coordinates for a given offset.
Definition: DBaseImage.h:182
RES_T test(const Image< T1 > &imIn1, const Image< T2 > &imIn2, const Image< T2 > &imIn3, Image< T2 > &imOut)
Test.
Definition: DImageArith.hpp:920