aimsalgo 6.0.0
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
54namespace 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,
84 )
85 {
86 init();
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
297 void GaborFilterFunc<T>::setKernel()
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];
321 _kernel = carto::VolumeRef<double>( _amplitude[0] + _amplitude[1] + 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 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
int getSizeZ() const
int getSizeT() const
int getSizeY() const
int getSizeX() const
std::vector< int > _amplitude
void setKernel()
carto::VolumeRef< double > _kernel
std::vector< float > _voxelsize
int verbose