SMIL  0.9.1
DMorphoLabel.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_LABEL_HPP
31 #define _D_MORPHO_LABEL_HPP
32 
33 #include "Base/include/private/DImageArith.hpp"
34 #include "Core/include/DImage.h"
35 #include "DMorphImageOperations.hpp"
36 #include "Base/include/private/DBlobMeasures.hpp"
37 
38 
39 #include <set>
40 #include <map>
41 #include <functional>
42 
43 namespace smil
44 {
52 #ifndef SWIG
53 
54  template <class T1, class T2, class compOperatorT=std::equal_to<T1> >
56  {
57  public:
59  typedef typename parentClass::imageInType imageInType;
60  typedef typename parentClass::imageOutType imageOutType;
61 
62  size_t getLabelNbr() { return real_labels; }
63 
64  virtual RES_T initialize(const imageInType &imIn, imageOutType &imOut, const StrElt &se)
65  {
66  parentClass::initialize(imIn, imOut, se);
67  fill(imOut, T2(0));
68  labels = 0;
69  real_labels = 0;
70  max_value_label = ImDtTypes<T2>::max();
71  return RES_OK;
72  }
73 
74  virtual RES_T processImage(const imageInType &imIn, imageOutType &/*imOut*/, const StrElt &/*se*/)
75  {
76  this->pixelsIn = imIn.getPixels();
77  for (size_t i=0; i<this->imSize[2]*this->imSize[1]*this->imSize[0]; i++)
78  {
79  if (this->pixelsOut[i] == T2(0)) {
80  vector<int> dum;
81  processPixel(i, dum);
82  }
83  }
84  return RES_OK;
85  }
86 
87  virtual void processPixel(size_t pointOffset,
88  SMIL_UNUSED vector<int> &dOffsets)
89  {
90 
91  T1 pVal = this->pixelsIn[pointOffset];
92 
93  if (pVal == T1(0) || this->pixelsOut[pointOffset] != T2(0))
94  return;
95 
96  queue<size_t> propagation;
97  int x, y, z, n_x, n_y, n_z;
98  IntPoint p;
99 
100  ++real_labels;
101  ++labels;
102  if (labels == max_value_label)
103  labels = 1;
104  this->pixelsOut[pointOffset] = (T2)labels;
105  propagation.push (pointOffset);
106 
107  bool oddLine = 0;
108  size_t curOffset, nbOffset;
109 
110  while (!propagation.empty ())
111  {
112  curOffset = propagation.front();
113  pVal = this->pixelsIn[curOffset];
114 
115  z = curOffset / (this->imSize[1]*this->imSize[0]);
116  y = (curOffset - z*this->imSize[1]*this->imSize[0])/this->imSize[0];
117  x = curOffset - y*this->imSize[0] - z*this->imSize[1]*this->imSize[0];
118 
119  oddLine = this->oddSe && (y%2);
120 
121  for (UINT i=0; i<this->sePointNbr; ++i)
122  {
123  p = this->sePoints[i];
124  n_x = x+p.x;
125  n_y = y+p.y;
126  n_x += (oddLine && ((n_y+1)%2) != 0) ;
127  n_z = z+p.z;
128  nbOffset = n_x+(n_y)*this->imSize[0]+(n_z)*this->imSize[1]*this->imSize[0];
129  if (nbOffset!=curOffset &&
130  n_x >= 0 && n_x < (int)this->imSize[0] &&
131  n_y >= 0 && n_y < (int)this->imSize[1] &&
132  n_z >= 0 && n_z < (int)this->imSize[2] &&
133  this->pixelsOut[nbOffset] != labels &&
134  compareFunc(this->pixelsIn[nbOffset], pVal))
135  {
136  this->pixelsOut[nbOffset] = T2(labels);
137  propagation.push (nbOffset);
138  }
139  }
140  propagation.pop();
141  }
142  }
143 
144  compOperatorT compareFunc;
145  protected:
146  T2 labels;
147  size_t real_labels;
148  T2 max_value_label;
149  };
150 
151  template <class T1, class T2, class compOperatorT=std::equal_to<T1> >
152  class labelFunctFast : public MorphImageFunctionBase <T1, T2>
153  {
154  public:
156  typedef typename parentClass::imageInType imageInType;
157  typedef typename parentClass::imageOutType imageOutType;
158  typedef typename imageInType::lineType lineInType;
159  typedef typename imageInType::sliceType sliceInType;
160  typedef typename imageOutType::lineType lineOutType;
161  typedef typename imageOutType::sliceType sliceOutType;
162 
163  size_t getLabelNbr() { return labels_real; }
164 
165  virtual RES_T initialize (const imageInType &imIn, imageOutType &imOut, const StrElt &se)
166  {
167  parentClass::initialize(imIn, imOut, se);
168  fill(imOut, T2(0));
169  labels = T2(0);
170  labels_real = 0;
171  max_value_label = ImDtTypes<T2>::max();
172  return RES_OK;
173  }
174 
175  virtual RES_T processImage (const imageInType &imIn, imageOutType &imOut, const StrElt &/*se*/) {
176  Image<T1> tmp(imIn);
177  Image<T1> tmp2(imIn);
178  ASSERT(clone(imIn, tmp)==RES_OK);
179  if (this->imSize[2] == 1) {
180  ASSERT(erode (tmp, tmp2, SquSE())==RES_OK);
181  } else {
182  ASSERT(erode (tmp, tmp2, CubeSE())==RES_OK);
183  }
184  ASSERT(sub(tmp, tmp2, tmp)==RES_OK);
185 
186  lineInType pixelsTmp = tmp.getPixels () ;
187 
188  // Adding the first point of each line to tmp.
189  #ifdef USE_OPEN_MP
190  #pragma omp parallel
191  #endif // USE_OPEN_MP
192  {
193  #ifdef USE_OPEN_MP
194  #pragma omp for
195  #endif // USE_OPEN_MP
196  for (size_t i=0; i<this->imSize[2]*this->imSize[1]; ++i) {
197  pixelsTmp[i*this->imSize[0]] = this->pixelsIn[i*this->imSize[0]];
198  }
199  }
200 
201  queue <size_t> propagation;
202  int x,y,z, n_x, n_y, n_z;
203  IntPoint p;
204 
205  T2 current_label = labels;
206  bool is_not_a_gap = false;
207  bool process_labeling = false;
208  bool oddLine = 0;
209 
210  // First PASS to label the boundaries. //
211  for (size_t i=0; i<this->imSize[2]*this->imSize[1]*this->imSize[0]; ++i) {
212  if (i%(this->imSize[0]) == 0) {
213  is_not_a_gap=false;
214  }
215  if (pixelsTmp[i] != T1(0)) {
216  if (this->pixelsOut[i] == T2(0)) {
217  if (!is_not_a_gap) {
218  ++labels;
219  ++labels_real;
220  if (labels == max_value_label)
221  labels=1;
222  current_label = (T2)labels;
223  }
224  this->pixelsOut[i] = current_label;
225  process_labeling = true;
226  } else {
227  current_label = this->pixelsOut[i];
228  }
229 
230  is_not_a_gap = true;
231  }
232  if (this->pixelsIn[i] == T1(0)) {
233  is_not_a_gap = false;
234  }
235 
236  if (process_labeling) {
237  propagation.push (i);
238 
239  while (!propagation.empty ()) {
240  z = propagation.front() / (this->imSize[1]*this->imSize[0]);
241  y = (propagation.front() - z*this->imSize[1]*this->imSize[0])/this->imSize[0];
242  x = propagation.front() - y*this->imSize[0] - z*this->imSize[1]*this->imSize[0];
243 
244  oddLine = this->oddSe && (y%2);
245  size_t nbOffset;
246 
247  for (UINT i=0; i<this->sePointNbr; ++i) {
248  p = this->sePoints[i];
249  n_x = x+p.x;
250  n_y = y+p.y;
251  n_x += (oddLine && ((n_y+1)%2) != 0) ;
252  n_z = z+p.z;
253  nbOffset = n_x+(n_y)*this->imSize[0]+(n_z)*this->imSize[1]*this->imSize[0];
254  if (n_x >= 0 && n_x < (int)this->imSize[0] &&
255  n_y >= 0 && n_y < (int)this->imSize[1] &&
256  n_z >= 0 && n_z < (int)this->imSize[2] &&
257  compareFunc(this->pixelsIn[nbOffset], pixelsTmp[propagation.front ()]) &&
258  this->pixelsOut[nbOffset] != current_label)
259  {
260  this->pixelsOut[nbOffset] = current_label;
261  propagation.push (nbOffset);
262  }
263 
264  }
265 
266  propagation.pop();
267  }
268  process_labeling = false;
269  }
270  }
271  // Propagate labels inside the borders //
272 
273  size_t nSlices = imIn.getDepth () ;
274  size_t nLines = imIn.getHeight () ;
275  size_t nPixels = imIn.getWidth () ;
276  size_t l, v;
277  T1 previous_value;
278  T2 previous_label;
279 
280  sliceInType srcLines = imIn.getLines () ;
281  sliceOutType desLines = imOut.getLines () ;
282  lineInType lineIn;
283  lineOutType lineOut;
284 
285  for (size_t s=0; s<nSlices; ++s) {
286  #ifdef USE_OPEN_MP
287  #pragma omp parallel private(lineIn,lineOut,l,v,previous_value,previous_label)
288  #endif // USE_OPEN_MP
289  {
290  #ifdef USE_OPEN_MP
291  #pragma omp for
292  #endif // USE_OPEN_MP
293  for (l=0; l<nLines; ++l) {
294  lineIn = srcLines[l+s*nSlices];
295  lineOut = desLines[l+s*nSlices];
296  previous_value = lineIn[0];
297  previous_label = lineOut[0];
298  for (v=1; v<nPixels; ++v) {
299  if (compareFunc (lineIn[v], previous_value)) {
300  lineOut[v] = previous_label;
301  } else {
302  previous_value = lineIn[v];
303  previous_label = lineOut[v];
304  }
305  }
306  }
307  }
308  }
309  return RES_OK;
310  }
311 
312  compOperatorT compareFunc;
313  protected :
314  T2 labels;
315  size_t labels_real;
316  T2 max_value_label;
317  };
318 
319 
320  template <class T>
322  {
323  inline bool operator()(T &a, T&b)
324  {
325  bool retVal = a>b ? (a-b)<=lambda : (b-a)<=lambda;
326  return retVal;
327 
328  }
329  T lambda;
330  };
331 
332 #endif // SWIG
333 
334  template <class T1, class T2 >
335  size_t labelWithoutFunctor(const Image<T1> &imIn, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
336  {
337  // Checks
338  ASSERT_ALLOCATED (&imIn, &imOut) ;
339  ASSERT_SAME_SIZE (&imIn, &imOut) ;
340 
341  // Typedefs
342  typedef Image<T1> inT;
343  typedef Image<T2> outT;
344  typedef typename inT::lineType inLineT;
345  typedef typename outT::lineType outLineT;
346 
347  // Initialisation.
348  StrElt cpSe = se.noCenter () ;
349  fill (imOut, T2(0));
350 
351  // Processing vars.
352  size_t lblNbr = 0;
353  size_t lblNbr_real = 0;
354  size_t size[3]; imIn.getSize (size) ;
355  UINT sePtsNumber = cpSe.points.size();
356  if (sePtsNumber == 0) return 0;
357  queue<size_t> propagation;
358  size_t o, nb_o;
359  size_t x,x0,y,y0,z,z0;
360  bool oddLine;
361  // Image related.
362  inLineT inP = imIn.getPixels () ;
363  outLineT outP = imOut.getPixels () ;
364 
365  for (size_t s=0; s<size[2]; ++s)
366  {
367  for (size_t l=0; l<size[1]; ++l)
368  {
369  for (size_t p=0; p<size[0]; ++p)
370  {
371  o = p + l*size[0] + s*size[0]*size[1];
372  if (inP[o] != T1(0) && outP[o] == T2(0))
373  {
374  ++lblNbr_real;
375  ++lblNbr ;
376  if (lblNbr == (size_t)(ImDtTypes<T2>::max() - 1))
377  lblNbr = 1;
378 
379  outP [o] = T2(lblNbr);
380  propagation.push (o);
381  do
382  {
383  o = propagation.front () ;
384  propagation.pop () ;
385 
386  x0 = o % size[0];
387  y0 = (o % (size[1]*size[0])) / size[0];
388  z0 = o / (size[0]*size[1]);
389  oddLine = cpSe.odd && y0 %2;
390  for (UINT pSE=0; pSE<sePtsNumber; ++pSE)
391  {
392  x = x0 + cpSe.points[pSE].x;
393  y = y0 + cpSe.points[pSE].y;
394  z = z0 + cpSe.points[pSE].z;
395 
396  if (oddLine)
397  x += (y+1)%2;
398 
399  nb_o = x + y*size[0] + z*size[0]*size[1];
400  if (x < size[0] && y < size[1] && z<size[2] && outP [nb_o] != lblNbr && inP [nb_o] == inP[o])
401  {
402  outP[nb_o] = T2(lblNbr);
403  propagation.push (nb_o);
404  }
405  }
406  } while (!propagation.empty()) ;
407  }
408  }
409  }
410  }
411 
412  return lblNbr_real;
413  }
414  template <class T1, class T2 >
415  size_t labelWithoutFunctor2Partitions(const Image<T1> &imIn,const Image<T1> &imIn2, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
416  {
417  // Checks
418  ASSERT_ALLOCATED (&imIn, &imIn2, &imOut) ;
419  ASSERT_SAME_SIZE (&imIn, &imOut) ;
420  ASSERT_SAME_SIZE (&imIn2, &imOut) ;
421 
422  // Typedefs
423  typedef Image<T1> inT;
424  typedef Image<T2> outT;
425  typedef typename inT::lineType inLineT;
426  typedef typename outT::lineType outLineT;
427 
428  // Initialisation.
429  StrElt cpSe = se.noCenter () ;
430  fill (imOut, T2(0));
431 
432  // Processing vars.
433  size_t lblNbr = 0;
434  size_t lblNbr_real = 0;
435  size_t size[3]; imIn.getSize (size) ;
436  UINT sePtsNumber = cpSe.points.size();
437  if (sePtsNumber == 0) return 0;
438  queue<size_t> propagation;
439  size_t o, nb_o;
440  size_t x,x0,y,y0,z,z0;
441  bool oddLine;
442  // Image related.
443  inLineT inP = imIn.getPixels () ;
444  inLineT in2P = imIn2.getPixels () ;
445  outLineT outP = imOut.getPixels () ;
446 
447  for (size_t s=0; s<size[2]; ++s)
448  {
449  for (size_t l=0; l<size[1]; ++l)
450  {
451  for (size_t p=0; p<size[0]; ++p)
452  {
453  o = p + l*size[0] + s*size[0]*size[1];
454  if (inP[o] != T1(0) && outP[o] == T2(0))
455  {
456  ++lblNbr_real;
457  ++lblNbr ;
458  if (lblNbr == (size_t)ImDtTypes<T2>::max()-1)
459  lblNbr = 1;
460 
461  outP [o] = T2(lblNbr);
462  propagation.push (o);
463  do
464  {
465  o = propagation.front () ;
466  propagation.pop () ;
467 
468  x0 = o % size[0];
469  y0 = (o % (size[1]*size[0])) / size[0];
470  z0 = o / (size[0]*size[1]);
471  oddLine = cpSe.odd && y0 %2;
472  for (UINT pSE=0; pSE<sePtsNumber; ++pSE)
473  {
474  x = x0 + cpSe.points[pSE].x;
475  y = y0 + cpSe.points[pSE].y;
476  z = z0 + cpSe.points[pSE].z;
477 
478  if (oddLine)
479  x += (y+1)%2;
480 
481  nb_o = x + y*size[0] + z*size[0]*size[1];
482  if (x < size[0] && y < size[1] && z<size[2] && outP [nb_o] != lblNbr && inP [nb_o] == inP[o] && in2P[nb_o]==in2P[o])
483  {
484  outP[nb_o] = T2(lblNbr);
485  propagation.push (nb_o);
486  }
487  }
488  } while (!propagation.empty()) ;
489  }
490  }
491  }
492  }
493 
494  return lblNbr_real;
495  }
496 
502  template<class T1, class T2>
503  size_t label(const Image<T1> &imIn, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
504  {
505  if ((void*)&imIn==(void*)&imOut)
506  {
507  Image<T1> tmpIm(imIn, true); // clone
508  return label(tmpIm, imOut);
509  }
510 
511  ASSERT_ALLOCATED(&imIn, &imOut);
512  ASSERT_SAME_SIZE(&imIn, &imOut);
513 
515 
516  ASSERT((f._exec(imIn, imOut, se)==RES_OK), 0);
517 
518  size_t lblNbr = f.getLabelNbr();
519 
520  if (lblNbr > size_t(ImDtTypes<T2>::max()))
521  std::cerr << "Label number exceeds data type max!" << std::endl;
522 
523  return lblNbr;
524  }
525 
531  template<class T1, class T2>
532  size_t lambdaLabel(const Image<T1> &imIn, const T1 &lambdaVal, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
533  {
534  ASSERT_ALLOCATED(&imIn, &imOut);
535  ASSERT_SAME_SIZE(&imIn, &imOut);
536 
538  f.compareFunc.lambda = lambdaVal;
539 
540  ASSERT((f._exec(imIn, imOut, se)==RES_OK), 0);
541 
542  size_t lblNbr = f.getLabelNbr();
543 
544  if (lblNbr > size_t(ImDtTypes<T2>::max()))
545  std::cerr << "Label number exceeds data type max!" << std::endl;
546 
547  return lblNbr;
548  }
549 
555  template<class T1, class T2>
556  size_t fastLabel(const Image<T1> &imIn, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
557  {
558  ASSERT_ALLOCATED(&imIn, &imOut);
559  ASSERT_SAME_SIZE(&imIn, &imOut);
560 
562 
563  ASSERT((f._exec(imIn, imOut, se)==RES_OK), 0);
564 
565  size_t lblNbr = f.getLabelNbr();
566 
567  if (lblNbr > size_t(ImDtTypes<T2>::max()))
568  std::cerr << "Label number exceeds data type max!" << std::endl;
569 
570  return lblNbr;
571  }
572 
578  template<class T1, class T2>
579  size_t lambdaFastLabel(const Image<T1> &imIn, const T1 &lambdaVal, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
580  {
581  ASSERT_ALLOCATED(&imIn, &imOut);
582  ASSERT_SAME_SIZE(&imIn, &imOut);
583 
585  f.compareFunc.lambda = lambdaVal;
586 
587  ASSERT((f._exec(imIn, imOut, se)==RES_OK), 0);
588 
589  size_t lblNbr = f.getLabelNbr();
590 
591  if (lblNbr < size_t(ImDtTypes<T2>::max()))
592  std::cerr << "Label number exceeds data type max!" << std::endl;
593 
594  return lblNbr;
595  }
596 
597 
602  template<class T1, class T2>
603  size_t labelWithArea(const Image<T1> &imIn, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
604  {
605  ASSERT_ALLOCATED(&imIn, &imOut);
606  ASSERT_SAME_SIZE(&imIn, &imOut);
607 
608  ImageFreezer freezer(imOut);
609 
610  Image<T2> imLabel(imIn);
611 
612  ASSERT(label(imIn, imLabel, se)!=0);
613  map<T2, double> areas = measAreas(imLabel);
614  ASSERT(!areas.empty());
615 
616  double maxV = std::max_element(areas.begin(), areas.end(), map_comp_value_less())->second;
617  ASSERT((maxV < double(ImDtTypes<T2>::max())), "Areas max value exceeds data type max!", 0);
618 
619  ASSERT(applyLookup(imLabel, areas, imOut)==RES_OK);
620 
621  return RES_OK;
622  }
623 
628  template<class T1, class T2>
629  size_t labelWithVolume(const Image<T1> &imIn, const Image<T2> &imLabelsInit, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
630  {
631  ASSERT_ALLOCATED(&imIn, &imOut);
632  ASSERT_SAME_SIZE(&imIn, &imOut);
633 
634  ImageFreezer freezer(imOut);
635 
636  Image<T2> imLabel(imIn);
637 
638  ASSERT(label(imLabelsInit, imLabel, se)!=0);
639  label(imLabelsInit, imLabel, se);
640  bool onlyNonZeros = true;
641  map<T2, Blob> blobs = computeBlobs(imLabel,onlyNonZeros);
642  map<T2, double> volumes = measVolumes(imIn,blobs);
643  ASSERT(!volumes.empty());
644 
645  double maxV = std::max_element(volumes.begin(), volumes.end(), map_comp_value_less())->second;
646  cout << maxV << endl;
647  ASSERT((maxV < double(ImDtTypes<T2>::max())), "Volumes max value exceeds data type max!", 0);
648 
649  ASSERT(applyLookup(imLabel, volumes, imOut)==RES_OK);
650 
651  return RES_OK;
652  }
653 
658  template<class T1, class T2>
659  size_t labelWithMaxima(const Image<T1> &imIn, const Image<T2> &imLabelsInit, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
660  {
661  ASSERT_ALLOCATED(&imIn, &imOut);
662  ASSERT_SAME_SIZE(&imIn, &imOut);
663 
664  ImageFreezer freezer(imOut);
665 
666  Image<T2> imLabel(imIn);
667 
668  ASSERT(label(imLabelsInit, imLabel, se)!=0);
669  label(imLabelsInit, imLabel, se);
670  bool onlyNonZeros = true;
671  map<T2, Blob> blobs = computeBlobs(imLabel,onlyNonZeros);
672  map<T2, T1> markers = measMaxVals(imIn,blobs);
673  ASSERT(!markers.empty());
674 
675  double maxV = std::max_element(markers.begin(), markers.end(), map_comp_value_less())->second;
676  cout << maxV << endl;
677  ASSERT((maxV < double(ImDtTypes<T2>::max())), "Markers max value exceeds data type max!", 0);
678 
679  ASSERT(applyLookup(imLabel, markers, imOut)==RES_OK);
680 
681  return RES_OK;
682  }
683 
684 
689  template<class T1, class T2>
690  size_t labelWithMean(const Image<T1> &imIn, const Image<T2> &imLabelsInit, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
691  {
692  ASSERT_ALLOCATED(&imIn, &imOut);
693  ASSERT_SAME_SIZE(&imIn, &imOut);
694 
695  ImageFreezer freezer(imOut);
696 
697  Image<T2> imLabel(imIn);
698 
699  ASSERT(label(imLabelsInit, imLabel, se)!=0);
700  label(imLabelsInit, imLabel, se);
701  bool onlyNonZeros = true;
702  map<T2, Blob> blobs = computeBlobs(imLabel,onlyNonZeros);
703  map<T2, std::vector<double> > meanValsStd = measMeanVals(imIn,blobs);
704  map<T2,double> markers;
705 
706  for (typename std::map<T2, std::vector<double> >::iterator iter = meanValsStd.begin(); iter != meanValsStd.end(); ++iter){
707  markers[iter->first] = (iter->second)[0];
708 // cout << "iter->first = " << iter->first << " iter->second[0] " << iter->second[0] << endl;
709  }
710 
711  ASSERT(!markers.empty());
712 
713  double maxV = std::max_element(markers.begin(), markers.end(), map_comp_value_less())->second;
714 // cout << maxV << endl;
715  ASSERT((maxV < double(ImDtTypes<T2>::max())), "Markers max value exceeds data type max!", 0);
716 
717  ASSERT(applyLookup(imLabel, markers, imOut)==RES_OK);
718 
719  return RES_OK;
720  }
721 
722 
723  template <class T1, class T2>
724  class neighborsFunct : public MorphImageFunctionBase<T1, T2>
725  {
726  public:
728 
729  virtual inline void processPixel(size_t pointOffset, vector<int> &dOffsetList)
730  {
731  vector<T1> vals;
732  UINT nbrValues = 0;
733  vector<int>::iterator dOffset = dOffsetList.begin();
734  while(dOffset!=dOffsetList.end())
735  {
736  T1 val = parentClass::pixelsIn[pointOffset + *dOffset];
737  if (find(vals.begin(), vals.end(), val)==vals.end())
738  {
739  vals.push_back(val);
740  nbrValues++;
741  }
742  dOffset++;
743  }
744  parentClass::pixelsOut[pointOffset] = T2(nbrValues);
745  }
746  };
747 
755  template <class T1, class T2>
756  RES_T neighbors(const Image<T1> &imIn, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
757  {
758  ASSERT_ALLOCATED(&imIn, &imOut);
759  ASSERT_SAME_SIZE(&imIn, &imOut);
760 
762 
763  ASSERT((f._exec(imIn, imOut, se)==RES_OK));
764 
765  return RES_OK;
766 
767  }
768 
769 
772 } // namespace smil
773 
774 #endif // _D_MORPHO_LABEL_HPP
775 
Square structuring element.
Definition: DStructuringElement.h:161
size_t labelWithArea(const Image< T1 > &imIn, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Image labelization with the size of each connected components.
Definition: DMorphoLabel.hpp:603
map< labelT, T > measMaxVals(const Image< T > &imIn, map< labelT, Blob > &blobs)
Measure the maximum value of each blob in imIn.
Definition: DBlobMeasures.hpp:88
Definition: DColorConvert.h:38
sliceType getLines() const
Get an array containing the start offset of each line.
Definition: DImage.hpp:114
RES_T sub(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Subtraction.
Definition: DImageArith.hpp:446
Definition: DBaseImage.h:235
vector< IntPoint > points
List of neighbor points.
Definition: DStructuringElement.h:125
Definition: DCommon.h:93
map< T, Blob > computeBlobs(const Image< T > &imIn, bool onlyNonZero=true)
Create a map of Blob from a labelized image.
Definition: DBlob.hpp:75
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:110
Definition: DMorphoLabel.hpp:724
RES_T fill(Image< T > &imOut, const T &value)
Fill an image with a given value.
Definition: DImageArith.hpp:62
size_t labelWithMaxima(const Image< T1 > &imIn, const Image< T2 > &imLabelsInit, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Image labelization with the maximum values of each connected components in the imLabelsInit image...
Definition: DMorphoLabel.hpp:659
size_t labelWithVolume(const Image< T1 > &imIn, const Image< T2 > &imLabelsInit, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Image labelization with the volume (sum of values) of each connected components in the imLabelsInit i...
Definition: DMorphoLabel.hpp:629
size_t fastLabel(const Image< T1 > &imIn, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Image labelization.
Definition: DMorphoLabel.hpp:556
map< labelT, double > measVolumes(const Image< T > &imIn, map< labelT, Blob > &blobs)
Measure the sum of values of each blob in imIn.
Definition: DBlobMeasures.hpp:118
RES_T neighbors(const Image< T1 > &imIn, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Neighbors.
Definition: DMorphoLabel.hpp:756
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:91
Definition: DMorphoLabel.hpp:321
Base structuring element.
Definition: DStructuringElement.h:51
Base morpho operator class.
Definition: DMorphImageOperations.hpp:54
3D Cubic structuring element (26 neighbors).
Definition: DStructuringElement.h:302
Definition: DMorphoLabel.hpp:152
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:87
size_t label(const Image< T1 > &imIn, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Image labelization.
Definition: DMorphoLabel.hpp:503
size_t lambdaFastLabel(const Image< T1 > &imIn, const T1 &lambdaVal, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Lambda-flat zones fast labelization.
Definition: DMorphoLabel.hpp:579
map< labelT, Vector_double > measMeanVals(const Image< T > &imIn, map< labelT, Blob > &blobs)
Measure the mean value and the std dev.
Definition: DBlobMeasures.hpp:108
Definition: DTypes.hpp:78
Definition: DMorphoLabel.hpp:55
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
size_t lambdaLabel(const Image< T1 > &imIn, const T1 &lambdaVal, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Lambda-flat zones labelization.
Definition: DMorphoLabel.hpp:532
RES_T applyLookup(const Image< T1 > &imIn, const mapT &_map, Image< T2 > &imOut, T2 defaultValue=T2(0))
Apply a lookup map.
Definition: DImageArith.hpp:1092
RES_T clone(const Image< T > &imIn, Image< T > &imOut)
Clone an image.
Definition: DImageArith.hpp:227
size_t labelWithMean(const Image< T1 > &imIn, const Image< T2 > &imLabelsInit, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Image labelization with the mean values of each connected components in the imLabelsInit image...
Definition: DMorphoLabel.hpp:690
size_t getDepth() const
Get image depth (Z)
Definition: DBaseImage.h:95
Definition: DCommon.h:104
map< T, double > measAreas(const Image< T > &imLbl, const bool onlyNonZero=true)
Measure label areas.
Definition: DBlobMeasures.hpp:56