36 #ifndef AIMS_DIFFUSION_SMOOTHER_D_H
37 #define AIMS_DIFFUSION_SMOOTHER_D_H
58 carto::AllocatorContext::fast() );
67 laplacian(1,1,0) = laplacian(1,0,1) = laplacian(0,1,1) =
68 laplacian(2,1,1) = laplacian(1,2,1) = laplacian(1,1,2) = 0.5;
69 laplacian(1,1,1) = -3;
79 std::cerr <<
"diffusionConvolution Smoother: "
80 <<
"maxiter negative value is forbidden" << std::endl;
93 kernel(0,1,1) = kernel(2,1,1) = this->_dt / ( vs[0] * vs[0] );
94 kernel(1,0,1) = kernel(1,2,1) = this->_dt / ( vs[1] * vs[1] );
95 kernel(1,1,0) = kernel(1,1,2) = this->_dt / ( vs[2] * vs[2] );
96 kernel(1,1,1) = -this->_dt * (2. / (vs[0] * vs[0])
97 + 2. / (vs[1] * vs[1])
98 + 2. / (vs[2] * vs[2]) );
101 kernel(1,1,1) = 1. + kernel(1,1,1);
111 std::vector<int> dim = ima->
getSize();
115 tmp1 = &imaF; tmp2 = &ima2;
117 for (
int i = 0; i < maxiter; i++)
119 if (
verbose) std::cout <<
"+" << std::flush;
120 if( _hasConstantSources )
123 for( z=0; z<dim[2]; ++z )
124 for( y=0; y<dim[1]; ++y )
125 for( x=0; x<dim[0]; ++x )
127 T & v = _constantSources( x, y, z );
128 if( v != _constantSourcesBackground )
129 (*tmp1)( x, y, z ) = v;
132 (*tmp2) = convolution.
doit( *tmp1, kernel );
138 if( _hasConstantSources )
141 for( z=0; z<dim[2]; ++z )
142 for( y=0; y<dim[1]; ++y )
143 for( x=0; x<dim[0]; ++x )
145 T & v = _constantSources( x, y, z );
146 if( v != _constantSourcesBackground )
147 (*tmp1)( x, y, z ) = v;
151 if (
verbose) std::cout <<
"Finished" << std::endl;
165 _constantSources = sources;
166 _constantSourcesBackground = bgr;
167 _hasConstantSources =
true;
171 template <
typename T>
174 _hasConstantSources =
false;
183 this->check(maxiter);
187 kernel(0,1,1) = kernel(2,1,1) = this->_dt / ( vs[0] * vs[0] );
188 kernel(1,0,1) = kernel(1,2,1) = this->_dt / ( vs[1] * vs[1] );
189 kernel(1,1,0) = kernel(1,1,2) = this->_dt / ( vs[2] * vs[2] );
190 kernel(1,1,1) = -this->_dt * (2. / (vs[0] * vs[0])
191 + 2. / (vs[1] * vs[1])
192 + 2. / (vs[2] * vs[2]) );
195 kernel(1,1,1) = 1. + kernel(1,1,1);
204 this->_background, this->_safe );
207 std::vector<int> dim = ima->
getSize();
210 tmp1 = &imaF; tmp2 = &ima2;
212 for (
int i = 0; i < maxiter; i++)
214 if (
verbose) std::cout <<
"+" << std::flush;
215 if (_has_neumann_condition)
216 update_neumann_conditions(*tmp1);
217 (*tmp2) = convolution.
doit((*tmp1), kernel);
223 if (
verbose) std::cout <<
"Finished" << std::endl;
233 template<
typename T>
inline
235 add_neumann_condition(
const Point3df &p)
237 _has_neumann_condition =
true;
238 _neumann_conditions.push_back(p);
250 for (
unsigned int i = 0; i < _neumann_conditions.size(); ++i)
253 const Point3df &p = _neumann_conditions[i];
254 for (i = 0; i < 3; ++i)
255 for (d = -1; d <= 1; d += 2)
259 if (p2[i] < 0 or p2[i] >= dim[i])
continue;
260 if (((this->_mask))(p2[0], p2[1], p2[2]) != 0)
262 ima(p[0], p[1], p[2]) =ima(p2[0], p2[1], p2[2]);
275 this->check(maxiter);
280 std::vector<int> dim = ima->
getSize();
283 tmp1 = &imaF; tmp2 = &ima2;
285 for (
int i = 0; i < maxiter; i++)
287 if (
verbose) std::cout <<
"+" << std::flush;
288 convolution((*tmp1), (*tmp2));
294 if (
verbose) std::cout <<
"Finished" << std::endl;
303 template<
typename T>
void
307 int i, d, x, y, z, t, n;
314 for (t = 0; t < dt; t++)
315 for (z = 0; z < dz; z++)
316 for (y = 0; y < dy; y++)
317 for (x = 0; x < dx; x++)
319 std::cout <<
"x,y,z = " << x <<
", " << y <<
", " << z << std::endl;
320 std::cout <<
"mask = " << ((*this->_mask)(x, y, z, t)) << std::endl;
321 if ((*this->_mask)(x, y, z, t) == this->_background or
322 (*this->_mask)(x, y, z, t) == this->_neumann_value)
324 ima2(x, y, z, t) = ima1(x, y, z, t);
330 for (i = 0; i < 3; ++i)
331 for (d = -1; d <= 1; d += 2)
335 if (p2[i] < 0 or p2[i] >= dim[i])
continue;
336 if ((*this->_mask)(p2[0], p2[1], p2[2], t)
337 == this->_neumann_value)
continue;
339 val += ima1(p2[0], p2[1], p2[2], t);
341 val -= n * ima1(x, y, z, t);
342 ima2(x, y, z, t) = ima1(x, y, z, t) + this->_dt * val;
The template class to make convolutions.
carto::VolumeRef< T > doit(carto::rc_ptr< carto::Volume< T > > &, carto::rc_ptr< carto::Volume< T > > &)
Make convolution only on a specified mask.
static carto::VolumeRef< float > init_laplacian(void)
static carto::VolumeRef< float > laplacian
Heat diffusion with a volume of given datasource (Dirichlet conditions)
void setConstantSources(const carto::VolumeRef< T > &, const T &background)
void removeConstantSources()
virtual carto::VolumeRef< T > doSmoothing(const carto::VolumeRef< T > &ima, int maxiter, bool verbose=false)
virtual void convert(const INP &in, OUTP &out) const
std::vector< float > getVoxelSize() const
std::vector< int > getSize() const
void swap(scoped_ptr< T > &x, scoped_ptr< T > &y)