aimsalgo  5.1.2
Neuroimaging image processing
peronaMalikSmoother_d.h
Go to the documentation of this file.
1 /* This software and supporting documentation are distributed by
2  * Institut Federatif de Recherche 49
3  * CEA/NeuroSpin, Batiment 145,
4  * 91191 Gif-sur-Yvette cedex
5  * France
6  *
7  * This software is governed by the CeCILL-B license under
8  * French law and abiding by the rules of distribution of free software.
9  * You can use, modify and/or redistribute the software under the
10  * terms of the CeCILL-B license as circulated by CEA, CNRS
11  * and INRIA at the following URL "http://www.cecill.info".
12  *
13  * As a counterpart to the access to the source code and rights to copy,
14  * modify and redistribute granted by the license, users are provided only
15  * with a limited warranty and the software's author, the holder of the
16  * economic rights, and the successive licensors have only limited
17  * liability.
18  *
19  * In this respect, the user's attention is drawn to the risks associated
20  * with loading, using, modifying and/or developing or reproducing the
21  * software by the user in light of its specific status of free software,
22  * that may mean that it is complicated to manipulate, and that also
23  * therefore means that it is reserved for developers and experienced
24  * professionals having in-depth computer knowledge. Users are therefore
25  * encouraged to load and test the software's suitability as regards their
26  * requirements in conditions enabling the security of their systems and/or
27  * data to be ensured and, more generally, to use and operate it in the
28  * same conditions as regards security.
29  *
30  * The fact that you are presently reading this means that you have had
31  * knowledge of the CeCILL-B license and that you accept its terms.
32  */
33 
34 
35 #ifndef AIMS_PRIMALSKETCH_PERONAMALIKSMOOTHER_D_H
36 #define AIMS_PRIMALSKETCH_PERONAMALIKSMOOTHER_D_H
37 
38 #include <cstdlib>
42 
43 namespace aims
44 {
45 
46  template<class T> carto::VolumeRef<T>
48  int maxiter, bool /*verbose*/ )
49  {
50  if (maxiter >= 0)
51  {
52  carto::VolumeRef<float> kernel( 3, 3, 3, 1,
53  carto::AllocatorContext::fast() );
54  carto::VolumeRef<float> *tmp1, *tmp2, *swap, grad;
55  int i;
56  int x,y,z, count=0;
57  int sx=ima->getSizeX(), sy=ima->getSizeY(), sz=ima->getSizeZ();
58  std::map<float, int> valueSet;
59  std::map<float,int>::iterator itVal;
60  float nbThresh;
61  float gxm, gxp, gym, gyp, gzm, gzp, cxm, cxp, cym, cyp, czm, czp;
62 
66 
68  conv;
69  carto::VolumeRef< float > imaF( ima->getSize() ),
70  ima2( ima->getSize() );
71  conv.convert( ima, imaF );
72 
73 
74  std::cout << "Evaluating gradient bound : " << std::endl;
75 
76  grad=gaussGrad.doit(imaF);
77 // Writer<carto::VolumeRef<float> > writerG( "gradient.ima" );
78 // writerG.write( grad );
79 
80  // Evaluation of the gradient parameter from K
81 
82  std::cout << "Ordering values" << std::endl;
83 
84  nbThresh=sx*sz*sy*_K;
85 
86  for (z=0; z<sz; z++)
87  for (y=0; y<sy; y++)
88  for (x=0; x<sx; x++)
89  {
90  if (valueSet.find(grad(x,y,z)) != valueSet.end())
91  valueSet[grad(x,y,z)]++;
92  else
93  valueSet.insert(std::pair<float,int>(grad(x,y,z), 1));
94  }
95  itVal=valueSet.begin();
96 
97  std::cout << "Looking for bound with K= " << _K << " at value number " << nbThresh << std::endl;
98  for (; itVal!=valueSet.end(); ++itVal)
99  {
100  count+=(*itVal).second;
101  if ((count>=nbThresh) && ((count-1)<nbThresh))
102  _gradK=(*itVal).first;
103  }
104  std::cout << "Gradient bound has been set to " << _gradK << std::endl;
105 
106  tmp1=&imaF; tmp2=&ima2;
107  std::cout << "Starting " << maxiter << " iterations of diffusion process" << std::endl;
108 
109  for (i=0; i<maxiter; i++)
110  {
111  std::cout << "+" << std::flush;
112  grad=gaussGrad.doit((*tmp1));
113 
114  for (z=0; z<sz; z++)
115  for (y=0; y<sy; y++)
116  for (x=0; x<sx; x++)
117  {
118  if (x==0)
119  {
120  gxm=0; gxp=(*tmp1)(x+1,y,z) - (*tmp1)(x,y,z);
121  cxm=0; cxp=conductance( (grad(x+1,y,z)+grad(x,y,z))/2.0);
122  }
123  else if (x==sx-1)
124  {
125  gxm=(*tmp1)(x-1,y,z) - (*tmp1)(x,y,z); gxp=0;
126  cxm=conductance( (grad(x-1,y,z)+grad(x,y,z))/2.0); cxp=0;
127  }
128  else
129  {
130  gxm=(*tmp1)(x-1,y,z) - (*tmp1)(x,y,z); gxp=(*tmp1)(x+1,y,z) - (*tmp1)(x,y,z);
131  cxm=conductance( (grad(x-1,y,z)+grad(x,y,z))/2.0); cxp=conductance( (grad(x+1,y,z)+grad(x,y,z))/2.0);
132  }
133 
134  if (y==0)
135  {
136  gym=0; gyp=(*tmp1)(x,y+1,z) - (*tmp1)(x,y,z);
137  cym=0; cyp=conductance( (grad(x,y+1,z)+grad(x,y,z))/2.0);
138  }
139  else if (y==sy-1)
140  {
141  gym=(*tmp1)(x,y-1,z) - (*tmp1)(x,y,z); gyp=0;
142  cym=conductance( (grad(x,y-1,z)+grad(x,y,z))/2.0); cyp=0;
143  }
144  else
145  {
146  gym=(*tmp1)(x,y-1,z) - (*tmp1)(x,y,z); gyp=(*tmp1)(x,y+1,z) - (*tmp1)(x,y,z);
147  cym=conductance( (grad(x,y-1,z)+grad(x,y,z))/2.0); cyp=conductance( (grad(x,y+1,z)+grad(x,y,z))/2.0);
148  }
149 
150  if (z==0)
151  {
152  gzm=0; gzp=(*tmp1)(x,y,z+1) - (*tmp1)(x,y,z);
153  czm=0; czp=conductance( (grad(x,y,z+1)+grad(x,y,z))/2.0);
154  }
155  else if (z==sz-1)
156  {
157  gzm=(*tmp1)(x,y,z-1) - (*tmp1)(x,y,z); gzp=0;
158  czm=conductance( (grad(x,y,z-1)+grad(x,y,z))/2.0); czp=0;
159  }
160  else
161  {
162  gzm=(*tmp1)(x,y,z-1) - (*tmp1)(x,y,z); gzp=(*tmp1)(x,y,z+1) - (*tmp1)(x,y,z);
163  czm=conductance( (grad(x,y,z-1)+grad(x,y,z))/2.0); czp=conductance( (grad(x,y,z+1)+grad(x,y,z))/2.0);
164  }
165 
166  (*tmp2)(x,y,z)=(*tmp1)(x,y,z) + _dt *
167  ( cxm*gxm + cxp*gxp
168  +cym*gym + cyp*gyp
169  +czm*gzm + czp*gzp );
170  }
171  swap=tmp1;
172  tmp1=tmp2;
173  tmp2=swap;
174  }
175  std::cout << "Finished" << std::endl;
177  conv2;
178  carto::VolumeRef<T> ima3( ima->getSize() );
179  conv2.convert( (*tmp1), ima3);
180 
181  return ima3;
182  }
183  else
184  {
185  std::cerr << "PeronaMalik smoother must have tIn < tOut" << std::endl;
186  exit(EXIT_FAILURE);
187  }
188  }
189 
190 }
191 
192 #endif
carto::VolumeRef< float > doit(const carto::rc_ptr< carto::Volume< T > > &)
Definition: ggradient.h:75
carto::VolumeRef< T > doSmoothing(const carto::VolumeRef< T > &ima, int maxiter, bool verbose=false)
virtual void convert(const INP &in, OUTP &out) const
int getSizeZ() const
std::vector< int > getSize() const
int getSizeY() const
iterator begin()
int getSizeX() const
void swap(scoped_ptr< T > &x, scoped_ptr< T > &y)