aimsalgo 6.0.0
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
17#include <cartobase/config/verbose.h>
19#include <aims/utility/threshold.h>
20
21
22template <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
59template <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{
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
87template <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
261template <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
279template <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.
carto::VolumeRef< U > bin(const carto::VolumeRef< T > &image)
Return the binary thresholded image.
carto::VolumeRef< U > bin(const carto::VolumeRef< T > &sqv)
carto::VolumeRef< T > operator()(const carto::VolumeRef< T > &sqv)
AimsThreshold(threshold_t type, T level, T level2=0, T backgd=0, U foregd=(U)(!std::numeric_limits< U >::is_specialized||(std::numeric_limits< U >::max() >=32767) ? 32767 :std::numeric_limits< U >::max()))
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