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 2008
- 14 participants
- 266 discussions
URL: https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
ChangeLog:
2008-11-10 Dalila Benboudjema <dalila(a)lrde.epita.fr>
Add a new sandbox for Dalila.
* dalila/Makefile: New.
* dalila/demat.hh: New.
* dalila/images/factures/facture.pbm: New.
* dalila/images/factures/facture2.pbm: New.
* dalila/images/factures/facture3.pbm: New.
* dalila/images/factures: New.
* dalila/images/photos/chavez.pbm: New.
* dalila/images/photos/family.pbm: New.
* dalila/images/photos/garden.pbm: New.
* dalila/images/photos/garden_crop.pbm: New.
* dalila/images/photos/revolution.pbm: New.
* dalila/images/photos/revolution2.pbm: New.
* dalila/images/photos: New.
* dalila/images: New.
* dalila/photo.cc: New.
* dalila/start.sh: New.
* dalila/table.cc: New.
* dalila: New.
---
Makefile | 18 ++
demat.hh | 564 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
photo.cc | 64 +++++++
start.sh | 44 ++++
table.cc | 66 +++++++
5 files changed, 756 insertions(+)
Index: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture2.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture2.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture3.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture3.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/garden_crop.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/garden_crop.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/revolution.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/revolution.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/revolution2.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/revolution2.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/chavez.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/chavez.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/garden.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/garden.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/family.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/family.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/start.sh
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/start.sh (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/start.sh (revision 2830)
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+out_location="./images-out"
+
+treat_file()
+{
+ file=$1
+ shift
+ echo "-------------------------"
+ echo " * Processing $file..."
+ echo " => Running: $1 $file"
+ echo "-------------------------"
+ d1=`date +%s`
+ time $1 $file
+ d2=`date +%s`
+ echo ""
+ dstdir="$out_location/`basename $file .pbm`"
+ echo "Moving output files to $dstdir..."
+ mkdir -p $dstdir
+ mv -f *.pbm $dstdir 2>/dev/null
+ mv -f *.ppm $dstdir 2>/dev/null
+ mv -f *.pgm $dstdir 2>/dev/null
+ echo ""
+}
+
+treat_dir()
+{
+ for file in $2/*; do
+ treat_file $file $1
+ done
+}
+
+rm -f *.pbm *.ppm *.pgm
+make
+
+# Traite une seule image
+# Usage: ./starh.sh <file.pbm> <table | photo>
+if [ $# -eq 2 ]; then
+ treat_file $1 ./$2
+else
+# Traite toutes les images
+ treat_dir ./table ./images/factures
+ treat_dir ./photo ./images/photos
+fi
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/start.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: branches/cleanup-2008/milena/sandbox/dalila/demat.hh
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/demat.hh (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/demat.hh (revision 2830)
@@ -0,0 +1,564 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+# ifndef DEMAT_HH_
+# define DEMAT_HH_
+
+# include <libgen.h>
+# include <sstream>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image1d.hh>
+
+# include <mln/core/concept/function.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/sub_image.hh>
+# include <mln/core/image/cast_image.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/core/var.hh>
+# include <mln/core/routine/clone.hh>
+# include <mln/core/routine/ops.hh>
+# include <mln/core/site_set/p_vaccess.hh>
+# include <mln/core/site_set/p_set.hh>
+
+# include <mln/accu/bbox.hh>
+# include <mln/accu/count.hh>
+
+# include <mln/border/fill.hh>
+
+# include <mln/convert/to.hh>
+# include <mln/convert/to_fun.hh>
+
+# include <mln/debug/println.hh>
+# include <mln/debug/colorize.hh>
+
+# include <mln/draw/box.hh>
+
+# include <mln/fun/i2v/array.hh>
+
+# include <mln/io/pbm/load.hh>
+# include <mln/io/pbm/save.hh>
+# include <mln/io/ppm/save.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/labeling/blobs.hh>
+# include <mln/labeling/compute.hh>
+
+# include <mln/level/convert.hh>
+# include <mln/level/compute.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/paste.hh>
+# include <mln/level/apply.hh>
+# include <mln/level/transform.hh>
+
+# include <mln/literal/all.hh>
+
+# include <mln/logical/not.hh>
+
+# include <mln/morpho/hit_or_miss.hh>
+# include <mln/morpho/erosion.hh>
+# include <mln/morpho/top_hat.hh>
+# include <mln/morpho/opening.hh>
+
+# include <mln/pw/all.hh>
+
+# include <mln/util/array.hh>
+
+# include <mln/value/int_u16.hh>
+# include <mln/value/rgb8.hh>
+
+# include <mln/win/hline2d.hh>
+# include <mln/win/vline2d.hh>
+
+namespace scribo
+{
+
+ namespace internal
+ {
+
+ using namespace mln;
+ using value::int_u16;
+ using value::rgb8;
+
+ char *input_file = 0;
+ int dbg_file_id = 0;
+
+ std::string output_file(const char *name, unsigned file_id)
+ {
+ std::ostringstream os;
+ os << "./"
+ << file_id
+ << "_"
+ << input_file
+ << "_"
+ << name;
+ return os.str();
+ }
+
+ void draw_component_boxes(image2d<rgb8>& output, const util::array<box2d>& boxes)
+ {
+ for (unsigned i = 1; i < boxes.nelements(); ++i)
+ if (boxes[i].is_valid())
+ {
+ output(boxes[i].center()) = literal::red;
+ draw::box(output, boxes[i], literal::red);
+ }
+ }
+
+ template <typename V>
+ void save_lbl_image(const image2d<V>& lbl, unsigned nlabels,
+ const char *filename, unsigned file_id)
+ {
+ image2d<rgb8> output = debug::colorize<image2d<rgb8>, image2d<V> >(lbl, nlabels);
+ io::ppm::save(output, output_file(filename, file_id));
+ }
+
+
+ /// Functions related to the matrix extraction
+ /// \{
+
+ void draw_hline(image2d<rgb8>& ima,
+ const box2d& box,
+ const rgb8& v)
+ {
+ unsigned ncols = box.pmax().col() - box.pmin().col();
+ point2d p1 = box.center();
+ p1.col() -= ncols / 2;
+ point2d p2 = box.center();
+ p2.col() += ncols / 2;
+
+ draw::line(ima, p1, p2, v);
+ }
+
+ void draw_vline(image2d<rgb8>& ima,
+ const box2d& box,
+ const rgb8& v)
+ {
+ unsigned nrows = box.pmax().row() - box.pmin().row();
+ point2d p1 = box.center();
+ p1.row() -= nrows / 2;
+ point2d p2 = box.center();
+ p2.row() += nrows / 2;
+
+ draw::line(ima, p1, p2, v);
+ }
+
+ void draw_row(image2d<rgb8>& ima,
+ unsigned line,
+ const rgb8& v)
+ {
+ draw::line(ima, point2d(line, 0), point2d(line, ima.ncols()), v);
+ }
+
+ void draw_col(image2d<rgb8>& ima,
+ unsigned line,
+ const rgb8& v)
+ {
+ draw::line(ima, point2d(0, line), point2d(ima.nrows(), line), v);
+ }
+
+ void
+ extract_matrix(const image2d<bool>& in,
+ std::pair<util::array<box2d>, util::array<box2d> > tboxes)
+ {
+ std::cout << "Extracting matrix..." << std::endl;
+
+ image1d<unsigned> hend(in.ncols()),
+ hrow(in.nrows()),
+ vend(in.nrows()),
+ vcol(in.ncols());
+
+ level::fill(hend, 0);
+ level::fill(hrow, 0);
+ level::fill(vend, 0);
+ level::fill(vcol, 0);
+
+ for (unsigned i = 1; i < tboxes.first.nelements(); ++i)
+ {
+ ++vend.at(tboxes.first[i].pmin().row());
+ ++vend.at(tboxes.first[i].pmax().row());
+ ++vcol.at(tboxes.first[i].center().col());
+ }
+
+ for (unsigned i = 1; i < tboxes.second.nelements(); ++i)
+ {
+ ++hend.at(tboxes.second[i].pmin().col());
+ ++hend.at(tboxes.second[i].pmax().col());
+ ++hrow.at(tboxes.second[i].center().row());
+ }
+
+#ifndef NOUT
+ image2d<rgb8> tmp(in.domain());
+ level::fill(tmp, literal::black);
+
+ for (unsigned i = 1; i < in.ncols(); ++i)
+ {
+ if (hend.at(i) > 0)
+ draw_col(tmp, i, literal::orange);
+ if (vcol.at(i) > 0)
+ draw_col(tmp, i, literal::orange);
+ }
+
+ for (unsigned i = 1; i < in.nrows(); ++i)
+ {
+ if (hrow.at(i) > 0)
+ draw_row(tmp, i, literal::magenta);
+ if (vend.at(i) > 0)
+ draw_row(tmp, i, literal::magenta);
+ }
+
+ for (unsigned i = 1; i < tboxes.first.nelements(); ++i)
+ draw_vline(tmp, tboxes.first[i], literal::green);
+
+ for (unsigned i = 1; i < tboxes.second.nelements(); ++i)
+ draw_hline(tmp, tboxes.second[i], literal::red);
+
+ io::ppm::save(tmp, output_file("matrix.ppm", 4));
+#endif
+
+ }
+
+ /// \}
+
+
+
+ /// Functions related to the table removal
+ /// \{
+
+
+ /// Extract the components bboxes.
+ util::array<box2d>
+ component_boxes(const image2d<bool>& filter)
+ {
+ std::cout << "component boxes" << std::endl;
+ int_u16 nlabels = 0;
+ image2d<int_u16> lbl = labeling::blobs(filter, c8(), nlabels);
+
+ return labeling::compute(accu::meta::bbox(), lbl, nlabels);
+ }
+
+ /// Remove table bboxes from an image.
+ void erase_table_boxes(image2d<bool>& output,
+ util::array<box2d>& boxes,
+ unsigned bbox_enlarge, unsigned dim)
+ {
+ for (unsigned i = 1; i < boxes.nelements(); ++i)
+ {
+ boxes[i].enlarge(dim, bbox_enlarge + 1);
+ boxes[i].crop_wrt(output.domain());
+ level::paste((pw::cst(false) | boxes[i] |
+ (pw::value(output) == pw::cst(true))), output);
+ }
+ }
+
+
+ /// Find table bboxes and remove them from the image.
+ std::pair<util::array<box2d>,
+ util::array<box2d> >
+ extract_tables(image2d<bool>& in,
+ image2d<rgb8>& output,
+ unsigned l)
+ {
+ typedef image2d<int_u16> I;
+ typedef accu::bbox<mln_psite_(I)> A;
+ typedef util::array<mln_result_(A)> boxes_t;
+
+
+ // Lignes verticales
+ std::cout << "Removing vertical lines" << std::endl;
+ win::vline2d vline(l);
+ image2d<bool> vfilter = morpho::erosion(in, vline);
+
+#ifndef NOUT
+ io::pbm::save(vfilter, output_file("table-vfilter.pbm", 1));
+#endif
+
+ boxes_t vboxes = component_boxes(vfilter);
+ erase_table_boxes(in, vboxes, (l / 2), 0);
+
+
+ // Lignes horizontales
+ std::cout << "Removing horizontal lines" << std::endl;
+ win::hline2d hline(l);
+ image2d<bool> hfilter = morpho::erosion(in, hline);
+
+#ifndef NOUT
+ io::pbm::save(hfilter, output_file("table-hfilter.pbm", 2));
+#endif
+
+ boxes_t hboxes = component_boxes(hfilter);
+ erase_table_boxes(in, hboxes, (l / 2), 1);
+
+
+#ifndef NOUT
+ image2d<rgb8> tmp = clone(output);
+ draw_component_boxes(tmp, vboxes);
+ draw_component_boxes(tmp, hboxes);
+ io::ppm::save(tmp, output_file("table-filtered.ppm", 3));
+#endif
+
+ return std::make_pair(vboxes, hboxes);
+ }
+
+ /// \}
+ /// End of functions related to the table removal.
+
+
+ /// Function related to text extraction
+ /// \{
+
+ inline
+ int_u16
+ most_left(const fun::i2v::array<int_u16>& left_link, unsigned i)
+ {
+ while (left_link(i) != i)
+ i = left_link(i);
+ return i;
+ }
+
+ inline
+ int_u16
+ uncurri_left_link(fun::i2v::array<int_u16>& left_link, unsigned i)
+ {
+ if (left_link(i) != i)
+ left_link(i) = uncurri_left_link(left_link, left_link(i));
+ return left_link(i);
+ }
+
+ template <typename V>
+ void
+ remove_small_comps_i2v(image2d<V>& lbl,
+ V& nlabels,
+ unsigned min_comp_size)
+ {
+ std::cout << "Removing small components smaller than "
+ << min_comp_size << " sites among " << nlabels
+ << "components" << std::endl;
+
+ typedef accu::count<mln_psite(image2d<V>)> accu_count_t;
+
+ util::array<mln_result(accu_count_t)> nsitecomp
+ = labeling::compute(accu_count_t(), lbl, nlabels);
+
+ V ncomp = 0;
+
+ fun::i2v::array<V> f(nsitecomp.nelements());
+ f(0) = 0;
+
+ for (unsigned i = 1; i <= nlabels; ++i)
+ {
+ if (nsitecomp[i] < min_comp_size)
+ f(i) = 0;
+ else
+ f(i) = ++ncomp;
+ }
+
+ lbl = level::transform(lbl, f);
+ nlabels = ncomp;
+
+#ifndef NOUT
+ save_lbl_image(lbl, nlabels, "lbl-small-comps-removed.pgm", 6);
+#endif
+ }
+
+
+ /// Merge bboxes according to their left box neighbor.
+ util::array< box2d >
+ group_bboxes(fun::i2v::array<int_u16>& left_link, image2d<int_u16>& lbl,
+ util::array<box2d>& cboxes, unsigned ncomp)
+ {
+ // Currify left_link lookup table and compute text area bboxes.
+ util::array< accu::bbox<point2d> > tboxes;
+ tboxes.resize(ncomp + 1);
+ for (unsigned i = 1; i <= ncomp; ++i)
+ tboxes[uncurri_left_link(left_link, i)].take(cboxes[i]);
+
+ //Update labels
+ lbl = level::transform(lbl, left_link);
+
+#ifndef NOUT
+ save_lbl_image(lbl, ncomp, "lbl-grouped-boxes.pgm", 7);
+#endif
+
+ util::array<box2d> result;
+ for (unsigned i = 1; i <= ncomp; ++i)
+ if (tboxes[i].is_valid())
+ result.append(tboxes[i].to_result());
+
+ return result;
+ }
+
+
+ /// Update the lookup table \p left if a neighbor is found on the right of
+ /// the current bbox.
+ void update_link(fun::i2v::array<int_u16>& left_link, image2d<int_u16>& lbl,
+ const point2d& p, const point2d& c,
+ unsigned i, int dmax)
+ {
+ if (lbl.domain().has(p) && lbl(p) != 0u && lbl(p) != i
+ && (math::abs(p.col() - c.col())) < dmax)
+ {
+ if (left_link(lbl(p)) == lbl(p) && most_left(left_link, i) != lbl(p))
+ left_link(lbl(p)) = i;
+// else
+// left_link(lbl(p)) = 0;//FIXME: should be uncommented?
+ }
+ }
+
+
+
+ /// Map each character bbox to its left bbox neighbor if possible.
+ /// Iterate to the right but link boxes to the left.
+ fun::i2v::array<int_u16>
+ link_character_bboxes(image2d<int_u16>& lbl,
+ const util::array<box2d>& cboxes,
+ unsigned ncomp,
+ unsigned bbox_distance)
+ {
+ fun::i2v::array<int_u16> left_link;
+ left_link.resize(ncomp + 1);
+
+ for (unsigned i = 0; i <= ncomp; ++i)
+ left_link(i) = i;
+
+ for (unsigned i = 1; i <= ncomp; ++i)
+ {
+ unsigned midcol = (cboxes[i].pmax().col() - cboxes[i].pmin().col()) / 2;
+ int dmax = midcol + bbox_distance;
+ point2d c = cboxes[i].center();
+ /// First site on the right of the central site
+ point2d p(c.row(), c.col() + 1);
+
+ // FIXME: Lemmings with a condition on the distance => write a special version?
+ while (lbl.domain().has(p) && (lbl(p) == 0u || lbl(p) == i)
+ && math::abs(p.col() - c.col()) < dmax)
+ ++p.col();
+
+ update_link(left_link, lbl, p, c, i, dmax);
+ }
+
+ return left_link;
+ }
+
+ util::array<box2d>
+ extract_text(image2d<bool>& in_,
+ image2d<rgb8>& output,
+ unsigned bbox_distance,
+ unsigned min_comp_size)
+ {
+ std::cout << "extracting text..." << std::endl;
+
+ typedef int_u16 V;
+ typedef image2d<V> I;
+ typedef util::array<box2d> boxes_t;
+
+ // Extract edges.
+ //win::rectangle2d l(5, 5);
+ unsigned l = 11;
+ //win::hline2d hline(l);
+ win::vline2d vline(l);
+ //image2d<bool> in = morpho::top_hat_white(in_, l);
+ image2d<bool> in = morpho::opening(in_, vline);
+ io::pbm::save(in, output_file("OuvertureSizevLine11.ppm", 9));
+
+ // Find character bboxes.
+ V nlabels;
+ image2d<V> lbl = labeling::blobs(in, c8(), nlabels);
+
+ //Remove small components.
+ remove_small_comps_i2v(lbl, nlabels, min_comp_size);
+
+ boxes_t cboxes = labeling::compute(accu::meta::bbox(), lbl, nlabels);
+
+#ifndef NOUT
+ image2d<rgb8> tmp = clone(output);
+ draw_component_boxes(tmp, cboxes);
+ io::ppm::save(tmp, output_file("character-bboxes.ppm", 5));
+#endif
+
+ //merge_bboxes(cboxes, lbl, nlabels);
+
+ //Link character bboxes to their left neighboor if possible.
+ fun::i2v::array<int_u16> left =
+ link_character_bboxes(lbl, cboxes, nlabels, bbox_distance);
+
+ //Merge character bboxes according to their left neighbor.
+ util::array<box2d> tboxes = group_bboxes(left, lbl, cboxes, nlabels);
+
+ return tboxes;
+ }
+
+ /// \}
+ /// End of functions related to text extraction
+
+ } // end of namespace scribo::internal
+
+
+ // Facade
+ void demat(char *argv[], bool treat_tables)
+ {
+ using namespace mln;
+ using value::rgb8;
+
+ border::thickness = 21;
+ trace::quiet = true;
+
+ //Useful debug variables
+ internal::input_file = basename(argv[1]);
+ unsigned l = 101;
+ unsigned bbox_distance = 25;
+ unsigned min_comp_size = 5;
+
+ //Load image
+ image2d<bool> in;
+ io::pbm::load(in, argv[1]);
+ in = logical::not_(in);
+
+ image2d<rgb8> output = level::convert(rgb8(), in);
+
+ std::pair<util::array<box2d>,
+ util::array<box2d> > tblboxes;
+ if (treat_tables)
+ {
+ tblboxes = internal::extract_tables(in, output, l);
+ internal::extract_matrix(in, tblboxes);
+ }
+
+ util::array<box2d> tboxes =
+ internal::extract_text(in, output, bbox_distance, min_comp_size);
+
+ internal::draw_component_boxes(output, tboxes);
+ io::ppm::save(output, internal::output_file("out.ppm", 8));
+
+ /// Use txt bboxes here with Tesseract
+ /// for (i = 1; i < tboxes.nelements(); ++i)
+ /// tesseract(in | tboxes[i])
+ }
+
+} // end of namespace scribo
+
+# endif // ! DEMAT_HH
Index: branches/cleanup-2008/milena/sandbox/dalila/table.cc
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/table.cc (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/table.cc (revision 2830)
@@ -0,0 +1,66 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+
+#include "demat.hh"
+
+int main(int argc, char*argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc < 2)
+ {
+ std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
+ << std::endl << std::endl
+ << std::endl
+ << "=========="
+ << std::endl << std::endl
+ << "<in.pbm> B/W inverted input image."
+ << std::endl << std::endl
+/* << "<out.ppm> RGB8 output image."
+ << std::endl << std::endl
+ << "<l> Line length"
+ << std::endl << std::endl
+ << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
+ << std::endl << std::endl
+ << "<min_comp_nsites> Minimum site count of a character/text component."
+ << std::endl
+ << " If a component have a site count lesser than this value, it is erased."
+ << std::endl << std::endl
+ << std::endl*/
+ << "=========="
+ << std::endl << std::endl
+ << "HINT: compile with -DNOUT to avoid debug images."
+ << std::endl << std::endl;
+ return 1;
+ }
+
+ scribo::demat(argv, true);
+
+ return 0;
+}
Index: branches/cleanup-2008/milena/sandbox/dalila/Makefile
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/Makefile (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/Makefile (revision 2830)
@@ -0,0 +1,18 @@
+OLENA_INCLUDE_PATH=../../../
+CXXFLAGS=-I$(OLENA_INCLUDE_PATH) -ggdb3 -Wall -O1 -DNDEBUG
+
+all: photo table
+
+photo: demat.hh photo.cc
+ g++ $(CXXFLAGS) photo.cc -o photo
+
+table: demat.hh table.cc
+ g++ $(CXXFLAGS) table.cc -o table
+
+dclean: clean
+ rm -f photo
+ rm -f table
+
+clean:
+ rm -f *.pbm *.pgm *.ppm
+
Index: branches/cleanup-2008/milena/sandbox/dalila/photo.cc
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/photo.cc (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/photo.cc (revision 2830)
@@ -0,0 +1,64 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+
+#include "demat.hh"
+
+int main(int argc, char*argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc < 2)
+ {
+ std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
+ << std::endl << std::endl
+ << std::endl
+ << "=========="
+ << std::endl << std::endl
+ << "<in.pbm> B/W inverted input image."
+ << std::endl << std::endl
+/* << "<out.ppm> RGB8 output image."
+ << std::endl << std::endl
+ << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
+ << std::endl << std::endl
+ << "<min_comp_nsites> Minimum site count of a character/text component."
+ << std::endl
+ << " If a component have a site count lesser than this value, it is erased."
+ << std::endl << std::endl
+ << std::endl*/
+ << "=========="
+ << std::endl << std::endl
+ << "HINT: compile with -DNOUT to avoid debug images."
+ << std::endl << std::endl;
+ return 1;
+ }
+
+ scribo::demat(argv, false);
+
+ return 0;
+}
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
INIM: Classif: Update palette proj.
* inim/classif/src/iccvg04.cc: Fix warning.
* inim/classif/src/proj.hh: Update palette prj.
* inim/classif/Makefile: Add warning flag.
Makefile | 8 ++++----
src/iccvg04.cc | 2 --
src/proj.hh | 10 +++++++---
3 files changed, 11 insertions(+), 9 deletions(-)
Index: inim/classif/src/iccvg04.cc
--- inim/classif/src/iccvg04.cc (revision 2828)
+++ inim/classif/src/iccvg04.cc (working copy)
@@ -53,7 +53,6 @@
const value::int_u8 v = 255 / f; // FIXME
image3d<unsigned> histo(v,v,v);
level::fill(histo, 0);
- unsigned i = 0;
mln_piter(I) p(ima.domain());
for_all(p)
@@ -163,7 +162,6 @@
image3d<unsigned> histo_filtered(histo.domain());
morpho::opening_volume(histo, c6(), lambda, histo_filtered);
-
//watershed over histo_closure
unsigned nbasins = 0;
image3d<unsigned> ws = morpho::meyer_wst(arith::revert(histo_filtered),
Index: inim/classif/src/proj.hh
--- inim/classif/src/proj.hh (revision 2828)
+++ inim/classif/src/proj.hh (working copy)
@@ -40,7 +40,7 @@
template <typename T, typename A>
image2d<mln_result(A)>
- proj(const image3d<T>& input, A a)
+ proj(const image3d<T>& input, A)
{
image2d<A> acc(geom::nslis(input), geom::nrows(input));
mln_piter(image3d<T>) p(input.domain());
@@ -69,11 +69,15 @@
image2d<value::rgb8> out(proj_class.domain());
level::fill(out, literal::white);
- mln_piter(image2d<value::int_u8>) p(hproj.domain());
+ mln_piter(image2d<value::int_u8>) p(proj_class.domain());
for_all(p)
if (hproj(p) > 0)
+ {
+ if (proj_class(p) > 0)
out(p) = convert::to<value::rgb8>(mean[proj_class(p)]);
-
+ else
+ out(p) = literal::red;
+ }
io::ppm::save(out, fn);
}
Index: inim/classif/Makefile
--- inim/classif/Makefile (revision 2828)
+++ inim/classif/Makefile (working copy)
@@ -21,18 +21,18 @@
$(ICCVG): $(ICCVG_SRC)
- g++ $(ICCVG_INCLUDES) -O1 -DNDEBUG $(ICCVG_SRC) -o $(ICCVG)
+ g++ $(ICCVG_INCLUDES) -Wall -W -O1 -DNDEBUG $(ICCVG_SRC) -o $(ICCVG)
$(ICCVG_DBG): $(ICCVG_SRC)
- g++ $(ICCVG_INCLUDES) -O0 -g3 -ggdb3 $(ICCVG_SRC) -o $(ICCVG_DBG)
+ g++ $(ICCVG_INCLUDES) -Wall -W -O0 -g3 -ggdb3 $(ICCVG_SRC) -o $(ICCVG_DBG)
$(V2): $(V2_SRC)
- g++ $(V2_INCLUDES) -O1 -DNDEBUG $(V2_SRC) -o $(V2)
+ g++ $(V2_INCLUDES) -Wall -W -O1 -DNDEBUG $(V2_SRC) -o $(V2)
$(V2_DBG): $(V2_SRC) .dep_v2
- g++ $(V2_INCLUDES) -O0 -g3 -ggdb3 $(V2_SRC) -o $(V2_DBG)
+ g++ $(V2_INCLUDES) -Wall -W -O0 -g3 -ggdb3 $(V2_SRC) -o $(V2_DBG)
.PHONY:clean check check-debug valgrind .dep_iccvg .dep_v2
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add a couple of geodesic transforms.
* mln/transform/influence_zone_geodesic.hh: New.
* mln/transform/all.hh: Update.
* tests/transform/influence_zone_geodesic.cc: New.
* mln/transform/distance_geodesic.hh: New.
* tests/transform/distance_geodesic.cc: New.
mln/transform/all.hh | 13 +-
mln/transform/distance_geodesic.hh | 153 +++++++++++++++++++++++++++
mln/transform/influence_zone_geodesic.hh | 160 +++++++++++++++++++++++++++++
tests/transform/distance_geodesic.cc | 52 +++++++++
tests/transform/influence_zone_geodesic.cc | 58 ++++++++++
5 files changed, 430 insertions(+), 6 deletions(-)
Index: tests/transform/distance_geodesic.cc
--- tests/transform/distance_geodesic.cc (revision 0)
+++ tests/transform/distance_geodesic.cc (revision 0)
@@ -0,0 +1,52 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/transform/distance_geodesic.cc
+///
+/// Test on mln::transform::distance_geodesic.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/level/fill.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/transform/distance_geodesic.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<bool> input(9, 9);
+ level::fill(input, false);
+ input.at(4, 4) = true;
+
+ image2d<int_u8> output = transform::distance_geodesic(input, c4(), int_u8(4));
+ debug::println(output);
+}
Index: tests/transform/influence_zone_geodesic.cc
--- tests/transform/influence_zone_geodesic.cc (revision 0)
+++ tests/transform/influence_zone_geodesic.cc (revision 0)
@@ -0,0 +1,58 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/transform/influence_zone_geodesic.cc
+///
+/// Test on mln::transform::influence_zone_geodesic.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/make/image2d.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/transform/influence_zone_geodesic.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ int_u8 vals[] =
+ { 1, 1, 0, 0, 0, 0, 3,
+ 1, 1, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0 };
+ image2d<int_u8> input = make::image2d(vals);
+
+ image2d<int_u8> output = transform::influence_zone_geodesic(input, c4(), int_u8(1));
+ debug::println(output);
+}
Index: mln/transform/influence_zone_geodesic.hh
--- mln/transform/influence_zone_geodesic.hh (revision 0)
+++ mln/transform/influence_zone_geodesic.hh (revision 0)
@@ -0,0 +1,160 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_TRANSFORM_INFLUENCE_ZONE_GEODESIC_HH
+# define MLN_TRANSFORM_INFLUENCE_ZONE_GEODESIC_HH
+
+/// \file mln/transform/influence_zone_geodesic.hh
+///
+/// Discrete geodesic distance transform.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/site_set/p_queue_fast.hh>
+# include <mln/core/routine/clone.hh>
+# include <mln/level/fill.hh>
+
+# include <mln/debug/println.hh>
+
+
+namespace mln
+{
+
+ namespace transform
+ {
+
+ /// Discrete geodesic distance transform.
+ template <typename I, typename N, typename D>
+ mln_concrete(I)
+ influence_zone_geodesic(const Image<I>& input, const Neighborhood<N>& nbh, D max);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I, typename N, typename D>
+ mln_concrete(I)
+ influence_zone_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ D max)
+ {
+ trace::entering("transform::impl::generic::influence_zone_geodesic");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.has_data());
+
+ mln_ch_value(I, D) dmap; // Distance map is aux data.
+ initialize(dmap, input);
+
+ typedef mln_site(I) P;
+ p_queue_fast<P> q;
+
+ mln_concrete(I) output = clone(input);
+
+ // Initialization.
+ {
+ level::fill(dmap, max);
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (input(p) != 0) // p in a component
+ {
+ dmap(p) = 0;
+ for_all(n)
+ if (input.domain().has(n) && input(n) == 0) // n in background
+ {
+ q.push(p);
+ break;
+ }
+ }
+ }
+
+ // Propagation.
+ {
+ P p;
+ mln_niter(N) n(nbh, p);
+ while (! q.is_empty())
+ {
+ p = q.pop_front();
+ if (dmap(p) == max)
+ {
+ // Saturation so stop.
+ q.clear();
+ break;
+ }
+ for_all(n)
+ if (input.domain().has(n) && dmap(n) == max)
+ {
+ dmap(n) = dmap(p) + 1;
+ output(n) = output(p);
+ q.push(n);
+ }
+ }
+ }
+
+ trace::exiting("transform::impl::generic::influence_zone_geodesic");
+ return output;
+ }
+
+ } // end of namespace mln::transform::impl::generic
+
+ } // end of namespace mln::transform::impl
+
+
+ // Facade.
+
+ template <typename I, typename N, typename D>
+ inline
+ mln_concrete(I)
+ influence_zone_geodesic(const Image<I>& input, const Neighborhood<N>& nbh,
+ D distance_max)
+ {
+ trace::entering("transform::influence_zone_geodesic");
+
+ // FIXME: tests.
+
+ mln_concrete(I) output;
+ output = impl::generic::influence_zone_geodesic(input, nbh, distance_max);
+
+ trace::exiting("transform::influence_zone_geodesic");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::transform
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TRANSFORM_DISTANCE_HH
Index: mln/transform/all.hh
--- mln/transform/all.hh (revision 2827)
+++ mln/transform/all.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,22 +28,23 @@
#ifndef MLN_TRANSFORM_ALL_HH
# define MLN_TRANSFORM_ALL_HH
-/*! \file mln/transform/all.hh
- *
- * \brief File that includes all "point-wise" expression tools.
- */
+/// \file mln/transform/all.hh
+///
+/// File that includes all transforms.
namespace mln
{
- /// Namespace of "point-wise" expression tools.
+ /// Namespace of transforms.
namespace transform {}
} // end of namespace mln
# include <mln/transform/distance.hh>
+# include <mln/transform/distance_geodesic.hh>
+# include <mln/transform/influence_zone_geodesic.hh>
#endif // ! MLN_TRANSFORM_ALL_HH
Index: mln/transform/distance_geodesic.hh
--- mln/transform/distance_geodesic.hh (revision 0)
+++ mln/transform/distance_geodesic.hh (revision 0)
@@ -0,0 +1,153 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_TRANSFORM_DISTANCE_GEODESIC_HH
+# define MLN_TRANSFORM_DISTANCE_GEODESIC_HH
+
+/// \file mln/transform/distance_geodesic.hh
+///
+/// Discrete geodesic distance transform.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/site_set/p_queue_fast.hh>
+# include <mln/level/fill.hh>
+
+
+
+namespace mln
+{
+
+ namespace transform
+ {
+
+ /// Discrete geodesic distance transform.
+ template <typename I, typename N, typename D>
+ mln_ch_value(I, D)
+ distance_geodesic(const Image<I>& input, const Neighborhood<N>& nbh, D max);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I, typename N, typename D>
+ mln_ch_value(I, D)
+ distance_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_, D max)
+ {
+ trace::entering("transform::impl::generic::distance_geodesic");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.has_data());
+
+ mln_ch_value(I, D) output;
+ initialize(output, input);
+
+ typedef mln_site(I) P;
+ p_queue_fast<P> q;
+
+ // Initialization.
+ {
+ level::fill(output, max);
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (input(p) == true) // p in object
+ {
+ output(p) = 0;
+ for_all(n)
+ if (input.domain().has(n) && input(n) == false) // n in background
+ {
+ q.push(p);
+ break;
+ }
+ }
+ }
+
+ // Propagation.
+ {
+ P p;
+ mln_niter(N) n(nbh, p);
+ while (! q.is_empty())
+ {
+ p = q.pop_front();
+ for_all(n)
+ if (input.domain().has(n) && output(n) == max)
+ {
+ output(n) = output(p) + 1;
+ if (output(n) == max)
+ {
+ // Saturation so stop.
+ q.clear();
+ break;
+ }
+ q.push(n);
+ }
+ }
+ }
+
+ trace::exiting("transform::impl::generic::distance_geodesic");
+ return output;
+ }
+
+ } // end of namespace mln::transform::impl::generic
+
+ } // end of namespace mln::transform::impl
+
+
+ // Facade.
+
+ template <typename I, typename N, typename D>
+ inline
+ mln_ch_value(I, D)
+ distance_geodesic(const Image<I>& input, const Neighborhood<N>& nbh, D max)
+ {
+ trace::entering("transform::distance_geodesic");
+
+ // FIXME: tests.
+
+ mln_ch_value(I, D) output;
+ output = impl::generic::distance_geodesic(input, nbh, max);
+
+ trace::exiting("transform::distance_geodesic");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::transform
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TRANSFORM_DISTANCE_HH
1
0
cleanup-2008 2827: Add directional filters for the gaussian and its derivatives.
by Nicolas Ballas 07 Nov '08
by Nicolas Ballas 07 Nov '08
07 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Add directional filters for the gaussian and its derivatives.
* tests/linear/gaussian.cc: Update tests.
* mln/linear/gaussian.hh: Add directional filters.
mln/linear/gaussian.hh | 293 ++++++++++++++++++++++++++++++++++++++++++++---
tests/linear/gaussian.cc | 3
2 files changed, 281 insertions(+), 15 deletions(-)
Index: tests/linear/gaussian.cc
--- tests/linear/gaussian.cc (revision 2826)
+++ tests/linear/gaussian.cc (working copy)
@@ -44,6 +44,8 @@
#include "tests/data.hh"
+#include <mln/trace/all.hh>
+
int main()
@@ -54,6 +56,5 @@
io::pgm::load(lena, MLN_IMG_DIR "/lena.pgm");
image2d<value::int_u8> out = linear::gaussian(lena, 5.1f);
-
io::pgm::save(out, "out.pgm");
}
Index: mln/linear/gaussian.hh
--- mln/linear/gaussian.hh (revision 2826)
+++ mln/linear/gaussian.hh (working copy)
@@ -43,6 +43,8 @@
# include <mln/geom/ncols.hh>
# include <mln/geom/nrows.hh>
+# include <mln/trait/image/props.hh>
+
# include <mln/extension/adjust_fill.hh>
# include <mln/level/stretch.hh>
@@ -51,6 +53,8 @@
# include <vector>
# include <cmath>
+# include <mln/debug/println.hh>
+
namespace mln
{
@@ -247,7 +251,6 @@
}
// Combine results from causal and non-causal parts.
-
current = start;
for (int i = 0; i < len; ++i)
{
@@ -331,8 +334,10 @@
float scale0 = 1 + exp2b0 - 2 * cos0 * expb0;
scale0 *= scale0 * scale0;
- float scaleA = a1 * sin0 * expb0 * (1 + expb0 * (2 * cos0 * (1 + exp2b0) + exp2b0 - 6)) +
- a0 * expb0 * (2 * expb0 * (2 - cos0 * cos0) * (1 - exp2b0) - cos0 * (1 - exp2b0 * exp2b0));
+ float scaleA = a1 * sin0 * expb0 *
+ (1 + expb0 * (2 * cos0 * (1 + exp2b0) + exp2b0 - 6)) +
+ a0 * expb0 * (2 * expb0 * (2 - cos0 * cos0) *
+ (1 - exp2b0) - cos0 * (1 - exp2b0 * exp2b0));
float expb1 = exp(b1);
float exp2b1 = exp(2.0 * b1);
@@ -340,8 +345,10 @@
float scale1 = 1 + exp2b1 - 2 * cos1 * expb1;
scale1 *= scale1 * scale1;
- float scaleC = c1 * sin1 * expb1 * (1 + expb1 * (2 * cos1 * (1 + exp2b1) + exp2b1 - 6)) +
- c0 * expb1 * (2 * expb1 * (2 - cos1 * cos1) * (1 - exp2b1) - cos1 * (1 - exp2b1 * exp2b1));
+ float scaleC = c1 * sin1 * expb1 *
+ (1 + expb1 * (2 * cos1 * (1 + exp2b1) + exp2b1 - 6)) +
+ c0 * expb1 * (2 * expb1 * (2 - cos1 * cos1) *
+ (1 - exp2b1) - cos1 * (1 - exp2b1 * exp2b1));
float sumA = scaleA / scale0;
float sumC = scaleC / scale1;
@@ -350,29 +357,114 @@
return (sumA + sumC);
}
+
+ template <class I, class F>
+ inline
+ void
+ generic_filter_(trait::image::dimension::one_d,
+ Image<I>& img_, const F& coef, int dir)
+ {
+ I& img = exact(img_);
+ mln_precondition(dir < I::site::dim);
+
+
+ recursivefilter_<mln_value(I)>(img, coef,
+ point1d(-img.border()),
+ point1d(geom::ninds(img) - 1 +
+ img.border()),
+ geom::ninds(img) + 2 * img.border(),
+ dpoint1d(1));
+ }
+
template <class I, class F>
inline
void
- generic_filter_(Image<I>& img_, const F& coef)
+ generic_filter_(trait::image::dimension::two_d,
+ Image<I>& img_, const F& coef, int dir)
{
I& img = exact(img_);
+ mln_precondition(dir < I::site::dim);
+
+
+ if (dir == 0)
+ {
// Apply on rows.
for (unsigned j = 0; j < geom::ncols(img); ++j)
recursivefilter_< mln_value(I) >(img, coef,
point2d(-img.border(), j),
- point2d(geom::nrows(img) - 1 + img.border(), j),
+ point2d(geom::nrows(img) - 1 +
+ img.border(), j),
geom::nrows(img) + 2 * img.border(),
dpoint2d(1, 0));
+ }
+ if (dir == 1)
+ {
// Apply on columns.
for (unsigned i = 0; i < geom::nrows(img); ++i)
recursivefilter_< mln_value(I) >(img, coef,
point2d(i, -img.border()),
- point2d(i, geom::ncols(img) - 1 + img.border()),
+ point2d(i, geom::ncols(img) - 1 +
+ img.border()),
geom::ncols(img) + 2 * img.border(),
dpoint2d(0, 1));
}
+ }
+
+ template <class I, class F>
+ inline
+ void
+ generic_filter_(trait::image::dimension::three_d,
+ Image<I>& img_, const F& coef, int dir)
+ {
+ I& img = exact(img_);
+ mln_precondition(dir < I::site::dim);
+
+ if (dir == 0)
+ {
+ // Apply on slices.
+ for (unsigned j = 0; j < geom::nrows(img); ++j)
+ for (unsigned k = 0; k < geom::ncols(img); ++k)
+ recursivefilter_<mln_value(I)>(img, coef,
+ point3d(-img.border(), j , k),
+ point3d(geom::nslis(img) - 1 +
+ img.border(), j, k),
+ geom::nslis(img) + 2 *
+ img.border(),
+ dpoint3d(1, 0, 0));
+ }
+
+
+ if (dir == 1)
+ {
+ // Apply on rows.
+ for (unsigned i = 0; i < geom::nslis(img); ++i)
+ for (unsigned k = 0; k < geom::ncols(img); ++k)
+ recursivefilter_<mln_value(I)>(img, coef,
+ point3d(i, -img.border(), k),
+ point3d(i, geom::nrows(img) - 1 +
+ img.border(), k),
+ geom::nrows(img) + 2 *
+ img.border(),
+ dpoint3d(0, 1, 0));
+ }
+
+ if (dir == 2)
+ {
+ // Apply on columns.
+ for (unsigned i = 0; i < geom::nslis(img); ++i)
+ for (unsigned j = 0; j < geom::nrows(img); ++i)
+ recursivefilter_<mln_value(I)>(img, coef,
+ point3d(i, j, -img.border()),
+ point3d(i, j, geom::ncols(img) -
+ 1 + img.border()),
+ geom::ncols(img) + 2 *
+ img.border(),
+ dpoint3d(0, 0, 1));
+ }
+ }
+
template <class I, class F, class O>
@@ -391,15 +483,42 @@
// On tiny sigma, Derich algorithm doesn't work.
// It is the same thing that to convolve with a Dirac.
if (sigma > 0.006)
- generic_filter_(work_img, coef);
- /* Convert the result image to the user-requested datatype.
- FIXME: We are making an unnecessary copy in case the
- user expects a ntg::float_s image. */
- //level::stretch(work_img, out);
+ for (int i = 0; i < I::site::dim; ++i)
+ generic_filter_(mln_trait_image_dimension(I)(),
+ work_img, coef, i);
+
+ // FIXME deal with overflow problem
+ // for instance, when we paste a float image into a int_u8 images.
+ level::paste(work_img, out);
+ }
+
+ template <class I, class F, class O>
+ inline
+ void
+ generic_filter_common_(trait::value::nature::scalar,
+ const Image<I>& in,
+ const F& coef,
+ float sigma,
+ Image<O>& out,
+ int dir)
+ {
+ mln_ch_value(O, float) work_img(exact(in).domain());
+ level::paste(in, work_img);
+ extension::adjust_fill(work_img, 4, 0);
+
+ // On tiny sigma, Derich algorithm doesn't work.
+ // It is the same thing that to convolve with a Dirac.
+ if (sigma > 0.006)
+ generic_filter_(mln_trait_image_dimension(I)(),
+ work_img, coef, dir);
+
+ // FIXME deal with overflow problem
+ // for instance, when we paste a float image into a int_u8 images.
level::paste(work_img, out);
}
+
template <class I, class F, class O>
inline
void
@@ -417,13 +536,145 @@
// On tiny sigma, Derich algorithm doesn't work.
// It is the same thing that to convolve with a Dirac.
if (sigma > 0.006)
- generic_filter_(out, coef);
+ for (int i = 0; i < I::site::dim; ++i)
+ generic_filter_(mln_trait_image_dimension(I)(),
+ out, coef, i);
+ }
+
+ template <class I, class F, class O>
+ inline
+ void
+ generic_filter_common_(trait::value::nature::vectorial,
+ const Image<I>& in,
+ const F& coef,
+ float sigma,
+ Image<O>& out,
+ int dir)
+ {
+ // typedef algebra::vec<3, float> vec3f;
+ // mln_ch_value(O, vec3f) work_img(exact(in).domain());
+ // FIXME : paste does not work (rgb8 -> vec3f).
+ level::paste(in, out);
+
+ // On tiny sigma, Derich algorithm doesn't work.
+ // It is the same thing that to convolve with a Dirac.
+ if (sigma > 0.006)
+ generic_filter_(mln_trait_image_dimension(I)(),
+ out, coef, dir);
}
} // end of namespace mln::linear::impl
+
// Facade.
+
+ /*! Apply an approximated gaussian filter of \p sigma on \p input.
+ * on a specific direction \p dir
+ * if \p dir = 0, the filter is applied on the first image dimension.
+ * if \p dir = 1, the filter is applied on the second image dimension.
+ * And so on...
+ *
+ * \pre input.has_data
+ * \pre dir < dimension(input)
+ */
+ template <class I>
+ inline
+ mln_concrete(I)
+ gaussian(const Image<I>& input, float sigma, int dir)
+ {
+ mln_precondition(exact(input).has_data());
+ mln_precondition(dir < I::site::dim);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+ impl::recursivefilter_coef_ coef(1.68f, 3.735f,
+ 1.783f, 1.723f,
+ -0.6803f, -0.2598f,
+ 0.6318f, 1.997f,
+ sigma, impl::gaussian_norm_coef_);
+
+ impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
+ input, coef, sigma, output, dir);
+ return output;
+ }
+
+
+ /*! Apply an approximated first derivative gaussian filter of \p sigma on
+ * \p input.
+ * on a specific direction \p dir
+ * if \p dir = 0, the filter is applied on the first image dimension.
+ * if \p dir = 1, the filter is applied on the second image dimension.
+ * And so on...
+ *
+ * \pre input.has_data
+ * \pre dir < dimension(input)
+ */
+ template <class I>
+ inline
+ mln_concrete(I)
+ gaussian_1st_derivative(const Image<I>& input, float sigma, int dir)
+ {
+ mln_precondition(exact(input).has_data());
+ mln_precondition(dir < I::site::dim);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ impl::recursivefilter_coef_
+ coef(-0.6472f, -4.531f,
+ 1.527f, 1.516f,
+ 0.6494f, 0.9557f,
+ 0.6719f, 2.072f,
+ sigma, impl::gaussian_1st_deriv_coef_norm_);
+
+ impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
+ input, coef, sigma, output, dir);
+ return output;
+ }
+
+ /*! Apply an approximated second derivative gaussian filter of \p sigma on
+ * \p input.
+ * on a specific direction \p dir
+ * if \p dir = 0, the filter is applied on the first image dimension.
+ * if \p dir = 1, the filter is applied on the second image dimension.
+ * And so on...
+ *
+ * \pre input.has_data
+ * \pre dir < dimension(input)
+ */
+ template <class I>
+ inline
+ mln_concrete(I)
+ gaussian_2nd_derivative(const Image<I>& input, float sigma, int dir)
+ {
+ mln_precondition(exact(input).has_data());
+ mln_precondition(dir < I::site::dim);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ impl::recursivefilter_coef_
+ coef(-1.331f, 3.661f,
+ 1.24f, 1.314f,
+ 0.3225f, -1.738f,
+ 0.748f, 2.166f,
+ sigma, impl::gaussian_2nd_deriv_coef_norm_);
+
+ impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
+ input, coef, sigma, output, dir);
+ return output;
+ }
+
+
+
+
+
+ /*! Apply an approximated gaussian filter of \p sigma on \p input.
+ * This filter is applied in all the input image direction.
+ *
+ * \pre input.has_data
+ */
template <class I>
inline
mln_concrete(I)
@@ -446,6 +697,13 @@
return output;
}
+
+ /*! Apply an approximated first derivative gaussian filter of \p sigma on
+ * \p input
+ * This filter is applied in all the input image direction.
+ *
+ * \pre input.has_data
+ */
template <class I>
inline
mln_concrete(I)
@@ -467,6 +725,13 @@
return output;
}
+
+ /*! Apply an approximated second derivative gaussian filter of \p sigma on
+ * \p input
+ * This filter is applied in all the input image direction.
+ *
+ * \pre input.has_data
+ */
template <class I>
inline
mln_concrete(I)
1
0
07 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Revamp linear sobel and cleanup level transform.
* mln/linear/ch_convolve.hh (mln_ch_convolve_grad): New.
* mln/linear/sobel_2d.hh: New.
* mln/linear/sobel.hh: Remove; obsolete.
* tests/linear/sobel.cc: Remove; obsolete.
* tests/linear/sobel_2d.cc: New.
* tests/linear/Makefile.am: Update.
* mln/fun/x2v/l1_norm.hh: New.
* mln/fun/vv2v/vec.hh: New.
* mln/fun/vv2v/all.hh: Update.
* mln/level/transform.spe.hh: Cleanup.
* mln/level/transform.hh: Cleanup.
* mln/level/transform_inplace.hh: New.
* tests/level/transform_inplace.cc: New.
* tests/level/Makefile.am: Update.
* mln/make/image2d.hh: Relax check; it was too strong.
* mln/core/concept/image.hh: Likewise.
* tests/make/image2d.cc: Augment.
mln/core/concept/image.hh | 6 -
mln/fun/vv2v/all.hh | 13 +-
mln/fun/vv2v/vec.hh | 80 +++++++++++++
mln/fun/x2v/l1_norm.hh | 81 +++++++++++++
mln/level/transform.hh | 139 +++++++++--------------
mln/level/transform.spe.hh | 94 +++++++---------
mln/level/transform_inplace.hh | 226 ++++++++++++++++++++++++++++++++++++++
mln/linear/ch_convolve.hh | 6 +
mln/linear/sobel_2d.hh | 229 +++++++++++----------------------------
mln/make/image2d.hh | 4
tests/level/Makefile.am | 2
tests/level/transform_inplace.cc | 56 +++++++++
tests/linear/Makefile.am | 4
tests/linear/sobel_2d.cc | 34 +----
tests/make/image2d.cc | 15 +-
15 files changed, 653 insertions(+), 336 deletions(-)
Index: tests/level/transform_inplace.cc
--- tests/level/transform_inplace.cc (revision 0)
+++ tests/level/transform_inplace.cc (revision 0)
@@ -0,0 +1,56 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/level/transform_inplace.cc
+///
+/// Tests on mln::level::transform_inplace
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/routine/clone.hh>
+#include <mln/fun/v2v/inc.hh>
+#include <mln/fun/v2v/dec.hh>
+#include <mln/debug/iota.hh>
+
+#include <mln/level/transform_inplace.hh>
+#include <mln/level/compare.hh>
+
+
+
+int main()
+{
+ using namespace mln;
+ const unsigned size = 50;
+
+ image2d<int> ref(3, 3);
+ debug::iota(ref);
+
+ image2d<int> ima = clone(ref);
+ level::transform_inplace(ima, fun::v2v::inc<int>());
+ level::transform_inplace(ima, fun::v2v::dec<int>());
+
+ mln_assertion(ima == ref);
+}
Index: tests/level/Makefile.am
--- tests/level/Makefile.am (revision 2825)
+++ tests/level/Makefile.am (working copy)
@@ -28,6 +28,7 @@
sort_psites_full \
stretch \
transform \
+ transform_inplace \
update
abs_SOURCES = abs.cc
@@ -52,6 +53,7 @@
sort_psites_SOURCES = sort_psites.cc
stretch_SOURCES = stretch.cc
transform_SOURCES = transform.cc
+transform_inplace_SOURCES = transform_inplace.cc
update_SOURCES = update.cc
# Lengthy tests.
Index: tests/linear/Makefile.am
--- tests/linear/Makefile.am (revision 2825)
+++ tests/linear/Makefile.am (working copy)
@@ -11,7 +11,7 @@
gaussian \
lap \
log \
- sobel
+ sobel_2d
convolve_SOURCES = convolve.cc
gaussian_SOURCES = gaussian.cc
@@ -19,6 +19,6 @@
convolve_directional_SOURCES = convolve_directional.cc
convolve_2x1d_SOURCES = convolve_2x1d.cc
log_SOURCES = log.cc
-sobel_SOURCES = sobel.cc
+sobel_2d_SOURCES = sobel_2d.cc
TESTS = $(check_PROGRAMS)
Index: tests/linear/sobel_2d.cc
--- tests/linear/sobel_2d.cc (revision 2821)
+++ tests/linear/sobel_2d.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,22 +26,20 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/linear/sobel.cc
- *
- * \brief Tests on mln::linear::sobel.
- */
+/// \file tests/linear/sobel_2d.cc
+///
+/// Tests on mln::linear::sobel_2d.
+
#include <mln/core/image/image2d.hh>
+#include <mln/core/var.hh>
#include <mln/value/int_u8.hh>
-#include <mln/level/saturate.hh>
#include <mln/level/stretch.hh>
#include <mln/io/pgm/load.hh>
#include <mln/io/pgm/save.hh>
-#include <mln/border/thickness.hh>
-#include <mln/linear/sobel.hh>
-
+#include <mln/linear/sobel_2d.hh>
#include <mln/debug/println.hh>
#include "tests/data.hh"
@@ -56,19 +55,6 @@
image2d<int_u8> input;
io::pgm::load(input, MLN_IMG_DIR "/tiny.pgm");
- // Create unused objects, for test purpose.
- linear::sobel_h(input);
- linear::sobel_v(input);
- linear::sobel(input);
-
- linear::sobel_norm(input);
-
- image2d<float> result = linear::sobel_norm(input);
- image2d<int_u8> output (result.domain());
- level::stretch (result, output);
- debug::println (output);
-
- image2d<int_u8> output_sat (output.domain());
- level::saturate(output, output_sat);
- io::pgm::save(output_sat, "out.pgm");
+ image2d<float> output = linear::sobel_2d_l1_norm(input);
+ io::pgm::save(level::stretch(int_u8(), output), "out.pgm");
}
Property changes on: tests/linear/sobel_2d.cc
___________________________________________________________________
Added: svn:mergeinfo
Index: tests/make/image2d.cc
--- tests/make/image2d.cc (revision 2825)
+++ tests/make/image2d.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,10 +25,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/make/image2d.cc
- *
- * \brief Tests on mln::make::image2d.
- */
+/// \file tests/make/image2d.cc
+///
+/// Tests on mln::make::image2d.
#include <mln/make/image2d.hh>
@@ -44,4 +43,10 @@
0, 1, 0, 0, 0 };
image2d<bool> ima = make::image2d(vals);
mln_assertion(ima.domain() == box2d(5,5));
+
+ bool vs[] = { 1, 0,
+ 1, 1 };
+ image2d<bool> tiny = make::image2d(vs);
+ mln_assertion(tiny.domain() == box2d(2,2));
+
}
Index: mln/core/concept/image.hh
--- mln/core/concept/image.hh (revision 2825)
+++ mln/core/concept/image.hh (working copy)
@@ -251,13 +251,13 @@
mlc_converts_to(V, mln_value(I))::check();
typedef mln_site(I) P;
enum { d = P::dim,
- s = mlc_root(d,S)::value / 2 };
- metal::bool_<(mlc_pow_int(2 * s + 1, d) == S)>::check();
+ s = mlc_root(d, S)::value };
+ metal::bool_<(mlc_pow_int(s, d) == S)>::check();
I& to = exact(to_);
mln_precondition(! to.has_data());
- box<P> b(all_to(0), all_to(2 * s));
+ box<P> b(all_to(0), all_to(s - 1));
to.init_(b);
mln_fwd_piter(box<P>) p(b);
unsigned i = 0;
Index: mln/level/transform.spe.hh
--- mln/level/transform.spe.hh (revision 2825)
+++ mln/level/transform.spe.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,11 +29,9 @@
#ifndef MLN_LEVEL_TRANSFORM_SPE_HH
# define MLN_LEVEL_TRANSFORM_SPE_HH
-/*! \file mln/level/transform.spe.hh
- *
- * \brief Specializations for mln::level::transform.
- *
- */
+/// \file mln/level/transform.spe.hh
+///
+/// Specializations for mln::level::transform.
# ifndef MLN_LEVEL_TRANSFORM_HH
# error "Forbidden inclusion of *.spe.hh"
@@ -58,11 +57,17 @@
namespace internal
{
- template <typename I, typename F, typename O>
+
+ template <typename I, typename F>
inline
void transform_tests(const Image<I>& input,
- const Function_v2v<F>& f,
- Image<O>& output);
+ const Function_v2v<F>& f);
+
+ template <typename I1, typename I2, typename F>
+ inline
+ void transform_tests(const Image<I1>& input1, const Image<I2>& input2,
+ const Function_v2v<F>& f);
+
}
@@ -88,17 +93,16 @@
{
trace::entering("level::impl::transform_lowq");
+ mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
+ trait::image::pw_io::read_write)::check();
+
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- level::internal::transform_tests(input, f, output);
- mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
- trait::image::pw_io::read_write)::check();
-
value::lut_vec<mln_vset(I), mln_result(F)>
lut(input.values_eligible(), f);
@@ -118,17 +122,16 @@
{
trace::entering("level::impl::transform_taken");
+ mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
+ trait::image::pw_io::read_write)::check();
+
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- level::internal::transform_tests(input, f, output);
- mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
- trait::image::pw_io::read_write)::check();
-
value::lut_vec<mln_vset(I), mln_result(F)>
lut(input.taken_values(), f);
@@ -151,13 +154,11 @@
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- level::internal::transform_tests(input_, f_, output);
-
mln_result(F) val = f(input.val());
fill_with_value(output, val);
@@ -173,18 +174,15 @@
{
trace::entering("level::impl::transform_fast");
- typedef mln_ch_value(I, mln_result(F)) O;
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
- mln_ch_value(I, mln_result(F)) output;
+ typedef mln_ch_value(I, mln_result(F)) O;
+ O output;
initialize(output, input);
-
- level::internal::transform_tests(input, f, output);
-
mln_pixter(const I) pi(input);
mln_pixter(O) po(output);
po.start();
@@ -207,17 +205,15 @@
const Function_v2v<F>& f_)
{
trace::entering("level::impl::transform_fast_lowq");
- typedef mln_ch_value(I, mln_result(F)) O;
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
- mln_ch_value(I, mln_result(F)) output;
+ typedef mln_ch_value(I, mln_result(F)) O;
+ O output;
initialize(output, input);
- level::internal::transform_tests(input, f, output);
-
value::lut_vec<mln_vset(I), mln_result(F)>
lut(input.values_eligible(), f);
@@ -247,7 +243,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::undef,
+ transform_dispatch(mln::trait::undef,
mln::trait::image::quant::any,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -258,7 +254,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::vw_set::any,
+ transform_dispatch(mln::trait::image::vw_set::any,
mln::trait::image::quant::any,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -269,7 +265,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::vw_set::uni,
+ transform_dispatch(mln::trait::image::vw_set::uni,
mln::trait::image::quant::any,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -281,7 +277,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::vw_set::any,
+ transform_dispatch(mln::trait::image::vw_set::any,
mln::trait::image::quant::low,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -294,7 +290,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::quant::any,
+ transform_dispatch(mln::trait::image::quant::any,
mln::trait::image::value_access::direct,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -306,7 +302,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::quant::low,
+ transform_dispatch(mln::trait::image::quant::low,
mln::trait::image::value_access::direct,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -319,12 +315,12 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::quant::any,
+ transform_dispatch(mln::trait::image::quant::any,
mln::trait::image::value_access::any,
const Image<I>& input,
const Function_v2v<F>& f)
{
- return transform_dispatch_(mln_trait_image_vw_set(I)(),
+ return transform_dispatch(mln_trait_image_vw_set(I)(),
mln_trait_image_quant(I)(),
input, f);
}
@@ -333,11 +329,11 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::value_storage::any,
+ transform_dispatch(mln::trait::image::value_storage::any,
const Image<I>& input,
const Function_v2v<F>& f)
{
- return transform_dispatch_(mln_trait_image_vw_set(I)(),
+ return transform_dispatch(mln_trait_image_vw_set(I)(),
mln_trait_image_quant(I)(),
input, f);
}
@@ -345,7 +341,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::value_storage::singleton,
+ transform_dispatch(mln::trait::image::value_storage::singleton,
const Image<I>& input,
const Function_v2v<F>& f)
{
@@ -355,7 +351,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::value_storage::one_block,
+ transform_dispatch(mln::trait::image::value_storage::one_block,
const Image<I>& input_,
const Function_v2v<F>& f_)
{
@@ -364,11 +360,11 @@
/// Check alignement property
if (mlc_is(mln_trait_image_value_alignement(I),
trait::image::value_alignement::with_grid)::value)
- return transform_dispatch_(mln_trait_image_quant(I)(),
+ return transform_dispatch(mln_trait_image_quant(I)(),
mln_trait_image_value_access(I)(),
input, f_);
else
- return transform_dispatch_(mln_trait_image_vw_set(I)(),
+ return transform_dispatch(mln_trait_image_vw_set(I)(),
mln_trait_image_quant(I)(),
input, f_);
}
@@ -377,10 +373,10 @@
template <typename I, typename F>
mln_ch_value(I, mln_result(F))
- transform_dispatch_(const Image<I>& input,
+ transform_dispatch(const Image<I>& input,
const Function_v2v<F>& f)
{
- return transform_dispatch_(mln_trait_image_value_storage(I)(),
+ return transform_dispatch(mln_trait_image_value_storage(I)(),
input, f);
}
Index: mln/level/transform.hh
--- mln/level/transform.hh (revision 2825)
+++ mln/level/transform.hh (working copy)
@@ -1,4 +1,5 @@
// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -39,10 +40,8 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/function.hh>
-
# include <mln/value/set.hh>
-
// Specializations are in:
# include <mln/level/transform.spe.hh>
@@ -53,7 +52,7 @@
namespace level
{
- /*! Transform the image \p input through a function \p f
+ /*! Transform the image \p input through a function \p f.
*
* \param[in] input The input image.
* \param[in] f The function.
@@ -67,95 +66,74 @@
transform(const Image<I>& input, const Function_v2v<F>& f);
- /*! Transform two images \p ima1 \p ima2 through a function \p f
+ /*! Transform two images \p input1 \p input2 through a function \p f.
*
- * \param[in] input The input image.
+ * \param[in] input1 The 1st input image.
+ * \param[in] input2 The 2nd input image.
* \param[in] f The function.
*
* This routine runs: \n
- * for all p of \p input, \p output(p) = \p f( \p input(p) ).
- *
+ * for all p of \p input, \p output(p) = \p f( \p input1(p), \p input2(p) ).
*/
- template <typename I, typename J, typename F>
- mln_ch_value(I, mln_result(F))
- transform(const Image<I>& ima1,
- const Image<J>& ima2,
+ template <typename I1, typename I2, typename F>
+ mln_ch_value(I1, mln_result(F))
+ transform(const Image<I1>& input1,
+ const Image<I2>& input2,
const Function_vv2v<F>& f);
+
# ifndef MLN_INCLUDE_ONLY
namespace internal
{
- template <typename I, typename F, typename O>
+
+ template <typename I, typename F>
inline
void transform_tests(const Image<I>& input,
- const Function_v2v<F>& f,
- Image<O>& output)
+ const Function_v2v<F>& f)
{
+ // Dynamic test.
+ mln_precondition(exact(input).has_data());
+
// Avoid a warning about an undefined variable when NDEBUG
// is not defined.
(void) input;
(void) f;
- (void) output;
-
- // Properties check
- mln_precondition((mlc_is(mln_trait_image_pw_io(O),
- trait::image::pw_io::read_write)::value ||
- mlc_is(mln_trait_image_vw_io(O),
- trait::image::vw_io::read_write)::value));
-
- // FIXME Convert test
- mlc_converts_to(mln_result(F), mln_value(O))::check();
-
-
- // Dynamic tests
- mln_precondition(exact(input).has_data());
- mln_precondition(exact(output).domain() >= exact(input).domain());
}
- template <typename I, typename J, typename F, typename O>
+ template <typename I1, typename I2, typename F>
inline
- void transform_tests(const Image<I>& ima1,
- const Image<J>& ima2,
- const Function_v2v<F>& f,
- Image<O>& output)
+ void transform_tests(const Image<I1>& input1,
+ const Image<I2>& input2,
+ const Function_vv2v<F>& f)
{
+ // Dynamic tests.
+ mln_precondition(exact(input1).has_data());
+ mln_precondition(exact(input2).has_data());
+ mln_precondition(exact(input2).domain() == exact(input1).domain());
+
// Avoid a warning about an undefined variable when NDEBUG
// is not defined.
- (void) ima1;
- (void) ima2;
+ (void) input1;
+ (void) input2;
(void) f;
- (void) output;
-
- // Properties check
- mln_precondition((mlc_is(mln_trait_image_pw_io(O),
- trait::image::pw_io::read_write)::value ||
- mlc_is(mln_trait_image_vw_io(O),
- trait::image::vw_io::read_write)::value));
-
- // FIXME Convert test
- mlc_converts_to(mln_result(F), mln_value(O))::check();
-
-
- // Dynamic tests
- mln_precondition(exact(ima1).has_data());
- mln_precondition(exact(ima2).has_data());
- mln_precondition(exact(ima1).domain() == exact(ima2).domain());
- mln_precondition(exact(output).domain() >= exact(ima1).domain());
}
} // end of namespace mln::level::internal
+
namespace impl
{
+ // Generic implementations.
+
+
namespace generic
{
- // Generic implementation.
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
@@ -166,11 +144,11 @@
const I& input = exact(input_);
const F& f = exact(f_);
- mln_precondition(exact(input).has_data());
+ level::internal::transform_tests(input, f);
+
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- level::internal::transform_tests(input, f, output);
mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
trait::image::pw_io::read_write)::check();
@@ -179,36 +157,33 @@
output(p) = f(input(p));
trace::exiting("level::impl::generic::transform");
-
return output;
}
- // Generic implementation.
- template <typename I, typename J, typename F>
+ template <typename I1, typename I2, typename F>
inline
- mln_ch_value(I, mln_result(F))
- transform(const Image<I>& ima1_,
- const Image<J>& ima2_,
+ mln_ch_value(I1, mln_result(F))
+ transform(const Image<I1>& input1_,
+ const Image<I2>& input2_,
const Function_vv2v<F>& f_)
{
trace::entering("level::impl::generic::transform");
- const I& ima1 = exact(ima1_);
- const I& ima2 = exact(ima2_);
+ const I1& input1 = exact(input1_);
+ const I2& input2 = exact(input2_);
const F& f = exact(f_);
- mln_ch_value(I, mln_result(F)) output;
- initialize(output, ima1);
+ level::internal::transform_tests(input1, input2, f);
-// level::internal::transform_tests(ima1, ima2, f, output);
+ mln_ch_value(I1, mln_result(F)) output;
+ initialize(output, input1);
- mln_piter(I) p(ima1.domain());
+ mln_piter(I1) p(input1.domain());
for_all(p)
- output(p) = f(ima1(p), ima2(p));
+ output(p) = f(input1(p), input2(p));
trace::exiting("level::impl::generic::transform");
-
return output;
}
@@ -217,7 +192,8 @@
} // end of namespace mln::level::impl
- // Facade.
+
+ // Facades.
template <typename I, typename F>
inline
@@ -226,30 +202,31 @@
{
trace::entering("level::transform");
+ internal::transform_tests(input, f);
+
mln_ch_value(I, mln_result(F)) output;
- output = impl::internal::transform_dispatch_(exact(input), exact(f));
+ output = impl::internal::transform_dispatch(exact(input), exact(f));
trace::exiting("level::transform");
-
return output;
}
- template <typename I, typename J, typename F>
+ template <typename I1, typename I2, typename F>
inline
- mln_ch_value(I, mln_result(F))
- transform(const Image<I>& ima1,
- const Image<J>& ima2,
+ mln_ch_value(I1, mln_result(F))
+ transform(const Image<I1>& input1,
+ const Image<I2>& input2,
const Function_vv2v<F>& f)
{
trace::entering("level::transform");
- mln_ch_value(I, mln_result(F)) output;
- output = impl::generic::transform(exact(ima1), exact(ima2), exact(f));
+ internal::transform_tests(input1, input2, f);
- trace::exiting("level::transform");
+ mln_ch_value(I1, mln_result(F)) output;
+ output = impl::generic::transform(input1, input2, f);
+ trace::exiting("level::transform");
return output;
-
}
Index: mln/level/transform_inplace.hh
--- mln/level/transform_inplace.hh (revision 0)
+++ mln/level/transform_inplace.hh (revision 0)
@@ -0,0 +1,226 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ // General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_LEVEL_TRANSFORM_INPLACE_HH
+# define MLN_LEVEL_TRANSFORM_INPLACE_HH
+
+/// \file mln/level/transform_inplace.hh
+///
+/// Transform inplace the contents of an image through a function.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/function.hh>
+
+
+namespace mln
+{
+
+ namespace level
+ {
+
+ /*! Transform inplace the image \p ima through a function \p f.
+ *
+ * \param[in,out] ima The image to be transformed.
+ * \param[in] f The function.
+ *
+ * This routine runs: \n
+ * for all p of \p ima, \p ima(p) = \p f( \p ima(p) ).
+ *
+ */
+ template <typename I, typename F>
+ void
+ transform_inplace(Image<I>& ima, const Function_v2v<F>& f);
+
+
+ /*! Transform inplace the image \p ima with the image \p aux
+ through a function \p f.
+ *
+ * \param[in] ima1 The image to be transformed.
+ * \param[in] aux The auxiliary image.
+ * \param[in] f The function.
+ *
+ * This routine runs: \n
+ * for all p of \p ima, \p ima(p) = \p f( \p ima(p), \p aux(p) ).
+ */
+ template <typename I1, typename I2, typename F>
+ void
+ transform_inplace(Image<I1>& ima, const Image<I2>& aux,
+ const Function_vv2v<F>& f);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename I, typename F>
+ inline
+ void transform_inplace_tests(const Image<I>& ima,
+ const Function_v2v<F>& f)
+ {
+ // Properties checks.
+ mlc_or(mlc_is(mln_trait_image_pw_io(I),
+ trait::image::pw_io::read_write),
+ mlc_is(mln_trait_image_vw_io(I),
+ trait::image::vw_io::read_write))::check();
+ mlc_converts_to(mln_result(F), mln_value(I))::check();
+
+ // Dynamic test.
+ mln_precondition(exact(ima).has_data());
+
+ // Avoid a warning.
+ (void) ima;
+ (void) f;
+ }
+
+ template <typename I1, typename I2, typename F>
+ inline
+ void transform_tests(const Image<I1>& ima,
+ const Image<I2>& aux,
+ const Function_v2v<F>& f)
+ {
+ // Properties checks.
+ mlc_or(mlc_is(mln_trait_image_pw_io(I1),
+ trait::image::pw_io::read_write),
+ mlc_is(mln_trait_image_vw_io(I1),
+ trait::image::vw_io::read_write))::check();
+ mlc_converts_to(mln_result(F), mln_value(I1))::check();
+
+ // Dynamic test.
+ mln_precondition(exact(ima).has_data());
+ mln_precondition(exact(aux).has_data());
+ mln_precondition(exact(aux).domain() == exact(ima).domain());
+
+ // Avoid a warning.
+ (void) ima;
+ (void) aux;
+ (void) f;
+ }
+
+ } // end of namespace mln::level::internal
+
+
+ namespace impl
+ {
+
+
+ namespace generic
+ {
+
+ // Generic implementation.
+ template <typename I, typename F>
+ inline
+ void
+ transform_inplace(Image<I>& ima_, const Function_v2v<F>& f_)
+ {
+ trace::entering("level::impl::generic::transform_inplace");
+
+ mlc_is(mln_trait_image_pw_io(I),
+ trait::image::pw_io::read_write)::check();
+
+ I& ima = exact(ima_);
+ const F& f = exact(f_);
+
+ level::internal::transform_inplace_tests(ima, f);
+
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ ima(p) = f(ima(p));
+
+ trace::exiting("level::impl::generic::transform_inplace");
+ }
+
+
+ // Generic implementation.
+ template <typename I1, typename I2, typename F>
+ inline
+ void
+ transform_inplace(Image<I1>& ima_, const Image<I2>& aux_,
+ const Function_vv2v<F>& f_)
+ {
+ trace::entering("level::impl::generic::transform_inplace");
+
+ mlc_is(mln_trait_image_pw_io(I1),
+ trait::image::pw_io::read_write)::check();
+
+ I1& ima = exact(ima_);
+ const I2& aux = exact(aux_);
+ const F& f = exact(f_);
+
+ level::internal::transform_inplace_tests(ima, aux, f);
+
+ mln_piter(I1) p(ima.domain());
+ for_all(p)
+ ima(p) = f(ima(p), aux(p));
+
+ trace::exiting("level::impl::generic::transform_inplace");
+ }
+
+ } // end of namespace mln::level::impl::generic
+
+
+ } // end of namespace mln::level::impl
+
+
+ // Facades.
+
+ template <typename I, typename F>
+ inline
+ void
+ transform_inplace(Image<I>& ima, const Function_v2v<F>& f)
+ {
+ trace::entering("level::transform_inplace");
+
+ level::internal::transform_inplace_tests(ima, f);
+ impl::generic::transform_inplace(ima, f);
+
+ trace::exiting("level::transform_inplace");
+ }
+
+ template <typename I1, typename I2, typename F>
+ void
+ transform_inplace(Image<I1>& ima, const Image<I2>& aux,
+ const Function_vv2v<F>& f)
+ {
+ trace::entering("level::transform_inplace");
+
+ level::internal::transform_inplace_tests(ima, aux, f);
+ impl::generic::transform_inplace(ima, aux, f);
+
+ trace::exiting("level::transform_inplace");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::level
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_TRANSFORM_INPLACE_HH
Index: mln/linear/ch_convolve.hh
--- mln/linear/ch_convolve.hh (revision 2825)
+++ mln/linear/ch_convolve.hh (working copy)
@@ -38,12 +38,18 @@
# include <mln/trait/ch_value.hh>
# include <mln/value/ops.hh>
+# include <mln/algebra/vec.hh>
+
/// Define the result of the convolution of an image with type \p I
/// with a weighted window of type \p W or weights of type \p W.
# define mln_ch_convolve(I, W) \
typename mln::linear::ch_convolve<I, W>::ret
+# define mln_ch_convolve_grad(I, W) \
+ typename mln::trait::ch_value< I, algebra::vec< I::site::dim, typename mln::linear::ch_convolve<I,W>::ret::value > >::ret
+
+
namespace mln
{
Index: mln/linear/sobel_2d.hh
--- mln/linear/sobel_2d.hh (revision 2821)
+++ mln/linear/sobel_2d.hh (working copy)
@@ -26,12 +26,12 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_LINEAR_SOBEL_HH
-# define MLN_LINEAR_SOBEL_HH
+#ifndef MLN_LINEAR_SOBEL_2D_HH
+# define MLN_LINEAR_SOBEL_2D_HH
-/// \file mln/linear/sobel.hh
+/// \file mln/linear/sobel_2d.hh
///
-/// Sobel filter.
+/// Sobel_2d filter.
/// \todo Extends to the case of other dimensions (only the 2-d case
/// is handled here).
@@ -42,24 +42,10 @@
# include <mln/arith/plus.hh>
# include <mln/level/abs.hh>
-# include <mln/fun/v2v/norm.hh>
-# include <mln/level/transform.hh>
-# include <mln/linear/line_x2_convolve.hh>
+# include <mln/fun/x2v/l1_norm.hh>
+# include <mln/fun/vv2v/vec.hh>
+# include <mln/linear/convolve_2x1d.hh>
-# include <mln/value/stack.hh>
-
-// FIXME: We might want to move these macros to another file, like
-// mln/core/gradient.hh.
-
-
-/// \brief Get the gradient component image type associated to image \a I.
-#define mln_gradient_component(I) \
- /* FIXME: Use mln_sum_x (or mln_sum_product) instead of mln_sum. */ \
- mln_ch_value(I, mln_sum(mln_value(I)))
-
-/// \brief Get the gradient image type associated to image \a I.
-#define mln_gradient(I) \
- mln::value::stack_image<I::point::dim, mln_gradient_component(I)>
namespace mln
@@ -68,194 +54,109 @@
namespace linear
{
- /// Sobel gradient components.
+ /// Sobel_2d gradient components.
/// \{
- /// Compute the vertical component of the Sobel gradient.
+ /// Compute the horizontal component of the 2D Sobel gradient.
template <typename I>
- mln_gradient_component(I) sobel_h(const Image<I>& input);
+ mln_ch_convolve(I, int)
+ sobel_2d_h(const Image<I>& input);
- /// Compute the horizontal component of the Sobel gradient.
+ /// Compute the vertical component of the 2D Sobel gradient.
template <typename I>
- mln_gradient_component(I) sobel_v(const Image<I>& input);
+ mln_ch_convolve(I, int)
+ sobel_2d_v(const Image<I>& input);
/// \}
- /// Compute the Sobel gradient of an image.
- ///
- /// \param[in] input A vectorial output image.
- /// \{
+ /// Compute the vertical component of the 2D Sobel gradient.
template <typename I>
- mln_gradient(I) sobel(const Image<I>& input);
- /// \}
-
- /// Compute the norm of the Sobel gradient of an image.
- ///
- /// \param input a vectorial input image
- /// \param norm a norm functor (\see mln/fun/v2v/norm.hh),
- /// defaulting to the L1-norm (mln::fun::v2v::l1_norm).
- /// \return the norm-image of the Sobel gradient of the input image
- /// FIXME: Add constraints on N (mln::Function_v2v<N>).
- /// \{
- template <typename I, typename N>
- mln_ch_value(I, mln_result(N)) sobel_norm(const Image<I>& input, N norm);
+ mln_ch_convolve_grad(I, int)
+ sobel_2d(const Image<I>& input);
/// \}
-
- /// \brief Compute the L-1 norm of the Sobel gradient of an image.
- ///
- /// This function is a shortcut for the general
- /// mln::linear::sobel_norm function.
- /// \{
+ /// Compute the L1 norm of the 2D Sobel gradient.
template <typename I>
- mln_ch_value(I, mln_sum(mln_value(I))) sobel_norm(const Image<I>& input);
+ mln_ch_convolve(I, int)
+ sobel_2d_l1_norm(const Image<I>& input);
/// \}
# ifndef MLN_INCLUDE_ONLY
-/// \brief Ensure type \p V is a scalar value.
-///
-/// For internal use only (#undef'd before the end of this file). (We
-/// might want to export this macro to the user interface; if so,
-/// rename it and move it elsewhere.)
-///
-/// FIXME: At the moment (rev. 1645), we cannot use mlc_is_a to check
-/// whether V derives from trait::value::nature::scalar like this
-///
-/// mlc_is_a(trait::value_<V>::nature, trait::value::nature::scalar)::check()
-///
-/// since `mlc_is_a' doesn't work on non template classes (yet). Hence
-/// the ugly workaround based on comprehensive checks.
-/// \{
-# define mlc_internal_ensure_is_scalar(V) \
- mlc_or(mlc_equal(typename mln::trait::value_<V>::nature, \
- mln::trait::value::nature::scalar), \
- mlc_or(mlc_equal(typename mln::trait::value_<V>::nature, \
- mln::trait::value::nature::integer), \
- mlc_equal(typename mln::trait::value_<V>::nature, \
- mln::trait::value::nature::floating)))::check()
-/// \}
- namespace impl
- {
+ // Facades.
template <typename I>
inline
- mln_gradient_component(I)
- sobel_h_(const Image<I>& input)
+ mln_ch_convolve(I, int)
+ sobel_2d_h(const Image<I>& input)
{
- // We don't use const ints here, since it would confuse the
- // STL allocators used within the windows used in the
- // convolutions.
- int wrow[] = { -1, 0, 1 };
- int wcol[] = { 1,
+ trace::entering("linear::sobel_2d_h");
+ mln_precondition(exact(input).has_data());
+
+ int wh[] = { -1, 0, 1 };
+ int wv[] = { 1,
2,
1 };
- // FIXME: It'd probably be nicer to have a "functional" version
- // of linear::line_x2_convolve.
- mln_gradient_component(I) output(exact(input).domain());
- linear::line_x2_convolve(input, wrow, wcol, output);
+ mln_ch_convolve(I, int) output = convolve_2x1d(input, wh, wv);
+
+ trace::exiting("linear::sobel_2d_h");
return output;
}
+
template <typename I>
inline
- mln_gradient_component(I)
- sobel_v_(const Image<I>& input)
+ mln_ch_convolve(I, int)
+ sobel_2d_v(const Image<I>& input)
{
- // We don't use const ints here, since it would confuse the
- // STL allocators used within the windows used in the
- // convolutions.
- int wrow[] = { 1, 2, 1 };
- int wcol[] = { -1,
+ trace::entering("linear::sobel_2d_v");
+ mln_precondition(exact(input).has_data());
+
+ int wh[] = { 1, 2, 1 };
+ int wv[] = { -1,
0,
+1 };
- // FIXME: It'd probably be nicer to have a "functional" version
- // of linear::line_x2_convolve.
- mln_gradient_component(I) output(exact(input).domain());
- linear::line_x2_convolve(input, wrow, wcol, output);
+ mln_ch_convolve(I, int) output = convolve_2x1d(input, wh, wv);
+
+ trace::exiting("linear::sobel_2d_v");
return output;
}
- template <typename I>
- inline
- mln_gradient(I)
- sobel_(const Image<I>& input)
- {
- /* FIXME: Not generic w.r.t. the dimension (only works on 2-D
- images here). Anyway, we'd need a n-dimensional definition
- of the Sobel gradient to.
-
- Stick with a very simple static assertion for the momemt,
- and improve later. */
- mlc_equal(metal::int_<I::point::dim>, metal::int_<2>)::check();
-
- mln_gradient_component(I) component_h = linear::sobel_h(input);
- mln_gradient_component(I) component_v = linear::sobel_v(input);
- return value::stack(component_h, component_v);
- }
- /* FIXME: Add constraints on N (mln::Function_v2v<N>). */
- template <typename I, typename N>
- mln_ch_value(I, mln_result(N))
- sobel_norm_(const Image<I>& input, N norm)
+ template <typename I>
+ mln_ch_convolve_grad(I, int)
+ sobel_2d(const Image<I>& input)
{
- mln_gradient(I) gradient = mln::linear::sobel (input);
- return level::transform (gradient, norm);
- }
-
- } // end of namespace mln::linear::impl
+ trace::entering("linear::sobel_2d");
+ mln_precondition(exact(input).has_data());
+ typedef mln_ch_convolve(I, int) J;
+ J h = sobel_2d_h(input),
+ v = sobel_2d_v(input);
+ fun::vv2v::vec<mln_value(J)> f;
+ mln_ch_convolve_grad(I, int) output = level::transform(h, v, f);
- // Facades.
-
- template <typename I>
- inline
- mln_gradient_component(I) sobel_h(const Image<I>& input)
- {
- mlc_internal_ensure_is_scalar(mln_value(I));
- return impl::sobel_h_(exact(input));
+ trace::exiting("linear::sobel_2d");
+ return output;
}
- template <typename I>
- inline
- mln_gradient_component(I) sobel_v(const Image<I>& input)
- {
- mlc_internal_ensure_is_scalar(mln_value(I));
- return impl::sobel_v_(exact(input));
- }
template <typename I>
- inline
- mln_gradient(I) sobel(const Image<I>& input)
+ mln_ch_convolve(I, int)
+ sobel_2d_l1_norm(const Image<I>& input)
{
- mlc_internal_ensure_is_scalar(mln_value(I));
- return impl::sobel_(exact(input));
- }
+ trace::entering("linear::sobel_2d_norm_l1");
+ mln_precondition(exact(input).has_data());
- template <typename I, typename N>
- inline
- mln_ch_value(I, mln_result(N))
- sobel_norm(const Image<I>& input, N norm)
- {
- mlc_internal_ensure_is_scalar(mln_value(I));
- return impl::sobel_norm_(exact(input), norm);
- }
+ typedef mln_ch_convolve_grad(I, int) G;
+ G grad = sobel_2d(input);
+ fun::x2v::l1_norm<mln_value(G)> f;
+ mln_ch_convolve(I, int) output = level::transform(grad, f);
- template <typename I>
- inline
- mln_ch_value(I, mln_sum(mln_value(I)))
- sobel_norm(const Image<I>& input)
- {
- // The type of a component of a vector from the gradient.
- typedef mln_sum(mln_value(I)) gradient_val_t;
- // The type of a vector from the gradient.
- typedef mln::algebra::vec<I::point::dim, gradient_val_t> gradient_vec_t;
- return sobel_norm(input,
- fun::v2v::l1_norm<gradient_vec_t, gradient_val_t>());
+ trace::exiting("linear::sobel_2d");
+ return output;
}
-# undef mlc_internal_ensure_is_scalar
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::linear
@@ -263,4 +164,4 @@
} // end of namespace mln
-#endif // ! MLN_LINEAR_SOBEL_HH
+#endif // ! MLN_LINEAR_SOBEL_2D_HH
Property changes on: mln/linear/sobel_2d.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: mln/make/image2d.hh
--- mln/make/image2d.hh (revision 2825)
+++ mln/make/image2d.hh (working copy)
@@ -60,8 +60,8 @@
image2d(V (&values)[S])
{
mlc_bool(S != 0)::check();
- enum { s = mlc_sqrt_int(S) / 2 };
- metal::bool_<((2 * s + 1) * (2 * s + 1) == S)>::check();
+ enum { s = mlc_sqrt_int(S) };
+ metal::bool_<(s * s == S)>::check();
mln::image2d<V> tmp;
convert::from_to(values, tmp);
return tmp;
Index: mln/fun/x2v/l1_norm.hh
--- mln/fun/x2v/l1_norm.hh (revision 0)
+++ mln/fun/x2v/l1_norm.hh (revision 0)
@@ -0,0 +1,81 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_FUN_X2V_L1_NORM_HH
+# define MLN_FUN_X2V_L1_NORM_HH
+
+/// \file mln/fun/x2v/l1_norm.hh
+///
+/// Define the L1-norm of an algebraic vector.
+
+# include <mln/core/concept/function.hh>
+# include <mln/algebra/vec.hh>
+# include <mln/math/abs.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace x2v
+ {
+
+ template <typename V>
+ struct l1_norm : public Function_v2v< l1_norm<V> >
+ {
+ typedef mln_coord(V) C;
+ typedef mln_sum(C) result;
+
+ result operator()(const V& v) const;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ typename l1_norm<V>::result
+ l1_norm<V>::operator()(const V& v) const
+ {
+ result res = 0;
+ for (unsigned i = 0; i < V::dim; ++i)
+ res += mln::math::abs(v[i]);
+ return res;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::x2v
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_X2V_L1_NORM_HH
Index: mln/fun/vv2v/all.hh
--- mln/fun/vv2v/all.hh (revision 2825)
+++ mln/fun/vv2v/all.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,10 +28,9 @@
#ifndef MLN_FUN_VV2V_ALL_HH
# define MLN_FUN_VV2V_ALL_HH
-/*! \file mln/fun/vv2v/all.hh
- *
- * \brief File that includes all functions from point to value.
- */
+/// \file mln/fun/vv2v/all.hh
+///
+/// File that includes all functions from point to value.
namespace mln
@@ -40,7 +39,7 @@
namespace fun
{
- /// Namespace of functions from point to value.
+ /// Namespace of functions from a couple of values to a value.
namespace vv2v
{
}
@@ -51,5 +50,7 @@
# include <mln/fun/vv2v/max.hh>
# include <mln/fun/vv2v/min.hh>
+# include <mln/fun/vv2v/vec.hh>
+
#endif // ! MLN_FUN_VV2V_ALL_HH
Index: mln/fun/vv2v/vec.hh
--- mln/fun/vv2v/vec.hh (revision 0)
+++ mln/fun/vv2v/vec.hh (revision 0)
@@ -0,0 +1,80 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_FUN_VV2V_VEC_HH
+# define MLN_FUN_VV2V_VEC_HH
+
+/// \file mln/fun/vv2v/vec.hh
+///
+/// computing the vecimum of two values using a functor.
+
+# include <mln/core/concept/function.hh>
+# include <mln/algebra/vec.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace vv2v
+ {
+
+ // FIXME: Doc.
+
+ /// \brief A functor computing the vecimum of two values.
+ template <typename V>
+ struct vec : public Function_vv2v< vec<V> >
+ {
+ typedef algebra::vec<2,V> result;
+ algebra::vec<2,V> operator()(const V& v1, const V& v2) const;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ algebra::vec<2,V>
+ vec<V>::operator()(const V& v1, const V& v2) const
+ {
+ algebra::vec<2,V> tmp;
+ tmp.set(v1, v2);
+ return tmp;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::vv2v
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_VV2V_VEC_HH
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Fix Update and Revamp Classif.
* inim/classif/max_tree.hh,
* inim/classif/display.hh,
* inim/classif/iccvg04.cc,
* inim/classif/proj.hh,
* inim/classif/v2.cc: Moved and update...
* inim/classif/src/max_tree.hh,
* inim/classif/src/display.hh,
* inim/classif/src/iccvg04.cc,
* inim/classif/src/proj.hh,
* inim/classif/src/v2.cc: ...here.
* inim/classif/Makefile: .
Makefile | 11 +--
src/iccvg04.cc | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/proj.hh | 83 +++++++++++++++++++++++++++
3 files changed, 263 insertions(+), 6 deletions(-)
Index: inim/classif/src/iccvg04.cc
--- inim/classif/src/iccvg04.cc (revision 0)
+++ inim/classif/src/iccvg04.cc (revision 0)
@@ -0,0 +1,175 @@
+#include <iostream>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/histo/data.hh>
+#include <mln/value/all.hh>
+
+#include <mln/level/fill.hh>
+
+#include <mln/morpho/closing_volume.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/morpho/opening_volume.hh>
+#include <mln/morpho/opening_area.hh>
+
+#include <mln/arith/revert.hh>
+#include <mln/morpho/meyer_wst.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/util/array.hh>
+#include <mln/labeling/compute.hh>
+
+#include <mln/geom/nrows.hh>
+#include <mln/geom/ncols.hh>
+#include <mln/geom/nslis.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/estim/min_max.hh>
+#include <mln/algebra/vec.hh>
+#include <mln/algebra/vec.hh>
+
+#include <mln/literal/all.hh>
+
+#include <mln/level/stretch.hh>
+
+#include <sys/stat.h>
+#include <sstream>
+#include <string.h>
+#include <stdlib.h>
+
+#include "proj.hh"
+#include "display.hh"
+
+using namespace mln;
+
+unsigned max = 0;
+
+template <typename I>
+mln::image3d<unsigned>
+fill_histo(const I& ima, int f)
+{
+ const value::int_u8 v = 255 / f; // FIXME
+ image3d<unsigned> histo(v,v,v);
+ level::fill(histo, 0);
+ unsigned i = 0;
+
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ {
+ point3d p3(ima(p).red() / f, ima(p).green() / f, ima(p).blue() / f);
+ histo(p3)++;
+ }
+ return histo;
+}
+
+template <typename I>
+void gplot(const I& ima)
+{
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ {
+ if (ima(p) != 0)
+ std::cout << p[0] << ' ' << p[1] << ' ' << p[2] << std::endl;
+ }
+}
+
+template <typename I, typename J, typename K>
+void
+classify_image(const I& ima, const J& histo, const K& ws, int nbasins, int f)
+{
+ unsigned border = 0;
+ unsigned count[nbasins + 1];
+ memset(count, 0, (nbasins + 1) * sizeof (unsigned));
+
+ algebra::vec<3, double> sum[nbasins + 1];
+ for (int i = 0; i < nbasins + 1; ++i)
+ sum[i] = literal::zero;
+
+ // Compute representatives of every class
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ {
+ point3d p3(ima(p).red() / f, ima(p).green() / f, ima(p).blue() / f);
+ int w = ws(p3);
+
+ //check if we are not on a border of the WS
+ if (w == 0)
+ border++;
+ count[w] += histo(p3);
+ sum[w] += histo(p3) * convert::to< algebra::vec<3, value::int_u8> >(p3);
+
+ std::cerr << "p3 : " << p3 << " == " <<
+ convert::to<algebra::vec<3, value::int_u8> >(p3) << std::endl;
+ }
+
+ std::cout << border << std::endl;
+ for (int i = 0; i < nbasins + 1; ++i)
+ {
+ std::cout << "sum[" << i << "] = " << sum[i] * f << " / " << count[i] << " == ";
+ sum[i] = (sum[i] * f) / count[i];
+ std::cout << sum[i] << std::endl;
+ }
+
+ // Make an output image where colors are replaced by their representatives.
+ mln_piter(I) pi(ima.domain());
+ I out(ima.domain());
+ for_all(pi)
+ {
+ //retrieve color class
+ value::rgb8 coul = ima(pi);
+ int w = ws(point3d(coul.red() / f, coul.green() / f, coul.blue() / f));
+
+ //if w == 0, out(pi) = 0 ie is part of a border of the watershed
+ if (w == 0)
+ out(pi) = literal::red;
+ else
+ out(pi) = convert::to<value::rgb8>(sum[w]);
+
+ std::cerr << "out(" << pi << ") = sum[" << w << "]; //"
+ << sum[w] << " : rgb8(" << sum[w] << ")" << std::endl;
+ }
+
+ io::ppm::save(out, "out.ppm");
+ save_class(histo, ws, sum, "palette.ppm");
+}
+
+bool usage(int argc, char ** argv)
+{
+ if (argc != 4)
+ {
+ std::cout << "usage: " << argv[0] << " image div_factor lambda" << std::endl;
+ return false;
+ }
+ return true;
+}
+
+
+int main(int argc, char **argv)
+{
+ if (not usage(argc, argv))
+ return 1;
+ const int div_factor = atoi(argv[2]);
+ const int lambda = atoi(argv[3]);
+
+ image2d<value::rgb8> ima;
+ ima = io::ppm::load<value::rgb8>(argv[1]);
+
+ //make histo
+ image3d<unsigned> histo = fill_histo(ima,div_factor);
+
+ //compute opening_volume of histo
+ image3d<unsigned> histo_filtered(histo.domain());
+ morpho::opening_volume(histo, c6(), lambda, histo_filtered);
+
+
+ //watershed over histo_closure
+ unsigned nbasins = 0;
+ image3d<unsigned> ws = morpho::meyer_wst(arith::revert(histo_filtered),
+ c6(), nbasins);
+ std::cout << "nbassins : " << nbasins << std::endl;
+
+ //classify image
+ classify_image(ima, histo, ws, nbasins, div_factor);
+}
Index: inim/classif/src/proj.hh
--- inim/classif/src/proj.hh (revision 0)
+++ inim/classif/src/proj.hh (revision 0)
@@ -0,0 +1,83 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_PROJ_HH
+# define MLN_PROJ_HH
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/level/paste.hh>
+#include <mln/accu/mean.hh>
+#include <mln/accu/maj_h.hh>
+#include <mln/literal/white.hh>
+
+namespace mln
+{
+
+ template <typename T, typename A>
+ image2d<mln_result(A)>
+ proj(const image3d<T>& input, A a)
+ {
+ image2d<A> acc(geom::nslis(input), geom::nrows(input));
+ mln_piter(image3d<T>) p(input.domain());
+ for_all(p) // 3d
+ if (input(p) != literal::zero)
+ acc.at(p.sli(), p.row()).take(input(p));
+
+ image2d<mln_result(A)> output(acc.domain());
+ level::paste(acc, output);
+ return output;
+ }
+
+ template <typename T, typename U, typename K>
+ void
+ save_class(const image3d<T>& histo, const image3d<U>& ws,
+ K mean, const char * fn)
+ {
+ accu::maj_h<value::int_u8> max_1;
+ image2d<value::int_u8> hproj = proj(histo, max_1);
+
+ accu::maj_h<value::int_u8> max_2;
+ image2d<value::int_u8> proj_class = proj(ws, max_2);
+
+ //std::cout << histo;
+
+ image2d<value::rgb8> out(proj_class.domain());
+
+ level::fill(out, literal::white);
+ mln_piter(image2d<value::int_u8>) p(hproj.domain());
+ for_all(p)
+ if (hproj(p) > 0)
+ out(p) = convert::to<value::rgb8>(mean[proj_class(p)]);
+
+ io::ppm::save(out, fn);
+ }
+
+} // end of namespace mln
+
+#endif /* MLN_PROJ_HH */
+
Index: inim/classif/Makefile
--- inim/classif/Makefile (revision 2824)
+++ inim/classif/Makefile (working copy)
@@ -2,7 +2,7 @@
# ICCVG
ICCVG_INCLUDES=-I../../..
-ICCVG_SRC=iccvg04.cc
+ICCVG_SRC=src/iccvg04.cc
ICCVG=iccvg
ICCVG_DBG=iccvg_dbg
@@ -10,10 +10,9 @@
DIV?=4
LAMBDA?=10
-
# V2
V2_INCLUDES=-I../../..
-V2_SRC=v2.cc max_tree.hh
+V2_SRC=src/v2.cc src/max_tree.hh
V2=v2
V2_DBG=v2_dbg
@@ -44,7 +43,7 @@
rm -f $(V2)
rm -f $(V2_DBG)
rm -f *.log
- rm -f .dep_iccvg .dep_v2
+ rm -f .dep_iccvg .dep_v2 .dep_iccvgr .dep_v2r
check-debug: $(ICCVG_DBG)
./iccvg_dbg $(IMG) $(DIV) $(LAMBDA) $(LOG)
@@ -74,12 +73,12 @@
.dep_iccvg:
- g++ $(ICCVG_INCLUDES) -MM iccvg04.cc > $@
+ g++ $(ICCVG_INCLUDES) -MM src/iccvg04.cc > $@
@sed -ir s/iccvg04.cc// .dep_iccvg
@sed -ir s/iccvg04.o/iccvg/ .dep_iccvg
.dep_v2:
- g++ $(V2_INCLUDES) -MM v2.cc > $@
+ g++ $(V2_INCLUDES) -MM src/v2.cc > $@
@sed -ir s/v2.cc// .dep_v2
@sed -ir s/v2.o/v2/ .dep_v2
1
0
06 Nov '08
URL: https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
ChangeLog:
2008-11-06 Matthieu Garrigues <garrigues(a)lrde.epita.fr>
Add arith::diff_abs.
* mln/arith/all.hh: add diff_abs.hh.
* mln/arith/diff_abs.hh: New, compute the absolute difference between
two images.
* mln/fun/vv2v/diff_abs.hh: New, diff_abs vv2v function.
* mln/level/transform.hh: Add a generic version of transform working
with 2 images and a vv2v functions.
* mln/math/all.hh: add diff_abs.hh.
* mln/math/diff_abs.hh: New, compute the absolute difference between
two values.
* tests/arith/Makefile.am: Add diff_abs test.
* tests/arith/diff_abs.cc: New, test arith::diff_abs.
* mln/core/clock_neighb.hh: Start to clean this neighboorhood.
Fix erosion on octogone.
* mln/morpho/erosion.spe.hh: Fix erosion on octogone by decomposing
the octogone with a vline, a hline, a diagonal and a backdiagonal. All
of these elements have a width of (width(oct) + 2) / 3.
---
mln/arith/all.hh | 1
mln/arith/diff_abs.hh | 86 +++++++++++++++++++++++++++++++++++++++++
mln/core/clock_neighb.hh | 36 ++++++++---------
mln/fun/vv2v/diff_abs.hh | 78 +++++++++++++++++++++++++++++++++++++
mln/level/transform.hh | 95 ++++++++++++++++++++++++++++++++++++++++++++++
mln/math/all.hh | 1
mln/math/diff_abs.hh | 63 ++++++++++++++++++++++++++++++
mln/morpho/erosion.spe.hh | 11 ++---
tests/arith/Makefile.am | 2
tests/arith/diff_abs.cc | 73 +++++++++++++++++++++++++++++++++++
10 files changed, 423 insertions(+), 23 deletions(-)
Index: branches/cleanup-2008/milena/tests/arith/diff_abs.cc
===================================================================
--- branches/cleanup-2008/milena/tests/arith/diff_abs.cc (revision 0)
+++ branches/cleanup-2008/milena/tests/arith/diff_abs.cc (revision 2824)
@@ -0,0 +1,73 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/*! \file tests/arith/diff_abs.cc
+ *
+ * \brief Tests on mln::arith::diff_abs.
+ */
+
+#include <mln/core/image/image2d.hh>
+#include <mln/debug/iota.hh>
+#include <mln/arith/diff_abs.hh>
+#include <mln/level/compare.hh>
+
+int main()
+{
+ using namespace mln;
+
+ trace::quiet = false;
+
+ {
+ image2d<int> ima(3,3);
+
+ int vs1[3][3] = {
+ {0, 1, 2},
+ {3, 4, 5},
+ {6, 7, 8}
+ };
+
+
+ int vs2[3][3] = {
+ {1, 0, 5},
+ {8, 5, 6},
+ {9, 5, 2}
+ };
+
+ int vs_ref[3][3] = {
+ {1, 1, 3},
+ {5, 1, 1},
+ {3, 2, 6}
+ };
+
+ image2d<int> ima1 = make::image(vs1);
+ image2d<int> ima2 = make::image(vs2);
+ image2d<int> ref = make::image(vs_ref);
+
+ mln_assertion (arith::diff_abs(ima1, ima2) == ref);
+ }
+
+}
Index: branches/cleanup-2008/milena/tests/arith/Makefile.am
===================================================================
--- branches/cleanup-2008/milena/tests/arith/Makefile.am (revision 2823)
+++ branches/cleanup-2008/milena/tests/arith/Makefile.am (revision 2824)
@@ -4,12 +4,14 @@
check_PROGRAMS = \
all_headers \
+ diff_abs \
minus \
plus \
revert \
times
all_headers_SOURCES = all_headers.cc
+diff_abs_SOURCES = diff_abs.cc
minus_SOURCES = minus.cc
plus_SOURCES = plus.cc
revert_SOURCES = revert.cc
Index: branches/cleanup-2008/milena/mln/core/clock_neighb.hh
===================================================================
--- branches/cleanup-2008/milena/mln/core/clock_neighb.hh (revision 2823)
+++ branches/cleanup-2008/milena/mln/core/clock_neighb.hh (revision 2824)
@@ -30,7 +30,7 @@
/*! \file mln/core/clock_neighb.hh
*
- * \brief Definition of the generic neighborhood class mln::clock_neighb_.
+ * \brief Definition of the generic neighborhood class mln::clock_neighb.
*/
# include <mln/core/concept/neighborhood.hh>
@@ -47,27 +47,27 @@
/*! \brief Generic neighborhood class.
*
- * This neighborhood of window is just like a set of delta-points.
- * The parameter is \c D, type of delta-point.
+ * This neighborhood of window is just like a set of delta-psites.
+ * The parameter is \c D, type of delta-psite.
*/
template <typename D>
- struct clock_neighb_ : public Neighborhood< clock_neighb_ <D> >
+ struct clock_neighb : public Neighborhood< clock_neighb <D> >
{
/// Dpsite associated type.
- typedef D dpoint;
+ typedef D dpsite;
/// Site associated type.
typedef mln_psite(D) point;
- /*! \brief Site_Iterator type to browse the points of a generic
- * neighborhood w.r.t. the ordering of delta-points.
+ /*! \brief Site_Iterator type to browse the psites of a generic
+ * neighborhood w.r.t. the ordering of delta-psites.
*/
typedef dpsites_fwd_piter<D> fwd_niter;
- /*! \brief Site_Iterator type to browse the points of a generic
- * neighborhood w.r.t. the reverse ordering of delta-points.
+ /*! \brief Site_Iterator type to browse the psites of a generic
+ * neighborhood w.r.t. the reverse ordering of delta-psites.
*
- * !!! Be careful the start delta point become the last now.
+ * !!! Be careful the start delta psite become the last now.
*/
typedef dpsites_bkd_piter<D> bkd_niter;
@@ -80,18 +80,18 @@
* The constructed neighborhood is empty. You have to use insert()
* to proceed to the neighborhood definition.
*/
- clock_neighb_();
+ clock_neighb();
- /*! \brief Insert a delta-point \p dp in the neighborhood
+ /*! \brief Insert a delta-psite \p dp in the neighborhood
* definition.
*
- * \param[in] dp The delta-point to insert.
+ * \param[in] dp The delta-psite to insert.
*
- * This method also insert the symmetrical delta-point, - \p dp,
+ * This method also insert the symmetrical delta-psite, - \p dp,
* in the neighborhood definition; thus the client has not to
* ensure the symmetry property; that is automatic.
*/
- clock_neighb_<D>& append(const D& dp);
+ clock_neighb<D>& append(const D& dp);
/// \}
const std::vector<D>& vect() const
{
@@ -106,14 +106,14 @@
template <typename D>
inline
- clock_neighb_<D>::clock_neighb_()
+ clock_neighb<D>::clock_neighb()
{
}
template <typename D>
inline
- clock_neighb_<D>&
- clock_neighb_<D>::append(const D& dp)
+ clock_neighb<D>&
+ clock_neighb<D>::append(const D& dp)
{
vec_.push_back(dp);
return *this;
Index: branches/cleanup-2008/milena/mln/math/all.hh
===================================================================
--- branches/cleanup-2008/milena/mln/math/all.hh (revision 2823)
+++ branches/cleanup-2008/milena/mln/math/all.hh (revision 2824)
@@ -44,6 +44,7 @@
# include <mln/math/abs.hh>
+# include <mln/math/diff_abs.hh>
# include <mln/math/jacobi.hh>
# include <mln/math/max.hh>
# include <mln/math/min.hh>
Index: branches/cleanup-2008/milena/mln/math/diff_abs.hh
===================================================================
--- branches/cleanup-2008/milena/mln/math/diff_abs.hh (revision 0)
+++ branches/cleanup-2008/milena/mln/math/diff_abs.hh (revision 2824)
@@ -0,0 +1,63 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MATH_DIFF_ABS_HH
+# define MLN_MATH_DIFF_ABS_HH
+
+/*! \file mln/math/diff_abs.hh
+ *
+ * \brief Define diff_abs routine.
+ */
+
+
+namespace mln
+{
+
+ namespace math
+ {
+
+ template <typename T>
+ T diff_abs(const T& v1, const T& v2);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename T>
+ inline
+ T diff_abs(const T& v1, const T& v2)
+ {
+ return abs(v1 - v2);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::math
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MATH_DIFF_ABS_HH
Index: branches/cleanup-2008/milena/mln/level/transform.hh
===================================================================
--- branches/cleanup-2008/milena/mln/level/transform.hh (revision 2823)
+++ branches/cleanup-2008/milena/mln/level/transform.hh (revision 2824)
@@ -67,6 +67,22 @@
transform(const Image<I>& input, const Function_v2v<F>& f);
+ /*! Transform two images \p ima1 \p ima2 through a function \p f
+ *
+ * \param[in] input The input image.
+ * \param[in] f The function.
+ *
+ * This routine runs: \n
+ * for all p of \p input, \p output(p) = \p f( \p input(p) ).
+ *
+ */
+ template <typename I, typename J, typename F>
+ mln_ch_value(I, mln_result(F))
+ transform(const Image<I>& ima1,
+ const Image<J>& ima2,
+ const Function_vv2v<F>& f);
+
+
# ifndef MLN_INCLUDE_ONLY
namespace internal
@@ -97,6 +113,38 @@
mln_precondition(exact(input).has_data());
mln_precondition(exact(output).domain() >= exact(input).domain());
}
+
+ template <typename I, typename J, typename F, typename O>
+ inline
+ void transform_tests(const Image<I>& ima1,
+ const Image<J>& ima2,
+ const Function_v2v<F>& f,
+ Image<O>& output)
+ {
+ // Avoid a warning about an undefined variable when NDEBUG
+ // is not defined.
+ (void) ima1;
+ (void) ima2;
+ (void) f;
+ (void) output;
+
+ // Properties check
+ mln_precondition((mlc_is(mln_trait_image_pw_io(O),
+ trait::image::pw_io::read_write)::value ||
+ mlc_is(mln_trait_image_vw_io(O),
+ trait::image::vw_io::read_write)::value));
+
+ // FIXME Convert test
+ mlc_converts_to(mln_result(F), mln_value(O))::check();
+
+
+ // Dynamic tests
+ mln_precondition(exact(ima1).has_data());
+ mln_precondition(exact(ima2).has_data());
+ mln_precondition(exact(ima1).domain() == exact(ima2).domain());
+ mln_precondition(exact(output).domain() >= exact(ima1).domain());
+ }
+
} // end of namespace mln::level::internal
@@ -135,6 +183,35 @@
return output;
}
+
+ // Generic implementation.
+ template <typename I, typename J, typename F>
+ inline
+ mln_ch_value(I, mln_result(F))
+ transform(const Image<I>& ima1_,
+ const Image<J>& ima2_,
+ const Function_vv2v<F>& f_)
+ {
+ trace::entering("level::impl::generic::transform");
+
+ const I& ima1 = exact(ima1_);
+ const I& ima2 = exact(ima2_);
+ const F& f = exact(f_);
+
+ mln_ch_value(I, mln_result(F)) output;
+ initialize(output, ima1);
+
+// level::internal::transform_tests(ima1, ima2, f, output);
+
+ mln_piter(I) p(ima1.domain());
+ for_all(p)
+ output(p) = f(ima1(p), ima2(p));
+
+ trace::exiting("level::impl::generic::transform");
+
+ return output;
+ }
+
} // end of namespace mln::level::impl::generic
@@ -157,6 +234,24 @@
return output;
}
+ template <typename I, typename J, typename F>
+ inline
+ mln_ch_value(I, mln_result(F))
+ transform(const Image<I>& ima1,
+ const Image<J>& ima2,
+ const Function_vv2v<F>& f)
+ {
+ trace::entering("level::transform");
+
+ mln_ch_value(I, mln_result(F)) output;
+ output = impl::generic::transform(exact(ima1), exact(ima2), exact(f));
+
+ trace::exiting("level::transform");
+
+ return output;
+
+ }
+
# endif // ! MLN_INCLUDE_ONLY
Index: branches/cleanup-2008/milena/mln/arith/all.hh
===================================================================
--- branches/cleanup-2008/milena/mln/arith/all.hh (revision 2823)
+++ branches/cleanup-2008/milena/mln/arith/all.hh (revision 2824)
@@ -54,6 +54,7 @@
}
+# include <mln/arith/diff_abs.hh>
# include <mln/arith/min.hh>
# include <mln/arith/minus.hh>
# include <mln/arith/plus.hh>
Index: branches/cleanup-2008/milena/mln/arith/diff_abs.hh
===================================================================
--- branches/cleanup-2008/milena/mln/arith/diff_abs.hh (revision 0)
+++ branches/cleanup-2008/milena/mln/arith/diff_abs.hh (revision 2824)
@@ -0,0 +1,86 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_ARITH_DIFF_ABS_HH
+# define MLN_ARITH_DIFF_ABS_HH
+
+/*! \file mln/arith/diff_abs.hh
+ *
+ * \brief Point-wise addition between images.
+ *
+ * \todo Speedup; some versions are not optimal.
+ */
+
+# include <mln/arith/includes.hh>
+# include <mln/fun/vv2v/diff_abs.hh>
+# include <mln/level/transform.hh>
+
+namespace mln
+{
+
+ namespace arith
+ {
+
+ /*! Point-wise absolute difference of images \p lhs and \p rhs.
+ *
+ * \param[in] lhs First operand image.
+ * \param[in] rhs Second operand image.
+ * \result The result image.
+ *
+ * \pre \p lhs.domain == \p rhs.domain
+ */
+ template <typename I>
+ mln_concrete(I)
+ diff_abs(const Image<I>& lhs, const Image<I>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ diff_abs(const Image<I>& lhs, const Image<I>& rhs)
+ {
+ trace::entering("arith::diff_abs");
+ mln_precondition(exact(lhs).has_data());
+ mln_precondition(exact(rhs).has_data());
+ mln_precondition(exact(rhs).domain() == exact(lhs).domain());
+
+ mln_concrete(I) output = level::transform(lhs, rhs, fun::vv2v::diff_abs<mln_value(I)>());
+
+ trace::exiting("arith::diff_abs");
+ return output;
+ }
+
+ } // end of namespace mln::arith
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ARITH_DIFF_ABS_HH
Index: branches/cleanup-2008/milena/mln/fun/vv2v/diff_abs.hh
===================================================================
--- branches/cleanup-2008/milena/mln/fun/vv2v/diff_abs.hh (revision 0)
+++ branches/cleanup-2008/milena/mln/fun/vv2v/diff_abs.hh (revision 2824)
@@ -0,0 +1,78 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_FUN_VV2V_DIFF_ABS_HH
+# define MLN_FUN_VV2V_DIFF_ABS_HH
+
+/// \file mln/fun/vv2v/diff_abs.hh
+/// \brief Computing the absolute difference between two values using
+/// a functor.
+
+# include <mln/core/concept/function.hh>
+# include <mln/math/diff_abs.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace vv2v
+ {
+
+ // FIXME: Doc.
+
+ /// \brief A functor computing the diff_absimum of two values.
+ template <typename V>
+ struct diff_abs : public Function_vv2v< diff_abs<V> >
+ {
+ typedef V result;
+ V operator()(const V& v1, const V& v2) const;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ V
+ diff_abs<V>::operator()(const V& v1, const V& v2) const
+ {
+ return mln::math::diff_abs(v1, v2);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::vv2v
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_VV2V_DIFF_ABS_HH
Index: branches/cleanup-2008/milena/mln/morpho/erosion.spe.hh
===================================================================
--- branches/cleanup-2008/milena/mln/morpho/erosion.spe.hh (revision 2823)
+++ branches/cleanup-2008/milena/mln/morpho/erosion.spe.hh (revision 2824)
@@ -295,12 +295,13 @@
const I& input = exact(input_);
- const unsigned len = win.length() / 3 + 1;
+ const unsigned len = (win.length() + 2) / 3;
- mln_concrete(I) temp_1, temp_2, output;
- temp_1 = morpho::erosion(input, win::hline2d(len));
- temp_2 = morpho::erosion(temp_1, win::diag2d(len));
- output = morpho::erosion(temp_2, win::backdiag2d(len));
+ mln_concrete(I) output;
+ output = morpho::erosion(input, win::hline2d(len));
+ output = morpho::erosion(output, win::vline2d(len));
+ output = morpho::erosion(output, win::diag2d(len));
+ output = morpho::erosion(output, win::backdiag2d(len));
trace::exiting("morpho::impl::erosion_(win::octagon2d)");
return output;
1
0
cleanup-2008 2823: Add fill_with_image_line specialization in fill_with_image routine.
by Nicolas Ballas 06 Nov '08
by Nicolas Ballas 06 Nov '08
06 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Add fill_with_image_line specialization in fill_with_image routine.
* tests/level/fill_with_image.cc: Add a new test.
* mln/level/paste.spe.hh: Add tests in paste_line.
* mln/level/fill_with_value.spe.hh: Update documentation.
* mln/level/fill_with_image.spe.hh: Add fill_with_image_line.
mln/level/fill_with_image.spe.hh | 49 +++++++++++++++++++++++++++++++--------
mln/level/fill_with_value.spe.hh | 1
mln/level/paste.spe.hh | 4 +--
tests/level/fill_with_image.cc | 15 +++++++++++
4 files changed, 57 insertions(+), 12 deletions(-)
Index: tests/level/fill_with_image.cc
--- tests/level/fill_with_image.cc (revision 2822)
+++ tests/level/fill_with_image.cc (working copy)
@@ -57,6 +57,21 @@
using namespace mln;
const unsigned size = 100;
+ // tests in two dimension
+ {
+ box2d b(point2d(1,2), point2d(2,4));
+ image2d<int> ima(b, 2);
+ debug::iota(ima);
+
+ box2d b2(point2d(-1,-2), point2d(3,6));
+ image2d<int> ima2(b2, 0);
+ debug::iota(ima2);
+
+ level::fill_with_image(ima, ima2); // Not so fast version...
+ mln_assertion(ima == (ima2 | b));
+ }
+
+
// 2d tests
{
image2d<unsigned int> ima(size, size);
Index: mln/level/paste.spe.hh
--- mln/level/paste.spe.hh (revision 2822)
+++ mln/level/paste.spe.hh (working copy)
@@ -32,7 +32,6 @@
*
* \brief Specializations for mln::level::paste.
*
- * \todo Rewrite the dispatch!!!
*/
# ifndef MLN_LEVEL_PASTE_HH
@@ -43,7 +42,7 @@
# include <mln/level/fill_with_value.hh>
# include <mln/level/memcpy_.hh>
# include <mln/core/box_runstart_piter.hh>
-# include <mln/border/all.hh>
+# include <mln/border/get.hh>
@@ -125,6 +124,7 @@
const I& input = exact(input_);
J& output = exact(output_);
+ level::internal::paste_tests(input, output);
mln_box_runstart_piter(I) p(input.domain());
for_all(p)
Index: mln/level/fill_with_value.spe.hh
--- mln/level/fill_with_value.spe.hh (revision 2822)
+++ mln/level/fill_with_value.spe.hh (working copy)
@@ -31,7 +31,6 @@
/// \file mln/level/fill_with_value.spe.hh
/// Specializations for mln::level::fill_with_value.
///
-/// \todo See todos in mln/level/fill.hh
# ifndef MLN_LEVEL_FILL_WITH_VALUE_HH
# error "Forbidden inclusion of *.spe.hh"
Index: mln/level/fill_with_image.spe.hh
--- mln/level/fill_with_image.spe.hh (revision 2822)
+++ mln/level/fill_with_image.spe.hh (working copy)
@@ -32,7 +32,6 @@
*
* \brief Specializations for mln::level::fill_with_image.
*
- * \todo Add specializations then rewrite the dispatch.
*/
# ifndef MLN_LEVEL_FILL_WITH_IMAGE_HH
@@ -41,9 +40,9 @@
# include <mln/level/memcpy_.hh>
# include <mln/level/fill_with_value.hh>
-
# include <mln/core/pixel.hh>
-
+# include <mln/core/box_runstart_piter.hh>
+# include <mln/border/get.hh>
# ifndef MLN_INCLUDE_ONLY
@@ -116,6 +115,26 @@
trace::exiting("level::impl::fill_with_image_fast");
}
+ template <typename I, typename J>
+ inline
+ void fill_with_image_lines(Image<I>& ima_, const Image<J>& data_)
+ {
+ trace::entering("level::impl::fill_with_image_lines");
+
+ I& ima = exact(ima_);
+ const J& data = exact(data_);
+
+ level::internal::fill_with_image_tests(ima, data);
+
+ mln_box_runstart_piter(I) p(ima.domain());
+ for_all(p)
+ {
+ pixel<J> dst(ima, p);
+ memcpy_(dst, make::pixel(data, p), p.run_length());
+ }
+
+ trace::exiting("level::impl::fill_with_image_lines");
+ }
template <typename I, typename J>
void fill_with_image_singleton(Image<I>& ima_,
@@ -149,10 +168,15 @@
I& ima = exact(ima_);
const J& data = exact(data_);
- if (ima.border() == data.border() &&
- sizeof(mln_value(I)) == sizeof(mln_value(J)))
+ if (sizeof(mln_value(I)) == sizeof(mln_value(J)))
+ {
+ if (border::get(ima) == border::get(data) &&
+ ima.domain() == data.domain())
impl::fill_with_image_fastest(ima, data);
else
+ impl::fill_with_image_lines(ima, data);
+ }
+ else
impl::fill_with_image_fast(ima, data);
}
@@ -162,12 +186,20 @@
mln::trait::image::value_access::direct,
mln::trait::image::ext_domain::none,
mln::trait::image::ext_domain::none,
- Image<I>& ima,
- const Image<J>& data)
+ Image<I>& ima_,
+ const Image<J>& data_)
{
+ I& ima = exact(ima_);
+ const J& data = exact(data_);
+
if (sizeof(mln_value(I)) == sizeof(mln_value(J)))
+ {
+ if (ima.domain() == data.domain())
impl::fill_with_image_fastest(ima, data);
else
+ impl::fill_with_image_lines(ima, data);
+ }
+ else
impl::fill_with_image_fast(ima, data);
}
@@ -219,8 +251,7 @@
if (mlc_is(mln_trait_image_value_alignement(I),
trait::image::value_alignement::with_grid)::value &&
mlc_is(mln_trait_image_value_alignement(J),
- trait::image::value_alignement::with_grid)::value &&
- ima.domain() == data.domain())
+ trait::image::value_alignement::with_grid)::value)
{
fill_with_image_(mln_trait_image_value_access(I)(),
mln_trait_image_value_access(J)(),
1
0
cleanup-2008 2822: Add paste_lines specialization for the level::paste routine.
by Nicolas Ballas 06 Nov '08
by Nicolas Ballas 06 Nov '08
06 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Add paste_lines specialization for the level::paste routine.
* mln/level/paste.spe.hh: Add paste_lines.
* mln/level/fill_with_value.spe.hh: Fix a dispatch.
fill_with_value.spe.hh | 4 --
paste.spe.hh | 75 ++++++++++++++++++++++++++++---------------------
2 files changed, 45 insertions(+), 34 deletions(-)
Index: mln/level/paste.spe.hh
--- mln/level/paste.spe.hh (revision 2821)
+++ mln/level/paste.spe.hh (working copy)
@@ -42,6 +42,8 @@
# include <mln/core/pixel.hh>
# include <mln/level/fill_with_value.hh>
# include <mln/level/memcpy_.hh>
+# include <mln/core/box_runstart_piter.hh>
+# include <mln/border/all.hh>
@@ -71,28 +73,6 @@
void paste(const Image<I>& input, Image<J>& output);
}
-// template <typename I, typename J>
-// inline
-// void paste_lines_(const I& data, J& destination)
-// {
-// trace::entering("level::impl::paste_lines_");
-// typedef mln_psite(I) P;
-// unsigned n = data.bbox().len(P::dim - 1);
-// // FIXME: Works only for raw data images
-// // FIXME: For linear data images, we should get the len for each line...
-
-// typename I::line_piter p(data.domain()); // FIXME: Alias mln_line_piter!
-// // mln_line_piter(I) p(data.domain());
-// for_all(p)
-// {
-// FIXME: TYPE pix = make::pixel(destination, p);
-// memcpy_(pix,
-// make::pixel(data, p),
-// n);
-// }
-// trace::exiting("level::impl::paste_lines_");
-// }
-
template <typename I, typename J>
void paste_fast(const Image<I>& input_, Image<J>& output_)
@@ -113,7 +93,7 @@
po.val() = pi.val();
po.next();
}
- trace::entering("level::impl::paste_fast");
+ trace::exiting("level::impl::paste_fast");
}
template <typename I, typename J>
@@ -133,7 +113,27 @@
memcpy_(dst, src, input.nelements());
- trace::entering("level::impl::paste_fastest");
+ trace::exiting("level::impl::paste_fastest");
+ }
+
+ template <typename I, typename J>
+ inline
+ void paste_lines(const Image<I>& input_, Image<J>& output_)
+ {
+ trace::entering("level::impl::paste_lines");
+
+ const I& input = exact(input_);
+ J& output = exact(output_);
+
+
+ mln_box_runstart_piter(I) p(input.domain());
+ for_all(p)
+ {
+ pixel<J> dst(output, p);
+ memcpy_(dst, make::pixel(input, p), p.run_length());
+ }
+
+ trace::exiting("level::impl::paste_lines");
}
template <typename I, typename J>
@@ -145,7 +145,7 @@
level::fill_with_value(output_, input.val());
- trace::entering("level::impl::paste_singleton");
+ trace::exiting("level::impl::paste_singleton");
}
} // end of namespace impl.
@@ -167,10 +167,15 @@
const I& input = exact(input_);
J& output = exact(output_);
- if (input.border() == output.border() &&
- sizeof(mln_value(I)) == sizeof(mln_value(J)))
+ if (sizeof(mln_value(I)) == sizeof(mln_value(J)))
+ {
+ if (border::get(input) == border::get(output) &&
+ input.domain() == output.domain())
impl::paste_fastest(input, output);
else
+ impl::paste_lines(input, output);
+ }
+ else
impl::paste_fast(input, output);
}
@@ -180,12 +185,21 @@
mln::trait::image::value_access::direct,
mln::trait::image::ext_domain::none,
mln::trait::image::ext_domain::none,
- const Image<I>& input,
- Image<J>& output)
+ const Image<I>& input_,
+ Image<J>& output_)
{
+ const I& input = exact(input_);
+ J& output = exact(output_);
+
+
if (sizeof(mln_value(I)) == sizeof(mln_value(J)))
+ {
+ if (input.domain() == output.domain())
impl::paste_fastest(input, output);
else
+ impl::paste_lines(input, output);
+ }
+ else
impl::paste_fast(input, output);
}
@@ -238,8 +252,7 @@
if (mlc_is(mln_trait_image_value_alignement(I),
trait::image::value_alignement::with_grid)::value &&
mlc_is(mln_trait_image_value_alignement(J),
- trait::image::value_alignement::with_grid)::value &&
- input.domain() == output.domain())
+ trait::image::value_alignement::with_grid)::value)
{
paste_(mln_trait_image_value_access(I)(),
mln_trait_image_value_access(J)(),
Index: mln/level/fill_with_value.spe.hh
--- mln/level/fill_with_value.spe.hh (revision 2821)
+++ mln/level/fill_with_value.spe.hh (working copy)
@@ -194,9 +194,7 @@
trait::image::vw_io::read_write,
Image<I>& ima, const V& val)
{
- // FIXME
- //impl::fill_with_value_cell_wise(ima, val);
- impl::generic::fill_with_value(ima, val);
+ impl::fill_with_value_cell_wise(ima, val);
}
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Tiny fix in windows.
* mln/core/w_window.hh (is_symmetric): New.
* mln/border/duplicate.hh: Fix typo.
* mln/win/sym.hh: Fix copyright.
(sym): Add trace.
border/duplicate.hh | 2 +-
core/w_window.hh | 18 +++++++++++++++++-
win/sym.hh | 14 ++++++++++----
3 files changed, 28 insertions(+), 6 deletions(-)
Index: mln/core/w_window.hh
--- mln/core/w_window.hh (revision 2820)
+++ mln/core/w_window.hh (working copy)
@@ -116,6 +116,9 @@
const mln::window<D>& win() const;
+ /// Test if the window is symmetric.
+ bool is_symmetric() const;
+
/// Apply a central symmetry to the window.
void sym();
@@ -278,11 +281,24 @@
template <typename D, typename W>
inline
+ bool
+ w_window<D,W>::is_symmetric() const
+ {
+ if (! win_.is_symmetric())
+ return false;
+ w_window<D,W> tmp;
+ tmp.sym();
+ return *this == tmp;
+ }
+
+ template <typename D, typename W>
+ inline
void
w_window<D,W>::sym()
{
w_window<D,W> tmp;
- for (unsigned i = 0; i < this->size(); ++i)
+ unsigned n = this->size();
+ for (unsigned i = 0; i < n; ++i)
tmp.insert(this->w(i), - this->dp(i));
*this = tmp;
}
Index: mln/border/duplicate.hh
--- mln/border/duplicate.hh (revision 2820)
+++ mln/border/duplicate.hh (working copy)
@@ -46,7 +46,7 @@
{
/*! Assign the virtual (outer) border of image \p ima with the
- * dupplicate of the inner border of this image.
+ * duplicate of the inner border of this image.
*
* \param[in,out] ima The image whose border is to be duplicated.
*
Index: mln/win/sym.hh
--- mln/win/sym.hh (revision 2820)
+++ mln/win/sym.hh (working copy)
@@ -1,4 +1,5 @@
// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,10 +29,9 @@
#ifndef MLN_WIN_SYM_HH
# define MLN_WIN_SYM_HH
-/*! \file mln/win/sym.hh
- *
- * \brief Give the symmetrical object.
- */
+/// \file mln/win/sym.hh
+///
+/// Give the symmetrical object.
# include <mln/core/concept/window.hh>
# include <mln/core/concept/weighted_window.hh>
@@ -61,8 +61,11 @@
inline
W sym(const Window<W>& win)
{
+ trace::entering("win::sym");
+ // mln_precondition(win.is_valid());
W tmp = exact(win);
tmp.sym();
+ trace::exiting("win::sym");
return tmp;
}
@@ -70,8 +73,11 @@
inline
W sym(const Weighted_Window<W>& w_win)
{
+ trace::entering("win::sym");
+ // mln_precondition(win.is_valid());
W tmp = exact(w_win);
tmp.sym();
+ trace::exiting("win::sym");
return tmp;
}
1
0