SMIL  1.0.4
DMeasures.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_MEASURES_HPP
31 #define _D_MEASURES_HPP
32 
33 #include "Core/include/private/DImage.hpp"
34 #include "DBaseMeasureOperations.hpp"
35 #include "DImageArith.hpp"
36 #include "Base/include/DImageDraw.h"
37 
38 #include <cmath>
39 #include <map>
40 #include <set>
41 #include <iostream>
42 #include <iterator> // std::back_inserter
43 #include <mutex>
44 
45 namespace smil
46 {
57  template <class T>
58  struct measAreaFunc : public MeasureFunctionBase<T, double> {
59  typedef typename Image<T>::lineType lineType;
60 
61  virtual void processSequence(lineType /*lineIn*/, size_t size)
62  {
63  this->retVal += size;
64  }
65  };
68  //
69  // ## ##### ###### ##
70  // # # # # # # #
71  // # # # # ##### # #
72  // ###### ##### # ######
73  // # # # # # # #
74  // # # # # ###### # #
75  //
90  template <class T>
91  size_t area(const Image<T> &imIn)
92  {
93  measAreaFunc<T> func;
94  return static_cast<size_t>(func(imIn, true));
95  }
96 
98  template <class T>
99  struct measVolFunc : public MeasureFunctionBase<T, double> {
100  typedef typename Image<T>::lineType lineType;
101 
102  virtual void processSequence(lineType lineIn, size_t size)
103  {
104  for (size_t i = 0; i < size; i++)
105  this->retVal += double(lineIn[i]);
106  }
107  };
110  //
111  // # # #### # # # # # ######
112  // # # # # # # # ## ## #
113  // # # # # # # # # ## # #####
114  // # # # # # # # # # #
115  // # # # # # # # # # #
116  // ## #### ###### #### # # ######
117  //
128  template <class T>
129  double vol(const Image<T> &imIn)
130  {
131 #if 1
132  return volume(imIn);
133 #else
134  measVolFunc<T> func;
135  return func(imIn, false);
136 #endif
137  }
138 
153  template <class T>
154  double volume(const Image<T> &imIn)
155  {
156  measVolFunc<T> func;
157  return func(imIn, false);
158  }
159 
160  //
161  // # # ###### ## # # # # ## #
162  // ## ## # # # ## # # # # # #
163  // # ## # ##### # # # # # # # # # #
164  // # # # ###### # # # # # ###### #
165  // # # # # # # ## # # # # #
166  // # # ###### # # # # ## # # ######
167  //
169  template <class T>
170  struct measMeanValFunc : public MeasureFunctionBase<T, Vector_double> {
171  typedef typename Image<T>::lineType lineType;
172  double sum1, sum2;
173  double pixNbr;
174 
175  virtual void initialize(const Image<T> & /*imIn*/)
176  {
177  this->retVal.clear();
178  sum1 = sum2 = pixNbr = 0.;
179  }
180  virtual void processSequence(lineType lineIn, size_t size)
181  {
182  double curV;
183  for (size_t i = 0; i < size; i++) {
184  pixNbr += 1;
185  curV = lineIn[i];
186  sum1 += curV;
187  sum2 += curV * curV;
188  }
189  }
190  virtual void finalize(const Image<T> & /*imIn*/)
191  {
192  double mean_val = pixNbr == 0 ? 0 : sum1 / pixNbr;
193  double std_dev_val =
194  pixNbr == 0 ? 0 : std::sqrt(sum2 / pixNbr - mean_val * mean_val);
195 
196  this->retVal.push_back(mean_val);
197  this->retVal.push_back(std_dev_val);
198  }
199  };
210  template <class T>
211  Vector_double meanVal(const Image<T> &imIn, bool onlyNonZero = false)
212  {
213  measMeanValFunc<T> func;
214  return func(imIn, onlyNonZero);
215  }
216 
217  //
218  // # # # # # # # ## #
219  // ## ## # ## # # # # # #
220  // # ## # # # # # # # # # #
221  // # # # # # # # # ###### #
222  // # # # # ## # # # # #
223  // # # # # # ## # # ######
224  //
226  template <class T>
227  struct measMinValFunc : public MeasureFunctionBase<T, T> {
228  typedef typename Image<T>::lineType lineType;
229  virtual void initialize(const Image<T> & /*imIn*/)
230  {
231  this->retVal = numeric_limits<T>::max();
232  }
233  virtual void processSequence(lineType lineIn, size_t size)
234  {
235  for (size_t i = 0; i < size; i++)
236  if (lineIn[i] < this->retVal)
237  this->retVal = lineIn[i];
238  }
239  };
240 
241  template <class T>
242  struct measMinValPosFunc : public MeasureFunctionWithPos<T, T> {
243  typedef typename Image<T>::lineType lineType;
244  Point<UINT> pt;
245  virtual void initialize(const Image<T> & /*imIn*/)
246  {
247  this->retVal = numeric_limits<T>::max();
248  }
249  virtual void processSequence(lineType lineIn, size_t size, size_t x,
250  size_t y, size_t z)
251  {
252  for (size_t i = 0; i < size; i++, x++)
253  if (lineIn[i] < this->retVal) {
254  this->retVal = lineIn[i];
255  pt.x = x;
256  pt.y = y;
257  pt.z = z;
258  }
259  }
260  };
270  template <class T>
271  T minVal(const Image<T> &imIn, bool onlyNonZero = false)
272  {
273  measMinValFunc<T> func;
274  return func(imIn, onlyNonZero);
275  }
276 
285  template <class T>
286  T minVal(const Image<T> &imIn, Point<UINT> &pt, bool onlyNonZero = false)
287  {
288  measMinValPosFunc<T> func;
289  func(imIn, onlyNonZero);
290  pt = func.pt;
291  return func.retVal;
292  }
293 
294  //
295  // # # ## # # # # ## #
296  // ## ## # # # # # # # # #
297  // # ## # # # ## # # # # #
298  // # # ###### ## # # ###### #
299  // # # # # # # # # # # #
300  // # # # # # # ## # # ######
301  //
303  template <class T>
304  struct measMaxValFunc : public MeasureFunctionBase<T, T> {
305  typedef typename Image<T>::lineType lineType;
306  virtual void initialize(const Image<T> & /*imIn*/)
307  {
308  this->retVal = numeric_limits<T>::min();
309  }
310  virtual void processSequence(lineType lineIn, size_t size)
311  {
312  for (size_t i = 0; i < size; i++)
313  if (lineIn[i] > this->retVal)
314  this->retVal = lineIn[i];
315  }
316  };
317 
318  template <class T>
319  struct measMaxValPosFunc : public MeasureFunctionWithPos<T, T> {
320  typedef typename Image<T>::lineType lineType;
321  Point<UINT> pt;
322  virtual void initialize(const Image<T> & /*imIn*/)
323  {
324  this->retVal = numeric_limits<T>::min();
325  }
326  virtual void processSequence(lineType lineIn, size_t size, size_t x,
327  size_t y, size_t z)
328  {
329  for (size_t i = 0; i < size; i++, x++)
330  if (lineIn[i] > this->retVal) {
331  this->retVal = lineIn[i];
332  pt.x = x;
333  pt.y = y;
334  pt.z = z;
335  }
336  }
337  };
347  template <class T>
348  T maxVal(const Image<T> &imIn, bool onlyNonZero = false)
349  {
350  measMaxValFunc<T> func;
351  return func(imIn, onlyNonZero);
352  }
353 
362  template <class T>
363  T maxVal(const Image<T> &imIn, Point<UINT> &pt, bool onlyNonZero = false)
364  {
365  measMaxValPosFunc<T> func;
366  func(imIn, onlyNonZero);
367  pt = func.pt;
368  return func.retVal;
369  }
370 
371  //
372  // # # # # # # # ## # # # # ## #
373  // ## ## # ## # ## ## # # # # # # # # #
374  // # ## # # # # # # ## # # # ## # # # # #
375  // # # # # # # # # ###### ## # # ###### #
376  // # # # # ## # # # # # # # # # # #
377  // # # # # # # # # # # # ## # # ######
378  //
380  template <class T>
381  struct measMinMaxValFunc : public MeasureFunctionBase<T, vector<T>> {
382  typedef typename Image<T>::lineType lineType;
383  T minVal, maxVal;
384  virtual void initialize(const Image<T> & /*imIn*/)
385  {
386  this->retVal.clear();
387  maxVal = numeric_limits<T>::min();
388  minVal = numeric_limits<T>::max();
389  }
390  virtual void processSequence(lineType lineIn, size_t size)
391  {
392  for (size_t i = 0; i < size; i++) {
393  T val = lineIn[i];
394  if (val > maxVal)
395  maxVal = val;
396  if (val < minVal)
397  minVal = val;
398  }
399  }
400  virtual void finalize(const Image<T> & /*imIn*/)
401  {
402  this->retVal.push_back(minVal);
403  this->retVal.push_back(maxVal);
404  }
405  };
415  template <class T>
416  vector<T> rangeVal(const Image<T> &imIn, bool onlyNonZero = false)
417  {
418  measMinMaxValFunc<T> func;
419  return func(imIn, onlyNonZero);
420  }
421 
422  //
423  // # # ## # # # ###### # # #### #####
424  // # # # # # # # # # # # #
425  // # # # # # # # ##### # # #### #
426  // # # ###### # # # # # # # #
427  // # # # # # # # # # # # # #
428  // ## # # ###### #### ###### ###### # #### #
429  //
431  template <class T>
432  struct valueListFunc : public MeasureFunctionBase<T, vector<T>> {
433  typedef typename Image<T>::lineType lineType;
434  set<T> valList;
435 
436  virtual void initialize(const Image<T> & /*imIn*/)
437  {
438  this->retVal.clear();
439  valList.clear();
440  }
441 
442  virtual void processSequence(lineType lineIn, size_t size)
443  {
444  for (size_t i = 0; i < size; i++)
445  valList.insert(lineIn[i]);
446  }
447  virtual void finalize(const Image<T> & /*imIn*/)
448  {
449  // Copy the content of the set into the ret vector
450  std::copy(valList.begin(), valList.end(),
451  std::back_inserter(this->retVal));
452  }
453  };
467  template <class T>
468  vector<T> valueList(const Image<T> &imIn, bool onlyNonZero = true)
469  {
470  valueListFunc<T> func;
471  return func(imIn, onlyNonZero);
472  }
473 
474  //
475  // # # #### ##### ###### # # ## #
476  // ## ## # # # # # # # # # #
477  // # ## # # # # # ##### # # # # #
478  // # # # # # # # # # ###### #
479  // # # # # # # # # # # # #
480  // # # #### ##### ###### ## # # ######
481  //
483  template <class T>
484  struct measModeValFunc : public MeasureFunctionBase<T, T> {
485  typedef typename Image<T>::lineType lineType;
486 
487  map<int, int> nbList;
488  int maxNb;
489  T mode;
490  virtual void initialize(const Image<T> & /*imIn*/)
491  {
492  // BMI this->retVal.clear();
493  nbList.clear();
494  maxNb = 0;
495  mode = 0;
496  }
497 
498  virtual void processSequence(lineType lineIn, size_t size)
499  {
500  for (size_t i = 0; i < size; i++) {
501  T val = lineIn[i];
502  if (val > 0) {
503  if (nbList.find(val) == nbList.end()) {
504  nbList.insert(std::pair<int, int>(val, 1));
505  } else
506  nbList[val]++;
507  if (nbList[val] > maxNb) {
508  mode = val;
509  maxNb = nbList[val];
510  }
511  } // if (val>0)
512  } // for i= 0; i < size
513  this->retVal = mode;
514 
515  } // virtual
516  }; // END measModeValFunc
533  template <class T>
534  T modeVal(const Image<T> &imIn, bool onlyNonZero = true)
535  {
536  measModeValFunc<T> func;
537  return func(imIn, onlyNonZero);
538  }
539 
540  //
541  // # # ###### ##### # ## # # # # ## #
542  // ## ## # # # # # # ## # # # # # #
543  // # ## # ##### # # # # # # # # # # # # #
544  // # # # # # # ###### # # # # # ###### #
545  // # # # # # # # # # ## # # # # #
546  // # # ###### ##### # # # # # ## # # ######
547  //
549  template <class T>
550  struct measMedianValFunc : public MeasureFunctionBase<T, T> {
551  typedef typename Image<T>::lineType lineType;
552 
553  map<int, int> nbList;
554  size_t acc_elem, total_elems;
555  T medianval;
556  virtual void initialize(const Image<T> & /*imIn*/)
557  {
558  // BMI this->retVal.clear();
559  nbList.clear();
560  medianval = 0;
561  acc_elem = 0;
562  total_elems = 0;
563  }
564 
565  virtual void processSequence(lineType lineIn, size_t size)
566  {
567  for (size_t i = 0; i < size; i++) {
568  T val = lineIn[i];
569  if (val > 0) {
570  total_elems++;
571  if (nbList.find(val) == nbList.end()) {
572  nbList.insert(std::pair<int, int>(val, 1));
573  } else
574  nbList[val]++;
575 
576  } // if (val>0)
577  } // for i= 0; i < size
578  // this->retVal = medianval;
579  } // virtual processSequence
580 
581  virtual void finalize(const Image<T> & /*imIn*/)
582  {
583  typedef std::map<int, int>::iterator it_type;
584 
585  for (it_type my_iterator = nbList.begin(); my_iterator != nbList.end();
586  my_iterator++) {
587  acc_elem = acc_elem + my_iterator->second; // nbList;
588  if (acc_elem > total_elems / 2.0) {
589  medianval = my_iterator->first;
590  break;
591  }
592  // iterator->first = key
593  // iterator->second = value
594  } // iterator
595 
596  this->retVal = medianval;
597  // this->retVal.push_back(xSum/tSum);
598  }
599 
600  }; // END measMedianValFunc
609  template <class T>
610  T medianVal(const Image<T> &imIn, bool onlyNonZero = true)
611  {
612  measMedianValFunc<T> func;
613  return func(imIn, onlyNonZero);
614  }
615 
616  //
617  // ##### ##### #### ###### # # ######
618  // # # # # # # # # # #
619  // # # # # # # ##### # # #####
620  // ##### ##### # # # # # #
621  // # # # # # # # # #
622  // # # # #### # # ###### ######
623  //
634  template <class T>
635  vector<T> profile(const Image<T> &im, size_t x0, size_t y0, size_t x1,
636  size_t y1, size_t z = 0)
637  {
638  vector<T> vec;
639  ASSERT(im.isAllocated(), vec);
640 
641  size_t imW = im.getWidth();
642  size_t imH = im.getHeight();
643 
644  vector<IntPoint> bPoints;
645  if (x0 >= imW || y0 >= imH || x1 >= imW || y1 >= imH)
646  bPoints = bresenhamPoints(x0, y0, x1, y1, imW, imH);
647  else
648  // no image range check (faster)
649  bPoints = bresenhamPoints(x0, y0, x1, y1);
650 
651  typename Image<T>::sliceType lines = im.getSlices()[z];
652 
653  for (vector<IntPoint>::iterator it = bPoints.begin(); it != bPoints.end();
654  it++)
655  vec.push_back(lines[(*it).y][(*it).x]);
656 
657  return vec;
658  }
659 
660  //
661  // ##### ## ##### # # #### ###### # # ##### ###### #####
662  // # # # # # # # # # # # ## # # # # #
663  // ##### # # # # # # ##### # # # # ##### # #
664  // # # ###### ##### # # # # # # # # #####
665  // # # # # # # # # # # # ## # # # #
666  // ##### # # # # # #### ###### # # # ###### # #
667  //
669  template <class T>
670  struct measBarycenterFunc : public MeasureFunctionWithPos<T, Vector_double> {
671  typedef typename Image<T>::lineType lineType;
672  double xSum, ySum, zSum, tSum;
673  virtual void initialize(const Image<T> & /*imIn*/)
674  {
675  this->retVal.clear();
676  xSum = ySum = zSum = tSum = 0.;
677  }
678  virtual void processSequence(lineType lineIn, size_t size, size_t x,
679  size_t y, size_t z)
680  {
681  for (size_t i = 0; i < size; i++, x++) {
682  T pixVal = lineIn[i];
683  xSum += double(pixVal) * x;
684  ySum += double(pixVal) * y;
685  zSum += double(pixVal) * z;
686  tSum += double(pixVal);
687  }
688  }
689  virtual void finalize(const Image<T> &imIn)
690  {
691  this->retVal.push_back(xSum / tSum);
692  this->retVal.push_back(ySum / tSum);
693  if (imIn.getDimension() == 3)
694  this->retVal.push_back(zSum / tSum);
695  }
696  };
704  template <class T>
706  {
707  measBarycenterFunc<T> func;
708  return func(im, false);
709  }
710 
711  //
712  // ##### #### # # # # ##### ##### #### # #
713  // # # # # # # ## # # # # # # # # #
714  // ##### # # # # # # # # # ##### # # ##
715  // # # # # # # # # # # # # # # # ##
716  // # # # # # # # ## # # # # # # # #
717  // ##### #### #### # # ##### ##### #### # #
718  //
720  template <class T>
721  struct measBoundBoxFunc : public MeasureFunctionWithPos<T, vector<size_t>> {
722  typedef typename Image<T>::lineType lineType;
723  double xMin, xMax, yMin, yMax, zMin, zMax;
724  bool im3d;
725  virtual void initialize(const Image<T> &imIn)
726  {
727  this->retVal.clear();
728  size_t imSize[3];
729  imIn.getSize(imSize);
730  im3d = (imSize[2] > 1);
731 
732  xMin = imSize[0];
733  xMax = 0;
734  yMin = imSize[1];
735  yMax = 0;
736  zMin = imSize[2];
737  zMax = 0;
738  }
739  virtual void processSequence(lineType /*lineIn*/, size_t size, size_t x,
740  size_t y, size_t z)
741  {
742  if (x < xMin)
743  xMin = x;
744  if (x + size - 1 > xMax)
745  xMax = x + size - 1;
746  if (y < yMin)
747  yMin = y;
748  if (y > yMax)
749  yMax = y;
750  if (im3d) {
751  if (z < zMin)
752  zMin = z;
753  if (z > zMax)
754  zMax = z;
755  }
756  }
757  virtual void finalize(const Image<T> & /*imIn*/)
758  {
759  this->retVal.push_back(UINT(xMin));
760  this->retVal.push_back(UINT(yMin));
761  if (im3d)
762  this->retVal.push_back(UINT(zMin));
763  this->retVal.push_back(UINT(xMax));
764  this->retVal.push_back(UINT(yMax));
765  if (im3d)
766  this->retVal.push_back(UINT(zMax));
767  }
768  };
778  template <class T>
779  vector<size_t> measBoundBox(Image<T> &im)
780  {
781  measBoundBoxFunc<T> func;
782  return func(im, true);
783  }
784 
785  //
786  // # # #### # # ###### # # ##### ####
787  // ## ## # # ## ## # ## # # #
788  // # ## # # # # ## # ##### # # # # ####
789  // # # # # # # # # # # # #
790  // # # # # # # # # ## # # #
791  // # # #### # # ###### # # # ####
792  //
794  template <class T>
795  struct measMomentsFunc : public MeasureFunctionWithPos<T, Vector_double> {
796  typedef typename Image<T>::lineType lineType;
797  double m000, m100, m010, m110, m200, m020, m001, m101, m011, m002;
798  bool im3d;
799  virtual void initialize(const Image<T> &imIn)
800  {
801  im3d = (imIn.getDimension() == 3);
802  this->retVal.clear();
803  m000 = m100 = m010 = m110 = m200 = m020 = m001 = m101 = m011 = m002 = 0.;
804  }
805  virtual void processSequence(lineType lineIn, size_t size, size_t x,
806  size_t y, size_t z)
807  {
808  for (size_t i = 0; i < size; i++, x++) {
809  double pxVal = double(lineIn[i]);
810  m000 += pxVal;
811  m100 += pxVal * x;
812  m010 += pxVal * y;
813  m110 += pxVal * x * y;
814  m200 += pxVal * x * x;
815  m020 += pxVal * y * y;
816  if (im3d) {
817  m001 += pxVal * z;
818  m101 += pxVal * x * z;
819  m011 += pxVal * y * z;
820  m002 += pxVal * z * z;
821  }
822  }
823  }
824  virtual void finalize(const Image<T> & /*imIn*/)
825  {
826  this->retVal.push_back(m000);
827  this->retVal.push_back(m100);
828  this->retVal.push_back(m010);
829  if (im3d)
830  this->retVal.push_back(m001);
831  this->retVal.push_back(m110);
832  if (im3d) {
833  this->retVal.push_back(m101);
834  this->retVal.push_back(m011);
835  }
836  this->retVal.push_back(m200);
837  this->retVal.push_back(m020);
838  if (im3d)
839  this->retVal.push_back(m002);
840  }
841  };
845  inline Vector_double centerMoments(Vector_double &moments)
846  {
847  double EPSILON = 1e-8;
848 
849  Vector_double m(moments.size(), 0);
850  if (moments[0] < EPSILON)
851  return m;
852 
853  bool im3d = (moments.size() == 10);
854 
855  /* Moments order in moment vector :
856  * 2D - m00 m10 m01 m11 m20 m02
857  * 3D - m000 m100 m010 m001 m110 m101 m011 m200 m020 m002
858  */
859  m = moments;
860  if (im3d) {
861  // m000
862  m[0] = moments[0];
863  // m100 m010 m001
864  m[1] = 0.;
865  m[2] = 0.;
866  m[3] = 0.;
867  // m110 m101 m011
868  m[4] -= moments[2] * moments[1] / moments[0];
869  m[5] -= moments[3] * moments[1] / moments[0];
870  m[6] -= moments[3] * moments[2] / moments[0];
871  // m200 m020 m002
872  m[7] -= moments[1] * moments[1] / moments[0];
873  m[8] -= moments[2] * moments[2] / moments[0];
874  m[9] -= moments[3] * moments[3] / moments[0];
875  } else {
876  // m00
877  m[0] = moments[0];
878  // m10 m01
879  m[1] = 0.;
880  m[2] = 0.;
881  // m11
882  m[3] -= moments[2] * moments[1] / moments[0];
883  // m20 m02
884  m[4] -= moments[1] * moments[1] / moments[0];
885  m[5] -= moments[2] * moments[2] / moments[0];
886  }
887 
888  return m;
889  }
930  template <class T>
931  Vector_double measMoments(Image<T> &im, const bool onlyNonZero = true,
932  const bool centered = false)
933  {
934  Vector_double m;
935 
936  measMomentsFunc<T> func;
937  m = func(im, onlyNonZero);
938 
939  if (centered)
940  m = centerMoments(m);
941 
942  return m;
943  }
944 
945  //
946  // #### #### # # ## ##### # ## # # #### ######
947  // # # # # # # # # # # # # # ## # # # #
948  // # # # # # # # # # # # # # # # # #####
949  // # # # # # ###### ##### # ###### # # # # #
950  // # # # # # # # # # # # # # # ## # # #
951  // #### #### ## # # # # # # # # # #### ######
952  //
953  template <class T>
954  inline vector<double>
955  genericCovariance(const Image<T> &imIn1, const Image<T> &imIn2, size_t dx,
956  size_t dy, size_t dz, size_t maxSteps = 0,
957  bool normalize = false)
958  {
959  vector<double> vec;
960  ASSERT(areAllocated(&imIn1, &imIn2, NULL), vec);
961  ASSERT(haveSameSize(&imIn1, &imIn2, NULL),
962  "Input images must have the same size", vec);
963  ASSERT((dx + dy + dz > 0),
964  "dx, dy and dz can't be all zero at the same time", vec);
965 
966  size_t s[3];
967  imIn1.getSize(s);
968 
969  size_t maxH = max(max(s[0], s[1]), s[2]);
970  if (dx > 0)
971  maxH = min(maxH, s[0]);
972  if (dy > 0)
973  maxH = min(maxH, s[1]);
974  if (dz > 0)
975  maxH = min(maxH, s[2]);
976  if (maxH > 0)
977  maxH--;
978 
979  if (maxSteps == 0)
980  maxSteps = maxH;
981 
982  maxSteps = min(maxSteps, maxH);
983  if (maxSteps == 0) {
984  ERR_MSG("Too small");
985  return vec;
986  }
987 
988  vec.clear();
989 
990  typename ImDtTypes<T>::volType slicesIn1 = imIn1.getSlices();
991  typename ImDtTypes<T>::volType slicesIn2 = imIn2.getSlices();
992  typename ImDtTypes<T>::sliceType curSliceIn1;
993  typename ImDtTypes<T>::sliceType curSliceIn2;
994  typename ImDtTypes<T>::lineType lineIn1;
995  typename ImDtTypes<T>::lineType lineIn2;
996  typename ImDtTypes<T>::lineType bufLine = ImDtTypes<T>::createLine(s[0]);
997 
998  for (size_t len = 0; len <= maxSteps; len++) {
999  double prod = 0;
1000 
1001  size_t mdx = min(dx * len, s[0] - 1);
1002  size_t mdy = min(dy * len, s[1] - 1);
1003  size_t mdz = min(dz * len, s[2] - 1);
1004 
1005  size_t xLen = s[0] - mdx;
1006  size_t yLen = s[1] - mdy;
1007  size_t zLen = s[2] - mdz;
1008 
1009  for (size_t z = 0; z < zLen; z++) {
1010  curSliceIn1 = slicesIn1[z];
1011  curSliceIn2 = slicesIn2[z + mdz];
1012  for (size_t y = 0; y < yLen; y++) {
1013  lineIn1 = curSliceIn1[y];
1014  lineIn2 = curSliceIn2[y + mdy];
1015  copyLine<T>(lineIn2 + mdx, xLen, bufLine);
1016  // Vectorized loop
1017  for (size_t x = 0; x < xLen; x++) {
1018  prod += lineIn1[x] * bufLine[x];
1019  }
1020  }
1021  }
1022  if (xLen * yLen * zLen != 0)
1023  prod /= (xLen * yLen * zLen);
1024  vec.push_back(prod);
1025  }
1026 
1027  if (normalize) {
1028  double orig = vec[0];
1029  for (vector<double>::iterator it = vec.begin(); it != vec.end(); it++)
1030  *it /= orig;
1031  }
1032 
1033  ImDtTypes<T>::deleteLine(bufLine);
1034 
1035  return vec;
1036  }
1037 #if 0
1038  /*
1039  * measCovariance() - Covariance of two images in the direction defined by
1040  * @b dx, @b dy and @b dz.
1041  *
1042  * The direction is given by @b dx, @b dy and @b dz.
1043  *
1044  * The lenght corresponds to the max number of steps @b maxSteps. When @b 0,
1045  * the length is limited by the dimensions of the image.
1046  *
1047  * @f[
1048  * vec[h] = \sum_{p \:\in\: imIn1} \frac{imIn1(p) \;.\; imIn2(p + h)}{N_p}
1049  * @f]
1050  *
1051  * @f[
1052  * vec[h] = \sum_{p \:\in\: imIn1} \frac{(imIn1(p) - meanVal(imIn1))
1053  * \;.\; (imIn2(p + h) - meanVal(imIn2))}{N_p}
1054  * @f]
1055  * where @b h are displacements in the direction defined by @b dx, @b dy and
1056  * @b dz.
1057  *
1058  * @f$N_p@f$ is the number of pixels used in each term of the sum, which may
1059  * different for each term in the sum.
1060  *
1061  * @param[in] imIn1, imIn2 : Input Images
1062  * @param[in] dx, dy, dz : direction
1063  * @param[in] maxSteps : number maximum of displacements to evaluate
1064  * @param[in] normalize : normalize result with respect to @b vec[0]
1065  * @return vec[h]
1066  */
1067  template <class T>
1068  vector<double> measCovariance(const Image<T> &imIn1, const Image<T> &imIn2,
1069  size_t dx, size_t dy, size_t dz,
1070  size_t maxSteps = 0, bool normalize = false)
1071  {
1072  vector<double> vec;
1073  ASSERT(areAllocated(&imIn1, &imIn2, NULL), vec);
1074  ASSERT(haveSameSize(&imIn1, &imIn2, NULL),
1075  "Input images must have the same size", vec);
1076  ASSERT((dx + dy + dz > 0),
1077  "dx, dy and dz can't be all zero at the same time", vec);
1078 
1079  size_t s[3];
1080  imIn1.getSize(s);
1081 
1082  size_t maxH = max(max(s[0], s[1]), s[2]);
1083  if (dx > 0)
1084  maxH = min(maxH, s[0]);
1085  if (dy > 0)
1086  maxH = min(maxH, s[1]);
1087  if (dz > 0)
1088  maxH = min(maxH, s[2]);
1089  if (maxH > 0)
1090  maxH--;
1091 
1092  if (maxSteps == 0)
1093  maxSteps = maxH;
1094 
1095  maxSteps = min(maxSteps, maxH);
1096  if (maxSteps == 0) {
1097  ERR_MSG("Too small");
1098  return vec;
1099  }
1100 
1101  vec.clear();
1102 
1103  typename ImDtTypes<T>::volType slicesIn1 = imIn1.getSlices();
1104  typename ImDtTypes<T>::volType slicesIn2 = imIn2.getSlices();
1105  typename ImDtTypes<T>::sliceType curSliceIn1;
1106  typename ImDtTypes<T>::sliceType curSliceIn2;
1107  typename ImDtTypes<T>::lineType lineIn1;
1108  typename ImDtTypes<T>::lineType lineIn2;
1109  typename ImDtTypes<T>::lineType bufLine = ImDtTypes<T>::createLine(s[0]);
1110 
1111  for (size_t len = 0; len <= maxSteps; len++) {
1112  double prod = 0;
1113 
1114  size_t mdx = min(dx * len, s[0] - 1);
1115  size_t mdy = min(dy * len, s[1] - 1);
1116  size_t mdz = min(dz * len, s[2] - 1);
1117 
1118  size_t xLen = s[0] - mdx;
1119  size_t yLen = s[1] - mdy;
1120  size_t zLen = s[2] - mdz;
1121 
1122  for (size_t z = 0; z < zLen; z++) {
1123  curSliceIn1 = slicesIn1[z];
1124  curSliceIn2 = slicesIn2[z + mdz];
1125  for (size_t y = 0; y < yLen; y++) {
1126  lineIn1 = curSliceIn1[y];
1127  lineIn2 = curSliceIn2[y + mdy];
1128  copyLine<T>(lineIn2 + mdx, xLen, bufLine);
1129  // Vectorized loop
1130  for (size_t x = 0; x < xLen; x++) {
1131  prod += lineIn1[x] * bufLine[x];
1132  }
1133  }
1134  }
1135  if (xLen * yLen * zLen != 0)
1136  prod /= (xLen * yLen * zLen);
1137  vec.push_back(prod);
1138  }
1139 
1140  if (normalize) {
1141  double orig = vec[0];
1142  for (vector<double>::iterator it = vec.begin(); it != vec.end(); it++)
1143  *it /= orig;
1144  }
1145 
1146  ImDtTypes<T>::deleteLine(bufLine);
1147 
1148  return vec;
1149  }
1150 #endif
1151 
1182  template <class T>
1183  vector<double> measCovariance(const Image<T> &imIn1, const Image<T> &imIn2,
1184  size_t dx, size_t dy, size_t dz,
1185  size_t maxSteps = 0, bool centered = false,
1186  bool normalize = false)
1187  {
1188  if (centered) {
1189  Image<float> imMean1(imIn1, true);
1190  float meanV1 = meanVal(imMean1)[0];
1191  sub(imMean1, meanV1, imMean1);
1192 
1193  Image<float> imMean2(imIn2, true);
1194  float meanV2 = meanVal(imMean2)[0];
1195  sub(imMean2, meanV2, imMean2);
1196 
1197  return genericCovariance(imMean1, imMean2, dx, dy, dz, maxSteps,
1198  normalize);
1199  } else {
1200  return genericCovariance(imIn1, imIn2, dx, dy, dz, maxSteps, normalize);
1201  }
1202  }
1203 
1218  template <class T>
1219  vector<double> measAutoCovariance(const Image<T> &imIn, size_t dx, size_t dy,
1220  size_t dz, size_t maxSteps = 0,
1221  bool centered = false,
1222  bool normalize = false)
1223  {
1224  if (centered) {
1225  Image<float> imMean(imIn, true);
1226  float meanV = meanVal(imMean)[0];
1227  sub(imMean, meanV, imMean);
1228  return genericCovariance(imMean, imMean, dx, dy, dz, maxSteps, normalize);
1229  } else {
1230  return genericCovariance(imIn, imIn, dx, dy, dz, maxSteps, normalize);
1231  }
1232  }
1233 
1234  //
1235  // ###### # # ##### ##### #### ##### # #
1236  // # ## # # # # # # # # # #
1237  // ##### # # # # # # # # # # #
1238  // # # # # # ##### # # ##### #
1239  // # # ## # # # # # # #
1240  // ###### # # # # # #### # #
1241  //
1243  template <class T>
1244  struct measEntropyFunc : public MeasureFunctionBase<T, double> {
1245  typedef typename Image<T>::lineType lineType;
1246 
1247  map<T, UINT> histo;
1248 
1249  virtual void initialize(const Image<T> & /*imIn*/)
1250  {
1251  histo.clear();
1252  }
1253 
1254  virtual void processSequence(lineType lineIn, size_t size)
1255  {
1256  for (size_t i = 0; i < size; i++) {
1257  T val = lineIn[i];
1258 
1259  UINT nb = histo[val];
1260  histo[val] = ++nb;
1261  }
1262  }
1263 
1264  virtual void finalize(const Image<T> & /*imIn*/)
1265  {
1266  double entropy = 0.;
1267  double sumP = 0.;
1268  double sumN = 0.;
1269 
1270  typename map<T, UINT>::iterator it;
1271  for (it = histo.begin(); it != histo.end(); it++) {
1272  if (it->second > 0) {
1273  sumN += it->second;
1274  sumP += it->second * log2(it->second);
1275  }
1276  }
1277  if (sumN > 0)
1278  entropy = log2(sumN) - sumP / sumN;
1279 
1280  this->retVal = entropy;
1281  }
1282  }; // END measEntropyFunc
1283 
1296  template <class T>
1297  double measEntropy(const Image<T> &imIn)
1298  {
1299  ASSERT_ALLOCATED(&imIn);
1300 
1301 #if 0
1302  double entropy = 0.;
1303  double sumP = 0.;
1304  double sumN = 0.;
1305 
1306  map<T, UINT> hist = histogram(imIn, false);
1307  typename map<T, UINT>::iterator it;
1308  for (it = hist.begin(); it != hist.end(); it++) {
1309  if (it->second > 0) {
1310  sumP += it->second * log2(it->second);
1311  sumN += it->second;
1312  }
1313  }
1314 
1315  if (sumN > 0)
1316  entropy = log2(sumN) - sumP / sumN;
1317 
1318  return entropy;
1319 #else
1320  measEntropyFunc<T> func;
1321  return func(imIn, false);
1322 #endif
1323  }
1324 
1337  template <class T>
1338  double measEntropy(const Image<T> &imIn, const Image<T> &imMask)
1339  {
1340  ASSERT_ALLOCATED(&imIn, &imMask);
1341  ASSERT_SAME_SIZE(&imIn, &imMask);
1342 
1343  double entropy = 0.;
1344  double sumP = 0.;
1345  double sumN = 0.;
1346 
1347  map<T, UINT> hist = histogram(imIn, imMask, false);
1348  typename map<T, UINT>::iterator it;
1349  for (it = hist.begin(); it != hist.end(); it++) {
1350  if (it->second > 0) {
1351  sumP += it->second * log2(it->second);
1352  sumN += it->second;
1353  }
1354  }
1355 
1356  if (sumN > 0)
1357  entropy = log2(sumN) - sumP / sumN;
1358 
1359  return entropy;
1360  }
1361 
1362  //
1363  // #### ##### # # ###### ##### ####
1364  // # # # # # # # # #
1365  // # # # ###### ##### # # ####
1366  // # # # # # # ##### #
1367  // # # # # # # # # # #
1368  // #### # # # ###### # # ####
1369  //
1378  template <class T>
1380  {
1381  Vector_size_t offsets;
1382 
1383  ASSERT(CHECK_ALLOCATED(&imIn), RES_ERR_BAD_ALLOCATION, offsets);
1384 
1385  typename Image<T>::lineType pixels = imIn.getPixels();
1386 
1387  for (size_t i = 0; i < imIn.getPixelCount(); i++)
1388  if (pixels[i] != 0)
1389  offsets.push_back(i);
1390 
1391  return offsets;
1392  }
1393 
1401  template <class T>
1402  bool isBinary(const Image<T> &imIn)
1403  {
1404  CHECK_ALLOCATED(&imIn);
1405 
1406  map<T, bool> h;
1407  typename Image<T>::lineType pixels = imIn.getPixels();
1408 
1409 #if 1
1410  // Not using OpenMP
1411 
1412  for (size_t i = 0; i < imIn.getPixelCount(); i++) {
1413  h[pixels[i]] = true;
1414  if (h.size() > 2)
1415  return false;
1416  }
1417 #else
1418  // Using OpenMP
1419 #ifdef USE_OPEN_MP
1420 #pragma omp parallel for
1421 #endif
1422  for (size_t i = 0; i < imIn.getPixelCount() && h.size() <= 2; i++) {
1423  h[pixels[i]] = True;
1424  }
1425 #endif
1426 
1427  return h[0] > 0 && h.size() == 2;
1428  }
1429 
1432 } // namespace smil
1433 
1434 #endif // _D_MEASURES_HPP
bool isAllocated() const
Check if the image is allocated.
Definition: DBaseImage.h:176
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:80
size_t getPixelCount() const
Get the number of pixels.
Definition: DBaseImage.h:160
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:85
Main Image class.
Definition: DImage.hpp:57
volType getSlices() const
Get an array containing the start offset of each slice.
Definition: DImage.hpp:117
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:105
Struct Point.
Definition: DCommon.h:125
RES_T sqrt(const Image< T1 > &imIn, Image< T2 > &imOut)
sqrt() - square root of an image
Definition: DImageArith.hpp:926
RES_T sub(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
sub() - Subtraction between two images
Definition: DImageArith.hpp:160
vector< size_t > Vector_size_t
Vector_size_t.
Definition: DCommon.h:242
vector< double > Vector_double
Vector_double.
Definition: DCommon.h:224
vector< IntPoint > bresenhamPoints(int p1x, int p1y, int p2x, int p2y, int xMax=0, int yMax=0)
Find intermediate points forming a line between two end points, using the Bresenham Line Draw Algorit...
Definition: DImageDraw.h:62
histogram(const Image< T > &imIn, size_t *h)
Image histogram.
Definition: DImageHistogram.hpp:64
vector< T > rangeVal(const Image< T > &imIn, bool onlyNonZero=false)
rangeVal() - Min and Max values of an image
Definition: DMeasures.hpp:416
Vector_size_t nonZeroOffsets(Image< T > &imIn)
nonZeroOffsets() - Returns the offsets of pixels having non nul values.
Definition: DMeasures.hpp:1379
T modeVal(const Image< T > &imIn, bool onlyNonZero=true)
modeVal() - Get the mode of the histogram present in the image, i.e.
Definition: DMeasures.hpp:534
double vol(const Image< T > &imIn)
vol() - Volume of an image
Definition: DMeasures.hpp:129
double volume(const Image< T > &imIn)
colume() - Volume of an image
Definition: DMeasures.hpp:154
double measEntropy(const Image< T > &imIn, const Image< T > &imMask)
measEntropy() - Image entropy
Definition: DMeasures.hpp:1338
vector< T > valueList(const Image< T > &imIn, bool onlyNonZero=true)
valueList() - Get the list of the pixel values present in the image
Definition: DMeasures.hpp:468
vector< double > measCovariance(const Image< T > &imIn1, const Image< T > &imIn2, size_t dx, size_t dy, size_t dz, size_t maxSteps=0, bool centered=false, bool normalize=false)
measCovariance() - Centered covariance of two images in the direction defined by dx,...
Definition: DMeasures.hpp:1183
T maxVal(const Image< T > &imIn, Point< UINT > &pt, bool onlyNonZero=false)
maxVal() - Max value of an image
Definition: DMeasures.hpp:363
Vector_double measBarycenter(Image< T > &im)
measBarycenter() - Gets the barycenter coordinates of an image
Definition: DMeasures.hpp:705
vector< size_t > measBoundBox(Image< T > &im)
measBoundBox() - Bounding Box measure - gets the coordinates of the bounding box
Definition: DMeasures.hpp:779
Vector_double meanVal(const Image< T > &imIn, bool onlyNonZero=false)
meanVal() - Mean value and standard deviation
Definition: DMeasures.hpp:211
bool isBinary(const Image< T > &imIn)
isBinary() - Test if an image is binary.
Definition: DMeasures.hpp:1402
Vector_double measMoments(Image< T > &im, const bool onlyNonZero=true, const bool centered=false)
measMoments() - Measure image moments
Definition: DMeasures.hpp:931
T minVal(const Image< T > &imIn, Point< UINT > &pt, bool onlyNonZero=false)
minVal() - Min value of an image
Definition: DMeasures.hpp:286
T medianVal(const Image< T > &imIn, bool onlyNonZero=true)
medianVal() - Get the median of the image histogram.
Definition: DMeasures.hpp:610
size_t area(const Image< T > &imIn)
area() - Area of an image
Definition: DMeasures.hpp:91
vector< double > measAutoCovariance(const Image< T > &imIn, size_t dx, size_t dy, size_t dz, size_t maxSteps=0, bool centered=false, bool normalize=false)
measAutoCovariance() - Auto-covariance
Definition: DMeasures.hpp:1219
vector< T > profile(const Image< T > &im, size_t x0, size_t y0, size_t x1, size_t y1, size_t z=0)
profile() - Get image values along a line defined by the points and in the slice .
Definition: DMeasures.hpp:635
RES_T copy(const Image< T1 > &imIn, size_t startX, size_t startY, size_t startZ, size_t sizeX, size_t sizeY, size_t sizeZ, Image< T2 > &imOut, size_t outStartX=0, size_t outStartY=0, size_t outStartZ=0)
copy() - Copy image (or a zone) into an output image
Definition: DImageTransform.hpp:84