https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Alexandre Abraham <abraham(a)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
+ *