cleanup-2008 2816: Update some files and add test suite for nature.
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox Index: ChangeLog from Alexandre Abraham <abraham@lrde.epita.fr> Update some files and add test suite for nature. * abraham/tests/core/image/thru_v2v.cc, abraham/tests/core/image/thru_const.cc: make::image2d to make::image . * abraham/mln/level/transform.hh: Remove. * abraham/mln/core/image/shell.hh: Remove. * abraham/mln/fun/meta/to_enc.hh: New Make this functor meta. * abraham/mln/fun/v2v/rgb_to_hsi.hh: Corrected version of rgb to hsi conversion. * abraham/mln/binarization/binarization.hh: Remove. * abraham/mln/transform: New. * abraham/mln/transform/fft.hh: New. * abraham/mln/value/shell.hh: Support Function_v2v. * nature/histo_hsi.cc: . * nature/hom.cc: . * nature/mco.cc: . * nature/nature.cc: New. * nature/opening.cc: . * nature/test.sh: New. abraham/mln/binarization/binarization.hh | 106 ---- abraham/mln/core/image/shell.hh | 157 ------- abraham/mln/fun/meta/to_enc.hh | 57 ++ abraham/mln/fun/v2v/rgb_to_hsi.hh | 8 abraham/mln/level/transform.hh | 209 --------- abraham/mln/transform/fft.hh | 681 +++++++++++++++++++++++++++++++ abraham/mln/value/shell.hh | 2 abraham/tests/core/image/thru_const.cc | 2 abraham/tests/core/image/thru_v2v.cc | 2 nature/histo_hsi.cc | 34 + nature/hom.cc | 224 ++++++++-- nature/mco.cc | 4 nature/nature.cc | 408 ++++++++++++++++++ nature/opening.cc | 2 nature/test.sh | 11 15 files changed, 1377 insertions(+), 530 deletions(-) Index: abraham/tests/core/image/thru_v2v.cc --- abraham/tests/core/image/thru_v2v.cc (revision 2815) +++ abraham/tests/core/image/thru_v2v.cc (working copy) @@ -47,7 +47,7 @@ }; - image2d<int> ima(make::image2d(vs)); + image2d<int> ima(make::image(vs)); thru<mln::fun::v2v::abs<int>, image2d<int> > out(ima); box_fwd_piter_<point2d> p(ima.domain()); Index: abraham/tests/core/image/thru_const.cc --- abraham/tests/core/image/thru_const.cc (revision 2815) +++ abraham/tests/core/image/thru_const.cc (working copy) @@ -47,7 +47,7 @@ }; - I ima(make::image2d(vs)); + I ima(make::image(vs)); thru<mln::fun::v2w2v::cos<double>, I > out(ima); double i = 0; Index: abraham/mln/fun/meta/to_enc.hh --- abraham/mln/fun/meta/to_enc.hh (revision 0) +++ abraham/mln/fun/meta/to_enc.hh (revision 0) @@ -0,0 +1,57 @@ +// Copyright (C) 2007 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, 51 Franklin Street, Fifth Floor, +// 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 MLN_FUN_META_RED_HH +# define MLN_FUN_META_RED_HH + +# include <mln/core/concept/meta_fun.hh> + +namespace mln { + + namespace meta { + + template <class T> + struct to_enc : impl< to_enc<T> > { typedef typename T::enc value; }; + + }; + + template <typename T> + struct function< meta::to_enc<T> > : public Function_v2v<function< meta::to_enc<T> > > + { + typedef typename T::enc value; + + value read(const T& t) + { + return t.to_enc(); + } + + }; + + +}; + +#endif // MLN_FUN_META_RED_HH Index: abraham/mln/fun/v2v/rgb_to_hsi.hh --- abraham/mln/fun/v2v/rgb_to_hsi.hh (revision 2815) +++ abraham/mln/fun/v2v/rgb_to_hsi.hh (working copy) @@ -83,7 +83,7 @@ // sqrt3_3 * rgb.green() + // sqrt3_3 * rgb.blue(); - hsi.inty() = (rgb.red() + rgb.green() + rgb.blue()) / 3; + hsi.inty() = (double) (rgb.red() + rgb.green() + rgb.blue()) / 3 / mln_max(typename T_rgb::red_t); typename T_rgb::red_t min = rgb.red(); if (rgb.green() < min) @@ -94,18 +94,18 @@ if (hsi.inty()) - hsi.sat() = (1 - (double) 3 * min / (double)(rgb.red() + rgb.green() + rgb.blue())) * 100; + hsi.sat() = (1 - (double) 3 * min / (double)(rgb.red() + rgb.green() + rgb.blue())); else hsi.sat() = 0; // this is black for any value of saturation if (hsi.sat()) hsi.hue() = acos( 0.5 * (2 * rgb.red() - rgb.green() - rgb.blue()) / - std::sqrt((rgb.red() - rgb.green()) * (rgb.red() - rgb.green()) + (rgb.red() - rgb.blue()) * (rgb.green() - rgb.blue()))) / 3.1415 * 180.0; + std::sqrt((rgb.red() - rgb.green()) * (rgb.red() - rgb.green()) + (rgb.red() - rgb.blue()) * (rgb.green() - rgb.blue()))) / 3.1416; else hsi.hue() = 0; // this is grey for any value of hue if (hsi.hue() < 0) - hsi.hue() = hsi.hue() + 360.0; + hsi.hue() = hsi.hue() + 1.0; mln_invariant(hsi.hue() >= 0); mln_invariant(hsi.hue() < 360); Index: abraham/mln/transform/fft.hh --- abraham/mln/transform/fft.hh (revision 0) +++ abraham/mln/transform/fft.hh (revision 0) @@ -0,0 +1,681 @@ +// Copyright (C) 2007, 2008 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, 51 Franklin Street, Fifth Floor, +// 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 MLN_TRANSFORM_FFT_HH +# define MLN_TRANSFORM_FFT_HH + +# ifdef HAVE_FFTW + +# include <fftw.h> +# include <rfftw.h> + +namespace mln { + + namespace internal { + + /// Dispatch traits for fftw + enum fft_dispatch { fft_cplx, fft_real }; + + /*! + ** \brief fft trait. + */ + template <class T> + struct fft_trait + { + void ensure() { ntg_is_a(T, ntg::real)::ensure(); } + + static const fft_dispatch which = fft_real; ///< Real dispatch. + typedef fftw_real fftw_input; ///< Type of input. + }; + + /*! + ** \brief fft trait. + ** + ** \specialization for ntg::cplx<R, T> + */ + template <ntg::cplx_representation R, class T> + struct fft_trait<ntg::cplx<R, T> > + { + static const fft_dispatch which = fft_cplx; ///< Complex dispatch. + typedef fftw_complex fftw_input; ///< Type of input. + }; + + /*! + ** _fft<ntg::cplx_representation, T> + ** + ** \param T Data type. + ** \param R type of representation. + */ + template <class T, ntg::cplx_representation R> + class _fft + { + public: + /*! + ** \brief Accessor to transformed image. + ** + ** Const version. + */ + const image2d<ntg::cplx<R, ntg::float_d> > transformed_image() const + { + return trans_im; + } + + /*! + ** \brief Accessor to transformed image. + ** + ** Non const version. + */ + image2d<ntg::cplx<R, ntg::float_d> >& transformed_image() + { + return trans_im; + } + + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** |T[p]|. + ** + ** \param T1 Data type of the resulting image. + ** + ** \arg ordered Kind of traversal. + */ + template <class T1> + image2d<T1> transformed_image_magn(bool ordered = true) const + { + ntg_is_a(T1, ntg::real)::ensure(); + + image2d<T1> new_im(trans_im.size()); + + if (ordered) + for (int row = 0; row < new_im.nrows(); ++row) + for (int col = 0; col < new_im.ncols(); ++col) + new_im(row, col) = + trans_im((row + trans_im.nrows() / 2) % trans_im.nrows(), + (col + trans_im.ncols() / 2) % trans_im.ncols()).magn(); + else + { + typename image2d<ntg::cplx<R, ntg::float_d> >::iter it(trans_im); + + for_all(it) + new_im[it] = trans_im[it].magn(); + } + + return new_im; + } + + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** |T[p]|. + ** + ** \arg ordered Kind of traversal. + */ + image2d<T> transformed_image_magn(bool ordered = true) const + { + return transformed_image_magn<T>(ordered); + } + + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** a clipped value of |T[p]|.\n + ** + ** \param T1 Data type of the resulting image. + ** + ** \arg clip Value used for clipping. + ** \arg ordered Kind of traversal. + */ + template <class T1> + image2d<T1> transformed_image_clipped_magn(const ntg::float_d clip, + bool ordered = true) const + { + ntg_is_a(T1, ntg::real)::ensure(); + + image2d<T1> new_im(trans_im.size()); + ntg::range<ntg::float_d, ntg::bounded_u<0, 1>, ntg::saturate> c(clip); + ntg::float_d max = 0; + typename image2d<ntg::cplx<R, ntg::float_d> >::iter_type it(trans_im); + + for_all(it) + if (max < trans_im[it].magn()) + max = trans_im[it].magn(); + + if (ordered) + for (int row = 0; row < new_im.nrows(); ++row) + for (int col = 0; col < new_im.ncols(); ++col) + { + if (trans_im((row + trans_im.nrows() / 2) % trans_im.nrows(), + (col + trans_im.ncols() / 2) % + trans_im.ncols()).magn() >= max * c) + new_im(row, col) = ntg_max_val(T); + else + new_im(row, col) = + ntg_max_val(T) * + trans_im((row + trans_im.nrows() / 2) % trans_im.nrows(), + (col + trans_im.ncols() / 2) % + trans_im.ncols()).magn() / (max * c); + } + else + for_all(it) + { + if (trans_im[it].magn() >= max * c) + new_im[it] = ntg_max_val(T); + else + new_im[it] = ntg_max_val(T) * + trans_im[it].magn() / (max * c); + } + + return new_im; + } + + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** a clipped value of |T[p]|.\n + ** + ** \arg clip Value used for clipping. + ** \arg ordered Kind of traversal. + */ + image2d<T> transformed_image_clipped_magn(const ntg::float_d clip, + bool ordered = true) const + { + return transformed_image_clipped_magn<T>(clip, ordered); + } + + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** a clipped value of |T[p]|.\n + ** + ** \param T1 Data type of the resulting image. + ** + ** \arg ordered Kind of traversal. + */ + template <class T1> + image2d<T1> transformed_image_clipped_magn(bool ordered = true) const + { + return transformed_image_clipped_magn<T1>(1, ordered); + } + + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** a clipped value of |T[p]|.\n + ** + ** \param T1 Data type of the resulting image. + ** + ** \arg ordered Kind of traversal. + */ + image2d<T> transformed_image_clipped_magn(bool ordered = true) const + { + return transformed_image_clipped_magn<T>(1, ordered); + } + + // FIXME: Find a more elegant way to fix range interval on a and b. + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** a log translated value of |T[p]| on interval [a; b].\n + ** + ** \arg a Lower bound. + ** \arg b Upper bound. + ** \arg ordered Kind of traversal. + */ + template <class T1> + image2d<T1> transformed_image_log_magn(const ntg::range<ntg::float_d, + ntg::bounded_u<0, 1000>, + ntg::saturate> a, + const ntg::range<ntg::float_d, + ntg::bounded_u<0, 1000>, + ntg::saturate> b, + bool ordered = true) const + { + ntg_is_a(T1, ntg::real)::ensure(); + + image2d<T1> new_im(trans_im.size()); + ntg::float_d max = 0; + typename image2d<ntg::cplx<R, ntg::float_d> >::iter_type it(trans_im); + + for_all(it) + if (max < trans_im[it].magn()) + max = trans_im[it].magn(); + + if (ordered) + for (int row = 0; row < new_im.nrows(); ++row) + for (int col = 0; col < new_im.ncols(); ++col) + new_im(row, col) = + log(a + b * trans_im((row + trans_im.nrows() / 2) % + trans_im.nrows(), + (col + trans_im.ncols() / 2) % + trans_im.ncols()).magn()) / + log(a + b * max) * ntg_max_val(T); + else + for_all(it) + new_im[it] = log(a + b * trans_im[it].magn()) / + log(a + b * max) * ntg_max_val(T); + + return new_im; + } + + // FIXME: Find a more elegant way to fix boundaries of a and b. + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** a log translated value of |T[p]| on interval [a; b].\n + ** + ** \arg a Lower bound. + ** \arg b Upper bound. + ** \arg ordered Kind of traversal. + */ + image2d<T> transformed_image_log_magn(const ntg::range<ntg::float_d, + ntg::bounded_u<0, 1000>, + ntg::saturate> a, + const ntg::range<ntg::float_d, + ntg::bounded_u<0, 1000>, + ntg::saturate> b, + bool ordered = true) const + { + return transformed_image_log_magn<T>(a, b, ordered); + } + + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** a log translated value of |T[p]| on interval [1; 100].\n + ** + ** \param T1 Data type of the resulting image. + ** + ** \arg ordered Kind of traversal. + */ + template <class T1> + image2d<T1> transformed_image_log_magn(bool ordered = true) const + { + return transformed_image_log_magn<T1>(1, 100, ordered); + } + + /*! + ** \brief Accessor to transformed image. + ** + ** For each point p of the transformed image T, you get + ** a log translated value of |T[p]| on interval [1; 100].\n + ** + ** \arg ordered Kind of traversal. + */ + image2d<T> transformed_image_log_magn(bool ordered = true) const + { + return transformed_image_log_magn<T>(1, 100, ordered); + } + + /*! + ** \brief Destructor. + ** + ** Let memory free for other big images !!! + */ + ~_fft() + { + delete [] in; + delete [] out; + fftwnd_destroy_plan(p); + fftwnd_destroy_plan(p_inv); + } + + protected: + + typename fft_trait<T>::fftw_input *in; ///< Input image. + fftw_complex *out; ///< Complex image. + fftwnd_plan p; ///< Plan. + fftwnd_plan p_inv; ///< inverted plan. + image2d<ntg::cplx<R, ntg::float_d> > trans_im; ///< Transformed image. + + }; + + } // end of namespace internal + + namespace transforms { + + /*! + ** \brief fft class declaration. + ** + ** \param T Data type. + ** \param R Complex representation kind. + ** \param which Dispatch. + */ + template <class T, + ntg::cplx_representation R = ntg::polar, + internal::fft_dispatch which = internal::fft_trait<T>::which > + class fft; + + /*! + ** \brief fft specialization for fft real dispatch. + ** + ** \param T Data type. + ** \param R Complex representation kind. + */ + template <class T, ntg::cplx_representation R> + class fft<T, R, internal::fft_real> : public internal::_fft<T, R> + { + + public: + + /*! + ** \brief Constructor. + ** + ** Initialization of data in order to compute the fft. + ** + ** \arg original_im Image to process. + */ + fft(const image2d<T>& original_im) + { + this->in = new fftw_real[original_im.nrows() * original_im.ncols()]; + this->out = new fftw_complex[original_im.nrows() * + (original_im.ncols() / 2 + 1)]; + + for (int row = 0; row < original_im.nrows(); ++row) + for (int col = 0; col < original_im.ncols(); ++col) + this->in[row * original_im.ncols() + col] = original_im(row, col); + + this->p = rfftw2d_create_plan(original_im.nrows(), original_im.ncols(), + FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); + this->p_inv = rfftw2d_create_plan(original_im.nrows(), original_im.ncols(), + FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE); + + this->trans_im = image2d<ntg::cplx<R, ntg::float_d> >(original_im.size()); + } + + /*! + ** \brief Compute and return the transform. + */ + image2d<ntg::cplx<R, ntg::float_d> > transform() + { + rfftwnd_one_real_to_complex(this->p, this->in, this->out); + + unsigned denom = this->trans_im.nrows() * this->trans_im.ncols(); + int i = 0; + for (int row = 0; row < this->trans_im.nrows(); ++row) + for (int col = 0; col <= this->trans_im.ncols() / 2; ++col) + { + this->out[i].re /= denom; + this->out[i].im /= denom; + this->trans_im(row, col) = ntg::cplx<ntg::rect, ntg::float_d>(this->out[i].re, + this->out[i].im); + ++i; + } + for (int row = 0; row < this->trans_im.nrows(); ++row) + for (int col = this->trans_im.ncols() - 1; col > this->trans_im.ncols() / 2; --col) + this->trans_im(row, col) = this->trans_im(this->trans_im.nrows() - row - 1, + this->trans_im.ncols() - col - 1); + return this->trans_im; + } + + /*! + ** \brief Compute and return the invert transform. + ** + ** \param T1 Data type of output image. + */ + template <class T1> + image2d<T1> transform_inv() + { + ntg_is_a(T1, ntg::real)::ensure(); + + for (int row = 0; row < this->trans_im.nrows(); ++row) + for (int col = 0; col <= this->trans_im.ncols() / 2; ++col) + { + this->out[row * (this->trans_im.ncols() / 2 + 1) + col].re = + this->trans_im(row, col).real(); + this->out[row * (this->trans_im.ncols() / 2 + 1) + col].im = + this->trans_im(row, col).imag(); + } + rfftwnd_one_complex_to_real(this->p_inv, this->out, this->in); + + image2d<T1> new_im(this->trans_im.size()); + int i = 0; + for (int row = 0; row < this->trans_im.nrows(); ++row) + for (int col = 0; col < this->trans_im.ncols(); ++col) + { + new_im(row, col) = (this->in[i] >= ntg_inf_val(T1) ? + (this->in[i] <= ntg_sup_val(T1) ? + this->in [i] : + ntg_sup_val(T1)) : + ntg_inf_val(T1)); + ++i; + } + return new_im; + } + + /*! + ** \brief Shift zero-frequency component of discrete Fourier transform + ** to center of spectrum. + ** + ** \param T1 The data type of the image returned. + ** + ** The zero-frequency component of discrete Fourier transform are moved + ** to center of the image : + ** + ** \htmlonly + ** <table> + ** <tr><td>1</td><td>2</td></tr> + ** <tr><td>3</td><td>4</td></tr> + ** </table> + ** becomes + ** <table> + ** <tr><td>4</td><td>3</td></tr> + ** <tr><td>2</td><td>1</td></tr> + ** </table> + ** \endhtmlonly + ** + */ + template <class T1> + image2d<T1> shift_transform_inv() + { + image2d<T1> t = transform_inv<T1>(); + image2d<T1> st(t.size()); + + // We have to exchange t_1 with t_1_dest and not directly t_3 because + // they have not he same size. + typedef morpher::piece_morpher< image2d<T1> > piece_t; + piece_t t_1(t, dpoint2d(0, 0), + image2d_size((t.size().nrows() - 1) / 2, + (t.size().ncols() - 1) / 2, + t.border())); + piece_t t_1_dest(st, dpoint2d(t.nrows() - t_1.nrows(), + t.ncols() - t_1.ncols()), + image2d_size(t_1.nrows(), t_1.ncols(), + t.border())); + piece_t t_2(t, dpoint2d(0, (t.size().ncols() - 1) / 2), + image2d_size((t.size().nrows() - 1) / 2, + t.size().ncols() - (t.size().ncols() - 1) / 2, + t.border())); + piece_t t_2_dest(st, dpoint2d(t.nrows() - t_2.nrows(), 0), + image2d_size(t_2.nrows(), t_2.ncols(), + t.border())); + piece_t t_3(t, dpoint2d((t.size().nrows() - 1) / 2, 0), + image2d_size(t.size().nrows() - (t.size().nrows() - 1) / 2, + (t.size().ncols() - 1) / 2, + t.border())); + piece_t t_3_dest(st, dpoint2d(0, t.ncols() - t_3.ncols()), + image2d_size(t_3.nrows(), t_3.ncols(), + t.border())); + piece_t t_4(t, dpoint2d((t.size().nrows() - 1) / 2, + (t.size().ncols() - 1) / 2), + image2d_size(t.size().nrows() - (t.size().nrows() - 1) / 2, + t.size().ncols() - (t.size().ncols() - 1) / 2, + t.border())); + piece_t t_4_dest(st, dpoint2d(0, 0), + image2d_size(t_4.nrows(), t_4.ncols(), + t.border())); + + oln_iter_type(piece_t) i1(t_1); + for_all(i1) + t_1_dest[i1] = t_1[i1]; + oln_iter_type(piece_t) i2(t_2); + for_all(i2) + t_2_dest[i2] = t_2[i2]; + oln_iter_type(piece_t) i3(t_3); + for_all(i3) + t_3_dest[i3] = t_3[i3]; + oln_iter_type(piece_t) i4(t_4); + for_all(i4) + t_4_dest[i4] = t_4[i4]; + + return st; + } + + /*! + ** \brief Compute and return the invert transform. + */ + image2d<T> transform_inv() + { + return transform_inv<T>(); + } + + /*! + ** \brief Shift zero-frequency component of discrete Fourier transform + ** to center of spectrum. + */ + image2d<T> shift_transform_inv() + { + return shift_transform_inv<T>(); + } + + }; + + /*! + ** \brief fft specialization for fft complex dispatch. + ** + ** \param T Data type. + ** \param R Complex representation kind. + */ + template <class T, ntg::cplx_representation R> + class fft<T, R, internal::fft_cplx> : public internal::_fft<T, R> + { + + public: + + /*! + ** \brief Constructor. + ** + ** Initialization of data in order to compute the fft. + ** + ** \arg original_im Image to process. + */ + template <ntg::cplx_representation R1> + fft(const image2d<ntg::cplx<R1, T> >& original_im) + { + this->in = new fftw_complex[original_im.nrows() * original_im.ncols()]; + this->out = new fftw_complex[original_im.nrows() * original_im.ncols()]; + + for (int row = 0; row < original_im.nrows(); ++row) + for (int col = 0; col < original_im.ncols(); ++col) + { + this->in[row * original_im.ncols() + col].re = + original_im(row, col).real(); + this->in[row * original_im.ncols() + col].im = + original_im(row, col).imag(); + } + + this->p = fftw2d_create_plan(original_im.nrows(), original_im.ncols(), + FFTW_FORWARD, FFTW_ESTIMATE); + this->p_inv = fftw2d_create_plan(original_im.nrows(), original_im.ncols(), + FFTW_BACKWARD, FFTW_ESTIMATE); + + this->trans_im = image2d<ntg::cplx<ntg::rect, ntg::float_d> >(original_im.size()); + } + + /*! + ** \brief Compute and return the transform. + */ + image2d<ntg::cplx<R, ntg::float_d> > transform() + { + fftwnd_one(this->p, this->in, this->out); + + unsigned denom = this->trans_im.nrows() * this->trans_im.ncols(); + int i = 0; + for (int row = 0; row < this->trans_im.nrows(); ++row) + for (int col = 0; col < this->trans_im.ncols(); ++col) + { + this->out[i].re /= denom; + this->out[i].im /= denom; + this->trans_im(row, col) = ntg::cplx<ntg::rect, ntg::float_d>(this->out[i].re, + this->out[i].im); + ++i; + } + return this->trans_im; + } + + /*! + ** \brief Compute and return the invert transform. + ** + ** \param T1 Data type of output image. + */ + template <class T1> + image2d<ntg::cplx<R, T1> > transform_inv() + { + for (int row = 0; row < this->trans_im.nrows(); ++row) + for (int col = 0; col < this->trans_im.ncols(); ++col) + { + this->out[row * this->trans_im.ncols() + col].re = this->trans_im(row, col).real(); + this->out[row * this->trans_im.ncols() + col].im = this->trans_im(row, col).imag(); + } + fftwnd_one(this->p_inv, this->out, this->in); + + image2d<ntg::cplx<R, T1> > new_im(this->trans_im.size()); + int i = 0; + for (int row = 0; row < this->trans_im.nrows(); ++row) + for (int col = 0; col < this->trans_im.ncols(); ++col) + { + new_im(row, col) = this->in[i]; + ++i; + } + return new_im; + } + + /*! + ** \brief Compute and return the invert transform. + */ + image2d<ntg::cplx<R, T> > transform_inv() + { + return transform_inv<T>(); + } + + }; + + } // end of namespace transforms + +} // end of namespace oln + +# endif // HAVE_FFTW + +#endif // ! MLN_TRANSFORM_FFT_HH Index: abraham/mln/value/shell.hh --- abraham/mln/value/shell.hh (revision 2815) +++ abraham/mln/value/shell.hh (working copy) @@ -49,7 +49,7 @@ namespace impl { template <typename F, typename I, class C> - struct shell_; + struct shell_ { }; template <typename F, typename I> struct shell_<F, I, Function_v2w2v<void> > Index: nature/histo_hsi.cc --- nature/histo_hsi.cc (revision 2815) +++ nature/histo_hsi.cc (working copy) @@ -39,6 +39,7 @@ #include <mln/value/hsi.hh> #include <mln/fun/v2v/rgb_to_hsi.hh> +#include <mln/level/to_enc.hh> #include <mln/fun/meta/hue.hh> #include <mln/fun/meta/sat.hh> #include <mln/fun/meta/inty.hh> @@ -68,21 +69,25 @@ histo::data<float01_8> h = histo::compute(ima); // Compute histo max - size_t max = 0; + unsigned max = 0; mln_viter(mln::value::set<float01_8>) v(h.vset()); for_all(v) if (h(v) > max) max = h(v); + std::cout << std::endl; + image2d<bool> output(max, mln_card(float01_8), 0); + std::cout << max << "x" << mln_card(float01_8) << std::endl; level::fill(output, true); for_all(v) for (size_t i = 0; i < h(v); ++i) { - // std::cout << height - i << ", " << (u_t)v << std::endl; - output(point2d(max - i - 1, (float01_8)v)) = false; + // std::cout << max - i - 1 << ", " << (unsigned) (((float01_8)v).to_enc()) << " ; " ; + if (output.has(point2d(max - i - 1, ((float01_8)v).to_enc() ))) + output(point2d(max - i - 1, ((float01_8)v).to_enc() )) = false; } io::pbm::save(output, name); @@ -107,7 +112,9 @@ std::string n(argv[i]); n.erase(n.length() - 4); - // io::pgm::save(hue, n.append("_hue.pgm")); + image2d<int_u8> henc; + level::transform(hue, fun::v2v::enc< float01_8 >(), henc); + io::pgm::save(henc, n.append("_hue.pgm")); image2d<hsi_f>::piter p(hsi.domain()); float m = 0; @@ -125,13 +132,14 @@ save_histo(hue, name.append("_hue.pbm")); - /* thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > s(hsi); - cast_image_<u_t, thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > > sat(s); + cast_image_<float01_8, thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > > sat(s); n = argv[i]; n.erase(n.length() - 4); - io::pgm::save(sat, n.append("_sat.pgm")); + image2d<int_u8> senc; + level::transform(sat, fun::v2v::enc< float01_8 >(), senc); + io::pgm::save(senc, n.append("_sat.pgm")); m = 0; for_all(p) @@ -144,14 +152,16 @@ name = argv[i]; name.erase(name.length() - 4); - save_histo(sat, name.append("_sat.pbm"), 100, 2560, npoints); + save_histo(sat, name.append("_sat.pbm")); thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > l(hsi); - cast_image_<u_t, thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > > inty(l); + cast_image_<float01_8, thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > > inty(l); n = argv[i]; n.erase(n.length() - 4); - io::pgm::save(inty, n.append("_inty.pgm")); + image2d<int_u8> ienc; + level::transform(inty, fun::v2v::enc< float01_8 >(), ienc); + io::pgm::save(ienc, n.append("_inty.pgm")); m = 0; @@ -165,7 +175,7 @@ name = argv[i]; name.erase(name.length() - 4); - save_histo(inty, name.append("_inty.pbm"), 256, 256, npoints); - */ + save_histo(inty, name.append("_inty.pbm")); + } } Index: nature/hom.cc --- nature/hom.cc (revision 2815) +++ nature/hom.cc (working copy) @@ -42,8 +42,11 @@ #include <mln/binarization/threshold.hh> #include <mln/estim/mean.hh> #include <mln/morpho/hit_or_miss.hh> +#include <mln/morpho/dilation.hh> +#include <mln/morpho/opening.hh> - +#include <mln/win/hline2d.hh> +#include <mln/win/vline2d.hh> int main(int argc, const char * argv[]) { @@ -59,15 +62,18 @@ { typedef int_u8 int_t; + border::thickness = 21; + image2d<int_t> ima; io::pgm::load(ima, argv[i]); // Compute the mean int_t mean = estim::mean(ima); - image2d<bool> imab = binarization::threshold(ima, mean); - border::thickness = 10; + image2d<bool> imab = binarization::threshold(ima, 10); + + window2d winout; window2d winin; @@ -80,15 +86,15 @@ // 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0}; -// static const bool matout [] = {0, 0, 0, 0, 0, -// 0, 1, 0, 0, 0, -// 0, 1, 0, 0, 0, -// 0, 1, 1, 1, 0, -// 0, 0, 0, 0, 0}; - - static const bool blmatout [] = {0, 0, 0, - 1, 0, 0, - 1, 1, 0}; + static const bool blmatout [] = {0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0}; + +// static const bool blmatout [] = {0, 0, 0, +// 1, 0, 0, +// 1, 1, 0}; convert::from_to(blmatout, winout); @@ -101,58 +107,170 @@ // 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0}; -// static const bool matin [] = {0, 0, 1, 0, 0, -// 0, 0, 1, 0, 0, -// 0, 0, 1, 1, 1, -// 0, 0, 0, 0, 0, -// 0, 0, 0, 0, 0}; - - static const bool blmatin [] = {0, 1, 0, - 0, 1, 1, - 0, 0, 0}; + static const bool blmatin [] = {0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + +// static const bool blmatin [] = {0, 1, 0, +// 0, 1, 1, +// 0, 0, 0}; convert::from_to(blmatin, winin); image2d<bool> bottom_left = morpho::hit_or_miss(imab, winout, winin); - static const bool brmatout [] = {0, 0, 0, - 0, 0, 1, - 0, 1, 1}; - - static const bool brmatin [] = {0, 1, 0, - 1, 1, 0, - 0, 0, 0}; +// static const bool brmatout [] = {0, 0, 0, +// 0, 0, 1, +// 0, 1, 1}; + +// static const bool brmatin [] = {0, 1, 0, +// 1, 1, 0, +// 0, 0, 0}; + + static const bool brmatout [] = {0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0}; + + static const bool brmatin [] = {0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + convert::from_to(brmatout, winout); convert::from_to(brmatin, winin); image2d<bool> bottom_right = morpho::hit_or_miss(imab, winout, winin); - static const bool urmatout [] = {0, 1, 1, - 0, 0, 1, - 0, 0, 0}; - - static const bool urmatin [] = {0, 0, 0, - 1, 1, 0, - 0, 1, 0}; +// static const bool urmatout [] = {0, 1, 1, +// 0, 0, 1, +// 0, 0, 0}; + +// static const bool urmatin [] = {0, 0, 0, +// 1, 1, 0, +// 0, 1, 0}; + + static const bool urmatout [] = {0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0}; + + static const bool urmatin [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0}; + convert::from_to(urmatout, winout); convert::from_to(urmatin, winin); image2d<bool> up_right = morpho::hit_or_miss(imab, winout, winin); - static const bool ulmatout [] = {1, 1, 0, - 1, 0, 0, - 0, 0, 0}; - - static const bool ulmatin [] = {0, 0, 0, - 0, 1, 1, - 0, 1, 0}; +// static const bool ulmatout [] = {1, 1, 0, +// 1, 0, 0, +// 0, 0, 0}; + +// static const bool ulmatin [] = {0, 0, 0, +// 0, 1, 1, +// 0, 1, 0}; + + static const bool ulmatout [] = {0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0}; + + static const bool ulmatin [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0}; + convert::from_to(ulmatout, winout); convert::from_to(ulmatin, winin); image2d<bool> up_left = morpho::hit_or_miss(imab, winout, winin); + static const bool umatout [] = {0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + static const bool umatin [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(umatout, winout); + convert::from_to(umatin, winin); + image2d<bool> up = morpho::hit_or_miss(imab, winout, winin); + + + static const bool bmatout [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0}; + + static const bool bmatin [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(bmatout, winout); + convert::from_to(bmatin, winin); + image2d<bool> bottom = morpho::hit_or_miss(imab, winout, winin); + + + static const bool lmatout [] = {0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0}; + + static const bool lmatin [] = {0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(lmatout, winout); + convert::from_to(lmatin, winin); + image2d<bool> left = morpho::hit_or_miss(imab, winout, winin); + + + static const bool rmatout [] = {0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0}; + + static const bool rmatin [] = {0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(rmatout, winout); + convert::from_to(rmatin, winin); + image2d<bool> right = morpho::hit_or_miss(imab, winout, winin); + + + std::string name(argv[i]); name.erase(name.length() - 4); @@ -160,7 +278,37 @@ name = argv[i]; name.erase(name.length() - 4); - io::pbm::save( up_left + up_right + bottom_right + bottom_left, + // image2d<bool> final(right.domain()); + // level::fill(final, false); + // mln_piter_(image2d<bool>) p(final.domain()); + // for_all(p) + // final(p) = up_left(p) || up_right(p) || bottom_right(p) || bottom_left(p) || up(p) || bottom(p) || left(p) || right(p); + + image2d<bool> inter (up_left + up_right + bottom_right + bottom_left + up + bottom + left + right); + + static const bool vert [] = {0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0}; + + static const bool hori [] = {0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0}; + + convert::from_to(vert, winin); + convert::from_to(hori, winout); + + image2d<bool> final = morpho::opening(inter, win::hline2d(20)); + final += morpho::opening(inter, win::vline2d(20)); + + io::pbm::save( final, name.append("_hom.pbm")); } } Index: nature/mco.cc --- nature/mco.cc (revision 2815) +++ nature/mco.cc (working copy) @@ -34,10 +34,14 @@ // Normalization unsigned m, M; estim::min_max(co, m, M); + std::cout << "max : " << M << std::endl; double norm = 255./M; mln_piter_ (image2d<unsigned>) p (co.domain()); for_all(p) + { + // std::cout << co(p) << " ; "; co(p) *= norm; + } io::pgm::save(cast_image<int_u<8> >(co), name.append("_mco.pgm")); } Index: nature/nature.cc --- nature/nature.cc (revision 0) +++ nature/nature.cc (revision 0) @@ -0,0 +1,408 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) +// +// 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, 51 Franklin Street, Fifth Floor, +// 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. + +#include <mln/core/image/image2d.hh> +#include <mln/core/image/cast_image.hh> +#include <mln/core/image/thru.hh> + +#include <mln/io/ppm/load.hh> + +#include <mln/histo/compute.hh> + +#include <mln/level/transform.hh> +#include <mln/level/paste.hh> +#include <mln/level/to_enc.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/hsi.hh> + +#include <mln/fun/v2v/rgb_to_hsi.hh> +#include <mln/fun/meta/hue.hh> +#include <mln/fun/meta/sat.hh> +#include <mln/fun/meta/inty.hh> + +#include <mln/win/hline2d.hh> +#include <mln/win/vline2d.hh> + +#include <mln/morpho/hit_or_miss.hh> +#include <mln/morpho/gradient.hh> +#include <mln/morpho/opening.hh> + +#include <mln/binarization/threshold.hh> + +#include <mln/estim/mean.hh> + +#include "co_occurence.hh" + +using namespace mln; +using namespace value; + +enum doctype + { + TEXT, + SCREENSHOT, + PHOTO, + DRAWING, + NB_DOCTYPE + }; + +template <typename T> +unsigned nb_peaks (histo::data<T> &h) +{ + // First, we compute the maximum, ignoring the first column because it + // contains nonsense points + + unsigned max = 0; + mln_viter(mln::value::set<T>) v(h.vset()); + + for_all(v) + if (((T)v).to_enc() && (h(v) > max)) + max = h(v); + + // We take the first value into account + if (h[0] / 6 > max) + max = h[0] / 6; + + // Now we count the number of peaks over max / 4 + unsigned cpt = 0; + for_all(v) + if (h(v) >= max / 4) + cpt ++; + + return cpt; +} + + +int main (int argc, const char * argv []) +{ + if (argc != 2) { + std::cerr << "usage: " << argv[0] << " in.pgm" << std::endl; + return 1; + } + + unsigned score[NB_DOCTYPE]; + for (unsigned i = 0; i < NB_DOCTYPE; ++i) + score[i] = 0; + + border::thickness = 21; + + image2d<rgb8> input; + io::ppm::load(input, argv[1]); + + // First, we get the HSI histograms and corresponding greyscale versions of the picture + + image2d<hsi_f> hsi = level::transform(input, fun::v2v::f_rgb_to_hsi_f); + + thru<mln::meta::hue<hsi_f>, image2d<hsi_f> > hue(hsi); + thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > sat(hsi); + thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > inty(hsi); + + cast_image_<float01_8, thru<mln::meta::hue<hsi_f>, image2d<hsi_f> > > qhue(hue); // quantified hue + cast_image_<float01_8, thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > > qsat(sat); // quantified sat + cast_image_<float01_8, thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > > qinty(inty); // quantified inty + + histo::data<float01_8> hhue = histo::compute(qhue); + histo::data<float01_8> hsat = histo::compute(qsat); + histo::data<float01_8> hinty = histo::compute(qinty); + + + // Compute the number of peaks in the histogram to give a first intuition + + unsigned n = nb_peaks(hhue) * 3; + + if (n > 100) + n = 100; + + score[PHOTO] += n; + score[SCREENSHOT] += 20 + 80 - n * 80 / 100; + score[TEXT] += 100 - n; + score[DRAWING] += 20 + 80 - n * 80 / 100; + + std::cout << "Test 1 : peaks number[" << nb_peaks(hhue) << "]" << std::endl + << "Photo : " << score[PHOTO] << std::endl + << "Screenshot : " << score[SCREENSHOT] << std::endl + << "Text : " << score[TEXT] << std::endl + << "Drawing : " << score[DRAWING] << std::endl << std::endl; + + + // Now we compute the co-occurence matrice + + dpoint2d d(0, 1); + image2d<int_u8> uinty (qinty.domain()); + { + image2d<unsigned char> tmp = level::transform(qinty, fun::v2v::enc< float01_8 >()); + level::paste(tmp, uinty); + /* mln_piter_(image2d<unsigned char>) p(tmp.domain()); + for_all(p) + uinty(p) = tmp(p); + */ + } + + image2d<unsigned> mco (co_occurence(uinty, d)); + + // If there is a plain background, there will be a massive peak in the diagonal of the matrix + unsigned max = 0; + for (unsigned i = 0; i < mco.nrows(); i++) + if (mco.at(i, i) > max) + max = mco.at(i, i); + + for (unsigned i = 0; i < mco.nrows() - 1; i++) { + if (mco.at(i + 1, i) > max) + max = mco.at(i + 1, i); + if (mco.at(i, i + 1) > max) + max = mco.at(i, i + 1); + } + + max = max * 100 / input.nelements(); + + score[PHOTO] += 100 - max; + score[TEXT] += max * 2; + + score[SCREENSHOT] += 50 + max / 2; + score[DRAWING] += 50 + max / 2; + + std::cout << "Test 2 : co-occurence matrix diag_max[" << max << "]" << std::endl + << "Photo : +" << 100 - max << std::endl; + + std::cout << "Screenshot : +" << 50 + max / 2 << std::endl; + + std::cout << "Text : +" << max * 2 << std::endl; + + std::cout << "Drawing : +" << 50 + max / 2 << std::endl << std::endl; + + + + + // A good way to detect screenshots : rectangle detection + + // First, we compute the gradient + + win::rectangle2d rect(5, 5); + image2d<int_u8> grad = morpho::gradient(uinty, rect); + + // Then, we apply a lot of hit or miss filters ! + + // Compute the mean + int_u8 mean = estim::mean(grad); + + image2d<bool> imab = binarization::threshold(grad, 10); + + window2d winout; + window2d winin; + + static const bool blmatout [] = {0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0}; + + convert::from_to(blmatout, winout); + + static const bool blmatin [] = {0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + convert::from_to(blmatin, winin); + + image2d<bool> bottom_left = morpho::hit_or_miss(imab, winout, winin); + + + static const bool brmatout [] = {0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0}; + + static const bool brmatin [] = {0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(brmatout, winout); + convert::from_to(brmatin, winin); + image2d<bool> bottom_right = morpho::hit_or_miss(imab, winout, winin); + + static const bool urmatout [] = {0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0}; + + static const bool urmatin [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0}; + + + convert::from_to(urmatout, winout); + convert::from_to(urmatin, winin); + image2d<bool> up_right = morpho::hit_or_miss(imab, winout, winin); + + static const bool ulmatout [] = {0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0}; + + static const bool ulmatin [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0}; + + + convert::from_to(ulmatout, winout); + convert::from_to(ulmatin, winin); + image2d<bool> up_left = morpho::hit_or_miss(imab, winout, winin); + + + static const bool umatout [] = {0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + static const bool umatin [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(umatout, winout); + convert::from_to(umatin, winin); + image2d<bool> up = morpho::hit_or_miss(imab, winout, winin); + + + static const bool bmatout [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0}; + + static const bool bmatin [] = {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(bmatout, winout); + convert::from_to(bmatin, winin); + image2d<bool> bottom = morpho::hit_or_miss(imab, winout, winin); + + + static const bool lmatout [] = {0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0}; + + static const bool lmatin [] = {0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(lmatout, winout); + convert::from_to(lmatin, winin); + image2d<bool> left = morpho::hit_or_miss(imab, winout, winin); + + + static const bool rmatout [] = {0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0}; + + static const bool rmatin [] = {0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0}; + + + convert::from_to(rmatout, winout); + convert::from_to(rmatin, winin); + image2d<bool> right = morpho::hit_or_miss(imab, winout, winin); + + image2d<bool> inter (up_left + up_right + bottom_right + bottom_left + up + bottom + left + right); + + image2d<bool> final = morpho::opening(inter, win::hline2d(20)); + final += morpho::opening(inter, win::vline2d(20)); + + // Now we count blank points in our result + + unsigned cpt = 0; + mln_piter_(image2d<bool>) p (final.domain()); + for_all(p) + cpt += final(p); + + // compute the percentage of blank points + + cpt = 1000 * cpt / final.domain().nsites(); + + if (cpt > 50) + cpt = 50; + + score[PHOTO] += 50 - cpt; + score[SCREENSHOT] += cpt * 5; + score[TEXT] += 50 + cpt * max / 10; + score[DRAWING] += 2 * (50 - cpt); + + std::cout << "Test 3 : rectangle detection[" << cpt << "]" << std::endl + << "Photo : +" << 50 - cpt << std::endl + << "Screenshot : +" << cpt * 5 << std::endl + << "Text : +" << 50 + cpt * max / 10 << std::endl + << "Drawing : +" << 2 * (50 - cpt) << std::endl << std::endl; + + + // Print the result ! + + std::cout << "Photo : " << score[PHOTO] << std::endl + << "Screenshot : " << score[SCREENSHOT] << std::endl + << "Text : " << score[TEXT] << std::endl + << "Drawing : " << score[DRAWING] << std::endl; + + max = 0; + unsigned index = 0; + + for (unsigned i = 0; i < NB_DOCTYPE; ++i) + if (score[i] > max) + { + max = score[i]; + index = i; + } + + return index; +} Index: nature/opening.cc --- nature/opening.cc (revision 2815) +++ nature/opening.cc (working copy) @@ -49,7 +49,7 @@ image2d<int_u8> ima; io::pgm::load(ima, argv[i]); - win::rectangle2d rect(5, 5); + win::rectangle2d rect(1, 1); border::thickness = 11; std::string name(argv[i]); Index: nature/test.sh --- nature/test.sh (revision 0) +++ nature/test.sh (revision 0) @@ -0,0 +1,11 @@ +#! /bin/sh + +for i in $@; +do + echo $i; + echo ""; + ./nature $i; + echo ""; + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; + echo ""; +done; Property changes on: nature/test.sh ___________________________________________________________________ Added: svn:executable + *
participants (1)
-
Alexandre Abraham