SMIL  1.0.4
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''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
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 {
44  template <class T_in, class lineFunction_T, class T_out = T_in>
46  : 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 
62  T_in border = numeric_limits<T_in>::min(),
63  T_out /*_initialValue*/ = ImDtTypes<T_out>::min())
65  {
66  }
67  virtual RES_T _exec_single(const imageInType &imIn, imageOutType &imOut,
68  const StrElt &se);
69  };
70 
71  template <class T_in, class lineFunction_T, class T_out>
73  const imageInType &imIn, imageOutType &imOut, const StrElt &se)
74  {
75  ASSERT_ALLOCATED(&imIn);
76  ASSERT_SAME_SIZE(&imIn, &imOut);
77 
78  if ((void *) &imIn == (void *) &imOut) {
79  Image<T_in> tmpIm = imIn;
80  return _exec_single(tmpIm, imOut, se);
81  }
82 
83  if (!areAllocated(&imIn, &imOut, NULL))
84  return RES_ERR_BAD_ALLOCATION;
85 
86  UINT sePtsNumber = se.points.size();
87  if (sePtsNumber == 0)
88  return RES_OK;
89 
90  size_t nSlices = imIn.getSliceCount();
91  size_t nLines = imIn.getHeight();
92 
93  this->lineLen = imIn.getWidth();
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(
101  nthreads, typename ImDtTypes<T_in>::vectorType(this->lineLen));
102  typename ImDtTypes<T_out>::matrixType bufsOut(
103  nthreads, typename ImDtTypes<T_out>::vectorType(this->lineLen));
104 
105  size_t l;
106 
107  for (size_t s = 0; s < nSlices; s++) {
108  lineInType * srcLines = srcSlices[s];
109  lineOutType *destLines = destSlices[s];
110 
111 #ifdef USE_OPEN_MP
112 #pragma omp parallel num_threads(nthreads)
113 #endif
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  lineInType lineIn = srcLines[l];
133  lineOutType lineOut = destLines[l];
134 
135  oddLine = oddSe && l % 2;
136 
137  fillLine<T_out>(tmpBuf2, this->lineLen, T_out(0));
138 
139  for (UINT p = 0; p < sePtsNumber; p++) {
140  y = l + se.points[p].y;
141  x = -se.points[p].x - (oddLine && (y + 1) % 2);
142  z = s + se.points[p].z;
143 
144  arrowLineFunction.trueVal = (1UL << p);
145  this->_extract_translated_line(&imIn, x, y, z, tmpBuf);
146  arrowLineFunction._exec(lineIn, tmpBuf, this->lineLen, tmpBuf2);
147  }
148  copyLine<T_out>(tmpBuf2, this->lineLen, lineOut);
149  }
150  } // pragma omp parallel
151  }
152 
153  imOut.modified();
154 
155  return RES_OK;
156  }
157 
158  template <class T_in, class T_out>
159  RES_T arrowLow(const Image<T_in> &imIn, Image<T_out> &imOut,
160  const StrElt &se = DEFAULT_SE,
161  T_in borderValue = numeric_limits<T_in>::min())
162  {
163  unaryMorphArrowImageFunction<T_in, lowSupLine<T_in, T_out>, T_out> iFunc(
164  borderValue);
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,
170  const StrElt &se = DEFAULT_SE,
171  T_in borderValue = numeric_limits<T_in>::min())
172  {
173  unaryMorphArrowImageFunction<T_in, lowOrEquSupLine<T_in, T_out>, T_out>
174  iFunc(borderValue);
175  return iFunc(imIn, imOut, se);
176  }
177 
178  template <class T_in, class T_out>
179  RES_T arrowGrt(const Image<T_in> &imIn, Image<T_out> &imOut,
180  const StrElt &se = DEFAULT_SE,
181  T_in borderValue = numeric_limits<T_in>::min())
182  {
183  unaryMorphArrowImageFunction<T_in, grtSupLine<T_in, T_out>, T_out> iFunc(
184  borderValue);
185  return iFunc(imIn, imOut, se);
186  }
187 
188  template <class T_in, class T_out>
189  RES_T arrowGrtOrEqu(const Image<T_in> &imIn, Image<T_out> &imOut,
190  const StrElt &se = DEFAULT_SE,
191  T_in borderValue = numeric_limits<T_in>::min())
192  {
193  unaryMorphArrowImageFunction<T_in, grtOrEquSupLine<T_in, T_out>, T_out>
194  iFunc(borderValue);
195  return iFunc(imIn, imOut, se);
196  }
197 
198  template <class T_in, class T_out>
199  RES_T arrowEqu(const Image<T_in> &imIn, Image<T_out> &imOut,
200  const StrElt &se = DEFAULT_SE,
201  T_in borderValue = numeric_limits<T_in>::min())
202  {
203  unaryMorphArrowImageFunction<T_in, equSupLine<T_in, T_out>, T_out> iFunc(
204  borderValue);
205  return iFunc(imIn, imOut, se);
206  }
207 
217  template <class T_in, class T_out>
218  RES_T arrow(const Image<T_in> &imIn, const char *operation,
219  Image<T_out> &imOut, const StrElt &se = DEFAULT_SE,
220  T_in borderValue = numeric_limits<T_in>::min())
221  {
222  if (strcmp(operation, "==") == 0)
223  return arrowEqu(imIn, imOut, se, borderValue);
224  else if (strcmp(operation, ">") == 0)
225  return arrowGrt(imIn, imOut, se, borderValue);
226  else if (strcmp(operation, ">=") == 0)
227  return arrowGrtOrEqu(imIn, imOut, se, borderValue);
228  else if (strcmp(operation, "<") == 0)
229  return arrowLow(imIn, imOut, se, borderValue);
230  else if (strcmp(operation, "<=") == 0)
231  return arrowLowOrEqu(imIn, imOut, se, borderValue);
232 
233  else
234  return RES_ERR;
235  }
236 
241  template <class arrowT, class statutT, class outT,
242  class containerType = STD_Queue<size_t>>
244  {
245  protected:
246  containerType q;
247 
248  virtual bool testAndAssign(statutT & /*pS*/, outT &pO)
249  {
250  if (pO != propagationValue) {
251  // pS = numeric_limits<statutT>::max();
252  pO = propagationValue;
253  return true;
254  }
255  return false;
256  }
257 
258  public:
259  outT propagationValue;
260 
261  typedef Image<arrowT> arrowIT;
262  typedef Image<statutT> statutIT;
263  typedef Image<outT> outIT;
264  typedef typename arrowIT::lineType arrowLT;
265  typedef typename statutIT::lineType statutLT;
266  typedef typename outIT::lineType outLT;
267 
269  {
270  }
271  virtual ~arrowPropagate()
272  {
273  }
274 
275  RES_T _exec(const Image<arrowT> &imArrow, Image<statutT> &imStatut,
276  Image<outT> &imOut, const StrElt &se, const size_t &offset)
277  {
278  arrowLT arrowP = imArrow.getPixels();
279  statutLT statutP = imStatut.getPixels();
280  outLT outP = imOut.getPixels();
281 
282  bool oddLine;
283  size_t size[3];
284  imArrow.getSize(size);
285  UINT sePtsNumber = se.points.size();
286 
287  size_t x, x0, y, y0, z, z0;
288  arrowT arrow;
289 
290  size_t o, nb_o;
291 
292  q.push(offset);
293  do {
294  o = q.front();
295  q.pop();
296  z0 = o / (size[1] * size[0]);
297  y0 = (o % (size[1] * size[0])) / size[0];
298  x0 = o % size[0];
299  oddLine = se.odd && y0 % 2;
300 
301  for (UINT p = 0; p < sePtsNumber; ++p) {
302  arrow = (1UL << p);
303  if (arrowP[o] & arrow) {
304  x = x0 + se.points[p].x;
305  y = y0 + se.points[p].y;
306  z = z0 + se.points[p].z;
307  if (oddLine)
308  x += (y + 1) % 2;
309  nb_o = x + y * size[0] + z * size[1] * size[0];
310  if (x < size[0] && y < size[1] && z < size[2])
311  if (testAndAssign(statutP[nb_o], outP[nb_o]))
312  q.push(nb_o);
313  }
314  }
315 
316  } while (!q.empty());
317  return RES_OK;
318  }
319  inline RES_T operator()(const Image<arrowT> &imArrow,
320  Image<statutT> &imStatut, Image<outT> &imOut,
321  const StrElt &se, const size_t &offset)
322  {
323  return _exec(imArrow, imStatut, imOut, se, offset);
324  }
325  inline RES_T operator()(const Image<arrowT> &imArrow, Image<outT> &imOut,
326  const StrElt &se, const size_t &offset)
327  {
328  return _exec(imArrow, imOut, imOut, se, offset);
329  }
330  };
331 
332  template <class T1, class T2, class T_out = T2>
333  struct equSupLine3 : public binaryLineFunctionBase<T1, T2, T_out> {
334  equSupLine3() : trueVal(ImDtTypes<T_out>::max()), falseVal(0)
335  {
336  }
337 
338  T_out trueVal, falseVal;
339 
341  typedef typename parentClass::lineType1 lineType1;
342  typedef typename parentClass::lineType2 lineType2;
343  typedef typename parentClass::lineOutType lineOutType;
344 
345  inline void operator()(const lineType1 lIn1, const lineType2 lIn2,
346  const size_t size, lineOutType lOut)
347  {
348  return _exec(lIn1, lIn2, size, lOut);
349  }
350  virtual void _exec(const lineType1 lIn1, const lineType2 lIn2,
351  const size_t size, lineOutType lOut)
352  {
353  T_out _trueVal(trueVal), _falseVal(falseVal);
354 
355  for (size_t i = 0; i < size; i++) {
356  lOut[i] += (lIn1[i] == lIn2[i]) ? _trueVal : _falseVal;
357  }
358  }
359  };
360 
361  template <class T, class arrowT = UINT8>
362  class arrowMinFunction : public MorphImageFunctionBase<T, arrowT>
363  {
364  public:
366 
367  typedef typename parentClass::imageInType imageInType;
368  typedef typename imageInType::lineType lineInType;
369  typedef typename imageInType::lineType sliceInType;
370  typedef typename imageInType::volType volInType;
371 
372  typedef typename parentClass::imageOutType imageArrowType;
373  typedef typename imageArrowType::lineType lineArrowType;
374  typedef typename imageArrowType::sliceType sliceArrowType;
375  typedef typename imageArrowType::volType volArrowType;
376 
377  arrowMinFunction(T border = numeric_limits<T>::max())
378  : borderValue(border), MorphImageFunctionBase<T, arrowT>()
379  {
380  }
381 
382  virtual RES_T _exec(const imageInType &in, imageArrowType &imOut,
383  const StrElt &se);
384 
385  private:
386  T borderValue;
387  size_t lineLen;
388  };
389 
390  template <class T, class arrowT>
391  RES_T arrowMinFunction<T, arrowT>::_exec(const imageInType &in,
392  imageArrowType & arrow,
393  const StrElt & se)
394  {
395  ASSERT_ALLOCATED(&in, &arrow);
396  ASSERT_SAME_SIZE(&in, &arrow);
397 
398  if (!areAllocated(&in, &arrow, NULL))
399  return RES_ERR_BAD_ALLOCATION;
400 
401  UINT sePtsNumber = se.points.size();
402 
403  if (sePtsNumber == 0)
404  return RES_OK;
405 
406  size_t nSlices = in.getSliceCount();
407  size_t nLines = in.getHeight();
408 
409  lineLen = in.getWidth();
410 
411  volInType srcSlices = in.getSlices();
412  volArrowType destSlices = arrow.getSlices();
413  lineInType * srcLines;
414  lineArrowType *destLines;
415 
416  bool oddSe = se.odd, oddLine = 0;
417 
418 #ifdef USE_OPEN_MP
419 #pragma omp parallel private(oddLine)
420 #endif // USE_OPEN_MP
421  {
422  T * borderBuf = ImDtTypes<T>::createLine(lineLen);
423  T * cpBuf = ImDtTypes<T>::createLine(lineLen);
424  T * minBuf = ImDtTypes<T>::createLine(lineLen);
425  T * nullBuf = ImDtTypes<T>::createLine(lineLen);
426  T * flagBuf = ImDtTypes<T>::createLine(lineLen);
427  lowLine<T> low;
428  infLine<T> inf;
429  testLine<T, arrowT> test;
431 
432  fillLine<T>(nullBuf, lineLen, arrowT(0));
433  fillLine<T>(borderBuf, lineLen, T(borderValue));
434 
435  lineInType lineIn;
436  lineArrowType lineArrow;
437  size_t x, y, z;
438 
439  for (size_t s = 0; s < nSlices; ++s) {
440  srcLines = srcSlices[s];
441  destLines = destSlices[s];
442 
443 #ifdef USE_OPEN_MP
444 #pragma omp for
445 #endif // USE_OPEN_MP
446  for (size_t l = 0; l < nLines; ++l) {
447  oddLine = oddSe && l % 2;
448 
449  lineIn = srcLines[l];
450  lineArrow = destLines[l];
451 
452  fillLine<arrowT>(lineArrow, lineLen, arrowT(0));
453  copyLine<T>(lineIn, lineLen, minBuf);
454 
455  for (UINT p = 0; p < sePtsNumber; ++p) {
456  y = l + se.points[p].y;
457  x = -se.points[p].x - (oddLine && (y + 1) % 2);
458  z = s + se.points[p].z;
459 
460  _equSup.trueVal = (1UL << p);
461 
462  if (z >= nSlices || y >= nLines)
463  copyLine<T>(borderBuf, lineLen, cpBuf);
464  else
465  shiftLine<T>(srcLines[y], x, lineLen, cpBuf, borderValue);
466 
467  low._exec(cpBuf, minBuf, lineLen, flagBuf);
468  inf._exec(cpBuf, minBuf, lineLen, minBuf);
469  test._exec(flagBuf, nullBuf, lineArrow, lineLen, lineArrow);
470  _equSup._exec(cpBuf, minBuf, lineLen, lineArrow);
471  }
472  }
473  }
474  }
475 
476  return RES_OK;
477  }
478 
479  template <class T, class arrowT>
480  RES_T arrowMin(const Image<T> &im, Image<arrowT> &arrow, const StrElt &se,
481  T borderValue = numeric_limits<T>::max())
482  {
483  arrowMinFunction<T, arrowT> iFunc(borderValue);
484  return iFunc(im, arrow, se);
485  }
486 
487  template <class T, class arrowT = UINT8>
489  {
490  public:
492  typedef typename parentClass::imageInType imageInType;
493  typedef typename imageInType::lineType lineInType;
494  typedef typename imageInType::lineType sliceInType;
495  typedef typename imageInType::volType volInType;
496  typedef typename parentClass::imageOutType imageArrowType;
497  typedef typename imageArrowType::lineType lineArrowType;
498  typedef typename imageArrowType::sliceType sliceArrowType;
499  typedef typename imageArrowType::volType volArrowType;
500 
501  arrowMinStepFunction(T border = numeric_limits<T>::max())
502  : borderValue(border), MorphImageFunctionBase<T, arrowT>()
503  {
504  borderValue = border;
505  }
506 
507  virtual RES_T _exec(const imageInType &in, imageArrowType &imOut,
508  const StrElt &se);
509 
510  private:
511  T borderValue;
512  size_t lineLen;
513  };
514 
515  template <class T, class arrowT>
516  RES_T arrowMinStepFunction<T, arrowT>::_exec(const imageInType &in,
517  imageArrowType & arrow,
518  const StrElt & se)
519  {
520  ASSERT_ALLOCATED(&in, &arrow);
521  ASSERT_SAME_SIZE(&in, &arrow);
522 
523  if (!areAllocated(&in, &arrow, NULL))
524  return RES_ERR_BAD_ALLOCATION;
525 
526  StrElt cpSe = se.noCenter();
527 
528  UINT sePtsNumber = cpSe.points.size();
529 
530  if (sePtsNumber == 0)
531  return RES_OK;
532 
533  size_t nSlices = in.getSliceCount();
534  size_t nLines = in.getHeight();
535  lineLen = in.getWidth();
536 
537  volInType srcSlices = in.getSlices();
538  volArrowType destSlices = arrow.getSlices();
539  lineInType * srcLines;
540  lineArrowType *destLines;
541 
542  bool oddSe = cpSe.odd, oddLine = 0;
543 
544 #ifdef USE_OPEN_MP
545 #pragma omp parallel private(oddLine)
546 #endif // USE_OPEN_MP
547  {
548  T * borderBuf = ImDtTypes<T>::createLine(lineLen);
549  T * cpBuf = ImDtTypes<T>::createLine(lineLen);
550  T * minBuf = ImDtTypes<T>::createLine(lineLen);
551  T * nullBuf = ImDtTypes<T>::createLine(lineLen);
552  T * flagBuf = ImDtTypes<T>::createLine(lineLen);
553  lowLine<T> low;
554  infLine<T> inf;
555  testLine<T, arrowT> test;
557  equLine<T> equ;
558 
559  fillLine<T>(nullBuf, lineLen, arrowT(0));
560  fillLine<T>(borderBuf, lineLen, T(borderValue));
561  equ.trueVal = 0;
562  equ.falseVal = numeric_limits<T>::max();
563 
564  lineInType lineIn;
565  lineArrowType lineArrow;
566  size_t x, y, z, i;
567 
568  for (size_t s = 0; s < nSlices; ++s) {
569  srcLines = srcSlices[s];
570  destLines = destSlices[s];
571 
572 #ifdef USE_OPEN_MP
573 #pragma omp for
574 #endif // USE_OPEN_MP
575  for (size_t l = 0; l < nLines; ++l) {
576  oddLine = oddSe && l % 2;
577 
578  lineIn = srcLines[l];
579  lineArrow = destLines[l];
580 
581  fillLine<arrowT>(lineArrow, lineLen, arrowT(0));
582  copyLine<T>(borderBuf, lineLen, minBuf);
583 
584  for (UINT p = 0; p < sePtsNumber; ++p) {
585  y = l + cpSe.points[p].y;
586  x = -cpSe.points[p].x - (oddLine && (y + 1) % 2);
587  z = s + cpSe.points[p].z;
588 
589  _equSup.trueVal = (1UL << p);
590 
591  if (z >= nSlices || y >= nLines)
592  copyLine<T>(borderBuf, lineLen, cpBuf);
593  else
594  shiftLine<T>(srcLines[y], x, lineLen, cpBuf, borderValue);
595 
596  for (i = 0; i < lineLen; ++i)
597  flagBuf[i] = cpBuf[i] >= lineIn[i] ? 255 : 0;
598  for (i = 0; i < lineLen; ++i)
599  cpBuf[i] = flagBuf[i] ? cpBuf[i] : borderBuf[i];
600 
601  low._exec(cpBuf, minBuf, lineLen, flagBuf);
602  inf._exec(cpBuf, minBuf, lineLen, minBuf);
603  test._exec(flagBuf, nullBuf, lineArrow, lineLen, lineArrow);
604  _equSup._exec(cpBuf, minBuf, lineLen, lineArrow);
605  }
606  }
607  }
608  }
609 
610  return RES_OK;
611  }
612 
613  template <class T>
614  RES_T arrowMinStep(const Image<T> &im, Image<T> &arrow, const StrElt &se,
615  T borderValue = numeric_limits<T>::max())
616  {
617  arrowMinStepFunction<T, T> iFunc(borderValue);
618  return iFunc(im, arrow, se);
619  }
620 
623 } // namespace smil
624 
625 #endif // _D_MORPHO_ARROW_HPP
void getSize(size_t *w, size_t *h, size_t *d) const
Get image size.
Definition: DBaseImage.h:118
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:105
Base morpho operator class.
Definition: DMorphImageOperations.hpp:58
Definition: DMorphImageOperations.hpp:145
Base structuring element.
Definition: DStructuringElement.h:68
vector< IntPoint > points
List of neighbor points.
Definition: DStructuringElement.h:201
Definition: DMorphoArrow.hpp:363
Definition: DMorphoArrow.hpp:489
Propagation Functor on a Arrow Image.
Definition: DMorphoArrow.hpp:244
Definition: DMorphoArrow.hpp:47
RES_T low(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
low() - Lower operator
Definition: DImageArith.hpp:604
RES_T inf(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
inf() - Inf of two images
Definition: DImageArith.hpp:305
RES_T equ(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
equ() - Equality operator (pixel by pixel)
Definition: DImageArith.hpp:366
RES_T test(const Image< T1 > &imIn, const Image< T2 > &imInT, const Image< T2 > &imInF, Image< T2 > &imOut)
test() - Test
Definition: DImageArith.hpp:1109
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:218
Definition: DTypes.hpp:88
Definition: DBaseLineOperations.hpp:110
Definition: DMorphoArrow.hpp:333
Definition: DBaseImageOperations.hxx:39