aimsalgo  5.1.2
Neuroimaging image processing
filteringfunction_linear_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 #ifndef AIMS_SIGNALFILTER_FILTERINGFUNCTION_LINEAR_D_H
35 #define AIMS_SIGNALFILTER_FILTERINGFUNCTION_LINEAR_D_H
36 
37 //--- aims -------------------------------------------------------------------
39 #include <aims/connectivity/structuring_element.h> // aims::StructuringElement
40 #include <aims/io/writer.h>
41 //--- cartodata --------------------------------------------------------------
42 #include <cartodata/volume/volume.h> // carto::VolumeRef
43 //--- cartobase --------------------------------------------------------------
44 #include <cartobase/config/verbose.h> // carto::verbose
45 #include <cartobase/smart/rcptr.h> // carto::rc_ptr
46 //--- std --------------------------------------------------------------------
47 #include <cmath> // std::fabs
48 #include <algorithm> // std::max
49 #include <map>
50 #include <set>
51 #include <string>
52 //----------------------------------------------------------------------------
53 
54 namespace aims {
55 
56 //============================================================================
57 // LINEAR FILTERING FUNCTIONS: FACTORY
58 //============================================================================
59 
60  template <typename T>
62  {
63  static bool initialized = false;
64  if( !initialized )
65  {
66  initialized = true;
67  registerFunction( "gab", GaborFilterFunc<T>() );
68  registerFunction( "gabor", GaborFilterFunc<T>() );
69  }
70  }
71 
72  template <typename T>
73  std::map<std::string,carto::rc_ptr<LinearFilteringFunction<T> > > &
75  {
76  static std::map<std::string,carto::rc_ptr<LinearFilteringFunction<T> > > m;
77  return m;
78  }
79 
80  template <typename T>
82  const std::string & name,
83  const LinearFilteringFunction<T> & func
84  )
85  {
86  init();
87  _map()[ name ] = carto::rc_ptr<LinearFilteringFunction<T> >( func.clone() );
88  }
89 
90  template <typename T>
92  {
93  init();
94  std::set<std::string> s;
95  typename std::map<std::string,carto::rc_ptr<LinearFilteringFunction<T> > >::const_iterator i, e = _map().end();
96  for( i=_map().begin(); i!=e; ++i )
97  s.insert( i->first );
98  return( s );
99  }
100 
101  template <typename T>
103  const std::string & name,
104  carto::Object options
105  )
106  {
107  init();
108  typename std::map<std::string,carto::rc_ptr<LinearFilteringFunction<T> > >::const_iterator i;
109  i = _map().find( name );
110  if( i == _map().end() )
111  return( 0 );
112  LinearFilteringFunction<T> * new_func = i->second->clone();
113  new_func->setOptions( options );
114  return new_func;
115  }
116 
117 //============================================================================
118 // LINEAR FILTERING FUNCTIONS: DERIVED CLASSES
119 //============================================================================
120  //--------------------------------------------------------------------------
121  // GaborFilterFunc
122  //--------------------------------------------------------------------------
123 
124  template <typename T>
125  GaborFilterFunc<T>::GaborFilterFunc( const GaborFilterFunc<T> & other ):
127  _sigma(other._sigma),
128  _theta(other._theta),
129  _lambda(other._lambda),
130  _psi(other._psi),
131  _gamma(other._gamma),
132  _real(other._real),
133  _nstd(other._nstd),
134  _init(other._init),
135  _amplitude(other._amplitude),
136  _voxelsize(other._voxelsize),
137  _kernel(new carto::Volume<double>( *(other._kernel) ))
138  {}
139 
140  template <typename T>
141  GaborFilterFunc<T>::~GaborFilterFunc()
142  {}
143 
144  template <typename T>
145  GaborFilterFunc<T> & GaborFilterFunc<T>::operator=( const GaborFilterFunc<T> & other )
146  {
147  if(this != &other) {
148  _init = other._init ;
149  _sigma = other._sigma;
150  _theta = other._theta;
151  _lambda = other._lambda;
152  _psi = other._psi;
153  _gamma = other._gamma;
154  _real = other._real;
155  _nstd = other._nstd;
156  _voxelsize = other._voxelsize;
157  _amplitude = other._amplitude;
158  _kernel = carto::VolumeRef<double>( new carto::Volume<double>( *(other._kernel) ) );
159  }
160  return *this;
161  }
162 
163  template <typename T>
164  void GaborFilterFunc<T>::setOptions( const carto::Object & options )
165  {
166  _init = false;
167  _sigma = 1.0;
168  _theta = 0.0;
169  _lambda = 1.0;
170  _psi = 0.0;
171  _gamma = 1.0;
172  _real = true;
173  _nstd = 2;
174  _voxelsize = std::vector<float>( 4, 1. );
175  _amplitude = std::vector<int>( 6, 0 );
176 
177  if( options )
178  {
179  if( options->hasProperty( "sigma" ) )
180  _sigma = (double)options->getProperty( "sigma" )->getScalar();
181  if( options->hasProperty( "theta" ) )
182  _theta = (double)options->getProperty( "theta" )->getScalar();
183  if( options->hasProperty( "lambda" ) )
184  _lambda = (double)options->getProperty( "lambda" )->getScalar();
185  if( options->hasProperty( "psi" ) )
186  _psi = (double)options->getProperty( "psi" )->getScalar();
187  if( options->hasProperty( "gamma" ) )
188  _gamma = (double)options->getProperty( "gamma" )->getScalar();
189  if( options->hasProperty( "real" ) )
190  _real = (bool)options->getProperty( "real" )->getScalar();
191  if( options->hasProperty( "nstd" ) )
192  _nstd = (int)options->getProperty( "nstd" )->getScalar();
193  if( options->hasProperty( "voxel_size" ) )
194  options->getProperty( "voxel_size", _voxelsize );
195  }
196 
197  if( carto::verbose )
198  {
199  std::cout << "Gabor Filter created with parameters:" << std::endl
200  << "- sigma: " << _sigma << " mm" << std::endl
201  << "- theta: " << _theta << "°" << std::endl
202  << "- lambda: " << _lambda << " mm" << std::endl
203  << "- psi: " << _psi << "°" << std::endl
204  << "- gamma: " << _gamma << std::endl
205  << "- return " << ( _real ? "real part" : "imaginary part" ) << std::endl
206  << "- nstd: " << _nstd << std::endl
207  << std::endl;
208  }
209 
210  setKernel();
211  }
212 
213  template <typename T>
214  void GaborFilterFunc<T>::updateOptions( const carto::Object & options )
215  {
216  bool changed = false;
217  double oldd;
218  bool oldb;
219  int oldi;
220  std::vector<float> oldv;
221 
222  if( options )
223  {
224  if( options->hasProperty( "sigma" ) ) {
225  oldd = _sigma;
226  _sigma = (double)options->getProperty( "sigma" )->getScalar();
227  if( oldd != _sigma )
228  changed = true;
229  }
230  if( options->hasProperty( "theta" ) ) {
231  oldd = _theta;
232  _theta = (double)options->getProperty( "theta" )->getScalar();
233  if( oldd != _theta )
234  changed = true;
235  }
236  if( options->hasProperty( "lambda" ) ) {
237  oldd = _lambda;
238  _lambda = (double)options->getProperty( "lambda" )->getScalar();
239  if( oldd != _lambda )
240  changed = true;
241  }
242  if( options->hasProperty( "psi" ) ) {
243  oldd = _psi;
244  _psi = (double)options->getProperty( "psi" )->getScalar();
245  if( oldd != _psi )
246  changed = true;
247  }
248  if( options->hasProperty( "gamma" ) ) {
249  oldd = _gamma;
250  _gamma = (double)options->getProperty( "gamma" )->getScalar();
251  if( oldd != _gamma )
252  changed = true;
253  }
254  if( options->hasProperty( "real" ) ) {
255  oldb = _real;
256  _real = (bool)options->getProperty( "real" )->getScalar();
257  if( oldb != _real )
258  changed = true;
259  }
260  if( options->hasProperty( "nstd" ) ) {
261  oldi = _nstd;
262  _nstd = (int)options->getProperty( "nstd" )->getScalar();
263  if( oldi != _nstd )
264  changed = true;
265  }
266  if( options->hasProperty( "voxel_size" ) ) {
267  oldv = _voxelsize;
268  options->getProperty( "voxel_size", _voxelsize );
269  if( oldv != _voxelsize )
270  changed = true;
271  }
272  }
273 
274  if( changed )
275  {
276  if( carto::verbose )
277  std::cout << "Gabor Filter updated with parameters:" << std::endl
278  << "- sigma: " << _sigma << " mm" << std::endl
279  << "- theta: " << _theta << "°" << std::endl
280  << "- lambda: " << _lambda << " mm" << std::endl
281  << "- psi: " << _psi << "°" << std::endl
282  << "- gamma: " << _gamma << std::endl
283  << "- return " << ( _real ? "real part" : "imaginary part" ) << std::endl
284  << "- nstd: " << _nstd << std::endl
285  << std::endl;
286  setKernel();
287  }
288  }
289 
290  template <typename T>
291  const std::vector<int> & GaborFilterFunc<T>::getAmplitude() const
292  {
293  return _amplitude;
294  }
295 
296  template <typename T> inline
298  {
299  if( carto::verbose )
300  std::cout << "setKernel" << std::endl
301  << "- voxel size: "
302  << _voxelsize[0] << ", "
303  << _voxelsize[1] << std::endl;
304 
305  double pi = 3.1415926535897;
306  std::vector<float> famplitude(2,0.);
307  famplitude[0] = std::max(
308  std::fabs( _nstd * _sigma * std::cos(_theta*pi/180. ) ),
309  std::fabs( _nstd * _sigma/_gamma * std::sin(_theta*pi/180. ) )
310  );
311  famplitude[1] = std::max(
312  std::fabs( _nstd * _sigma * std::sin(_theta*pi/180. ) ),
313  std::fabs( _nstd * _sigma/_gamma * std::cos(_theta*pi/180. ) )
314  );
315  famplitude[0] /= _voxelsize[0];
316  famplitude[1] /= _voxelsize[1];
317  _amplitude[0] = (int) famplitude[0];
318  _amplitude[1] = (int) famplitude[0];
319  _amplitude[2] = (int) famplitude[1];
320  _amplitude[3] = (int) famplitude[1];
322  _amplitude[2] + _amplitude[3] + 1 );
323  if( carto::verbose )
324  std::cout << "- amplitude: "
325  << _amplitude[0] << ", "
326  << _amplitude[1] << ", "
327  << _amplitude[2] << ", "
328  << _amplitude[3] << ", "
329  << _amplitude[4] << ", "
330  << _amplitude[5] << std::endl;
331 
332 
333  double offsetx = (double)(_kernel->getSizeX())/2;
334  double offsety = (double)(_kernel->getSizeY())/2;
335  double xp, yp;
336  for( int32_t y=0; y<_kernel->getSizeY(); ++y )
337  for( int32_t x=0; x<_kernel->getSizeX(); ++x )
338  {
339  xp = ( (double)x-offsetx ) * _voxelsize[0] * std::cos( _theta*pi/180. ) +
340  ( (double)y-offsety ) * _voxelsize[1] * std::sin( _theta*pi/180. );
341  yp = ( -(double)x+offsetx ) * _voxelsize[0] * std::sin( _theta*pi/180. ) +
342  ( (double)y-offsety ) * _voxelsize[1] * std::cos( _theta*pi/180. );
343  _kernel(x,y) = std::exp( ( std::pow(xp,2) +
344  std::pow(_gamma,2) *
345  std::pow(yp,2) ) /
346  ( -2. * std::pow(_sigma,2) ) );
347  if( _real )
348  _kernel(x,y) *= std::cos( 2. * pi * xp / _lambda + _psi * pi / 180. );
349  else
350  _kernel(x,y) *= std::sin( 2. * pi * xp / _lambda + _psi * pi / 180. );
351  }
352 
353  _init = true;
354  }
355 
356  template <typename T> inline
357  T GaborFilterFunc<T>::execute( const carto::VolumeRef<T> & volume ) const
358  {
359  ASSERT( volume->getSizeZ() == 1 );
360  ASSERT( volume->getSizeT() == 1 );
361  double result = 0;
362 
363  for( int32_t y=0; y<volume->getSizeY(); ++y )
364  for( int32_t x=0; x<volume->getSizeX(); ++x )
365  result += _kernel(x,y) * volume(x,y);
366 
367  return (T) result;
368  }
369 
370 } // namespace aims
371 
372 #endif
#define ASSERT(EX)
virtual void setOptions(const carto::Object &)
Set the parameters of the filters If a parameter value is not set in the options object,...
static std::map< std::string, carto::rc_ptr< LinearFilteringFunction< T > > > & _map()
static std::set< std::string > names()
static LinearFilteringFunction< T > * create(const std::string &name, carto::Object options=carto::none())
static void registerFunction(const std::string &name, const LinearFilteringFunction< T > &func)
Base class for linear filtering functions.
virtual LinearFilteringFunction< T > * clone() const =0
clone
const T * const_iterator
int getSizeZ() const
int getSizeT() const
int getSizeY() const
int getSizeX() const
float max(float x, float y)
Definition: thickness.h:98
std::vector< int > _amplitude
void setKernel()
carto::VolumeRef< double > _kernel
std::vector< float > _voxelsize
int verbose