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
 
November 2010
- 7 participants
 - 370 discussions
 
                        
                            
                                
                            
                            last-svn-commit-650-gf148998	scribo/toolchain/text_in_doc.hh: Make use of non visible	separators information.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 scribo/ChangeLog                       |    5 +++++
 scribo/scribo/toolchain/text_in_doc.hh |   31 +++++++++++++++++++++----------
 2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 000bf1a..07d166b 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,10 @@
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/toolchain/text_in_doc.hh: Make use of non visible
+	separators information.
+
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	* scribo/io/xml/save.hh: Make use of document structure.
 
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
diff --git a/scribo/scribo/toolchain/text_in_doc.hh b/scribo/scribo/toolchain/text_in_doc.hh
index 50db26a..279ac13 100644
--- a/scribo/scribo/toolchain/text_in_doc.hh
+++ b/scribo/scribo/toolchain/text_in_doc.hh
@@ -37,6 +37,7 @@
 
 # include <scribo/primitive/extract/components.hh>
 # include <scribo/primitive/extract/vertical_separators.hh>
+# include <scribo/primitive/extract/separators_nonvisible.hh>
 
 # include <scribo/primitive/remove/separators.hh>
 
@@ -63,13 +64,15 @@
 # include <scribo/debug/looks_like_a_text_line_image.hh>
 
 
-
 namespace scribo
 {
 
   namespace toolchain
   {
 
+    using namespace mln;
+
+
     template <typename I>
     line_set<mln_ch_value(I, def::lbl_type)>
     text_in_doc(const Image<I>& input, bool denoise, bool debug = false);
@@ -77,6 +80,7 @@ namespace scribo
 
 # ifndef MLN_INCLUDE_ONLY
 
+
     template <typename I>
     line_set<mln_ch_value(I, def::lbl_type)>
     text_in_doc(const Image<I>& input, bool denoise, bool debug = false)
@@ -84,15 +88,11 @@ namespace scribo
       typedef value::label<30> V;
       typedef image2d<V> L;
 
-      // Add whitespace separators.
-      //   win::rectangle2d win = win::rectangle2d(151, 41);
-      //   image2d<bool> whitespaces = morpho::closing::structural(input, win);
-      //   logical::not_inplace(whitespaces);
-
       // Remove separators
       if (debug)
 	std::cout << "Find vertical separators..." << std::endl;
 
+      // Vertical separators
       image2d<bool>
 	separators = primitive::extract::vertical_separators(input, 81);
 
@@ -102,15 +102,23 @@ namespace scribo
       image2d<bool> input_cleaned = primitive::remove::separators(input,
 								  separators);
 
-//   whitespaces += separators;
+      // Whitespace separators
+      if (debug)
+	std::cout << "Find whitespace separators..." << std::endl;
+
+      image2d<bool>
+	whitespaces = primitive::extract::separators_nonvisible(input);
 
       if (debug)
       {
+	mln::io::pbm::save(whitespaces,
+			   scribo::make::debug_filename("whitespaces.pbm"));
+
 	mln::io::pbm::save(separators,
 			   scribo::make::debug_filename("vseparators.pbm"));
-//   mln::io::pbm::save(whitespaces, "separators.pbm");
 
-	mln::io::pbm::save(input_cleaned, scribo::make::debug_filename("input_wo_vseparators.pbm"));
+	mln::io::pbm::save(input_cleaned,
+			   scribo::make::debug_filename("input_wo_vseparators.pbm"));
       }
 
       // Denoise
@@ -137,10 +145,13 @@ namespace scribo
 
       /// Set separator components.
       components.add_separators(separators);
-//  components.add_separators(whitespaces);
+      components.add_separators(whitespaces);
 
       components = scribo::filter::components_small(components, 3);
 
+      if (debug)
+	mln::io::pbm::save(components.separators(),
+			   scribo::make::debug_filename("all_separators.pbm"));
 
       /// Linking potential objects
       if (debug)
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-651-g4e3b22c	scribo/toolchain/text_in_doc.hh: Make use of non visible	separators information.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 scribo/ChangeLog                       |    5 +++++
 scribo/scribo/toolchain/text_in_doc.hh |   31 +++++++++++++++++++++----------
 2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index b14e5bf..9400016 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,10 @@
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/toolchain/text_in_doc.hh: Make use of non visible
+	separators information.
+
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	* scribo/io/xml/save.hh: Make use of document structure.
 
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
diff --git a/scribo/scribo/toolchain/text_in_doc.hh b/scribo/scribo/toolchain/text_in_doc.hh
index 50db26a..279ac13 100644
--- a/scribo/scribo/toolchain/text_in_doc.hh
+++ b/scribo/scribo/toolchain/text_in_doc.hh
@@ -37,6 +37,7 @@
 
 # include <scribo/primitive/extract/components.hh>
 # include <scribo/primitive/extract/vertical_separators.hh>
+# include <scribo/primitive/extract/separators_nonvisible.hh>
 
 # include <scribo/primitive/remove/separators.hh>
 
@@ -63,13 +64,15 @@
 # include <scribo/debug/looks_like_a_text_line_image.hh>
 
 
-
 namespace scribo
 {
 
   namespace toolchain
   {
 
+    using namespace mln;
+
+
     template <typename I>
     line_set<mln_ch_value(I, def::lbl_type)>
     text_in_doc(const Image<I>& input, bool denoise, bool debug = false);
@@ -77,6 +80,7 @@ namespace scribo
 
 # ifndef MLN_INCLUDE_ONLY
 
+
     template <typename I>
     line_set<mln_ch_value(I, def::lbl_type)>
     text_in_doc(const Image<I>& input, bool denoise, bool debug = false)
@@ -84,15 +88,11 @@ namespace scribo
       typedef value::label<30> V;
       typedef image2d<V> L;
 
-      // Add whitespace separators.
-      //   win::rectangle2d win = win::rectangle2d(151, 41);
-      //   image2d<bool> whitespaces = morpho::closing::structural(input, win);
-      //   logical::not_inplace(whitespaces);
-
       // Remove separators
       if (debug)
 	std::cout << "Find vertical separators..." << std::endl;
 
+      // Vertical separators
       image2d<bool>
 	separators = primitive::extract::vertical_separators(input, 81);
 
@@ -102,15 +102,23 @@ namespace scribo
       image2d<bool> input_cleaned = primitive::remove::separators(input,
 								  separators);
 
-//   whitespaces += separators;
+      // Whitespace separators
+      if (debug)
+	std::cout << "Find whitespace separators..." << std::endl;
+
+      image2d<bool>
+	whitespaces = primitive::extract::separators_nonvisible(input);
 
       if (debug)
       {
+	mln::io::pbm::save(whitespaces,
+			   scribo::make::debug_filename("whitespaces.pbm"));
+
 	mln::io::pbm::save(separators,
 			   scribo::make::debug_filename("vseparators.pbm"));
-//   mln::io::pbm::save(whitespaces, "separators.pbm");
 
-	mln::io::pbm::save(input_cleaned, scribo::make::debug_filename("input_wo_vseparators.pbm"));
+	mln::io::pbm::save(input_cleaned,
+			   scribo::make::debug_filename("input_wo_vseparators.pbm"));
       }
 
       // Denoise
@@ -137,10 +145,13 @@ namespace scribo
 
       /// Set separator components.
       components.add_separators(separators);
-//  components.add_separators(whitespaces);
+      components.add_separators(whitespaces);
 
       components = scribo::filter::components_small(components, 3);
 
+      if (debug)
+	mln::io::pbm::save(components.separators(),
+			   scribo::make::debug_filename("all_separators.pbm"));
 
       /// Linking potential objects
       if (debug)
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-649-gf502432 scribo/io/xml/save.hh:	Make use of document structure.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 scribo/ChangeLog             |    4 +
 scribo/scribo/io/xml/save.hh |  214 +++++++++++++++++++++---------------------
 2 files changed, 111 insertions(+), 107 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 828f9b8..000bf1a 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/io/xml/save.hh: Make use of document structure.
+
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	* scribo/primitive/extract/elements.hh: New routine.
 
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
diff --git a/scribo/scribo/io/xml/save.hh b/scribo/scribo/io/xml/save.hh
index f13396f..c6b416d 100644
--- a/scribo/scribo/io/xml/save.hh
+++ b/scribo/scribo/io/xml/save.hh
@@ -28,7 +28,7 @@
 
 /// \file
 ///
-/// \brief Save text line information as XML.
+/// \brief Save document information as XML.
 
 # include <fstream>
 # include <sstream>
@@ -46,7 +46,7 @@ namespace scribo
     namespace xml
     {
 
-      /*! \brief Save text line information as XML.
+      /*! \brief Save document information as XML.
 
 	We use a XML Schema part of the PAGE (Page Analysis and Ground
 	truth Elements) image representation framework.
@@ -60,8 +60,7 @@ namespace scribo
        */
       template <typename L>
       void
-      save(const std::string& input_name,
-	   const line_set<L>& lines,
+      save(const document<L>& doc,
 	   const std::string& output_name,
 	   bool extended_format);
 
@@ -86,12 +85,34 @@ namespace scribo
 	  return input;
 	}
 
+
+	void print_box_coords(std::ofstream& ostr, const box2d& b,
+			      const char *space)
+	{
+	  std::string sc = space;
+	  std::string sp = sc + "  ";
+	  ostr << sc << "<coords>" << std::endl
+	       << sp << "<point x=\"" << b.pmin().col()
+	       << "\" y=\"" << b.pmin().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmax().col()
+	       << "\" y=\"" << b.pmin().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmax().col()
+	       << "\" y=\"" << b.pmax().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmin().col()
+	       << "\" y=\"" << b.pmax().row() << "\"/>"
+	       << std::endl
+	       << sc << "</coords>" << std::endl;
+
+	}
+
       } // end of namespace scribo::io::xml::internal
 
       template <typename L>
       void
-      save(const std::string& input_name,
-	   const line_set<L>& lines,
+      save(const document<L>& doc,
 	   const std::string& output_name,
 	   bool extended_format)
       {
@@ -100,9 +121,12 @@ namespace scribo
 	std::ofstream file(output_name.c_str());
 	if (! file)
 	{
-	  std::cerr << "error: cannot open file '" << input_name << "'!";
+	  std::cerr << "error: cannot open file '" << doc.filename() << "'!";
 	  abort();
 	}
+
+	const line_set<L>& lines = doc.text();
+
 	std::map<char, std::string> html_map;
 	html_map['\"'] = """;
 	html_map['<'] = "<";
@@ -111,13 +135,13 @@ namespace scribo
 
 	file << "<?xml version=\"1.0\"?>" << std::endl;
 	if (extended_format)
-	  {
-	    file << "<pcGts>" << std::endl;
-	  }
+	{
+	  file << "<pcGts>" << std::endl;
+	}
 	else
-	  {
-	    file << "<pcGts xmlns=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16 http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…" pcGtsId=\"" << input_name << "\">" << std::endl;
-	  }
+	{
+	  file << "<pcGts xmlns=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16 http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…" pcGtsId=\"" << doc.filename() << "\">" << std::endl;
+	}
 
 	file << "  <PcMetadata>" << std::endl;
 	file << "    <PcCreator>LRDE</PcCreator>" << std::endl;
@@ -126,110 +150,86 @@ namespace scribo
 	file << "    <PcComments>Generated by Scribo from Olena.</PcComments>" << std::endl;
 	file << "  </PcMetadata>" << std::endl;
 
-	file << "  <page image_filename=\"" << input_name
+	file << "  <page image_filename=\"" << doc.filename()
 	     << "\" image_width=\"" << lines.components().labeled_image().ncols()
 	     << "\" image_height=\"" << lines.components().labeled_image().nrows()
 	     << "\">" << std::endl;
 
 	for_all_lines(l, lines)
+	{
+	  if (! lines(l).is_valid()
+	      || lines(l).tag() != line::None
+	      || lines(l).type() != line::Text) // Is NOT a text line.
+	    continue;
 	  {
-	    if (! lines(l).is_valid()
-		|| lines(l).tag() != line::None
-		|| lines(l).type() != line::Text) // Is NOT a text line.
-	      continue;
+	    file << "    <text_region id=\"" << lines(l).id()
+		 << "\" txt_orientation=\"" << lines(l).orientation()
+		 << "\" txt_reading_orientation=\"" << lines(l).reading_orientation()
+		 << "\" txt_reading_direction=\"" << lines(l).reading_direction()
+		 << "\" txt_text_type=\"" << lines(l).type()
+		 << "\" txt_reverse_video=\"" << (lines(l).reverse_video() ? "true" : "false")
+		 << "\" txt_indented=\"" << (lines(l).indented() ? "true" : "false")
+		 << "\" kerning=\"" << lines(l).char_space();
+
+	    // EXTENSIONS - Not officially supported
+	    if (extended_format)
 	    {
-	      file << "    <text_region id=\"" << lines(l).id()
-		   << "\" txt_orientation=\"" << lines(l).orientation()
-		   << "\" txt_reading_orientation=\"" << lines(l).reading_orientation()
-		   << "\" txt_reading_direction=\"" << lines(l).reading_direction()
-		   << "\" txt_text_type=\"" << lines(l).type()
-		   << "\" txt_reverse_video=\"" << (lines(l).reverse_video() ? "true" : "false")
-		   << "\" txt_indented=\"" << (lines(l).indented() ? "true" : "false")
-		   << "\" kerning=\"" << lines(l).char_space();
-
-	      // EXTENSIONS - Not officially supported
-	      if (extended_format)
-		{
-		  file << "\" baseline=\"" << lines(l).baseline()
-		       << "\" meanline=\"" << lines(l).meanline()
-		       << "\" x_height=\"" << lines(l).x_height()
-		       << "\" d_height=\"" << lines(l).d_height()
-		       << "\" a_height=\"" << lines(l).a_height()
-		       << "\" char_width=\"" << lines(l).char_width();
-		}
-	      // End of EXTENSIONS
-	      file << "\">"
-		   << std::endl;
+	      file << "\" baseline=\"" << lines(l).baseline()
+		   << "\" meanline=\"" << lines(l).meanline()
+		   << "\" x_height=\"" << lines(l).x_height()
+		   << "\" d_height=\"" << lines(l).d_height()
+		   << "\" a_height=\"" << lines(l).a_height()
+		   << "\" char_width=\"" << lines(l).char_width();
+	    }
+	    // End of EXTENSIONS
+	    file << "\">"
+		 << std::endl;
 
-	      if (extended_format)
-		{
-		  file << "      <coords>" << std::endl
-		       << "        <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "        <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "        <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "        <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "      </coords>" << std::endl;
-
-
-		  file << "      <paragraph>" << std::endl;
-
-		  file << "        <coords>" << std::endl
-		       << "          <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "          <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "          <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "          <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "        </coords>" << std::endl;
-
-		  if (lines(l).has_text())
-		    {
-		      std::string tmp = lines(l).text();
-		      tmp = internal::html_markups_replace(tmp, html_map);
-
-		      file << "        <line text=\""
-			   << tmp
-			   << "\">" << std::endl;
-		    }
-		  else
-		    file << "        <line>" << std::endl;
-
-		  file << "          <coords>" << std::endl
-		       << "            <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "            <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "            <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "            <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "          </coords>" << std::endl;
-
-		  file << "        </line>" << std::endl;
-
-		  file << "      </paragraph>" << std::endl;
-		}
+	    internal::print_box_coords(file, lines(l).bbox(), "      ");
+
+	    if (extended_format)
+	    {
+	      file << "      <paragraph>" << std::endl;
+
+	      internal::print_box_coords(file, lines(l).bbox(), "        ");
+
+	      if (lines(l).has_text())
+	      {
+		std::string tmp = lines(l).text();
+		tmp = internal::html_markups_replace(tmp, html_map);
+
+		file << "        <line text=\""
+		     << tmp
+		     << "\">" << std::endl;
+	      }
+	      else
+		file << "        <line>" << std::endl;
+
+	      internal::print_box_coords(file, lines(l).bbox(), "          ");
 
-	      file << "    </text_region>" << std::endl;
+	      file << "        </line>" << std::endl;
+
+	      file << "      </paragraph>" << std::endl;
 	    }
+
+	    file << "    </text_region>" << std::endl;
+	  }
+	}
+
+
+	const component_set<L>& elts = doc.elements();
+	for_all_comps(e, elts)
+	  if (elts(e).is_valid())
+	  {
+	    file << "    <image_region id=\"ir" << elts(e).id()
+		 << "\" img_colour_type=\"24_Bit_Colour\""
+		 << " img_orientation=\"0.000000\" "
+		 << " img_emb_text=\"No\" "
+		 << " img_bgcolour=\"White\">" << std::endl;
+
+	    internal::print_box_coords(file, elts(e).bbox(), "      ");
+
+	    file << "    </image_region>" << std::endl;
 	  }
 
 	file << "  </page>" << std::endl;
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-650-gc2ce47f scribo/io/xml/save.hh:	Make use of document structure.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 scribo/ChangeLog             |    4 +
 scribo/scribo/io/xml/save.hh |  214 +++++++++++++++++++++---------------------
 2 files changed, 111 insertions(+), 107 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index e738a8a..b14e5bf 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/io/xml/save.hh: Make use of document structure.
+
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	* scribo/primitive/extract/elements.hh: New routine.
 
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
diff --git a/scribo/scribo/io/xml/save.hh b/scribo/scribo/io/xml/save.hh
index f13396f..c6b416d 100644
--- a/scribo/scribo/io/xml/save.hh
+++ b/scribo/scribo/io/xml/save.hh
@@ -28,7 +28,7 @@
 
 /// \file
 ///
-/// \brief Save text line information as XML.
+/// \brief Save document information as XML.
 
 # include <fstream>
 # include <sstream>
@@ -46,7 +46,7 @@ namespace scribo
     namespace xml
     {
 
-      /*! \brief Save text line information as XML.
+      /*! \brief Save document information as XML.
 
 	We use a XML Schema part of the PAGE (Page Analysis and Ground
 	truth Elements) image representation framework.
@@ -60,8 +60,7 @@ namespace scribo
        */
       template <typename L>
       void
-      save(const std::string& input_name,
-	   const line_set<L>& lines,
+      save(const document<L>& doc,
 	   const std::string& output_name,
 	   bool extended_format);
 
@@ -86,12 +85,34 @@ namespace scribo
 	  return input;
 	}
 
+
+	void print_box_coords(std::ofstream& ostr, const box2d& b,
+			      const char *space)
+	{
+	  std::string sc = space;
+	  std::string sp = sc + "  ";
+	  ostr << sc << "<coords>" << std::endl
+	       << sp << "<point x=\"" << b.pmin().col()
+	       << "\" y=\"" << b.pmin().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmax().col()
+	       << "\" y=\"" << b.pmin().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmax().col()
+	       << "\" y=\"" << b.pmax().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmin().col()
+	       << "\" y=\"" << b.pmax().row() << "\"/>"
+	       << std::endl
+	       << sc << "</coords>" << std::endl;
+
+	}
+
       } // end of namespace scribo::io::xml::internal
 
       template <typename L>
       void
-      save(const std::string& input_name,
-	   const line_set<L>& lines,
+      save(const document<L>& doc,
 	   const std::string& output_name,
 	   bool extended_format)
       {
@@ -100,9 +121,12 @@ namespace scribo
 	std::ofstream file(output_name.c_str());
 	if (! file)
 	{
-	  std::cerr << "error: cannot open file '" << input_name << "'!";
+	  std::cerr << "error: cannot open file '" << doc.filename() << "'!";
 	  abort();
 	}
+
+	const line_set<L>& lines = doc.text();
+
 	std::map<char, std::string> html_map;
 	html_map['\"'] = """;
 	html_map['<'] = "<";
@@ -111,13 +135,13 @@ namespace scribo
 
 	file << "<?xml version=\"1.0\"?>" << std::endl;
 	if (extended_format)
-	  {
-	    file << "<pcGts>" << std::endl;
-	  }
+	{
+	  file << "<pcGts>" << std::endl;
+	}
 	else
-	  {
-	    file << "<pcGts xmlns=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16 http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…" pcGtsId=\"" << input_name << "\">" << std::endl;
-	  }
+	{
+	  file << "<pcGts xmlns=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16 http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…" pcGtsId=\"" << doc.filename() << "\">" << std::endl;
+	}
 
 	file << "  <PcMetadata>" << std::endl;
 	file << "    <PcCreator>LRDE</PcCreator>" << std::endl;
@@ -126,110 +150,86 @@ namespace scribo
 	file << "    <PcComments>Generated by Scribo from Olena.</PcComments>" << std::endl;
 	file << "  </PcMetadata>" << std::endl;
 
-	file << "  <page image_filename=\"" << input_name
+	file << "  <page image_filename=\"" << doc.filename()
 	     << "\" image_width=\"" << lines.components().labeled_image().ncols()
 	     << "\" image_height=\"" << lines.components().labeled_image().nrows()
 	     << "\">" << std::endl;
 
 	for_all_lines(l, lines)
+	{
+	  if (! lines(l).is_valid()
+	      || lines(l).tag() != line::None
+	      || lines(l).type() != line::Text) // Is NOT a text line.
+	    continue;
 	  {
-	    if (! lines(l).is_valid()
-		|| lines(l).tag() != line::None
-		|| lines(l).type() != line::Text) // Is NOT a text line.
-	      continue;
+	    file << "    <text_region id=\"" << lines(l).id()
+		 << "\" txt_orientation=\"" << lines(l).orientation()
+		 << "\" txt_reading_orientation=\"" << lines(l).reading_orientation()
+		 << "\" txt_reading_direction=\"" << lines(l).reading_direction()
+		 << "\" txt_text_type=\"" << lines(l).type()
+		 << "\" txt_reverse_video=\"" << (lines(l).reverse_video() ? "true" : "false")
+		 << "\" txt_indented=\"" << (lines(l).indented() ? "true" : "false")
+		 << "\" kerning=\"" << lines(l).char_space();
+
+	    // EXTENSIONS - Not officially supported
+	    if (extended_format)
 	    {
-	      file << "    <text_region id=\"" << lines(l).id()
-		   << "\" txt_orientation=\"" << lines(l).orientation()
-		   << "\" txt_reading_orientation=\"" << lines(l).reading_orientation()
-		   << "\" txt_reading_direction=\"" << lines(l).reading_direction()
-		   << "\" txt_text_type=\"" << lines(l).type()
-		   << "\" txt_reverse_video=\"" << (lines(l).reverse_video() ? "true" : "false")
-		   << "\" txt_indented=\"" << (lines(l).indented() ? "true" : "false")
-		   << "\" kerning=\"" << lines(l).char_space();
-
-	      // EXTENSIONS - Not officially supported
-	      if (extended_format)
-		{
-		  file << "\" baseline=\"" << lines(l).baseline()
-		       << "\" meanline=\"" << lines(l).meanline()
-		       << "\" x_height=\"" << lines(l).x_height()
-		       << "\" d_height=\"" << lines(l).d_height()
-		       << "\" a_height=\"" << lines(l).a_height()
-		       << "\" char_width=\"" << lines(l).char_width();
-		}
-	      // End of EXTENSIONS
-	      file << "\">"
-		   << std::endl;
+	      file << "\" baseline=\"" << lines(l).baseline()
+		   << "\" meanline=\"" << lines(l).meanline()
+		   << "\" x_height=\"" << lines(l).x_height()
+		   << "\" d_height=\"" << lines(l).d_height()
+		   << "\" a_height=\"" << lines(l).a_height()
+		   << "\" char_width=\"" << lines(l).char_width();
+	    }
+	    // End of EXTENSIONS
+	    file << "\">"
+		 << std::endl;
 
-	      if (extended_format)
-		{
-		  file << "      <coords>" << std::endl
-		       << "        <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "        <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "        <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "        <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "      </coords>" << std::endl;
-
-
-		  file << "      <paragraph>" << std::endl;
-
-		  file << "        <coords>" << std::endl
-		       << "          <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "          <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "          <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "          <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "        </coords>" << std::endl;
-
-		  if (lines(l).has_text())
-		    {
-		      std::string tmp = lines(l).text();
-		      tmp = internal::html_markups_replace(tmp, html_map);
-
-		      file << "        <line text=\""
-			   << tmp
-			   << "\">" << std::endl;
-		    }
-		  else
-		    file << "        <line>" << std::endl;
-
-		  file << "          <coords>" << std::endl
-		       << "            <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "            <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmin().row() << "\"/>"
-		       << std::endl
-		       << "            <point x=\"" << lines(l).bbox().pmax().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "            <point x=\"" << lines(l).bbox().pmin().col()
-		       << "\" y=\"" << lines(l).bbox().pmax().row() << "\"/>"
-		       << std::endl
-		       << "          </coords>" << std::endl;
-
-		  file << "        </line>" << std::endl;
-
-		  file << "      </paragraph>" << std::endl;
-		}
+	    internal::print_box_coords(file, lines(l).bbox(), "      ");
+
+	    if (extended_format)
+	    {
+	      file << "      <paragraph>" << std::endl;
+
+	      internal::print_box_coords(file, lines(l).bbox(), "        ");
+
+	      if (lines(l).has_text())
+	      {
+		std::string tmp = lines(l).text();
+		tmp = internal::html_markups_replace(tmp, html_map);
+
+		file << "        <line text=\""
+		     << tmp
+		     << "\">" << std::endl;
+	      }
+	      else
+		file << "        <line>" << std::endl;
+
+	      internal::print_box_coords(file, lines(l).bbox(), "          ");
 
-	      file << "    </text_region>" << std::endl;
+	      file << "        </line>" << std::endl;
+
+	      file << "      </paragraph>" << std::endl;
 	    }
+
+	    file << "    </text_region>" << std::endl;
+	  }
+	}
+
+
+	const component_set<L>& elts = doc.elements();
+	for_all_comps(e, elts)
+	  if (elts(e).is_valid())
+	  {
+	    file << "    <image_region id=\"ir" << elts(e).id()
+		 << "\" img_colour_type=\"24_Bit_Colour\""
+		 << " img_orientation=\"0.000000\" "
+		 << " img_emb_text=\"No\" "
+		 << " img_bgcolour=\"White\">" << std::endl;
+
+	    internal::print_box_coords(file, elts(e).bbox(), "      ");
+
+	    file << "    </image_region>" << std::endl;
 	  }
 
 	file << "  </page>" << std::endl;
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-648-g222955a	scribo/primitive/extract/elements.hh: New routine.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 scribo/ChangeLog                            |    4 +
 scribo/scribo/primitive/extract/elements.hh |  227 +++++++++++++++++++++++++++
 2 files changed, 231 insertions(+), 0 deletions(-)
 create mode 100644 scribo/scribo/primitive/extract/elements.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index be9d85d..828f9b8 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/primitive/extract/elements.hh: New routine.
+
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	* scribo/primitive/extract/separators_nonvisible.hh: New routine.
 
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
diff --git a/scribo/scribo/primitive/extract/elements.hh b/scribo/scribo/primitive/extract/elements.hh
new file mode 100644
index 0000000..c083988
--- /dev/null
+++ b/scribo/scribo/primitive/extract/elements.hh
@@ -0,0 +1,227 @@
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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.
+
+/// \file
+///
+/// \brief Find in a document elements which are not text.
+///
+/// \fixme To be optimized!
+
+#ifndef SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
+# define SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
+
+# include <mln/core/image/image2d.hh>
+# include <mln/data/fill.hh>
+# include <mln/util/array.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/labeling/relabel.hh>
+# include <mln/accu/math/count.hh>
+# include <mln/pw/all.hh>
+
+# include <mln/value/label_8.hh>
+# include <mln/value/rgb8.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/component_set.hh>
+# include <scribo/core/line_set.hh>
+# include <scribo/filter/objects_small.hh>
+
+#include <mln/clustering/kmean_rgb.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+namespace scribo
+{
+
+  namespace primitive
+  {
+
+    namespace extract
+    {
+
+
+      template <typename L, typename I>
+      component_set<L>
+      elements(const document<L>& doc, const Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+      namespace internal
+      {
+
+	template <typename L>
+	struct order_bbox
+	{
+	  order_bbox(const scribo::component_set<L>& comps)
+	    : comps_(comps)
+	  {
+	  }
+
+	  bool operator()(const unsigned& c1, const unsigned& c2) const
+	  {
+	    if (comps_(c1).bbox().nsites() == comps_(c2).bbox().nsites())
+	      return c1 > c2;
+	    return comps_(c1).bbox().nsites() > comps_(c2).bbox().nsites();
+	  }
+
+	  scribo::component_set<L> comps_;
+	};
+
+      } // end of namespace scribo::primitive::extract::internal
+
+
+
+      // FACADE
+
+      template <typename L, typename I>
+      component_set<L>
+      elements(const document<L>& doc, const Image<I>& input_)
+      {
+	trace::entering("scribo::primitive::extract::elements");
+
+	const I& input = exact(input_);
+	mln_precondition(doc.is_valid());
+	mln_precondition(input.is_valid());
+
+	const line_set<L>& lines = doc.text();
+
+	// Element extraction
+
+	image2d<value::label_8> img_lbl8;
+	{
+	  image2d<bool> content;
+	  initialize(content, input);
+	  data::fill(content, true);
+
+	  for_all_lines(l, lines)
+	    if (lines(l).type() == line::Text)
+	      data::fill((content | lines(l).bbox()).rw(), false);
+
+	  typedef mln::value::rgb<5>                 t_rgb5;
+	  typedef mln::fun::v2v::rgb8_to_rgbn<5>     t_rgb8_to_rgb5;
+
+	  image2d<t_rgb5>
+	    img_rgb5 = mln::data::transform(doc.image(), t_rgb8_to_rgb5());
+
+	  img_lbl8 =
+	    mln::clustering::kmean_rgb<double,5>((img_rgb5 | pw::value(content)), 3, 10, 10).unmorph_();
+	  data::fill((img_lbl8 | !pw::value(content)).rw(), 0u);
+
+	  mln::util::array<unsigned>
+	    card = mln::labeling::compute(accu::math::count<value::label_8>(),
+					  img_lbl8, img_lbl8, 3);
+
+	  unsigned max = 0, bg_id = 0;
+	  for_all_ncomponents(c, 3)
+	    if (card(c) > max)
+	    {
+	      max = card(c);
+	      bg_id = c;
+	    }
+
+	  mln::fun::i2v::array<bool> f(4, true);
+	  f(0) = false;
+	  f(bg_id) = false;
+	  labeling::relabel_inplace(img_lbl8, 4, f);
+	}
+
+
+	component_set<L> output;
+
+	std::cout << "Removing small elements" << std::endl;
+	{
+	image2d<bool> elts;
+	initialize(elts, img_lbl8);
+	data::fill(elts, false);
+	data::fill((elts | (pw::value(img_lbl8) != pw::cst(0))).rw(), true);
+
+	scribo::def::lbl_type nlabels;
+	elts = filter::components_small(elts, c8(), nlabels, 40);
+
+	output = primitive::extract::components(elts, c8(), nlabels);
+	}
+
+
+	std::cout << "Ignoring inner elements" << std::endl;
+
+	{
+	  // FIXME: We would like to use the convex hull instead of the bbox.
+	  internal::order_bbox<L> func(output);
+	  util::array<unsigned> box_ordered_comps;
+	  for (unsigned i = 1; i < output.nelements(); ++i)
+	    box_ordered_comps.append(i);
+	  std::sort(box_ordered_comps.hook_std_vector_().begin(),
+		    box_ordered_comps.hook_std_vector_().end(), func);
+
+	  image2d<bool> merged_elts;
+	  initialize(merged_elts, img_lbl8);
+	  data::fill(merged_elts, false);
+	  for (unsigned i = 0; i < box_ordered_comps.nelements(); ++i)
+	  {
+	    unsigned c = box_ordered_comps(i);
+	    point2d
+	      pminright = output(c).bbox().pmin(),
+	      pmaxleft = output(c).bbox().pmax();
+	    pminright.col() = output(c).bbox().pmax().col();
+	    pmaxleft.col() = output(c).bbox().pmin().col();
+
+	    if (merged_elts(output(c).bbox().pmin())
+		&& merged_elts(output(c).bbox().pmax())
+		&& merged_elts(pminright)
+		&& merged_elts(pmaxleft))
+	      output(c).update_tag(component::Ignored);
+	    else
+	      mln::draw::box_plain(merged_elts, output(c).bbox(), true);
+	  }
+	}
+
+// 	mln::io::pbm::save(merged_elts, "merged_elts.pbm");
+
+// 	mln::util::array<image2d<value::rgb8> > elt_ima;
+// 	unsigned i = 0;
+// 	for_all_comps(c, elt_comp)
+// 	  if (elt_comp(c).is_valid())
+// 	  {
+// 	    elt_ima.append(preprocessing::crop(doc.image(), elt_comp(c).bbox()));
+// 	    mln::io::ppm::save(elt_ima(i), mln::debug::filename("elt.ppm", i));
+// 	    ++i;
+// 	  }
+
+
+	trace::exiting("scribo::primitive::extract::elements");
+	return output;
+      }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+    } // end of namespace scribo::primitive::extract
+
+  } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-649-g15f9077	scribo/primitive/extract/elements.hh: New routine.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 scribo/ChangeLog                            |    4 +
 scribo/scribo/primitive/extract/elements.hh |  227 +++++++++++++++++++++++++++
 2 files changed, 231 insertions(+), 0 deletions(-)
 create mode 100644 scribo/scribo/primitive/extract/elements.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 9c65829..e738a8a 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/primitive/extract/elements.hh: New routine.
+
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	* scribo/primitive/extract/separators_nonvisible.hh: New routine.
 
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
diff --git a/scribo/scribo/primitive/extract/elements.hh b/scribo/scribo/primitive/extract/elements.hh
new file mode 100644
index 0000000..c083988
--- /dev/null
+++ b/scribo/scribo/primitive/extract/elements.hh
@@ -0,0 +1,227 @@
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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.
+
+/// \file
+///
+/// \brief Find in a document elements which are not text.
+///
+/// \fixme To be optimized!
+
+#ifndef SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
+# define SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
+
+# include <mln/core/image/image2d.hh>
+# include <mln/data/fill.hh>
+# include <mln/util/array.hh>
+# include <mln/labeling/compute.hh>
+# include <mln/labeling/relabel.hh>
+# include <mln/accu/math/count.hh>
+# include <mln/pw/all.hh>
+
+# include <mln/value/label_8.hh>
+# include <mln/value/rgb8.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/component_set.hh>
+# include <scribo/core/line_set.hh>
+# include <scribo/filter/objects_small.hh>
+
+#include <mln/clustering/kmean_rgb.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+namespace scribo
+{
+
+  namespace primitive
+  {
+
+    namespace extract
+    {
+
+
+      template <typename L, typename I>
+      component_set<L>
+      elements(const document<L>& doc, const Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+      namespace internal
+      {
+
+	template <typename L>
+	struct order_bbox
+	{
+	  order_bbox(const scribo::component_set<L>& comps)
+	    : comps_(comps)
+	  {
+	  }
+
+	  bool operator()(const unsigned& c1, const unsigned& c2) const
+	  {
+	    if (comps_(c1).bbox().nsites() == comps_(c2).bbox().nsites())
+	      return c1 > c2;
+	    return comps_(c1).bbox().nsites() > comps_(c2).bbox().nsites();
+	  }
+
+	  scribo::component_set<L> comps_;
+	};
+
+      } // end of namespace scribo::primitive::extract::internal
+
+
+
+      // FACADE
+
+      template <typename L, typename I>
+      component_set<L>
+      elements(const document<L>& doc, const Image<I>& input_)
+      {
+	trace::entering("scribo::primitive::extract::elements");
+
+	const I& input = exact(input_);
+	mln_precondition(doc.is_valid());
+	mln_precondition(input.is_valid());
+
+	const line_set<L>& lines = doc.text();
+
+	// Element extraction
+
+	image2d<value::label_8> img_lbl8;
+	{
+	  image2d<bool> content;
+	  initialize(content, input);
+	  data::fill(content, true);
+
+	  for_all_lines(l, lines)
+	    if (lines(l).type() == line::Text)
+	      data::fill((content | lines(l).bbox()).rw(), false);
+
+	  typedef mln::value::rgb<5>                 t_rgb5;
+	  typedef mln::fun::v2v::rgb8_to_rgbn<5>     t_rgb8_to_rgb5;
+
+	  image2d<t_rgb5>
+	    img_rgb5 = mln::data::transform(doc.image(), t_rgb8_to_rgb5());
+
+	  img_lbl8 =
+	    mln::clustering::kmean_rgb<double,5>((img_rgb5 | pw::value(content)), 3, 10, 10).unmorph_();
+	  data::fill((img_lbl8 | !pw::value(content)).rw(), 0u);
+
+	  mln::util::array<unsigned>
+	    card = mln::labeling::compute(accu::math::count<value::label_8>(),
+					  img_lbl8, img_lbl8, 3);
+
+	  unsigned max = 0, bg_id = 0;
+	  for_all_ncomponents(c, 3)
+	    if (card(c) > max)
+	    {
+	      max = card(c);
+	      bg_id = c;
+	    }
+
+	  mln::fun::i2v::array<bool> f(4, true);
+	  f(0) = false;
+	  f(bg_id) = false;
+	  labeling::relabel_inplace(img_lbl8, 4, f);
+	}
+
+
+	component_set<L> output;
+
+	std::cout << "Removing small elements" << std::endl;
+	{
+	image2d<bool> elts;
+	initialize(elts, img_lbl8);
+	data::fill(elts, false);
+	data::fill((elts | (pw::value(img_lbl8) != pw::cst(0))).rw(), true);
+
+	scribo::def::lbl_type nlabels;
+	elts = filter::components_small(elts, c8(), nlabels, 40);
+
+	output = primitive::extract::components(elts, c8(), nlabels);
+	}
+
+
+	std::cout << "Ignoring inner elements" << std::endl;
+
+	{
+	  // FIXME: We would like to use the convex hull instead of the bbox.
+	  internal::order_bbox<L> func(output);
+	  util::array<unsigned> box_ordered_comps;
+	  for (unsigned i = 1; i < output.nelements(); ++i)
+	    box_ordered_comps.append(i);
+	  std::sort(box_ordered_comps.hook_std_vector_().begin(),
+		    box_ordered_comps.hook_std_vector_().end(), func);
+
+	  image2d<bool> merged_elts;
+	  initialize(merged_elts, img_lbl8);
+	  data::fill(merged_elts, false);
+	  for (unsigned i = 0; i < box_ordered_comps.nelements(); ++i)
+	  {
+	    unsigned c = box_ordered_comps(i);
+	    point2d
+	      pminright = output(c).bbox().pmin(),
+	      pmaxleft = output(c).bbox().pmax();
+	    pminright.col() = output(c).bbox().pmax().col();
+	    pmaxleft.col() = output(c).bbox().pmin().col();
+
+	    if (merged_elts(output(c).bbox().pmin())
+		&& merged_elts(output(c).bbox().pmax())
+		&& merged_elts(pminright)
+		&& merged_elts(pmaxleft))
+	      output(c).update_tag(component::Ignored);
+	    else
+	      mln::draw::box_plain(merged_elts, output(c).bbox(), true);
+	  }
+	}
+
+// 	mln::io::pbm::save(merged_elts, "merged_elts.pbm");
+
+// 	mln::util::array<image2d<value::rgb8> > elt_ima;
+// 	unsigned i = 0;
+// 	for_all_comps(c, elt_comp)
+// 	  if (elt_comp(c).is_valid())
+// 	  {
+// 	    elt_ima.append(preprocessing::crop(doc.image(), elt_comp(c).bbox()));
+// 	    mln::io::ppm::save(elt_ima(i), mln::debug::filename("elt.ppm", i));
+// 	    ++i;
+// 	  }
+
+
+	trace::exiting("scribo::primitive::extract::elements");
+	return output;
+      }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+    } // end of namespace scribo::primitive::extract
+
+  } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_EXTRACT_ELEMENTS_HH
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-647-geec4ffe	scribo/primitive/extract/separators_nonvisible.hh: New routine.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 scribo/ChangeLog                                   |    4 +
 .../primitive/extract/separators_nonvisible.hh     |  912 ++++++++++++++++++++
 2 files changed, 916 insertions(+), 0 deletions(-)
 create mode 100644 scribo/scribo/primitive/extract/separators_nonvisible.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index cd8db5d..be9d85d 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/primitive/extract/separators_nonvisible.hh: New routine.
+
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	Import rgb8 to rgbn conversion function from Yann's sandbox.
 
 	* mln/fun/v2v/rgb8_to_rgbn.hh: New.
diff --git a/scribo/scribo/primitive/extract/separators_nonvisible.hh b/scribo/scribo/primitive/extract/separators_nonvisible.hh
new file mode 100644
index 0000000..460d10e
--- /dev/null
+++ b/scribo/scribo/primitive/extract/separators_nonvisible.hh
@@ -0,0 +1,912 @@
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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.
+
+/// \file
+///
+/// \brief Find non visible separators (whitespaces)
+///
+/// \fixme To be cleaned up
+
+#ifndef SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
+# define SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
+
+#include <mln/core/concept/image.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/pw/all.hh>
+
+#include <mln/draw/line.hh>
+
+#include <mln/data/wrap.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/convert.hh>
+
+
+#include <mln/labeling/colorize.hh>
+#include <mln/labeling/relabel.hh>
+#include <mln/labeling/blobs.hh>
+
+#include <mln/morpho/closing/structural.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/opening/structural.hh>
+#include <mln/win/rectangle2d.hh>
+#include <mln/win/vline2d.hh>
+
+#include <mln/logical/not.hh>
+#include <mln/io/pbm/all.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/value/label_16.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/draw/box_plain.hh>
+
+#include <mln/transform/influence_zone_geodesic.hh>
+
+#include <mln/data/stretch.hh>
+
+#include <mln/util/timer.hh>
+
+#include <mln/norm/l1.hh>
+
+#include <scribo/core/object_groups.hh>
+#include <scribo/core/component_set.hh>
+#include <scribo/primitive/extract/components.hh>
+
+#include <scribo/primitive/extract/lines_h_pattern.hh>
+#include <scribo/primitive/remove/separators.hh>
+
+#include <scribo/preprocessing/denoise_fg.hh>
+#include <scribo/preprocessing/rotate_90.hh>
+
+#include <scribo/primitive/link/internal/dmax_default.hh>
+
+#include <scribo/primitive/link/with_single_right_link_dmax_ratio.hh>
+#include <scribo/primitive/link/with_single_right_link_dmax_ratio_aligned.hh>
+
+#include <scribo/primitive/group/from_double_link_any.hh>
+
+#include <scribo/filter/object_links_top_aligned.hh>
+#include <scribo/filter/object_groups_small.hh>
+#include <scribo/filter/object_links_bottom_aligned.hh>
+#include <scribo/debug/save_linked_bboxes_image.hh>
+#include <scribo/debug/decision_image.hh>
+
+
+
+
+
+namespace scribo
+{
+
+  namespace primitive
+  {
+
+    namespace extract
+    {
+
+      using namespace mln;
+
+
+      /// \brief Find non visible separators (whitespaces)
+      //
+      template <typename I>
+      mln_concrete(I)
+      separators_nonvisible(const Image<I>& in_);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+      namespace internal
+      {
+
+	// Enable debug.
+	bool _debug_;
+
+
+	template <typename L>
+	void filter_bad_groups(object_groups<L>& top_groups,
+			       object_groups<L>& bot_groups)
+	{
+	  const component_set<L>& comps = top_groups.components();
+	  const L& lbl = comps.labeled_image();
+
+	  for_all_groups(c, top_groups)
+	  {
+	    box2d b = comps(c).bbox();
+	    b.enlarge(0, comps(c).bbox().height());
+	    b.crop_wrt(lbl.domain());
+
+	    typedef mln_value(L) V;
+
+	    const V* top_ptr = & lbl(b.pmin());
+	    const V* bot_ptr = & lbl(point2d(b.pmax().row(), b.pmin().col()));
+
+	    unsigned ntop = 0, nbot = 0;
+	    for (unsigned n = 0; n < b.width(); ++n)
+	    {
+	      if (*top_ptr)
+		++ntop;
+	      if (*bot_ptr)
+		++nbot;
+	    }
+
+	    if (ntop / b.width() > 0.50f)
+	      top_groups(c) = c;
+
+	    if (nbot / b.width() > 0.50f)
+	      bot_groups(c) = c;
+	  }
+
+	}
+
+
+	template <typename L>
+	mln_site(L)
+	my_anchors(const component_set<L>& comps,
+		   unsigned current_object,
+		   anchor::Type anchor)
+	{
+	  mln_site(L) sp;// = comps(current_object).bbox().pcenter();
+
+	  unsigned h = comps(current_object).bbox().height();
+
+	  switch (anchor)
+	  {
+	    default:
+	      return sp;
+
+
+	      // Bounding box top center
+	    case anchor::Top: // FIXME: rename as TopLeft
+	      sp.col() = comps(current_object).bbox().pmin().col();
+	      sp.row() = comps(current_object).bbox().pmin().row()
+		+ math::min(2u, (h + 1) / 2 - 1);
+	      break;
+
+
+	      // Bounding box bottom center
+	    case anchor::Bottom: // FIXME: rename as BottomLeft
+	      sp.col() = comps(current_object).bbox().pmax().col();
+	      sp.row() = comps(current_object).bbox().pmax().row()
+		- math::min(2u, (h + 1) / 2 - 1);
+	      break;
+	  }
+
+	  return sp;
+	}
+
+
+
+	using namespace primitive::link::internal;
+
+	template <typename L, typename E>
+	class single_dmax_ratio_aligned_functor_base
+	  : public link_single_dmax_ratio_base<L, dmax_default, E>
+	{
+	  typedef link_single_dmax_ratio_base<L, dmax_default, E> super_;
+
+	public:
+	  typedef mln_site(L) P;
+
+	  single_dmax_ratio_aligned_functor_base(
+	    const mln_ch_value(L,bool)& input,
+	    const component_set<L>& components,
+	    unsigned dmax,
+	    float min_angle,
+	    float max_angle,
+	    anchor::Type anchor_)
+	    : super_(components,
+		     anchor::Horizontal,
+		     dmax_default(dmax)),
+	      anchor(anchor_),
+	      debug_(data::convert(value::rgb8(), input)),
+	      debug_angle_(data::convert(value::rgb8(), input))
+	  {
+	    min_alpha_rad = (min_angle / 180.0f) * math::pi;
+	    max_alpha_rad = (max_angle / 180.0f) * math::pi;
+	  }
+
+	  void compute_next_site_(P& p)
+	  {
+	    ++p.col();
+	  }
+
+	  void compute_next_site_f_(unsigned& p)
+	  {
+	    ++p;
+	  }
+
+
+	  mln_site(L)
+	  start_point_(unsigned current_object, anchor::Type anchor)
+	  {
+	    return my_anchors(this->components_, current_object, anchor);
+	  }
+
+
+	  inline
+	  bool
+	  valid_link_(unsigned current_object,
+		      const P& start_point,
+		      const P& p)
+	  {
+	    if (!super_::valid_link_(current_object, start_point, p))
+	      return false;
+
+	    box<P> b = this->components_(current_object).bbox();
+
+	    // Distance between the two components.
+	    float dist;
+
+	    // current object is on the left.
+	    if (p[this->direction_] > b.pmax()[this->direction_])
+	      dist = math::abs(p[this->direction_] - b.pmax()[this->direction_]);
+	    // current object is on the right.
+	    else
+	      dist = math::abs(p[this->direction_] - b.pmin()[this->direction_]);
+
+
+	    int ldist = this->components_(current_object).bbox().width();
+
+	    // Components are really close, so the angle is more permissive.
+	    if (dist < 3 * ldist)
+	    {
+	      return
+		filter::internal::component_aligned_rad(this->components_,
+							current_object,
+							this->labeled_image_(p),
+							anchor,
+							max_alpha_rad);
+	    }
+
+
+	    // Components are really far, so the angle is less permissive.
+	    return
+	      filter::internal::component_aligned_rad(this->components_,
+						      current_object,
+						      this->labeled_image_(p),
+						      anchor,
+						      min_alpha_rad);
+	  }
+
+	  void validate_link_(unsigned current_object,
+			      const P& start_point,
+			      const P& p,
+			      anchor::Type anchor)
+	  {
+	    super_::validate_link_(current_object, start_point, p, anchor);
+
+	    if (_debug_)
+	    {
+	      mln_site(L)
+		p1 = my_anchors(this->components_, current_object, anchor),
+		p2 = my_anchors(this->components_, this->labeled_image_(p),
+				     anchor);
+	      mln::draw::line(debug_, p1, p2, literal::green);
+
+
+	      float
+		angle = filter::internal::alignment_angle(this->components_,
+							  current_object,
+							  this->labeled_image_(p),
+							  anchor);
+	      angle = (angle * 180.0f) / math::pi;
+	      angle = angle * 20.0f + 1.0f;
+	      mln::draw::line(debug_angle_, p1, p2,
+			      value::rgb8(angle, angle, angle));
+	    }
+	  }
+
+	  void invalidate_link_(unsigned current_object,
+				const P& start_point,
+				const P& p,
+				anchor::Type anchor)
+	  {
+	    super_::invalidate_link_(current_object, start_point, p, anchor);
+
+	    if (_debug_)
+	    {
+	      if (this->labeled_image_.domain().has(p) && this->labeled_image_(p) != 0)
+	      {
+		mln_site(L)
+		  p1 = my_anchors(this->components_, current_object, anchor),
+		  p2 = my_anchors(this->components_, this->labeled_image_(p),
+				       anchor);
+		if (this->labeled_image_.domain().has(p2) && norm::l1_distance(p1.to_vec(), p2.to_vec()) < 300)
+		{
+		  mln::draw::line(debug_, p1, p2, literal::red);
+		}
+
+
+		float
+		  angle = filter::internal::alignment_angle(this->components_,
+							    current_object,
+							    this->labeled_image_(p),
+							    anchor);
+		angle = (angle * 180.0f) / math::pi;
+		angle = angle * 20.0f + 1.0f;
+		mln::draw::line(debug_angle_, p1, p2,
+				value::rgb8(angle, angle, angle));
+	      }
+	    }
+	  }
+
+
+	  float min_alpha_rad;
+	  float max_alpha_rad;
+	  anchor::Type anchor;
+
+
+	  mln_ch_value(L, value::rgb8) debug_;
+	  mln_ch_value(L, value::rgb8) debug_angle_;
+	};
+
+
+	template <typename L>
+	class single_right_dmax_ratio_aligned_functor
+	  : public single_dmax_ratio_aligned_functor_base<L, single_right_dmax_ratio_aligned_functor<L> >
+	{
+	  typedef single_right_dmax_ratio_aligned_functor<L> self_t;
+	  typedef single_dmax_ratio_aligned_functor_base<L, self_t> super_;
+
+	public:
+	  typedef mln_site(L) P;
+
+	  single_right_dmax_ratio_aligned_functor(
+	    const mln_ch_value(L, bool)& input,
+	    const component_set<L>& components,
+	    unsigned dmax,
+	    float min_angle,
+	    float max_angle,
+	    anchor::Type anchor)
+	    : super_(input, components, dmax, min_angle, max_angle, anchor)
+	  {
+	  }
+
+	  void compute_next_site_(P& p)
+	  {
+	    ++p.col();
+	  }
+
+	  void compute_next_site_f_(unsigned& p)
+	  {
+	    ++p;
+	  }
+
+	};
+
+
+	template <typename L>
+	class single_left_dmax_ratio_aligned_functor
+	  : public single_dmax_ratio_aligned_functor_base<L, single_left_dmax_ratio_aligned_functor<L> >
+	{
+	  typedef single_left_dmax_ratio_aligned_functor<L> self_t;
+	  typedef single_dmax_ratio_aligned_functor_base<L, self_t> super_;
+
+	public:
+	  typedef mln_site(L) P;
+
+	  single_left_dmax_ratio_aligned_functor(
+	    const mln_ch_value(L, bool)& input,
+	    const component_set<L>& components,
+	    unsigned dmax,
+	    float min_angle,
+	    float max_angle,
+	    anchor::Type anchor)
+	    : super_(input, components, dmax, min_angle, max_angle, anchor)
+	  {
+	  }
+
+	  void compute_next_site_(P& p)
+	  {
+	    --p.col();
+	  }
+
+	  void compute_next_site_f_(unsigned& p)
+	  {
+	    --p;
+	  }
+
+
+	};
+
+      } // end of namespace scribo::primitive::extract::internal
+
+
+
+
+      // FACADE
+
+      template <typename I>
+      mln_concrete(I)
+      separators_nonvisible(const Image<I>& in_)
+      {
+	const I& in = exact(in_);
+	mln_precondition(in.is_valid());
+	typedef mln_value(I) Vi;
+	mlc_is(Vi,bool)::check();
+
+	internal::_debug_ = false;
+	unsigned
+	  min_angle = 3,
+	  max_angle = 5,
+	  min_card = 3;
+
+	util::timer t;
+	util::timer gt;
+
+	// Load (OK)
+	t.start();
+	float t_ = t;
+	std::cout << "Image loaded - " << t_ << std::endl;
+
+	gt.start();
+
+
+	// Remove horizontal lines.
+	t.restart();
+
+	mln_concrete(I) hlines = primitive::extract::lines_h_pattern(in, 50, 3);
+	mln_concrete(I) input = primitive::remove::separators(in, hlines);
+
+	t_ = t;
+	std::cout << "Horizontal lines removed - " << t_ << std::endl;
+
+
+	// Closing structural - Connect characters.
+	t.restart();
+
+	win::hline2d vl(17);
+	mln_concrete(I) input_clo = morpho::closing::structural(input, vl);
+
+//  input_clo = scribo::preprocessing::rotate_90(input_clo, true);
+
+	t_ = t;
+	std::cout << "closing_structural - " << t_ << std::endl;
+
+	if (internal::_debug_)
+	{
+	  // Restore input orientation.
+	  input = scribo::preprocessing::rotate_90(input, false);
+
+	  io::pbm::save(input_clo, "input_clo.pbm");
+	}
+
+	// Rotate (OK)
+	t.restart();
+	input_clo = scribo::preprocessing::rotate_90(input_clo, false);
+	t_ = t;
+	std::cout << "rotate_90 - " << t_ << std::endl;
+
+
+
+	/// Finding components.
+	typedef value::int_u16 V;
+	typedef mln_ch_value(I,V) L;
+
+	t.restart();
+	V ncomponents;
+	component_set<L>
+	  components = scribo::primitive::extract::components(input_clo, c8(),
+							      ncomponents);
+	t_ = t;
+	std::cout << "extract::components - " << t_ << std::endl;
+
+	if (internal::_debug_)
+	  io::pgm::save(data::convert(value::int_u8(), components.labeled_image()),
+			"lbl.pgm");
+
+
+	unsigned dmax = 5;
+
+	t.restart();
+	object_links<L> top_right, bot_right;
+
+	object_links<L> top_left, bot_left;
+
+
+	// Top
+	{
+	  // Right
+	  internal::single_right_dmax_ratio_aligned_functor<L>
+	    functor(input_clo, components, dmax, min_angle, max_angle, anchor::Top);
+//    top_right = primitive::link::impl::compute_fastest(functor, anchor::Top);
+	  top_right = primitive::link::compute(functor, anchor::Top);
+
+	  t.stop();
+
+
+	  if (internal::_debug_)
+	  {
+	    io::ppm::save(functor.debug_, "right_top.ppm");
+	    io::ppm::save(functor.debug_angle_, "right_top_angle.ppm");
+	  }
+
+	  t.resume();
+
+	  // Left
+	  internal::single_left_dmax_ratio_aligned_functor<L>
+	    lfunctor(input_clo, components, dmax, min_angle, max_angle, anchor::Top);
+	  top_left = primitive::link::compute(lfunctor, anchor::Top);
+
+
+	  t.stop();
+
+	  if (internal::_debug_)
+	  {
+	    io::ppm::save(lfunctor.debug_, "left_top.ppm");
+	    io::ppm::save(lfunctor.debug_angle_, "left_top_angle.ppm");
+
+	    mln_ch_value(I, value::rgb8) output = duplicate(functor.debug_);
+	    data::paste((lfunctor.debug_ | (pw::value(lfunctor.debug_) != pw::cst(literal::black))) | (pw::value(lfunctor.debug_) != pw::cst(literal::white)), output);
+
+	    io::ppm::save(output, "left_right_top.ppm");
+	  }
+
+	  t.resume();
+	}
+
+
+	// Bottom
+	{
+	  // Right
+	  internal::single_right_dmax_ratio_aligned_functor<L>
+	    functor(input_clo, components, dmax, min_angle, max_angle, anchor::Bottom);
+	  bot_right = primitive::link::compute(functor, anchor::Bottom);
+	  t.stop();
+
+	  if (internal::_debug_)
+	  {
+	    io::ppm::save(functor.debug_, "right_bot.ppm");
+	    io::ppm::save(functor.debug_angle_, "right_bot_angle.ppm");
+	  }
+
+	  t.resume();
+
+	  // Left
+	  internal::single_left_dmax_ratio_aligned_functor<L>
+	    lfunctor(input_clo, components, dmax, min_angle, max_angle, anchor::Bottom);
+	  bot_left = primitive::link::compute(lfunctor, anchor::Bottom);
+	  t.stop();
+
+	  if (internal::_debug_)
+	  {
+	    io::ppm::save(lfunctor.debug_, "left_bot.ppm");
+	    io::ppm::save(lfunctor.debug_angle_, "left_bot_angle.ppm");
+	  }
+
+	  if (internal::_debug_)
+	  {
+	    mln_ch_value(I, value::rgb8) output = duplicate(functor.debug_);
+	    data::paste((lfunctor.debug_ | (pw::value(lfunctor.debug_) != pw::cst(literal::black))) | (pw::value(lfunctor.debug_) != pw::cst(literal::white)), output);
+
+	    io::ppm::save(output, "left_right_bot.ppm");
+	  }
+	}
+
+
+	t_ = t;
+	std::cout << "links - " << t_ << std::endl;
+
+
+	t.restart();
+	std::cout << "group - top" << std::endl;
+	object_groups<L>
+	  top_groups = primitive::group::from_double_link_any(top_left, top_right);
+	std::cout << "group - bot" << std::endl;
+	object_groups<L>
+	  bot_groups = primitive::group::from_double_link_any(bot_left, bot_right);
+	t_ = t;
+	std::cout << "group - " << t_ << std::endl;
+
+	t.restart();
+	util::array<accu::shape::bbox<point2d> >
+	  btop_accu(top_groups.nelements()),
+	  bbot_accu(bot_groups.nelements());
+
+
+	for_all_groups(c, top_groups)
+	{
+	  btop_accu(top_groups(c)).take(components(c).bbox());
+	  bbot_accu(bot_groups(c)).take(components(c).bbox());
+	}
+	t_ = t;
+	std::cout << "groups to group bboxes - " << t_ << std::endl;
+
+
+
+	if (internal::_debug_)
+	{
+
+	  mln_ch_value(I, value::rgb8)
+	    wo_filtering = data::convert(value::rgb8(), input);
+
+	  for_all_comp_data(d, btop_accu)
+	  {
+	    if (btop_accu(d).is_valid())
+	    {
+	      mln::draw::line(wo_filtering,
+			      btop_accu(d).to_result().pmin(),
+			      point2d(btop_accu(d).to_result().pmin().row(),
+				      btop_accu(d).to_result().pmax().col()),
+			      literal::green);
+
+	    }
+	  }
+
+	  for_all_comp_data(d, bbot_accu)
+	  {
+	    if (bbot_accu(d).is_valid())
+	    {
+	      mln::draw::line(wo_filtering,
+			      point2d(bbot_accu(d).to_result().pmax().row(),
+				      bbot_accu(d).to_result().pmin().col()),
+			      bbot_accu(d).to_result().pmax(),
+			      literal::green);
+	    }
+
+	  }
+	  io::ppm::save(wo_filtering, "wo_filtering.ppm");
+	}
+
+
+	t.restart();
+	top_groups = filter::object_groups_small(top_groups, min_card);
+	bot_groups = filter::object_groups_small(bot_groups, min_card);
+	t_ = t;
+	std::cout << "small groups - " << t_ << std::endl;
+
+
+
+	t.restart();
+	util::array<accu::shape::bbox<point2d> >
+	  top_accu(top_groups.nelements()),
+	  bot_accu(bot_groups.nelements());
+
+
+	for_all_groups(c, top_groups)
+	{
+	  top_accu(top_groups(c)).take(components(c).bbox());
+	  bot_accu(bot_groups(c)).take(components(c).bbox());
+	}
+	t_ = t;
+	std::cout << "groups to group bboxes - " << t_ << std::endl;
+
+
+
+
+
+
+
+
+	t.restart();
+	mln_concrete(I) separators;
+	initialize(separators, input_clo);
+	data::fill(separators, false);
+	t_ = t;
+	std::cout << "Initialize separators image - " << t_ << std::endl;
+
+	mln_ch_value(I, value::rgb8) both;
+
+	if (internal::_debug_)
+	  both = data::convert(value::rgb8(), input);
+
+
+
+	t.restart();
+	for_all_comp_data(d, top_accu)
+	{
+	  if (top_accu(d).is_valid()  ||  btop_accu(d).is_valid())
+	  {
+	    if (top_accu(d).is_valid())
+	    {
+	      if (internal::_debug_)
+		mln::draw::line(both,
+				top_accu(d).to_result().pmin(),
+				point2d(top_accu(d).to_result().pmin().row(),
+					top_accu(d).to_result().pmax().col()),
+				literal::green);
+
+	      mln::draw::line(separators,
+			      top_accu(d).to_result().pmin(),
+			      point2d(top_accu(d).to_result().pmin().row(),
+				      top_accu(d).to_result().pmax().col()),
+			      true);
+	    }
+	    else
+	      if (internal::_debug_ && btop_accu(d).is_valid())
+		mln::draw::line(both,
+				btop_accu(d).to_result().pmin(),
+				point2d(btop_accu(d).to_result().pmin().row(),
+					btop_accu(d).to_result().pmax().col()),
+				literal::yellow);
+
+	  }
+	  if (bot_accu(d).is_valid() ||  bbot_accu(d).is_valid())
+	  {
+	    if (bot_accu(d).is_valid())
+	    {
+	      if (internal::_debug_)
+		mln::draw::line(both,
+				point2d(bot_accu(d).to_result().pmax().row(),
+					bot_accu(d).to_result().pmin().col()),
+				bot_accu(d).to_result().pmax(),
+				literal::green);
+
+	      mln::draw::line(separators,
+			      point2d(bot_accu(d).to_result().pmax().row(),
+				      bot_accu(d).to_result().pmin().col()),
+			      bot_accu(d).to_result().pmax(),
+			      true);
+	    }
+	    else
+	      if (internal::_debug_ && bbot_accu(d).is_valid())
+		mln::draw::line(both,
+				point2d(bbot_accu(d).to_result().pmax().row(),
+					bbot_accu(d).to_result().pmin().col()),
+				bbot_accu(d).to_result().pmax(),
+				literal::yellow);
+	  }
+
+	}
+	t_ = t;
+	std::cout << "Drawing output image - " << t_ << std::endl;
+
+
+	if (internal::_debug_)
+	{
+	  io::ppm::save(both, "both.ppm");
+	  io::pbm::save(separators, "separators.pbm");
+	}
+
+
+	// Hit or miss
+	{
+	  if (internal::_debug_)
+	  {
+	    mln_concrete(I) input_with_seps = duplicate(input_clo);
+	    data::paste(separators | pw::value(separators), input_with_seps);
+
+	    io::pbm::save(input_with_seps, "input_with_seps.pbm");
+	  }
+
+	  t.restart();
+	  unsigned length = 25;
+
+	  dpoint2d
+	    dp1(-21, 0),
+	    dp2( 21, 0);
+
+	  // Adjusting extension.
+	  t.restart();
+	  extension::adjust_fill(input_clo, length / 2, 0);
+
+	  accu::count_value<bool> accu(true);
+	  typedef mln_ch_value(I,unsigned) J;
+
+	  J tmp = accu::transform_line(accu, input_clo, length, 1);
+	  t_ = t;
+	  std::cout << "* accu::transform_line - " << t_ << std::endl;
+
+	  if (internal::_debug_)
+	    io::pgm::save(data::convert(value::int_u8(), tmp), "tmp.pgm");
+
+
+	  t.restart();
+	  value::int_u8 nlabels;
+	  mln_ch_value(I,value::int_u8)
+	    sep_lbl = labeling::value(separators, true, c8(), nlabels);
+	  t_ = t;
+	  std::cout << "* labeling seps - " << t_ << std::endl;
+
+
+	  t.restart();
+
+	  util::array<bool> relbl(unsigned(nlabels) + 1, true);
+	  relbl(0) = false;
+
+	  unsigned invalid_ratio = unsigned(length * 0.30f);
+
+	  mln_piter(I) p(separators.domain());
+	  for_all(p)
+	    if (separators(p))
+	    {
+	      unsigned lbl = sep_lbl(p);
+
+	      unsigned
+		top_count = tmp(p + dp1),
+		bot_count = tmp(p + dp2);
+
+	      // This site is wrapped between two lines of text so we don't
+	      // want it.
+	      if (top_count >= invalid_ratio + 1
+		  && bot_count >= invalid_ratio + 1)
+	      {
+		relbl(lbl) = false;
+	      }
+	    }
+
+	  t_ = t;
+	  std::cout << "* reading data - " << t_ << std::endl;
+
+	  t.restart();
+	  labeling::relabel_inplace(sep_lbl, nlabels, relbl);
+	  t_ = t;
+	  std::cout << "* relabel_inplace - " << t_ << std::endl;
+
+	  mln_concrete(I) output = data::convert(bool(), sep_lbl);
+
+	  if (internal::_debug_)
+	  {
+	    io::pbm::save(output, "separators_hom.pbm");
+	    io::pbm::save(separators, "separators_filtered.pbm");
+	  }
+
+	  t.restart();
+	  value::int_u16 ncomps;
+	  component_set<L> comps = primitive::extract::components(output, c8(), ncomps);
+	  mln_ch_value(I, value::rgb8) both;
+
+	  both = data::convert(value::rgb8(), input);
+
+	  // Needed since the rotated image origin is (0,0). Rotation does
+	  // not preserve rotated coordinates.
+	  dpoint2d dp(input.domain().pcenter() - input_clo.domain().pcenter());
+
+	  for_all_comps(c, comps)
+	  {
+	    box2d b = geom::rotate(comps(c).bbox(), -90, input_clo.domain().pcenter());
+	    mln::draw::line(both,
+			    b.pmin() + dp,
+			    b.pmax() + dp,
+			    literal::green);
+	  }
+	  t_ = t;
+	  std::cout << "Output image - " << t_ << std::endl;
+	  gt.stop();
+	  t_ = gt;
+	  std::cout << "Total time: " << t_ << std::endl;
+
+	  return scribo::preprocessing::rotate_90(output, true);
+	}
+      }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+    } // end of namespace scribo::primitive::extract
+
+  } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-648-g929109d	scribo/primitive/extract/separators_nonvisible.hh: New routine.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 scribo/ChangeLog                                   |    4 +
 .../primitive/extract/separators_nonvisible.hh     |  912 ++++++++++++++++++++
 2 files changed, 916 insertions(+), 0 deletions(-)
 create mode 100644 scribo/scribo/primitive/extract/separators_nonvisible.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index dd11567..9c65829 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
 2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/primitive/extract/separators_nonvisible.hh: New routine.
+
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	Import rgb8 to rgbn conversion function from Yann's sandbox.
 
 	* mln/fun/v2v/rgb8_to_rgbn.hh: New.
diff --git a/scribo/scribo/primitive/extract/separators_nonvisible.hh b/scribo/scribo/primitive/extract/separators_nonvisible.hh
new file mode 100644
index 0000000..460d10e
--- /dev/null
+++ b/scribo/scribo/primitive/extract/separators_nonvisible.hh
@@ -0,0 +1,912 @@
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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.
+
+/// \file
+///
+/// \brief Find non visible separators (whitespaces)
+///
+/// \fixme To be cleaned up
+
+#ifndef SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
+# define SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
+
+#include <mln/core/concept/image.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/pw/all.hh>
+
+#include <mln/draw/line.hh>
+
+#include <mln/data/wrap.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/convert.hh>
+
+
+#include <mln/labeling/colorize.hh>
+#include <mln/labeling/relabel.hh>
+#include <mln/labeling/blobs.hh>
+
+#include <mln/morpho/closing/structural.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/opening/structural.hh>
+#include <mln/win/rectangle2d.hh>
+#include <mln/win/vline2d.hh>
+
+#include <mln/logical/not.hh>
+#include <mln/io/pbm/all.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/value/label_16.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/draw/box_plain.hh>
+
+#include <mln/transform/influence_zone_geodesic.hh>
+
+#include <mln/data/stretch.hh>
+
+#include <mln/util/timer.hh>
+
+#include <mln/norm/l1.hh>
+
+#include <scribo/core/object_groups.hh>
+#include <scribo/core/component_set.hh>
+#include <scribo/primitive/extract/components.hh>
+
+#include <scribo/primitive/extract/lines_h_pattern.hh>
+#include <scribo/primitive/remove/separators.hh>
+
+#include <scribo/preprocessing/denoise_fg.hh>
+#include <scribo/preprocessing/rotate_90.hh>
+
+#include <scribo/primitive/link/internal/dmax_default.hh>
+
+#include <scribo/primitive/link/with_single_right_link_dmax_ratio.hh>
+#include <scribo/primitive/link/with_single_right_link_dmax_ratio_aligned.hh>
+
+#include <scribo/primitive/group/from_double_link_any.hh>
+
+#include <scribo/filter/object_links_top_aligned.hh>
+#include <scribo/filter/object_groups_small.hh>
+#include <scribo/filter/object_links_bottom_aligned.hh>
+#include <scribo/debug/save_linked_bboxes_image.hh>
+#include <scribo/debug/decision_image.hh>
+
+
+
+
+
+namespace scribo
+{
+
+  namespace primitive
+  {
+
+    namespace extract
+    {
+
+      using namespace mln;
+
+
+      /// \brief Find non visible separators (whitespaces)
+      //
+      template <typename I>
+      mln_concrete(I)
+      separators_nonvisible(const Image<I>& in_);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+      namespace internal
+      {
+
+	// Enable debug.
+	bool _debug_;
+
+
+	template <typename L>
+	void filter_bad_groups(object_groups<L>& top_groups,
+			       object_groups<L>& bot_groups)
+	{
+	  const component_set<L>& comps = top_groups.components();
+	  const L& lbl = comps.labeled_image();
+
+	  for_all_groups(c, top_groups)
+	  {
+	    box2d b = comps(c).bbox();
+	    b.enlarge(0, comps(c).bbox().height());
+	    b.crop_wrt(lbl.domain());
+
+	    typedef mln_value(L) V;
+
+	    const V* top_ptr = & lbl(b.pmin());
+	    const V* bot_ptr = & lbl(point2d(b.pmax().row(), b.pmin().col()));
+
+	    unsigned ntop = 0, nbot = 0;
+	    for (unsigned n = 0; n < b.width(); ++n)
+	    {
+	      if (*top_ptr)
+		++ntop;
+	      if (*bot_ptr)
+		++nbot;
+	    }
+
+	    if (ntop / b.width() > 0.50f)
+	      top_groups(c) = c;
+
+	    if (nbot / b.width() > 0.50f)
+	      bot_groups(c) = c;
+	  }
+
+	}
+
+
+	template <typename L>
+	mln_site(L)
+	my_anchors(const component_set<L>& comps,
+		   unsigned current_object,
+		   anchor::Type anchor)
+	{
+	  mln_site(L) sp;// = comps(current_object).bbox().pcenter();
+
+	  unsigned h = comps(current_object).bbox().height();
+
+	  switch (anchor)
+	  {
+	    default:
+	      return sp;
+
+
+	      // Bounding box top center
+	    case anchor::Top: // FIXME: rename as TopLeft
+	      sp.col() = comps(current_object).bbox().pmin().col();
+	      sp.row() = comps(current_object).bbox().pmin().row()
+		+ math::min(2u, (h + 1) / 2 - 1);
+	      break;
+
+
+	      // Bounding box bottom center
+	    case anchor::Bottom: // FIXME: rename as BottomLeft
+	      sp.col() = comps(current_object).bbox().pmax().col();
+	      sp.row() = comps(current_object).bbox().pmax().row()
+		- math::min(2u, (h + 1) / 2 - 1);
+	      break;
+	  }
+
+	  return sp;
+	}
+
+
+
+	using namespace primitive::link::internal;
+
+	template <typename L, typename E>
+	class single_dmax_ratio_aligned_functor_base
+	  : public link_single_dmax_ratio_base<L, dmax_default, E>
+	{
+	  typedef link_single_dmax_ratio_base<L, dmax_default, E> super_;
+
+	public:
+	  typedef mln_site(L) P;
+
+	  single_dmax_ratio_aligned_functor_base(
+	    const mln_ch_value(L,bool)& input,
+	    const component_set<L>& components,
+	    unsigned dmax,
+	    float min_angle,
+	    float max_angle,
+	    anchor::Type anchor_)
+	    : super_(components,
+		     anchor::Horizontal,
+		     dmax_default(dmax)),
+	      anchor(anchor_),
+	      debug_(data::convert(value::rgb8(), input)),
+	      debug_angle_(data::convert(value::rgb8(), input))
+	  {
+	    min_alpha_rad = (min_angle / 180.0f) * math::pi;
+	    max_alpha_rad = (max_angle / 180.0f) * math::pi;
+	  }
+
+	  void compute_next_site_(P& p)
+	  {
+	    ++p.col();
+	  }
+
+	  void compute_next_site_f_(unsigned& p)
+	  {
+	    ++p;
+	  }
+
+
+	  mln_site(L)
+	  start_point_(unsigned current_object, anchor::Type anchor)
+	  {
+	    return my_anchors(this->components_, current_object, anchor);
+	  }
+
+
+	  inline
+	  bool
+	  valid_link_(unsigned current_object,
+		      const P& start_point,
+		      const P& p)
+	  {
+	    if (!super_::valid_link_(current_object, start_point, p))
+	      return false;
+
+	    box<P> b = this->components_(current_object).bbox();
+
+	    // Distance between the two components.
+	    float dist;
+
+	    // current object is on the left.
+	    if (p[this->direction_] > b.pmax()[this->direction_])
+	      dist = math::abs(p[this->direction_] - b.pmax()[this->direction_]);
+	    // current object is on the right.
+	    else
+	      dist = math::abs(p[this->direction_] - b.pmin()[this->direction_]);
+
+
+	    int ldist = this->components_(current_object).bbox().width();
+
+	    // Components are really close, so the angle is more permissive.
+	    if (dist < 3 * ldist)
+	    {
+	      return
+		filter::internal::component_aligned_rad(this->components_,
+							current_object,
+							this->labeled_image_(p),
+							anchor,
+							max_alpha_rad);
+	    }
+
+
+	    // Components are really far, so the angle is less permissive.
+	    return
+	      filter::internal::component_aligned_rad(this->components_,
+						      current_object,
+						      this->labeled_image_(p),
+						      anchor,
+						      min_alpha_rad);
+	  }
+
+	  void validate_link_(unsigned current_object,
+			      const P& start_point,
+			      const P& p,
+			      anchor::Type anchor)
+	  {
+	    super_::validate_link_(current_object, start_point, p, anchor);
+
+	    if (_debug_)
+	    {
+	      mln_site(L)
+		p1 = my_anchors(this->components_, current_object, anchor),
+		p2 = my_anchors(this->components_, this->labeled_image_(p),
+				     anchor);
+	      mln::draw::line(debug_, p1, p2, literal::green);
+
+
+	      float
+		angle = filter::internal::alignment_angle(this->components_,
+							  current_object,
+							  this->labeled_image_(p),
+							  anchor);
+	      angle = (angle * 180.0f) / math::pi;
+	      angle = angle * 20.0f + 1.0f;
+	      mln::draw::line(debug_angle_, p1, p2,
+			      value::rgb8(angle, angle, angle));
+	    }
+	  }
+
+	  void invalidate_link_(unsigned current_object,
+				const P& start_point,
+				const P& p,
+				anchor::Type anchor)
+	  {
+	    super_::invalidate_link_(current_object, start_point, p, anchor);
+
+	    if (_debug_)
+	    {
+	      if (this->labeled_image_.domain().has(p) && this->labeled_image_(p) != 0)
+	      {
+		mln_site(L)
+		  p1 = my_anchors(this->components_, current_object, anchor),
+		  p2 = my_anchors(this->components_, this->labeled_image_(p),
+				       anchor);
+		if (this->labeled_image_.domain().has(p2) && norm::l1_distance(p1.to_vec(), p2.to_vec()) < 300)
+		{
+		  mln::draw::line(debug_, p1, p2, literal::red);
+		}
+
+
+		float
+		  angle = filter::internal::alignment_angle(this->components_,
+							    current_object,
+							    this->labeled_image_(p),
+							    anchor);
+		angle = (angle * 180.0f) / math::pi;
+		angle = angle * 20.0f + 1.0f;
+		mln::draw::line(debug_angle_, p1, p2,
+				value::rgb8(angle, angle, angle));
+	      }
+	    }
+	  }
+
+
+	  float min_alpha_rad;
+	  float max_alpha_rad;
+	  anchor::Type anchor;
+
+
+	  mln_ch_value(L, value::rgb8) debug_;
+	  mln_ch_value(L, value::rgb8) debug_angle_;
+	};
+
+
+	template <typename L>
+	class single_right_dmax_ratio_aligned_functor
+	  : public single_dmax_ratio_aligned_functor_base<L, single_right_dmax_ratio_aligned_functor<L> >
+	{
+	  typedef single_right_dmax_ratio_aligned_functor<L> self_t;
+	  typedef single_dmax_ratio_aligned_functor_base<L, self_t> super_;
+
+	public:
+	  typedef mln_site(L) P;
+
+	  single_right_dmax_ratio_aligned_functor(
+	    const mln_ch_value(L, bool)& input,
+	    const component_set<L>& components,
+	    unsigned dmax,
+	    float min_angle,
+	    float max_angle,
+	    anchor::Type anchor)
+	    : super_(input, components, dmax, min_angle, max_angle, anchor)
+	  {
+	  }
+
+	  void compute_next_site_(P& p)
+	  {
+	    ++p.col();
+	  }
+
+	  void compute_next_site_f_(unsigned& p)
+	  {
+	    ++p;
+	  }
+
+	};
+
+
+	template <typename L>
+	class single_left_dmax_ratio_aligned_functor
+	  : public single_dmax_ratio_aligned_functor_base<L, single_left_dmax_ratio_aligned_functor<L> >
+	{
+	  typedef single_left_dmax_ratio_aligned_functor<L> self_t;
+	  typedef single_dmax_ratio_aligned_functor_base<L, self_t> super_;
+
+	public:
+	  typedef mln_site(L) P;
+
+	  single_left_dmax_ratio_aligned_functor(
+	    const mln_ch_value(L, bool)& input,
+	    const component_set<L>& components,
+	    unsigned dmax,
+	    float min_angle,
+	    float max_angle,
+	    anchor::Type anchor)
+	    : super_(input, components, dmax, min_angle, max_angle, anchor)
+	  {
+	  }
+
+	  void compute_next_site_(P& p)
+	  {
+	    --p.col();
+	  }
+
+	  void compute_next_site_f_(unsigned& p)
+	  {
+	    --p;
+	  }
+
+
+	};
+
+      } // end of namespace scribo::primitive::extract::internal
+
+
+
+
+      // FACADE
+
+      template <typename I>
+      mln_concrete(I)
+      separators_nonvisible(const Image<I>& in_)
+      {
+	const I& in = exact(in_);
+	mln_precondition(in.is_valid());
+	typedef mln_value(I) Vi;
+	mlc_is(Vi,bool)::check();
+
+	internal::_debug_ = false;
+	unsigned
+	  min_angle = 3,
+	  max_angle = 5,
+	  min_card = 3;
+
+	util::timer t;
+	util::timer gt;
+
+	// Load (OK)
+	t.start();
+	float t_ = t;
+	std::cout << "Image loaded - " << t_ << std::endl;
+
+	gt.start();
+
+
+	// Remove horizontal lines.
+	t.restart();
+
+	mln_concrete(I) hlines = primitive::extract::lines_h_pattern(in, 50, 3);
+	mln_concrete(I) input = primitive::remove::separators(in, hlines);
+
+	t_ = t;
+	std::cout << "Horizontal lines removed - " << t_ << std::endl;
+
+
+	// Closing structural - Connect characters.
+	t.restart();
+
+	win::hline2d vl(17);
+	mln_concrete(I) input_clo = morpho::closing::structural(input, vl);
+
+//  input_clo = scribo::preprocessing::rotate_90(input_clo, true);
+
+	t_ = t;
+	std::cout << "closing_structural - " << t_ << std::endl;
+
+	if (internal::_debug_)
+	{
+	  // Restore input orientation.
+	  input = scribo::preprocessing::rotate_90(input, false);
+
+	  io::pbm::save(input_clo, "input_clo.pbm");
+	}
+
+	// Rotate (OK)
+	t.restart();
+	input_clo = scribo::preprocessing::rotate_90(input_clo, false);
+	t_ = t;
+	std::cout << "rotate_90 - " << t_ << std::endl;
+
+
+
+	/// Finding components.
+	typedef value::int_u16 V;
+	typedef mln_ch_value(I,V) L;
+
+	t.restart();
+	V ncomponents;
+	component_set<L>
+	  components = scribo::primitive::extract::components(input_clo, c8(),
+							      ncomponents);
+	t_ = t;
+	std::cout << "extract::components - " << t_ << std::endl;
+
+	if (internal::_debug_)
+	  io::pgm::save(data::convert(value::int_u8(), components.labeled_image()),
+			"lbl.pgm");
+
+
+	unsigned dmax = 5;
+
+	t.restart();
+	object_links<L> top_right, bot_right;
+
+	object_links<L> top_left, bot_left;
+
+
+	// Top
+	{
+	  // Right
+	  internal::single_right_dmax_ratio_aligned_functor<L>
+	    functor(input_clo, components, dmax, min_angle, max_angle, anchor::Top);
+//    top_right = primitive::link::impl::compute_fastest(functor, anchor::Top);
+	  top_right = primitive::link::compute(functor, anchor::Top);
+
+	  t.stop();
+
+
+	  if (internal::_debug_)
+	  {
+	    io::ppm::save(functor.debug_, "right_top.ppm");
+	    io::ppm::save(functor.debug_angle_, "right_top_angle.ppm");
+	  }
+
+	  t.resume();
+
+	  // Left
+	  internal::single_left_dmax_ratio_aligned_functor<L>
+	    lfunctor(input_clo, components, dmax, min_angle, max_angle, anchor::Top);
+	  top_left = primitive::link::compute(lfunctor, anchor::Top);
+
+
+	  t.stop();
+
+	  if (internal::_debug_)
+	  {
+	    io::ppm::save(lfunctor.debug_, "left_top.ppm");
+	    io::ppm::save(lfunctor.debug_angle_, "left_top_angle.ppm");
+
+	    mln_ch_value(I, value::rgb8) output = duplicate(functor.debug_);
+	    data::paste((lfunctor.debug_ | (pw::value(lfunctor.debug_) != pw::cst(literal::black))) | (pw::value(lfunctor.debug_) != pw::cst(literal::white)), output);
+
+	    io::ppm::save(output, "left_right_top.ppm");
+	  }
+
+	  t.resume();
+	}
+
+
+	// Bottom
+	{
+	  // Right
+	  internal::single_right_dmax_ratio_aligned_functor<L>
+	    functor(input_clo, components, dmax, min_angle, max_angle, anchor::Bottom);
+	  bot_right = primitive::link::compute(functor, anchor::Bottom);
+	  t.stop();
+
+	  if (internal::_debug_)
+	  {
+	    io::ppm::save(functor.debug_, "right_bot.ppm");
+	    io::ppm::save(functor.debug_angle_, "right_bot_angle.ppm");
+	  }
+
+	  t.resume();
+
+	  // Left
+	  internal::single_left_dmax_ratio_aligned_functor<L>
+	    lfunctor(input_clo, components, dmax, min_angle, max_angle, anchor::Bottom);
+	  bot_left = primitive::link::compute(lfunctor, anchor::Bottom);
+	  t.stop();
+
+	  if (internal::_debug_)
+	  {
+	    io::ppm::save(lfunctor.debug_, "left_bot.ppm");
+	    io::ppm::save(lfunctor.debug_angle_, "left_bot_angle.ppm");
+	  }
+
+	  if (internal::_debug_)
+	  {
+	    mln_ch_value(I, value::rgb8) output = duplicate(functor.debug_);
+	    data::paste((lfunctor.debug_ | (pw::value(lfunctor.debug_) != pw::cst(literal::black))) | (pw::value(lfunctor.debug_) != pw::cst(literal::white)), output);
+
+	    io::ppm::save(output, "left_right_bot.ppm");
+	  }
+	}
+
+
+	t_ = t;
+	std::cout << "links - " << t_ << std::endl;
+
+
+	t.restart();
+	std::cout << "group - top" << std::endl;
+	object_groups<L>
+	  top_groups = primitive::group::from_double_link_any(top_left, top_right);
+	std::cout << "group - bot" << std::endl;
+	object_groups<L>
+	  bot_groups = primitive::group::from_double_link_any(bot_left, bot_right);
+	t_ = t;
+	std::cout << "group - " << t_ << std::endl;
+
+	t.restart();
+	util::array<accu::shape::bbox<point2d> >
+	  btop_accu(top_groups.nelements()),
+	  bbot_accu(bot_groups.nelements());
+
+
+	for_all_groups(c, top_groups)
+	{
+	  btop_accu(top_groups(c)).take(components(c).bbox());
+	  bbot_accu(bot_groups(c)).take(components(c).bbox());
+	}
+	t_ = t;
+	std::cout << "groups to group bboxes - " << t_ << std::endl;
+
+
+
+	if (internal::_debug_)
+	{
+
+	  mln_ch_value(I, value::rgb8)
+	    wo_filtering = data::convert(value::rgb8(), input);
+
+	  for_all_comp_data(d, btop_accu)
+	  {
+	    if (btop_accu(d).is_valid())
+	    {
+	      mln::draw::line(wo_filtering,
+			      btop_accu(d).to_result().pmin(),
+			      point2d(btop_accu(d).to_result().pmin().row(),
+				      btop_accu(d).to_result().pmax().col()),
+			      literal::green);
+
+	    }
+	  }
+
+	  for_all_comp_data(d, bbot_accu)
+	  {
+	    if (bbot_accu(d).is_valid())
+	    {
+	      mln::draw::line(wo_filtering,
+			      point2d(bbot_accu(d).to_result().pmax().row(),
+				      bbot_accu(d).to_result().pmin().col()),
+			      bbot_accu(d).to_result().pmax(),
+			      literal::green);
+	    }
+
+	  }
+	  io::ppm::save(wo_filtering, "wo_filtering.ppm");
+	}
+
+
+	t.restart();
+	top_groups = filter::object_groups_small(top_groups, min_card);
+	bot_groups = filter::object_groups_small(bot_groups, min_card);
+	t_ = t;
+	std::cout << "small groups - " << t_ << std::endl;
+
+
+
+	t.restart();
+	util::array<accu::shape::bbox<point2d> >
+	  top_accu(top_groups.nelements()),
+	  bot_accu(bot_groups.nelements());
+
+
+	for_all_groups(c, top_groups)
+	{
+	  top_accu(top_groups(c)).take(components(c).bbox());
+	  bot_accu(bot_groups(c)).take(components(c).bbox());
+	}
+	t_ = t;
+	std::cout << "groups to group bboxes - " << t_ << std::endl;
+
+
+
+
+
+
+
+
+	t.restart();
+	mln_concrete(I) separators;
+	initialize(separators, input_clo);
+	data::fill(separators, false);
+	t_ = t;
+	std::cout << "Initialize separators image - " << t_ << std::endl;
+
+	mln_ch_value(I, value::rgb8) both;
+
+	if (internal::_debug_)
+	  both = data::convert(value::rgb8(), input);
+
+
+
+	t.restart();
+	for_all_comp_data(d, top_accu)
+	{
+	  if (top_accu(d).is_valid()  ||  btop_accu(d).is_valid())
+	  {
+	    if (top_accu(d).is_valid())
+	    {
+	      if (internal::_debug_)
+		mln::draw::line(both,
+				top_accu(d).to_result().pmin(),
+				point2d(top_accu(d).to_result().pmin().row(),
+					top_accu(d).to_result().pmax().col()),
+				literal::green);
+
+	      mln::draw::line(separators,
+			      top_accu(d).to_result().pmin(),
+			      point2d(top_accu(d).to_result().pmin().row(),
+				      top_accu(d).to_result().pmax().col()),
+			      true);
+	    }
+	    else
+	      if (internal::_debug_ && btop_accu(d).is_valid())
+		mln::draw::line(both,
+				btop_accu(d).to_result().pmin(),
+				point2d(btop_accu(d).to_result().pmin().row(),
+					btop_accu(d).to_result().pmax().col()),
+				literal::yellow);
+
+	  }
+	  if (bot_accu(d).is_valid() ||  bbot_accu(d).is_valid())
+	  {
+	    if (bot_accu(d).is_valid())
+	    {
+	      if (internal::_debug_)
+		mln::draw::line(both,
+				point2d(bot_accu(d).to_result().pmax().row(),
+					bot_accu(d).to_result().pmin().col()),
+				bot_accu(d).to_result().pmax(),
+				literal::green);
+
+	      mln::draw::line(separators,
+			      point2d(bot_accu(d).to_result().pmax().row(),
+				      bot_accu(d).to_result().pmin().col()),
+			      bot_accu(d).to_result().pmax(),
+			      true);
+	    }
+	    else
+	      if (internal::_debug_ && bbot_accu(d).is_valid())
+		mln::draw::line(both,
+				point2d(bbot_accu(d).to_result().pmax().row(),
+					bbot_accu(d).to_result().pmin().col()),
+				bbot_accu(d).to_result().pmax(),
+				literal::yellow);
+	  }
+
+	}
+	t_ = t;
+	std::cout << "Drawing output image - " << t_ << std::endl;
+
+
+	if (internal::_debug_)
+	{
+	  io::ppm::save(both, "both.ppm");
+	  io::pbm::save(separators, "separators.pbm");
+	}
+
+
+	// Hit or miss
+	{
+	  if (internal::_debug_)
+	  {
+	    mln_concrete(I) input_with_seps = duplicate(input_clo);
+	    data::paste(separators | pw::value(separators), input_with_seps);
+
+	    io::pbm::save(input_with_seps, "input_with_seps.pbm");
+	  }
+
+	  t.restart();
+	  unsigned length = 25;
+
+	  dpoint2d
+	    dp1(-21, 0),
+	    dp2( 21, 0);
+
+	  // Adjusting extension.
+	  t.restart();
+	  extension::adjust_fill(input_clo, length / 2, 0);
+
+	  accu::count_value<bool> accu(true);
+	  typedef mln_ch_value(I,unsigned) J;
+
+	  J tmp = accu::transform_line(accu, input_clo, length, 1);
+	  t_ = t;
+	  std::cout << "* accu::transform_line - " << t_ << std::endl;
+
+	  if (internal::_debug_)
+	    io::pgm::save(data::convert(value::int_u8(), tmp), "tmp.pgm");
+
+
+	  t.restart();
+	  value::int_u8 nlabels;
+	  mln_ch_value(I,value::int_u8)
+	    sep_lbl = labeling::value(separators, true, c8(), nlabels);
+	  t_ = t;
+	  std::cout << "* labeling seps - " << t_ << std::endl;
+
+
+	  t.restart();
+
+	  util::array<bool> relbl(unsigned(nlabels) + 1, true);
+	  relbl(0) = false;
+
+	  unsigned invalid_ratio = unsigned(length * 0.30f);
+
+	  mln_piter(I) p(separators.domain());
+	  for_all(p)
+	    if (separators(p))
+	    {
+	      unsigned lbl = sep_lbl(p);
+
+	      unsigned
+		top_count = tmp(p + dp1),
+		bot_count = tmp(p + dp2);
+
+	      // This site is wrapped between two lines of text so we don't
+	      // want it.
+	      if (top_count >= invalid_ratio + 1
+		  && bot_count >= invalid_ratio + 1)
+	      {
+		relbl(lbl) = false;
+	      }
+	    }
+
+	  t_ = t;
+	  std::cout << "* reading data - " << t_ << std::endl;
+
+	  t.restart();
+	  labeling::relabel_inplace(sep_lbl, nlabels, relbl);
+	  t_ = t;
+	  std::cout << "* relabel_inplace - " << t_ << std::endl;
+
+	  mln_concrete(I) output = data::convert(bool(), sep_lbl);
+
+	  if (internal::_debug_)
+	  {
+	    io::pbm::save(output, "separators_hom.pbm");
+	    io::pbm::save(separators, "separators_filtered.pbm");
+	  }
+
+	  t.restart();
+	  value::int_u16 ncomps;
+	  component_set<L> comps = primitive::extract::components(output, c8(), ncomps);
+	  mln_ch_value(I, value::rgb8) both;
+
+	  both = data::convert(value::rgb8(), input);
+
+	  // Needed since the rotated image origin is (0,0). Rotation does
+	  // not preserve rotated coordinates.
+	  dpoint2d dp(input.domain().pcenter() - input_clo.domain().pcenter());
+
+	  for_all_comps(c, comps)
+	  {
+	    box2d b = geom::rotate(comps(c).bbox(), -90, input_clo.domain().pcenter());
+	    mln::draw::line(both,
+			    b.pmin() + dp,
+			    b.pmax() + dp,
+			    literal::green);
+	  }
+	  t_ = t;
+	  std::cout << "Output image - " << t_ << std::endl;
+	  gt.stop();
+	  t_ = gt;
+	  std::cout << "Total time: " << t_ << std::endl;
+
+	  return scribo::preprocessing::rotate_90(output, true);
+	}
+      }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+    } // end of namespace scribo::primitive::extract
+
+  } // end of namespace scribo::primitive
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-646-g964a8b8	mln/clustering/kmean_rgb.hh: Import Kmean RGB from Yann's sandbox.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 milena/ChangeLog                                   |    5 +
 .../green => milena}/mln/clustering/kmean_rgb.hh   |  106 ++++++++++----------
 2 files changed, 57 insertions(+), 54 deletions(-)
 copy {scribo/sandbox/green => milena}/mln/clustering/kmean_rgb.hh (93%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index fee653d..66d79f3 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,8 @@
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
+	* mln/clustering/kmean_rgb.hh: Import Kmean RGB from Yann's
+	sandbox.
+
 2010-06-21  Yann Jacquelet  <jacquelet(a)lrde.epita.fr>
 
 	Fix the way to convert unsigned to float.
diff --git a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh b/milena/mln/clustering/kmean_rgb.hh
similarity index 93%
copy from scribo/sandbox/green/mln/clustering/kmean_rgb.hh
copy to milena/mln/clustering/kmean_rgb.hh
index 544066b..daf6499 100644
--- a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh
+++ b/milena/mln/clustering/kmean_rgb.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
 //
 // This file is part of Olena.
 //
@@ -167,7 +167,7 @@ namespace mln
     /// \return an image which represents the pixel classification.
     template <typename T, unsigned n, typename I>
     inline
-    image2d<value::label_8>
+    mln_ch_value(I,value::label_8)
     kmean_rgb(const Image<I>& point,
 	      const unsigned  k_center,
 	      const unsigned  watch_dog,
@@ -544,16 +544,22 @@ namespace mln
 	}
       };
 
-      template <typename T, unsigned n>
+      template <typename T, unsigned n, typename I>
       inline
-      image2d<value::label_8>
-      kmean_image2d_rgb(const image2d< value::rgb<n> >& point,
-			const unsigned                  k_center,
-			const unsigned                  watch_dog = 10,
-			const unsigned                  n_times   = 10)
+      mln_ch_value(I,value::label_8)
+      kmean_image2d_rgb(const Image<I>& point__,
+			const unsigned  k_center,
+			const unsigned  watch_dog = 10,
+			const unsigned  n_times   = 10)
       {
 	trace::entering("mln::clustering::impl::kmean_image2d_rgb");
-	trace::quiet = true;
+
+	const I& point = exact(point__);
+	typedef mln_value(I) V;
+	mlc_is(V, value::rgb<n>)::check();
+	mlc_bool(mln_site_(I)::dim == 2u)::check();
+	mln_precondition(point.is_valid());
+
 	// BEGIN TYPEDEF
 	typedef value::rgb<8>                      t_rgb;
 	typedef value::label<8>                    t_label;
@@ -564,7 +570,7 @@ namespace mln
 	typedef T                                  t_result1d;
 	typedef algebra::vec<3,T>                  t_result3d;
 
-	typedef image2d<t_value>                   t_point_img;
+	typedef I                                  t_point_img;
 	typedef image3d<unsigned>                  t_histo_img;
 	typedef util::array<t_result1d>            t_number_img;
 	typedef util::array<t_result3d>            t_mean_img;
@@ -574,7 +580,7 @@ namespace mln
 	typedef image3d<t_result1d>                t_distance_val;
 	typedef util::array<t_distance_val>        t_distance_img;
 
-	typedef image2d<t_label>                   t_label_dbg;
+	typedef mln_ch_value(I,t_label)            t_label_dbg;
 	typedef image2d<t_rgb>                     t_color_dbg;
 	typedef image2d<t_value>                   t_mean_dbg;
 
@@ -702,18 +708,14 @@ namespace mln
 	  while (_current_launching < _n_times)
 	  {
 	    // BEGIN LAUNCH ONE TIME
-	    trace::quiet = false;
 	    trace::entering("Launch one time");
-	    trace::quiet = true;
 	    {
 	      t_result1d old_variance = mln_max(t_result1d);
 	      _within_variance        = mln_max(t_result1d);
 	      _current_step           = 0;
 
 	      // BEGIN INIT_MEAN
-	      trace::quiet = false;
 	      trace::entering("init mean");
-	      trace::quiet = true;
 	      {
 		t_value_comp0           min_comp0 = mln_min(t_value_comp0);
 		t_value_comp0           max_comp0 = mln_max(t_value_comp0);
@@ -730,16 +732,12 @@ namespace mln
 		  _mean[l.index_()][2]=(rand()%(max_comp2-min_comp2))+min_comp2;
 		}
 	      }
-	      trace::quiet = false;
 	      trace::exiting("init mean");
-	      trace::quiet = true;
 	      // END INIT MEAN
 
 
 	      // UPDATE DISTANCE
-	      trace::quiet = false;
 	      trace::entering("update distance");
-	      trace::quiet = true;
 
 	      for (unsigned i = 0; i < _k_center; ++i)
 	      {
@@ -760,9 +758,7 @@ namespace mln
 		}
 	      }
 
-	      trace::quiet = false;
 	      trace::exiting("update distance");
-	      trace::quiet = true;
 	      // END UPDATE DISTANCE
 
 	      do
@@ -770,9 +766,7 @@ namespace mln
 		old_variance = _within_variance;
 
 		// BEGIN UPDATE GROUP
-		trace::quiet = false;
 		trace::entering("update group");
-		trace::quiet = true;
 		{
 		    mln_piter(t_group_img) rgb(_group.domain());
 
@@ -795,15 +789,11 @@ namespace mln
 		    }
 
 		}
-		trace::quiet = false;
 		trace::exiting("update group");
-		trace::quiet = true;
 		// END UPDATE GROUP
 
 		// BEGIN UPDATE MEAN
-		trace::quiet = false;
 		trace::entering("update mean");
-		trace::quiet = true;
 		{
 		  mln_eiter(t_number_img) en(_number);
 		  mln_eiter(t_mean_img)   em(_mean);
@@ -836,9 +826,7 @@ namespace mln
 		      _mean[l.index_()] /= _number[l.index_()];
 		  }
 		}
-		trace::quiet = false;
 		trace::exiting("update mean");
-		trace::quiet = true;
 		// END UPDATE MEAN
 
 
@@ -847,9 +835,7 @@ namespace mln
 		  break;
 
 		// UPDATE DISTANCE
-		trace::quiet = false;
 		trace::entering("update distance");
-		trace::quiet = true;
 
 		for (unsigned i = 0; i < _k_center; ++i)
 		{
@@ -865,15 +851,11 @@ namespace mln
 		      (diff2_row + diff2_col + diff2_sli);
 		  }
 		}
-		trace::quiet = false;
 		trace::exiting("update distance");
-		trace::quiet = true;
 		// END UPDATE DISTANCE
 
 		// BEGIN UPDATE VARIANCE
-		trace::quiet = false;
 		trace::entering("update variance");
-		trace::quiet = true;
 		{
 		  _within_variance          = literal::zero;
 		  mln_eiter(t_variance_img) l(_variance);
@@ -894,9 +876,7 @@ namespace mln
 		  }
 
 		}
-		trace::quiet = false;
 		trace::exiting("update variance");
-		trace::quiet = true;
 		// END UPDATE VARIANCE
 
 		//update_cnv();
@@ -909,9 +889,7 @@ namespace mln
 	      //finalize_cnv();
 	      //build_all_dbg();
 	    }
-	    trace::quiet = false;
 	    trace::exiting("Launch one time");
-	    trace::quiet = true;
 	    // END LAUNCH ONE TIME
 
 	    if ((_is_number_valid && (_current_step < _watch_dog))||
@@ -962,7 +940,6 @@ namespace mln
 // 	}
 
 	// END BUILD LABEL IMAGE
-	trace::quiet = false;
 	trace::exiting("mln::clustering::impl::kmean_image2d_rgb");
 
 	return _label_dbg;
@@ -982,27 +959,49 @@ namespace mln
     namespace internal
     {
 
-      template <typename T, unsigned n>
+      template <typename T, unsigned n, typename I>
       inline
-      image2d<value::label_8>
-      kmean_rgb_dispatch(const image2d< value::rgb<n> >& img,
-			 const unsigned                  k_center,
-			 const unsigned                  watch_dog,
-			 const unsigned                  n_times)
+      mln_ch_value(I,value::label_8)
+      kmean_rgb_dispatch(const Image<I>& img,
+			 const unsigned  k_center,
+			 const unsigned  watch_dog,
+			 const unsigned  n_times,
+			 const value::rgb<n>&,
+			 const point2d&)
       {
 	return impl::kmean_image2d_rgb<T,n>(img, k_center, watch_dog, n_times);
       }
 
+      template <typename T, unsigned n, typename I, typename V, typename P>
+      inline
+      mln_ch_value(I,value::label_8)
+      kmean_rgb_dispatch(const Image<I>& img,
+			 const unsigned  k_center,
+			 const unsigned  watch_dog,
+			 const unsigned  n_times,
+			 const V&,
+			 const P&)
+      {
+	// No kmean implementation found.
+	mlc_abort(I)::check();
+
+	typedef mln_ch_value(I, value::label_8) output_t;
+	return output_t();
+      }
+
 
       template <typename T, unsigned n, typename I>
       inline
-      image2d< value::label_8>
+      mln_ch_value(I,value::label_8)
       kmean_rgb_dispatch(const Image<I>& img,
 			 const unsigned  k_center,
 			 const unsigned  watch_dog,
 			 const unsigned  n_times)
       {
-	return kmean_rgb_dispatch<T,n>(exact(img),k_center,watch_dog,n_times);
+	typedef mln_value(I) V;
+	typedef mln_site(I) P;
+	return kmean_rgb_dispatch<T,n>(img, k_center, watch_dog,
+				       n_times, V(), P());
       }
 
 
@@ -1015,7 +1014,7 @@ namespace mln
 
     template <typename T, unsigned n, typename I>
     inline
-    image2d<value::label_8>
+    mln_ch_value(I,value::label_8)
     kmean_rgb(const Image<I>& point,
 	      const unsigned  k_center,
 	      const unsigned  watch_dog,
@@ -1023,13 +1022,12 @@ namespace mln
     {
       trace::entering("mln::clustering::kmean_rgb");
 
-      image2d<value::label_8> tmp = internal::kmean_rgb_dispatch<T,n>(point,
-								      k_center,
-								      watch_dog,
-								      n_times);
+      mln_ch_value(I, value::label_8)
+	output = internal::kmean_rgb_dispatch<T,n>(point, k_center,
+						   watch_dog, n_times);
       trace::exiting("mln::clustering::kmean_rgb");
 
-      return tmp;
+      return output;
     }
 
 
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-647-gf6cd71c	mln/clustering/kmean_rgb.hh: Import Kmean RGB from Yann's sandbox.
                        
                        
by Guillaume Lazzara 15 Nov '10
                    by Guillaume Lazzara 15 Nov '10
15 Nov '10
                    
                        ---
 milena/ChangeLog                                   |    5 +
 .../green => milena}/mln/clustering/kmean_rgb.hh   |  106 ++++++++++----------
 2 files changed, 57 insertions(+), 54 deletions(-)
 copy {scribo/sandbox/green => milena}/mln/clustering/kmean_rgb.hh (93%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index fee653d..66d79f3 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,8 @@
+2010-11-15  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
+	* mln/clustering/kmean_rgb.hh: Import Kmean RGB from Yann's
+	sandbox.
+
 2010-06-21  Yann Jacquelet  <jacquelet(a)lrde.epita.fr>
 
 	Fix the way to convert unsigned to float.
diff --git a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh b/milena/mln/clustering/kmean_rgb.hh
similarity index 93%
copy from scribo/sandbox/green/mln/clustering/kmean_rgb.hh
copy to milena/mln/clustering/kmean_rgb.hh
index 544066b..daf6499 100644
--- a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh
+++ b/milena/mln/clustering/kmean_rgb.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
 //
 // This file is part of Olena.
 //
@@ -167,7 +167,7 @@ namespace mln
     /// \return an image which represents the pixel classification.
     template <typename T, unsigned n, typename I>
     inline
-    image2d<value::label_8>
+    mln_ch_value(I,value::label_8)
     kmean_rgb(const Image<I>& point,
 	      const unsigned  k_center,
 	      const unsigned  watch_dog,
@@ -544,16 +544,22 @@ namespace mln
 	}
       };
 
-      template <typename T, unsigned n>
+      template <typename T, unsigned n, typename I>
       inline
-      image2d<value::label_8>
-      kmean_image2d_rgb(const image2d< value::rgb<n> >& point,
-			const unsigned                  k_center,
-			const unsigned                  watch_dog = 10,
-			const unsigned                  n_times   = 10)
+      mln_ch_value(I,value::label_8)
+      kmean_image2d_rgb(const Image<I>& point__,
+			const unsigned  k_center,
+			const unsigned  watch_dog = 10,
+			const unsigned  n_times   = 10)
       {
 	trace::entering("mln::clustering::impl::kmean_image2d_rgb");
-	trace::quiet = true;
+
+	const I& point = exact(point__);
+	typedef mln_value(I) V;
+	mlc_is(V, value::rgb<n>)::check();
+	mlc_bool(mln_site_(I)::dim == 2u)::check();
+	mln_precondition(point.is_valid());
+
 	// BEGIN TYPEDEF
 	typedef value::rgb<8>                      t_rgb;
 	typedef value::label<8>                    t_label;
@@ -564,7 +570,7 @@ namespace mln
 	typedef T                                  t_result1d;
 	typedef algebra::vec<3,T>                  t_result3d;
 
-	typedef image2d<t_value>                   t_point_img;
+	typedef I                                  t_point_img;
 	typedef image3d<unsigned>                  t_histo_img;
 	typedef util::array<t_result1d>            t_number_img;
 	typedef util::array<t_result3d>            t_mean_img;
@@ -574,7 +580,7 @@ namespace mln
 	typedef image3d<t_result1d>                t_distance_val;
 	typedef util::array<t_distance_val>        t_distance_img;
 
-	typedef image2d<t_label>                   t_label_dbg;
+	typedef mln_ch_value(I,t_label)            t_label_dbg;
 	typedef image2d<t_rgb>                     t_color_dbg;
 	typedef image2d<t_value>                   t_mean_dbg;
 
@@ -702,18 +708,14 @@ namespace mln
 	  while (_current_launching < _n_times)
 	  {
 	    // BEGIN LAUNCH ONE TIME
-	    trace::quiet = false;
 	    trace::entering("Launch one time");
-	    trace::quiet = true;
 	    {
 	      t_result1d old_variance = mln_max(t_result1d);
 	      _within_variance        = mln_max(t_result1d);
 	      _current_step           = 0;
 
 	      // BEGIN INIT_MEAN
-	      trace::quiet = false;
 	      trace::entering("init mean");
-	      trace::quiet = true;
 	      {
 		t_value_comp0           min_comp0 = mln_min(t_value_comp0);
 		t_value_comp0           max_comp0 = mln_max(t_value_comp0);
@@ -730,16 +732,12 @@ namespace mln
 		  _mean[l.index_()][2]=(rand()%(max_comp2-min_comp2))+min_comp2;
 		}
 	      }
-	      trace::quiet = false;
 	      trace::exiting("init mean");
-	      trace::quiet = true;
 	      // END INIT MEAN
 
 
 	      // UPDATE DISTANCE
-	      trace::quiet = false;
 	      trace::entering("update distance");
-	      trace::quiet = true;
 
 	      for (unsigned i = 0; i < _k_center; ++i)
 	      {
@@ -760,9 +758,7 @@ namespace mln
 		}
 	      }
 
-	      trace::quiet = false;
 	      trace::exiting("update distance");
-	      trace::quiet = true;
 	      // END UPDATE DISTANCE
 
 	      do
@@ -770,9 +766,7 @@ namespace mln
 		old_variance = _within_variance;
 
 		// BEGIN UPDATE GROUP
-		trace::quiet = false;
 		trace::entering("update group");
-		trace::quiet = true;
 		{
 		    mln_piter(t_group_img) rgb(_group.domain());
 
@@ -795,15 +789,11 @@ namespace mln
 		    }
 
 		}
-		trace::quiet = false;
 		trace::exiting("update group");
-		trace::quiet = true;
 		// END UPDATE GROUP
 
 		// BEGIN UPDATE MEAN
-		trace::quiet = false;
 		trace::entering("update mean");
-		trace::quiet = true;
 		{
 		  mln_eiter(t_number_img) en(_number);
 		  mln_eiter(t_mean_img)   em(_mean);
@@ -836,9 +826,7 @@ namespace mln
 		      _mean[l.index_()] /= _number[l.index_()];
 		  }
 		}
-		trace::quiet = false;
 		trace::exiting("update mean");
-		trace::quiet = true;
 		// END UPDATE MEAN
 
 
@@ -847,9 +835,7 @@ namespace mln
 		  break;
 
 		// UPDATE DISTANCE
-		trace::quiet = false;
 		trace::entering("update distance");
-		trace::quiet = true;
 
 		for (unsigned i = 0; i < _k_center; ++i)
 		{
@@ -865,15 +851,11 @@ namespace mln
 		      (diff2_row + diff2_col + diff2_sli);
 		  }
 		}
-		trace::quiet = false;
 		trace::exiting("update distance");
-		trace::quiet = true;
 		// END UPDATE DISTANCE
 
 		// BEGIN UPDATE VARIANCE
-		trace::quiet = false;
 		trace::entering("update variance");
-		trace::quiet = true;
 		{
 		  _within_variance          = literal::zero;
 		  mln_eiter(t_variance_img) l(_variance);
@@ -894,9 +876,7 @@ namespace mln
 		  }
 
 		}
-		trace::quiet = false;
 		trace::exiting("update variance");
-		trace::quiet = true;
 		// END UPDATE VARIANCE
 
 		//update_cnv();
@@ -909,9 +889,7 @@ namespace mln
 	      //finalize_cnv();
 	      //build_all_dbg();
 	    }
-	    trace::quiet = false;
 	    trace::exiting("Launch one time");
-	    trace::quiet = true;
 	    // END LAUNCH ONE TIME
 
 	    if ((_is_number_valid && (_current_step < _watch_dog))||
@@ -962,7 +940,6 @@ namespace mln
 // 	}
 
 	// END BUILD LABEL IMAGE
-	trace::quiet = false;
 	trace::exiting("mln::clustering::impl::kmean_image2d_rgb");
 
 	return _label_dbg;
@@ -982,27 +959,49 @@ namespace mln
     namespace internal
     {
 
-      template <typename T, unsigned n>
+      template <typename T, unsigned n, typename I>
       inline
-      image2d<value::label_8>
-      kmean_rgb_dispatch(const image2d< value::rgb<n> >& img,
-			 const unsigned                  k_center,
-			 const unsigned                  watch_dog,
-			 const unsigned                  n_times)
+      mln_ch_value(I,value::label_8)
+      kmean_rgb_dispatch(const Image<I>& img,
+			 const unsigned  k_center,
+			 const unsigned  watch_dog,
+			 const unsigned  n_times,
+			 const value::rgb<n>&,
+			 const point2d&)
       {
 	return impl::kmean_image2d_rgb<T,n>(img, k_center, watch_dog, n_times);
       }
 
+      template <typename T, unsigned n, typename I, typename V, typename P>
+      inline
+      mln_ch_value(I,value::label_8)
+      kmean_rgb_dispatch(const Image<I>& img,
+			 const unsigned  k_center,
+			 const unsigned  watch_dog,
+			 const unsigned  n_times,
+			 const V&,
+			 const P&)
+      {
+	// No kmean implementation found.
+	mlc_abort(I)::check();
+
+	typedef mln_ch_value(I, value::label_8) output_t;
+	return output_t();
+      }
+
 
       template <typename T, unsigned n, typename I>
       inline
-      image2d< value::label_8>
+      mln_ch_value(I,value::label_8)
       kmean_rgb_dispatch(const Image<I>& img,
 			 const unsigned  k_center,
 			 const unsigned  watch_dog,
 			 const unsigned  n_times)
       {
-	return kmean_rgb_dispatch<T,n>(exact(img),k_center,watch_dog,n_times);
+	typedef mln_value(I) V;
+	typedef mln_site(I) P;
+	return kmean_rgb_dispatch<T,n>(img, k_center, watch_dog,
+				       n_times, V(), P());
       }
 
 
@@ -1015,7 +1014,7 @@ namespace mln
 
     template <typename T, unsigned n, typename I>
     inline
-    image2d<value::label_8>
+    mln_ch_value(I,value::label_8)
     kmean_rgb(const Image<I>& point,
 	      const unsigned  k_center,
 	      const unsigned  watch_dog,
@@ -1023,13 +1022,12 @@ namespace mln
     {
       trace::entering("mln::clustering::kmean_rgb");
 
-      image2d<value::label_8> tmp = internal::kmean_rgb_dispatch<T,n>(point,
-								      k_center,
-								      watch_dog,
-								      n_times);
+      mln_ch_value(I, value::label_8)
+	output = internal::kmean_rgb_dispatch<T,n>(point, k_center,
+						   watch_dog, n_times);
       trace::exiting("mln::clustering::kmean_rgb");
 
-      return tmp;
+      return output;
     }
 
 
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0