* lazzara/icdar/binarization.cc: Use graphes and gradient for
binarization.
---
milena/sandbox/ChangeLog | 7 +
milena/sandbox/lazzara/icdar/binarization.cc | 273 ++++++++++++++++++++++++++
2 files changed, 280 insertions(+), 0 deletions(-)
create mode 100644 milena/sandbox/lazzara/icdar/binarization.cc
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index 2f10d6b..70acc5a 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,3 +1,10 @@
+2009-04-01 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Add some code for ICDAR.
+
+ * lazzara/icdar/binarization.cc: Use graphes and gradient for
+ binarization.
+
2009-04-01 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add a 1st threshold code.
diff --git a/milena/sandbox/lazzara/icdar/binarization.cc
b/milena/sandbox/lazzara/icdar/binarization.cc
new file mode 100644
index 0000000..ade1695
--- /dev/null
+++ b/milena/sandbox/lazzara/icdar/binarization.cc
@@ -0,0 +1,273 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/site_set/box.hh>
+#include <mln/data/fill.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/core/macros.hh>
+#include <mln/core/concept/function.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/site_set/p_edges.hh>
+#include <mln/core/site_set/p_vertices.hh>
+#include <mln/io/essential.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/label_16.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/morpho/elementary/gradient_internal.hh>
+#include <mln/morpho/closing/volume.hh>
+#include <mln/morpho/watershed/flooding.hh>
+#include <mln/make/rag_and_labeled_wsl.hh>
+#include <mln/util/graph.hh>
+#include <mln/util/couple.hh>
+#include <mln/debug/colorize.hh>
+#include <mln/fun/i2v/array.hh>
+#include <mln/labeling/compute.hh>
+#include <mln/accu/center.hh>
+#include <mln/accu/median_h.hh>
+#include <mln/accu/mean.hh>
+#include <mln/pw/cst.hh>
+#include <mln/math/abs.hh>
+#include <mln/literal/colors.hh>
+#include <mln/debug/draw_graph.hh>
+
+namespace mln
+{
+
+ struct edge_values : Function_vv2v<edge_values>
+ {
+ typedef value::int_u8 result;
+ typedef void mutable_result;
+
+ value::int_u8 operator()(const value::int_u8& v1,
+ const value::int_u8& v2) const
+ { return math::abs(v1 - v2); }
+
+ };
+
+
+ template <typename I, typename V>
+ class edge_to_color : public Function_p2v< edge_to_color<I,V> >
+ {
+ public:
+ typedef V result;
+
+ edge_to_color(const I& ima_e) : ima_e_(ima_e)
+ {}
+
+ V
+ operator()(const unsigned& e) const
+ { return convert::to<V>(ima_e_.function()(e)); }
+
+ private:
+ const I& ima_e_;
+ };
+
+
+ namespace make
+ {
+
+ template <typename G, typename P>
+ p_edges<G,pw::cst_<P> >
+ dummy_pedges(const Graph<G>& g_, const P& dummy_value)
+ {
+ trace::entering("dummy_pedges");
+
+ const G& g = exact(g_);
+ mln_precondition(g.is_valid());
+ p_edges<G,pw::cst_<P> > pe(g, pw::cst(dummy_value));
+
+ trace::exiting("dummy_pedges");
+ return pe;
+ }
+
+ template <typename FVV, typename G, typename V2P, typename E2P, typename FVE>
+ pw::image<fun::i2v::array<mln_result(FVE)>,p_edges<G,E2P> >
+ edge_image(const pw::image<FVV,p_vertices<G,V2P> >& vertex_image,
+ const p_edges<G,E2P>& pe,
+ const Function_vv2v<FVE>& edge_value_)
+ {
+ trace::entering("edge_image");
+
+ const FVE& edge_value = exact(edge_value_);
+ mln_precondition(vertex_image.is_valid());
+ mln_precondition(pe.is_valid());
+
+ typedef fun::i2v::array<mln_result(FVE)> edge_values_t;
+ edge_values_t edge_values(pe.nsites());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, p_edges<G,E2P> > ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e)
+ ima_e(e) = edge_value(vertex_image.function()(e.element().v1()),
+ vertex_image.function()(e.element().v2()));
+
+ trace::exiting("edge_image");
+ return ima_e;
+ }
+
+
+ template <typename W, typename G>
+ inline
+ p_vertices<util::graph, fun::i2v::array<mln_site(W)> >
+ common_pvertices(const Image<W>& wst, const mln_value(W)& nbasins,
+ const Graph<G>& g_)
+ {
+ trace::entering("common_pvertices");
+
+ const G& g = exact(g_);
+ mln_precondition(g.is_valid());
+
+ typedef fun::i2v::array<mln_site(W)> vertex_sites_t;
+ vertex_sites_t vertex_sites;
+ convert::from_to(labeling::compute(accu::center<mln_site(W)>(), wst,
nbasins),
+ vertex_sites);
+
+ p_vertices<util::graph, vertex_sites_t> pv(g, vertex_sites);
+
+ trace::exiting("common_pvertices");
+ return pv;
+ }
+
+
+ template <typename A, typename G, typename F, typename I, typename W>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<G,F> >
+ vertex_image(const Accumulator<A>& accu,
+ const p_vertices<G,F>& pv,
+ const Image<I>& input_,
+ const Image<W>& wst_,
+ const mln_value(W)& nbasins)
+ {
+ trace::entering("vertex_image");
+
+ const I& input = exact(input_);
+ const W& wst = exact(wst_);
+ mln_precondition(input.is_valid());
+ mln_precondition(wst.is_valid());
+ mln_precondition(pv.is_valid());
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(labeling::compute(accu, input, wst, nbasins),
+ vertex_values);
+
+ pw::image<fun::i2v::array<mln_value(I)>,
+ p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ ima_vertex = vertex_values | pv;
+
+ trace::exiting("vertex_image");
+ return ima_vertex;
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ mln_concrete(I)
+ debug_graph_image(const Image<I>& input_,
+ const Image<V>& ima_v_, const Image<E>& ima_e_,
+ unsigned box_size, const mln_value(I)& bg)
+ {
+ trace::entering("debug_graph_image");
+
+ const I& input = exact(input_);
+ const V& ima_v = exact(ima_v_);
+ const E& ima_e = exact(ima_e_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(ima_v.is_valid());
+ mln_precondition(ima_e.is_valid());
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ data::fill(output, bg);
+ debug::draw_graph(output, ima_v.domain(),
+ pw::cst(150u),
+ 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)
+ {
+ box<mln_site(I)> b(p + tl, p + br);
+ b.crop_wrt(output.domain());
+ data::fill((output | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ trace::exiting("debug_graph_image");
+ return output;
+ }
+
+ } // end of namespace mln::make
+
+} // end of namespace mln
+
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using namespace value;
+
+ if (argc < 2)
+ {
+ std::cout << argv[0] << " <input.pgm> " <<
std::endl;
+ return 1;
+ }
+
+ image2d<int_u8> input;
+ io::pgm::load(input, argv[1]);
+
+ image2d<int_u8> grad = morpho::elementary::gradient_internal(input, c4());
+ io::pgm::save(grad, "binarization_grad.pgm");
+
+ image2d<int_u8> clo_vol = morpho::closing::volume(grad, c4(), 500);
+ io::pgm::save(clo_vol, "binarization_clo.pgm");
+
+ label_16 nbasins;
+ image2d<label_16> wst = morpho::watershed::flooding(clo_vol, c4(), nbasins);
+ io::ppm::save(debug::colorize(rgb8(), wst, nbasins),
"binarization_wst.ppm");
+
+
+ util::couple<util::graph, image2d<label_16> >
+ rag_data = make::rag_and_labeled_wsl(wst, c4(), nbasins);
+
+ io::pgm::save(rag_data.second(), "binarization_lwsl.pgm");
+ io::ppm::save(debug::colorize(rgb8(), rag_data.second(), nbasins),
"binarization_lwsl.ppm");
+
+ p_vertices<util::graph, fun::i2v::array<point2d> >
+ pv = make::common_pvertices(wst, nbasins, rag_data.first());
+
+ pw::image<fun::i2v::array<int_u8>,
+ p_vertices<util::graph, fun::i2v::array<point2d> > >
+ ima_v = make::vertex_image(accu::mean<int_u8>(), pv, input, wst, nbasins);
+
+ pw::image<fun::i2v::array<int_u8>,
+ p_edges<util::graph,pw::cst_<literal::origin_t> > >
+ ima_e = make::edge_image(ima_v,
+ make::dummy_pedges(rag_data.first(),literal::origin),
+ edge_values());
+
+
+ io::pgm::save(make::debug_graph_image(input,ima_v, ima_e, 4, 0),
"binarization_graph.ppm");
+
+ // FIXME: we should use the following line instead. We cannot since currently
+ // graph edges are numbered from 0 and we must use mln_max() - 1 as
+ // background id.
+ //
+ //label_16 nelts = rag.first().e_nmax();
+ label_16 nelts = mln_max(label_16).prev();
+
+ util::array<int_u8> median_grad = labeling::compute(accu::meta::median_h(),
+ grad,
+ rag_data.second(),
+ nelts);
+ fun::i2v::array<int_u8> f;
+ convert::from_to(median_grad, f);
+
+ image2d<int_u8> med = level::transform(rag_data.second(), f);
+
+ io::pgm::save(med, "binarization_median_grad.pgm");
+}
--
1.5.6.5