Index: olena/ChangeLog from Niels Van Vliet niels@lrde.epita.fr
* olena/oln/core/neighborhood3d.hh: Add some common neighborhoods. * olena/oln/convol/slow_gaussian.hh: Add file. * olena/oln/convol/slow_gaussian.hxx: Add file.
Index: olena/oln/core/neighborhood3d.hh --- olena/oln/core/neighborhood3d.hh Mon, 29 Mar 2004 09:53:11 +0200 odou_s (oln/c/35_neighborho 1.19 600) +++ olena/oln/core/neighborhood3d.hh Tue, 11 May 2004 09:50:46 +0200 van-vl_n (oln/c/35_neighborho 1.19 600) @@ -260,6 +260,55 @@ return neighb; }
+ + /*! + ** \brief Create an ellipsoid neighborhood (3 dimension). + ** \arg zradius radius Z. + ** \arg yradius radius Y. + ** \arg xradius radius X. + ** \pre zradius > 0 + ** \pre yradius > 0 + ** \pre xradius > 0 + ** + ** The ellipsoid formula is : + ** \f$$\frac{x^2}{xradius^2} + \frac{y^2}{yradius^2} + \frac{z^2}{zradius^2} = 1$\f$ + */ + inline neighborhood3d + mk_neighb_ellipsoid(float zradius, float yradius, float xradius) + { + precondition(zradius > 0); + precondition(yradius > 0); + precondition(xradius > 0); + + neighborhood3d neighb; + coord zmax = (coord)roundf(zradius); + float zr2 = zradius * zradius; + float yr2 = yradius * yradius; + for (coord z = -zmax; z <= zmax; ++z) + { + /* + x^2 y^2 z^2 + --------- + --------- + --------- = 1 + xradius^2 yradius^2 zradius^2 + */ + + /* Set x to 0 in the above formula to find ymax. */ + float v = 1 - z * z / zr2; + if (v < 0) v = 0; // Can happen because zmax has been rounded. + coord ymax = (coord)roundf(yradius * sqrtf(v)); + for (coord y = -ymax; y <= ymax; ++y) + { + float w = v - y * y / yr2; + if (w < 0) w = 0; // Can happen because ymax has been rounded. + coord xmax = (coord)roundf(xradius * sqrtf(w)); + for (coord x = z > 0 ? 0 : 1; x <= xmax; ++x) + neighb.add(z, y, x); + } + } + return neighb; + } + + /*! ** \brief Create a cube neighborhood (3 dimension). ** \arg width Number of slice, colunm and row. @@ -285,6 +334,16 @@ return win; }
+ /*! + ** \brief Create a ball neighborhood (3 dimension). + ** \arg radius The radius. + ** \return The new neighborhood (3d). + */ + inline neighborhood3d + mk_neighb_ball(float radius) + { + return mk_neighb_ellipsoid(radius, radius, radius); + } } // end of oln
#endif // OLENA_CORE_NEIGHBORHOOD3D_HH Index: olena/oln/convol/slow_gaussian.hh --- olena/oln/convol/slow_gaussian.hh Wed, 12 May 2004 23:10:01 +0200 van-vl_n () +++ olena/oln/convol/slow_gaussian.hh Wed, 12 May 2004 23:04:19 +0200 van-vl_n (oln/r/7_slow_gauss 644) @@ -0,0 +1,80 @@ +// Copyright (C) 2004 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, Boston, +// MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + + +#ifndef SLOW_GAUSSIAN_HH +# define SLOW_GAUSSIAN_HH +# include <oln/core/image.hh> +# include <ntg/float.hh> +# include "convolution.hh" + +namespace oln { + namespace convol { + namespace slow { + + /*! Gaussian kernel. + ** + ** In the specialization, the function kernel must be defined. + */ + template <int Dim> + struct gaussian_kernel + { + }; + + /*! Gaussian filter. + ** + ** \todo FIXME: this class has been done on hurry. + ** \arg in input image. + ** \arg sigma sigma. + ** \arg mu point corresponding to the center. + */ + template <class I> + oln_concrete_type(I) + gaussian(const oln::abstract::non_vectorial_image<I> & in, + const ntg::float_d sigma, + const oln_point_type(I) & mu = oln_point_type(I)()) + { + static const typename gaussian_kernel<I::dim>::ret k + = gaussian_kernel<I::dim>::kernel_norm(sigma, mu); + in.border_adapt_mirror(k.delta()); + //FIXME: we should use fast convol. + //FIXME: This is hugely. + typename mute<I, double>::ret im = oln::convol::slow::convolve<double> + (in, + gaussian_kernel<I::dim>::kernel(sigma, mu)); + oln_concrete_type(I) out(in.size()); + oln_iter_type(I) it(out); + for_all(it) + out[it] = oln_value_type(I)(im[it]); + return out; + } + }//End namespace slow + }// End namespace convol +}// End namespace oln + +#include "slow_gaussian.hxx" +#endif // end SLOW_GAUSSIAN_HH Index: olena/oln/convol/slow_gaussian.hxx --- olena/oln/convol/slow_gaussian.hxx Wed, 12 May 2004 23:10:01 +0200 van-vl_n () +++ olena/oln/convol/slow_gaussian.hxx Wed, 12 May 2004 23:07:36 +0200 van-vl_n (oln/r/8_slow_gauss 644) @@ -0,0 +1,158 @@ +// Copyright (C) 2004 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, Boston, +// MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + + +#ifndef SLOW_GAUSSIAN_HXX +# define SLOW_GAUSSIAN_HXX +# include <oln/core/w_window1d.hh> +# include <oln/core/w_window2d.hh> +# include <oln/core/w_window3d.hh> + +//! SIGMA_COEF times sigma is the size of the kernel. +# define SIGMA_COEF 3 + +namespace oln { + namespace convol { + namespace slow { + namespace internal { + /* FIXME: The hierarchy w_window is a REAL mess. + a w_window1d is not an abstract::w_window, + and w_windownd does not supprot concrete_type, etc + */ + template<class T> + T + normalise(const T &in) + { + T w = in; + double sum = 0; + for (unsigned i = 0; i < in.card(); ++i) + sum += in.w(i); + sum = 1. / sum; + for (unsigned i = 0; i < in.card(); ++i) + w.set(w.dp(i), in.w(i) * sum); + return w; + } + + }// End namespace internal + + //! Kernel of a 1D Gaussian. + template<> + struct gaussian_kernel<1> + { + typedef oln::w_window1d<double> ret; + enum {dim = 1}; + + static w_window1d<double> + kernel_norm(double sigma, const point1d & mu = point1d(0)) + { + return internal::normalise(kernel(sigma, mu)); + } + + w_window1d<double> + static kernel(double sigma, const point1d & mu = point1d(0)) + { + assert(sigma >= 0); + w_window1d<double> w; + + const int size = int(sigma * SIGMA_COEF); + const double inv_sigma_sqrt_2pi = 1. / (sigma * sqrt(M_PI * 2.)); + for (int x = -size; x <= +size; ++x) + w.add(x, inv_sigma_sqrt_2pi * exp( -(x - mu.nth(0)) * (x - mu.nth(0)) / (2 * sigma * sigma)) + ); + return w; + } + }; + + //! Kernel of a 2D Gaussian. + template<> + struct gaussian_kernel<2> + { + typedef w_window2d<double> ret; + enum {dim = 2}; + + static w_window2d<double> + kernel_norm(double sigma, const point2d & mu = point2d(0, 0)) + { + return internal::normalise(kernel(sigma, mu)); + } + w_window2d<double> + static kernel(double sigma, const point2d & mu = point2d(0, 0)) + { + assert(sigma >= 0); + w_window2d<double> w; + const int size = int(sigma * SIGMA_COEF); + const double inv_sigma_sigma_pi_2 = 1. / (sigma * sigma * M_PI * 2.); + + for (int x = -size; x <= +size; ++x) + for (int y = -size; y <= +size; ++y) + w.add(x, y, inv_sigma_sigma_pi_2 + * exp(- ((x - mu.nth(0)) * (x - mu.nth(0)) + (y - mu.nth(1)) * (y - mu.nth(1)) + ) + / ( 2. * sigma * sigma) + ) + ); + return w; + } + }; + + //! Kernel of a 3D Gaussian. + template<> + struct gaussian_kernel<3> + { + typedef w_window3d<double> ret; + enum {dim = 3}; + + static w_window3d<double> + kernel_norm(double sigma, const point3d & mu = point3d(0, 0, 0)) + { + return internal::normalise(kernel(sigma, mu)); + } + static w_window3d<double> + kernel(double sigma, const point3d & mu = point3d(0, 0, 0)) + { + assert(sigma >= 0); + w_window3d<double> w; + + const int size = int(sigma * SIGMA_COEF); + const double k = 1. / (sigma * sigma * sigma * sqrt((M_PI * 2.) * (M_PI * 2.) * (M_PI * 2.))); + + for (int x = -size; x <= +size; ++x) + for (int y = -size; y <= +size; ++y) + for (int z = -size; z <= +size; ++z) + w.add(x, y, z, k * + exp(-((x - mu.nth(0)) * (x - mu.nth(0)) + + (y - mu.nth(1)) * (y - mu.nth(1)) + + (z - mu.nth(2)) * (z - mu.nth(2)) + ) / (2. * sigma * sigma))); + return w; + } + }; + + }//End namespace slow + }// End namespace convol +}// End namespace oln +#endif // end SLOW_GAUSSIAN_HXX