* primitive/extract/lines_h_pattern.hh,
* primitive/extract/lines_v_pattern.hh: Use reconstruction
algorithm.
* primitive/extract/lines_pattern.hh: Add a fast implementation.
---
scribo/ChangeLog | 10 ++
scribo/primitive/extract/lines_h_pattern.hh | 40 ++++--
scribo/primitive/extract/lines_pattern.hh | 227 ++++++++++++++++++++++-----
scribo/primitive/extract/lines_v_pattern.hh | 39 +++--
4 files changed, 250 insertions(+), 66 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index fe1e390..a4e2373 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,15 @@
2010-05-25 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Improve line detection.
+
+ * primitive/extract/lines_h_pattern.hh,
+ * primitive/extract/lines_v_pattern.hh: Use reconstruction
+ algorithm.
+
+ * primitive/extract/lines_pattern.hh: Add a fast implementation.
+
+2010-05-25 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* io/text_boxes/save.hh: New. Save text boxes information.
2010-05-25 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/scribo/primitive/extract/lines_h_pattern.hh
b/scribo/primitive/extract/lines_h_pattern.hh
index 08025a1..0da7900 100644
--- a/scribo/primitive/extract/lines_h_pattern.hh
+++ b/scribo/primitive/extract/lines_h_pattern.hh
@@ -53,15 +53,30 @@ namespace scribo
using namespace mln;
- /// Extract horizontal lines matching a specific pattern.
- ///
- /// \param[in] input A binary image.
- /// \param[in] length The minimum line length.
- /// \param[in] delta Distance between the object pixel and the
- /// background pixel.
- ///
- /// \result An image of horizontal lines.
- //
+ /*! \brief Extract horizontal lines matching a specific pattern.
+
+ \param[in] input A binary image.
+ \param[in] length The minimum line length.
+ \param[in] delta Distance between the object pixel and the
+ background pixel.
+
+ \result An image of horizontal lines.
+
+
+ o
+ | ^
+ | | Delta
+ | v
+ X
+ | ^
+ | | Delta
+ | v
+ o
+
+ Using a delta of 0 is equivalent to the use of a c2_row
+ neighborhood.
+
+ */
template <typename I>
mln_concrete(I)
lines_h_pattern(const Image<I>& input, unsigned length, unsigned delta);
@@ -73,15 +88,16 @@ namespace scribo
mln_concrete(I)
lines_h_pattern(const Image<I>& input, unsigned length, unsigned delta)
{
+ trace::entering("scribo::primitive::extract::lines_h_pattern");
+
mlc_is(mln_value(I), bool)::check();
mln_precondition(exact(input).is_valid());
- mln_precondition(length % 2 == 1);
// FIXME: not generic.
window2d win;
mln_deduce(I, site, dpsite)
- dp1(-delta, 0),
- dp2( delta, 0);
+ dp1(-delta - 1, 0),
+ dp2( delta + 1, 0);
win.insert(dp1);
win.insert(dp2);
diff --git a/scribo/primitive/extract/lines_pattern.hh
b/scribo/primitive/extract/lines_pattern.hh
index 18cb784..5f9950a 100644
--- a/scribo/primitive/extract/lines_pattern.hh
+++ b/scribo/primitive/extract/lines_pattern.hh
@@ -75,61 +75,216 @@ namespace scribo
# ifndef MLN_INCLUDE_ONLY
- template <typename I, typename W>
- mln_concrete(I)
- lines_pattern(const Image<I>& input_, unsigned length,
- unsigned dir, const Window<W>& win_)
+
+ // Implementations
+
+ namespace impl
{
- trace::entering("scribo::primitive::extract::lines_pattern");
- const I& input = exact(input_);
- const W& win = exact(win_);
- mlc_is(mln_value(I), bool)::check();
- mln_precondition(input.is_valid());
+ namespace generic
+ {
+
+ template <typename I, typename W>
+ mln_concrete(I)
+ lines_pattern(const Image<I>& input_, unsigned length,
+ unsigned dir, const Window<W>& win_)
+ {
+
trace::entering("scribo::primitive::extract::impl::generic::lines_pattern");
+
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+ mlc_is(mln_value(I), bool)::check();
+ mln_precondition(input.is_valid());
+
+ // Adjusting extension.
+ extension::adjust_fill(input, length / 2, 0);
+
+ accu::count_value<bool> accu(true);
+ mln_ch_value(I,unsigned)
+ tmp = accu::transform_line(accu, input, length, dir);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_qiter(window2d) q(win, p);
+ bool is_foreground;
+ for_all(p)
+ {
- // Adjusting extension.
- extension::adjust_fill(input, length / 2, 0);
+ // If the foreground part of the pattern has more than 20%
+ // of background pixels, the current pixel is considered as
+ // background pixel.
+ if (length - tmp(p) > unsigned(0.2f * length) + 1)
+ {
+ output(p) = false;
+ continue;
+ }
- accu::count_value<bool> accu(true);
- mln_ch_value(I,unsigned)
- tmp = accu::transform_line(accu, input, length, dir);
+ // If the background parts of the pattern have exactly or
+ // less than 95% of background pixels, the current pixel is
+ // considered as part of the background.
+ is_foreground = true;
+ for_all(q)
+ if ((length - tmp(q)) < unsigned(length * 0.95f) + 1)
+ {
+ is_foreground = false;
+ break;
+ }
- mln_concrete(I) output;
- initialize(output, input);
+ output(p) = is_foreground;
+ }
+
+
trace::exiting("scribo::primitive::extract::impl::generic::lines_pattern");
+ return output;
+ }
+
+ } // end of namespace scribo::primitive::extract::impl::generic
- mln_piter(I) p(input.domain());
- mln_qiter(window2d) q(win, p);
- bool is_foreground;
- for_all(p)
+
+
+ template <typename I, typename W>
+ mln_concrete(I)
+ lines_pattern_fast(const Image<I>& input_, unsigned length,
+ unsigned dir, const Window<W>& win_)
{
+ trace::entering("scribo::primitive::extract::impl::lines_pattern_fast");
+
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+ mlc_is(mln_value(I), bool)::check();
+ mln_precondition(input.is_valid());
+
+ // Adjusting extension.
+ extension::adjust_fill(input, length / 2, 0);
- // If the foreground part of the pattern has more than 20%
- // of background pixels, the current pixel is considered as
- // background pixel.
- if (length - tmp(p) > unsigned(0.2f * length) + 1)
+ accu::count_value<bool> accu(true);
+ mln_ch_value(I,unsigned)
+ tmp = accu::transform_line(accu, input, length, dir);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ util::array<int>
+ q_arr = offsets_wrt(output, win);
+
+ bool is_foreground;
+ unsigned ncols = geom::ncols(output);
+ unsigned hit_ratio = 0.2f * length + 1;
+ unsigned miss_ratio = 0.95f * length + 1;
+
+ mln_box_runstart_piter(I) p(output.domain());
+ for_all(p)
{
- output(p) = false;
- continue;
- }
+ unsigned pi = output.index_of_point(p);
+ unsigned *tmp_ptr = &tmp.element(pi);
+ unsigned *end_ptr = tmp_ptr + ncols;
+
+ mln_value(I) *out_ptr = &output.element(pi);
- // If the background parts of the pattern have exactly or
- // less than 95% of background pixels, the current pixel is
- // considered as part of the background.
- is_foreground = true;
- for_all(q)
- if ((length - tmp(q)) < unsigned(length * 0.95f) + 1)
+ for (; tmp_ptr < end_ptr; ++out_ptr, ++tmp_ptr)
{
- is_foreground = false;
- break;
+
+ // If the foreground part of the pattern has more than 20%
+ // of background pixels, the current pixel is considered as
+ // background pixel.
+ if (length - *tmp_ptr > hit_ratio)
+ {
+ *out_ptr = false;
+ continue;
+ }
+
+ // If the background parts of the pattern have exactly or
+ // less than 95% of background pixels, the current pixel is
+ // considered as part of the background.
+ is_foreground = true;
+ for (unsigned i = 0; i < q_arr.size(); ++i)
+ if ((length - *(tmp_ptr + q_arr[i])) < miss_ratio)
+ {
+ is_foreground = false;
+ break;
+ }
+
+ *out_ptr = is_foreground;
}
+ }
+
+ trace::exiting("scribo::primitive::extract::impl::lines_pattern_fast");
+ return output;
+ }
+
+ } // end of namespace scribo::primitive::extract::impl
+
+
+
+ // Dispatch
- output(p) = is_foreground;
+ namespace internal
+ {
+
+ template <typename I, typename W>
+ mln_concrete(I)
+ lines_pattern_dispatch(mln::trait::image::value_storage::any,
+ mln::trait::image::value_access::any,
+ mln::trait::image::ext_domain::any,
+ const Image<I>& input, unsigned length,
+ unsigned dir, const Window<W>& win)
+ {
+ return impl::generic::lines_pattern(input, length, dir, win);
+ }
+
+
+ template <typename I, typename W>
+ mln_concrete(I)
+ lines_pattern_dispatch(mln::trait::image::value_storage::one_block,
+ mln::trait::image::value_access::direct,
+ mln::trait::image::ext_domain::some,
+ const Image<I>& input, unsigned length,
+ unsigned dir, const Window<W>& win)
+ {
+ return impl::lines_pattern_fast(input, length, dir, win);
}
+
+ template <typename I, typename W>
+ mln_concrete(I)
+ lines_pattern_dispatch(const Image<I>& input, unsigned length,
+ unsigned dir, const Window<W>& win)
+ {
+ return lines_pattern_dispatch(mln_trait_image_value_storage(I)(),
+ mln_trait_image_value_access(I)(),
+ mln_trait_image_ext_domain(I)(),
+ input,
+ length,
+ dir, win);
+ }
+
+ } // end of namespace scribo::primitive::extract::internal
+
+
+ // Facade
+
+ template <typename I, typename W>
+ mln_concrete(I)
+ lines_pattern(const Image<I>& input, unsigned length,
+ unsigned dir, const Window<W>& win)
+ {
+ trace::entering("scribo::primitive::extract::lines_pattern");
+
+ mlc_is(mln_value(I), bool)::check();
+ mln_precondition(exact(input).is_valid());
+ mln_precondition(exact(win).is_valid());
+ mln_precondition(length != 0);
+ mln_precondition(dir == 0 || dir == 1);
+
+ mln_concrete(I)
+ output = internal::lines_pattern_dispatch(input, length, dir, win);
+
trace::exiting("scribo::primitive::extract::lines_pattern");
return output;
}
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace scribo::primitive::extract
diff --git a/scribo/primitive/extract/lines_v_pattern.hh
b/scribo/primitive/extract/lines_v_pattern.hh
index ccd21c5..cbdf080 100644
--- a/scribo/primitive/extract/lines_v_pattern.hh
+++ b/scribo/primitive/extract/lines_v_pattern.hh
@@ -30,15 +30,17 @@
///
/// Extract vertical lines matching a specific pattern.
-#include <mln/core/concept/image.hh>
-#include <mln/core/alias/window2d.hh>
-
-# include <mln/win/hline2d.hh>
-
+# include <mln/core/concept/image.hh>
+# include <mln/core/alias/window2d.hh>
+# include <mln/win/rectangle2d.hh>
# include <mln/morpho/dilation.hh>
+# include <mln/arith/times.hh>
+
# include <scribo/primitive/extract/lines_pattern.hh>
+# include <scribo/primitive/internal/rd.hh>
+
namespace scribo
{
@@ -70,26 +72,27 @@ namespace scribo
mln_concrete(I)
lines_v_pattern(const Image<I>& input, unsigned length, unsigned delta)
{
- mln_precondition(length % 2 == 1);
+ trace::entering("scribo::primitive::extract::lines_v_pattern");
-// bool win_def[1][7] = { { 1, 0, 0, 0, 0, 0, 1 } };
-
-// window2d win;
-// convert::from_to(win_def, win);
+ mln_precondition(length % 2 == 1);
- // FIXME: not generic.
window2d win;
mln_deduce(I, site, dpsite)
- dp1(0, -delta),
- dp2(0, delta);
+ dp1(0, -delta - 1),
+ dp2(0, delta + 1);
win.insert(dp1);
win.insert(dp2);
- //FIXME: Add reconstruction instead of this arbitrary dilation.
- win::vline2d vwin(length/2 + 2);
-// win::vline2d vwin(length);
- return morpho::dilation(lines_pattern(input, length, 0, win), vwin);
-// return lines_pattern(input, length, 0, win);
+ mln_concrete(I) output = lines_pattern(input, length, 0, win);
+
+ mln_concrete(I)
+ output_dil = morpho::dilation(output,
+ win::rectangle2d(length / 2 + delta, 3));
+
+ output = scribo::primitive::internal::rd(output, input * output_dil);
+
+ trace::exiting("scribo::primitive::extract::lines_v_pattern");
+ return output;
}
--
1.5.6.5