aimsalgo  5.1.2
Neuroimaging image processing
emthreshold.h
Go to the documentation of this file.
1 /* Copyright (C) 2000-2013 CEA
2  *
3  * This software and supporting documentation were developed by
4  * bioPICSEL
5  * CEA/DSV/I²BM/MIRCen/LMN, Batiment 61,
6  * 18, route du Panorama
7  * 92265 Fontenay-aux-Roses
8  * France
9  */
10 
11 /*
12  * EM Threshold operators
13  */
14 #ifndef AIMS_UTILITY_EMTHRESHOLD_H
15 #define AIMS_UTILITY_EMTHRESHOLD_H
16 
19 #include <aims/utility/threshold.h>
20 
21 
22 template <class T, class U>
24 {
25  public:
26  inline
28  T backgd = 0,
29  float foregd = 32767,
30  int classes = 2,
31  int levelindex = 0, /* Level expressed as index */
32  int level2index = 1, /* Level expressed as index */
33  int bins = 0,
34  int binstart = 0, /* First bin considered during thresholding process */
35  int binend = 0 /* Last bin considered during thresholding process */
36  );
37 
38  virtual ~AimsEMThreshold() {}
39 
40  inline
41  std::vector<T> processEMThresholds(const carto::VolumeRef<T> &image);
42 
45 
47  inline
49 
50  private :
51  int _classes;
52  int _levelindex;
53  int _level2index;
54  int _bins;
55  int _binstart;
56  int _binend;
57 };
58 
59 template <class T, class U> inline
61  T backgd, float foregd,
62  int classes,
63  int levelindex, int levelindex2,
64  int bins,
65  int binstart,
66  int binend )
67  : _classes(classes),
68  _levelindex(levelindex),
69  _level2index(levelindex2),
70  _bins(bins),
71  _binstart(binstart),
72  _binend(binend),
73  AimsThreshold<T, U>( type, 0, 0, backgd, foregd )
74 {
75  if (carto::verbose)
76  {
77  std::cout << "Type " << carto::toString(this->_type) << " ..." << std::endl << std::flush;
78  std::cout << "Backgd " << carto::toString(this->_backgd) << " ..." << std::endl << std::flush;
79  std::cout << "Foregd " << carto::toString(this->_foregd) << " ..." << std::endl << std::flush;
80  std::cout << "Classes " << carto::toString(_classes) << " ..." << std::endl << std::flush;
81  std::cout << "Level index " << carto::toString(_levelindex) << " ..." << std::endl << std::flush;
82  std::cout << "Level 2 index " << carto::toString(_level2index) << " ..." << std::endl << std::flush;
83 // std::cout << "Bins " << carto::toString(_bins) << " ..." << std::endl << std::flush;
84  }
85 }
86 // EM
87 template <class T, class U> inline
89  const carto::VolumeRef<T> &image )
90 {
91  std::vector<T> thresholds, thresholds_mu;
92  int bins = _bins;
93  int binend;
94 
95 
96  T maxi = image.max(), mini = image.min();
97  if ( bins <= 0 )
98  bins = int(maxi - mini);
99 
100  if (!_binend)
101  binend = bins;
102  else
103  binend = _binend + 1;
104 
105  if (carto::verbose)
106  std::cout << "Bins " << carto::toString(bins) << " ..." << std::endl << std::flush;
107 
108  // Histogram
110  his.doit(image);
111 
112  // Declarations
113  carto::VolumeRef<double> th_pi(_classes);
114  carto::VolumeRef<double> th_mu(_classes);
115  carto::VolumeRef<double> th_sigma(_classes);
116  carto::VolumeRef<double> th_tau(bins, _classes);
117  carto::VolumeRef<double> aux(_classes);
118  int n, i, j;
119 
120  // Initialisation of the EM algorithm
121  double scl = (double) bins / (double)( maxi - mini );
122 // std::cout << "scl : " << carto::toString(scl) << std::endl << std::flush;
123  double points_count = 0.;
124  for (n = _binstart; n < binend; ++n)
125  points_count += his.data()(n);
126 
127 // std::cout << "points_count : " << carto::toString(points_count) << std::endl << std::flush;
128  // Same number of points for each EM class
129  double class_points_count = 0.;
130  for (n = _binstart; n < binend; ++n)
131  {
132  class_points_count += his.data()(n);
133  for (i = 0; i < _classes; ++i)
134  {
135  if ((i <= (_classes * class_points_count / points_count))
136  && (i >= (_classes * class_points_count / points_count) - 1))
137  th_tau(n, i) = 1;
138  else
139  th_tau(n, i) = 0;
140  }
141  }
142 
143  // MAIN interation
144  int count = 0;
145  double sum1 = 0, sum2 = 0, sum = 0, sum_aux;
146  while ( count <= (_classes + 1) )
147  {
148  count++;
149 
150  // EM STEP E : calculate expect classification variable tau for each class
151  // the first time jump this step to initialize mu, sigma and pi.
152  if (count > 1)
153  {
154  th_tau = 0.;
155  for (n = _binstart; n < binend; ++n)
156  {
157  for (i = 0; i < _classes; ++i)
158  {
159  aux = 0.;
160  sum_aux = 0.;
161  for (j = 0; j < _classes; ++j)
162  {
163  aux(j) = th_pi(j) * (1 / sqrt(2 * M_PI * th_sigma(j)))
164  * exp(-(1 / (2 * th_sigma(j))) * (n - th_mu(j)) * (n - th_mu(j)));
165  sum_aux += aux(j);
166  }
167  th_tau(n, i) = aux(i) / sum_aux;
168  }
169  }
170  }
171 
172  // EM STEP M : calculate new threshold means and variances for classified data
173  th_mu = 0.; th_sigma = 0.; th_pi = 0.;
174 
175  for (j = 0; j < _classes; ++j)
176  {
177  // Mean and covariance
178  sum1 = 0.;
179  sum2 = 0.;
180  sum = 0.;
181  for (n = _binstart; n < binend; ++n) {
182  sum += th_tau(n, j) * his.data()(n);
183  sum1 += th_tau(n, j) * n * his.data()(n);
184  }
185  th_mu(j) = sum1 / sum;
186 
187  for (n = _binstart; n < binend; ++n)
188  sum2 += th_tau(n, j) * (n - th_mu(j)) * (n - th_mu(j)) * his.data()(n);
189  th_sigma(j) = sum2 / sum;
190 
191  // Classifying variable pi
192  sum1 = 0.;
193  sum = 0.;
194  for (n = _binstart; n < binend; ++n)
195  {
196  sum1 += th_tau(n, j) * his.data()(n);
197  sum += his.data()(n);
198  }
199  th_pi(j) = sum1 / sum;
200  }
201  }
202 
203  // Compute thresholds
204  T level;
205  for (j = 0; j < _classes; ++j)
206  {
207  level = (T)th_mu(j);
208 
209  if (level < 0)
210  level = 0;
211 
212  else if (level > (binend - 1))
213  level = binend - 1;
214 
215  thresholds_mu.push_back(level);
216  }
217 
218  std::sort(thresholds_mu.begin(), thresholds_mu.end());
219 
220  if (carto::verbose) {
221  std::cout << "Found class means : [";
222 
223  for (i = 0; i < _classes; ++i)
224  {
225  // Search for last minimum between class means
226  std::cout << carto::toString((T)(thresholds_mu[i] / scl) + mini);
227  if (i < (_classes - 1))
228  std::cout << ", ";
229  }
230  std::cout << "]" << std::endl << std::flush;
231  }
232 
233  if (carto::verbose)
234  std::cout << "Found thresholds : [";
235 
236  for (i = 0; i < (_classes - 1); ++i)
237  {
238  // Search for last minimum between class means
239  level = thresholds_mu[i];
240  for(int j = thresholds_mu[i]; j <= thresholds_mu[i + 1]; j++)
241  {
242  if (his.data()(j) < his.data()(level))
243  level = j;
244  }
245 
246  thresholds.push_back(((T)(level / scl) + mini));
247 
248  if (carto::verbose) {
249  std::cout << carto::toString(thresholds[i]);
250  if (i < (_classes - 2))
251  std::cout << ", ";
252  }
253  }
254 
255  if (carto::verbose)
256  std::cout << "]" << std::endl << std::flush;
257 
258  return thresholds;
259 }
260 
261 template <class T, class U> inline
263  const carto::VolumeRef<T> &image)
264 {
265  // Threshold
266  std::vector<T> thresholds = processEMThresholds(image);
267  if (_levelindex < thresholds.size())
268  AimsEMThreshold<T, U>::_level = thresholds[_levelindex];
269 
270  if (_level2index < thresholds.size())
271  AimsEMThreshold<T, U>::_level2 = thresholds[_level2index];
272 
273 // std::cout << "Thresholding values ..." << std::endl << std::flush;
275 
276  return thresholded;
277 }
278 
279 template <class T, class U> inline
281  const carto::VolumeRef<T> &image)
282 {
283  // Threshold
284  std::vector<T> thresholds = processEMThresholds(image);
285  if (_levelindex < thresholds.size())
286  AimsEMThreshold<T, U>::_level = thresholds[_levelindex];
287 
288  if (_level2index < thresholds.size())
289  AimsEMThreshold<T, U>::_level2 = thresholds[_level2index];
290 
291  carto::VolumeRef<U> thresholded = AimsThreshold<T, U>::bin( image );
292 
293  return thresholded;
294 }
295 
296 #endif
AimsEMThreshold(threshold_t type, T backgd=0, float foregd=32767, int classes=2, int levelindex=0, int level2index=1, int bins=0, int binstart=0, int binend=0)
Definition: emthreshold.h:60
virtual ~AimsEMThreshold()
Definition: emthreshold.h:38
std::vector< T > processEMThresholds(const carto::VolumeRef< T > &image)
Definition: emthreshold.h:88
carto::VolumeRef< U > operator()(const carto::VolumeRef< T > &image)
Return the multi-level thresholded image.
Definition: emthreshold.h:262
carto::VolumeRef< U > bin(const carto::VolumeRef< T > &image)
Return the binary thresholded image.
Definition: emthreshold.h:280
carto::VolumeRef< U > bin(const carto::VolumeRef< T > &sqv)
carto::VolumeRef< T > operator()(const carto::VolumeRef< T > &sqv)
carto::VolumeRef< int32_t > & data()
return a reference to the data field of the histogram class.
Definition: histogram.h:66
Histogram container class, with a specified number of regular bins.
void doit(const carto::rc_ptr< carto::Volume< T > > &thing)
classical histogram computation function.
std::string toString(const T &object)
int verbose
DataTypeTraits< T >::LongType sum(const Volume< T > &vol)
threshold_t