Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 9625 discussions
URL: https://svn.lrde.epita.fr/svn/oln/trunk
ChangeLog:
2009-03-09 Frederic Bour <bour(a)lrde.epita.fr>
Add missing trait for thru_morpher.
* milena/sandbox/fred/fun/unary.hh: Add is_assignable trait, just
a workaround.
---
unary.hh | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
Index: trunk/milena/sandbox/fred/fun/unary.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/unary.hh (revision 3501)
+++ trunk/milena/sandbox/fred/fun/unary.hh (revision 3502)
@@ -77,6 +77,23 @@
};
}
+ namespace trait
+ {
+
+ namespace fun
+ {
+
+ /// Find correct implementation
+ template <typename F>
+ struct is_assignable
+ {
+ typedef metal::true_ ret;
+ };
+
+ }
+
+ }
+
namespace meta
{
template <template <class> class F>
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk
ChangeLog:
2009-03-09 Frederic Bour <bour(a)lrde.epita.fr>
Verify constness of "thru" image morpher.
* milena/mln/trait/image/props.hh: Correct small typos errors.
* milena/sandbox/fred/fun/abs.hh,
* milena/sandbox/fred/fun/cos.hh,
* milena/sandbox/fred/fun/inc.hh,
* milena/sandbox/fred/fun/norm.hh,
* milena/sandbox/fred/fun/red.hh:
Namespace name desambiguation.
* milena/sandbox/fred/fun/thru.cc,
* milena/sandbox/fred/fun/thru_morpher.hh:
Verify constness (WIP).
---
mln/trait/image/props.hh | 8 +--
sandbox/fred/fun/abs.hh | 4 -
sandbox/fred/fun/cos.hh | 4 -
sandbox/fred/fun/inc.hh | 4 -
sandbox/fred/fun/norm.hh | 12 ++--
sandbox/fred/fun/red.hh | 4 -
sandbox/fred/fun/thru.cc | 1
sandbox/fred/fun/thru_morpher.hh | 94 ++++++++++++++++++++++++++++++---------
8 files changed, 92 insertions(+), 39 deletions(-)
Index: trunk/milena/mln/trait/image/props.hh
===================================================================
--- trunk/milena/mln/trait/image/props.hh (revision 3500)
+++ trunk/milena/mln/trait/image/props.hh (revision 3501)
@@ -393,7 +393,7 @@
{
struct any { protected: any() {} };
struct slow : any { std::string name() const { return "speed::slow"; } };
- struct fast : any { std::string name() const { return "speedw::fast"; } };
+ struct fast : any { std::string name() const { return "speed::fast"; } };
struct fastest
: fast { std::string name() const { return "speed::fastest"; } };
};
@@ -502,11 +502,11 @@
struct any { protected: any() {} };
struct some : any { protected: some() {} };
struct read
- : some { std::string name() const { return "pw_io::read"; } };
+ : some { std::string name() const { return "vw_io::read"; } };
struct read_write
- : some { std::string name() const { return "pw_io::read_write"; } };
+ : some { std::string name() const { return "vw_io::read_write"; } };
struct none
- : any { std::string name() const { return "pw_io::none"; } };
+ : any { std::string name() const { return "vw_io::none"; } };
};
// vw_set: /any/
Index: trunk/milena/sandbox/fred/fun/cos.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/cos.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/cos.hh (revision 3501)
@@ -18,7 +18,7 @@
namespace trait
{
template <typename T>
- struct set_unary_<fun::cos, mln::value::Floating, T>
+ struct set_unary_<mln::fun::cos, mln::value::Floating, T>
{
typedef set_unary_ ret;
typedef T result;
@@ -39,7 +39,7 @@
namespace meta
{
- typedef unary<fun::cos> cos;
+ typedef unary<mln::fun::cos> cos;
}
}
Index: trunk/milena/sandbox/fred/fun/abs.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/abs.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/abs.hh (revision 3501)
@@ -17,7 +17,7 @@
namespace trait
{
template <typename T>
- struct set_unary_<fun::abs, mln::value::Scalar, T>
+ struct set_unary_<mln::fun::abs, mln::value::Scalar, T>
{
typedef set_unary_ ret;
typedef T result;
@@ -33,7 +33,7 @@
namespace meta
{
- typedef unary<fun::abs> abs;
+ typedef unary<mln::fun::abs> abs;
}
}
Index: trunk/milena/sandbox/fred/fun/thru.cc
===================================================================
--- trunk/milena/sandbox/fred/fun/thru.cc (revision 3500)
+++ trunk/milena/sandbox/fred/fun/thru.cc (revision 3501)
@@ -8,6 +8,7 @@
#include <iostream>
#define dbg_print(val) std::cout << #val << "\n\t -> \t" << (val) << std::endl
+
int main()
{
using namespace mln;
Index: trunk/milena/sandbox/fred/fun/inc.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/inc.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/inc.hh (revision 3501)
@@ -15,7 +15,7 @@
namespace trait
{
template <typename T>
- struct set_unary_<fun::inc, mln::value::Scalar, T>
+ struct set_unary_<mln::fun::inc, mln::value::Scalar, T>
{
typedef set_unary_ ret;
typedef T result;
@@ -36,7 +36,7 @@
namespace meta
{
- typedef unary<fun::inc> inc;
+ typedef unary<mln::fun::inc> inc;
}
}
Index: trunk/milena/sandbox/fred/fun/red.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/red.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/red.hh (revision 3501)
@@ -16,7 +16,7 @@
namespace trait
{
template <unsigned n>
- struct set_precise_unary_<fun::red, mln::value::rgb<n> >
+ struct set_precise_unary_<mln::fun::red, mln::value::rgb<n> >
{
typedef set_precise_unary_ ret;
typedef mln::value::rgb<n> argument;
@@ -37,7 +37,7 @@
namespace meta
{
- typedef unary<fun::red> red;
+ typedef unary<mln::fun::red> red;
}
}
Index: trunk/milena/sandbox/fred/fun/norm.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/norm.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/norm.hh (revision 3501)
@@ -25,7 +25,7 @@
namespace trait
{
template <unsigned n, typename T>
- struct set_precise_unary_<fun::norm::l1, mln::algebra::vec<n, T> >
+ struct set_precise_unary_<mln::fun::norm::l1, mln::algebra::vec<n, T> >
{
typedef set_precise_unary_ ret;
typedef mln::algebra::vec<n, T> argument;
@@ -44,7 +44,7 @@
};
template <unsigned n, typename T>
- struct set_precise_unary_<fun::norm::l2, mln::algebra::vec<n, T> >
+ struct set_precise_unary_<mln::fun::norm::l2, mln::algebra::vec<n, T> >
{
typedef set_precise_unary_ ret;
typedef mln::algebra::vec<n, T> argument;
@@ -63,7 +63,7 @@
};
template <unsigned n, typename T>
- struct set_precise_unary_<fun::norm::linfty, mln::algebra::vec<n, T> >
+ struct set_precise_unary_<mln::fun::norm::linfty, mln::algebra::vec<n, T> >
{
typedef set_precise_unary_ ret;
typedef mln::algebra::vec<n, T> argument;
@@ -86,9 +86,9 @@
{
namespace norm
{
- typedef unary<fun::norm::l1> l1;
- typedef unary<fun::norm::l2> l2;
- typedef unary<fun::norm::linfty> linfty;
+ typedef unary<mln::fun::norm::l1> l1;
+ typedef unary<mln::fun::norm::l2> l2;
+ typedef unary<mln::fun::norm::linfty> linfty;
}
}
}
Index: trunk/milena/sandbox/fred/fun/thru_morpher.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/thru_morpher.hh (revision 3500)
+++ trunk/milena/sandbox/fred/fun/thru_morpher.hh (revision 3501)
@@ -30,7 +30,9 @@
# define THRU_HH
# include <mln/core/internal/image_value_morpher.hh>
+# include <mln/metal/bexpr.hh>
# include "meta_function.hh"
+# include "unary.hh" // For is_assignable trait
// FIXME: constness of thru_image
@@ -40,9 +42,23 @@
// Forward declaration.
template <typename I, typename F> struct thru_image;
-
namespace internal
{
+ template <typename I, typename F> struct thru_image_write;
+ template <typename I, typename F> struct thru_image_read;
+
+ /// Find correct implementation
+ template <typename I, typename F>
+ struct thru_find_impl
+ {
+ typedef thru_image_write<I, F> write;
+ typedef thru_image_read<I, F> read;
+ typedef mlc_if(mlc_and(typename trait::fun::is_assignable<F>::ret,
+ mlc_and(mlc_not(mlc_is_const(I)),
+ mlc_equal(mln_trait_image_pw_io(I),
+ trait::image::pw_io::read_write))),
+ write, read) ret;
+ };
/// Data structure for \c mln::thru_image<I>.
template <typename I, typename F>
@@ -62,7 +78,7 @@
{
template <typename I, typename F>
- struct image_< thru_image<I, F> > : image_< I > // Same as I except...
+ struct image_< thru_image<I, F> > : image_< typename mln::internal::thru_find_impl<I, F>::ret > // Same as I except...
{
// ...these changes.
typedef trait::image::category::value_morpher category;
@@ -70,14 +86,29 @@
typedef trait::image::value_access::computed value_access;
};
+ template <typename I, typename F>
+ struct image_< mln::internal::thru_image_write<I, F> > : image_< I > // Same as I except...
+ {
+ typedef trait::image::vw_io::read_write vw_io;
+ };
+
+ template <typename I, typename F>
+ struct image_< mln::internal::thru_image_read<I, F> > : image_< I > // Same as I except...
+ {
+ typedef trait::image::vw_io::read vw_io;
+ };
+
} // end of namespace mln::trait
// FIXME: Doc!
+ namespace internal
+ {
+
template <typename I, typename F>
- class thru_image : public internal::image_value_morpher< I, typename F::result, thru_image<I,F> >
+ class thru_image_read : public internal::image_value_morpher< I, typename F::result, thru_image<I,F> >
{
public:
@@ -90,23 +121,39 @@
/// Value associated type.
typedef typename F::result value;
+ /// Return type of read-only access.
+ typedef typename F::result rvalue;
+
+ rvalue operator()(const mln_psite(I)& p) const;
+
+ };
+
+ // Inheritance from read ?!
+ template <typename I, typename F>
+ class thru_image_write : public thru_image_read<I,F>
+ {
+ public:
+
/// Type returned by the read-write pixel value operator.
typedef typename F::lresult lvalue;
- /// Return type of read-only access.
- typedef typename F::result rvalue;
+ using thru_image_read<I,F>::operator();
+ lvalue operator()(const mln_psite(I)& p);
+
+ };
+ }
+
+ template <typename I, typename F>
+ class thru_image : public internal::thru_find_impl<I, F>::ret
+ {
+ public:
thru_image();
thru_image(I& ima);
thru_image(I& ima, const F& f);
- // Initialize an empty image.
void init_(I& ima, const F& f);
- rvalue operator()(const mln_psite(I)& p) const;
-
- lvalue operator()(const mln_psite(I)& p);
-
/// Const promotion via conversion.
operator thru_image<const I, F>() const;
};
@@ -116,7 +163,7 @@
Image<I>& ima);
template <typename I, typename F>
- thru_image<const I, F> thru(const mln::Function<F>& f,
+ const thru_image<const I, F> thru(const mln::Function<F>& f,
const Image<I>& ima);
template <typename I, typename M>
@@ -124,7 +171,7 @@
thru(const mln::Meta_Function<M>& f, Image<I>& ima);
template <typename I, typename M>
- thru_image<const I, mln_fun_with(M, mln_value(I))>
+ const thru_image<const I, mln_fun_with(M, mln_value(I))>
thru(const mln::Meta_Function<M>& f, const Image<I>& ima);
# ifndef MLN_INCLUDE_ONLY
@@ -180,17 +227,19 @@
template <typename I, typename F>
inline
- typename thru_image<I, F>::rvalue
- thru_image<I, F>::operator()(const mln_psite(I)& p) const
+ thru_image<I, F>::operator thru_image<const I, F>() const
{
- mln_precondition(this->is_valid());
- return this->data_->f_(this->data_->ima_(p));
+ thru_image<const I, F> tmp(this->data_->ima_, this->data_->f_);
+ return tmp;
}
+ namespace internal
+ {
+
template <typename I, typename F>
inline
- typename thru_image<I, F>::lvalue
- thru_image<I, F>::operator()(const mln_psite(I)& p)
+ typename thru_image_read<I, F>::rvalue
+ thru_image_read<I, F>::operator()(const mln_psite(I)& p) const
{
mln_precondition(this->is_valid());
return this->data_->f_(this->data_->ima_(p));
@@ -198,10 +247,13 @@
template <typename I, typename F>
inline
- thru_image<I, F>::operator thru_image<const I, F>() const
+ typename thru_image_write<I, F>::lvalue
+ thru_image_write<I, F>::operator()(const mln_psite(I)& p)
{
- thru_image<const I, F> tmp(this->data_->ima_, this->data_->default_value_);
- return tmp;
+ mln_precondition(this->is_valid());
+ return this->data_->f_(this->data_->ima_(p));
+ }
+
}
// thru
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-09 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Fix dicom_mask binary.
* fabien/bin/dicom_mask.cc: Fix bugs.
* fabien/igr/watershed.cc: Update with watershed implementation.
---
TODO | 2 ++
bin/dicom_mask.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++++-------
igr/watershed.cc | 37 ++++++++++++++++++++++++-------------
3 files changed, 73 insertions(+), 20 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/watershed.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed.cc (revision 3499)
+++ trunk/milena/sandbox/fabien/igr/watershed.cc (revision 3500)
@@ -52,6 +52,7 @@
#include <mln/draw/box.hh>
#include <mln/level/stretch.hh>
#include <mln/fun/v2v/id.hh>
+#include <mln/fun/l2l/wrap.hh>
#include <mln/core/image/line_graph_elt_neighborhood.hh>
#include <mln/morpho/elementary/dilation.hh>
#include <mln/labeling/mean_values.hh>
@@ -121,7 +122,7 @@
{
// Cf. sandbox/theo/color/segment_rgb_pixels.cc
- util::array<vec3d_f> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ util::array<float> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
input, // input color image
w, // watershed labeling
nbasins);
@@ -129,11 +130,11 @@
util::array<mln_value(I)> m;
convert::from_to(m_3f, m);
- m[0] = literal::yellow;
+ m[0] = 150u;
- io::ppm::save(level::transform(w,
+ /*io::ppm::save(level::transform(w,
convert::to< fun::i2v::array<mln_value(I)> >(m)),
- "wst_rag_wshd_color.ppm");
+ "wst_rag_wshd_color.ppm");*/
return m;
}
@@ -159,7 +160,7 @@
typedef fun::i2v::array<mln_value(I)> vertex_values_t;
vertex_values_t vertex_values;
- // convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+ convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
mln_VAR(ima_v, (vertex_values | pv));
@@ -203,14 +204,14 @@
image2d<mln_value(I)>
make_debug_graph_image(const I& input,
const V& ima_v, const E& ima_e,
- unsigned box_size, const value::rgb8& bg)
+ unsigned box_size, const value::int_u12& bg)
{
image2d<mln_value(I)> ima;
initialize(ima, input);
data::fill(ima, bg);
debug::draw_graph(ima, ima_v.domain(),
- pw::cst(mln_value(I)(literal::green)),
+ pw::cst(150u),
edge_to_color<E, mln_value(I)>(ima_e));
dpoint2d tl(-box_size,-box_size);
@@ -246,26 +247,35 @@
if (argc < 4)
{
- std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size>"
+ std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size> <dist_max>"
<< std::endl;
return 1;
}
+ unsigned closure_lambda = atoi(argv[2]);
unsigned box_size = atoi(argv[3]);
+ unsigned dist_max = atoi(argv[4]);
image2d<int_u12> dcm;
io::dicom::load(dcm, argv[1]);
+ io::pgm::save(level::stretch(int_u8(), dcm), "wsd_01_src.pgm");
+
image2d<int_u12> grad = morpho::gradient(dcm, win_c4p());
- image2d<int_u12> clo = morpho::closing::area(grad, c4(), atoi(argv[2]));
+ image2d<int_u12> clo = morpho::closing::area(grad, c4(), closure_lambda);
label_16 nbasins;
image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+ io::pgm::save(level::stretch(int_u8(), clo), "wsd_02.pgm");
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_03.pgm");
+
mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u), wshed), c8()));
data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()), "wsd_04.pgm");
+
/// Build graph
util::graph g = make::graph(wshed, c4(), nbasins);
// Build graph images and compute distance values with a RGB image.
@@ -282,8 +292,7 @@
{
unsigned v1 = e.element().v1();
unsigned v2 = e.element().v2();
- if (ima_e(e) <= (unsigned)(atoi(argv[5]))
- && find_root(parent, v1) != find_root(parent, v2))
+ if (ima_e(e) <= dist_max && find_root(parent, v1) != find_root(parent, v2))
parent[find_root(parent, v1)] = find_root(parent, v2);
}
@@ -302,6 +311,7 @@
--nbasins2; // nbasins2 does not count the basin with label 0.
image2d<label_16> wsd2 = level::transform(wshed, f);
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_05.pgm");
/// Reconstruct a graph from the simplified image.
util::graph g2 = make::graph(wsd2, c4(), nbasins2);
@@ -314,7 +324,8 @@
data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()), "wsd_99_result.pgm");
//io::ppm::save(labeling::mean_values(dcm, wsd2, nbasins2), "wst_rag_mean_colors.ppm");
- //io::ppm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, literal::white), "wst_rag_graph_image2_white.ppm");
- //io::ppm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, literal::black), "wst_rag_graph_image2_black.ppm");
+ io::pgm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 4095), "wsd_graph_image2_white.pgm");
+ io::pgm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, 0), "wsd_graph_image2_black.pgm");
}
Index: trunk/milena/sandbox/fabien/TODO
===================================================================
--- trunk/milena/sandbox/fabien/TODO (revision 3499)
+++ trunk/milena/sandbox/fabien/TODO (revision 3500)
@@ -21,3 +21,5 @@
[X] Create dicom2dump (2d, 3d, int_u8, int_u12)
[ ] After threshold, take biggest object and then erode, dilate
[ ] Fix n_max
+[ ] Create routine for binary images (keep n big bg & m big objects)
+[ ] US: projection of internal gradient
Index: trunk/milena/sandbox/fabien/bin/dicom_mask.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dicom_mask.cc (revision 3499)
+++ trunk/milena/sandbox/fabien/bin/dicom_mask.cc (revision 3500)
@@ -1,5 +1,7 @@
#include <mln/core/concept/image.hh>
#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/var.hh>
#include <mln/geom/ncols.hh>
#include <mln/geom/nrows.hh>
@@ -9,6 +11,7 @@
#include <mln/io/pbm/save.hh>
#include <mln/literal/colors.hh>
+#include <mln/morpho/elementary/gradient_internal.hh>
#include <mln/level/transform.hh>
#include <mln/fun/v2b/threshold.hh>
@@ -36,29 +39,66 @@
image2d<int_u8> input;
io::dicom::load(input, argv[1]);
- util::array<unsigned> xproj(geom::nrows(input), 0);
- util::array<unsigned> yproj(geom::ncols(input), 0);
+ util::array<unsigned> xsrcproj(geom::nrows(input), 0);
+ util::array<unsigned> ysrcproj(geom::ncols(input), 0);
- mln_piter_(image2d<int_u8>) p(input.domain());
+ mln_piter_(image2d<int_u8>) psrc(input.domain());
+ for_all(psrc)
+ {
+ xsrcproj[psrc.row()] += input(psrc);
+ ysrcproj[psrc.col()] += input(psrc);
+ }
+ std::ofstream fout_xsrc("xsrc.plot");
+ for (unsigned int i = 0; i < xsrcproj.nelements(); ++i)
+ {
+ fout_xsrc << i << " " << xsrcproj[i] << std::endl;
+ }
+ std::ofstream fout_ysrc("ysrc.plot");
+ for (unsigned int i = 0; i < ysrcproj.nelements(); ++i)
+ {
+ fout_ysrc << i << " " << ysrcproj[i] << std::endl;
+ }
+
+ image2d<bool> ima = level::transform(input, fun::v2b::threshold<int_u8>(1));
+ io::pbm::save(ima, argv[2]);
+ mln_VAR(grad_int, morpho::elementary::gradient_internal(ima, c4()));
+
+ util::array<unsigned> xproj(geom::nrows(ima), 0);
+ util::array<unsigned> yproj(geom::ncols(ima), 0);
+ util::array<unsigned> xgradproj(geom::nrows(grad_int), 0);
+ util::array<unsigned> ygradproj(geom::ncols(grad_int), 0);
+
+ mln_piter_(image2d<bool>) p(ima.domain());
for_all(p)
{
- xproj[p.row()] += input(p);
- yproj[p.col()] += input(p);
+ if (ima(p))
+ {
+ ++xproj[p.row()];
+ ++yproj[p.col()];
+ }
+ }
+ mln_piter_(image2d<int_u8>) pgrad(grad_int.domain());
+ for_all(pgrad)
+ {
+ xgradproj[pgrad.row()] += grad_int(pgrad);
+ ygradproj[pgrad.col()] += grad_int(pgrad);
}
// Plot files
std::ofstream fout_x("x.plot");
+ std::ofstream fout_xgrad("xgrad.plot");
for (unsigned int i = 0; i < xproj.nelements(); ++i)
{
fout_x << i << " " << xproj[i] << std::endl;
+ fout_xgrad << i << " " << xgradproj[i] << std::endl;
}
std::ofstream fout_y("y.plot");
+ std::ofstream fout_ygrad("ygrad.plot");
for (unsigned int i = 0; i < yproj.nelements(); ++i)
{
fout_y << i << " " << yproj[i] << std::endl;
+ fout_ygrad << i << " " << ygradproj[i] << std::endl;
}
- image2d<bool> ima = level::transform(input, fun::v2b::threshold<int_u8>(1));
- io::pbm::save(ima, argv[2]);
}
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-03-08 Frederic Bour <bour(a)lrde.epita.fr>
Add work on meta functions and thru morpher.
* sandbox/fred/fun/abs.hh: New.
* sandbox/fred/fun/cos.hh: New.
* sandbox/fred/fun/fun.cc: New.
Some tests don't pass, see FIXMEs (operator==(rgb::red_t,int) ?)
* sandbox/fred/fun/inc.hh: New.
* sandbox/fred/fun/meta_function.hh: New.
* sandbox/fred/fun/norm.hh: New.
* sandbox/fred/fun/red.hh: New.
* sandbox/fred/fun/thru.cc: New.
* sandbox/fred/fun/thru_morpher.hh: New.
Constness of thru_image has to be corrected.
* sandbox/fred/fun/unary.hh: New.
* sandbox/fred/fun: New.
---
abs.hh | 40 ++++++++
cos.hh | 46 ++++++++++
fun.cc | 103 ++++++++++++++++++++++
inc.hh | 43 +++++++++
meta_function.hh | 132 +++++++++++++++++++++++++++++
norm.hh | 96 +++++++++++++++++++++
red.hh | 44 +++++++++
thru.cc | 30 ++++++
thru_morpher.hh | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
unary.hh | 115 +++++++++++++++++++++++++
10 files changed, 898 insertions(+)
Index: trunk/milena/sandbox/fred/fun/cos.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/cos.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/cos.hh (revision 3498)
@@ -0,0 +1,46 @@
+#ifndef COS_HH
+# define COS_HH
+
+# include "unary.hh"
+# include <mln/value/concept/floating.hh>
+# include <mln/math/acos.hh>
+# include <mln/math/cos.hh>
+
+namespace mln
+{
+ // COS, bijective
+ namespace fun
+ {
+ template <typename T>
+ struct cos : unary<cos, T> {};
+ }
+
+ namespace trait
+ {
+ template <typename T>
+ struct set_unary_<fun::cos, mln::value::Floating, T>
+ {
+ typedef set_unary_ ret;
+ typedef T result;
+ typedef T argument;
+ typedef T& lvalue;
+
+ static result read(const argument& x)
+ {
+ return math::cos(x);
+ }
+
+ static void write(lvalue l, const result& x)
+ {
+ l = math::acos(x);
+ }
+ };
+ }
+
+ namespace meta
+ {
+ typedef unary<fun::cos> cos;
+ }
+}
+
+#endif /* ! COS_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/abs.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/abs.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/abs.hh (revision 3498)
@@ -0,0 +1,40 @@
+#ifndef ABS_HH
+# define ABS_HH
+
+# include "unary.hh"
+# include <mln/value/concept/scalar.hh>
+# include <mln/math/abs.hh>
+
+namespace mln
+{
+ // ABS, pure
+ namespace fun
+ {
+ template <typename T>
+ struct abs : unary<abs, T> {};
+ }
+
+ namespace trait
+ {
+ template <typename T>
+ struct set_unary_<fun::abs, mln::value::Scalar, T>
+ {
+ typedef set_unary_ ret;
+ typedef T result;
+ typedef T argument;
+ typedef T& lvalue;
+
+ static result read(const argument& x)
+ {
+ return math::abs(x);
+ }
+ };
+ }
+
+ namespace meta
+ {
+ typedef unary<fun::abs> abs;
+ }
+}
+
+#endif /* ! ABS_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/thru.cc
===================================================================
--- trunk/milena/sandbox/fred/fun/thru.cc (revision 0)
+++ trunk/milena/sandbox/fred/fun/thru.cc (revision 3498)
@@ -0,0 +1,30 @@
+// Meta functions test
+#include "cos.hh"
+#include "thru_morpher.hh"
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/debug/all.hh>
+#include <iostream>
+
+#define dbg_print(val) std::cout << #val << "\n\t -> \t" << (val) << std::endl
+int main()
+{
+ using namespace mln;
+
+ meta::cos cos;
+ typedef image2d<float> I;
+ I ima(5, 5);
+
+ image2d<value::int_u8> tmp(5, 5);
+ debug::iota(tmp);
+ data::fill_with_image(ima, tmp);
+
+ debug::println(ima);
+ debug::println(thru(meta::cos(), ima));
+
+ thru_image<I, mln::fun::cos<float> > ima2 = thru(meta::cos(), ima);
+ data::fill_with_image(ima2, (pw::value(tmp) - pw::cst(13.0f)) / pw::cst(12.0f) | tmp.domain());
+
+ debug::println(ima);
+}
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/inc.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/inc.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/inc.hh (revision 3498)
@@ -0,0 +1,43 @@
+#ifndef INC_HH
+# define INC_HH
+
+# include "unary.hh"
+
+namespace mln
+{
+ // INC, bijective
+ namespace fun
+ {
+ template <typename T>
+ struct inc : unary<inc, T> {};
+ }
+
+ namespace trait
+ {
+ template <typename T>
+ struct set_unary_<fun::inc, mln::value::Scalar, T>
+ {
+ typedef set_unary_ ret;
+ typedef T result;
+ typedef T argument;
+ typedef T& lvalue;
+
+ static result read(const argument& x)
+ {
+ return x + 1;
+ }
+
+ static void write(lvalue l, const result& r)
+ {
+ l = r - 1;
+ }
+ };
+ }
+
+ namespace meta
+ {
+ typedef unary<fun::inc> inc;
+ }
+}
+
+#endif /* ! INC_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/red.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/red.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/red.hh (revision 3498)
@@ -0,0 +1,44 @@
+#ifndef RED_HH
+# define RED_HH
+
+# include "unary.hh"
+# include <mln/value/rgb.hh>
+
+namespace mln
+{
+ // RED, assignable
+ namespace fun
+ {
+ template <typename T>
+ struct red : unary<red, T> {};
+ }
+
+ namespace trait
+ {
+ template <unsigned n>
+ struct set_precise_unary_<fun::red, mln::value::rgb<n> >
+ {
+ typedef set_precise_unary_ ret;
+ typedef mln::value::rgb<n> argument;
+ typedef typename argument::red_t result;
+ typedef argument& lvalue;
+
+ static result read(const argument& x)
+ {
+ return x.red();
+ }
+
+ static void write(lvalue l, const result& r)
+ {
+ l.red() = r;
+ }
+ };
+ }
+
+ namespace meta
+ {
+ typedef unary<fun::red> red;
+ }
+}
+
+#endif /* ! RED_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/meta_function.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/meta_function.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/meta_function.hh (revision 3498)
@@ -0,0 +1,132 @@
+// 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 F 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_CORE_CONCEPT_META_FUNCTION_HH
+# define MLN_CORE_CONCEPT_META_FUNCTION_HH
+
+/// \file mln/core/concept/meta_function.hh
+///
+/// Definition of the concept of mln::Meta_Function.
+
+# include <mln/core/concept/object.hh>
+# include <mln/core/concept/function.hh>
+
+
+# define mln_fun_with(F, T) \
+typename F::template with< T >::ret
+
+# define mln_fun_with_(F, T) \
+F::with< T >::ret
+
+
+# define mln_fun_result(F, T) \
+typename F::template with< T >::ret::result
+
+
+# define mln_fun_result_(F, T) \
+F::with< T >::ret::result
+
+
+
+namespace mln
+{
+
+ // Fwd decl.
+ template <typename E> struct Meta_Function;
+
+ // Meta_Function category flag type.
+ template <>
+ struct Meta_Function<void>
+ {
+ typedef Object<void> super;
+ };
+
+
+ /*! \brief Base class for implementation of meta functions.
+ *
+ * The parameter \a E is the exact type.
+ *
+ * \see mln::doc::Meta_Function for a complete documentation of
+ * this class contents.
+ */
+ template <typename E>
+ struct Meta_Function : public Object<E>
+ {
+ typedef Meta_Function<void> category;
+ protected:
+ Meta_Function();
+ };
+
+
+ namespace fun
+ {
+
+ // To be specialized when some state (attributes) have to be transfered
+ // from the meta-function to the function.
+ // Warning: the first argument has to be an object with the exact type.
+ template <typename M, typename T>
+ mln_fun_with(M, T)
+ unmeta(const M&, T);
+
+ template <typename M, typename T>
+ void
+ unmeta(const Meta_Function<M>&, T); // Safety.
+
+ } // end of namespace mln::fun
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename E>
+ inline
+ Meta_Function<E>::Meta_Function()
+ {
+ // FIXME: Check "with" on E.
+ }
+
+ namespace fun
+ {
+
+ template <typename M, typename T>
+ inline
+ mln_fun_with(M, T)
+ unmeta(const M&, T)
+ {
+ mlc_is_a(M, Meta_Function)::check();
+ mln_fun_with(M, T) a;
+ return a;
+ }
+
+ } // end of namespace mln::fun
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_CONCEPT_META_FUNCTION_HH
Index: trunk/milena/sandbox/fred/fun/norm.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/norm.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/norm.hh (revision 3498)
@@ -0,0 +1,96 @@
+#ifndef NORM_HH
+# define NORM_HH
+
+# include "unary.hh"
+# include <mln/norm/all.hh>
+
+namespace mln
+{
+ // NORMS, reversible
+ namespace fun
+ {
+ namespace norm
+ {
+ template <typename T>
+ struct l1 : unary<l1, T> {};
+
+ template <typename T>
+ struct l2 : unary<l2, T> {};
+
+ template <typename T>
+ struct linfty : unary<linfty, T> {};
+ }
+ }
+
+ namespace trait
+ {
+ template <unsigned n, typename T>
+ struct set_precise_unary_<fun::norm::l1, mln::algebra::vec<n, T> >
+ {
+ typedef set_precise_unary_ ret;
+ typedef mln::algebra::vec<n, T> argument;
+ typedef argument& lvalue;
+ typedef mln_sum_product(argument,argument) result;
+
+ static result read(const argument& x)
+ {
+ return mln::norm::l1(x);
+ }
+
+ static void write(lvalue l, const result& x)
+ {
+ l = l / read(l) * x;
+ }
+ };
+
+ template <unsigned n, typename T>
+ struct set_precise_unary_<fun::norm::l2, mln::algebra::vec<n, T> >
+ {
+ typedef set_precise_unary_ ret;
+ typedef mln::algebra::vec<n, T> argument;
+ typedef argument& lvalue;
+ typedef mln_sum_product(argument,argument) result;
+
+ static result read(const argument& x)
+ {
+ return mln::norm::l2(x);
+ }
+
+ static void write(lvalue l, const result& x)
+ {
+ l = l / read(l) * x;
+ }
+ };
+
+ template <unsigned n, typename T>
+ struct set_precise_unary_<fun::norm::linfty, mln::algebra::vec<n, T> >
+ {
+ typedef set_precise_unary_ ret;
+ typedef mln::algebra::vec<n, T> argument;
+ typedef argument& lvalue;
+ typedef mln_sum_product(argument,argument) result;
+
+ static result read(const argument& x)
+ {
+ return mln::norm::linfty(x);
+ }
+
+ static void write(lvalue l, const result& x)
+ {
+ l = l / read(l) * x;
+ }
+ };
+ }
+
+ namespace meta
+ {
+ namespace norm
+ {
+ typedef unary<fun::norm::l1> l1;
+ typedef unary<fun::norm::l2> l2;
+ typedef unary<fun::norm::linfty> linfty;
+ }
+ }
+}
+
+#endif /* ! NORM_HH */
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/fun.cc
===================================================================
--- trunk/milena/sandbox/fred/fun/fun.cc (revision 0)
+++ trunk/milena/sandbox/fred/fun/fun.cc (revision 3498)
@@ -0,0 +1,103 @@
+// Meta functions test
+#include "abs.hh"
+#include "cos.hh"
+#include "inc.hh"
+#include "norm.hh"
+#include "red.hh"
+
+#include <iostream>
+
+#define dbg_print(val) std::cout << #val << "\n\t -> \t" << (val) << std::endl
+int main()
+{
+ mln::meta::abs abs;
+ mln::meta::cos cos;
+ mln::meta::inc inc;
+ mln::meta::red red;
+
+ mln::meta::norm::l1 l1;
+ mln::meta::norm::l2 l2;
+ mln::meta::norm::linfty linfty;
+
+ std::cout << "Read only tests." << std::endl;
+ std::cout << "----------------" << std::endl;
+
+ // ABS
+ mln_invariant(abs(-1) == 1);
+ dbg_print(abs(-1));
+ dbg_print(abs(-3.1415926535));
+
+ // INC
+ mln_invariant(inc(-1) == 0);
+ dbg_print(inc(-1));
+ dbg_print(inc(-3.1415926535));
+
+ // COS
+ mln_invariant(cos(0.) == 1.);
+ dbg_print(cos(0.));
+ dbg_print(cos(mln::math::acos(0.5)));
+
+ // RED
+ mln_invariant(red(mln::value::rgb8(8,13,21)) == 8);
+ dbg_print(red(mln::value::rgb8(8,13,21)));
+
+ // NORM
+ mln::algebra::vec<3, double> v;
+ v[0] = 1;
+ v[1] = -1;
+ v[2] = 0;
+ dbg_print(v);
+ dbg_print(l1(v));
+ dbg_print(l2(v));
+ dbg_print(linfty(v));
+
+ std::cout << "Read/Write tests." << std::endl;
+ std::cout << "-----------------" << std::endl;
+
+ // INC
+ {
+ int x;
+ dbg_print(inc(x) = 1);
+ mln_invariant(inc(x) == 1);
+ dbg_print(inc(x));
+ dbg_print(x);
+ }
+
+ // COS
+ {
+ double x;
+ dbg_print(cos(x) = 1.);
+ mln_invariant(cos(x) == 1.);
+ dbg_print(x);
+ }
+
+ // RED
+ {
+ mln::value::rgb8 rgb(8,13,21);
+ dbg_print(rgb);
+ dbg_print(red(rgb) = 0);
+// FIXME: Doesn't compile! mln_invariant(red(rgb) == 0);
+ dbg_print(rgb);
+ }
+
+ // NORM
+ {
+ dbg_print(v);
+ dbg_print(l1(v) = 1.0);
+ dbg_print(l1(v));
+ dbg_print(v);
+// mln_invariant(l1(v) == 1.0); FIXME: check with epsilon
+
+ dbg_print(l2(v) = 1.0);
+ dbg_print(l2(v));
+ dbg_print(v);
+// mln_invariant(l2(v) == 1.0);
+
+ dbg_print(linfty(v) = 1.0);
+ dbg_print(linfty(v));
+ dbg_print(v);
+// mln_invariant(linfty(v) == 1.0);
+ }
+
+ std::cout << "All invariants passed." << std::endl;
+}
\ No newline at end of file
Index: trunk/milena/sandbox/fred/fun/thru_morpher.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/thru_morpher.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/thru_morpher.hh (revision 3498)
@@ -0,0 +1,249 @@
+// 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.
+
+#ifndef THRU_HH
+# define THRU_HH
+
+# include <mln/core/internal/image_value_morpher.hh>
+# include "meta_function.hh"
+
+// FIXME: constness of thru_image
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename I, typename F> struct thru_image;
+
+
+ namespace internal
+ {
+
+ /// Data structure for \c mln::thru_image<I>.
+ template <typename I, typename F>
+ struct data< thru_image<I, F> >
+ {
+ data(I& ima, const F& f);
+
+ I ima_;
+ // FIXME: value or pointer or whatever ?
+ F f_;
+ };
+
+ } // end of namespace mln::internal
+
+
+ namespace trait
+ {
+
+ template <typename I, typename F>
+ struct image_< thru_image<I, F> > : image_< I > // Same as I except...
+ {
+ // ...these changes.
+ typedef trait::image::category::value_morpher category;
+ typedef mln_internal_trait_image_speed_from(I) speed; // Un-fastest.
+ typedef trait::image::value_access::computed value_access;
+ };
+
+ } // end of namespace mln::trait
+
+
+
+ // FIXME: Doc!
+
+ template <typename I, typename F>
+ class thru_image : public internal::image_value_morpher< I, typename F::result, thru_image<I,F> >
+ {
+ public:
+
+ /// Skeleton.
+ typedef thru_image<tag::image_<I>, F> skeleton;
+
+ /// Point_Site associated type.
+ typedef mln_psite(I) psite;
+
+ /// Value associated type.
+ typedef typename F::result value;
+
+ /// Type returned by the read-write pixel value operator.
+ typedef typename F::lresult lvalue;
+
+ /// Return type of read-only access.
+ typedef typename F::result rvalue;
+
+ thru_image();
+ thru_image(I& ima);
+ thru_image(I& ima, const F& f);
+
+ // Initialize an empty image.
+ void init_(I& ima, const F& f);
+
+ rvalue operator()(const mln_psite(I)& p) const;
+
+ lvalue operator()(const mln_psite(I)& p);
+
+ /// Const promotion via conversion.
+ operator thru_image<const I, F>() const;
+ };
+
+ template <typename I, typename F>
+ thru_image<I, F> thru(const mln::Function<F>& f,
+ Image<I>& ima);
+
+ template <typename I, typename F>
+ thru_image<const I, F> thru(const mln::Function<F>& f,
+ const Image<I>& ima);
+
+ template <typename I, typename M>
+ thru_image<I, mln_fun_with(M, mln_value(I))>
+ thru(const mln::Meta_Function<M>& f, Image<I>& ima);
+
+ template <typename I, typename M>
+ thru_image<const I, mln_fun_with(M, mln_value(I))>
+ thru(const mln::Meta_Function<M>& f, const Image<I>& ima);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // internal::data< thru_image<I,S> >
+
+ namespace internal
+ {
+
+ template <typename I, typename F>
+ inline
+ data< thru_image<I, F> >::data(I& ima, const F& f)
+ : ima_(ima),
+ f_(f)
+ {
+ }
+
+ } // end of namespace mln::internal
+
+ // thru_image<I>
+
+ template <typename I, typename F>
+ inline
+ thru_image<I, F>::thru_image()
+ {
+ }
+
+ template <typename I, typename F>
+ inline
+ thru_image<I, F>::thru_image(I& ima, const F& f)
+ {
+ mln_precondition(ima.is_valid());
+ init_(ima, f);
+ }
+
+ template <typename I, typename F>
+ inline
+ thru_image<I, F>::thru_image(I& ima)
+ {
+ mln_precondition(ima.is_valid());
+ init_(ima, mln_value(I)());
+ }
+
+ template <typename I, typename F>
+ inline
+ void
+ thru_image<I, F>::init_(I& ima, const F& f)
+ {
+ mln_precondition(! this->is_valid());
+ mln_precondition(ima.is_valid());
+ this->data_ = new internal::data< thru_image<I, F> >(ima, f);
+ }
+
+ template <typename I, typename F>
+ inline
+ typename thru_image<I, F>::rvalue
+ thru_image<I, F>::operator()(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->f_(this->data_->ima_(p));
+ }
+
+ template <typename I, typename F>
+ inline
+ typename thru_image<I, F>::lvalue
+ thru_image<I, F>::operator()(const mln_psite(I)& p)
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->f_(this->data_->ima_(p));
+ }
+
+ template <typename I, typename F>
+ inline
+ thru_image<I, F>::operator thru_image<const I, F>() const
+ {
+ thru_image<const I, F> tmp(this->data_->ima_, this->data_->default_value_);
+ return tmp;
+ }
+
+ // thru
+ template <typename I, typename F>
+ thru_image<I, F> thru(const mln::Function<F>& f,
+ Image<I>& ima)
+ {
+ thru_image<I, F> tmp(exact(ima), exact(f));
+ return tmp;
+ }
+
+ template <typename I, typename F>
+ thru_image<const I, F> thru(const mln::Function<F>& f,
+ const Image<I>& ima)
+ {
+ thru_image<const I, F> tmp(exact(ima), exact(f));
+ return tmp;
+ }
+
+ template <typename I, typename M>
+ thru_image<I, mln_fun_with(M, mln_value(I))>
+ thru(const mln::Meta_Function<M>& f, Image<I>& ima)
+ {
+ typedef mln_fun_with(M, mln_value(I)) F;
+ thru_image<I, F> tmp(exact(ima), F());
+
+ return tmp;
+ }
+
+ template <typename I, typename M>
+ thru_image<const I, mln_fun_with(M, mln_value(I))>
+ thru(const mln::Meta_Function<M>& f, const Image<I>& ima)
+ {
+ typedef mln_fun_with(M, mln_value(I)) F;
+ thru_image<const I, F> tmp(exact(ima), F());
+
+ return tmp;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! THRU_HH
Index: trunk/milena/sandbox/fred/fun/unary.hh
===================================================================
--- trunk/milena/sandbox/fred/fun/unary.hh (revision 0)
+++ trunk/milena/sandbox/fred/fun/unary.hh (revision 3498)
@@ -0,0 +1,115 @@
+#ifndef UNARY_HH
+# define UNARY_HH
+
+# include <mln/trait/solve.hh>
+# include <mln/fun/essential.hh>
+# include <mln/fun/internal/resolve.hh>
+# include "meta_function.hh"
+
+namespace mln
+{
+ // UNARY
+ namespace fun
+ {
+ namespace internal
+ {
+ template <typename Impl>
+ struct unary_modifier
+ {
+ typedef typename Impl::result result;
+ typedef typename Impl::argument argument;
+ typedef typename Impl::lvalue lvalue;
+ typedef unary_modifier lresult;
+
+ // FIXME: argument or lvalue? ~~~
+ unary_modifier(argument& x)
+ : x_(&x)
+ {
+ }
+
+ result to_result() const
+ {
+ return Impl::read(*x_);
+ };
+
+ operator result() const
+ {
+ return to_result();
+ };
+
+ const result& operator = (const result& r) const
+ {
+ Impl::write(*x_, r);
+ return r;
+ }
+
+ private:
+ argument *x_;
+ };
+ }
+
+ template <template <class> class Fun, typename T>
+ struct unary : mln::Function_v2v< Fun<T> >
+ {
+ // FIXME: mln_fun_internal_resolve? Fun<T> is not defined at this point...
+ // so mln_is_a(Fun<T>, Function) won't work.
+ typedef typename mln::trait::solve_unary< Fun, T >::ret impl;
+
+ typedef typename impl::result result;
+ typedef typename impl::argument argument;
+ typedef typename impl::lvalue lvalue;
+ typedef internal::unary_modifier<impl> lresult;
+
+ result operator () (const argument& value) const
+ {
+ return impl::read(value);
+ }
+
+ lresult operator () (argument& value) const
+ {
+ return lresult(value);
+ }
+
+ void set(lvalue l, const result& r) const
+ {
+ impl::write(l, r);
+ }
+ };
+ }
+
+ namespace meta
+ {
+ template <template <class> class F>
+ struct unary : mln::Meta_Function< unary<F> >
+ {
+ template <typename T>
+ typename F<T>::result operator()(const T& v) const
+ {
+ F<T> tmp;
+ return tmp(v);
+ }
+
+ template <typename T>
+ typename F<T>::lresult operator()(T& v) const
+ {
+ F<T> tmp;
+ return tmp(v);
+ }
+
+ template <typename T>
+ struct with
+ {
+ typedef F<T> ret;
+ };
+ };
+ }
+
+}
+
+template <typename Impl>
+std::ostream& operator << (std::ostream& o, const mln::fun::internal::unary_modifier<Impl>& m)
+{
+ return o << m.to_result();
+}
+
+#endif /* ! UNARY_HH */
\ No newline at end of file
1
0
r3497: Add routine to calculate the number of components retaled to a createria
by Edwin Carlinet 06 Mar '09
by Edwin Carlinet 06 Mar '09
06 Mar '09
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-06 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Add routine to calculate the number of components retaled to a createria.
* edwin/tree/propagate.hh: Back propagation iterates on nodes now.
* edwin/tree/routines.hh: Add routine to get hightest nodes
satifying a criteria .
* edwin/tree/tree.cc: Add function to calcul number of
components retaled to a createria (in expectation of finding a
treshold).
---
propagate.hh | 13 +++--
routines.hh | 46 +------------------
tree.cc | 136 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
3 files changed, 122 insertions(+), 73 deletions(-)
Index: trunk/milena/sandbox/edwin/tree/propagate.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate.hh (revision 3496)
+++ trunk/milena/sandbox/edwin/tree/propagate.hh (revision 3497)
@@ -60,12 +60,15 @@
void
back_propagate_subbranch(const T& t, A& a, mln_value(A) v)
{
- mln_bkd_piter(T) p(t.domain());
- for_all(p)
- if (t.is_a_node(p) && a(t.parent(p)) == v)
+ mln_fwd_piter(T::nodes_t) n(t.nodes());
+ for_all(n)
{
- mln_assertion(t.is_a_node(t.parent(p)));
- a(p) = a(t.parent(p));
+ mln_assertion(t.is_a_node(n));
+ if (a(t.parent(n)) == v)
+ {
+ mln_assertion(t.is_a_node(t.parent(n)));
+ a(n) = a(t.parent(n));
+ }
}
}
} // end of namespace mln::morpho::tree
Index: trunk/milena/sandbox/edwin/tree/tree.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/tree.cc (revision 3496)
+++ trunk/milena/sandbox/edwin/tree/tree.cc (revision 3497)
@@ -2,6 +2,7 @@
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/core/routine/duplicate.hh>
+#include <mln/core/site_set/p_set.hh>
#include <mln/pw/all.hh>
#include <mln/value/int_u8.hh>
@@ -76,6 +77,9 @@
{
mln_VAR(a, morpho::tree::compute_attribute_image(a_, tree_));
+ display_tree_attributes(tree_, a);
+ find_treshold(a, tree_);
+
img_ = duplicate((pw::cst(lambda1) < pw::value(a) &&
pw::value(a) < pw::cst(lambda2))
| a.domain());
@@ -83,39 +87,125 @@
debug::println("attribut", a);
}
-// template <typename T>
-// inline
-// float
-// find_treshold(const T& t)
-// {
-// mln_bkd_piter(T) = p(t.domain());
+ template <typename I, typename T>
+ inline
+ float
+ find_treshold(const Image<I>& img_, const T& tree)
+ {
+ typedef p_set< mln_psite(I) > PS;
+ typedef p_array<mln_psite(I)> N;
+
+ I img = exact(img_);
+ PS pset, ps_rm; // component container.
+ mln_value(I) val, old;
+ std::vector< mln_value(I)> f_domain;
+ std::vector< unsigned> f;
+
+ //debug::println(img | tree.nodes());
+
+
+ N nodes = level::sort_psites_increasing(img);
+ mln_fwd_piter(N) n(nodes);
+ mln_fwd_piter(PS) p(pset), p_rm(ps_rm);
+ old = 0;
+
+ // FIXME: hack because we want iterate on nodes and we would
+ // have wanted to write:
+ // N nodes = level::sort_psites_increasing(img | tree.nodes)
+ //
+ // but it doesn't work, so we iterate on domain regarding if n is
+ // a node.
+
+ n.start();
+ while (n.is_valid() && !tree.is_a_node(n))
+ n.next();
+
+ while (n.is_valid() && tree.is_a_node(n))
+ {
+ val = img(n);
+ do {
+ // Remove p's children from set.
+ // FIXME: improve deletion pass.
+ ps_rm.clear();
+ for_all(p)
+ if (tree.parent(p) == n)
+ ps_rm.insert(p);
+
+ for_all(p_rm)
+ pset.remove(p_rm);
+
+ // Add the new representant to component set.
+ pset.insert(n);
+ do {
+ n.next();
+ } while (n.is_valid() && !tree.is_a_node(n));
+ } while (img(n) == val && n.is_valid());
+
+ if (pset.nsites() != old)
+ {
+ old = pset.nsites();
+ f_domain.push_back(val);
+ f.push_back(pset.nsites());
+ }
+
+
+ // Debug.
+ {
+ std::cout << " - " << val << ":" << pset.nsites() << " {";
+ for_all(p)
+ std::cout << p << ",";
+ std::cout << "}" << std::endl;
+ }
+ }
+
+ for (unsigned i = 0; i < f_domain.size() - 1; i++)
+ {
+ std::cout << "[" << f_domain[i] << ","
+ << f_domain[i + 1] << "[ -> "
+ << f[i] << std::endl;
+ }
+ std::cout << ">=" << f_domain[f_domain.size() - 1] << " -> "
+ << f[f_domain.size() - 1] << std::endl;
+
+ return 0;
+ }
-// for_all(p)
-// if (t.is_a_node(p))
-// {
-// if
-// }
-// }
template <typename I, typename A>
- void filtercheck(const Image<I>& img, const Meta_Accumulator<A>& a)
+ void filtercheck(treefilter<I>& f, const Meta_Accumulator<A>& a)
{
using value::label_8;
label_8 n;
util::array<unsigned int> counts;
+ util::array< mln_psite(I) > fnodes;
- debug::println("binaire:", img);
- mln_VAR(lbl, labeling::blobs(img, c4(), n));
- debug::println("blob:", lbl);
+ mln_VAR(lbl, labeling::blobs(f.img(), c4(), n));
counts = labeling::compute(a, lbl, n);
- for (unsigned i = 0; i < counts.nelements(); i++)
+
+ mln_VAR(acc, morpho::tree::compute_attribute_image(morpho::attribute::card<I>(), f.tree()));
+ fnodes = morpho::tree::get_first_nodes(f.img(), f.tree());
+
+ mln_assertion(counts.nelements() == fnodes.nelements() + 1);
+
+ std::vector<unsigned> counts2;
+ counts2.resize(fnodes.nelements());
+ std::transform(fnodes.hook_std_vector_().begin(), fnodes.hook_std_vector_().end(),
+ counts2.begin(), acc);
+
+ std::sort(counts.hook_std_vector_().begin(), counts.hook_std_vector_().end());
+ std::sort(counts2.begin(), counts2.end());
+
+ for (unsigned i = 0; i < counts2.size(); i++)
{
- std::cout << "counts[" << i << "]: " << counts[i]
+ mln_assertion(acc.domain().has(fnodes(p)));
+ std::cout << "counts[" << i << "]: (ref " << counts[i] << ") " << counts2[i]
<< std::endl;
}
+
+
}
} // end of namespace mln
@@ -157,20 +247,16 @@
else
usage(argv);
+
+
back_propagate_subbranch(f->tree(), f->img() ,true);
back_propagate_level(f->tree(), f->img());
- filtercheck(f->img(), accu::meta::count());
+ filtercheck(*f, accu::meta::count());
- util::array< mln_psite_(I) > counts;
- counts = morpho::tree::get_first_nodes(f->img(), f->tree());
- for (unsigned i = 0; i < counts.nelements(); i++)
- std::cout << "counts[" << i << "]: " << counts[i] << std::endl;
- mln_VAR(a, morpho::tree::compute_attribute_image(morpho::attribute::card<I>(), f->tree()));
- display_tree_attributes(f->tree(), a);
io::pbm::save(f->img(), "out.pbm");
delete f;
Index: trunk/milena/sandbox/edwin/tree/routines.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/routines.hh (revision 3496)
+++ trunk/milena/sandbox/edwin/tree/routines.hh (revision 3497)
@@ -49,60 +49,20 @@
data::fill(deja_vu, false);
bool can_break = false;
- mln_bkd_piter(T) p(tree.domain());
+ mln_bkd_piter(T) p(tree.nodes());
for_all(p)
{
- if (tree.is_a_node(p) && bin(p) && bin(t.parent(p))
+ mln_assertion(tree.is_a_node(p));
+ if (bin(p) && !bin(tree.parent(p)))
{
fnodes.append(p);
}
}
-
- // else if (can_break)
-// {
-// std::cout << p << std::endl;
-// break;
-// }
-
return fnodes;
}
}
}
-
-// namespace debug {
-
-// template <typename T, typename I>
-// void
-// println(const T& t, const Image<I> f_)
-// {
-// //theo's code
-// typedef mln_site(I) P;
-// I f = exact(f_);
-
-// mln_ch_value(I, bool) deja_vu;
-// initialize(deja_vu, f);
-// data::fill(deja_vu, false);
-
-// typedef typename T::nodes_t nodes_t;
-// mln_fwd_piter(T) p(t.nodes());
-// for_all(p)
-// {
-// if (deja_vu(p))
-// continue;
-// P e = p;
-// do
-// {
-// std::cout << f(e) << ':' << e << " -> ";
-// deja_vu(e) = true;
-// e = t.parent(e);
-// }
-// while (! deja_vu(e));
-// std::cout << f(e) << ':' << e << std::endl;
-// }
-// std::cout << std::endl;
-// }
-// }
}
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-06 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add watershed implementation for IRM images.
* fabien/bin/Makefile: Update.
* fabien/bin/dicom2dump.cc: Update.
* fabien/bin/dicom_mask.cc: Update.
* fabien/igr/Makefile: Update.
* fabien/igr/dumps: Remove.
* fabien/igr/watershed.cc: Watershed implementation.
---
bin/Makefile | 3
bin/dicom2dump.cc | 19 ---
bin/dicom_mask.cc | 26 ++++
igr/Makefile | 9 -
igr/watershed.cc | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 353 insertions(+), 24 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/watershed.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/watershed.cc (revision 3496)
@@ -0,0 +1,320 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/convert/to_fun.hh>
+
+#include <mln/make/graph.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/core/var.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/core/routine/extend.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/essential/2d.hh>
+#include <mln/core/alias/vec3d.hh>
+#include <mln/debug/draw_graph.hh>
+#include <mln/util/graph.hh>
+#include <mln/accu/center.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/accu/compute.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/draw/box.hh>
+#include <mln/level/stretch.hh>
+#include <mln/fun/v2v/id.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/extension/adjust_fill.hh>
+#include <mln/extract/all.hh>
+#include <mln/make/region_adjacency_graph.hh>
+
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
+namespace mln
+{
+
+ template <typename V>
+ value::int_u8 dist(const V& c1, const V& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+
+ if (d_ > d)
+ d = d_;
+
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
+ template <typename I>
+ inline
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
+ {
+ // edge sites.
+ typedef fun::i2v::array<mln_site(I)> edge_site_t;
+ edge_site_t edge_site(g.e_nmax(), literal::origin);
+ typedef p_edges<util::graph, edge_site_t > pe_t;
+ pe_t pe(g, edge_site);
+
+ // edge values
+ typedef fun::i2v::array<value::int_u8> edge_values_t;
+ edge_values_t edge_values(g.e_nmax());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, pe_t> ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e) // in ima_e
+ ima_e(e) = math::diff_abs(ima_v.function()(e.element().v1()), ima_v.function()(e.element().v2()));
+
+ return ima_e;
+ }
+
+
+ template <typename I, typename J>
+ inline
+ util::array<mln_value(I)>
+ mean_color_values(const I& input, const J& w, mln_value(J) nbasins)
+ {
+ // Cf. sandbox/theo/color/segment_rgb_pixels.cc
+
+ util::array<vec3d_f> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = literal::zero;
+
+ util::array<mln_value(I)> m;
+ convert::from_to(m_3f, m);
+ m[0] = literal::yellow;
+
+ io::ppm::save(level::transform(w,
+ convert::to< fun::i2v::array<mln_value(I)> >(m)),
+ "wst_rag_wshd_color.ppm");
+
+ return m;
+ }
+
+
+ template <typename I, typename J>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_vertex_graph_image(const util::graph& g, const I&input, const J& w, const mln_value(J)& nbasins)
+ {
+ typedef util::array<mln_site(I)> vertex_sites_t;
+ vertex_sites_t site_values;
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
+
+ typedef fun::i2v::array<mln_site(J)> f_sites_t;
+ f_sites_t sites;
+ convert::from_to(site_values, sites);
+
+ // p_vertices
+ typedef p_vertices<util::graph, f_sites_t> S;
+ S pv(g, sites);
+
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ // convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+
+ mln_VAR(ima_v, (vertex_values | pv));
+
+ return ima_v;
+ }
+
+
+ template <typename I, typename V>
+ struct edge_to_color : Function_p2v< edge_to_color<I,V> >
+ {
+ typedef V result;
+
+ edge_to_color(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ V
+ operator()(const unsigned& e) const
+ {
+ return convert::to<V>(ima_.function()(e));
+ }
+
+ const I& ima_;
+ };
+
+ template <typename V>
+ inline
+ unsigned
+ find_root(util::array<V>& parent, const unsigned& x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ image2d<mln_value(I)>
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size, const value::rgb8& bg)
+ {
+ image2d<mln_value(I)> ima;
+ initialize(ima, input);
+
+ data::fill(ima, bg);
+ debug::draw_graph(ima, ima_v.domain(),
+ pw::cst(mln_value(I)(literal::green)),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box2d b(p + tl, p + br);
+ b.crop_wrt(ima.domain());
+ data::fill((ima | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ return ima;
+ }
+
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::rgb8;
+ using value::label_16;
+
+ if (argc < 4)
+ {
+ std::cout << "Usage: " << argv[0] << " <ima.dcm> <closure_lambda> <box_size>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned box_size = atoi(argv[3]);
+
+ image2d<int_u12> dcm;
+ io::dicom::load(dcm, argv[1]);
+
+ image2d<int_u12> grad = morpho::gradient(dcm, win_c4p());
+ image2d<int_u12> clo = morpho::closing::area(grad, c4(), atoi(argv[2]));
+
+ label_16 nbasins;
+ image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+
+ mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u), wshed), c8()));
+
+ data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+
+ /// Build graph
+ util::graph g = make::graph(wshed, c4(), nbasins);
+ // Build graph images and compute distance values with a RGB image.
+ mln_VAR(ima_v, make_vertex_graph_image(g, dcm, wshed, nbasins));
+ mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
+
+ /// Try to merge vertices.
+ mln_piter_(ima_e_t) e(ima_e.domain());
+ util::array<label_16> parent(g.v_nmax());
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ parent[i] = i;
+
+ for_all(e)
+ {
+ unsigned v1 = e.element().v1();
+ unsigned v2 = e.element().v2();
+ if (ima_e(e) <= (unsigned)(atoi(argv[5]))
+ && find_root(parent, v1) != find_root(parent, v2))
+ parent[find_root(parent, v1)] = find_root(parent, v2);
+ }
+
+ fun::i2v::array<label_16> f(parent.nelements());
+ std::vector<unsigned> new_label(parent.nelements(), 0);
+ unsigned nbasins2 = 0;
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ {
+ unsigned p = find_root(parent, i);
+ mln_assertion(parent[p] == find_root(parent, i));
+ if (new_label[p] == 0)
+ new_label[p] = nbasins2++;
+ f(i) = new_label[p];
+ }
+ mln_invariant(f(0) == 0u);
+ --nbasins2; // nbasins2 does not count the basin with label 0.
+ image2d<label_16> wsd2 = level::transform(wshed, f);
+
+
+ /// Reconstruct a graph from the simplified image.
+ util::graph g2 = make::graph(wsd2, c4(), nbasins2);
+
+ // Compute distance values with a RGB image.
+ mln_VAR(ima_v2, make_vertex_graph_image(g2, dcm, wsd2, nbasins2));
+ mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
+
+ mln_VAR(wsd2_, morpho::elementary::dilation(extend(wsd2 | (pw::value(wsd2) == 0u), wsd2), c8()));
+
+ data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+
+ //io::ppm::save(labeling::mean_values(dcm, wsd2, nbasins2), "wst_rag_mean_colors.ppm");
+ //io::ppm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, literal::white), "wst_rag_graph_image2_white.ppm");
+ //io::ppm::save(make_debug_graph_image(dcm, ima_v2, ima_e2, box_size, literal::black), "wst_rag_graph_image2_black.ppm");
+}
Index: trunk/milena/sandbox/fabien/igr/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile (revision 3495)
+++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3496)
@@ -8,7 +8,7 @@
-framework CoreFoundation
CXXFLAGS = -DNDEBUG -O1
-all: 2d 3d
+all: 2d 3d wsd
2d: seg_vol_irm.hh seg2d.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg2d.cc -o seg2d
@@ -16,11 +16,8 @@
3d: seg_vol_irm.hh seg3d.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg3d.cc -o seg3d
-grad: grad_clo_and_wshd.cc
- g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o grad_clo
-
-wst: wst_rag.cc
- g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wst_rag
+wsd: watershed.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd
clean:
rm -rf *.dump *.p?m *.plot *.log *.csv
Index: trunk/milena/sandbox/fabien/bin/dicom2dump.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dicom2dump.cc (revision 3495)
+++ trunk/milena/sandbox/fabien/bin/dicom2dump.cc (revision 3496)
@@ -2,7 +2,6 @@
#include <mln/core/image/image2d.hh>
#include <mln/core/image/image3d.hh>
-#include <mln/value/int_u8.hh>
#include <mln/value/int_u12.hh>
#include <mln/io/dicom/load.hh>
#include <mln/io/dump/save.hh>
@@ -17,31 +16,15 @@
}
-/*int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u12;
-
- if (argc != 3)
- return usage(argv);
-
- image3d<int_u12> ima;
- io::dicom::load(ima, argv[1]);
- io::dump::save(ima, argv[2]);
-
- return 0;
-}*/
-
int main(int argc, char* argv[])
{
using namespace mln;
- using value::int_u8;
using value::int_u12;
if (argc != 3)
return usage(argv);
- image2d<int_u8> ima;
+ image3d<int_u12> ima;
io::dicom::load(ima, argv[1]);
io::dump::save(ima, argv[2]);
Index: trunk/milena/sandbox/fabien/bin/dicom_mask.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dicom_mask.cc (revision 3495)
+++ trunk/milena/sandbox/fabien/bin/dicom_mask.cc (revision 3496)
@@ -1,6 +1,9 @@
#include <mln/core/concept/image.hh>
#include <mln/core/image/image2d.hh>
+#include <mln/geom/ncols.hh>
+#include <mln/geom/nrows.hh>
+
#include <mln/value/int_u8.hh>
#include <mln/io/dicom/load.hh>
#include <mln/io/pbm/save.hh>
@@ -33,6 +36,29 @@
image2d<int_u8> input;
io::dicom::load(input, argv[1]);
+ util::array<unsigned> xproj(geom::nrows(input), 0);
+ util::array<unsigned> yproj(geom::ncols(input), 0);
+
+ mln_piter_(image2d<int_u8>) p(input.domain());
+ for_all(p)
+ {
+ xproj[p.row()] += input(p);
+ yproj[p.col()] += input(p);
+ }
+
+ // Plot files
+ std::ofstream fout_x("x.plot");
+ for (unsigned int i = 0; i < xproj.nelements(); ++i)
+ {
+ fout_x << i << " " << xproj[i] << std::endl;
+ }
+
+ std::ofstream fout_y("y.plot");
+ for (unsigned int i = 0; i < yproj.nelements(); ++i)
+ {
+ fout_y << i << " " << yproj[i] << std::endl;
+ }
+
image2d<bool> ima = level::transform(input, fun::v2b::threshold<int_u8>(1));
io::pbm::save(ima, argv[2]);
}
Index: trunk/milena/sandbox/fabien/bin/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/bin/Makefile (revision 3495)
+++ trunk/milena/sandbox/fabien/bin/Makefile (revision 3496)
@@ -21,3 +21,6 @@
dump: dicom2dump.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o dicom2dump
+
+pgm: dicom2pgm.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o dicom2pgm
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Have all labeling routines be consistent.
* mln/core/concept/window.hh,
* mln/core/concept/neighborhood.hh
(positive_offsets_wrt): New.
* mln/morpho/tree/compute_parent.hh (todo): New.
(doc): Augment.
* mln/morpho/tree/data.hh (todo): New.
* mln/canvas/labeling.hh: Swap fwd and bkd between both passes.
(todo): New.
Now it is consistent with labeling::blobs.
* tests/level/sort_psites.cc: Test reversibility.
* tests/morpho/tree/data.cc: Precise fwd when needed.
* tests/labeling/foreground.cc: Upgrade doc style.
Augment test.
mln/canvas/labeling.hh | 26 +++++-------
mln/core/concept/neighborhood.hh | 18 ++++++++
mln/core/concept/window.hh | 30 ++++++++++++++
mln/morpho/tree/compute_parent.hh | 78 ++++++++++++++++++++++++++++++++++----
mln/morpho/tree/data.hh | 7 ++-
tests/labeling/foreground.cc | 38 +++++++++++++++---
tests/level/sort_psites.cc | 19 ++++++---
tests/morpho/tree/data.cc | 15 +++++--
8 files changed, 193 insertions(+), 38 deletions(-)
Index: mln/core/concept/window.hh
--- mln/core/concept/window.hh (revision 3494)
+++ mln/core/concept/window.hh (working copy)
@@ -121,6 +121,10 @@
template <typename I, typename W>
util::array<int>
+ positive_offsets_wrt(const Image<I>& ima, const Window<W>& win);
+
+ template <typename I, typename W>
+ util::array<int>
negative_offsets_wrt(const Image<I>& ima, const Window<W>& win);
@@ -346,6 +350,32 @@
template <typename I, typename W>
inline
util::array<int>
+ positive_offsets_wrt(const Image<I>& ima_, const Window<W>& win_)
+ {
+ mln_is_simple_window(W)::check();
+
+ const I& ima = exact(ima_);
+ const W& win = exact(win_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(win.is_valid());
+
+ util::array<int> arr;
+ unsigned n = win.size();
+
+ for (unsigned i = 0; i < n; ++i)
+ {
+ int offset = ima.delta_index(win.dp(i));
+ if (offset > 0)
+ arr.append(offset);
+ }
+
+ return arr;
+ }
+
+
+ template <typename I, typename W>
+ inline
+ util::array<int>
negative_offsets_wrt(const Image<I>& ima_, const Window<W>& win_)
{
mln_is_simple_window(W)::check();
Index: mln/core/concept/neighborhood.hh
--- mln/core/concept/neighborhood.hh (revision 3494)
+++ mln/core/concept/neighborhood.hh (working copy)
@@ -104,6 +104,10 @@
template <typename I, typename N>
util::array<int>
+ positive_offsets_wrt(const Image<I>& ima, const Neighborhood<N>& nbh);
+
+ template <typename I, typename N>
+ util::array<int>
negative_offsets_wrt(const Image<I>& ima, const Neighborhood<N>& nbh);
@@ -166,6 +170,20 @@
template <typename I, typename N>
util::array<int>
+ positive_offsets_wrt(const Image<I>& ima_, const Neighborhood<N>& nbh_)
+ {
+ mln_is_simple_neighborhood(N)::check();
+
+ const I& ima = exact(ima_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ return positive_offsets_wrt(ima, nbh.win());
+ }
+
+ template <typename I, typename N>
+ util::array<int>
negative_offsets_wrt(const Image<I>& ima_, const Neighborhood<N>& nbh_)
{
mln_is_simple_neighborhood(N)::check();
Index: mln/morpho/tree/compute_parent.hh
--- mln/morpho/tree/compute_parent.hh (revision 3494)
+++ mln/morpho/tree/compute_parent.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 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
@@ -33,6 +34,11 @@
/// Compute a canonized tree from an image.
///
/// \todo Specialize for low quant (and try fastest).
+///
+/// \todo Augment and improve documentation.
+///
+/// \todo Change level::sort so that the explanations below are valid
+/// whatever the choice 'increasing or decreasing'.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
@@ -55,16 +61,72 @@
/// "natural" childhood relationship. The parenthood is thus
/// inverted w.r.t. to \p s.
///
- /// It is very convenient since all processing upon the parent
- /// tree are performed following \p s (in the default "forward"
- /// way).
+ /// It is very convenient since most processing routines upon
+ /// the parent tree are performed following \p s (in the default
+ /// "forward" way). Indeed that is the way to propagate
+ /// information from parents to children.
///
- /// FIXME: Put it more clearly...
///
/// The parent result image verifies: \n
/// - p is root iff parent(p) == p \n
/// - p is a node iff either p is root or f(parent(p)) != f(p).
-
+ ///
+ ///
+ ///
+ /// The choice "s means childhood" is consistent with labeling
+ /// in binary images. In that particular case, while browsing
+ /// the image in forward scan (video), we expect to find first a
+ /// tree root (a first point, representative of a component) and
+ /// then the other component points. Please note that it leads
+ /// to increasing values of labels in the "natural" video scan.
+ ///
+ /// Since mathematical morphology on functions is related to
+ /// morphology on sets, we clearly want to keep the equivalence
+ /// between "component labeling" and "component filtering" using
+ /// trees.
+ ///
+ ///
+ /// FIXME: Put it more clearly... Insert pictures!
+ ///
+ /// A binary image:
+ ///
+ /// - | | - - \n
+ /// - | | - | \n
+ /// - - - - - \n
+ /// - - | | - \n
+ ///
+ /// where '|' means true and '-' means false.
+ ///
+ /// Its labeling:
+ ///
+ /// 0 1 1 0 0 \n
+ /// 0 1 1 0 2 \n
+ /// 0 0 0 0 0 \n
+ /// 0 0 3 3 0 \n
+ ///
+ /// The corresponding forest:
+ ///
+ /// x o . x x \n
+ /// x . . x o \n
+ /// x x x x x \n
+ /// x x o . x \n
+ ///
+ /// where 'x' means "no data", 'o' is a tree root
+ /// (representative point for a component), and '.' is a tree
+ /// regular (non-root) point (in a component by not its
+ /// representative point).
+ ///
+ ///
+ /// The forest, with the parent relationship looks like:
+ ///
+ /// o < . \n
+ /// ^ r \n
+ /// . . o \n
+ /// \n
+ /// \n
+ /// o < . \n
+ ///
+ ///
template <typename I, typename N, typename S>
mln_ch_value(I, mln_psite(I))
compute_parent(const Image<I>& f, const Neighborhood<N>& nbh,
@@ -159,7 +221,7 @@
data::fill(deja_vu, false);
// Body.
- mln_bkd_piter(S) p(s);
+ mln_bkd_piter(S) p(s); // Backward.
mln_niter(N) n(nbh, p);
for_all(p)
{
@@ -183,7 +245,7 @@
// Canonization.
{
- mln_fwd_piter(S) p(s);
+ mln_fwd_piter(S) p(s); // Forward.
for_all(p)
{
P q = parent(p);
Index: mln/morpho/tree/data.hh
--- mln/morpho/tree/data.hh (revision 3494)
+++ mln/morpho/tree/data.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 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
@@ -31,6 +32,10 @@
/// \file mln/morpho/tree/data.hh
///
/// FIXME: First Attempt.
+///
+/// \todo Fix the issue pointed to by Edwin without modifying the way
+/// sites are browsed (see the documentation of compute_parent to
+/// learn why we want the 1st pass to be in forward scan of s).
# include <mln/morpho/tree/compute_parent.hh>
# include <mln/core/image/sub_image.hh>
Index: mln/canvas/labeling.hh
--- mln/canvas/labeling.hh (revision 3494)
+++ mln/canvas/labeling.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -33,8 +33,8 @@
///
/// Connected component labeling of the object part in a binary image.
///
-/// \todo Make the fastest version work.
-/// FIXME: is 'status' useful?
+/// \todo Can we get rid of 'deja_vu' (while playing with the border)
+/// in the fastest video version?
# include <mln/core/concept/image.hh>
# include <mln/data/fill.hh>
@@ -139,7 +139,7 @@
// Output.
mln_ch_value(I, L) output;
- bool status;
+ bool status; // FIXME: Is-it useful?
// Initialization.
{
@@ -157,7 +157,7 @@
// First Pass.
{
- mln_fwd_piter(S) p(s);
+ mln_bkd_piter(S) p(s); // Backward.
mln_niter(N) n(nbh, p);
for_all(p) if (f.handles(p))
{
@@ -187,7 +187,7 @@
// Second Pass.
{
- mln_bkd_piter(S) p(s);
+ mln_fwd_piter(S) p(s); // Forward.
for_all(p) if (f.handles(p))
{
if (parent(p) == p) // if p is root
@@ -274,10 +274,10 @@
// First Pass.
{
- util::array<int> dp = negative_offsets_wrt(input, nbh);
+ util::array<int> dp = positive_offsets_wrt(input, nbh);
const unsigned n_nbhs = dp.nelements();
- mln_pixter(const I) px(input);
+ mln_bkd_pixter(const I) px(input); // Backward.
for_all(px)
{
unsigned p = px.offset();
@@ -311,7 +311,7 @@
// Second Pass.
{
- mln_bkd_pixter(const I) px(input);
+ mln_fwd_pixter(const I) px(input); // Forward.
for_all(px)
{
unsigned p = px.offset();
@@ -394,8 +394,7 @@
// First Pass.
{
-
- for (unsigned i = 0; i < n_points; ++i)
+ for (int i = n_points - 1; i >=0; --i) // Backward.
{
unsigned p = s[i];
if (! f.handles_(p))
@@ -425,13 +424,12 @@
f.do_no_union_(n, p);
}
deja_vu.element(p) = true;
-
}
}
// Second Pass.
{
- for (int i = n_points - 1; i >=0; --i)
+ for (unsigned i = 0; i < n_points; ++i) // Forward.
{
unsigned p = s[i];
if (! f.handles_(p))
Index: tests/level/sort_psites.cc
--- tests/level/sort_psites.cc (revision 3494)
+++ tests/level/sort_psites.cc (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -31,7 +31,7 @@
/// Tests on mln::level::sort_psites.
#include <mln/core/image/image2d.hh>
-#include <mln/debug/iota.hh>
+#include <mln/make/image2d.hh>
#include <mln/level/sort_psites.hh>
#include <mln/core/site_set/p_array.hh>
@@ -40,11 +40,20 @@
{
using namespace mln;
- image2d<int> ima(3, 3);
- debug::iota (ima);
+ int vals[] = { 0, 3, 4,
+ 2, 2, 2,
+ 0, 1, 4 };
+ image2d<int> ima = make::image2d(vals);
p_array<point2d> array_inc = level::sort_psites_increasing(ima);
p_array<point2d> array_dec = level::sort_psites_decreasing(ima);
+ {
+ p_array<point2d>::fwd_piter p1(array_inc);
+ p_array<point2d>::bkd_piter p2(array_dec);
+ for_all_2(p1, p2)
+ mln_assertion(ima(p1) == ima(p2));
+ }
+
p_array<point2d> array_inc_ref;
p_array<point2d> array_dec_ref;
Index: tests/morpho/tree/data.cc
--- tests/morpho/tree/data.cc (revision 3494)
+++ tests/morpho/tree/data.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 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
@@ -62,9 +63,17 @@
{
std::cout << "nodes = ";
- tree_t::nodes_t::piter p(t.nodes());
+ tree_t::nodes_t::fwd_piter p(t.nodes());
for_all(p)
std::cout << p << ' ';
+ std::cout << std::endl;
+ }
+ {
+ std::cout << "nodes = ";
+ tree_t::fwd_piter p(t.domain());
+ for_all(p)
+ if (t.is_a_node(p))
+ std::cout << p << ' ';
std::cout << std::endl
<< std::endl;
}
@@ -73,7 +82,7 @@
{
image2d<unsigned> area(ima.domain());
data::fill(area, 1);
- tree_t::piter p(t.domain());
+ tree_t::fwd_piter p(t.domain());
for_all(p)
if (! t.is_root(p))
area(t.parent(p)) += area(p);
Index: tests/labeling/foreground.cc
--- tests/labeling/foreground.cc (revision 3494)
+++ tests/labeling/foreground.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -25,14 +26,15 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling/foreground.cc
- *
- * \brief Test on mln::labeling::foreground.
- */
+/// \file tests/labeling/foreground.cc
+///
+/// Test on mln::labeling::foreground.
#include <mln/core/image/image2d.hh>
+#include <mln/core/var.hh>
#include <mln/io/pbm/load.hh>
#include <mln/core/alias/neighb2d.hh>
+#include <mln/level/compare.hh>
#include <mln/labeling/foreground.hh>
#include "tests/data.hh"
@@ -42,8 +44,30 @@
{
using namespace mln;
- image2d<bool> pic = io::pbm::load(MLN_IMG_DIR "/picasso.pbm");
+ typedef image2d<bool> I;
+ mln_VAR(nbh, c4());
+
+ I pic = io::pbm::load(MLN_IMG_DIR "/picasso.pbm");
+ image2d<unsigned> out, ref;
+
unsigned n;
- labeling::foreground(pic, c4(), n);
+ out = labeling::foreground(pic, nbh, n); // Calls the fastest 'video'
+ // version.
mln_assertion(n == 33);
+
+ {
+ // Note that labeling::foreground actually is labeling::level
+ // which calls canvas::labeling_video and its generic dispatch
+ // leads to canvas::impl::generic::labeling.
+
+ labeling::impl::level_functor<I> f(pic, true);
+
+ unsigned n_;
+ ref = canvas::impl::generic::labeling(pic, nbh, n_,
+ pic.domain(),
+ f);
+ mln_invariant(n_ == n);
+ mln_invariant(ref == out);
+ }
+
}
1
0
* scribo/+out.txt: remove.
* scribo/Makefile: add new rules.
* scribo/demat.hh: cleanup and comment.
---
milena/sandbox/ChangeLog | 10 +
milena/sandbox/scribo/+out.txt | 1882 ----------------------------------------
milena/sandbox/scribo/Makefile | 7 +-
milena/sandbox/scribo/demat.hh | 743 +++++++++++++---
4 files changed, 635 insertions(+), 2007 deletions(-)
delete mode 100644 milena/sandbox/scribo/+out.txt
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index 3fe2325..8915137 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,3 +1,13 @@
+2009-03-06 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Revamp and cleanup code for Scribo.
+
+ * scribo/+out.txt: remove.
+
+ * scribo/Makefile: add new rules.
+
+ * scribo/demat.hh: cleanup and comment.
+
2009-03-05 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add Matlab code from Anne.
diff --git a/milena/sandbox/scribo/+out.txt b/milena/sandbox/scribo/+out.txt
deleted file mode 100644
index efe7f36..0000000
--- a/milena/sandbox/scribo/+out.txt
+++ /dev/null
@@ -1,1882 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AES
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- FACTURE
-
- 20084 73.9 46
-
- M
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N":
-
- •l=1=]Il=l|1;ï
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 29/os/00
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- f'
-
-
-
-
-
-
-
- SNECMA (CF 0844 7)
-
-
- 924
-
- 134637
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- V/Ref
-
-
-
- mons)
-
-
- DEPT FOURNISSEURS
-
-
- 12/07/00
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- FF
-
-
-
-
- MR BROHARD / BP 82
-
-
- 462578
-
- SNECEVRY
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N/raf
-
-
-
-
- ANNIE GOUGEON
-
- 91003 EVRY CEDEX
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Commercia
-
- PI
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ¤€§HEêIBi'91©TEURs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- M
-
- . HAMER~POLE W1—W2/0160597435
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SITE DE VILLÀROCHE
-
- .J
-
-
- L
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 7 7550 MOISSY CRAMAYEL
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Quanüf Prix Uni
-
- Il
-
- Xahî » A `
-
-
- T'O¤d¤
-
-
- nïï
-
-
-
- litignmion
-
- îlïyuï iirr H¤m1 `fbmz
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- W7}
-
-
-
- V
-
- î
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- B. L N° 56:055
-
-
- du 23/08/GD
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- uaasiaïauxvx par rœuénque nomm¤<,bL1vr¤w0.»:r, 1 n1,ss.as.·>s.zs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 3(
-
- SNE<.1~1A1SFS1.7m7+ ïI`HF P'5'I7¤17¥ SNECMA ZPHO MMS16
-
-
- 44 5170/OU
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- J ,,«,u
-
-
-
- BAC SQUF PF¢21/P»\—20 SNECMA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 4 4s¤,¤o
-1 —’z#¤¤, un
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ~«· Lxvanxsuu 1.2 za/os/oa···«
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 4; 4444 L
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- TOTAL HX
-
-
-
- xpmûzâ
-
- TVA :
-
-
- H.(• g ai
-
-
-
-
-
- 9« W
-
-
-
-
-
- Il
-
- E I
-
- ¥ë]rg§î"À PÃVÈÉ
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 6*/ 574,00
-
-
-
-
-
-
-
-
-
-
-
-
-
- 55 500,0Dg
-
- ss suu,¤:7[
-
- 11 014,ua [
-
- É? 514, dïg
-
- Il
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Par Virc
-
- . banc
-
-
- A 45J Soit
-
-
- le 13/10/00 Francs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bacompze de L5! pour paiement sans 8 jours, date de facture. Si le client prend l'
-
-
- es·c¤'¤Pta finanoier
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- '11 doit déduite est fonction du montant payé
-
-
- . TVA acquittés sur les débits
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Pour être libératoire, le règlement de cette créance dci: être effectué directement Ã
-
-
- â l'crdxe de la
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Saciêtê Française du Inernxâng [SFF}
-
-
-
- . Elle le reçoit: par suhrngation dans le cadre du cnntrat dhaffactuxaga
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- La SFF devra être avisés de toutes demandes de renseignements et réclamations
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ·· BPI, Taux d'l|.m1ir¤: · 926047 ASHXIAIG UIDBX
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-23
-
-
-
-
-
-
-
- V 7 \
- @5
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 3Ã
-
-
-
- à 9, avenue de Norvège - BR 390 ~ 91959 Courtabœuü cedsx - Tél. :01 B9 BS 60 00 - Fax : 01 69 2B 19 18
-
-
-
-
-
-
-
-
-
-
-
- Ã Ã ?
-
-
-
-
-
-
-
-
- SA. au capital de 65.670500 F - RCS, Evry · Sire! 332 108 901 00023 - N.A.E : 721 Z » '1È\/.A, : FH 42 332 108 901
-
-
- Dis
-
- Hbuliun
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/milena/sandbox/scribo/Makefile b/milena/sandbox/scribo/Makefile
index 730d8c2..5d09e02 100644
--- a/milena/sandbox/scribo/Makefile
+++ b/milena/sandbox/scribo/Makefile
@@ -1,10 +1,13 @@
all: table photo
+tabledbg: demat.hh
+ g++ -Wextra -Wall -I../.. -I$(HOME)/local/include -O1 -g table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o table
+
table: demat.hh
- g++ -I../.. -I$(HOME)/local/include -O1 -DNDEBUG table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o table
+ g++ -Wextra -Wall -I../.. -I$(HOME)/local/include -O1 -DNDEBUG table.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o table
photo: demat.hh
- g++ -I../.. -I$(HOME)/local/include -O1 -DNDEBUG photo.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o photo
+ g++ -Wextra -Wall -I../.. -I$(HOME)/local/include -O1 -DNDEBUG photo.cc $(HOME)/local/lib/libtesseract_full.a -lpthread -o photo
clean:
rm *.ppm *.pgm *.pbm
diff --git a/milena/sandbox/scribo/demat.hh b/milena/sandbox/scribo/demat.hh
index 8872afc..06e22da 100644
--- a/milena/sandbox/scribo/demat.hh
+++ b/milena/sandbox/scribo/demat.hh
@@ -55,6 +55,9 @@
# include <mln/io/txt/save.hh>
# include <mln/canvas/browsing/depth_first_search.hh>
+# include <mln/transform/distance_and_influence_zone_geodesic.hh>
+# include <mln/fun/l2l/wrap.hh>
+# include <mln/fun/meta/all.hh>
# include <tesseract/baseapi.h>
@@ -66,8 +69,9 @@ namespace scribo
using namespace mln;
using value::label_16;
+ using value::label_8;
using value::rgb8;
-
+ using value::int_u8;
struct settings_t
@@ -83,6 +87,7 @@ namespace scribo
max_dist_lines = 10;
max_txt_box_height = 100;
max_cos = 0.994;
+ repair_max_dist = 51;
}
unsigned bbox_enlarge;
@@ -91,6 +96,7 @@ namespace scribo
unsigned min_comp_size;
unsigned max_comp_size;
unsigned max_dist_lines;
+ unsigned repair_max_dist;
int max_txt_box_height;
unsigned rank_filter;
bool treat_tables;
@@ -143,7 +149,7 @@ namespace scribo
** |---X---|
**
*/
- std::pair<point2d, point2d>
+ util::couple<point2d, point2d>
central_sites(const box2d& b, unsigned dim)
{
unsigned n = b.pmax()[dim] - b.pmin()[dim];
@@ -153,7 +159,7 @@ namespace scribo
point2d p2 = b.center();
p2[dim] += n / 2;
- return std::make_pair(p1, p2);
+ return make::couple(p1, p2);
}
@@ -226,6 +232,8 @@ namespace scribo
b.ncols(), // n cols
b.nrows()); // n rows
+
+
point2d p = tboxes[i].center();
p.col() -= (tboxes[i].pmax().col() - tboxes[i].pmin().col()) / 2;
if (s != 0)
@@ -251,10 +259,11 @@ namespace scribo
/// \{
/// Align table lines bboxes according to a given dimension.
+ ///
+ /// \return A list of the resulting aligned cols. Each integer is actually
+ /// a col number.
/*
**
- ** FIXME: DOC!
- **
** 0 1 3 4 5 6
** ------------ -------
** 0 |- - - - - | | {0,1} |
@@ -281,23 +290,28 @@ namespace scribo
** and all bboxes referenced in this set are aligned on the same row or col.
**
*/
+ template <typename P>
util::array<int>
align_lines(unsigned nsites,
int min_coord,
int max_coord,
- util::array<box2d>& hboxes,
+ util::array<box<P> >& line_boxes,
unsigned dim)
{
+ trace::entering("scribo::internal::align_lines");
+
+ mln_precondition(nsites > 0);
+
std::cout << "extracting table lines..." << std::endl;
util::array< util::set<unsigned> > lines;
lines.resize(nsites);
// Map components with actual lines.
- for_all_components(i, hboxes)
+ for_all_components(i, line_boxes)
{
- int minline = hboxes[i].pmin()[dim] - 5;
+ int minline = line_boxes[i].pmin()[dim] - 5;
minline = (minline < min_coord ? min_coord : minline);
- int maxline = hboxes[i].pmax()[dim] + 5;
+ int maxline = line_boxes[i].pmax()[dim] + 5;
maxline = (maxline > max_coord ? max_coord : maxline);
for (int line = minline;
@@ -307,7 +321,7 @@ namespace scribo
// Init box2line
util::array<int> box2line;
- box2line.resize(hboxes.nelements());
+ box2line.resize(line_boxes.nelements());
for_all_elements(i, box2line)
box2line[i] = -1;
@@ -330,15 +344,15 @@ namespace scribo
accu::mean<unsigned> mean;
for_all_elements(j, lines[i])
if (box2line[lines[i][j]] == -1)
- mean.take(hboxes[lines[i][j]].center()[dim]);
+ mean.take(line_boxes[lines[i][j]].center()[dim]);
if (mean.is_valid())
{
for_all_elements(j, lines[i])
if (box2line[lines[i][j]] == -1)
{
- hboxes[lines[i][j]].pmin()[dim] = mean.to_result();
- hboxes[lines[i][j]].pmax()[dim] = mean.to_result();
+ line_boxes[lines[i][j]].pmin()[dim] = mean.to_result();
+ line_boxes[lines[i][j]].pmax()[dim] = mean.to_result();
box2line[lines[i][j]] = mean.to_result();
}
newlines.append(mean.to_result());
@@ -347,18 +361,75 @@ namespace scribo
--max_nelts;
}
+ trace::exiting("scribo::internal::align_lines");
return newlines;
}
+ /// Align line bboxes verticaly.
+ ///
+ /// \param[in] input Image from which the line bboxes are
+ /// extracted from.
+ /// \param[in, out] lines_bboxes vertical lines bounding boxes.
+ ///
+ /// \return A list of the resulting aligned cols. Each integer is actually
+ /// a col number.
+ template <typename I>
+ util::array<int>
+ align_lines_verticaly(const Image<I>& input,
+ util::array<box<mln_site(I)> >& lines_bboxes)
+ {
+ trace::entering("scribo::internal::align_lines_horizontaly");
+
+ mln_precondition(exact(input).is_valid());
+ util::array<int> res = align_lines(geom::ncols(input), geom::min_col(input),
+ geom::max_col(input), lines_bboxes, 1);
+
+ trace::exiting("scribo::internal::align_lines_horizontaly");
+ return res;
+
+ }
+
+ /// Align line bboxes horizontaly.
+ ///
+ /// \param[in] input Image from which the line bboxes are
+ /// extracted from.
+ /// \param[in, out] lines_bboxes horizontal lines bounding boxes.
+ ///
+ /// \return A list of the resulting aligned rows. Each integer is actually
+ /// a row number.
+ template <typename I>
+ util::array<int>
+ align_lines_horizontaly(const Image<I>& input,
+ util::array<box<mln_site(I)> >& lines_bboxes)
+ {
+ trace::entering("scribo::internal::align_lines_horizontaly");
+
+ mln_precondition(exact(input).is_valid());
+ util::array<int> res = align_lines(geom::nrows(input), geom::min_row(input),
+ geom::max_row(input), lines_bboxes, 0);
+
+ trace::exiting("scribo::internal::align_lines_horizontaly");
+ return res;
+ }
+
/// Connect vertical and horizontal lines if they are close to each other.
+ ///
+ /// ------ ------
+ /// ---> |
+ /// | |
+ /// | |
+ ///
+ template <typename P>
void
connect_lines(const util::array<int>& aligned_lines,
- util::array<box2d>& boxes,
+ util::array< box<P> >& boxes,
unsigned dim,
unsigned dim_size)
{
+ trace::entering("scribo::internal::connect_lines");
+
image1d<int> l(dim_size);
data::fill(l, -1);
@@ -370,14 +441,130 @@ namespace scribo
for_all_components(i, boxes)
{
- std::pair<point2d, point2d> cp = central_sites(boxes[i], dim);
- if (opt::at(l, cp.first[dim]) != -1)
- boxes[i].pmin()[dim] = aligned_lines[opt::at(l, cp.first[dim])];
- if (opt::at(l, cp.second[dim]) != -1)
- boxes[i].pmax()[dim] = aligned_lines[opt::at(l, cp.second[dim])];
+ util::couple<point2d, point2d> cp = central_sites(boxes[i], dim);
+ if (opt::at(l, cp.first()[dim]) != -1)
+ boxes[i].pmin()[dim] = aligned_lines[opt::at(l, cp.first()[dim])];
+ if (opt::at(l, cp.second()[dim]) != -1)
+ boxes[i].pmax()[dim] = aligned_lines[opt::at(l, cp.second()[dim])];
}
+
+ trace::exiting("scribo::internal::connect_lines");
+ }
+
+
+ /// Connect vertical lines with the new aligned rows.
+ template <typename I>
+ void
+ connect_vertical_lines(const util::array<int>& aligned_rows,
+ util::couple<util::array<box<mln_site(I)> >,
+ util::array<box<mln_site(I)> > > tblboxes,
+ const Image<I>& input)
+ {
+ trace::entering("scribo::internal::connect_vertical_lines");
+ mln_precondition(exact(input).is_valid());
+
+ connect_lines(aligned_rows, tblboxes.first(), 0, exact(input).nrows());
+
+ trace::exiting("scribo::internal::connect_vertical_lines");
+ }
+
+
+ /// Connect horizontal lines with the new aligned columns.
+ template <typename I>
+ void
+ connect_horizontal_lines(const util::array<int>& aligned_cols,
+ util::couple<util::array<box<mln_site(I)> >,
+ util::array<box<mln_site(I)> > > tblboxes,
+ const Image<I>& input)
+ {
+ trace::entering("scribo::internal::connect_horizontal_lines");
+ mln_precondition(exact(input).is_valid());
+
+ connect_lines(aligned_cols, tblboxes.second(), 1, exact(input).ncols());
+
+ trace::exiting("scribo::internal::connect_horizontal_lines");
+ }
+
+
+ /// Repair lines with small discontinuities.
+ /// FIXME: buggy. Sometimes few lines move or shrink!
+ template <unsigned axis, typename I>
+ void
+ repair_lines(const Image<I>& input_,
+ util::array<box<mln_site(I)> >& tblboxes)
+ {
+ std::cout << "repairing lines" << std::endl;
+
+ const I& input = exact(input_);
+ typedef mln_site(I) P;
+ typedef win::line<mln_grid(P), axis, mln_coord(P)> line_t;
+
+ // Initialization
+ image2d<unsigned> l(input.domain());
+ data::fill(l, 0u);
+ for_all_components(i, tblboxes)
+ {
+ util::couple<point2d, point2d> cp = central_sites(tblboxes[i], axis);
+ l(cp.first()) = i;
+ l(cp.second()) = i;
+ }
+
+ // Repair
+ extension_val<image2d<unsigned> > l_ext(l, 0u);
+
+ util::array<box<P> > result;
+ std::vector<bool> to_keep(tblboxes.nelements(), true);
+
+ mln_VAR(tbb_ima, extend(l | pw::value(l) != 0u, l));
+ line_t vl(settings.repair_max_dist); //FIXME: use a half window, just the bottom of the vertical line.
+ mln_piter(tbb_ima_t) p(tbb_ima.domain());
+ mln_qiter(line_t) q(vl, p);
+ for_all(p)
+ for_all(q)
+ if (l_ext(q) != 0u && l_ext(q) != l_ext(p))
+ {
+ to_keep[l_ext(q)] = false;
+
+ std::cout << "Merging " << tblboxes[l_ext(p)] << " with " << tblboxes[l_ext(q)] << std::endl;
+ tblboxes[l_ext(p)].pmax() = tblboxes[l_ext(q)].pmax();
+
+ util::couple<P,P> cp = central_sites(tblboxes[l_ext(q)], axis);
+ l_ext(cp.first()) = l_ext(p);
+ l_ext(cp.second()) = l_ext(p);
+ }
+
+
+ // Remove merged boxes.
+ for_all_elements(i, tblboxes)
+ if (to_keep[i])
+ result.append(tblboxes[i]);
+
+ std::cout << tblboxes[0] << " - " << result[0] << std::endl;
+ std::cout << "previous box count = " << tblboxes.nelements() << " - " << " now = " << result.nelements() << std::endl;
+ tblboxes = result;
+ }
+
+
+ template <typename I>
+ void
+ repair_vertical_lines(const Image<I>& input,
+ util::couple<util::array<box<mln_site(I)> >,
+ util::array<box<mln_site(I)> > >& tblboxes)
+ {
+ repair_lines<0>(input, tblboxes.first());
}
+
+ template <typename I>
+ void
+ repair_horizontal_lines(const Image<I>& input,
+ util::couple<util::array<box<mln_site(I)> >,
+ util::array<box<mln_site(I)> > >& tblboxes)
+ {
+ repair_lines<1>(input, tblboxes.second());
+ }
+
+
// void
// connect_lines2(const util::array<int>& aligned_lines,
// util::array<box2d>& boxes,
@@ -398,11 +585,11 @@ namespace scribo
//
// for_all_components(i, boxes)
// {
-// std::pair<point2d, point2d> cp = central_sites(boxes[i], dim);
+// util::couple<point2d, point2d> cp = central_sites(boxes[i], dim);
//
// win::segment1d seg(11);
// {
-// mln_qiter_(win::segment1d) q(seg, point1d(cp.first[dim]));
+// mln_qiter_(win::segment1d) q(seg, point1d(cp.first()[dim]));
// for_all(q)
// if (opt::at(l, q[0]) != -1)
// {
@@ -411,7 +598,7 @@ namespace scribo
// }
// }
// {
-// mln_qiter_(win::segment1d) q(seg, point1d(cp.second[dim]));
+// mln_qiter_(win::segment1d) q(seg, point1d(cp.second()[dim]));
// for_all(q)
// if (opt::at(l, q[0]) != -1)
// {
@@ -423,56 +610,80 @@ namespace scribo
// }
+ /// Save lines bounding boxes in an image filled with \p bg_color.
+ /// Bounding boxes are displayed with \p bbox_color.
+ template <typename I>
+ void
+ save_table(const Image<I>& input,
+ util::couple<util::array<box<mln_site(I)> >,
+ util::array<box<mln_site(I)> > > tblboxes,
+ const std::string& filename,
+ const value::rgb8& bg_color = literal::black,
+ const value::rgb8& bbox_color = literal::red)
+ {
+ trace::entering("scribo::internal::save_table");
+ mln_precondition(exact(input).is_valid());
+
+ image2d<rgb8> out2(exact(input).domain());
+ data::fill(out2, bg_color);
+ for_all_components(i, tblboxes.first())
+ {
+ util::couple<mln_site(I), mln_site(I)> cp = central_sites(tblboxes.first()[i], 0);
+ out2(cp.first()) = literal::green;
+ out2(cp.second()) = literal::green;
+ draw::box(out2, tblboxes.first()[i], bbox_color);
+ }
+ for_all_components(i, tblboxes.second())
+ {
+ util::couple<mln_site(I), mln_site(I)> cp = central_sites(tblboxes.second()[i], 1);
+ out2(cp.first()) = literal::green;
+ out2(cp.second()) = literal::green;
+ draw::box(out2, tblboxes.second()[i], bbox_color);
+ }
+ io::ppm::save(out2, output_file(filename.c_str()));
+
+ trace::exiting("scribo::internal::save_table");
+ }
+
/// Align line bboxes vertically and horizontally. Then, try to join
/// vertical and horizontal lines in order to rebuild the table.
- image2d<bool>
- rebuild_table(const image2d<bool>& in,
- std::pair<util::array<box2d>,
- util::array<box2d> >& tblboxes)
+ template <typename I>
+ mln_ch_value(I,bool)
+ rebuild_table(const Image<I>& in_,
+ util::couple<util::array<box2d>,
+ util::array<box2d> >& tblboxes)
{
+ const I& in = exact(in_);
+
+ mlc_equal(mln_value(I), bool)::check();
+ mln_precondition(in.is_valid());
+
std::cout << "Rebuild table" << std::endl;
- util::array<int> rows = align_lines(in.nrows(), geom::min_row(in),
- geom::max_row(in), tblboxes.second,
- 0);
- util::array<int> cols = align_lines(in.ncols(), geom::min_col(in),
- geom::max_col(in), tblboxes.first,
- 1);
+ util::array<int> rows = align_lines_horizontaly(in, tblboxes.second());
+ util::array<int> cols = align_lines_verticaly(in, tblboxes.first());
+
# ifndef NOUT
- image2d<rgb8> out2(in.domain());
- data::fill(out2, literal::black);
- for_all_components(i, tblboxes.first)
- draw::box(out2, tblboxes.first[i], literal::red);
- for_all_components(i, tblboxes.second)
- draw::box(out2, tblboxes.second[i], literal::red);
- io::ppm::save(out2, output_file("after-alignment.ppm"));
+ save_table(in, tblboxes, "after-alignment.ppm");
# endif
- // FIXME: Rebuild incomplete lines if possible.
- // ----- --- => ----------
-// connect_lines2(tblboxes.first, 0, in.nrows());
-// connect_lines2(rows, tblboxes.second, 0, in.nrows());
+// repair_vertical_lines(in, tblboxes);
+// repair_horizontal_lines(in, tblboxes);
// Connect vertical lines with horizontal lines.
- connect_lines(rows, tblboxes.first, 0, in.nrows());
- connect_lines(cols, tblboxes.second, 1, in.ncols());
+ connect_vertical_lines(rows, tblboxes, in);
+ connect_horizontal_lines(cols, tblboxes, in);
image2d<bool> res;
initialize(res, in);
data::fill(res, false);
- for_all_components(i, tblboxes.first)
- draw::box(res, tblboxes.first[i], true);
- for_all_components(i, tblboxes.second)
- draw::box(res, tblboxes.second[i], true);
+ for_all_components(i, tblboxes.first())
+ draw::box(res, tblboxes.first()[i], true);
+ for_all_components(i, tblboxes.second())
+ draw::box(res, tblboxes.second()[i], true);
# ifndef NOUT
- image2d<rgb8> out(in.domain());
- data::fill(out, literal::black);
- for_all_components(i, tblboxes.first)
- draw::box(out, tblboxes.first[i], literal::red);
- for_all_components(i, tblboxes.second)
- draw::box(out, tblboxes.second[i], literal::red);
- io::ppm::save(out, output_file("table.ppm"));
+ save_table(in, tblboxes, "table.ppm");
# endif
return res;
@@ -485,9 +696,9 @@ namespace scribo
const box2d& box,
const rgb8& v)
{
- std::pair<point2d, point2d> cp = central_sites(box, dim);
+ util::couple<point2d, point2d> cp = central_sites(box, dim);
- draw::line(ima, cp.first, cp.second, v);
+ draw::line(ima, cp.first(), cp.second(), v);
}
@@ -547,26 +758,32 @@ namespace scribo
boxes[i].enlarge(dim, settings.bbox_enlarge);
boxes[i].crop_wrt(output.domain());
data::paste((pw::cst(false) | boxes[i] |
- (pw::value(output) == pw::cst(true))), output);
+ (pw::value(output) == true)), output);
}
}
/// Find table bboxes and remove them from the image.
- std::pair<util::array<box2d>,
- util::array<box2d> >
- extract_tables(image2d<bool>& in)
+ /// Use rank filter.
+ ///
+ /// \return pair of array of bounding boxes. The first array holds the
+ /// vertical lines bboxes and the second one the horizontal lines
+ /// bboxes.
+ template <typename I, typename HW, typename VW>
+ util::couple<util::array<box<mln_site(I)> >,
+ util::array<box<mln_site(I)> > >
+ extract_table_lines_with_rank(const Image<I>& in,
+ const Window<HW>& vwin,
+ const Window<VW>& hwin,
+ unsigned rank_k)
{
- typedef image2d<label_16> I;
- typedef accu::bbox<mln_psite_(I)> A;
- typedef util::array<mln_result_(A)> boxes_t;
-
+ typedef accu::bbox<mln_psite(I)> A;
+ typedef util::array<mln_result(A)> boxes_t;
// Vertical lines
std::cout << "Removing vertical lines" << std::endl;
- win::vline2d vline(settings.ero_line_width);
- image2d<bool> vfilter = morpho::rank_filter(in, vline, settings.rank_filter);
+ mln_ch_value(I,bool) vfilter = morpho::rank_filter(in, vwin, rank_k);
#ifndef NOUT
io::pbm::save(vfilter, output_file("vertical-erosion.pbm"));
@@ -576,8 +793,7 @@ namespace scribo
// Horizontal lines.
std::cout << "Removing horizontal lines" << std::endl;
- win::hline2d hline(settings.ero_line_width);
- image2d<bool> hfilter = morpho::rank_filter(in, hline, settings.rank_filter);
+ mln_ch_value(I,bool) hfilter = morpho::rank_filter(in, hwin, rank_k);
#ifndef NOUT
io::pbm::save(hfilter, output_file("horizontal-erosion.pbm"));
@@ -585,19 +801,42 @@ namespace scribo
boxes_t hboxes = component_boxes(hfilter);
- erase_table_boxes(in, vboxes, 0);
- erase_table_boxes(in, hboxes, 1);
+ return make::couple(vboxes, hboxes);
+ }
+
+
+ /// Erase table line bboxes from an image.
+ ///
+ /// \param[in] line_bboxes vertical and horizontal line bounding
+ /// boxes.
+ ///
+ /// \param[in, out] in input image in which the lines are
+ /// erased.
+ template <typename I>
+ void
+ erase_table(util::couple<util::array<box2d>,
+ util::array<box2d> >& line_bboxes,
+ Image<I>& in_)
+ {
+ trace::entering("scribo::internal::erase_table");
+ I& in = exact(in_);
+ mln_precondition(in.is_valid());
+
+ erase_table_boxes(in, line_bboxes.first(), 0);
+ erase_table_boxes(in, line_bboxes.second(), 1);
#ifndef NOUT
- image2d<rgb8> tmp = level::convert(rgb8(), in);
- draw_component_boxes(tmp, vboxes);
- draw_component_boxes(tmp, hboxes);
+ mln_ch_value(I,rgb8) tmp = level::convert(rgb8(), in);
+ draw_component_boxes(tmp, line_bboxes.first());
+ draw_component_boxes(tmp, line_bboxes.second());
io::ppm::save(tmp, output_file("vertical-and-horizontal-erosion.ppm"));
+ io::pbm::save(in, output_file("table_removed.pbm"));
#endif
- return std::make_pair(vboxes, hboxes);
+ trace::exiting("scribo::internal::erase_table");
}
+
/// \}
//--------------------------------------------------
/// End of functions related to the table removal.
@@ -764,12 +1003,50 @@ namespace scribo
util::array<unsigned> treated;
};
+ unsigned
+ find_root(util::array<unsigned>& parent, unsigned x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+ /// Merge bboxes according to their left neighbor.
+ util::array<box2d>
+ group_bboxes_with_single_link(util::array<unsigned>& link_array,
+ image2d<label_16>& lbl,
+ util::array<box2d>& cboxes, label_16& nlabels)
+ {
+ for (unsigned i = 0; i < link_array.nelements(); ++i)
+ link_array[i] = find_root(link_array, i);
+ util::array< accu::bbox<point2d> > tboxes;
+ tboxes.resize(nlabels.next());
+ for_all_ncomponents(i, nlabels)
+ tboxes[link_array[i]].take(cboxes[i]);
- /// Merge bboxes according to their left box neighbor.
+ //Update labels
+ labeling::relabel_inplace(lbl, nlabels,
+ convert::to<fun::l2l::relabel<label_16> >(link_array));
+
+#ifndef NOUT
+ save_lbl_image(lbl, nlabels, "lbl-grouped-boxes.pgm");
+#endif
+
+ util::array<box2d> result;
+ convert::from_to(tboxes, result);
+
+ nlabels = result.nelements();
+
+ return result;
+ }
+
+
+ /// Merge bboxes according to their neighbors.
util::array<box2d>
- group_bboxes(const util::graph& g, image2d<label_16>& lbl,
- util::array<box2d>& cboxes, label_16& nlabels)
+ group_bboxes_with_graph(const util::graph& g, image2d<label_16>& lbl,
+ util::array<box2d>& cboxes, label_16& nlabels)
{
// Build relabel function.
make_relabel_fun_t f;
@@ -805,7 +1082,7 @@ namespace scribo
for_all_ncomponents(i, nlabels)
if (tboxes[i].is_valid())
if (comp_size.treated[i] < 3)
- data::fill((lbl2 | (tboxes[i].to_result() | (pw::value(lbl2) == pw::cst(i)))).rw(), 0u);
+ data::fill((lbl2 | (tboxes[i].to_result() | (pw::value(lbl2) == i))).rw(), 0u);
save_lbl_image(lbl2, nlabels, "lbl-grouped-boxes-cleaned.ppm");
#endif
@@ -814,8 +1091,7 @@ namespace scribo
- /// Update the lookup table \p left if a neighbor is found on the right of
- /// the current bbox.
+ /// Add an edge if a valid neighbor is found
void update_link(util::graph& g, image2d<label_16>& lbl,
const point2d& p, const point2d& c,
unsigned i, int dmax)
@@ -825,14 +1101,122 @@ namespace scribo
g.add_edge(lbl(p), i);
}
+ /// Update the lookup table \p link_array if a neighbor is found on the right of
+ /// the current bbox.
+ void update_link_array(util::array<unsigned>& link_array, image2d<label_16>& lbl,
+ const point2d& p, const point2d& c,
+ unsigned i, int dmax)
+ {
+ if (lbl.domain().has(p) && lbl(p) != 0u && lbl(p) != i
+ && (math::abs(p.col() - c.col())) < dmax && link_array[lbl(p)] == lbl(p))
+ link_array[lbl(p)] = i;
+ }
+
+
+
+ void init_link_array(util::array<unsigned>& link_array)
+ {
+ for (unsigned i = 0; i < link_array.nelements(); ++i)
+ link_array[i] = i;
+ }
+
+ /// Map each character bbox to its left bbox neighbor if possible.
+ /// Iterate to the right but link boxes to the left.
+ ///
+ /// \return an util::array. Map a bbox to its left neighbor.
+ util::array<unsigned>
+ link_character_bboxes_with_single_link(image2d<label_16>& lbl,
+ const util::array<box2d>& cboxes,
+ unsigned ncomp)
+ {
+ util::array<unsigned> left_link(ncomp + 1);
+ init_link_array(left_link);
+
+ for_all_ncomponents(i, ncomp)
+ {
+ unsigned midcol = (cboxes[i].pmax().col() - cboxes[i].pmin().col()) / 2;
+ int dmax = midcol + settings.bbox_distance;
+ point2d c = cboxes[i].center();
+
+ ///
+ /// Find a neighbor on the right
+ ///
+
+ /// First site on the right of the central site
+ point2d p = c + right;
+
+ // FIXME: Lemmings with a condition on the distance => write a special version?
+ while (lbl.domain().has(p) && (lbl(p) == 0u || lbl(p) == i)
+ && math::abs(p.col() - c.col()) < dmax)
+ ++p.col();
+
+ update_link_array(left_link, lbl, p, c, i, dmax);
+
+ }
+
+ return left_link;
+ }
/// Map each character bbox to its left bbox neighbor if possible.
/// Iterate to the right but link boxes to the left.
+ ///
+ /// \return a pair of util::array. The first one map a bbox to its left
+ /// neighbor and the second one map a bbox to its right neighbor.
+ util::couple<util::array<unsigned>, util::array<unsigned> >
+ link_character_bboxes_with_double_link(image2d<label_16>& lbl,
+ const util::array<box2d>& cboxes,
+ unsigned ncomp)
+ {
+ util::array<unsigned> left_link(ncomp + 1), right_link(ncomp + 1);
+ init_link_array(left_link);
+ init_link_array(right_link);
+
+ for_all_ncomponents(i, ncomp)
+ {
+ unsigned midcol = (cboxes[i].pmax().col() - cboxes[i].pmin().col()) / 2;
+ int dmax = midcol + settings.bbox_distance;
+ point2d c = cboxes[i].center();
+
+ ///
+ /// Find a neighbor on the right
+ ///
+
+ /// First site on the right of the central site
+ point2d p = c + right;
+
+ // FIXME: Lemmings with a condition on the distance => write a special version?
+ while (lbl.domain().has(p) && (lbl(p) == 0u || lbl(p) == i)
+ && math::abs(p.col() - c.col()) < dmax)
+ ++p.col();
+
+ update_link_array(left_link, lbl, p, c, i, dmax);
+
+
+ ///
+ /// Find a neighbor on the left
+ ///
+
+ /// First site on the left of the central site
+ p = c + left;
+
+ // FIXME: Lemmings with a condition on the distance => write a special version?
+ while (lbl.domain().has(p) && (lbl(p) == 0u || lbl(p) == i)
+ && math::abs(p.col() - c.col()) < dmax)
+ --p.col();
+
+ update_link_array(right_link, lbl, p, c, i, dmax);
+ }
+
+ return make::couple(left_link, right_link);
+ }
+
+
+ /// Map each character bbox to its left neighbors.
util::graph
- link_character_bboxes(image2d<label_16>& lbl,
- const util::array<box2d>& cboxes,
- unsigned ncomp)
+ link_character_bboxes_with_left_graph(image2d<label_16>& lbl,
+ const util::array<box2d>& cboxes,
+ unsigned ncomp)
{
util::graph g(ncomp + 1);
@@ -856,6 +1240,54 @@ namespace scribo
}
+ /// Map each character bbox to its left and right neighbors.
+ util::graph
+ link_character_bboxes_with_left_and_right_graph(image2d<label_16>& lbl,
+ const util::array<box2d>& cboxes,
+ unsigned ncomp)
+ {
+ util::graph g(ncomp + 1);
+
+ for_all_ncomponents(i, ncomp)
+ {
+ unsigned midcol = (cboxes[i].pmax().col() - cboxes[i].pmin().col()) / 2;
+ int dmax = midcol + settings.bbox_distance;
+ point2d c = cboxes[i].center();
+
+ //
+ // Find neighbors on the right
+ //
+
+ /// First site on the right of the central site
+ point2d p = c + right;
+
+ // FIXME: Lemmings with a condition on the distance => write a special version?
+ while (lbl.domain().has(p) && (lbl(p) == 0u || lbl(p) == i)
+ && math::abs(p.col() - c.col()) < dmax)
+ ++p.col();
+
+ update_link(g, lbl, p, c, i, dmax);
+
+ //
+ // Find neighbors on the left
+ //
+
+ /// First site on the right of the central site
+ p = c + left;
+
+ // FIXME: Lemmings with a condition on the distance => write a special version?
+ while (lbl.domain().has(p) && (lbl(p) == 0u || lbl(p) == i)
+ && math::abs(p.col() - c.col()) < dmax)
+ --p.col();
+
+ update_link(g, lbl, p, c, i, dmax);
+
+ }
+
+ return g;
+ }
+
+
util::array<box2d>
extract_text(image2d<bool>& in,
@@ -870,6 +1302,13 @@ namespace scribo
boxes_t cboxes = labeling::compute(accu::meta::bbox(), lbl, nlabels);
+ image2d<label_16> lbl_bbox;
+ initialize(lbl_bbox, lbl);
+ data::fill(lbl_bbox, 0u);
+
+ for_all_components(i, cboxes)
+ draw::box(lbl_bbox, cboxes[i], i);
+
#ifndef NOUT
image2d<rgb8> tmp = level::convert(rgb8(), in);
draw_component_boxes(tmp, cboxes);
@@ -877,10 +1316,10 @@ namespace scribo
#endif
//Link character bboxes to their left neighboor if possible.
- util::graph g = link_character_bboxes(lbl, cboxes, nlabels);
+ util::graph g = link_character_bboxes_with_left_graph(lbl_bbox, cboxes, nlabels);
- //Merge character bboxes according to their left neighbor.
- util::array<box2d> tboxes = group_bboxes(g, lbl, cboxes, nlabels);
+ //Merge character bboxes through a graph.
+ util::array<box2d> tboxes = group_bboxes_with_graph(g, lbl, cboxes, nlabels);
return tboxes;
}
@@ -889,20 +1328,42 @@ namespace scribo
/// Function mapping value to sites of a line graph image.
- template <typename P>
- struct lg_vertex_values : public mln::Function_p2v< lg_vertex_values<P> >
+ template <typename S>
+ struct lg_vertex_values : public mln::Function_p2v< lg_vertex_values<S> >
{
- typedef float result;
+ /// Result is composed of a L2 distance between the two vertices of
+ /// the edge, and the angle between the edge and the origin axis.
+ typedef util::couple<unsigned,float> result;
// Compute the angle between P and (0,1)
- float operator()(const P& p) const
+ util::couple<unsigned,float> operator()(const mln_psite(S)& p) const
{
- mln::algebra::vec<2,float> v, pv;
- v[0] = 0;
- v[1] = 1;
- pv = p.to_vec().normalize();
+ unsigned distance = norm::l2_distance(p.to_site().begin().to_vec(),
+ p.to_site().end().to_vec());
- return v * pv;
+ /// Compute angle between the edge and the axis.
+ mln::algebra::vec<2,float> v, pv;
+ v[0] = 1;
+ v[1] = 0;
+ pv = p.to_site().to_vec().normalize();
+
+ float pi = 3.14;
+ float pi_div2 = pi / 2;
+ float angle = v * pv;
+ // Be sure the angle is between 0 and pi/2
+
+ // up left part of the circle.
+ if (angle > pi_div2 && angle < pi)
+ angle = pi - angle;
+ // down left part of the circle.
+ else if (angle < 0 && angle < -pi_div2)
+ angle += pi;
+
+ // down right part of the circle.
+ if (angle < 0)
+ angle *= -1;
+
+ return make::couple(distance, angle);
}
};
@@ -922,8 +1383,8 @@ namespace scribo
for_all_elements(i, tboxes)
if (tboxes[i].is_valid())
- data::paste(pw::cst(color(tboxes[i].center())) | (tboxes[i] | pw::value(in) == pw::cst(true)),
- dbg);
+ data::paste(pw::cst(color(tboxes[i].center())) | (tboxes[i] | pw::value(in) == true),
+ dbg);
io::ppm::save(dbg, output_file("text2cell.ppm"));
# endif
}
@@ -934,18 +1395,26 @@ namespace scribo
{
std::cout << "Merging aligned text boxes" << std::endl;
- image2d<label_16> lbl_iz = duplicate(lbl);
- io::ppm::save(debug::colorize(rgb8(), lbl, nlabels), output_file("tboxes-lbl.ppm"));
+ io::ppm::save(debug::colorize(rgb8(), lbl, nlabels),
+ output_file("tboxes-lbl.ppm"));
+
+ typedef util::couple<image2d<unsigned>, image2d<label_16> > cpl_t;
+ cpl_t diz =
+ transform::distance_and_influence_zone_geodesic(lbl, c8(),
+ settings.bbox_distance);
- image2d<label_16> iz = transform::influence_zone_geodesic(lbl_iz, c8(), settings.bbox_distance);
#ifndef NOUT
- io::ppm::save(debug::colorize(rgb8(), iz, nlabels), output_file("tboxes-iz.ppm"));
+ io::pgm::save(level::transform(diz.first(), fun::l2l::wrap<label_8>()),
+ output_file("tboxes-dmap.pgm"));
+ io::ppm::save(debug::colorize(rgb8(), diz.second(), nlabels),
+ output_file("tboxes-iz.ppm"));
#endif
typedef util::graph G;
- G g = make::graph(iz | (pw::value(iz) != pw::cst(0u)), c8(), nlabels);
+ G g = make::graph(diz.second() | (pw::value(diz.second()) != pw::cst(0u)),
+ c8(), nlabels);
- // Compute the component centers and use them as vertex.
+ // Compute the component centers and use them as vertex sites.
//FIXME: Add fun::vertex2p
typedef fun::i2v::array<point2d> fv2p_t;
fv2p_t fv2p(nlabels.next());
@@ -953,9 +1422,6 @@ namespace scribo
for_all_components(i, tboxes)
fv2p(i) = tboxes[i].center();
- // Create a p_vertices.
- p_vertices<G, fv2p_t> pv(g, fv2p);
-
typedef util::line_graph<G> LG;
LG lg(g);
@@ -972,24 +1438,47 @@ namespace scribo
// Construct an image from a p_edges and a function mapping
// lines to angles.
- typedef lg_vertex_values<p_line2d> lgv2v_t;
+ typedef lg_vertex_values<pvlg_t> lgv2v_t;
lgv2v_t lgv2v;
mln_VAR(lg_ima, lgv2v | pvlg);
- fun::i2v::array<value::rgb8> ecolor(pvlg.nsites(), literal::olive);
- mln_piter_(lg_ima_t) p(lg_ima.domain());
- for_all (p)
- if ((lg_ima(p) > settings.max_cos) || (lg_ima(p) < - settings.max_cos))
- ecolor(p) = literal::cyan;
+// unsigned dmax = level::compute(accu::max<unsigned>(),
+// thru(meta::first<mln_value_(lg_ima_t)>(),
+// lg_ima));
+//
+// mln_VAR(angle_ima, level::stretch(int_u8(),
+// thru(meta::second<mln_value_(lg_ima_t)>(),
+// lg_ima)));
+//
+// image2d<unsigned> stats(make::box2d(dmax, 255));
+// data::fill(stats, 0u);
+//
+// mln_piter_(lg_ima_t) p(lg_ima.domain());
+// for_all(p)
+// ++stats(point2d(lg_ima(p).first(), angle_ima(p)));
#ifndef NOUT
- image2d<rgb8> output = level::convert(rgb8(), in);
- internal::draw_component_boxes(output, tboxes);
- debug::draw_graph(output, pvlg, pw::cst(literal::cyan), ecolor);
- io::ppm::save(output, internal::output_file("aligned-bboxes-merged.ppm"));
+// io::pgm::save(stats, "stats.pgm");
+ {
+ fun::i2v::array<value::rgb8> ecolor(pvlg.nsites(), literal::olive);
+ mln_piter_(lg_ima_t) p(lg_ima.domain());
+ for_all (p)
+ {
+ mln_value_(lg_ima_t) v = lg_ima(p);
+ if ((v.second() > settings.max_cos) || (v.second() < - settings.max_cos))
+ ecolor(p) = literal::cyan;
+ }
+
+ image2d<rgb8> output = level::convert(rgb8(), in);
+ internal::draw_component_boxes(output, tboxes);
+ debug::draw_graph(output, pvlg, pw::cst(literal::cyan), ecolor);
+ io::ppm::save(output, internal::output_file("aligned-bboxes-merged.ppm"));
+ }
#endif
+
+
}
/// \}
@@ -1028,10 +1517,18 @@ namespace scribo
internal::settings.max_comp_size = in.ncols() * in.nrows() * 0.05;
- // tblboxes.first = vertical lines.
- // tblboxes.second = horizontal lines.
- std::pair<util::array<box2d>,
- util::array<box2d> > tblboxes = internal::extract_tables(in);
+ // tblboxes.first() = vertical lines.
+ // tblboxes.second() = horizontal lines.
+ typedef util::couple<util::array<box2d>,util::array<box2d> > tblboxes_t;
+
+ win::vline2d vline(internal::settings.ero_line_width);
+ win::hline2d hline(internal::settings.ero_line_width);
+ tblboxes_t tblboxes =
+ internal::extract_table_lines_with_rank(in, vline, hline,
+ internal::settings.rank_filter);
+
+ internal::erase_table(tblboxes, in);
+
image2d<bool> table = internal::rebuild_table(in, tblboxes);
/// relabel since the table has been removed.
@@ -1056,7 +1553,7 @@ namespace scribo
io::ppm::save(output, internal::output_file("out.ppm"));
#endif
- internal::text_recognition(in, lbl, tboxes);
+// internal::text_recognition(in, lbl, tboxes);
}
--
1.5.6.5
1
0
* doc/outputs/box2d-bbox.txt,
* doc/outputs/domain-display.txt,
* doc/outputs/dpoint-1.txt,
* doc/outputs/forall-piter.txt,
* doc/outputs/graph-data.txt,
* doc/outputs/ima2d-1.txt,
* doc/outputs/labeling-compute.txt,
* doc/outputs/parray-bbox.txt: update outputs according Theo's last
patch.
---
milena/ChangeLog | 14 ++++++++++++++
milena/doc/outputs/box2d-bbox.txt | 2 +-
milena/doc/outputs/domain-display.txt | 4 ++--
milena/doc/outputs/dpoint-1.txt | 2 +-
milena/doc/outputs/forall-piter.txt | 2 +-
milena/doc/outputs/graph-data.txt | 10 +++++-----
milena/doc/outputs/ima2d-1.txt | 4 ++--
milena/doc/outputs/labeling-compute.txt | 6 +++---
milena/doc/outputs/parray-bbox.txt | 2 +-
9 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 890f5b5..de1a395 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,17 @@
+2009-03-06 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
+ Update documentation reference outputs.
+
+ * doc/outputs/box2d-bbox.txt,
+ * doc/outputs/domain-display.txt,
+ * doc/outputs/dpoint-1.txt,
+ * doc/outputs/forall-piter.txt,
+ * doc/outputs/graph-data.txt,
+ * doc/outputs/ima2d-1.txt,
+ * doc/outputs/labeling-compute.txt,
+ * doc/outputs/parray-bbox.txt: update outputs according Theo's last
+ patch.
+
2009-03-05 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Rewrite the ostream op for grid points and dpoints.
diff --git a/milena/doc/outputs/box2d-bbox.txt b/milena/doc/outputs/box2d-bbox.txt
index f31cdef..61e33e9 100644
--- a/milena/doc/outputs/box2d-bbox.txt
+++ b/milena/doc/outputs/box2d-bbox.txt
@@ -1,2 +1,2 @@
-[(0, 0)..(1, 2)]
+[(0,0)..(1,2)]
nsites = 6
diff --git a/milena/doc/outputs/domain-display.txt b/milena/doc/outputs/domain-display.txt
index 02f0962..16690ac 100644
--- a/milena/doc/outputs/domain-display.txt
+++ b/milena/doc/outputs/domain-display.txt
@@ -1,2 +1,2 @@
-ima1.domain() = [(0, 0)..(4, 4)]
-ima2.domain() = [(0, 0)..(9, 9)]
+ima1.domain() = [(0,0)..(4,4)]
+ima2.domain() = [(0,0)..(9,9)]
diff --git a/milena/doc/outputs/dpoint-1.txt b/milena/doc/outputs/dpoint-1.txt
index 8982f0f..8636f2f 100644
--- a/milena/doc/outputs/dpoint-1.txt
+++ b/milena/doc/outputs/dpoint-1.txt
@@ -1 +1 @@
-(0, 1)
+(0,1)
diff --git a/milena/doc/outputs/forall-piter.txt b/milena/doc/outputs/forall-piter.txt
index f22d097..dc9ffba 100644
--- a/milena/doc/outputs/forall-piter.txt
+++ b/milena/doc/outputs/forall-piter.txt
@@ -1 +1 @@
-(0, 0)(0, 1)(1, 0)(1, 1)(2, 0)(2, 1)
\ No newline at end of file
+(0,0)(0,1)(1,0)(1,1)(2,0)(2,1)
\ No newline at end of file
diff --git a/milena/doc/outputs/graph-data.txt b/milena/doc/outputs/graph-data.txt
index 6bfffae..83f73e1 100644
--- a/milena/doc/outputs/graph-data.txt
+++ b/milena/doc/outputs/graph-data.txt
@@ -1,5 +1,5 @@
-graph_vertices_ima((0, 0)) = 10
-graph_vertices_ima((2, 2)) = 11
-graph_vertices_ima((0, 4)) = 12
-graph_vertices_ima((4, 3)) = 13
-graph_vertices_ima((4, 4)) = 14
+graph_vertices_ima((0,0)) = 10
+graph_vertices_ima((2,2)) = 11
+graph_vertices_ima((0,4)) = 12
+graph_vertices_ima((4,3)) = 13
+graph_vertices_ima((4,4)) = 14
diff --git a/milena/doc/outputs/ima2d-1.txt b/milena/doc/outputs/ima2d-1.txt
index 2a65d2f..eeb0573 100644
--- a/milena/doc/outputs/ima2d-1.txt
+++ b/milena/doc/outputs/ima2d-1.txt
@@ -1,2 +1,2 @@
-b = [(-2, -3)..(3, 5)]
-domain = [(-2, -3)..(3, 5)]
+b = [(-2,-3)..(3,5)]
+domain = [(-2,-3)..(3,5)]
diff --git a/milena/doc/outputs/labeling-compute.txt b/milena/doc/outputs/labeling-compute.txt
index 174807d..19f03f4 100644
--- a/milena/doc/outputs/labeling-compute.txt
+++ b/milena/doc/outputs/labeling-compute.txt
@@ -1,3 +1,3 @@
-[(0, 1)..(1, 2)]
-[(3, 0)..(5, 1)]
-[(3, 2)..(4, 4)]
+[(0,1)..(1,2)]
+[(3,0)..(5,1)]
+[(3,2)..(4,4)]
diff --git a/milena/doc/outputs/parray-bbox.txt b/milena/doc/outputs/parray-bbox.txt
index 28c8c9e..6a34ab2 100644
--- a/milena/doc/outputs/parray-bbox.txt
+++ b/milena/doc/outputs/parray-bbox.txt
@@ -1,2 +1,2 @@
-[(1, 0)..(1, 1)]
+[(1,0)..(1,1)]
nsites = 2
--
1.5.6.5
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Rewrite the ostream op for grid points and dpoints.
* mln/core/concept/gpoint.hh,
* mln/core/concept/gdpoint.hh (operator<<): Rewrite.
It does not rely on to_vec anymore. Important note: the discrete
coordinates on a grid do not follow those of algebra vectors.
For example, we have:
point3d = (sli,row,col)
and
vec3d = (x, y, z)
where
x = row, y = col, and z = sli.
Now vectors are printed with a white space after every comma,
whereas there is no white space for discrete grid points and
dpoints. That is intuive since grid coordinates are integers
and vector coordinates are floating values (usually with a '.'
in them).
gdpoint.hh | 12 +++++++++---
gpoint.hh | 11 ++++++++---
2 files changed, 17 insertions(+), 6 deletions(-)
Index: mln/core/concept/gpoint.hh
--- mln/core/concept/gpoint.hh (revision 3491)
+++ mln/core/concept/gpoint.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -39,6 +39,7 @@
# include <mln/value/concept/scalar.hh>
# include <mln/algebra/vec.hh>
# include <mln/util/ord.hh>
+# include <mln/debug/format.hh>
namespace mln
@@ -383,7 +384,11 @@
inline
std::ostream& operator<<(std::ostream& ostr, const Gpoint<P>& p)
{
- return ostr << exact(p).to_vec();
+ enum { n = P::dim };
+ ostr << '(';
+ for (unsigned i = 0; i < n; ++i)
+ ostr << debug::format(exact(p)[i]) << (i == n - 1 ? ')' : ',');
+ return ostr;
}
template <typename P, typename D>
Index: mln/core/concept/gdpoint.hh
--- mln/core/concept/gdpoint.hh (revision 3491)
+++ mln/core/concept/gdpoint.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -37,6 +37,8 @@
# include <mln/core/grids.hh>
# include <mln/trait/all.hh>
# include <mln/value/scalar.hh>
+# include <mln/debug/format.hh>
+
namespace mln
{
@@ -175,7 +177,11 @@
inline
std::ostream& operator<<(std::ostream& ostr, const Gdpoint<D>& dp)
{
- return ostr << exact(dp).to_vec();
+ enum { n = D::dim };
+ ostr << '(';
+ for (unsigned i = 0; i < n; ++i)
+ ostr << debug::format(exact(dp)[i]) << (i == n - 1 ? ')' : ',');
+ return ostr;
}
1
0