LRE
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
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
List overview
Download
Olena-patches
January 2009
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
olena-patches@lrde.epita.fr
9 participants
152 discussions
Start a n
N
ew thread
3187: Handle properly output in Laurent's method.
by Thierry Geraud
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog from Thierry Geraud <thierry.geraud(a)lrde.epita.fr> Handle properly output in Laurent's method. * laurent/ismm2009.cc: Sic. ismm2009.cc | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) Index: laurent/ismm2009.cc --- laurent/ismm2009.cc (revision 3186) +++ laurent/ismm2009.cc (working copy) @@ -16,6 +16,7 @@ # include <mln/core/site_set/p_queue.hh> # include <mln/core/site_set/p_priority.hh> +#include <mln/level/stretch.hh> #include <mln/labeling/compute.hh> #include <mln/accu/count.hh> @@ -478,9 +479,10 @@ compute_wst_g_from_f(f, g, e2p(), e2e(), n_basins, echo) ); + std::cout << "n basins = " << n_basins << std::endl; + if (echo) { - std::cout << "n basins = " << n_basins << std::endl; debug::println("g:", g); debug::println("wst(g):", wst_g); } @@ -970,6 +972,8 @@ mln_VAR(aa_line, aa | is_line); + A aa_max = 0; + { { @@ -990,6 +994,8 @@ // The attribute value propagates from the lca to the current edge // of the line: aa(e) = aa(e_); + if (aa(e) > aa_max) + aa_max = aa(e); } if (echo) @@ -1069,14 +1075,38 @@ // Output is salency map. + { + if (aa_max < 256) + { image2d<int_u8> output(f_.domain()); data::fill(output, 0); data::paste(aa_line, output); io::pgm::save(output, argv[3]); } + else + { + std::cerr << "warning: stretching [0," << aa_max << "] to int_u8" << std::endl; + + image2d<A> output(f_.domain()); + data::fill(output, 0); + data::paste(aa_line, output); + io::pgm::save(level::stretch(int_u8(), output), + argv[3]); +// image2d<int_u8> output(f_.domain()); +// data::fill(output, 0); +// A threshold = aa_max - 255; +// mln_piter(aa_line_t) e(aa_line.domain()); +// for_all(e) +// if (aa_line(e) <= threshold) +// output(e) = 1; +// else +// output(e) = aa_line(e) - threshold; +// io::pgm::save(output, argv[3]); + } + } } // end of main
15 years, 11 months
1
0
0
0
3185: Add important comment to bilinear.hh.
by Ugo Jardonnet
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr> Add important comment to bilinear.hh. * mln/fun/x2v/bilinear.hh: Add comment. bilinear.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: mln/fun/x2v/bilinear.hh --- mln/fun/x2v/bilinear.hh (revision 3185) +++ mln/fun/x2v/bilinear.hh (working copy) @@ -97,7 +97,7 @@ double y1 = std::floor(v[1]); double y2 = std::floor(v[1]) + 1; - //if (not ima.has(point2d(x1, y1))) return mln_value(I)(); + //Following access are supposed valid. vsum q11 = ima(point2d(static_cast<unsigned>(x1), static_cast<unsigned>(y1))); vsum q12 = ima(point2d(static_cast<unsigned>(x1), static_cast<unsigned>(y2))); vsum q21 = ima(point2d(static_cast<unsigned>(x2), static_cast<unsigned>(y1)));
15 years, 11 months
1
0
0
0
3185: Move INIM related projects into the appropriate directory.
by Thierry Geraud
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog from Thierry Geraud <thierry.geraud(a)lrde.epita.fr> Move INIM related projects into the appropriate directory. * garrigues/ocr: Move directory... * inim/ocr: ...here. * ballas/color: Move directory... * inim/color: ...here. * nature: Move directory... * inim/nature: ...here. ballas/color/README | 83 --- ballas/color/laplacien.cc | 130 ----- ballas/color/min_tree_area_filter.cc | 515 --------------------- ballas/color/min_tree_color.cc | 536 ---------------------- ballas/color/min_tree_color_v2.cc | 533 ---------------------- ballas/color/min_tree_height_filter.cc | 553 ----------------------- ballas/color/min_tree_volume_filter.cc | 551 ----------------------- ballas/color/reference.cc | 557 ----------------------- ballas/color/reference2.cc | 408 ----------------- ballas/color/src/convert.hh | 37 - ballas/color/src/distance.hh | 52 -- ballas/color/src/graph.hh | 62 -- ballas/color/src/io.hh | 57 -- garrigues/ocr/Makefile | 26 - garrigues/ocr/check.sh | 31 - garrigues/ocr/check_simple_point.cc | 61 -- garrigues/ocr/compute_local_configurations.cc | 74 --- garrigues/ocr/enlarge.hh | 202 -------- garrigues/ocr/ocr_with_preprocess.cc | 170 ------- garrigues/ocr/ocr_without_preprocess.cc | 90 --- garrigues/ocr/resize.hh | 96 ---- garrigues/ocr/simple_point.cc | 39 - garrigues/ocr/simple_point.hh | 206 -------- garrigues/ocr/skeleton.hh | 200 -------- garrigues/ocr/skeleton.old.cc | 30 - garrigues/ocr/skeleton.old.hh | 612 -------------------------- garrigues/ocr/tesseract_wrap.hh | 91 --- nature/Makefile | 24 - nature/closing.cc | 59 -- nature/co_occurence.hh | 77 --- nature/erosion.cc | 60 -- nature/fft.cc | 61 -- nature/gradient.cc | 60 -- nature/histo_hsi.cc | 181 ------- nature/hom.cc | 84 --- nature/mco.cc | 48 -- nature/nature.cc | 498 --------------------- nature/opening.cc | 59 -- nature/proj.cc | 68 -- nature/proj.hh | 64 -- nature/test.sh | 11 41 files changed, 7356 deletions(-) Index: garrigues/ocr/resize.hh --- garrigues/ocr/resize.hh (revision 3184) +++ garrigues/ocr/resize.hh (working copy) @@ -1,96 +0,0 @@ -// 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_GEOM_RESIZE_HH -# define MLN_GEOM_RESIZE_HH - -# include <mln/win/rectangle2d.hh> - -namespace mln -{ - - namespace geom - { - - - /*! - * \brief Resize an image \p input_ with \p ratio. - * - * \param[in] input_ The image to resize. - * \param[in] ratio The ratio of the resize image. - * - * \pre \p input_ has to be initialized. - * \pre \p ratio >= 1. - * - * \return The resized image. - */ - template <typename I> - mln_concrete(I) - resize(const Image<I>& input_, const unsigned ratio); - -# ifndef MLN_INCLUDE_ONLY - - - template <typename I> - mln_concrete(I) - resize(const Image<I>& input_, const unsigned ratio) - { - trace::entering("mln::geom::resize"); - - typedef mln_concrete(I) O; - - const I input = exact (input_); - - std::size_t rows = input.domain().len(0); - std::size_t cols = input.domain().len(1); - std::size_t new_rows = ratio * rows; - std::size_t new_cols = ratio * cols; - - O output(new_rows, new_cols); - - mln_piter(O) p(output.domain()); - - for_all(p) - { - output(p) = input(point2d(p[0] / ratio, p[1] / ratio)) ? 255 : 0; - } - - trace::exiting("mln::geom::resize"); - return output; - - } - -# endif // ! MLN_INCLUDE_ONLY - - - } // end of namespace mln::geom - -} // end of namespace mln - - - -#endif // ! MLN_GEOM_RESIZE_HH Index: garrigues/ocr/ocr_without_preprocess.cc --- garrigues/ocr/ocr_without_preprocess.cc (revision 3184) +++ garrigues/ocr/ocr_without_preprocess.cc (working copy) @@ -1,90 +0,0 @@ -// 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. - -#include <iostream> - -#include <mln/core/image/image2d.hh> -#include <mln/core/alias/window2d.hh> -#include <mln/core/alias/neighb2d.hh> - -#include <mln/core/image/cast_image.hh> - -#include <mln/value/int_u8.hh> - -#include "resize.hh" -#include "enlarge.hh" -//#include "skeleton.hh" -#include <mln/linear/gaussian.hh> - -#include <mln/trace/all.hh> -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> -#include <mln/io/pbm/load.hh> -#include <mln/io/pbm/save.hh> -#include <mln/core/alias/w_window2d_float.hh> - -#include <mln/debug/println.hh> -#include <mln/geom/chamfer.hh> -#include <mln/make/win_chamfer.hh> -#include <mln/labeling/regional_maxima.hh> -#include <mln/morpho/dilation.hh> - -#include "tesseract_wrap.hh" - -// _COMPILATION_ -// g++ -DNDEBUG -O3 -I../../.. ocr.cc -L/usr/lib -ltesseract_full -lpthread - - -// Call tesseract -// lang: expected language - -int main(int argc, char** argv) -{ - using namespace mln; - using value::int_u8; - - image2d<bool> input; - - if (argc < 2) - { - std::cerr << "Usage: " << argv[0] << " in.pbm" << std::endl; - return 1; - } - - mln::border::thickness = 0; - - io::pbm::load(input, argv[1]); - - { - image2d<int_u8> tmp = duplicate(cast_image<int_u8>(input)); - float score = 0; - char* s = tesseract("fra", tmp, &score); - std::cerr << "Tesseract result: (score " << score << ")" << std::endl; - std::cout << s; - delete[] s; - } -} Index: garrigues/ocr/skeleton.old.hh --- garrigues/ocr/skeleton.old.hh (revision 3184) +++ garrigues/ocr/skeleton.old.hh (working copy) @@ -1,612 +0,0 @@ -// 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 SKELETON_HH -# define SKELETON_HH - -#include <mln/core/image/image2d.hh> -#include <mln/core/alias/neighb2d.hh> -#include <sandbox/aroumougame/skeleton/sedt.hh> - -#include <mln/core/site_set/p_set.hh> -#include <mln/math/sqrt.hh> -#include <mln/opt/at.hh> - -namespace mln -{ - - -template <typename P> - std::vector< std::pair< double, P > > remove(std::vector< std::pair< double, P > > Q, P p) -{ - typename std::vector<std::pair< double, P > >::iterator it; - - for(it = Q.begin(); it!=Q.end(); it++) - { - if((*it).second==p) - { - it = Q.erase(it); - break; - } - } - return Q; -} -template <typename N> - double distance(N a, N b, N c, N d) -{ - double dist = sqrt((a-c)*(a-c)+(b-d)*(b-d)); - return dist; -} -template <typename P> - std::vector< std::pair< double, P > > insertDicho(std::vector< std::pair< double, P > > Q, std::pair< double, P> p) -{ - int indMin, indMax, indMid; - - indMin = 0; - indMax = Q.size(); - - if(indMax==0 || Q[indMax-1].first <= p.first) - Q.push_back(p); - else - { - while(indMax > indMin) - { - indMid = int(indMin + (indMax-indMin)/2); - if(Q[indMid].first < p.first) - { - indMin = indMid+1; - if(Q[indMin].first > p.first) - { - indMax = indMid; - } - } - else - { - indMax = indMid-1; - if(Q[indMax].first < p.first) - { - indMin = indMid; - } - } - } - - typename std::vector< std::pair< double, P > >::iterator it=Q.begin(); - it = Q.insert ( it+indMin, p); - } - - return Q; -} - - -const neighb2d& complement_neighborhood(const Neighborhood<neighb2d>& nbh) -{ - if(&nbh == &c4()) - return c8(); - return c4(); -} - -template <typename N> - int nb_composant_connexe(p_set< mln_psite(N) > X_full,const Neighborhood<N>& nbh_,const mln_psite(N)& p_ref, bool local) -{ - N nbh = exact(nbh_); - p_set< mln_psite(N) > X; - if(local) - { - mln_niter(N) n(max_neighborhood(nbh), p_ref); - - for_all(n) - { - if (X_full.has(n)) - X.insert(n); - } - } - else - { - X = X_full; - } - - int T; - p_set< mln_psite(N) > done; - p_set< mln_psite(N) > neighbors; - p_set< mln_psite(N) > composant; - - done.insert(p_ref); - mln_niter(N) q(nbh, p_ref); - for_all(q) - { - if (X.has(q)&&!done.has(q)) - { - neighbors.insert(q); - } - } -// std::cout << "nb_composant_connexe: neighbors " << neighbors.nsites() <<std::endl; - if(neighbors.nsites()<=1) - { - return neighbors.nsites(); - } - else - T=0; - - while(neighbors.nsites()!=0) - { - T++; - done.insert(neighbors[0]); - mln_niter(N) t(nbh, neighbors[0]); - neighbors.remove(neighbors[0]); - for_all(t) - { - if (X.has(t)&&!done.has(t)) - { - composant.insert(t); - } - } - - while(composant.nsites()!=0) - { - done.insert(composant[0]); - if(neighbors.has(composant[0])) - { - neighbors.remove(composant[0]); - if(neighbors.nsites()==0) - return T; - } - - mln_niter(N) r(nbh, composant[0]); - composant.remove(composant[0]); - for_all(r) - { - if (X.has(r) && !done.has(r)) - { - composant.insert(r); - } - } - } - } - return T; -} - -template <typename N> - bool simple_point(p_set< mln_psite(N) > X,const Neighborhood<N>& nbh, p_set< mln_psite(N) > X_complement, const mln_psite(N)& p_ref, bool local) -{ - int nX = nb_composant_connexe(X,exact(nbh),p_ref,local); - int nX_complement = nb_composant_connexe(X_complement,complement_neighborhood(exact(nbh)),p_ref,local); - - if((nX_complement == 1)&&(nX == 1)) - return true; - return false; -} - - - template <typename N> - p_set<mln_psite(N)> euclideanSkeleton(p_set<mln_psite(N)> X, p_set<mln_psite(N)> X_complement, image2d<value::int_u8> dt, p_set<mln_psite(N)>& Y, const Neighborhood<N>& nbh_, bool local) - { - std::vector< std::pair< double, mln::point2d> > Q; - std::vector< std::pair< double, mln::point2d> > R; - N nbh = exact(nbh_); - - // fill Q - for (uint i = 0; i < X.nsites(); i++) - { - if (!Y.has(X[i])) - { - std::pair<double, mln_psite(N)> p(math::sqrt(double(dt(X[i]))),X[i]); - Q = insertDicho(Q,p); - } - } - - // fill R - for (uint i = 0; i < X.nsites(); i++) - { - if (!Y.has(X[i])) - { - double min = 1023.99; - mln_niter(N) r(nbh, X[i]); - for_all(r) - { - if (Y.has(r)) - { - double tmp = distance(r[0], r[1], X[i][0], X[i][1]); - double d = math::sqrt(double(dt(r)))+(math::sqrt(double(dt(X[i])))-math::sqrt(double(dt(r))))/tmp; - min = math::min(min,d); - } - } - if (min!=1023.99) - { - std::pair<double, mln_psite(N)> p(min,X[i]); - R = insertDicho(R, p); - } - } - } - - while (!Q.empty() || !R.empty()) - { - mln_psite(N) tmp; - if (Q[0].first < R[0].first) - { - tmp = Q[0].second; - } - else - { - tmp = R[0].second; - } - - Q = remove(Q, tmp); - R = remove(R, tmp); - - if (!Y.has(tmp) && X.has(tmp)) - { - if (simple_point(X, nbh, X_complement, tmp, local)) - { - X.remove(tmp); - X_complement.insert(tmp); - } - else - { - Y.insert(tmp); - mln_niter(N) r(nbh, tmp); - for_all(r) - { - if (!Y.has(r) && X.has(r)) - { - double dist = distance(r[0], r[1], tmp[0], tmp[1]); - double d = math::sqrt(double(dt(tmp)))+(math::sqrt(double(dt(r)))-math::sqrt(double(dt(tmp))))/dist; - std::pair<double, mln_psite(N)> p(d,r); - R = insertDicho(R, p); - } - } - - } - } - - } - return X; - } - - - p_set<point2d> EP(image2d<value::int_u8> dt, point2d x, std::vector< std::vector<std::pair< int, int> > > lut, const neighb2d& nbh) - { - p_set<point2d> EP; - p_set<point2d> tmp; - int w = geom::ncols(dt); - int h = geom::nrows(dt); - - - mln_niter_(neighb2d) r(nbh, x); - for_all(r) - { - if (dt(r) <= dt(x)) - { - for (uint i=0; i<lut[dt(r)].size(); i++) - { - if ((r[0]+lut[dt(r)][i].first < h) && (r[1]+lut[dt(r)][i].second < w)) - { - if (!dt(r+dpoint2d(lut[dt(r)][i].first, lut[dt(r)][i].second))) - EP.insert(r+dpoint2d(lut[dt(r)][i].first, lut[dt(r)][i].second)); - } - if ((r[0]-lut[dt(r)][i].first >= 0) && (r[1]-lut[dt(r)][i].second >= 0)) - { - if (!dt(r+dpoint2d(-lut[dt(r)][i].first, -lut[dt(r)][i].second))) - EP.insert(r+dpoint2d(-lut[dt(r)][i].first, -lut[dt(r)][i].second)); - } - if ((r[0]+lut[dt(r)][i].first < h) && (r[1]-lut[dt(r)][i].second >= 0)) - { - if (!dt(r+dpoint2d(lut[dt(r)][i].first, -lut[dt(r)][i].second))) - EP.insert(r+dpoint2d(lut[dt(r)][i].first, -lut[dt(r)][i].second)); - } - if ((r[0]-lut[dt(r)][i].first >= 0) && (r[1]+lut[dt(r)][i].second < w)) - { - if (!dt(r+dpoint2d(-lut[dt(r)][i].first, lut[dt(r)][i].second))) - EP.insert(r+dpoint2d(-lut[dt(r)][i].first, lut[dt(r)][i].second)); - } - if ((r[0]+lut[dt(r)][i].second < h) && (r[1]+lut[dt(r)][i].first < w)) - { - if (!dt(r+dpoint2d(lut[dt(r)][i].second, lut[dt(r)][i].first))) - EP.insert(r+dpoint2d(lut[dt(r)][i].second, lut[dt(r)][i].first)); - } - if ((r[0]-lut[dt(r)][i].second >= 0) && (r[1]-lut[dt(r)][i].first >= 0)) - { - if (!dt(r+dpoint2d(-lut[dt(r)][i].second, -lut[dt(r)][i].first))) - EP.insert(r+dpoint2d(-lut[dt(r)][i].second, -lut[dt(r)][i].first)); - } - if ((r[0]+lut[dt(r)][i].second < h) && (r[1]-lut[dt(r)][i].first >= 0)) - { - if (!dt(r+dpoint2d(lut[dt(r)][i].second, -lut[dt(r)][i].first))) - EP.insert(r+dpoint2d(lut[dt(r)][i].second, -lut[dt(r)][i].first)); - } - if ((r[0]-lut[dt(r)][i].second >= 0) && (r[1]+lut[dt(r)][i].first < w)) - { - if (!dt(r+dpoint2d(-lut[dt(r)][i].second, lut[dt(r)][i].first))) - EP.insert(r+dpoint2d(-lut[dt(r)][i].second, lut[dt(r)][i].first)); - } - } - } - } - - return EP; - } - - std::vector< std::vector<std::pair< int, int> > > Lut2d(int N) - { - int n = int(sqrt(N))+1; - int i=0; - std::vector< std::vector<std::pair< int, int> > > lut; - - for(i = 0; i <= N; i++) - { - std::vector<std::pair< int, int> > vect; - lut.push_back(vect); - } - - for(int x = 0; x <= n; x++) - { - for(int y = 0; y <= x; y++) - { - i=x*x+y*y; - if(i<=N) - { - std::pair<int,int> p(x,y); - lut[i].push_back(p); - } - } - } - - return lut; -} - - image2d<value::int_u8> DiscreteBisector(image2d<value::int_u8> dt, p_set<point2d> Y, const neighb2d& nbh, int N) - { - int w = geom::ncols(dt); - int h = geom::nrows(dt); - - int ux,uy,vx,vy, produit, angle, max; - double cos, normu, normv; - - std::vector< std::vector<std::pair< int, int> > > lut; - lut = Lut2d(N); - - p_set<point2d> proj; - - image2d<value::int_u8> bisector(h, w); - data::fill(bisector, 0); - - for (uint i=0; i<Y.nsites(); i++) - { - proj = EP(dt, Y[i], lut, nbh); - - int n=proj.nsites(); - - if (n>1) - { - max = 0; - for (int y=0; y<n; y++) - { - for (int z=0; z<y; z++) - { - ux = proj[y][0]-Y[i][0]; - uy = proj[y][1]-Y[i][1]; - vx = proj[z][0]-Y[i][0]; - vy = proj[z][1]-Y[i][1]; - - produit = ux * vx + uy * vy; - - normu = sqrt(ux*ux + uy*uy); - normv = sqrt(vx*vx + vy*vy); - - cos = produit/(normu*normv); - angle = int(acos(cos)*180.0/3.1415); - - max = math::max(max, angle); - } - } - bisector(Y[i]) = max; - } - - } - - return bisector; - - } - - - -const neighb2d& max_neighborhood(const Neighborhood<neighb2d>& nbh) -{ - return c8(); -} -template <typename N> - p_set<mln_psite(N)> ultimateSkeleton(p_set<mln_psite(N)> X, p_set<mln_psite(N)> X_complement, image2d<value::int_u8> dt, p_set<mln_psite(N)> Y, const Neighborhood<N>& nbh_, bool local) -{ - std::vector< std::pair< double, mln::point2d> > Q; - - N nbh = exact(nbh_); - // fill Q - for(uint i = 0; i < X.nsites(); i++) - { - if (!Y.has(X[i])) - { - std::pair<double, mln_psite(N)> p(dt(X[i]),X[i]); - Q = insertDicho(Q,p); - } - } - - - while(!Q.empty()) - { - mln_psite(N) tmp = Q[0].second; - - Q = remove(Q, tmp); - - if(simple_point(X, nbh, X_complement, tmp, local)) - { - X.remove(tmp); - X_complement.insert(tmp); - mln_niter(N) r(nbh, tmp); - for_all(r) - { - if(!Y.has(r) && X.has(r)) - { - std::pair<double, mln_psite(N)> p(dt(r),r); - Q = insertDicho(Q, p); - } - } - } - - } - return X; -} - - image2d<value::int_u8> intImage(image2d<bool> pic) -{ - int w = geom::ncols(pic); - int h = geom::nrows(pic); - - image2d<value::int_u8> out(h,w); - for(int i=0; i<w; i++) - for(int j=0; j<h; j++) - { - if(opt::at(pic, j,i)) - opt::at(out, j,i) = 1; - else - opt::at(out, j,i) = 0; - } - return out; -} - image2d<bool> filteredSkeleton(image2d<bool> pic, const neighb2d& nbh, uint r, uint alpha, bool local) - { - using value::int_u8; - - typedef image2d<bool> I; - typedef p_set<point2d> S; - - image2d<value::int_u8> pic1 = intImage(pic); - image2d<value::int_u8> dt = sedt(pic1); - - mln::io::pgm::save(dt, "dt.pgm"); - - int w = geom::ncols(pic); - int h = geom::nrows(pic); - int l= math::min(w, h); - uint rmax = getRMax(dt); - uint rknown = 0; - p_set<point2d> X,Y,Z; - p_set<point2d> X_complement, Z_complement; - - image2d<value::int_u8> DTg(l,l,0); - std::vector< std::vector<int> > Mgl; - std::vector< std::vector<int> > Lut; - - Mgl = CompLutMask (DTg,Mgl,Lut,l,0,rmax); - - rknown =rmax; - - mln_fwd_piter_(image2d<bool>) p(pic.domain()); - - for_all(p) - { - if (pic(p)==1) - { - X.insert(p); - } - else - { - X_complement.insert(p); - } - } - std::cout << " medial axis " << std::endl; - pic = MA(pic, Mgl, dt, Lut); - - mln::io::pbm::save(pic, "ma.pbm"); - - for_all(p) - { - if (pic(p)==1) - { - Y.insert(p); - } - } - - std::cout << " euclidean skeleton " << std::endl; - Z = euclideanSkeleton(X, X_complement, dt, Y, nbh, local); - - sub_image<I, S> es = pic | Z; - I es1(pic.domain()); - data::fill(es1, false); - - data::paste(es, es1); - - mln::io::pbm::save(es1, "euclidean.pbm"); - - for_all(p) - { - if (!Z.has(p)) - { - Z_complement.insert(p); - } - } - std::cout << " discrete bisector " << std::endl; - pic1 = DiscreteBisector(dt, Y, nbh, rmax); - - - mln::io::pgm::save(pic1, "bisector.pgm"); - - uint cpt=0; - while (cpt!=Y.nsites()) - { - if (dt(Y[cpt])>=r && pic1(Y[cpt])>=alpha) - { - cpt++; - } - else - { - Y.remove(Y[cpt]); - } - } - - - sub_image<I, S> skel = pic | Y; - I test(pic.domain()); - data::fill(test, false); - - data::paste(skel, test); - - mln::io::pbm::save(test, "Y.pbm"); - - std::cout << " ultimate skeleton " << std::endl; - Z = ultimateSkeleton(Z, Z_complement, dt, Y, nbh, local); - - - - sub_image<I, S> skeleton = pic | Z; - I output(pic.domain()); - data::fill(output, false); - - data::paste(skeleton, output); - - return output; - } - -} // End of namespace mln -#endif // ! SKELETON_HH Index: garrigues/ocr/simple_point.hh --- garrigues/ocr/simple_point.hh (revision 3184) +++ garrigues/ocr/simple_point.hh (working copy) @@ -1,206 +0,0 @@ -// 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_SIMPLE_POINT_HH -# define MLN_SIMPLE_POINT_HH - -/*! \file simple_point.hh - * - * \brief is_simple_point tell if a point is simple or not (Cf - * bertrand.07.chap). - * - */ - -#include <mln/core/alias/point2d.hh> -#include <mln/core/image/image2d.hh> -#include <mln/core/alias/neighb2d.hh> - -namespace mln -{ - -/*! Tell if a point is simple or not. A point of an object is simple - * if in its c8 neiborhood, there is exactly one connected component of the - * object, and only one connected component of the background - * Examples : ( | == object, - = background) - * - * - - | - * | P | Here p is simple in the c4 and c8 case. - * | | | - * - * - | - - * | P | Here p is never simple. - * | | | - * - */ - - bool is_simple_point(const image2d<bool>& ima, const neighb2d& nbh, const point2d& p); - - unsigned nb_connexity2d(const image2d<bool>& ima, const neighb2d& nbh, const point2d& p); - - bool is_curve_extremum(const image2d<bool>& ima, unsigned nbh, const point2d& p); - -# ifndef MLN_INCLUDE_ONLY - - static const unsigned char nb_connexity_c8[256] = - { - 0, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, - 1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, - 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, - - 1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, - 1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, - 2, 3, 3, 3, 3, 4, 3, 3, 2, 2, 2, 2, 3, 3, 2, 2, - 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, - - 1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - }; - - static const unsigned char nb_connexity_c4[256] = - { - 0, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 2, 1, - 1, 2, 2, 2, 1, 2, 1, 1, 2, 2, 3, 2, 2, 2, 2, 1, - 1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 1, - 2, 3, 3, 3, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 1, - - 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3, 3, 3, 2, - 2, 3, 3, 3, 2, 3, 2, 2, 3, 3, 4, 3, 3, 3, 3, 2, - 1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 1, - 2, 3, 3, 3, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 1, - - 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3, 3, 3, 2, - 1, 2, 2, 2, 1, 2, 1, 1, 2, 2, 3, 2, 2, 2, 2, 1, - 2, 3, 3, 3, 3, 4, 3, 3, 2, 2, 3, 2, 3, 3, 3, 2, - 2, 3, 3, 3, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 1, - - 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3, 3, 3, 2, - 1, 2, 2, 2, 1, 2, 1, 1, 2, 2, 3, 2, 2, 2, 2, 1, - 1, 2, 2, 2, 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 1, - 1, 2, 2, 2, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1 - }; - - neighb2d int_to_neighb(unsigned i) - { - if (i == 8) - return c8(); - if (i == 4) - return c4(); - mln_assertion(0); - return c4(); - } - - unsigned complement_neighb(unsigned i) - { - if (i == 8) - return 4; - if (i == 4) - return 8; - mln_assertion(0); - return 0; - } - - unsigned nb_connexity2d(const image2d<bool>& ima, unsigned nbh, const point2d& p, bool object) - { - unsigned res = 0; - - mln_bkd_niter_(neighb2d) n(c8() , p); - for_all(n) - { - res = (res << 1); - if (ima.domain().has(n) && ima(n) == object) - res = res | 1; - } - - if (nbh == 8) - return nb_connexity_c8[res]; - else - { - mln_assertion(nbh == 4); - return nb_connexity_c4[res]; - } - } - - bool is_curve_extremum(const image2d<bool>& ima, unsigned nbh_i, const point2d& p_, unsigned deep) - { -// return false; - unsigned cpt = 0; - mln_site_(image2d<bool>) next = p_; - mln_site_(image2d<bool>) p = next; - mln_niter_(neighb2d) n(int_to_neighb(nbh_i) , p); - - p = next; - for_all(n) - { - if (ima.domain().has(n) && ima(n) == true) - { - next = n; - cpt++; - } - } - if (cpt != 1) - return false; - - for (unsigned i = 0; i < deep - 1; i++) - { - cpt = 0; - p = next; - for_all(n) - { - if (ima.domain().has(n) && ima(n) == true) - { - next = n; - cpt++; - } - } - if (cpt != 2) - return false; - } - - return true; - } - - bool is_simple_point2d(const image2d<bool>& ima, unsigned nbh, const point2d& p) - { - mln_assertion(nbh == 4 || nbh == 8); - - return (nb_connexity2d(ima, nbh, p, true) == 1) && - (nb_connexity2d(ima, complement_neighb(nbh), p, false) == 1); - } - -# endif // MLN_INCLUDE_ONLY - -} // end of namespace mln - -#endif // ! MLN_SIMPLE_POINT_HH Index: garrigues/ocr/skeleton.hh --- garrigues/ocr/skeleton.hh (revision 3184) +++ garrigues/ocr/skeleton.hh (working copy) @@ -1,200 +0,0 @@ -// 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_SKELETON_HH -# define MLN_SKELETON_HH - -# include <iomanip> -# include <iostream> -# include <sstream> - -# include <mln/core/var.hh> - -# include <mln/core/image/image2d.hh> -# include <mln/core/image/cast_image.hh> -# include <mln/core/alias/neighb2d.hh> -# include <mln/core/site_set/p_queue_fast.hh> -# include <mln/core/site_set/p_priority.hh> - -# include <mln/value/int_u8.hh> -# include <mln/arith/revert.hh> -# include <mln/transform/distance.hh> - -# include <mln/make/w_window2d_int.hh> - -# include <mln/data/fill.hh> - -# include <mln/debug/println.hh> - -# include <mln/logical/not.hh> - -# include "simple_point.hh" - -#include <mln/make/w_window2d_int.hh> - -# include <mln/io/pgm/save.hh> -# include <mln/io/pbm/save.hh> - -namespace mln -{ - - template <typename V> - void save_state(const image2d<V>& ima) - { - static int id = 0; - std::stringstream filename; - - std::cout << id << std::endl; - filename << "skel_trace_" << std::setw(5) << std::setfill('0') - << std::right << id++ << ".ppm"; - - io::pbm::save(ima, filename.str()); - } - - image2d<bool> crest(const image2d<bool>& input, - const image2d<value::int_u8>& dist_map, - const neighb2d& nbh) - { - image2d<bool> is_crest; - initialize(is_crest, input); - data::fill(is_crest, false); - - mln_piter_(image2d<bool>) p(input.domain()); - mln_niter_(neighb2d) n(nbh, p); - for_all(p) - { - if (!input(p) || dist_map(p) < 0) - continue; - - unsigned nb_eq = 0; - unsigned nb_gt = 0; - unsigned nb_lt = 0; - for_all(n) - if (input.domain().has(n)) - { - if (dist_map(n) == dist_map(p)) - nb_eq++; - else if (dist_map(n) > dist_map(p)) - nb_gt++; - else - nb_lt++; - } - - -// if ((nb_gt == 1 && nb_eq == 0) || -// (nb_gt == 0)) - - if ((nb_lt + nb_eq) > 5) // Pixel Superiority index - is_crest(p) = true; - } - return is_crest; - } - - - image2d<bool> - skeleton_with_constraint(const image2d<bool>& input, - unsigned nbh_i, - const image2d<bool>& K, - const image2d<value::int_u8>& priority) - { - mln_assertion(nbh_i == 4 || nbh_i == 8); - - neighb2d nbh = int_to_neighb(nbh_i); - image2d<bool> output; - initialize(output, input); - - typedef mln_site_(image2d<bool>) P; - p_priority<value::int_u8, p_queue_fast<P> > q; - - // Initialization. - { - p_priority<value::int_u8, p_queue_fast<P> > q_tmp; - - data::fill(output, input); - mln_piter_(image2d<bool>) p(input.domain()); - for_all(p) - if (!input(p) && - is_simple_point2d(input, nbh_i, p)) // p is a simple point of background - q.push(priority(p), p); - } - - // Propagation. - { - P p; - mln_niter_(neighb2d) n(nbh, p); - while (! q.is_empty()) - { - p = q.pop_front(); - - for_all(n) - if (output.domain().has(n) && - output(n) && - K(n) == false && - is_simple_point2d(output, nbh_i, n) - // && // n is simple - // !is_curve_extremum(output, nbh_i, n, 1) - ) - { - output(n) = false; // Remove n from object - // save_state(output); - q.push(priority(n), n); - } - } - } - - return output; - } - - - image2d<bool> - skeleton(const image2d<bool>& input, unsigned nbh_i) - { - mln_assertion(nbh_i == 4 || nbh_i == 8); - neighb2d nbh = int_to_neighb(nbh_i); - - int vals[] = { 0, 9, 0, 9, 0, - 9, 6, 4, 6, 9, - 0, 4, 0, 4, 0, // Values of distances. - 9, 6, 4, 6, 9, - 0, 9, 0, 9, 0 }; - - image2d<value::int_u8> dist_map_n = transform::distance(value::int_u8(), logical::not_(input), nbh, make::w_window2d_int(vals)); - image2d<value::int_u8> dist_map = arith::revert(dist_map_n); - - io::pgm::save(dist_map, "distance.pgm"); - io::pgm::save(dist_map_n, "distance_n.pgm"); - - // Make K - image2d<bool> K = crest(input, dist_map_n, nbh); - io::pbm::save(K, "K.pbm"); - - return skeleton_with_constraint(input, nbh_i, K, dist_map); - } - -} // end of namespace mln - -#endif Index: garrigues/ocr/check_simple_point.cc --- garrigues/ocr/check_simple_point.cc (revision 3184) +++ garrigues/ocr/check_simple_point.cc (working copy) @@ -1,61 +0,0 @@ -#include <mln/core/image/image2d.hh> -#include <mln/core/alias/neighb2d.hh> - -#include <mln/labeling/blobs.hh> -#include <mln/data/fill.hh> -#include <mln/debug/println.hh> -#include "simple_point.hh" - - -int main() -{ - using namespace mln; - using namespace mln::value; - - typedef image2d<bool> I; - image2d<bool> ima(3,3); - point2d p(1,1); - - std::cout << "----- Object in C8 ------" << std::endl; - - for (unsigned i = 0; i < 256; i++) - { - data::fill(ima, false); - int_u8 tmp = i; - - mln_niter_(neighb2d) n(c8() , p); - for_all(n) - { - if (tmp % 2) - ima(n) = true; - tmp = tmp >> 1; - } - - unsigned x; - labeling::blobs(ima, c8(), x); - - mln_assertion(nb_connexity2d(ima, 8, p, true) == x); - } - - std::cout << "----- Object in C4 ------" << std::endl; - - for (unsigned i = 0; i < 256; i++) - { - data::fill(ima, false); - int_u8 tmp = i; - - mln_niter_(neighb2d) n(c8() , p); - for_all(n) - { - if (tmp % 2) - ima(n) = true; - tmp = tmp >> 1; - } - - - unsigned x; - labeling::blobs(ima, c4(), x); - - mln_assertion(nb_connexity2d(ima, 4, p, true) == x); - } -} Index: garrigues/ocr/compute_local_configurations.cc --- garrigues/ocr/compute_local_configurations.cc (revision 3184) +++ garrigues/ocr/compute_local_configurations.cc (working copy) @@ -1,74 +0,0 @@ -#include <mln/core/image/image2d.hh> -#include <mln/core/alias/neighb2d.hh> - -#include <mln/labeling/blobs.hh> -#include <mln/data/fill.hh> -#include <mln/debug/println.hh> -#include <iomanip> - - -int main() -{ - using namespace mln; - using value::int_u8; - - typedef image2d<bool> I; - - box2d b = make::box2d(-1,-1, 1,1); - image2d<bool> ima(b, 0); - point2d p(0, 0); - - std::vector<int_u8> x8(256), x4(256); - - - for (unsigned i = 0; i < 256; i++) - { - data::fill(ima, false); - - int_u8 tmp = i; - mln_fwd_niter_(neighb2d) n(c8(), p); - for_all(n) - { - if (tmp % 2) - ima(n) = true; - tmp = tmp >> 1; - } - - labeling::blobs(ima, c8(), x8[i]); - - { - int_u8 nl; - image2d<int_u8> lab = labeling::blobs(ima, c4(), nl); - std::set<int_u8> s; - mln_fwd_niter_(neighb2d) n(c4(), p); - for_all(n) - if (lab(n) != 0) - s.insert(lab(n)); - x4[i] = s.size(); - } - } - - - // Now printing! - - std::cout << "----- Object in C8 ------" << std::endl; - - for (unsigned i = 0; i < 256; i++) - { - std::cout << std::setw(2) << x8[i] << ", "; - if (! ((i + 1) % 4)) std::cout << " "; - if (! ((i + 1) % 16)) std::cout << std::endl; - if (! ((i + 1) % 64)) std::cout << std::endl; - } - - std::cout << "----- Object in C4 ------" << std::endl; - - for (unsigned i = 0; i < 256; i++) - { - std::cout << std::setw(2) << x4[i] << ", "; - if (! ((i + 1) % 4)) std::cout << " "; - if (! ((i + 1) % 16)) std::cout << std::endl; - if (! ((i + 1) % 64)) std::cout << std::endl; - } - -} Index: garrigues/ocr/tesseract_wrap.hh --- garrigues/ocr/tesseract_wrap.hh (revision 3184) +++ garrigues/ocr/tesseract_wrap.hh (working copy) @@ -1,91 +0,0 @@ -#ifndef TESSERACT_WRAP_HH -# define TESSERACT_WRAP_HH - -# include <cassert> - -# include <mln/core/image/image2d.hh> - -# include <tesseract/baseapi.h> - -struct TessWrap : public TessBaseAPI -{ - static int InitWithLanguage(const char* datapath, const char* outputbase, - const char* language, const char* configfile, - bool numeric_mode, int argc, char* argv[]) - { - return TessBaseAPI::InitWithLanguage(datapath, outputbase, - language, configfile, - numeric_mode, argc, argv); - } - - static char* TesseractRect(const unsigned char* imagedata, - int bytes_per_pixel, - int bytes_per_line, - int left, int top, int width, int height, - float* score) - { - int kMinRectSize = 10; // Quick and dirty... (value imported from tesseract src) - if (width < kMinRectSize || height < kMinRectSize) - return NULL; // Nothing worth doing. - - // Copy/Threshold the image to the tesseract global page_image. - CopyImageToTesseract(imagedata, bytes_per_pixel, bytes_per_line, - left, top, width, height); - - { // RecognizeToString - BLOCK_LIST* block_list = FindLinesCreateBlockList(); - PAGE_RES* page_res = Recognize(block_list, NULL); - - char* string; - int* lengths; - float* costs; - int* x0; - int* y0; - int* x1; - int* y1; - // Retrieve Tesseract internal data to compute the quality score. - int n = TessBaseAPI::TesseractExtractResult(&string, &lengths, &costs, &x0, &y0, &x1, &y1, page_res); - - float average_uncertainty = 0.f; - for (int i = 0; i < n; ++i) - average_uncertainty += costs[i]; - - if (n) - *score = average_uncertainty / n; - else - *score = -1; - - // Some memory cleanup - delete[] string; - delete[] lengths; - delete[] costs; - delete[] x0; - delete[] y0; - delete[] x1; - delete[] y1; - - return TesseractToText(page_res); - } - } -}; - -// Call tesseract -// lang: expected language -template <typename T> -char* tesseract(const char* lang, const mln::image2d<T>& input, float* score) -{ - assert(score); - TessWrap::InitWithLanguage(NULL, NULL, lang, NULL, false, 0, NULL); - char* s = TessWrap::TesseractRect( - (unsigned char*) input.buffer(), - sizeof (T), - input.ncols() * sizeof (T), - 0, 0, - input.ncols(), - input.nrows(), - score); - return s; -} - - -#endif // ! TESSERACT_WRAP_HH Index: garrigues/ocr/skeleton.old.cc --- garrigues/ocr/skeleton.old.cc (revision 3184) +++ garrigues/ocr/skeleton.old.cc (working copy) @@ -1,30 +0,0 @@ - -#include <mln/core/alias/point2d.hh> -#include "skeleton.hh" -#include <mln/data/paste.hh> -#include <mln/data/fill.hh> -#include <mln/core/image/sub_image.hh> -#include <mln/io/pgm/save.hh> -#include <mln/io/pbm/save.hh> -#include <mln/io/pbm/load.hh> - - -int main(int argc, char* argv[]) -{ - if(argc!=5) - { - std::cout << "arguments: filename voisinage R alpha" << std::endl; - exit(1); - } - image2d<bool> output; - std::string filename = argv[1]; - int r = atoi(argv[3]); - int alpha = atoi(argv[4]); - - image2d<bool> pic = io::pbm::load(filename); - if(atoi(argv[2])==4) - output = filteredSkeleton( pic, c4(), r, alpha, true); - else - output = filteredSkeleton( pic, c8(), r, alpha, true); - mln::io::pbm::save(output, "FS-"+std::string(argv[2])+"_"+std::string(argv[3])+"_"+std::string(argv[4])+"_"+filename); -} Index: garrigues/ocr/check.sh --- garrigues/ocr/check.sh (revision 3184) +++ garrigues/ocr/check.sh (working copy) @@ -1,31 +0,0 @@ -output_dir=tmp/`date '+%y_%m_%d__%H_%M_%S'` -mkdir $output_dir -for i in input/*.pbm ; do - echo "===========================================" - echo "--------- $i" - echo "===========================================" - - ref="$i.txt" - echo "______________________________Reference" - cat $ref - sed -e 's/\(.\)/\1\n/g' $ref > tmp/ref - total=`cat tmp/ref | wc -l ` - - echo "______________________________without preprocessing" - ./ocr_without_preprocess $i > tmp/without - cat tmp/without - cat tmp/without | sed -e 's/\(.\)/\1\n/g' > tmp/without - - echo "______________________________with preprocessing" - ./ocr_with_preprocess $i $output_dir/`basename $i` > tmp/with - cat tmp/with - cat tmp/with | sed -e 's/\(.\)/\1\n/g' > tmp/with - - - d_without=`diff ./tmp/without tmp/ref | diffstat | grep insert | sed -r 's/.*, ([0-9]+) insertion.*/\1/g'` - echo "$(($d_without * 100 / $total))% missmatch without preprocessing" - - d_with=`diff ./tmp/with tmp/ref | diffstat | grep insert | sed -r 's/.*, ([0-9]+) insertion.*/\1/g'` - echo "$(($d_with * 100 / $total))% missmatch with preprocessing" - echo "" -done Index: garrigues/ocr/simple_point.cc --- garrigues/ocr/simple_point.cc (revision 3184) +++ garrigues/ocr/simple_point.cc (working copy) @@ -1,39 +0,0 @@ -# include <mln/core/image/image2d.hh> -# include <mln/io/pbm/load.hh> -# include <mln/io/pbm/save.hh> -# include <mln/data/fill.hh> - -# include "simple_point.hh" - - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.pbm output.pbm" << std::endl; - abort(); -} - - - -int main(int argc, char* argv[]) -{ - using namespace mln; - using value::int_u8; - - if (argc != 3) - usage(argv); - - typedef image2d<bool> I; - I input; - io::pbm::load(input, argv[1]); - - I output; - initialize(output, input); - data::fill(output, false); - - mln_piter_(I) p(input.domain()); - for_all(p) - if (input(p) && simple_point2d(input, 4, p)) - output(p) = true; - - io::pbm::save(output, argv[2]); -} Index: garrigues/ocr/ocr_with_preprocess.cc --- garrigues/ocr/ocr_with_preprocess.cc (revision 3184) +++ garrigues/ocr/ocr_with_preprocess.cc (working copy) @@ -1,170 +0,0 @@ -// 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. - -#include <iostream> - -#include <mln/core/image/image2d.hh> -#include <mln/core/alias/window2d.hh> -#include <mln/core/alias/neighb2d.hh> - -#include <mln/core/image/cast_image.hh> - -#include <mln/value/int_u8.hh> - -#include "resize.hh" -#include "enlarge.hh" -#include "skeleton.hh" - -#include <mln/linear/gaussian.hh> - -#include <mln/trace/all.hh> - -#include <mln/fun/p2v/ternary.hh> -#include <mln/pw/image.hh> - -#include <mln/debug/println.hh> -#include <mln/labeling/regional_maxima.hh> -#include <mln/morpho/dilation.hh> -#include <mln/win/octagon2d.hh> -#include <mln/border/resize.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> -#include <mln/io/pbm/load.hh> -#include <mln/io/pbm/save.hh> -#include <mln/logical/not.hh> - -#include "tesseract_wrap.hh" -#include <mln/subsampling/subsampling.hh> - -// _COMPILATION_ -// g++ -DNDEBUG -O3 -I../../.. ocr.cc -L/usr/lib -ltesseract_full -lpthread - -// image2d<int_u8> tmp = duplicate(cast_image<int_u8>(Var)); \ - -#if 1 -# define OCR_TEST(Var) \ - { \ - float score = 0.f; \ - char* s = tesseract("fra", Var, &score); \ - std::cerr << #Var << ": " << score << std::endl << s; \ - delete[] s; \ - } -#else -# define OCR_TEST(Var) -#endif - - -int main(int argc, char** argv) -{ - using namespace mln; - using value::int_u8; - - image2d<bool> input; - - if (argc < 2) - { - std::cerr << "Usage: " << argv[0] << " in.pbm out.pbm" << std::endl; - return 1; - } - - mln::border::thickness = 0; - - io::pbm::load(input, argv[1]); - - // Resize - image2d<int_u8> enlarged = enlarge(logical::not_(input), 2); - image2d<bool> big = geom::resize(logical::not_(input), 4); - io::pgm::save(enlarged, std::string(argv[2]) + "_1_enlarge.pgm"); - OCR_TEST(enlarged); - - // Blur. - image2d<int_u8> blur = linear::gaussian(enlarged, 2); - io::pgm::save(blur, std::string(argv[2]) + "_2_gaussian.pgm"); - OCR_TEST(blur); - -// // Threshold -// image2d<bool> binary; -// { -// initialize(binary, blur); -// mln_piter_(image2d<int_u8>) p(blur.domain()); -// for_all(p) -// binary(p) = blur(p) > 100; - -// io::pbm::save(binary, std::string(argv[2]) + "_3_threshold.pbm"); -// OCR_TEST(binary); -// } - -// // Skeleton -// image2d<bool> skel = skeleton(binary, 4); -// io::pbm::save(skel, std::string(argv[2]) + "_4_skeleton.pbm"); -// OCR_TEST(skel); - -// // Dilation -// win::octagon2d oct(5); -// image2d<bool> dilate = morpho::dilation(skel, oct); -// border::resize(dilate, 0); -// io::pbm::save(dilate, std::string(argv[2]) + "_5_dilation.pbm"); -// OCR_TEST(dilate); - -// // Subsampling -// image2d<bool> subsampled = subsampling::subsampling(dilate, dpoint2d(1,1), 2); -// io::pbm::save(subsampled, std::string(argv[2]) + "_6_subsampling.pbm"); -// OCR_TEST(subsampled); - -// io::pbm::save(subsampled, argv[2]); - - - image2d<bool> K = crest(big, blur, c8()); - OCR_TEST(K); - io::pbm::save(K, std::string(argv[2]) + "_6_K.pbm"); - - image2d<bool> skel_on_gaussian = skeleton_with_constraint(big, 8, K, arith::revert(blur)); - OCR_TEST(skel_on_gaussian); - io::pbm::save(skel_on_gaussian, std::string(argv[2]) + "_7_skeleton_on_gaussian.pbm"); - - // Dilation - win::octagon2d oct(5); - image2d<bool> dilate_on_gaussian = morpho::dilation(skel_on_gaussian, oct); - border::resize(dilate_on_gaussian, 0); - io::pbm::save(dilate_on_gaussian, std::string(argv[2]) + "_8_dilation_on_gaussian.pbm"); - OCR_TEST(dilate_on_gaussian); - - // Subsampling - image2d<bool> subsampled_on_gaussian = subsampling::subsampling(dilate_on_gaussian, dpoint2d(1,1), 2); - io::pbm::save(subsampled_on_gaussian, std::string(argv[2]) + "_9_subsampling_on_gaussian.pbm"); - OCR_TEST(subsampled_on_gaussian); - - { - float score = 0; - char* s = tesseract("fra", subsampled_on_gaussian, &score); - std::cerr << "Tesseract result: (score " << score << ")" << std::endl; - std::cout << s; - delete[] s; - } - -} Index: garrigues/ocr/enlarge.hh --- garrigues/ocr/enlarge.hh (revision 3184) +++ garrigues/ocr/enlarge.hh (working copy) @@ -1,202 +0,0 @@ -# include <iostream> - -# include <mln/core/image/image2d.hh> -# include <mln/core/routine/initialize.hh> - -# include <mln/value/int_u8.hh> -# include <mln/fun/p2v/ternary.hh> - -# include <mln/pw/image.hh> -# include <mln/pw/cst.hh> -# include <mln/pw/value.hh> -# include <mln/opt/at.hh> - -# include <mln/core/routine/duplicate.hh> - - -float val(bool b) { return b ? 1 : 0; } - -int do_threshold(float value) -{ - return 255.f * value; -} - -namespace mln -{ - - image2d<value::int_u8> - enlargex2(const image2d<bool>& input) - { - using value::int_u8; - - unsigned nrows, ncols; - - nrows = input.nrows(); - ncols = input.ncols(); - - image2d<int_u8> output(2 * nrows, 2 * ncols); - float value; - - // row 0 - - opt::at(output, 0, 0) = do_threshold(opt::at(input, 0, 0)); - - for (int col = 2; col < output.ncols(); col += 2) - { - value = val(opt::at(input, 0, col / 2)); - value += val(opt::at(input, 0, col / 2 - 1)); - opt::at(output, 0, col) = do_threshold(value / 2); - } - - for (int col = 1; col < output.ncols(); col += 2) - opt::at(output, 0, col) = do_threshold(opt::at(input, 0, col / 2)); - - // col 0 - - for (int row = 2; row < output.nrows(); row += 2) - { - value = val(opt::at(input, row / 2, 0)); - value += val(opt::at(input, row / 2 - 1, 0)); - opt::at(output, row, 0) = do_threshold(value / 2); - } - - for (int row = 1; row < output.nrows(); row += 2) - opt::at(output, row, 0) = do_threshold(opt::at(input, row / 2, 0)); - - // others - - for (int row = 2; row < output.nrows(); row += 2) - { - for (int col = 2; col < output.ncols(); col += 2) - { - value = val(opt::at(input, row / 2, col / 2)); - value += val(opt::at(input, row / 2 - 1, col / 2)); - value += val(opt::at(input, row / 2, col / 2 - 1)); - value += val(opt::at(input, row / 2 - 1, col / 2 - 1)); - opt::at(output, row, col) = do_threshold(value / 4); - } - for (int col = 1; col < output.ncols(); col += 2) - { - value = val(opt::at(input, row / 2, col / 2)); - value += val(opt::at(input, row / 2 - 1, col / 2)); - opt::at(output, row, col) = do_threshold(value / 2); - } - } - - for (int row = 1; row < output.nrows(); row += 2) - { - for (int col = 2; col < output.ncols(); col += 2) - { - value = val(opt::at(input, row / 2, col / 2)); - value += val(opt::at(input, row / 2, col / 2 - 1)); - opt::at(output, row, col) = do_threshold(value / 2); - } - for (int col = 1; col < output.ncols(); col += 2) - opt::at(output, row, col) = do_threshold(opt::at(input, row / 2, col / 2)); - } - - return output; - } - - - - image2d<value::int_u8> - enlargex2(const image2d<value::int_u8>& input) - { - using value::int_u8; - - unsigned nrows, ncols; - - nrows = input.nrows(); - ncols = input.ncols(); - - image2d<int_u8> output(2 * nrows, 2 * ncols); - unsigned value; - - // row 0 - - opt::at(output, 0, 0) = (opt::at(input, 0, 0)); - - for (int col = 2; col < output.ncols(); col += 2) - { - value = (opt::at(input, 0, col / 2)); - value += (opt::at(input, 0, col / 2 - 1)); - opt::at(output, 0, col) = (value / 2); - } - - for (int col = 1; col < output.ncols(); col += 2) - opt::at(output, 0, col) = (opt::at(input, 0, col / 2)); - - // col 0 - - for (int row = 2; row < output.nrows(); row += 2) - { - value = (opt::at(input, row / 2, 0)); - value += (opt::at(input, row / 2 - 1, 0)); - opt::at(output, row, 0) = (value / 2); - } - - for (int row = 1; row < output.nrows(); row += 2) - opt::at(output, row, 0) = (opt::at(input, row / 2, 0)); - - // others - - for (int row = 2; row < output.nrows(); row += 2) - { - for (int col = 2; col < output.ncols(); col += 2) - { - value = (opt::at(input, row / 2, col / 2)); - value += (opt::at(input, row / 2 - 1, col / 2)); - value += (opt::at(input, row / 2, col / 2 - 1)); - value += (opt::at(input, row / 2 - 1, col / 2 - 1)); - opt::at(output, row, col) = ((unsigned(value)+2) / 4); - } - for (int col = 1; col < output.ncols(); col += 2) - { - value = (opt::at(input, row / 2, col / 2)); - value += (opt::at(input, row / 2 - 1, col / 2)); - opt::at(output, row, col) = (value / 2); - } - } - - for (int row = 1; row < output.nrows(); row += 2) - { - for (int col = 2; col < output.ncols(); col += 2) - { - value = (opt::at(input, row / 2, col / 2)); - value += (opt::at(input, row / 2, col / 2 - 1)); - opt::at(output, row, col) = (value / 2); - } - for (int col = 1; col < output.ncols(); col += 2) - opt::at(output, row, col) = (opt::at(input, row / 2, col / 2)); - } - - return output; - } - - - - - - - // enlarge 2^n times - image2d<value::int_u8> - enlarge(const image2d<bool>& input, unsigned int n) - { - using value::int_u8; - - if (n == 0) - return duplicate(fun::p2v::ternary(pw::value(input), - pw::cst(int_u8(255)), - pw::cst(int_u8(0))) - | input.domain()); - - image2d<int_u8> output = enlargex2(input); - - while (--n) - output = enlargex2(output); - - return output; - } - -} // mln Index: garrigues/ocr/Makefile --- garrigues/ocr/Makefile (revision 3184) +++ garrigues/ocr/Makefile (working copy) @@ -1,26 +0,0 @@ -CXXFLAGS=-I../../.. -I${HOME}/local/include -LFLAGS=-L${HOME}/local/lib -ltesseract_full -lpthread - -all: ocr_without_preprocess ocr_with_preprocess - -ocr_without_preprocess: ocr_without_preprocess.cc - g++ -DNDEBUG -O3 ${CXXFLAGS} $< ${LFLAGS} -o $@ - -ocr_with_preprocess: ocr_with_preprocess.cc - g++ -DNDEBUG -O3 ${CXXFLAGS} $< ${LFLAGS} -o $@ -clean: - rm -f *.o ocr_without_preprocess ocr_with_preprocess - -logs: - mkdir logs - -tmp: - mkdir tmp - -check: logs tmp ocr_without_preprocess ocr_with_preprocess - ./check.sh - -skeleton: skeleton.cc - g++ -DNDEBUG -W -Wall -Wextra ${CXXFLAGS} $< -o $@ - -.PHONY: skeleton Property changes on: inim/ocr ___________________________________________________________________ Added: svn:mergeinfo Property changes on: inim/color ___________________________________________________________________ Added: svn:mergeinfo Property changes on: inim/nature ___________________________________________________________________ Added: svn:mergeinfo Index: nature/gradient.cc --- nature/gradient.cc (revision 3184) +++ nature/gradient.cc (working copy) @@ -1,60 +0,0 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) -// -// This file is part of the Olena Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// of the GNU General Public License version 2 as published by the -// Free Software Foundation. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this library; see the file COPYING. If not, write to -// the Free Software Foundation, 51 Franklin Street, Fifth Floor, -// Boston, MA 02111-1307, USA. -// -// As a special exception, you may use this file as part of a free -// software library without restriction. Specifically, if other files -// instantiate templates or use macros or inline functions from this -// file, or you compile this file and link it with other files to -// produce an executable, this file does not by itself cause the -// resulting executable to be covered by the GNU General Public -// License. This exception does not however invalidate any other -// reasons why the executable file might be covered by the GNU General -// Public License. - -#include <mln/core/image/image2d.hh> -#include <mln/win/rectangle2d.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> - -#include <mln/value/int_u8.hh> -#include <mln/morpho/gradient.hh> - - -int main(int argc, const char * argv[]) -{ - using namespace mln; - using value::int_u8; - - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.pgm [other_files.pgm]" << std::endl; - return 1; - } - - for (int i = 1; i < argc; ++i) - { - image2d<int_u8> ima; - io::pgm::load(ima, argv[i]); - - win::rectangle2d rect(5, 5); - border::thickness = 5; - - std::string name(argv[i]); - name.erase(name.length() - 4); - io::pgm::save(morpho::gradient(ima, rect), name.append("_grad.pgm")); - } -} Index: nature/closing.cc --- nature/closing.cc (revision 3184) +++ nature/closing.cc (working copy) @@ -1,59 +0,0 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) -// -// This file is part of the Olena Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// of the GNU General Public License version 2 as published by the -// Free Software Foundation. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this library; see the file COPYING. If not, write to -// the Free Software Foundation, 51 Franklin Street, Fifth Floor, -// Boston, MA 02111-1307, USA. -// -// As a special exception, you may use this file as part of a free -// software library without restriction. Specifically, if other files -// instantiate templates or use macros or inline functions from this -// file, or you compile this file and link it with other files to -// produce an executable, this file does not by itself cause the -// resulting executable to be covered by the GNU General Public -// License. This exception does not however invalidate any other -// reasons why the executable file might be covered by the GNU General -// Public License. - -#include <mln/core/image/image2d.hh> -#include <mln/win/rectangle2d.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> - -#include <mln/value/int_u8.hh> -#include <mln/morpho/closing.hh> - -int main(int argc, const char * argv[]) -{ - using namespace mln; - using value::int_u8; - - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.pgm [other_files.pgm]" << std::endl; - return 1; - } - - for (int i = 1; i < argc; ++i) - { - image2d<int_u8> ima; - io::pgm::load(ima, argv[i]); - - win::rectangle2d rect(5, 5); - border::thickness = 11; - - std::string name(argv[i]); - name.erase(name.length() - 4); - io::pgm::save(morpho::closing(ima, rect), name.append("_closed.pgm")); - } -} Index: nature/nature.cc --- nature/nature.cc (revision 3184) +++ nature/nature.cc (working copy) @@ -1,498 +0,0 @@ -// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) -// -// This file is part of the Olena Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// 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 <mln/core/image/image2d.hh> -#include <mln/core/image/cast_image.hh> -#include <mln/core/image/fun_image.hh> -#include <mln/core/alias/neighb2d.hh> - -#include <mln/io/ppm/load.hh> -#include <mln/io/pgm/save.hh> -#include <mln/io/pbm/save.hh> - -#include <mln/histo/compute.hh> - -#include <mln/level/transform.hh> -#include <mln/data/paste.hh> -#include <mln/level/to_enc.hh> - -#include <mln/value/rgb8.hh> -#include <mln/value/hsi.hh> - -#include <mln/fun/v2v/rgb_to_hsi.hh> -#include <mln/fun/meta/hue.hh> -#include <mln/fun/meta/sat.hh> -#include <mln/fun/meta/inty.hh> - -#include <mln/win/hline2d.hh> -#include <mln/win/vline2d.hh> - -#include <mln/morpho/hit_or_miss.hh> -#include <mln/morpho/gradient.hh> -#include <mln/morpho/opening.hh> - -#include <mln/binarization/threshold.hh> - -#include <mln/estim/mean.hh> - -#include <mln/transform/fft.hh> - -#include <mln/opt/at.hh> - -#include "co_occurence.hh" - -#include <math.h> - -using namespace mln; -using namespace value; - -enum doctype - { - TEXT, - SCREENSHOT, - PHOTO, - DRAWING, - NB_DOCTYPE - }; - -template <typename T> -unsigned nb_peaks (histo::array<T> &h) -{ - // First, we compute the maximum, ignoring the first column because it - // contains nonsense points - - unsigned max = 0; - mln_viter(mln::value::set<T>) v(h.vset()); - - for_all(v) - if (((T)v).to_enc() && (h(v) > max)) - max = h(v); - - // We take the first value into account - if (h[0] / 6 > max) - max = h[0] / 6; - - // Now we count the number of peaks over max / 4 - unsigned cpt = 0; - for_all(v) - if (h(v) >= max / 4) - cpt ++; - - return cpt; -} - - -int main (int argc, const char * argv []) -{ - if (argc != 2) { - std::cerr << "usage: " << argv[0] << " in.pgm" << std::endl; - return 1; - } - - unsigned score[NB_DOCTYPE]; - for (unsigned i = 0; i < NB_DOCTYPE; ++i) - score[i] = 0; - - border::thickness = 21; - - image2d<rgb8> input; - io::ppm::load(input, argv[1]); - - // First, we get the HSI histograms and corresponding greyscale versions of the picture - - image2d<hsi_f> hsi = level::transform(input, fun::v2v::f_rgb_to_hsi_f); - - fun_image<mln::meta::hue<hsi_f>, image2d<hsi_f> > hue(hsi); - fun_image<mln::meta::sat<hsi_f>, image2d<hsi_f> > sat(hsi); - fun_image<mln::meta::inty<hsi_f>, image2d<hsi_f> > inty(hsi); - - cast_image_<float01_8, fun_image<mln::meta::hue<hsi_f>, image2d<hsi_f> > > qhue(hue); // quantified hue - cast_image_<float01_8, fun_image<mln::meta::sat<hsi_f>, image2d<hsi_f> > > qsat(sat); // quantified sat - cast_image_<float01_8, fun_image<mln::meta::inty<hsi_f>, image2d<hsi_f> > > qinty(inty); // quantified inty - - histo::array<float01_8> hhue = histo::compute(qhue); - histo::array<float01_8> hsat = histo::compute(qsat); - histo::array<float01_8> hinty = histo::compute(qinty); - - - // Compute the number of peaks in the histogram to give a first intuition - - unsigned n = nb_peaks(hhue) * 3; - - if (n > 100) - n = 100; - - score[PHOTO] += n; - score[SCREENSHOT] += 20 + 80 - n * 80 / 100; - score[TEXT] += 100 - n; - score[DRAWING] += 20 + 80 - n * 80 / 100; - - std::cout << "Test 1 : peaks number[" << nb_peaks(hhue) << "]" << std::endl - << "Photo : " << score[PHOTO] << std::endl - << "Screenshot : " << score[SCREENSHOT] << std::endl - << "Text : " << score[TEXT] << std::endl - << "Drawing : " << score[DRAWING] << std::endl << std::endl; - - - // Now we compute the co-occurence matrice - - dpoint2d d(0, 1); - image2d<int_u8> uinty (qinty.domain()); - { - image2d<unsigned char> tmp = level::transform(qinty, fun::v2v::enc< float01_8 >()); - data::paste(tmp, uinty); - /* mln_piter_(image2d<unsigned char>) p(tmp.domain()); - for_all(p) - uinty(p) = tmp(p); - */ - } - - image2d<unsigned> mco (co_occurence(uinty, d)); - - // If there is a plain background, there will be a massive peak in the diagonal of the matrix - unsigned max = 0; - for (unsigned i = 0; i < mco.nrows(); i++) - if (opt::at(mco, i, i) > max) - max = opt::at(mco, i, i); - - for (unsigned i = 0; i < mco.nrows() - 1; i++) { - if (opt::at(mco, i + 1, i) > max) - max = opt::at(mco, i + 1, i); - if (opt::at(mco, i, i + 1) > max) - max = opt::at(mco, i, i + 1); - } - - max = max * 100 / input.nelements(); - - score[PHOTO] += 100 - max; - score[TEXT] += max * 2; - - score[SCREENSHOT] += 80 + max / 2; - score[DRAWING] += 50 + max / 2; - - std::cout << "Test 2 : co-occurence matrix diag_max[" << max << "]" << std::endl - << "Photo : +" << 100 - max << std::endl; - - std::cout << "Screenshot : +" << 80 + max / 2 << std::endl; - - std::cout << "Text : +" << max * 2 << std::endl; - - std::cout << "Drawing : +" << 80 + max / 2 << std::endl << std::endl; - - - - - // A good way to detect screenshots : rectangle detection - - // First, we compute the gradient - - win::rectangle2d rect(5, 5); - image2d<int_u8> grad = morpho::gradient(uinty, rect); - - // Then, we apply a lot of hit or miss filters ! - - // Compute the mean - int_u8 mean = estim::mean(grad); - - image2d<bool> imab = binarization::threshold(grad, 10); - - window2d winout; - window2d winin; - - static const bool blmatout [] = {0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0}; - - convert::from_to(blmatout, winout); - - static const bool blmatin [] = {0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 1, 1, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - convert::from_to(blmatin, winin); - - image2d<bool> bottom_left = morpho::hit_or_miss(imab, winout, winin); - - - static const bool brmatout [] = {0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0}; - - static const bool brmatin [] = {0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(brmatout, winout); - convert::from_to(brmatin, winin); - image2d<bool> bottom_right = morpho::hit_or_miss(imab, winout, winin); - - static const bool urmatout [] = {0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0}; - - static const bool urmatin [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0}; - - - convert::from_to(urmatout, winout); - convert::from_to(urmatin, winin); - image2d<bool> up_right = morpho::hit_or_miss(imab, winout, winin); - - static const bool ulmatout [] = {0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0}; - - static const bool ulmatin [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0}; - - - convert::from_to(ulmatout, winout); - convert::from_to(ulmatin, winin); - image2d<bool> up_left = morpho::hit_or_miss(imab, winout, winin); - - - static const bool umatout [] = {0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - static const bool umatin [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(umatout, winout); - convert::from_to(umatin, winin); - image2d<bool> up = morpho::hit_or_miss(imab, winout, winin); - - - static const bool bmatout [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0}; - - static const bool bmatin [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(bmatout, winout); - convert::from_to(bmatin, winin); - image2d<bool> bottom = morpho::hit_or_miss(imab, winout, winin); - - - static const bool lmatout [] = {0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0}; - - static const bool lmatin [] = {0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(lmatout, winout); - convert::from_to(lmatin, winin); - image2d<bool> left = morpho::hit_or_miss(imab, winout, winin); - - - static const bool rmatout [] = {0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0}; - - static const bool rmatin [] = {0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(rmatout, winout); - convert::from_to(rmatin, winin); - image2d<bool> right = morpho::hit_or_miss(imab, winout, winin); - - image2d<bool> inter (up_left + up_right + bottom_right + bottom_left + up + bottom + left + right); - - image2d<bool> final = morpho::opening(inter, win::hline2d(20)); - final += morpho::opening(inter, win::vline2d(20)); - - // Now we count blank points in our result - - unsigned cpt = 0; - mln_piter_(image2d<bool>) p (final.domain()); - for_all(p) - cpt += final(p); - - // compute the percentage of blank points - - cpt = 1000 * cpt / final.domain().nsites(); - - if (cpt > 50) - cpt = 50; - - score[PHOTO] += 50 - cpt; - score[SCREENSHOT] += cpt * 8; - score[TEXT] += 50 + cpt * max / 3; - score[DRAWING] += 2 * (60 - cpt); - - std::cout << "Test 3 : rectangle detection[" << cpt << "]" << std::endl - << "Photo : +" << 50 - cpt << std::endl - << "Screenshot : +" << cpt * 8 << std::endl - << "Text : +" << 50 + cpt * max / 3 << std::endl - << "Drawing : +" << 2 * (60 - cpt) << std::endl << std::endl; - - - // Last but not least : text detection thanks to FFT - - transform::fft<double> fourier(morpho::opening(uinty, win::hline2d(20))); - fourier.transform(); - - std::string name(argv[1]); - name.erase(name.length() - 4); - image2d<int_u8> fft = fourier.transformed_image_log_magn<int_u8>(true); - mln_piter_(image2d<int_u8>) q (fft.domain()); - max = 0; - for_all(q) - if (fft(q) > max) - max = fft(q); - - image2d<bool> fftb = binarization::threshold(fft, max * 4 / 10); - - // Find the line that best fits the points - - unsigned - center_r = fft.nrows() / 2, - center_c = fft.ncols() / 2; - - double arg = 0, coeff = 0; - - for_all(q) - if (fftb(q)) - { - double dist = - (center_c - q.col()) * (center_c - q.col()) + - (center_r - q.row()) * (center_r - q.row()); - - if (!dist) - continue; - - double angle = acos (abs(center_r - q.row()) / sqrt(dist)); - while (angle > M_PI) - angle -= M_PI; - while (angle < 0) - angle += M_PI; - - arg = (arg * coeff + dist * angle) / (coeff + dist); - - coeff += dist; - - } - - // std::cout << "arg : " << arg << " coeff : " << coeff << std::endl; - double a = tan(arg); - - // Now compute the mean distance of the points to the line - - double b = center_c - a * center_r; - double dist = 0; - coeff = 0; - - for_all(q) - if (fftb(q)) - { - double d = abs(a * q.row() - q.col() + b) / sqrt(a * a + 1); - dist += d * d; - coeff ++; - } - - dist /= coeff; - - dist = dist / (log(fftb.nelements()) / log(10)); - - score[PHOTO] += dist * 25; - score[SCREENSHOT] += dist * 50; - score[TEXT] += (1 + abs(cos(arg))) * (4 - dist) * 40; - score[DRAWING] += dist * 50; - - std::cout << "Test 4 : Fourier distance[" << dist << "]" << std::endl - << "Photo : +" << dist * 25 << std::endl - << "Screenshot : +" << dist * 50 << std::endl - << "Text : +" << (1 + abs(cos(arg))) * (4 - dist) * 40 << std::endl - << "Drawing : +" << dist * 50 << std::endl << std::endl; - - - // io::pbm::save(binarization::threshold(fft, max * 4 / 10), name.append("_fft.pbm")); - - // Print the result ! - - std::cout << "Photo : " << score[PHOTO] << std::endl - << "Screenshot : " << score[SCREENSHOT] << std::endl - << "Text : " << score[TEXT] << std::endl - << "Drawing : " << score[DRAWING] << std::endl; - - max = 0; - unsigned index = 0; - - for (unsigned i = 0; i < NB_DOCTYPE; ++i) - if (score[i] > max) - { - max = score[i]; - index = i; - } - - return index; -} Index: nature/opening.cc --- nature/opening.cc (revision 3184) +++ nature/opening.cc (working copy) @@ -1,59 +0,0 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) -// -// This file is part of the Olena Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// of the GNU General Public License version 2 as published by the -// Free Software Foundation. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this library; see the file COPYING. If not, write to -// the Free Software Foundation, 51 Franklin Street, Fifth Floor, -// Boston, MA 02111-1307, USA. -// -// As a special exception, you may use this file as part of a free -// software library without restriction. Specifically, if other files -// instantiate templates or use macros or inline functions from this -// file, or you compile this file and link it with other files to -// produce an executable, this file does not by itself cause the -// resulting executable to be covered by the GNU General Public -// License. This exception does not however invalidate any other -// reasons why the executable file might be covered by the GNU General -// Public License. - -#include <mln/core/image/image2d.hh> -#include <mln/win/rectangle2d.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> - -#include <mln/value/int_u8.hh> -#include <mln/morpho/opening.hh> - -int main(int argc, const char * argv[]) -{ - using namespace mln; - using value::int_u8; - - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.pgm [other_files.pgm]" << std::endl; - return 1; - } - - for (int i = 1; i < argc; ++i) - { - image2d<int_u8> ima; - io::pgm::load(ima, argv[i]); - - win::rectangle2d rect(3, 3); - border::thickness = 11; - - std::string name(argv[i]); - name.erase(name.length() - 4); - io::pgm::save(morpho::opening(ima, rect), name.append("_opened.pgm")); - } -} Index: nature/co_occurence.hh --- nature/co_occurence.hh (revision 3184) +++ nature/co_occurence.hh (working copy) @@ -1,77 +0,0 @@ -// 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_CO_OCCURENCE_HH -# define MLN_CO_OCCURENCE_HH - -/*! \file ?? - * - * \brief FIXME - */ - -# include <mln/core/concept/image.hh> -# include <mln/core/dpoint.hh> -# include <mln/core/image/image2d.hh> -# include <mln/data/fill.hh> -# include <mln/opt/at.hh> - - -namespace mln -{ - - - template <typename I, typename D> - // image2d<unsigned> co_occurence (const Image<I>&, const Dpoint<D>&); - image2d<unsigned> co_occurence (const Image<I>&, const Gdpoint<D>&); - -# ifndef MLN_INCLUDE_ONLY - - template <typename I, typename D> - image2d<unsigned> co_occurence (const Image<I> &ima_, const Gdpoint<D> &dp_) - { - mln::metal::equal<mln_psite(I), mln_psite(D)>::check(); - // FIXME : check thaat Image<I> is quant low - - const I &ima = exact(ima_); - const D &dp = exact(dp_); - image2d<unsigned> mco(mln_card(mln_value(I)), mln_card(mln_value(I)), 0); - data::fill(mco, 0); - - - mln_piter(I) p(ima.domain()); - for_all(p) - if (ima.domain().has(p + dp)) - opt::at(mco, ima(p), ima(p + dp))++; - - return mco; - } - -#endif // MLN_INCLUDE_ONLY - -} - -#endif // MLN_CO_OCCURENCE_HH Index: nature/test.sh --- nature/test.sh (revision 3184) +++ nature/test.sh (working copy) @@ -1,11 +0,0 @@ -#! /bin/sh - -for i in $@; -do - echo $i; - echo ""; - ./nature $i; - echo ""; - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; - echo ""; -done; Index: nature/proj.cc --- nature/proj.cc (revision 3184) +++ nature/proj.cc (working copy) @@ -1,68 +0,0 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) -// -// This file is part of the Olena Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// of the GNU General Public License version 2 as published by the -// Free Software Foundation. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this library; see the file COPYING. If not, write to -// the Free Software Foundation, 51 Franklin Street, Fifth Floor, -// Boston, MA 02111-1307, USA. -// -// As a special exception, you may use this file as part of a free -// software library without restriction. Specifically, if other files -// instantiate templates or use macros or inline functions from this -// file, or you compile this file and link it with other files to -// produce an executable, this file does not by itself cause the -// resulting executable to be covered by the GNU General Public -// License. This exception does not however invalidate any other -// reasons why the executable file might be covered by the GNU General -// Public License. - -#include <mln/core/image/image2d.hh> -#include <mln/core/image/image1d.hh> -#include <mln/win/rectangle2d.hh> -#include <mln/core/image/cast_image.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> - -#include <mln/value/int_u8.hh> -#include <mln/morpho/opening.hh> - -#include "proj.hh" - -int main(int argc, const char * argv[]) -{ - using namespace mln; - using value::int_u8; - - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.pgm [other_files.pgm]" << std::endl; - return 1; - } - - for (int i = 1; i < argc; ++i) - { - image2d<int_u8> ima; - io::pgm::load(ima, argv[i]); - - std::string name(argv[i]); - name.erase(name.length() - 4); - image1d<float> toto = proj_nat(ima); - image2d<int_u8> tata (toto.domain().nsites(), 1); - mln_piter_(image1d<int_u8>) p(toto.domain()); - - for_all(p) { - tata(point2d(p[0], 0)) = toto(p); - } - - io::pgm::save(tata, name.append("_proj.pgm")); - } -} Index: nature/erosion.cc --- nature/erosion.cc (revision 3184) +++ nature/erosion.cc (working copy) @@ -1,60 +0,0 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) -// -// This file is part of the Olena Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// of the GNU General Public License version 2 as published by the -// Free Software Foundation. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this library; see the file COPYING. If not, write to -// the Free Software Foundation, 51 Franklin Street, Fifth Floor, -// Boston, MA 02111-1307, USA. -// -// As a special exception, you may use this file as part of a free -// software library without restriction. Specifically, if other files -// instantiate templates or use macros or inline functions from this -// file, or you compile this file and link it with other files to -// produce an executable, this file does not by itself cause the -// resulting executable to be covered by the GNU General Public -// License. This exception does not however invalidate any other -// reasons why the executable file might be covered by the GNU General -// Public License. - -#include <mln/core/image/image2d.hh> -#include <mln/win/rectangle2d.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> - -#include <mln/value/int_u8.hh> -#include <mln/morpho/gradient.hh> - - -int main(int argc, const char * argv[]) -{ - using namespace mln; - using value::int_u8; - - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.pgm [other_files.pgm]" << std::endl; - return 1; - } - - for (int i = 1; i < argc; ++i) - { - image2d<int_u8> ima; - io::pgm::load(ima, argv[i]); - - win::hline2d f(31); - border::thickness = 16; - - std::string name(argv[i]); - name.erase(name.length() - 4); - io::pgm::save(morpho::erosion(ima, f), name.append("_eroded.pgm")); - } -} Index: nature/mco.cc --- nature/mco.cc (revision 3184) +++ nature/mco.cc (working copy) @@ -1,48 +0,0 @@ -#include <iostream> - -#include <mln/core/image/image2d.hh> -#include <mln/core/image/cast_image.hh> -#include <mln/value/int_u16.hh> -#include "co_occurence.hh" -#include <mln/core/alias/dpoint2d.hh> -#include <mln/io/pgm/save.hh> -#include <mln/io/pgm/load.hh> -#include <mln/estim/min_max.hh> - -int main(int argc, const char * argv[]) -{ - using namespace mln; - using namespace value; - - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.pgm [other_files.pgm]" << std::endl; - return 1; - } - - dpoint2d d(0, 1); - - for (int i = 1; i < argc; ++i) - { - image2d<int_u8> ima; - io::pgm::load(ima, argv[i]); - - std::string name(argv[i]); - name.erase(name.length() - 4); - - image2d<unsigned> co (co_occurence(ima, d)); - - // Normalization - unsigned m, M; - estim::min_max(co, m, M); - std::cout << "max : " << M << std::endl; - double norm = 255./M; - mln_piter_ (image2d<unsigned>) p (co.domain()); - for_all(p) - { - // std::cout << co(p) << " ; "; - co(p) *= norm; - } - - io::pgm::save(cast_image<int_u<8> >(co), name.append("_mco.pgm")); - } -} Index: nature/fft.cc --- nature/fft.cc (revision 3184) +++ nature/fft.cc (working copy) @@ -1,61 +0,0 @@ -// -*- c++ -*- -// Copyright (C) 2004 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, Inc., 51 Franklin Street, Fifth Floor, -// Boston, MA 02110-1301, 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 <mln/transform/fft.hh> -#include <mln/value/int_u8.hh> -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> - -using namespace mln; -using namespace transform; -using namespace value; - -int main(int argc, const char * argv[]) -{ - using namespace mln; - using value::int_u8; - - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.pgm [other_files.pgm]" << std::endl; - return 1; - } - - for (int i = 1; i < argc; ++i) - { - image2d<int_u8> ima; - io::pgm::load(ima, argv[i]); - - fft<double> fourier(ima); - - fourier.transform(); - - std::string name(argv[i]); - name.erase(name.length() - 4); - io::pgm::save(fourier.transformed_image_log_magn<int_u8>(true), name.append("_fft.pgm")); - } -} Index: nature/hom.cc --- nature/hom.cc (revision 3184) +++ nature/hom.cc (working copy) @@ -1,84 +0,0 @@ -// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) -// -// This file is part of the Olena Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// 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 <mln/core/image/image2d.hh> - -#include <mln/win/rectangle2d.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pbm/save.hh> - -#include <mln/value/int_u8.hh> -#include <mln/value/int_u16.hh> - -# include <mln/core/alias/window2d.hh> - -#include <mln/level/transform.hh> -#include <mln/binarization/threshold.hh> -#include <mln/estim/mean.hh> -#include <mln/morpho/hit_or_miss.hh> -#include <mln/morpho/dilation.hh> -#include <mln/morpho/opening.hh> - -#include <mln/win/all.hh> - -int main(int argc, const char * argv[]) -{ - using namespace mln; - using namespace value; - - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.pgm [other_files.pgm]" << std::endl; - return 1; - } - - for (int i = 1; i < argc; ++i) - { - typedef int_u8 int_t; - - border::thickness = 21; - - image2d<int_t> ima; - io::pgm::load(ima, argv[i]); - - // Compute the mean - int_t mean = estim::mean(ima); - - image2d<bool> imab = binarization::threshold(ima, mean-10); - - io::pbm::save(imab, "hop.pbm"); - - window2d out = win::disk2d(25) - win::disk2d(22); - win::disk2d in(4); - - - std::string name(argv[i]); - name.erase(name.length() - 4); - io::pbm::save(morpho::hit_or_miss(imab, in, out), name.append("_hom.pbm")); - } -} Index: nature/proj.hh --- nature/proj.hh (revision 3184) +++ nature/proj.hh (working copy) @@ -1,64 +0,0 @@ -// 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/pgm/save.hh> -#include <mln/data/paste.hh> -#include <mln/accu/mean.hh> -#include <mln/literal/white.hh> -#include <mln/core/image/image2d.hh> -#include <mln/core/image/image1d.hh> -#include <mln/data/fill.hh> -#include <mln/opt/at.hh> - -namespace mln -{ - template <typename T> - image1d<float> - proj_nat(const image2d<T>& input) - { - image1d<float> out(geom::nrows(input)); - data::fill(out, 0); - - mln_piter(image2d<T>) p(input.domain()); - for_all(p) // 2d - opt::at(out, p.row()) += input(p); - - mln_piter(image1d<T>) p2(out.domain()); - unsigned count = geom::ncols(input); - for_all(p2) { - out(p2) /= count; - } - return out; - } - -} // end of namespace mln - -#endif /* MLN_PROJ_HH */ - Index: nature/Makefile --- nature/Makefile (revision 3184) +++ nature/Makefile (working copy) @@ -1,24 +0,0 @@ -SRC=$(wildcard *.cc) -OBJ=$(SRC:.cc=.o) -EXEC=$(SRC:.cc=) -CC=g++ -CXXFLAGS=-Wall -W -I ../abraham -I ../.. -O3 -DNDEBUG - -fft: fft.o - $(CC) $(CXXFLAGS) $< -o $@ -l fftw3 - -nature: nature.o - $(CC) $(CXXFLAGS) $< -o $@ -l fftw3 - -all: $(EXEC) - -clean: - rm -rf *.o - rm -rf *~ - -distclean: clean - rm -rf $(EXEC) - -proj: proj.cc proj.hh - -.PHONY: clean distclean Index: nature/histo_hsi.cc --- nature/histo_hsi.cc (revision 3184) +++ nature/histo_hsi.cc (working copy) @@ -1,181 +0,0 @@ -// 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. - -#include <iterator> -#include <string> - -#include <mln/core/image/image2d.hh> -#include <mln/core/image/cast_image.hh> -#include <mln/core/image/thru.hh> -#include <mln/core/alias/window2d.hh> -#include <mln/core/alias/neighb2d.hh> -#include <mln/core/site_set/p_set.hh> - -#include <mln/value/rgb8.hh> -#include <mln/value/hsi.hh> - -#include <mln/fun/v2v/rgb_to_hsi.hh> -#include <mln/level/to_enc.hh> -#include <mln/fun/meta/hue.hh> -#include <mln/fun/meta/sat.hh> -#include <mln/fun/meta/inty.hh> - -#include <mln/level/compare.hh> - -#include <mln/io/ppm/load.hh> -#include <mln/io/pbm/save.hh> -#include <mln/io/pgm/save.hh> - -#include <mln/accu/histo.hh> -#include <mln/histo/compute.hh> -#include <mln/level/transform.hh> -#include <mln/data/fill.hh> - -using namespace mln; -using namespace value; - -typedef int_u16 u_t; - - -template <typename I> -void save_histo(Image<I> &i, std::string &name) -{ - I& ima = exact(i); - - histo::data<float01_8> h = histo::compute(ima); - - // Compute histo max - unsigned max = 0; - mln_viter(mln::value::set<float01_8>) v(h.vset()); - - for_all(v) - if (h(v) > max) - max = h(v); - - std::cout << std::endl; - - image2d<bool> output(max, mln_card(float01_8), 0); - std::cout << max << "x" << mln_card(float01_8) << std::endl; - data::fill(output, true); - - for_all(v) - for (size_t i = 0; i < h(v); ++i) - { - // std::cout << max - i - 1 << ", " << (unsigned) (((float01_8)v).to_enc()) << " ; " ; - if (output.has(point2d(max - i - 1, ((float01_8)v).to_enc() ))) - output(point2d(max - i - 1, ((float01_8)v).to_enc() )) = false; - } - - io::pbm::save(output, name); -} - -int main (int argc, const char* argv []) -{ - if (argc < 2) { - std::cerr << "usage: " << argv[0] << " in.ppm [other_files.ppm]" << std::endl; - return 1; - } - - for (int i = 1; i < argc; ++i) - { - - image2d<rgb8> input; - io::ppm::load(input, argv[i]); - - image2d<hsi_f> hsi = level::transform(input, fun::v2v::f_rgb_to_hsi_f); - thru<mln::meta::hue<hsi_f>, image2d<hsi_f> > h(hsi); - cast_image_<float01_8, thru<mln::meta::hue<hsi_f>, image2d<hsi_f> > > hue(h); - - std::string n(argv[i]); - n.erase(n.length() - 4); - image2d<int_u8> henc; - level::transform(hue, fun::v2v::enc< float01_8 >(), henc); - io::pgm::save(henc, n.append("_hue.pgm")); - - image2d<hsi_f>::piter p(hsi.domain()); - float m = 0; - for_all(p) - { - if (h(p) > m) - m = h(p); - } - std::cout << std::endl << m << std::endl; - - - - std::string name(argv[i]); - name.erase(name.length() - 4); - save_histo(hue, name.append("_hue.pbm")); - - - thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > s(hsi); - cast_image_<float01_8, thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > > sat(s); - - n = argv[i]; - n.erase(n.length() - 4); - image2d<int_u8> senc; - level::transform(sat, fun::v2v::enc< float01_8 >(), senc); - io::pgm::save(senc, n.append("_sat.pgm")); - - m = 0; - for_all(p) - { - if (s(p) > m) - m = s(p); - } - std::cout << std::endl << m << std::endl; - - - name = argv[i]; - name.erase(name.length() - 4); - save_histo(sat, name.append("_sat.pbm")); - - thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > l(hsi); - cast_image_<float01_8, thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > > inty(l); - - n = argv[i]; - n.erase(n.length() - 4); - image2d<int_u8> ienc; - level::transform(inty, fun::v2v::enc< float01_8 >(), ienc); - io::pgm::save(ienc, n.append("_inty.pgm")); - - - m = 0; - for_all(p) - { - if (l(p) > m) - m = l(p); - } - std::cout << std::endl << m << std::endl; - - - name = argv[i]; - name.erase(name.length() - 4); - save_histo(inty, name.append("_inty.pbm")); - - } -} Index: ballas/color/min_tree_volume_filter.cc --- ballas/color/min_tree_volume_filter.cc (revision 3184) +++ ballas/color/min_tree_volume_filter.cc (working copy) @@ -1,551 +0,0 @@ -# include <mln/core/var.hh> - -# include <mln/core/image/image2d.hh> -# include <mln/core/image/image_if.hh> -# include <mln/core/image/extended.hh> -# include <mln/core/routine/extend.hh> - -# include <mln/core/alias/window2d.hh> -# include <mln/core/alias/neighb2d.hh> -# include <mln/make/double_neighb2d.hh> -# include <mln/core/site_set/p_centered.hh> - - -# include <mln/literal/black.hh> - -# include <mln/value/int_u8.hh> -# include <mln/value/int_u16.hh> -# include <mln/io/pgm/load.hh> -# include <mln/io/pgm/save.hh> - -# include <mln/value/rgb8.hh> -# include <mln/io/ppm/load.hh> -# include <mln/io/ppm/save.hh> - -# include <mln/accu/min_max.hh> - -# include <mln/fun/i2v/array.hh> -# include <mln/fun/p2v/iota.hh> - -# include <mln/data/paste.hh> -# include <mln/data/fill.hh> -# include <mln/level/transform.hh> -# include <mln/extension/fill.hh> - -# include <mln/morpho/closing_area.hh> -# include <mln/opt/at.hh> - - -# include <mln/debug/println.hh> - -# include "src/distance.hh" - - -namespace mln -{ - template <typename I, typename N, typename Ic, typename Nc> - struct min_tree_ - { - typedef mln_site(I) point; - typedef p_array<point> S; - - // in: - const I& f; - const N& nbh; - const Ic& ref; - const Nc& nbhc; - - // aux: - S s; - mln_ch_value(I, bool) deja_vu; - mln_ch_value(I, point) parent; - mln_ch_value(I, bool) resp; - mln_ch_value(I, point) zpar; - - // attached data: - int lambda; - mln_ch_value(I, int) volume; - mln_ch_value(Ic, value::rgb8) color; - - - min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) - : f(f), - nbh(nbh), - ref(ref), - nbhc(nbhc), - lambda(lambda) - { - run(); - } - - void run() - { - // init - { - initialize(deja_vu, f); - initialize(parent, f); - initialize(resp, f); - initialize(zpar, f); - initialize(volume, f); - initialize(color, f); - - mln::data::fill(deja_vu, false); - mln::data::fill(color, value::rgb8(255, 255, 255)); - mln::data::fill(volume, 0); - - s = level::sort_psites_increasing(f); - } - - // first pass - { - mln_fwd_piter(S) p(s); - mln_niter(N) n(nbh, p); - for_all(p) - { - make_set(p); - for_all(n) - if (f.has(n) && deja_vu(n)) - do_union(n, p); - deja_vu(p) = true; - } - } - - // second pass: canonization - { - mln_bkd_piter(S) p(s); - for_all(p) - { - point q = parent(p); - if (f(parent(q)) == f(q)) - { - parent(p) = parent(q); - resp(q) = false; - } - } - } - - // third pass: Merging region with volume < lambda - { - mln_fwd_piter(S) p(s); - for_all(p) - { - if (resp(p) && (volume(p) < lambda)) - { - resp(p) = false; - update_data(parent(p), volume(p), color(p)); - } - } - } - - } // end of run() - - void make_set(const point& p) - { - parent(p) = p; - zpar(p) = p; - init_data(p); - } - - void set_parent(const point& r, const point& p) - { - parent(r) = p; - merge_data(r, p); - } - - bool is_root(const point& p) const - { - return parent(p) == p; - } - - bool is_node(const point& p) const - { - //return is_root(p) || f(parent(p)) != f(p); - return (is_root(p) || resp(p)); - } - - point find_root(const point& x) - { - if (zpar(x) == x) - return x; - else - return zpar(x) = find_root(zpar(x)); - } - - point find_representative(const point& x) - { - if (parent(x) == x || resp(x)) - return x; - else - return find_representative(parent(x)); - } - - void do_union(const point& n, const point& p) - { - point r = find_root(n); - if (r != p) - { - set_parent(r, p); - zpar(r) = p; - } - } - - void init_data(const point& p) - { - // init volume - volume(p) = f(p); - - - // init color - int red =0, green = 0, blue = 0; - - mln_niter(Nc) n(nbhc, p); - for_all(n) - { - red += ref(n).red(); - green += ref(n).green(); - blue += ref(n).blue(); - } - - red /= 2; - green /= 2; - blue /= 2; - - color(p).red() = red; - color(p).green() = green; - color(p).blue() = blue; - - - resp(p) = true; - } - - void merge_data(const point& r, const point& p) - { - if (f(p) == f(r)) - { - resp(p) = false; - - // merge volume - volume(r) += volume(p); - - // merge color - color(r) = (color(r) + color(p)) / 2; - } - } - - void update_data(const point& p, int val, value::rgb8 c) - { - // update volume - volume(p) += val; - // update color - color(p) = (color(p) + c) / 2; - - if (parent(p) != p && !resp(p)) - update_data(parent(p), val, color(p)); - } - - }; -} - -namespace mln -{ - image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data) - { - image2d<value::int_u16> output(data.domain()); - mln_piter_(image2d<value::int_u16>) p(output.domain()); - for_all(p) - output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12; - return output; - } -} // end of mln - -namespace mln -{ - - struct colorize : Function_v2v< colorize > - { - typedef value::rgb8 result; - colorize(unsigned max) - : lut(max + 1) - { - lut[0] = literal::black; - for (unsigned i = 1; i <= max; ++i) - lut[i] = result(100 + std::rand() % 150, - 100 + std::rand() % 150, - 100 + std::rand() % 150); - } - result operator()(unsigned i) const - { - return lut[i]; - } - std::vector<result> lut; - }; - - template <typename I> - I display_edge(const I& ima, mln_value(I) bg, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - data::fill(output, bg); - - mln_VAR(edge, ima | is_edge); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - - template <typename I> - I display_edge(const I& ima, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - - mln_VAR( cell, ima | is_cell ); - mln_piter(cell_t) q(cell.domain()); - for_all(q) - { - unsigned row = (q.row() / 2) * (zoom + 1); - unsigned col = (q.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - for (unsigned j = 0; j < zoom; ++j) - opt::at(output, row + i, col + j) = ima(q); - } - - mln_VAR( edge, ima | is_edge ); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - - namespace morpho - { - - template <typename I, typename N> - mln_concrete(I) - dilation(const I& input, const N& nbh) - { - typedef mln_value(I) V; - - mln_concrete(I) output; - initialize(output, input); - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - for_all(n) - if (input.has(n) && input(n) != value::rgb8(0,0,0)) - output(p) = input(n); - } - return output; - } - } // mln::morpho - -} // mln - - - -template <typename T> -mln::image2d<T> -image2cells(const mln::image2d<T>& input) -{ - mln::image2d<T> output(2 * input.nrows() - 1, - 2 * input.ncols() - 1); - for (unsigned row = 0; row < input.nrows(); ++row) - for (unsigned col = 0; col < input.ncols(); ++col) - mln::opt::at(output, 2 * row, 2 * col) = mln::opt::at(input, row, col); - return output; -} - - -template <typename T> -mln::image2d<T> -cells2image(const mln::image2d<T>& input) -{ - mln::image2d<T> output((input.nrows() + 1) / 2, - (input.ncols() + 1) / 2); - for (unsigned row = 0; row < input.nrows(); row += 2) - for (unsigned col = 0; col < input.ncols(); col += 2) - mln::opt::at(output, row / 2, col / 2) = mln::opt::at(input, row, col); - return output; -} - - - - -template <typename I, typename N, typename Ic, typename Nc> -unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) -{ - using namespace mln; - - min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda); - - - mln_piter(I) p(f.domain()); - unsigned nnodes = 0; - for_all(p) - { - if (run.is_node(p)) - ++nnodes; - } - - colorize colors(nnodes); - image2d<value::rgb8> tmp(ref.domain()); - data::fill(tmp, literal::black); - image2d<value::rgb8> tmp2(ref.domain()); - data::fill(tmp, ref); - - mln_piter(I) q(f.domain()); - unsigned int i = 0; - for_all(q) - { - if (run.is_node(q)) - { - tmp(q) = run.color(q); - tmp2(q) = colors(i); - i++; - } - } - - mln_piter(I) r(f.domain()); - for_all(r) - { - if (!run.is_node(r)) - { - tmp(r) = tmp(run.find_representative(r)); - tmp2(r) = tmp2(run.find_representative(r)); - } - } - - image2d<value::rgb8> to_display(tmp.domain()); - image2d<value::rgb8> to_display2(tmp2.domain()); - - data::fill(to_display, literal::black); - data::paste((tmp | is_edge), to_display); - data::paste(morpho::dilation(to_display, c4()), to_display); - - data::fill(to_display2, literal::black); - data::paste((tmp2 | is_edge), to_display2); - data::paste(morpho::dilation(to_display2, c4()), to_display2); - - - io::ppm::save(display_edge(tmp, literal::black, 3), "edge.ppm"); - io::ppm::save(tmp, "full.ppm"); - io::ppm::save(cells2image(to_display), "colorize.ppm"); - - io::ppm::save(display_edge(tmp2, literal::black, 3), "edge2.ppm"); - io::ppm::save(cells2image(to_display2), "colorize2.ppm"); - - return nnodes; -} - - - -template <typename I> -I -do_it(I& input, int lambda, unsigned& nbasins) -{ - using namespace mln; - - /// Graph creation - I graph; - create_graph(input, graph, value::rgb8(0, 0, 0)); - - // Initialization - image2d<value::int_u16> ima = convert_to_grey(graph); - - // Neigbhorhood - // e2c - bool e2c_h[] = { 0, 1, 0, - 0, 0, 0, - 0, 1, 0 }; - bool e2c_v[] = { 0, 0, 0, - 1, 0, 1, - 0, 0, 0 }; - - mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v)); - - bool e2e_h[] = { 0, 0, 1, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 1, 0, 0 }; - - bool e2e_v[] = { 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 1, 0, 0, 0, 1, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0 }; - mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v)); - - // Algorithm - distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima); - - io::pgm::save(ima, "edge.pgm"); - - nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda); - - return graph; -} - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl; - std::cerr << " lambda >= 0" << std::endl; - abort(); -} - -int main(int argc, char* argv[]) -{ - using namespace mln; - - if (argc != 3) - usage(argv); - - int lambda = atoi(argv[2]); - if (lambda < 0) - usage(argv); - - image2d<value::rgb8> ima; - io::ppm::load(ima, argv[1]); - - unsigned nbasins; - image2d<value::rgb8> output = do_it(ima, lambda, nbasins); - - //io::ppm::save(output, argv[3]); -} Index: ballas/color/reference.cc --- ballas/color/reference.cc (revision 3184) +++ ballas/color/reference.cc (working copy) @@ -1,557 +0,0 @@ -# include <mln/core/var.hh> - -# include <mln/core/image/image2d.hh> -# include <mln/core/image/image_if.hh> -# include <mln/core/image/extended.hh> -# include <mln/core/routine/extend.hh> - -# include <mln/core/alias/window2d.hh> -# include <mln/core/alias/neighb2d.hh> -# include <mln/make/double_neighb2d.hh> -# include <mln/core/site_set/p_centered.hh> - -# include <mln/literal/origin.hh> -# include <mln/literal/black.hh> -# include <mln/literal/white.hh> - -# include <mln/value/int_u8.hh> -# include <mln/io/pgm/load.hh> -# include <mln/io/pgm/save.hh> - -# include <mln/value/rgb8.hh> -# include <mln/io/ppm/load.hh> -# include <mln/io/ppm/save.hh> - -# include <mln/accu/min_max.hh> -# include <mln/accu/mean.hh> - -# include <mln/fun/i2v/array.hh> -# include <mln/fun/p2v/iota.hh> - -# include <mln/data/paste.hh> -# include <mln/data/fill.hh> -# include <mln/level/transform.hh> -# include <mln/extension/fill.hh> -# include <mln/convert/to.hh> - -# include <mln/linear/gaussian.hh> - -# include <mln/morpho/meyer_wst.hh> -# include <mln/morpho/closing_volume.hh> - -# include <mln/make/w_window2d.hh> -# include <mln/opt/at.hh> - -# include <mln/debug/println.hh> - -// Laplacian method -namespace mln -{ - namespace linear - { - // required to deal with a input image that differ from the output since I - //don't succeed in using a float image in entry. - template <class I, class O> - inline - void - gaussian_2nd_derivative(const Image<I>& input, float sigma, Image<O>& output) - { - mln_precondition(exact(input).is_valid()); - - 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); - } - - template <class I, class O> - inline - void - gaussian_1st_derivative(const Image<I>& input, float sigma, Image<O>& output) - { - mln_precondition(exact(input).is_valid()); - - 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); - } - } -} - -// Gradient + watershed method -namespace mln -{ - namespace morpho - { - template <typename I, typename N> - mln_concrete(I) - closing_volume(const I& input, const Neighborhood<N>& nbh, std::size_t lambda) - { - mln_concrete(I) output; - initialize(output, input); - closing_volume(input, nbh, lambda, output); - return output; - } - } -} // !mln - -namespace mln -{ - image2d<value::int_u8> convert_to_grey(const image2d<value::rgb8>& data) - { - image2d<value::int_u8> output(data.domain()); - mln_piter_(image2d<value::int_u8>) p(output.domain()); - for_all(p) - output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12; - return output; - } -} // !mln - -// Functions - -inline -bool is_row_odd(const mln::point2d& p) -{ - return p.row() % 2; -} - -inline -bool is_cell(const mln::point2d& p) -{ - return p.row() % 2 == 0 && p.col() % 2 == 0; -} - -inline -bool is_edge(const mln::point2d& p) -{ - return p.row() % 2 + p.col() % 2 == 1; -} - -inline -bool is_point(const mln::point2d& p) -{ - return p.row() % 2 && p.col() % 2; -} - -inline -bool is_not_edge(const mln::point2d& p) -{ - return ! is_edge(p); -} - - - -namespace mln -{ - - namespace border - { - - template <typename I> - void - fill(I& ima, const mln_value(I)& v) - { - const int nrows = ima.nrows(); - const int ncols = ima.ncols(); - for (int r = -1; r <= nrows; ++r) - { - opt::at(ima, r, -1) = v; - opt::at(ima, r, ncols) = v; - } - for (int c = -1; c <= ncols; ++c) - { - opt::at(ima, -1, c) = v; - opt::at(ima, nrows, c) = v; - } - } - - } // mln::border - - namespace accu - { - - template <typename I, typename L, typename A, typename V> - inline - void - compute(const Image<I>& input_, - const Image<L>& label_, - const Accumulator<A>&, - V& v) - { - trace::entering("accu::compute"); - - const I& input = exact(input_); - const L& label = exact(label_); - - const unsigned n = v.size(); - std::vector<A> a(n); - - mln_piter(I) p(input.domain()); - for_all(p) - a[label(p)].take(input(p)); - - for (unsigned l = 1; l < n; ++l) - v(l) = a[l].to_result(); - - trace::exiting("accu::compute"); - } - - } // mln::accu - - namespace morpho - { - - template <typename I, typename N> - mln_concrete(I) - gradient(const I& input, const N& nbh) - { - mln_concrete(I) output; - initialize(output, input); - accu::min_max<mln_value(I)> mm; - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - mm.init(); - for_all(n) if (input.has(n)) - mm.take(input(n)); - output(p) = mm.second() - mm.first(); - } - return output; - } - - template <typename I, typename N> - mln_concrete(I) - dilation(const I& input, const N& nbh) - { - typedef mln_value(I) V; - - mln_concrete(I) output; - initialize(output, input); - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - for_all(n) - if (input.has(n) && input(n) != value::rgb8(0,0,0)) - output(p) = input(n); - } - return output; - } - } // mln::morpho - - - struct colorize : Function_v2v< colorize > - { - typedef value::rgb8 result; - colorize(unsigned max) - : lut(max + 1) - { - lut[0] = literal::black; - for (unsigned i = 1; i <= max; ++i) - lut[i] = result(100 + std::rand() % 150, - 100 + std::rand() % 150, - 100 + std::rand() % 150); - } - result operator()(unsigned i) const - { - return lut[i]; - } - std::vector<result> lut; - }; - - - template <typename I> - I display_edge_with_bg(const I& ima, unsigned zoom, mln_value(I) bg) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - data::fill(output, bg); - mln_VAR( edge, ima | is_edge ); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - template <typename I> - I display_edge(const I& ima, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - - mln_VAR( cell, ima | is_cell ); - mln_piter(cell_t) q(cell.domain()); - for_all(q) - { - unsigned row = (q.row() / 2) * (zoom + 1); - unsigned col = (q.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - for (unsigned j = 0; j < zoom; ++j) - opt::at(output, row + i, col + j) = ima(q); - } - - mln_VAR( edge, ima | is_edge ); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - -} // mln - - - -template <typename T> -mln::image2d<T> -image2cells(const mln::image2d<T>& input) -{ - mln::image2d<T> output(2 * input.nrows() - 1, - 2 * input.ncols() - 1); - for (int row = 0; row < input.nrows(); ++row) - for (int col = 0; col < input.ncols(); ++col) - mln::opt::at(output, 2 * row, 2 * col) = mln::opt::at(input, row, col); - return output; -} - -namespace mln { - - template <typename I, typename N, typename M> - mln_concrete(I) - mean(const I& input, const N& nbh, const M& nbh2) - { - mln_concrete(I) output; - initialize(output, input); - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - mln_niter(M) m(nbh2, p); - for_all(p) - { - if (is_edge(p)) - { - int nb = 0; - int r = 0, g = 0, b = 0; - for_all(n) - { - if (input.has(n)) - { - r += input(n).red(); - g += input(n).green(); - b += input(n).blue(); - ++nb; - } - } - output(p) = value::rgb8(r / nb, g / nb, b / nb); - } - if (is_point(p)) - { - int nb = 0; - int r = 0, g = 0, b = 0; - for_all(m) - { - if (input.has(m)) - { - r += input(m).red(); - g += input(m).green(); - b += input(m).blue(); - ++nb; - } - } - output(p) = value::rgb8(r / nb, g / nb, b / nb); - } - if (is_cell(p)) - output(p) = input(p); - } - return output; - } - -} - -template <typename T> -mln::image2d<T> -cells2image(const mln::image2d<T>& input) -{ - mln::image2d<T> output((input.nrows() + 1) / 2, - (input.ncols() + 1) / 2); - for (int row = 0; row < input.nrows(); row += 2) - for (int col = 0; col < input.ncols(); col += 2) - mln::opt::at(output, row / 2, col / 2) = mln::opt::at(input, row, col); - return output; -} - - - - -template <typename I> -mln_concrete(I) -do_it(I& input, float lambda, unsigned& nbasins) -{ - using namespace mln; - - /**************************/ - /* Neighborhood defintion */ - /**************************/ - - // e2c - bool e2c_h[] = { 0, 1, 0, - 0, 0, 0, - 0, 1, 0 }; - bool e2c_v[] = { 0, 0, 0, - 1, 0, 1, - 0, 0, 0 }; - mln_VAR( e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v) ); - - // e2e - bool e2e_h[] = { 0, 0, 1, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 1, 0, 0 }; - bool e2e_v[] = { 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 1, 0, 0, 0, 1, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0 }; - mln_VAR( e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v) ); - - // e2p - bool e2p_h[] = { 1, 0, 1, - 0, 0, 0, - 1, 0, 1 }; - bool e2p_v[] = { 1, 0, 1, - 0, 0, 0, - 1, 0, 1 }; - mln_VAR( e2p, make::double_neighb2d(is_row_odd, e2p_h, e2p_v) ); - - /******************/ - /* Initialisation */ - /******************/ - - I output = mean(image2cells(input), e2c, e2p); - io::ppm::save(output, "tmp_input.ppm"); - //image2d<value::int_u8> ima = convert_to_grey(output); - image2d<value::int_u8> imau = convert_to_grey(output); - io::pgm::save(imau, "tmp_grey_input.pgm"); - - image2d<float> ima(exact(imau).domain()); - - // cell - mln_VAR(cell, imau | is_cell); - - // edge - mln_VAR(edge, extend((imau | is_edge).rw(), pw::value(imau))); - - // FIXME until laplacian is working use gradient / closing_area / wst - - linear::gaussian_2nd_derivative(imau, lambda, ima); - - mln_piter(edge_t) p(edge.domain()); - for_all(p) - { - if (is_row_odd(p)) - { - mln_value(image2d<float>) t = opt::at(ima, p.row() - 1, p.col()); - mln_value(image2d<float>) b = opt::at(ima, p.row() + 1, p.col()); - if ((t > 0 && b < 0) || (t < 0 && b > 0)) - output(p) = value::rgb8(255,0,0); - } - else - { - mln_value(image2d<float>) r = opt::at(ima, p.row(), p.col() - 1); - mln_value(image2d<float>) d = opt::at(ima, p.row(), p.col() + 1); - if ((r > 0 && d < 0) || (r < 0 && d > 0)) - output(p) = value::rgb8(255,0,0); - } - } - -#if 0 - data::paste(morpho::gradient(edge, e2c), edge); - data::paste(morpho::closing_volume(edge, e2e, lambda), edge); - data::fill(edge, morpho::meyer_wst(edge, e2e, nbasins)); - - // Fill regions (with colorize) (won't work with laplacian...) - - colorize colors(nbasins); - - image2d<value::rgb8> cells(ima.domain()); - data::fill(cells, literal::white); - data::paste(level::transform(edge, colors), cells); - io::ppm::save(display_edge_with_bg(cells, 3, literal::white), "tmp_edge.ppm"); - - // Move the color of an edge which is non black in the cell - data::paste(morpho::dilation(cells, c4()), cells); -#endif - - //cells = convert_to_rgb8(ima); - - return output; -} - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.pgm lambda output.ppm" << std::endl; - std::cerr << " lambda >= 0" << std::endl; - abort(); -} - -int main(int argc, char* argv[]) -{ - using namespace mln; - - if (argc != 4) - usage(argv); - - float lambda = atof(argv[2]); - if (lambda < 0) - usage(argv); - - image2d<value::rgb8> ima; - io::ppm::load(ima, argv[1]); - - unsigned nbasins; - image2d<value::rgb8> output = do_it(ima, lambda, nbasins); - - io::ppm::save(display_edge(output, 3), argv[3]); -} Index: ballas/color/min_tree_area_filter.cc --- ballas/color/min_tree_area_filter.cc (revision 3184) +++ ballas/color/min_tree_area_filter.cc (working copy) @@ -1,515 +0,0 @@ -# include <mln/core/var.hh> - -# include <mln/core/image/image2d.hh> -# include <mln/core/image/image_if.hh> -# include <mln/core/image/extended.hh> -# include <mln/core/routine/extend.hh> - -# include <mln/core/alias/window2d.hh> -# include <mln/core/alias/neighb2d.hh> -# include <mln/make/double_neighb2d.hh> -# include <mln/core/site_set/p_centered.hh> - -# include <mln/literal/origin.hh> -# include <mln/literal/black.hh> -# include <mln/literal/white.hh> - -# include <mln/value/int_u8.hh> -# include <mln/value/int_u16.hh> -# include <mln/io/pgm/load.hh> -# include <mln/io/pgm/save.hh> - -# include <mln/value/rgb8.hh> -# include <mln/io/ppm/load.hh> -# include <mln/io/ppm/save.hh> - -# include <mln/accu/min_max.hh> - -# include <mln/fun/i2v/array.hh> -# include <mln/fun/p2v/iota.hh> - -# include <mln/data/paste.hh> -# include <mln/data/fill.hh> -# include <mln/level/transform.hh> -# include <mln/extension/fill.hh> - -# include <mln/morpho/meyer_wst.hh> -# include <mln/morpho/closing_area.hh> - -# include <mln/opt/at.hh> - -# include <mln/debug/println.hh> - -# if 0 -# include <mln/core/concept/image.hh> -# include <mln/core/concept/neighborhood.hh> -# include <mln/util/pix.hh> -# include <mln/morpho/includes.hh> -# include <mln/level/sort_psites.hh> -#endif - -# include "src/distance.hh" - -namespace mln -{ - template <typename I, typename N, typename Ic, typename Nc> - struct min_tree_ - { - typedef mln_site(I) point; - typedef p_array<point> S; - - // in: - const I& f; - const N& nbh; - const Ic& ref; - const Nc& nbhc; - - // aux: - S s; - mln_ch_value(I, bool) deja_vu; - mln_ch_value(I, point) parent; - mln_ch_value(I, bool) resp; - mln_ch_value(I, point) zpar; - - // attached data: - int lambda; - mln_ch_value(I, int) area; - //mln_ch_value(Ic, value::rgb8) values; - //initialize(values, ref); - //mln_ch_value(I, int) comp; - - min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) - : f(f), - nbh(nbh), - ref(ref), - nbhc(nbhc), - lambda(lambda) - { - run(); - } - - void run() - { - // init - { - initialize(deja_vu, f); - initialize(parent, f); - initialize(resp, f); - initialize(zpar, f); - initialize(area, f); - //initialize(comp, f); - - mln::data::fill(deja_vu, false); - //mln::data::fill(resp, false); - mln::data::fill(area, 0); - - s = level::sort_psites_increasing(f); - } - - // first pass - { - mln_fwd_piter(S) p(s); - mln_niter(N) n(nbh, p); - for_all(p) - { - make_set(p); - for_all(n) - if (f.has(n) && deja_vu(n)) - do_union(n, p); - deja_vu(p) = true; - } - } - - // second pass: canonization - { - mln_bkd_piter(S) p(s); - for_all(p) - { - point q = parent(p); - if (f(parent(q)) == f(q)) - { - parent(p) = parent(q); - resp(q) = false; - } - } - } - - // third pass: Merging region with area < lambda - { - mln_fwd_piter(S) p(s); - for_all(p) - { - if (resp(p) && area(p) < lambda) - { - resp(p) = false; - update_data(parent(p), area(p)); - } - } - } - } // end of run() - - void make_set(const point& p) - { - parent(p) = p; - zpar(p) = p; - init_data(p); - } - - void set_parent(const point& r, const point& p) - { - parent(r) = p; - merge_data(r, p); - } - - bool is_root(const point& p) const - { - return parent(p) == p; - } - - bool is_node(const point& p) const - { - //return is_root(p) || f(parent(p)) != f(p); - return (is_root(p) || resp(p)); - } - - point find_root(const point& x) - { - if (zpar(x) == x) - return x; - else - return zpar(x) = find_root(zpar(x)); - } - - point find_representative(const point& x) - { - if (parent(x) == x || resp(x)) - return x; - else - return find_representative(parent(x)); - } - - void do_union(const point& n, const point& p) - { - point r = find_root(n); - if (r != p) - { - set_parent(r, p); - zpar(r) = p; - } - } - - void init_data(const point& p) - { - area(p) = 1; - resp(p) = true; - } - - void merge_data(const point& r, const point& p) - { - if (f(p) == f(r)) - { - resp(p) = false; - area(p) += area(r); - } - } - - void update_data(const point& p, int val) - { - area(p) += val; - if (parent(p) != p && !resp(p)) - update_data(parent(p), val); - } - - }; -} - -namespace mln -{ - image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data) - { - image2d<value::int_u16> output(data.domain()); - mln_piter_(image2d<value::int_u16>) p(output.domain()); - for_all(p) - output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12; - return output; - } -} // end of mln - -namespace mln -{ - - struct colorize : Function_v2v< colorize > - { - typedef value::rgb8 result; - colorize(unsigned max) - : lut(max + 1) - { - lut[0] = literal::black; - for (unsigned i = 1; i <= max; ++i) - lut[i] = result(100 + std::rand() % 150, - 100 + std::rand() % 150, - 100 + std::rand() % 150); - } - result operator()(unsigned i) const - { - return lut[i]; - } - std::vector<result> lut; - }; - - template <typename I> - I display_edge(const I& ima, mln_value(I) bg, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - data::fill(output, bg); - - mln_VAR(edge, ima | is_edge); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - template <typename I> - I display_edge(const I& ima, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - - mln_VAR( cell, ima | is_cell ); - mln_piter(cell_t) q(cell.domain()); - for_all(q) - { - unsigned row = (q.row() / 2) * (zoom + 1); - unsigned col = (q.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - for (unsigned j = 0; j < zoom; ++j) - opt::at(output, row + i, col + j) = ima(q); - } - - mln_VAR( edge, ima | is_edge ); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - - namespace morpho - { - - template <typename I, typename N> - mln_concrete(I) - dilation(const I& input, const N& nbh) - { - typedef mln_value(I) V; - - mln_concrete(I) output; - initialize(output, input); - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - for_all(n) - if (input.has(n) && input(n) != value::rgb8(0,0,0)) - output(p) = input(n); - } - return output; - } - } // mln::morpho - - -} // mln - - - -template <typename T> -mln::image2d<T> -image2cells(const mln::image2d<T>& input) -{ - mln::image2d<T> output(2 * input.nrows() - 1, - 2 * input.ncols() - 1); - for (unsigned row = 0; row < input.nrows(); ++row) - for (unsigned col = 0; col < input.ncols(); ++col) - mln::opt::at(output, 2 * row, 2 * col) = mln::opt::at(input, row, col); - return output; -} - - -template <typename T> -mln::image2d<T> -cells2image(const mln::image2d<T>& input) -{ - mln::image2d<T> output((input.nrows() + 1) / 2, - (input.ncols() + 1) / 2); - for (unsigned row = 0; row < input.nrows(); row += 2) - for (unsigned col = 0; col < input.ncols(); col += 2) - mln::opt::at(output, row / 2, col / 2) = mln::opt::at(input, row, col); - return output; -} - - -template <typename I, typename N, typename Ic, typename Nc> -unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) -{ - using namespace mln; - - min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda); - - - mln_piter(I) p(f.domain()); - unsigned nnodes = 0; - for_all(p) - { - if (run.is_node(p)) - { - std::cout << "nodes: " << p << std::endl; - ++nnodes; - } - } - - colorize colors(nnodes); - image2d<value::rgb8> tmp(ref.domain()); - data::fill(tmp, ref); - - mln_piter(I) q(f.domain()); - unsigned int i = 0; - for_all(q) - { - if (run.is_node(q)) - { - tmp(q) = colors(i); - i++; - } - } - mln_piter(I) r(f.domain()); - for_all(r) - { - if (!run.is_node(r)) - { - tmp(r) = tmp(run.find_representative(r)); - } - } - - - image2d<value::rgb8> to_display(tmp.domain()); - - data::fill(to_display, value::rgb8(255, 255, 255)); - data::paste((tmp | is_edge), to_display); - data::paste(morpho::dilation(to_display, c4()), to_display); - - io::ppm::save(display_edge(tmp, literal::white, 3), - "edge.ppm"); - io::ppm::save(tmp, "full.ppm"); - io::ppm::save(cells2image(to_display), "colorize.ppm"); - - return nnodes; -} - - -template <typename I> -I -do_it(I& input, int lambda, unsigned& nbasins) -{ - using namespace mln; - - /// Graph creation - I graph; - create_graph(input, graph, value::rgb8(0, 0, 0)); - - // Initialization - image2d<value::int_u16> ima = convert_to_grey(graph); - - // Neigbhorhood - // e2c - bool e2c_h[] = { 0, 1, 0, - 0, 0, 0, - 0, 1, 0 }; - bool e2c_v[] = { 0, 0, 0, - 1, 0, 1, - 0, 0, 0 }; - - mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v)); - - bool e2e_h[] = { 0, 0, 1, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 1, 0, 0 }; - - bool e2e_v[] = { 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 1, 0, 0, 0, 1, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0 }; - mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v)); - - // Algorithm - distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima); - io::pgm::save(ima, "edge.pgm"); - - nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda); - - return graph; -} - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl; - std::cerr << " lambda >= 0" << std::endl; - abort(); -} - -int main(int argc, char* argv[]) -{ - using namespace mln; - - if (argc != 3) - usage(argv); - - int lambda = atoi(argv[2]); - if (lambda < 0) - usage(argv); - - image2d<value::rgb8> ima; - io::ppm::load(ima, argv[1]); - - unsigned nbasins; - image2d<value::rgb8> output = do_it(ima, lambda, nbasins); - - //io::ppm::save(output, argv[3]); -} Index: ballas/color/min_tree_height_filter.cc --- ballas/color/min_tree_height_filter.cc (revision 3184) +++ ballas/color/min_tree_height_filter.cc (working copy) @@ -1,553 +0,0 @@ -# include <mln/core/var.hh> - -# include <mln/core/image/image2d.hh> -# include <mln/core/image/image_if.hh> -# include <mln/core/image/extended.hh> -# include <mln/core/routine/extend.hh> - -# include <mln/core/alias/window2d.hh> -# include <mln/core/alias/neighb2d.hh> -# include <mln/make/double_neighb2d.hh> -# include <mln/core/site_set/p_centered.hh> - - -# include <mln/literal/black.hh> - -# include <mln/value/int_u8.hh> -# include <mln/value/int_u16.hh> -# include <mln/io/pgm/load.hh> -# include <mln/io/pgm/save.hh> - -# include <mln/value/rgb8.hh> -# include <mln/io/ppm/load.hh> -# include <mln/io/ppm/save.hh> - -# include <mln/accu/min_max.hh> - -# include <mln/fun/i2v/array.hh> -# include <mln/fun/p2v/iota.hh> - -# include <mln/data/paste.hh> -# include <mln/data/fill.hh> -# include <mln/level/transform.hh> -# include <mln/extension/fill.hh> -# include <mln/opt/at.hh> - -# include <mln/morpho/closing_area.hh> - - -# include <mln/debug/println.hh> - -# include "src/distance.hh" - - -namespace mln -{ - template <typename I, typename N, typename Ic, typename Nc> - struct min_tree_ - { - typedef mln_site(I) point; - typedef p_array<point> S; - - // in: - const I& f; - const N& nbh; - const Ic& ref; - const Nc& nbhc; - - // aux: - S s; - mln_ch_value(I, bool) deja_vu; - mln_ch_value(I, point) parent; - mln_ch_value(I, bool) resp; - mln_ch_value(I, point) zpar; - - // attached data: - int lambda; - mln_ch_value(I, int) height; - mln_ch_value(Ic, value::rgb8) color; - - - min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) - : f(f), - nbh(nbh), - ref(ref), - nbhc(nbhc), - lambda(lambda) - { - run(); - } - - void run() - { - // init - { - initialize(deja_vu, f); - initialize(parent, f); - initialize(resp, f); - initialize(zpar, f); - initialize(height, f); - initialize(color, f); - - mln::data::fill(deja_vu, false); - mln::data::fill(color, value::rgb8(255, 255, 255)); - mln::data::fill(height, 0); - - s = level::sort_psites_increasing(f); - } - - // first pass - { - mln_fwd_piter(S) p(s); - mln_niter(N) n(nbh, p); - for_all(p) - { - make_set(p); - for_all(n) - if (f.has(n) && deja_vu(n)) - do_union(n, p); - deja_vu(p) = true; - } - } - - // second pass: canonization - { - mln_bkd_piter(S) p(s); - for_all(p) - { - point q = parent(p); - if (f(parent(q)) == f(q)) - { - parent(p) = parent(q); - resp(q) = false; - } - } - } - - // third pass: Merging region with height < lambda - { - mln_fwd_piter(S) p(s); - for_all(p) - { - if (resp(p) && (height(p) < lambda)) - { - resp(p) = false; - update_data(parent(p), height(p), color(p)); - } - } - } - - } // end of run() - - void make_set(const point& p) - { - parent(p) = p; - zpar(p) = p; - init_data(p); - } - - void set_parent(const point& r, const point& p) - { - parent(r) = p; - merge_data(r, p); - } - - bool is_root(const point& p) const - { - return parent(p) == p; - } - - bool is_node(const point& p) const - { - //return is_root(p) || f(parent(p)) != f(p); - return (is_root(p) || resp(p)); - } - - point find_root(const point& x) - { - if (zpar(x) == x) - return x; - else - return zpar(x) = find_root(zpar(x)); - } - - point find_representative(const point& x) - { - if (parent(x) == x || resp(x)) - return x; - else - return find_representative(parent(x)); - } - - void do_union(const point& n, const point& p) - { - point r = find_root(n); - if (r != p) - { - set_parent(r, p); - zpar(r) = p; - } - } - - void init_data(const point& p) - { - // init height - height(p) = f(p); - - - // init color - int red =0, green = 0, blue = 0; - - mln_niter(Nc) n(nbhc, p); - for_all(n) - { - red += ref(n).red(); - green += ref(n).green(); - blue += ref(n).blue(); - } - - red /= 2; - green /= 2; - blue /= 2; - - color(p).red() = red; - color(p).green() = green; - color(p).blue() = blue; - - - resp(p) = true; - } - - void merge_data(const point& r, const point& p) - { - if (f(p) == f(r)) - { - resp(p) = false; - - // merge height - height(r) += height(r) > height(p) ? height(r) : height(p); - - // merge color - color(r) = (color(r) + color(p)) / 2; - } - } - - void update_data(const point& p, int val, value::rgb8 c) - { - // update height - height(p) = height(p) > val ? height(p) : val; - // update color - color(p) = (color(p) + c) / 2; - - if (parent(p) != p && !resp(p)) - update_data(parent(p), val, color(p)); - } - - }; -} - -namespace mln -{ - image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data) - { - image2d<value::int_u16> output(data.domain()); - mln_piter_(image2d<value::int_u16>) p(output.domain()); - for_all(p) - output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12; - return output; - } -} // end of mln - -namespace mln -{ - - struct colorize : Function_v2v< colorize > - { - typedef value::rgb8 result; - colorize(unsigned max) - : lut(max + 1) - { - lut[0] = literal::black; - for (unsigned i = 1; i <= max; ++i) - lut[i] = result(100 + std::rand() % 150, - 100 + std::rand() % 150, - 100 + std::rand() % 150); - } - result operator()(unsigned i) const - { - return lut[i]; - } - std::vector<result> lut; - }; - - template <typename I> - I display_edge(const I& ima, mln_value(I) bg, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - data::fill(output, bg); - - mln_VAR(edge, ima | is_edge); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - - template <typename I> - I display_edge(const I& ima, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - - mln_VAR( cell, ima | is_cell ); - mln_piter(cell_t) q(cell.domain()); - for_all(q) - { - unsigned row = (q.row() / 2) * (zoom + 1); - unsigned col = (q.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - for (unsigned j = 0; j < zoom; ++j) - opt::at(output, row + i, col + j) = ima(q); - } - - mln_VAR( edge, ima | is_edge ); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - - namespace morpho - { - - template <typename I, typename N> - mln_concrete(I) - dilation(const I& input, const N& nbh) - { - typedef mln_value(I) V; - - mln_concrete(I) output; - initialize(output, input); - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - for_all(n) - if (input.has(n) && input(n) != value::rgb8(0,0,0)) - output(p) = input(n); - } - return output; - } - } // mln::morpho - -} // mln - - - -template <typename T> -mln::image2d<T> -image2cells(const mln::image2d<T>& input) -{ - mln::image2d<T> output(2 * input.nrows() - 1, - 2 * input.ncols() - 1); - for (unsigned row = 0; row < input.nrows(); ++row) - for (unsigned col = 0; col < input.ncols(); ++col) - mln::opt::at(output, 2 * row, 2 * col) = - mln::opt::at(input, row, col); - return output; -} - - -template <typename T> -mln::image2d<T> -cells2image(const mln::image2d<T>& input) -{ - mln::image2d<T> output((input.nrows() + 1) / 2, - (input.ncols() + 1) / 2); - for (unsigned row = 0; row < input.nrows(); row += 2) - for (unsigned col = 0; col < input.ncols(); col += 2) - mln::opt::at(output, row / 2, col / 2) = - mln::opt::at(input, row, col); - return output; -} - - - - -template <typename I, typename N, typename Ic, typename Nc> -unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) -{ - using namespace mln; - - min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda); - - - mln_piter(I) p(f.domain()); - unsigned nnodes = 0; - for_all(p) - { - if (run.is_node(p)) - ++nnodes; - } - - colorize colors(nnodes); - image2d<value::rgb8> tmp(ref.domain()); - data::fill(tmp, literal::black); - image2d<value::rgb8> tmp2(ref.domain()); - data::fill(tmp, ref); - - mln_piter(I) q(f.domain()); - unsigned int i = 0; - for_all(q) - { - if (run.is_node(q)) - { - tmp(q) = run.color(q); - tmp2(q) = colors(i); - i++; - } - } - - mln_piter(I) r(f.domain()); - for_all(r) - { - if (!run.is_node(r)) - { - tmp(r) = tmp(run.find_representative(r)); - tmp2(r) = tmp2(run.find_representative(r)); - } - } - - image2d<value::rgb8> to_display(tmp.domain()); - image2d<value::rgb8> to_display2(tmp2.domain()); - - data::fill(to_display, literal::black); - data::paste((tmp | is_edge), to_display); - data::paste(morpho::dilation(to_display, c4()), to_display); - - data::fill(to_display2, literal::black); - data::paste((tmp2 | is_edge), to_display2); - data::paste(morpho::dilation(to_display2, c4()), to_display2); - - - io::ppm::save(display_edge(tmp, literal::black, 3), "edge.ppm"); - io::ppm::save(tmp, "full.ppm"); - io::ppm::save(cells2image(to_display), "colorize.ppm"); - - io::ppm::save(display_edge(tmp2, literal::black, 3), "edge2.ppm"); - io::ppm::save(cells2image(to_display2), "colorize2.ppm"); - - return nnodes; -} - - - -template <typename I> -I -do_it(I& input, int lambda, unsigned& nbasins) -{ - using namespace mln; - - /// Graph creation - I graph; - create_graph(input, graph, value::rgb8(0, 0, 0)); - - // Initialization - image2d<value::int_u16> ima = convert_to_grey(graph); - - // Neigbhorhood - // e2c - bool e2c_h[] = { 0, 1, 0, - 0, 0, 0, - 0, 1, 0 }; - bool e2c_v[] = { 0, 0, 0, - 1, 0, 1, - 0, 0, 0 }; - - mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v)); - - bool e2e_h[] = { 0, 0, 1, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 1, 0, 0 }; - - bool e2e_v[] = { 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 1, 0, 0, 0, 1, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0 }; - mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v)); - - // Algorithm - distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima); - - io::pgm::save(ima, "edge.pgm"); - - nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda); - - return graph; -} - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl; - std::cerr << " lambda >= 0" << std::endl; - abort(); -} - -int main(int argc, char* argv[]) -{ - using namespace mln; - - if (argc != 3) - usage(argv); - - int lambda = atoi(argv[2]); - if (lambda < 0) - usage(argv); - - image2d<value::rgb8> ima; - io::ppm::load(ima, argv[1]); - - unsigned nbasins; - image2d<value::rgb8> output = do_it(ima, lambda, nbasins); - - //io::ppm::save(output, argv[3]); -} Index: ballas/color/min_tree_color.cc --- ballas/color/min_tree_color.cc (revision 3184) +++ ballas/color/min_tree_color.cc (working copy) @@ -1,536 +0,0 @@ -# include <mln/core/var.hh> - -# include <mln/core/image/image2d.hh> -# include <mln/core/image/image_if.hh> -# include <mln/core/image/extended.hh> -# include <mln/core/routine/extend.hh> - -# include <mln/core/alias/window2d.hh> -# include <mln/core/alias/neighb2d.hh> -# include <mln/make/double_neighb2d.hh> -# include <mln/core/site_set/p_centered.hh> - -# include <mln/literal/origin.hh> -# include <mln/literal/black.hh> -# include <mln/literal/white.hh> - -# include <mln/value/int_u8.hh> -# include <mln/value/int_u16.hh> -# include <mln/io/pgm/load.hh> -# include <mln/io/pgm/save.hh> - -# include <mln/value/rgb8.hh> -# include <mln/io/ppm/load.hh> -# include <mln/io/ppm/save.hh> - -# include <mln/accu/min_max.hh> - -# include <mln/fun/i2v/array.hh> -# include <mln/fun/p2v/iota.hh> - -# include <mln/data/paste.hh> -# include <mln/data/fill.hh> -# include <mln/level/transform.hh> -# include <mln/extension/fill.hh> - -# include <mln/morpho/closing_area.hh> -# include <mln/opt/at.hh> - - -# include <mln/debug/println.hh> - -# if 0 -# include <mln/core/concept/image.hh> -# include <mln/core/concept/neighborhood.hh> -# include <mln/util/pix.hh> -# include <mln/morpho/includes.hh> -# include <mln/level/sort_psites.hh> -#endif - -# include "src/distance.hh" - -namespace mln -{ - template <typename I, typename N, typename Ic, typename Nc> - struct min_tree_ - { - typedef mln_site(I) point; - typedef p_array<point> S; - - // in: - const I& f; - const N& nbh; - const Ic& ref; - const Nc& nbhc; - - // aux: - S s; - mln_ch_value(I, bool) deja_vu; - mln_ch_value(I, point) parent; - mln_ch_value(I, bool) resp; - mln_ch_value(I, point) zpar; - - // attached data: - unsigned lambda; - mln_ch_value(I, value::rgb8) color; - //mln_ch_value(Ic, value::rgb8) values; - //initialize(values, ref); - //mln_ch_value(I, int) comp; - - min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) - : f(f), - nbh(nbh), - ref(ref), - nbhc(nbhc), - lambda(lambda) - { - run(); - } - - void run() - { - // init - { - initialize(deja_vu, f); - initialize(parent, f); - initialize(resp, f); - initialize(zpar, f); - initialize(color, f); - //initialize(comp, f); - - mln::data::fill(deja_vu, false); - //mln::data::fill(resp, false); - mln::data::fill(color, value::rgb8(0, 0, 0)); - - s = level::sort_psites_increasing(f); - } - - // first pass - { - mln_fwd_piter(S) p(s); - mln_niter(N) n(nbh, p); - for_all(p) - { - make_set(p); - for_all(n) - if (f.has(n) && deja_vu(n)) - do_union(n, p); - deja_vu(p) = true; - } - } - - // second pass: canonization - { - mln_bkd_piter(S) p(s); - for_all(p) - { - point q = parent(p); - if (f(parent(q)) == f(q)) - { - parent(p) = parent(q); - resp(q) = false; - } - } - } - - // third pass: Merging region with distance(color) < lambda - { - mln_fwd_piter(S) p(s); - for_all(p) - { - point q = parent(p); - if (resp(p) && distance(color(p), color(q)) < lambda) - { - resp(p) = false; - update_data(q, color(p)); - } - } - } - - } // end of run() - - void make_set(const point& p) - { - parent(p) = p; - zpar(p) = p; - init_data(p); - } - - void set_parent(const point& r, const point& p) - { - parent(r) = p; - merge_data(r, p); - } - - bool is_root(const point& p) const - { - return parent(p) == p; - } - - bool is_node(const point& p) const - { - //return is_root(p) || f(parent(p)) != f(p); - return (is_root(p) || resp(p)); - } - - point find_root(const point& x) - { - if (zpar(x) == x) - return x; - else - return zpar(x) = find_root(zpar(x)); - } - - point find_representative(const point& x) - { - if (parent(x) == x || resp(x)) - return x; - else - return find_representative(parent(x)); - } - - void do_union(const point& n, const point& p) - { - point r = find_root(n); - if (r != p) - { - set_parent(r, p); - zpar(r) = p; - } - } - - void init_data(const point& p) - { - int red =0, green = 0, blue = 0; - - mln_niter(Nc) n(nbhc, p); - for_all(n) - { - red += ref(n).red(); - green += ref(n).green(); - blue += ref(n).blue(); - } - - red /= 2; - green /= 2; - blue /= 2; - - color(p).red() = red; - color(p).green() = green; - color(p).blue() = blue; - - resp(p) = true; - } - - void merge_data(const point& r, const point& p) - { - if (f(p) == f(r)) - { - resp(p) = false; - color(r) = (color(r) + color(p)) / 2; - } - } - - void update_data(const point& p, value::rgb8 val) - { - color(p) = (color(p) + val) / 2; - if (parent(p) != p && !resp(p)) - update_data(parent(p), color(p)); - } - - }; -} - -namespace mln -{ - image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data) - { - image2d<value::int_u16> output(data.domain()); - mln_piter_(image2d<value::int_u16>) p(output.domain()); - for_all(p) - output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12; - return output; - } -} // end of mln - -namespace mln -{ - - struct colorize : Function_v2v< colorize > - { - typedef value::rgb8 result; - colorize(unsigned max) - : lut(max + 1) - { - lut[0] = literal::black; - for (unsigned i = 1; i <= max; ++i) - lut[i] = result(100 + std::rand() % 150, - 100 + std::rand() % 150, - 100 + std::rand() % 150); - } - result operator()(unsigned i) const - { - return lut[i]; - } - std::vector<result> lut; - }; - - template <typename I> - I display_edge(const I& ima, mln_value(I) bg, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - data::fill(output, bg); - - mln_VAR(edge, ima | is_edge); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - template <typename I> - I display_edge(const I& ima, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - - mln_VAR( cell, ima | is_cell ); - mln_piter(cell_t) q(cell.domain()); - for_all(q) - { - unsigned row = (q.row() / 2) * (zoom + 1); - unsigned col = (q.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - for (unsigned j = 0; j < zoom; ++j) - opt::at(output, row + i, col + j) = ima(q); - } - - mln_VAR( edge, ima | is_edge ); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - - namespace morpho - { - - template <typename I, typename N> - mln_concrete(I) - dilation(const I& input, const N& nbh) - { - typedef mln_value(I) V; - - mln_concrete(I) output; - initialize(output, input); - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - for_all(n) - if (input.has(n) && input(n) != value::rgb8(0,0,0)) - output(p) = input(n); - } - return output; - } - } // mln::morpho - -} // mln - - - -template <typename T> -mln::image2d<T> -image2cells(const mln::image2d<T>& input) -{ - mln::image2d<T> output(2 * input.nrows() - 1, - 2 * input.ncols() - 1); - for (unsigned row = 0; row < input.nrows(); ++row) - for (unsigned col = 0; col < input.ncols(); ++col) - mln::opt::at(output, 2 * row, 2 * col) = - mln::opt::at(input, row, col); - return output; -} - - -template <typename T> -mln::image2d<T> -cells2image(const mln::image2d<T>& input) -{ - mln::image2d<T> output((input.nrows() + 1) / 2, - (input.ncols() + 1) / 2); - for (unsigned row = 0; row < input.nrows(); row += 2) - for (unsigned col = 0; col < input.ncols(); col += 2) - mln::opt::at(output, row / 2, col / 2) = - mln::opt::at(input, row, col); - return output; -} - - -template <typename I, typename N, typename Ic, typename Nc> -unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) -{ - using namespace mln; - - min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda); - - - mln_piter(I) p(f.domain()); - unsigned nnodes = 0; - for_all(p) - { - if (run.is_node(p)) - ++nnodes; - } - -#if 1 - colorize colors(nnodes); - image2d<value::rgb8> tmp(ref.domain()); - data::fill(tmp, ref); - - - mln_piter(I) q(f.domain()); - unsigned int i = 0; - for_all(q) - { - if (run.is_node(q)) - { - tmp(q) = colors(i); - i++; - } - } - mln_piter(I) r(f.domain()); - for_all(r) - { - if (!run.is_node(r)) - tmp(r) = tmp(run.find_representative(r)); - } - - image2d<value::rgb8> to_display(tmp.domain()); - - data::fill(to_display, value::rgb8(255, 255, 255)); - data::paste((tmp | is_edge), to_display); - data::paste(morpho::dilation(to_display, c4()), to_display); - - io::ppm::save(display_edge(tmp, literal::white, 3), - "edge.ppm"); - io::ppm::save(tmp, "full.ppm"); - io::ppm::save(cells2image(to_display), "colorize.ppm"); -#endif - -#if 1 - // io::ppm::save(display_edge(run.values, literal::white, 3), "tmp_tree_colored.pgm"); -#endif - - return nnodes; -} - - -template <typename I> -I -do_it(I& input, int lambda, unsigned& nbasins) -{ - using namespace mln; - - /// Graph creation - I graph; - create_graph(input, graph, value::rgb8(0, 0, 0)); - - // Initialization - image2d<value::int_u16> ima = convert_to_grey(graph); - - // Neigbhorhood - // e2c - bool e2c_h[] = { 0, 1, 0, - 0, 0, 0, - 0, 1, 0 }; - bool e2c_v[] = { 0, 0, 0, - 1, 0, 1, - 0, 0, 0 }; - - mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v)); - - bool e2e_h[] = { 0, 0, 1, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 1, 0, 0 }; - - bool e2e_v[] = { 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 1, 0, 0, 0, 1, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0 }; - mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v)); - - // Algorithm - distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima); - - io::pgm::save(ima, "edge.pgm"); - - nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda); - - return graph; -} - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl; - std::cerr << " lambda >= 0" << std::endl; - abort(); -} - -int main(int argc, char* argv[]) -{ - using namespace mln; - - if (argc != 3) - usage(argv); - - int lambda = atoi(argv[2]); - if (lambda < 0) - usage(argv); - - image2d<value::rgb8> ima; - io::ppm::load(ima, argv[1]); - - unsigned nbasins; - image2d<value::rgb8> output = do_it(ima, lambda, nbasins); - - //io::ppm::save(output, argv[3]); -} Index: ballas/color/reference2.cc --- ballas/color/reference2.cc (revision 3184) +++ ballas/color/reference2.cc (working copy) @@ -1,408 +0,0 @@ -# include <mln/core/var.hh> - -# include <mln/core/image/image2d.hh> -# include <mln/core/image/image_if.hh> -# include <mln/core/image/extended.hh> -# include <mln/core/routine/extend.hh> - -# include <mln/core/alias/window2d.hh> -# include <mln/core/alias/neighb2d.hh> -# include <mln/make/double_neighb2d.hh> -# include <mln/core/site_set/p_centered.hh> - -# include <mln/literal/origin.hh> -# include <mln/literal/black.hh> -# include <mln/literal/white.hh> - -# include <mln/value/int_u8.hh> -# include <mln/io/pgm/load.hh> -# include <mln/io/pgm/save.hh> - -# include <mln/value/rgb8.hh> -# include <mln/io/ppm/load.hh> -# include <mln/io/ppm/save.hh> - -# include <mln/accu/min_max.hh> -# include <mln/accu/mean.hh> - -# include <mln/fun/i2v/array.hh> -# include <mln/fun/p2v/iota.hh> - -# include <mln/data/paste.hh> -# include <mln/data/fill.hh> -# include <mln/level/transform.hh> -# include <mln/extension/fill.hh> - -# include <mln/morpho/meyer_wst.hh> -# include <mln/morpho/closing_volume.hh> - -# include <mln/linear/convolve.hh> -# include <mln/make/w_window2d.hh> - -# include <mln/opt/at.hh> - -# include <mln/debug/println.hh> - -namespace mln -{ - namespace morpho - { - template <typename I, typename N> - mln_concrete(I) - closing_volume(const I& input, const Neighborhood<N>& nbh, std::size_t lambda) - { - mln_concrete(I) output; - initialize(output, input); - closing_volume(input, nbh, lambda, output); - return output; - } - } -} - -namespace mln -{ - template <typename I, typename O> - void - LoG_17x17(const I& input, const O& output) - { - mln_precondition(exact(output).domain() == exact(input).domain()); - int ws[] = { +0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, - +0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, - +0, 0,-1,-1,-1,-2,-3,-3,-3,-3,-3,-2,-1,-1,-1, 0, 0, - +0, 0,-1,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1,-1, 0, 0, - +0,-1,-1,-2,-3,-3,-3,-2,-3,-2,-3,-3,-3,-2,-1,-1, 0, - +0,-1,-2,-3,-3,-3, 0, 2, 4, 2, 0,-3,-3,-3,-2,-1, 0, - -1,-1,-3,-3,-3, 0, 4,10,12,10, 4, 0,-3,-3,-3,-1,-1, - -1,-1,-3,-3,-2, 2,10,18,21,18,10, 2,-2,-3,-3,-1,-1, - -1,-1,-3,-3,-3, 4,12,21,24,21,12, 4,-3,-3,-3,-1,-1, - -1,-1,-3,-3,-2, 2,10,18,21,18,10, 2,-2,-3,-3,-1,-1, - -1,-1,-3,-3,-3, 0, 4,10,12,10, 4, 0,-3,-3,-3,-1,-1, - +0,-1,-2,-3,-3,-3, 0, 2, 4, 2, 0,-3,-3,-3,-2,-1, 0, - +0,-1,-1,-2,-3,-3,-3,-2,-3,-2,-3,-3,-3,-2,-1,-1, 0, - +0, 0,-1,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1,-1, 0, 0, - +0, 0,-1,-1,-1,-2,-3,-3,-3,-3,-3,-2,-1,-1,-1, 0, 0, - +0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, - +0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0 }; - linear::convolve(input, make::w_window2d(ws), output); - } -} // !mln - -namespace mln -{ - image2d<value::int_u8> convert_to_grey(const image2d<value::rgb8>& data) - { - image2d<value::int_u8> output(data.domain()); - mln_piter_(image2d<value::int_u8>) p(output.domain()); - for_all(p) - output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12; - return output; - } -} // !mln - -// Functions - -inline -bool is_row_odd(const mln::point2d& p) -{ - return p.row() % 2; -} - -inline -bool is_cell(const mln::point2d& p) -{ - return p.row() % 2 == 0 && p.col() % 2 == 0; -} - -inline -bool is_edge(const mln::point2d& p) -{ - return p.row() % 2 + p.col() % 2 == 1; -} - -inline -bool is_point(const mln::point2d& p) -{ - return p.row() % 2 && p.col() % 2; -} - -inline -bool is_not_edge(const mln::point2d& p) -{ - return ! is_edge(p); -} - - - -namespace mln -{ - - namespace border - { - - template <typename I> - void - fill(I& ima, const mln_value(I)& v) - { - const int nrows = ima.nrows(); - const int ncols = ima.ncols(); - for (int r = -1; r <= nrows; ++r) - { - opt::at(ima, r, -1) = v; - opt::at(ima, r, ncols) = v; - } - for (int c = -1; c <= ncols; ++c) - { - opt::at(ima, -1, c) = v; - opt::at(ima, nrows, c) = v; - } - } - - } // mln::border - - namespace accu - { - - template <typename I, typename L, typename A, typename V> - inline - void - compute(const Image<I>& input_, - const Image<L>& label_, - const Accumulator<A>&, - V& v) - { - trace::entering("accu::compute"); - - const I& input = exact(input_); - const L& label = exact(label_); - - const unsigned n = v.size(); - std::vector<A> a(n); - - mln_piter(I) p(input.domain()); - for_all(p) - a[label(p)].take(input(p)); - - for (unsigned l = 1; l < n; ++l) - v(l) = a[l].to_result(); - - trace::exiting("accu::compute"); - } - - } // mln::accu - - namespace morpho - { - - template <typename I, typename N> - mln_concrete(I) - gradient(const I& input, const N& nbh) - { - mln_concrete(I) output; - initialize(output, input); - accu::min_max<mln_value(I)> mm; - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - mm.init(); - for_all(n) if (input.has(n)) - mm.take(input(n)); - output(p) = mm.second() - mm.first(); - } - return output; - } - - template <typename I, typename N> - mln_concrete(I) - dilation(const I& input, const N& nbh) - { - typedef mln_value(I) V; - - mln_concrete(I) output; - initialize(output, input); - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - for_all(n) - if (input.has(n) && input(n) != value::rgb8(0,0,0)) - output(p) = input(n); - } - return output; - } - } // mln::morpho - - - struct colorize : Function_v2v< colorize > - { - typedef value::rgb8 result; - colorize(unsigned max) - : lut(max + 1) - { - lut[0] = literal::black; - for (unsigned i = 1; i <= max; ++i) - lut[i] = result(100 + std::rand() % 150, - 100 + std::rand() % 150, - 100 + std::rand() % 150); - } - result operator()(unsigned i) const - { - return lut[i]; - } - std::vector<result> lut; - }; - - - template <typename I> - I display_edge(const I& ima, mln_value(I) bg, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - data::fill(output, bg); - mln_VAR( edge, ima | is_edge ); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - -} // mln - - - -template <typename T> -mln::image2d<T> -image2cells(const mln::image2d<T>& input) -{ - mln::image2d<T> output(2 * input.nrows() - 1, - 2 * input.ncols() - 1); - for (int row = 0; row < input.nrows(); ++row) - for (int col = 0; col < input.ncols(); ++col) - mln::opt::at(output, 2 * row, 2 * col) = mln::opt::at(input, row, col); - return output; -} - - -template <typename T> -mln::image2d<T> -cells2image(const mln::image2d<T>& input) -{ - mln::image2d<T> output((input.nrows() + 1) / 2, - (input.ncols() + 1) / 2); - for (int row = 0; row < input.nrows(); row += 2) - for (int col = 0; col < input.ncols(); col += 2) - mln::opt::at(output, row / 2, col / 2) = mln::opt::at(input, row, col); - return output; -} - - - - -template <typename I> -mln_concrete(I) -do_it(I& input, int lambda, unsigned& nbasins) -{ - using namespace mln; - - /******************/ - /* Initialisation */ - /******************/ - - image2d<value::int_u8> ima = image2cells(convert_to_grey(input)); - - /**************************/ - /* Neighborhood defintion */ - /**************************/ - - // e2c - bool e2c_h[] = { 0, 1, 0, - 0, 0, 0, - 0, 1, 0 }; - bool e2c_v[] = { 0, 0, 0, - 1, 0, 1, - 0, 0, 0 }; - mln_VAR( e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v) ); - - // e2e - bool e2e_h[] = { 0, 0, 1, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 1, 0, 0 }; - bool e2e_v[] = { 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 1, 0, 0, 0, 1, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0 }; - mln_VAR( e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v) ); - - // cell - mln_VAR(cell, ima | is_cell); - - // edge - mln_VAR(edge, extend((ima | is_edge).rw(), pw::value(ima))); - - // FIXME until laplacian is working use gradient / closing_area / wst - - data::paste(morpho::gradient(edge, e2c), edge); - data::paste(morpho::closing_volume(edge, e2e, lambda), edge); - data::fill(edge, morpho::meyer_wst(edge, e2e, nbasins)); - - // Fill regions (with colorize) (won't work with laplacian...) - - colorize colors(nbasins); - - image2d<value::rgb8> cells(ima.domain()); - data::fill(cells, literal::white); - data::paste(level::transform(edge, colors), cells); - io::ppm::save(display_edge(cells, literal::white, 3), "tmp_edge.ppm"); - - // Move the color of an edge which is non black in the cell - data::paste(morpho::dilation(cells, c4()), cells); - - return cells2image(cells); -} - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.pgm lambda output.ppm" << std::endl; - std::cerr << " lambda >= 0" << std::endl; - abort(); -} - -int main(int argc, char* argv[]) -{ - using namespace mln; - - if (argc != 4) - usage(argv); - - int lambda = atoi(argv[2]); - if (lambda < 0) - usage(argv); - - image2d<value::rgb8> ima; - io::ppm::load(ima, argv[1]); - - unsigned nbasins; - image2d<value::rgb8> output = do_it(ima, lambda, nbasins); - - io::ppm::save(output, argv[3]); -} Index: ballas/color/src/graph.hh --- ballas/color/src/graph.hh (revision 3184) +++ ballas/color/src/graph.hh (working copy) @@ -1,62 +0,0 @@ -/*! \file src/graph.hh - * - */ - -#ifndef SRC_GRAPH_HH -# define SRC_GRAPH_HH - -# include <mln/value/int_u8.hh> -# include <mln/value/int_u16.hh> -# include <mln/value/rgb8.hh> - -# include <mln/data/fill.hh> -# include <mln/opt/at.hh> - -# include <mln/core/image/image2d.hh> - - -// Neighborhood functions -inline -bool is_row_odd(const mln::point2d& p) -{ - return p.row() % 2; -} -inline -bool is_cell(const mln::point2d& p) -{ - return p.row() % 2 == 0 && p.col() % 2 == 0; -} -inline -bool is_edge(const mln::point2d& p) -{ - return (p.row() % 2 + p.col() % 2) == 1; -} -inline -bool is_point(const mln::point2d& p) -{ - return p.row() % 2 && p.col() % 2; -} -inline -bool is_not_edge(const mln::point2d& p) -{ - return ! is_edge(p); -} - -// Graph image creation function -// FIXME: add exact conversion.... -// FIXME: check that the input image is in 2 dimension -template <typename I> -void -create_graph(const I& ima, I& graph, mln_value(I) val) -{ - graph = I(ima.nrows() * 2 -1, ima.ncols() * 2 - 1); - - mln::data::fill(graph, val); - - mln_piter(I) p(ima.domain()); - for_all(p) - mln::opt::at(graph, p.row() * 2, p.col() * 2) = ima(p); -} - - -#endif // !SRC_GRAPH_HH Index: ballas/color/src/io.hh --- ballas/color/src/io.hh (revision 3184) +++ ballas/color/src/io.hh (working copy) @@ -1,57 +0,0 @@ -/*! \file src/io.hh - * - * Contains various method to load/save an image - */ - -#ifndef SRC_IO_HH -# define SRC_IO_HH - -#include <mln/core/image/image2d.hh> - -#include <mln/value/int_u16.hh> -#include <mln/value/int_s16.hh> - -# include <mln/io/pgm/load.hh> -# include <mln/io/pgm/save.hh> -# include <mln/io/ppm/load.hh> -# include <mln/io/ppm/save.hh> - -namespace IO -{ - - template <typename I> - void load(I& ima, const std::string& file) - { - mln::io::ppm::load(ima, file); - } - - template <> - void load(mln::image2d<mln::value::int_u16>& ima, - const std::string& file) - { - mln::io::pgm::load(ima, file); - } - - template <typename I> - void save(I& ima, const std::string& file) - { - mln::io::ppm::save(ima, file); - } - - template <> - void save(mln::image2d<mln::value::int_u16>& ima, - const std::string& file) - { - mln::io::pgm::save(ima, file); - } - - template <> - void save(mln::image2d<mln::value::int_s16>& ima, - const std::string& file) - { - mln::io::pgm::save(ima, file); - } - -} // !IO - -#endif // !SRC_IO_HH Index: ballas/color/src/distance.hh --- ballas/color/src/distance.hh (revision 3184) +++ ballas/color/src/distance.hh (working copy) @@ -1,52 +0,0 @@ -/*! \file src/distance.hh - * - */ - -#ifndef SRC_DISTANCE_HH -# define SRC_DISTANCE_HH - -# include "graph.hh" - -# include <cmath> - - -/// Manhatan distance -inline -unsigned distance(const mln::value::rgb8& lhs, - const mln::value::rgb8& rhs) -{ - return abs(lhs.red() - rhs.red()) + - abs(lhs.green() - rhs.green()) + - abs(lhs.blue() - rhs.blue()); -} - - -/// Store the distance between two points on edge -/// FIXME documentation -template <typename I, typename N, typename O> -void distance(const I& rgb_graph, - const N& nbh, - O& gl_graph) -{ - mln_piter(I) p(rgb_graph.domain()); - mln_niter(N) n(nbh, p); - - for_all(p) - { - mln::value::rgb8 v1; - mln::value::rgb8 v2; - - n.start(); - assert(n.is_valid() && rgb_graph.has(n)); - v1 = rgb_graph(n); - n.next(); - assert(n.is_valid() && rgb_graph.has(n)); - v2 = rgb_graph(n); - - gl_graph(p) = distance(v1, v2); - } -} - - - -#endif // !SRC_DISTANCE_HH Index: ballas/color/src/convert.hh --- ballas/color/src/convert.hh (revision 3184) +++ ballas/color/src/convert.hh (working copy) @@ -1,37 +0,0 @@ -/*! \file src/convert.hh - * - * Method that convert an rgb image 2d into gray level - */ - -#ifndef SRC_CONVERT_HH -# define SRC_CONVERT_HH - -# include <mln/value/int_u8.hh> -# include <mln/value/int_u16.hh> -# include <mln/value/int_s16.hh> -# include <mln/value/rgb8.hh> - -# include <mln/core/image/image2d.hh> - -// Convert function -void convert_to_gl(mln::image2d<mln::value::int_u16>& ima, - const mln::image2d<mln::value::rgb8>& data) -{ - mln_piter_(mln::image2d<mln::value::int_u16>) p(ima.domain()); - for_all(p) - ima(p) = (int) (data(p).red() * 0.3 + - data(p).green() * 0.58 + - data(p).blue() * 0.12); -} - -void convert_to_gl(mln::image2d<mln::value::int_s16>& ima, - const mln::image2d<mln::value::rgb8>& data) -{ - mln_piter_(mln::image2d<mln::value::int_s16>) p(ima.domain()); - for_all(p) - ima(p) = (int) (data(p).red() * 0.3 + - data(p).green() * 0.58 + - data(p).blue() * 0.12); -} - -#endif // !SRC_CONVERT_HH Index: ballas/color/min_tree_color_v2.cc --- ballas/color/min_tree_color_v2.cc (revision 3184) +++ ballas/color/min_tree_color_v2.cc (working copy) @@ -1,533 +0,0 @@ -# include <mln/core/var.hh> - -# include <mln/core/image/image2d.hh> -# include <mln/core/image/image_if.hh> -# include <mln/core/image/extended.hh> -# include <mln/core/routine/extend.hh> - -# include <mln/core/alias/window2d.hh> -# include <mln/core/alias/neighb2d.hh> -# include <mln/make/double_neighb2d.hh> -# include <mln/core/site_set/p_centered.hh> - - -# include <mln/literal/black.hh> - -# include <mln/value/int_u8.hh> -# include <mln/value/int_u16.hh> -# include <mln/io/pgm/load.hh> -# include <mln/io/pgm/save.hh> - -# include <mln/value/rgb8.hh> -# include <mln/io/ppm/load.hh> -# include <mln/io/ppm/save.hh> - -# include <mln/accu/min_max.hh> - -# include <mln/fun/i2v/array.hh> -# include <mln/fun/p2v/iota.hh> - -# include <mln/data/paste.hh> -# include <mln/data/fill.hh> -# include <mln/level/transform.hh> -# include <mln/extension/fill.hh> - -# include <mln/morpho/closing_area.hh> -# include <mln/opt/at.hh> - - -# include <mln/debug/println.hh> - -# include "src/distance.hh" - -namespace mln -{ - template <typename I, typename N, typename Ic, typename Nc> - struct min_tree_ - { - typedef mln_site(I) point; - typedef p_array<point> S; - - // in: - const I& f; - const N& nbh; - const Ic& ref; - const Nc& nbhc; - - // aux: - S s; - mln_ch_value(I, bool) deja_vu; - mln_ch_value(I, point) parent; - mln_ch_value(I, bool) resp; - mln_ch_value(I, point) zpar; - - // attached data: - unsigned lambda; - mln_ch_value(I, value::rgb8) color; - //mln_ch_value(Ic, value::rgb8) values; - //initialize(values, ref); - //mln_ch_value(I, int) comp; - - min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) - : f(f), - nbh(nbh), - ref(ref), - nbhc(nbhc), - lambda(lambda) - { - run(); - } - - void run() - { - // init - { - initialize(deja_vu, f); - initialize(parent, f); - initialize(resp, f); - initialize(zpar, f); - initialize(color, f); - - mln::data::fill(deja_vu, false); - mln::data::fill(color, value::rgb8(255, 255, 255)); - - s = level::sort_psites_increasing(f); - } - - // first pass - { - mln_fwd_piter(S) p(s); - mln_niter(N) n(nbh, p); - for_all(p) - { - make_set(p); - for_all(n) - if (f.has(n) && deja_vu(n)) - do_union(n, p); - deja_vu(p) = true; - } - } - - // second pass: canonization - { - mln_bkd_piter(S) p(s); - for_all(p) - { - point q = parent(p); - if (f(parent(q)) == f(q)) - { - parent(p) = parent(q); - resp(q) = false; - } - } - } - - // third pass: Merging region with distance(color) < lambda - { - mln_fwd_piter(S) p(s); - for_all(p) - { - point q = parent(p); - if (resp(p) && distance(color(p), color(q)) < lambda) - { - resp(p) = false; - update_data(q, color(p)); - } - } - } - - } // end of run() - - void make_set(const point& p) - { - parent(p) = p; - zpar(p) = p; - init_data(p); - } - - void set_parent(const point& r, const point& p) - { - parent(r) = p; - merge_data(r, p); - } - - bool is_root(const point& p) const - { - return parent(p) == p; - } - - bool is_node(const point& p) const - { - //return is_root(p) || f(parent(p)) != f(p); - return (is_root(p) || resp(p)); - } - - point find_root(const point& x) - { - if (zpar(x) == x) - return x; - else - return zpar(x) = find_root(zpar(x)); - } - - point find_representative(const point& x) - { - if (parent(x) == x || resp(x)) - return x; - else - return find_representative(parent(x)); - } - - void do_union(const point& n, const point& p) - { - point r = find_root(n); - if (r != p) - { - set_parent(r, p); - zpar(r) = p; - } - } - - void init_data(const point& p) - { - int red =0, green = 0, blue = 0; - - mln_niter(Nc) n(nbhc, p); - for_all(n) - { - red += ref(n).red(); - green += ref(n).green(); - blue += ref(n).blue(); - } - - red /= 2; - green /= 2; - blue /= 2; - - color(p).red() = red; - color(p).green() = green; - color(p).blue() = blue; - - resp(p) = true; - } - - void merge_data(const point& r, const point& p) - { - if (f(p) == f(r)) - { - resp(p) = false; - color(r) = (color(r) + color(p)) / 2; - } - } - - void update_data(const point& p, value::rgb8 val) - { - color(p) = (color(p) + val) / 2; - if (parent(p) != p && !resp(p)) - update_data(parent(p), color(p)); - } - - }; -} - -namespace mln -{ - image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data) - { - image2d<value::int_u16> output(data.domain()); - mln_piter_(image2d<value::int_u16>) p(output.domain()); - for_all(p) - output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12; - return output; - } -} // end of mln - -namespace mln -{ - - struct colorize : Function_v2v< colorize > - { - typedef value::rgb8 result; - colorize(unsigned max) - : lut(max + 1) - { - lut[0] = literal::black; - for (unsigned i = 1; i <= max; ++i) - lut[i] = result(100 + std::rand() % 150, - 100 + std::rand() % 150, - 100 + std::rand() % 150); - } - result operator()(unsigned i) const - { - return lut[i]; - } - std::vector<result> lut; - }; - - template <typename I> - I display_edge(const I& ima, mln_value(I) bg, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - data::fill(output, bg); - - mln_VAR(edge, ima | is_edge); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - template <typename I> - I display_edge(const I& ima, unsigned zoom) - { - unsigned nrows = ima.nrows() / 2 + 1; - unsigned ncols = ima.ncols() / 2 + 1; - I output(nrows * (zoom + 1) - 1, - ncols * (zoom + 1) - 1); - - mln_VAR( cell, ima | is_cell ); - mln_piter(cell_t) q(cell.domain()); - for_all(q) - { - unsigned row = (q.row() / 2) * (zoom + 1); - unsigned col = (q.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - for (unsigned j = 0; j < zoom; ++j) - opt::at(output, row + i, col + j) = ima(q); - } - - mln_VAR( edge, ima | is_edge ); - mln_piter(edge_t) p(edge.domain()); - for_all(p) - if (p.row() % 2) // horizontal edge - { - unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1; - unsigned col = (p.col() / 2) * (zoom + 1); - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row, col + i) = ima(p); - } - else // vertical edge - { - unsigned row = (p.row() / 2) * (zoom + 1); - unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1; - for (unsigned i = 0; i < zoom; ++i) - opt::at(output, row + i, col) = ima(p); - } - return output; - } - - - namespace morpho - { - - template <typename I, typename N> - mln_concrete(I) - dilation(const I& input, const N& nbh) - { - typedef mln_value(I) V; - - mln_concrete(I) output; - initialize(output, input); - - mln_piter(I) p(input.domain()); - mln_niter(N) n(nbh, p); - for_all(p) - { - for_all(n) - if (input.has(n) && input(n) != value::rgb8(0,0,0)) - output(p) = input(n); - } - return output; - } - } // mln::morpho - -} // mln - - - -template <typename T> -mln::image2d<T> -image2cells(const mln::image2d<T>& input) -{ - mln::image2d<T> output(2 * input.nrows() - 1, - 2 * input.ncols() - 1); - for (unsigned row = 0; row < input.nrows(); ++row) - for (unsigned col = 0; col < input.ncols(); ++col) - mln::opt::at(output, 2 * row, 2 * col) = - mln::opt::at(input, row, col); - return output; -} - - -template <typename T> -mln::image2d<T> -cells2image(const mln::image2d<T>& input) -{ - mln::image2d<T> output((input.nrows() + 1) / 2, - (input.ncols() + 1) / 2); - for (unsigned row = 0; row < input.nrows(); row += 2) - for (unsigned col = 0; col < input.ncols(); col += 2) - mln::opt::at(output, row / 2, col / 2) = - mln::opt::at(input, row, col); - return output; -} - - -template <typename I, typename N, typename Ic, typename Nc> -unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc, - int lambda) -{ - using namespace mln; - - min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda); - - - mln_piter(I) p(f.domain()); - unsigned nnodes = 0; - for_all(p) - { - if (run.is_node(p)) - ++nnodes; - } - - colorize colors(nnodes); - image2d<value::rgb8> tmp(ref.domain()); - data::fill(tmp, literal::black); - image2d<value::rgb8> tmp2(ref.domain()); - data::fill(tmp, ref); - - mln_piter(I) q(f.domain()); - unsigned int i = 0; - for_all(q) - { - if (run.is_node(q)) - { - tmp(q) = run.color(q); - tmp2(q) = colors(i); - i++; - } - } - - mln_piter(I) r(f.domain()); - for_all(r) - { - if (!run.is_node(r)) - { - tmp(r) = tmp(run.find_representative(r)); - tmp2(r) = tmp2(run.find_representative(r)); - } - } - - image2d<value::rgb8> to_display(tmp.domain()); - image2d<value::rgb8> to_display2(tmp2.domain()); - - data::fill(to_display, literal::black); - data::paste((tmp | is_edge), to_display); - data::paste(morpho::dilation(to_display, c4()), to_display); - - data::fill(to_display2, literal::black); - data::paste((tmp2 | is_edge), to_display2); - data::paste(morpho::dilation(to_display2, c4()), to_display2); - - - io::ppm::save(display_edge(tmp, literal::black, 3), "edge.ppm"); - io::ppm::save(tmp, "full.ppm"); - io::ppm::save(cells2image(to_display), "colorize.ppm"); - - io::ppm::save(display_edge(tmp2, literal::black, 3), "edge2.ppm"); - io::ppm::save(cells2image(to_display2), "colorize2.ppm"); - - return nnodes; -} - - -template <typename I> -I -do_it(I& input, int lambda, unsigned& nbasins) -{ - using namespace mln; - - /// Graph creation - I graph; - create_graph(input, graph, value::rgb8(0, 0, 0)); - - // Initialization - image2d<value::int_u16> ima = convert_to_grey(graph); - - // Neigbhorhood - // e2c - bool e2c_h[] = { 0, 1, 0, - 0, 0, 0, - 0, 1, 0 }; - bool e2c_v[] = { 0, 0, 0, - 1, 0, 1, - 0, 0, 0 }; - - mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v)); - - bool e2e_h[] = { 0, 0, 1, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 0, 0, 1, 0, 0 }; - - bool e2e_v[] = { 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, - 1, 0, 0, 0, 1, - 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0 }; - mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v)); - - // Algorithm - distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima); - - io::pgm::save(ima, "edge.pgm"); - - nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda); - - return graph; -} - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl; - std::cerr << " lambda >= 0" << std::endl; - abort(); -} - -int main(int argc, char* argv[]) -{ - using namespace mln; - - if (argc != 3) - usage(argv); - - int lambda = atoi(argv[2]); - if (lambda < 0) - usage(argv); - - image2d<value::rgb8> ima; - io::ppm::load(ima, argv[1]); - - unsigned nbasins; - image2d<value::rgb8> output = do_it(ima, lambda, nbasins); - - //io::ppm::save(output, argv[3]); -} Index: ballas/color/laplacien.cc --- ballas/color/laplacien.cc (revision 3184) +++ ballas/color/laplacien.cc (working copy) @@ -1,130 +0,0 @@ -#include <mln/core/image/image2d.hh> -#include <mln/core/image/image_if.hh> - -# include <mln/core/alias/neighb2d.hh> -# include <mln/make/double_neighb2d.hh> - -#include <mln/value/rgb8.hh> -#include <mln/value/int_u16.hh> -#include <mln/value/int_s16.hh> - -#include <mln/linear/gaussian.hh> -#include <mln/morpho/erosion.hh> - -#include <mln/core/var.hh> -#include <mln/debug/println.hh> -#include <mln/opt/at.hh> - -#include "src/io.hh" -#include "src/graph.hh" -#include "src/convert.hh" - - -void usage(char* argv[]) -{ - std::cerr << "usage: " << argv[0] << " input.ppm output.pgm" << std::endl; - abort(); -} - -/// FIXME Put these elsewhere -typedef mln::image2d<mln::value::rgb8> Icolor; -typedef mln::image2d<mln::value::int_u16> Igray; - -void process(Icolor& graph, const Icolor& input) -{ - using namespace mln; - - // Neighborhood definition - -// bool e2c_h[] = { 0, 1, 0, -// 0, 0, 0, -// 0, 1, 0 }; -// bool e2c_v[] = { 0, 0, 0, -// 1, 0, 1, -// 0, 0, 0 }; - -// bool e2e_h[] = { 0, 0, 1, 0, 0, -// 0, 1, 0, 1, 0, -// 0, 0, 0, 0, 0, -// 0, 1, 0, 1, 0, -// 0, 0, 1, 0, 0 }; -// bool e2e_v[] = { 0, 0, 0, 0, 0, -// 0, 1, 0, 1, 0, -// 1, 0, 0, 0, 1, -// 0, 1, 0, 1, 0, -// 0, 0, 0, 0, 0 }; - -// bool e2p_h[] = { 0, 0, 1, -// 0, 0, 0, -// 1, 0, 0 }; -// bool e2p_v[] = { 1, 0, 0, -// 0, 0, 0, -// 0, 0, 1 }; - //mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v)); - - - // convert the image into grey level - Igray gray_graph(graph.bbox()); - convert_to_gl(gray_graph, graph); - - Igray gray_input(input.bbox()); - convert_to_gl(gray_input, input); - - - //data::paste(morpho::dilation((gray_graph | is_cell), e2c.win()), gray_graph); -// Igray save(gray_graph.bbox()); -// data::paste(gray_graph | is_cell, save); -// IO::save(save, "tmp3.ppm"); - - // Create the laplacian image - //Igray laplacian(gray_input.bbox()); - image2d<int> laplacian(gray_input.bbox()); - linear::gaussian(gray_input, 2.0f, laplacian); - //IO::save(laplacian, "tmp1.ppm"); - linear::laplacian(gray_input, 2.0f, laplacian); - debug::println(laplacian); - //IO::save(laplacian, "tmp2.ppm"); - - // Display edge on the output images -// debug::println(laplacian); - -// mln_piter_(Igray) p(laplacian.domain()); -// for_all(p) -// if (laplacian(p) == 0u) -// { -// std::cout << "I'm here" << std::endl; -// opt::at(graph, p.row() * 2, p.col() * 2) = value::rgb<8>(255, 0, 0); -// } - -} - - - -int main(int argc, char* argv[]) -{ - using namespace mln; - - // Initialisation - if (argc != 3) - usage(argv); - - std::string input_file(argv[1]); - std::string output_file(argv[2]); - - - Icolor input; - - // Load the image - IO::load(input, input_file); - - // create a graph image from the input - Icolor graph; - create_graph(input, graph); - - // Process - process(graph, input); - - - // Save - IO::save(graph, output_file); -} Index: ballas/color/README --- ballas/color/README (revision 3184) +++ ballas/color/README (working copy) @@ -1,83 +0,0 @@ --*- outline -*- - -* Fichiers sources: - -Les fichiers sources se trouvent dans milena/sandbox/ballas/color/. - -** Les méthodes de références: - -*** reference.cc: - Utilisation de la seconde dérivée de gaussienne. - Les passages par 0 sont mis en rouges. - -*** reference2.cc: - Utilisation d'un gradient puis d'un filtre de clôture de volumes. - - Variante testée (non retenue): - - un filtre de clôture d'aires. - -** min_tree: - -Les approches développées avec le min tree essayent de prendre en compte -la couleur de l'image initial. - -Ici, on "expand" l'image pour pouvoir stocker les points et les edges directement -sur l'image. Puis sur chaque edge, on stocke la distance séparant les deux -pixels voisins cet edge. On construit ensuite un min tree sur ces edges. -Ce min tree est ensuite filtrer afin d'éviter la sur-segmentation - - -*** min_tree_area.cc: - Dans cette version, un filtre d'aire est appliqué aux edges constituant -le min tree. Si l'aire des edges d'une région du min tree est inférieure à un -lambda donné, on fusionne la région avec sa région supérieure. - -*** min_tree_volume.cc - Dans cette version, un filtre de volume est appliqué aux edges constituant -le min tree. - -*** min_tree_color.cc - Dans cette version, on filtre en fonction de la couleur moyenne. -Si la distance entre la couleur moyenne constituant 2 régions est inférieure -à un lambda donné, on fusionne les régions. - - -* Organisation des répertoires: - -Les images de tests se trouve dans le répertoire ~ballas/pub/result/ - -Chaque sous-répertoire contient des tests sur une image en particulier -Cette image est stockée dans le répertoire sous le nom input.ppm. - -Chaque sous-répertoire contiennent des répertoires avec les résultats -en fonction des méthodes utilisées: -- ref1 contient les résultats de la méthode reference.cc -- ref2 contient les résultats de la méthode reference2.cc -- area contient les résultats de la méthode min_tree_area.cc -- volume contient les résultats de la méthode min_tree_volume.cc -- color contient les résultats de la méthode min_tree_color.cc - -Les résultats sont organisés de la manière suivante dans les répertoires -area, volume et color. -** edge.pgm: - Image affichant les edges calculés avant le passage de min tree. - Ces edges contiennent la distance entre les deux pixels voisins. - Les pixels sont noir par défaut dans cette image. -** edge.ppm: - Image affichant les edges calcules après l'application du filtre sur le - min tree. - Ces edges contiennent la distance entre les deux pixels voisins. - Les pixels sont noir par défaut dans cette image. -** full.ppm: - Superposition de l'image edge.ppm et de l'image de départ. -** colorize.ppm: - Image contenant les pixels coloriés à partir des edges de l'image. - On utilise une dilatation pour colorier les pixels, ce qui altère la - forme des lettres. - -Les résultats sont organisés de la manière suivante dans les répertoires -ref1 et ref2. -** lambda_x.ppm: - x est le lambda utilisé pour le filtre. - Dans ref1, nous avons une image avec les contours, alors que dans ref2, - nous une image découpée en zones.
15 years, 11 months
1
0
0
0
3184: Fix coeff.
by Alexandre Abraham
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog from Alexandre Abraham <abraham(a)lrde.epita.fr> Fix coeff. * nature/nature.cc: Fix coeff. nature.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) Index: nature/nature.cc --- nature/nature.cc (revision 3183) +++ nature/nature.cc (working copy) @@ -191,17 +191,17 @@ score[PHOTO] += 100 - max; score[TEXT] += max * 2; - score[SCREENSHOT] += 50 + max / 2; + score[SCREENSHOT] += 80 + max / 2; score[DRAWING] += 50 + max / 2; std::cout << "Test 2 : co-occurence matrix diag_max[" << max << "]" << std::endl << "Photo : +" << 100 - max << std::endl; - std::cout << "Screenshot : +" << 50 + max / 2 << std::endl; + std::cout << "Screenshot : +" << 80 + max / 2 << std::endl; std::cout << "Text : +" << max * 2 << std::endl; - std::cout << "Drawing : +" << 50 + max / 2 << std::endl << std::endl; + std::cout << "Drawing : +" << 80 + max / 2 << std::endl << std::endl; @@ -385,15 +385,15 @@ cpt = 50; score[PHOTO] += 50 - cpt; - score[SCREENSHOT] += cpt * 5; - score[TEXT] += 50 + cpt * max / 10; - score[DRAWING] += 2 * (50 - cpt); + score[SCREENSHOT] += cpt * 8; + score[TEXT] += 50 + cpt * max / 3; + score[DRAWING] += 2 * (60 - cpt); std::cout << "Test 3 : rectangle detection[" << cpt << "]" << std::endl << "Photo : +" << 50 - cpt << std::endl << "Screenshot : +" << cpt * 8 << std::endl - << "Text : +" << 50 + cpt * max / 10 << std::endl - << "Drawing : +" << 2 * (50 - cpt) << std::endl << std::endl; + << "Text : +" << 50 + cpt * max / 3 << std::endl + << "Drawing : +" << 2 * (60 - cpt) << std::endl << std::endl; // Last but not least : text detection thanks to FFT @@ -464,15 +464,15 @@ dist = dist / (log(fftb.nelements()) / log(10)); score[PHOTO] += dist * 25; - score[SCREENSHOT] += dist * 25; - score[TEXT] += (1 + cos(arg)) * (4 - dist) * 25; - score[DRAWING] += dist * 25; + score[SCREENSHOT] += dist * 50; + score[TEXT] += (1 + abs(cos(arg))) * (4 - dist) * 40; + score[DRAWING] += dist * 50; std::cout << "Test 4 : Fourier distance[" << dist << "]" << std::endl << "Photo : +" << dist * 25 << std::endl - << "Screenshot : +" << dist * 25 << std::endl - << "Text : +" << (1 + cos(arg)) * (4 - dist) * 25 << std::endl - << "Drawing : +" << dist * 25 << std::endl << std::endl; + << "Screenshot : +" << dist * 50 << std::endl + << "Text : +" << (1 + abs(cos(arg))) * (4 - dist) * 40 << std::endl + << "Drawing : +" << dist * 50 << std::endl << std::endl; // io::pbm::save(binarization::threshold(fft, max * 4 / 10), name.append("_fft.pbm"));
15 years, 11 months
1
0
0
0
3183: Fix call to 'at'.
by Alexandre Abraham
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog from Alexandre Abraham <abraham(a)lrde.epita.fr> Fix call to 'at'. * abraham/mln/transform/fft.hh: Add forgotten opt:: before at. fft.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) Index: abraham/mln/transform/fft.hh --- abraham/mln/transform/fft.hh (revision 3182) +++ abraham/mln/transform/fft.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008, 2009 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 @@ -442,7 +442,7 @@ } for (unsigned row = 0; row < this->trans_im.nrows(); ++row) for (unsigned col = this->trans_im.ncols() - 1; col > this->trans_im.ncols() / 2; --col) - at(this->trans_im, row, col) = opt::at(this->trans_im, this->trans_im.nrows() - row - 1, + opt::at(this->trans_im, row, col) = opt::at(this->trans_im, this->trans_im.nrows() - row - 1, this->trans_im.ncols() - col - 1); return this->trans_im; }
15 years, 11 months
1
0
0
0
3182: Fix some constants.
by Alexandre Abraham
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog from Alexandre Abraham <abraham(a)lrde.epita.fr> Fix some constants. * nature/nature.cc: Fix constants. * nature/hsi.cc: New. * nature/hom.cc: . hom.cc | 246 ++------------------------------------------------------------ hsi.cc | 80 ++++++++++++++++++++ nature.cc | 26 +++--- 3 files changed, 101 insertions(+), 251 deletions(-) Index: nature/nature.cc --- nature/nature.cc (revision 3181) +++ nature/nature.cc (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -27,7 +27,7 @@ #include <mln/core/image/image2d.hh> #include <mln/core/image/cast_image.hh> -#include <mln/core/image/thru.hh> +#include <mln/core/image/fun_image.hh> #include <mln/core/alias/neighb2d.hh> #include <mln/io/ppm/load.hh> @@ -80,7 +80,7 @@ }; template <typename T> -unsigned nb_peaks (histo::data<T> &h) +unsigned nb_peaks (histo::array<T> &h) { // First, we compute the maximum, ignoring the first column because it // contains nonsense points @@ -126,17 +126,17 @@ image2d<hsi_f> hsi = level::transform(input, fun::v2v::f_rgb_to_hsi_f); - thru<mln::meta::hue<hsi_f>, image2d<hsi_f> > hue(hsi); - thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > sat(hsi); - thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > inty(hsi); - - cast_image_<float01_8, thru<mln::meta::hue<hsi_f>, image2d<hsi_f> > > qhue(hue); // quantified hue - cast_image_<float01_8, thru<mln::meta::sat<hsi_f>, image2d<hsi_f> > > qsat(sat); // quantified sat - cast_image_<float01_8, thru<mln::meta::inty<hsi_f>, image2d<hsi_f> > > qinty(inty); // quantified inty - - histo::data<float01_8> hhue = histo::compute(qhue); - histo::data<float01_8> hsat = histo::compute(qsat); - histo::data<float01_8> hinty = histo::compute(qinty); + fun_image<mln::meta::hue<hsi_f>, image2d<hsi_f> > hue(hsi); + fun_image<mln::meta::sat<hsi_f>, image2d<hsi_f> > sat(hsi); + fun_image<mln::meta::inty<hsi_f>, image2d<hsi_f> > inty(hsi); + + cast_image_<float01_8, fun_image<mln::meta::hue<hsi_f>, image2d<hsi_f> > > qhue(hue); // quantified hue + cast_image_<float01_8, fun_image<mln::meta::sat<hsi_f>, image2d<hsi_f> > > qsat(sat); // quantified sat + cast_image_<float01_8, fun_image<mln::meta::inty<hsi_f>, image2d<hsi_f> > > qinty(inty); // quantified inty + + histo::array<float01_8> hhue = histo::compute(qhue); + histo::array<float01_8> hsat = histo::compute(qsat); + histo::array<float01_8> hinty = histo::compute(qinty); // Compute the number of peaks in the histogram to give a first intuition @@ -465,7 +465,7 @@ score[PHOTO] += dist * 25; score[SCREENSHOT] += dist * 25; - score[TEXT] += (1 + cos(arg)) * 2 * (4 - dist) * 50; + score[TEXT] += (1 + cos(arg)) * (4 - dist) * 25; score[DRAWING] += dist * 25; std::cout << "Test 4 : Fourier distance[" << dist << "]" << std::endl Index: nature/hsi.cc --- nature/hsi.cc (revision 0) +++ nature/hsi.cc (revision 0) @@ -0,0 +1,80 @@ +// Copyright (C) 2007, 2008, 2009 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 <iterator> +#include <string> + +#include <mln/core/image/image2d.hh> +#include <mln/core/image/fun_image.hh> +#include <mln/core/alias/window2d.hh> +#include <mln/win/all.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/hsi.hh> + +#include <mln/fun/v2v/rgb_to_hsi.hh> +#include <mln/fun/meta/inty.hh> + +#include <mln/level/compare.hh> + +#include <mln/io/ppm/load.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/morpho/erosion.hh> + +#include <mln/accu/histo.hh> +#include <mln/histo/compute.hh> +#include <mln/level/transform.hh> +#include <mln/data/paste.hh> + +using namespace mln; +using namespace value; + +int main (int argc, const char* argv []) +{ + if (argc < 2) { + std::cerr << "usage: " << argv[0] << " in.ppm [other_files.ppm]" << std::endl; + return 1; + } + + for (int i = 1; i < argc; ++i) + { + image2d<rgb8> input; + io::ppm::load(input, argv[i]); + + image2d<hsi_f> hsi = level::transform(input, fun::v2v::f_rgb_to_hsi_f); + fun_image<mln::meta::inty<hsi_f>, image2d<hsi_f> > l(hsi); + + win::rectangle2d rect(7,7); + + std::string name = argv[i]; + name.erase(name.length() - 4); + data::paste(morpho::erosion(l, rect), l); + input = level::transform(hsi, fun::v2v::f_hsi_to_rgb_3x8); + io::ppm::save(input, name.append("_tst.ppm")); + } +} Index: nature/hom.cc --- nature/hom.cc (revision 3181) +++ nature/hom.cc (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -45,8 +45,7 @@ #include <mln/morpho/dilation.hh> #include <mln/morpho/opening.hh> -#include <mln/win/hline2d.hh> -#include <mln/win/vline2d.hh> +#include <mln/win/all.hh> int main(int argc, const char * argv[]) { @@ -70,245 +69,16 @@ // Compute the mean int_t mean = estim::mean(ima); + image2d<bool> imab = binarization::threshold(ima, mean-10); - image2d<bool> imab = binarization::threshold(ima, 10); - - - - window2d winout; - window2d winin; - -// static const bool matout [] = {0, 0, 0, 0, 0, 0, 0, -// 0, 0, 1, 0, 0, 0, 0, -// 0, 0, 1, 0, 0, 0, 0, -// 0, 0, 1, 0, 0, 0, 0, -// 0, 0, 1, 1, 1, 1, 0, -// 0, 0, 0, 0, 0, 0, 0, -// 0, 0, 0, 0, 0, 0, 0}; - - static const bool blmatout [] = {0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0}; - -// static const bool blmatout [] = {0, 0, 0, -// 1, 0, 0, -// 1, 1, 0}; - - - convert::from_to(blmatout, winout); - -// static const bool matin [] = {0, 0, 0, 1, 0, 0, 0, -// 0, 0, 0, 1, 0, 0, 0, -// 0, 0, 0, 1, 0, 0, 0, -// 0, 0, 0, 1, 1, 1, 1, -// 0, 0, 0, 0, 0, 0, 0, -// 0, 0, 0, 0, 0, 0, 0, -// 0, 0, 0, 0, 0, 0, 0}; - - static const bool blmatin [] = {0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 1, 1, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - -// static const bool blmatin [] = {0, 1, 0, -// 0, 1, 1, -// 0, 0, 0}; - - convert::from_to(blmatin, winin); - image2d<bool> bottom_left = morpho::hit_or_miss(imab, winout, winin); - - -// static const bool brmatout [] = {0, 0, 0, -// 0, 0, 1, -// 0, 1, 1}; - -// static const bool brmatin [] = {0, 1, 0, -// 1, 1, 0, -// 0, 0, 0}; - - static const bool brmatout [] = {0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0}; - - static const bool brmatin [] = {0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(brmatout, winout); - convert::from_to(brmatin, winin); - image2d<bool> bottom_right = morpho::hit_or_miss(imab, winout, winin); - -// static const bool urmatout [] = {0, 1, 1, -// 0, 0, 1, -// 0, 0, 0}; - -// static const bool urmatin [] = {0, 0, 0, -// 1, 1, 0, -// 0, 1, 0}; - - static const bool urmatout [] = {0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0}; - - static const bool urmatin [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0}; - - - convert::from_to(urmatout, winout); - convert::from_to(urmatin, winin); - image2d<bool> up_right = morpho::hit_or_miss(imab, winout, winin); - - -// static const bool ulmatout [] = {1, 1, 0, -// 1, 0, 0, -// 0, 0, 0}; - -// static const bool ulmatin [] = {0, 0, 0, -// 0, 1, 1, -// 0, 1, 0}; - - static const bool ulmatout [] = {0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0}; - - static const bool ulmatin [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0}; - - - convert::from_to(ulmatout, winout); - convert::from_to(ulmatin, winin); - image2d<bool> up_left = morpho::hit_or_miss(imab, winout, winin); - - - static const bool umatout [] = {0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - static const bool umatin [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(umatout, winout); - convert::from_to(umatin, winin); - image2d<bool> up = morpho::hit_or_miss(imab, winout, winin); - - - static const bool bmatout [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0}; - - static const bool bmatin [] = {0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(bmatout, winout); - convert::from_to(bmatin, winin); - image2d<bool> bottom = morpho::hit_or_miss(imab, winout, winin); - - - static const bool lmatout [] = {0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0}; - - static const bool lmatin [] = {0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(lmatout, winout); - convert::from_to(lmatin, winin); - image2d<bool> left = morpho::hit_or_miss(imab, winout, winin); - - - static const bool rmatout [] = {0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0, - 0, 0, 0, 1, 0}; - - static const bool rmatin [] = {0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0}; - - - convert::from_to(rmatout, winout); - convert::from_to(rmatin, winin); - image2d<bool> right = morpho::hit_or_miss(imab, winout, winin); - + io::pbm::save(imab, "hop.pbm"); + window2d out = win::disk2d(25) - win::disk2d(22); + win::disk2d in(4); std::string name(argv[i]); name.erase(name.length() - 4); - io::pbm::save( imab, name.append("_bin.pbm")); - - name = argv[i]; - name.erase(name.length() - 4); - // image2d<bool> final(right.domain()); - // data::fill(final, false); - // mln_piter_(image2d<bool>) p(final.domain()); - // for_all(p) - // final(p) = up_left(p) || up_right(p) || bottom_right(p) || bottom_left(p) || up(p) || bottom(p) || left(p) || right(p); - - image2d<bool> inter (up_left + up_right + bottom_right + bottom_left + up + bottom + left + right); - - static const bool vert [] = {0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0}; - - static const bool hori [] = {0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0}; - - convert::from_to(vert, winin); - convert::from_to(hori, winout); - - image2d<bool> final = morpho::opening(inter, win::hline2d(20)); - final += morpho::opening(inter, win::vline2d(20)); - - io::pbm::save( final, - name.append("_hom.pbm")); + io::pbm::save(morpho::hit_or_miss(imab, in, out), name.append("_hom.pbm")); } }
15 years, 11 months
1
0
0
0
3181: Add a new LCA implementation to Laurent's code.
by Guillaume Lazzara
* laurent/ismm2009.cc: Use the implementation written by Alexandre Abraham for one of its previous seminar (#0821). --- milena/sandbox/ChangeLog | 7 + milena/sandbox/laurent/ismm2009.cc | 282 ++++++++++++++++++------------------ 2 files changed, 151 insertions(+), 138 deletions(-) diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog index 7fd1cbf..ccd1ffd 100644 --- a/milena/sandbox/ChangeLog +++ b/milena/sandbox/ChangeLog @@ -1,3 +1,10 @@ +2009-01-21 Guillaume Lazzara <z(a)lrde.epita.fr> + + Add a new LCA implementation to Laurent's code. + + * laurent/ismm2009.cc: Use the implementation written by Alexandre + Abraham for one of its previous seminar (#0821). + 2009-01-21 Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr> Update INIM. diff --git a/milena/sandbox/laurent/ismm2009.cc b/milena/sandbox/laurent/ismm2009.cc index eed5f65..c3250d1 100644 --- a/milena/sandbox/laurent/ismm2009.cc +++ b/milena/sandbox/laurent/ismm2009.cc @@ -22,13 +22,13 @@ #include <mln/util/timer.hh> #include <mln/util/fibonacci_heap.hh> - +#include <stack> /* TO-DO list: - handling adjacency on the fly (instead of having an image) - */ +*/ namespace mln @@ -109,23 +109,23 @@ namespace mln typedef mln_element(Q) E; while (! q.is_empty()) - { - E e = q.pop_front(); - - L l1 = wst(p1_from_e(e)), - l2 = wst(p2_from_e(e)); - mln_invariant(l1 != l2); - L l1r = find_root_l(lpar, l1), - l2r = find_root_l(lpar, l2); - - mln_invariant(l1r == lr || l2r == lr); - - if (l1r == l2r) - // 'e' is an internal edge => forget it. - continue; + { + E e = q.pop_front(); - return e; - } + L l1 = wst(p1_from_e(e)), + l2 = wst(p2_from_e(e)); + mln_invariant(l1 != l2); + L l1r = find_root_l(lpar, l1), + l2r = find_root_l(lpar, l2); + + mln_invariant(l1r == lr || l2r == lr); + + if (l1r == l2r) + // 'e' is an internal edge => forget it. + continue; + + return e; + } mln_invariant(0); // We should not be here! @@ -133,160 +133,168 @@ namespace mln } - // Compute an LCA; reference(?) code. - - template <typename L, typename E, typename Epar> - std::vector< std::vector<E> > - compute_lca(const L& l_max, - const std::vector<E>& edge, - const Epar& epar) + /// Compute an LCA + /// Reference article: The LCA Problem Revisited, M. A. Bender and M. + /// Farach-Colton, May 2000 + /// + /// See also Topological Watershed, Alexandre Abraham, LRDE CSI report + /// 0821, June 2008 + template <typename L, typename I, typename E> + class lca_t { - std::cout << "LCA computing..."; - std::cout.flush(); - mln_ch_value(Epar, std::vector<L>) chl; // Children (known as array). - initialize(chl, epar); - - unsigned size = l_max.next(); + public: - std::vector< std::vector<E> > lca(size); - for (L l = 1; l <= l_max; ++l) + /// Constructor + lca_t(const L& l_max_, + const I& edge_children, + const std::vector<E>& roots) + { + unsigned l_max = l_max_.next(); + euler_tour_edge_.resize(2 * l_max + 1); + euler_tour_depth_.resize(2 * l_max + 1); + initialize (euler_position_, edge_children); + + // BUILD EULER TOUR + std::stack<E> to_treat; + for (unsigned i = 0; i < roots.size(); ++i) + to_treat.push(roots[i]); + + unsigned euler_edge = 0; + mln_ch_value(I, bool) deja_vu; + initialize(deja_vu, edge_children); + data::fill(deja_vu, false); + + while (!to_treat.empty()) { - lca[l].resize(size); - lca[l][l] = edge[l]; // Diagonal => itself. - } - std::vector<bool> deja_vu(size); + E e = to_treat.top(); + to_treat.pop(); - E e; + euler_tour_edge_[euler_edge] = e; + if (deja_vu(e)) + euler_tour_depth_[euler_edge] = euler_tour_depth_[euler_edge - 1] - 1; + else + euler_tour_depth_[euler_edge] = euler_tour_depth_[euler_edge - 1] + 1; - // The 1st label (l = 1) is a special case since - // we cannot have lca[1][i] with i < 1! - { - e = edge[1]; - do + if (!deja_vu(e)) { - chl(e).push_back(1); - e = epar(e); + for (int j = edge_children(e).size() - 1; j >= 0; --j) + { + to_treat.push(e); + to_treat.push(edge_children(e)[j]); + } + deja_vu(e) = true; + euler_position_(e) = euler_edge; } - while (e != epar(e)); - chl(e).push_back(1); - } + ++euler_edge; + } - for (L l = 2; l <= l_max; ++l) - { - std::fill(deja_vu.begin(), deja_vu.end(), false); - e = edge[l]; - for (;;) - { - std::vector<L>& chl_e = chl(e); - unsigned n = chl_e.size(); + // BUILD MINIMAS + int size = 2 * l_max - 1; + int logn = (int)(ceil(log((double)(size))/log(2.0))); - // Compute lca[l_][l] with l_ = 1..l-1 - for (unsigned i = 0; i < n; ++i) - { - if (deja_vu[chl_e[i]]) - continue; - L l_ = chl_e[i]; - mln_invariant(l_ < l); - lca[l_][l] = e; - deja_vu[l_] = true; - } + minim_ = new int [logn * size]; // FIXME : Think about freeing this + Minim_ = new int* [logn]; - // Update 'chl' with l; - chl(e).push_back(l); + Minim_[0] = minim_; + + // Init + for (unsigned i = 0; i < size - 1; ++i) + if (euler_tour_depth_[i] < euler_tour_depth_[i+1]) + { + Minim_[0][i] = i; + } else { + Minim_[0][i] = i+1; + } - if (e == epar(e)) // Root so stop. - break; - e = epar(e); // Otherwise go to parent. + int k; + for (int j = 1; j < logn; j++) + { + k = 1 << (j - 1); + Minim_[j] = &minim_[j * size]; + for (int i = 0; i < size; i++) + { + if ((i + (k << 1)) < size) + { + if (euler_tour_depth_[Minim_[j - 1][i]] <= euler_tour_depth_[Minim_[j - 1][i + k]]) + Minim_[j][i] = Minim_[j - 1][i]; + else + Minim_[j][i] = Minim_[j - 1][i + k]; } + } } + } - // e is the root node; we have processed all labels - // so they are stored as the children of e: - mln_invariant(chl(e).size() == l_max); // All labels are children. - - -// // Save the LCA into a file. -// { -// std::ofstream out("lca.txt"); - -// for (L l = 1; l <= l_max; ++l) -// { -// out << "l = " << l << ": "; -// for (L l2 = l; l2 <= l_max; ++l2) -// { -// out << lca[l][l2] << ' '; -// } -// out << std::endl; -// } -// out.close(); + /// Destructor + ~lca_t() + { + delete[] Minim_; + delete[] minim_; + } -// // Display children tree. -// { -// std::cout << "chl tree: " << std::endl; -// for (L l = 1; l <= l_max; ++l) -// { -// E e_ = edge[l]; -// std::cout << "l = " << l << " => "; -// do -// { -// std::cout << e_ << " : "; -// for (unsigned i = 0; i < chl(e_).size(); ++i) -// std::cout << chl(e_)[i] << ' '; -// std::cout << " -> "; -// e_ = epar(e_); -// } -// while (epar(e_) != e_); -// std::cout << e_ << " : "; -// for (unsigned i = 0; i < chl(e_).size(); ++i) -// std::cout << chl(e_)[i] << ' '; -// std::cout << std::endl; -// } -// } + const E& operator() (const E& a, const E& b) + { + if (a == b) + return a; + int m = euler_position_(a), + n = euler_position_(b), + k; - std::cout << "done!" << std::endl; + if (m > n) + std::swap(m, n); - return lca; - } + k = (int)(log((double)(n - m))/log(2.)); + if (euler_tour_depth_[Minim_[k][m]] + < euler_tour_depth_[Minim_[k][n - (1 << k)]]) + return euler_tour_edge_[Minim_[k][m]]; + else + return euler_tour_edge_[Minim_[k][n - (1 << k)]]; + } + private: + int *minim_; + int **Minim_; + std::vector<E> euler_tour_edge_; + std::vector<unsigned> euler_tour_depth_; + mln_ch_value(I, unsigned) euler_position_; + }; + // Transform attributes so that they are all different! - // Transform attributes so that they are all different! - template <typename A, typename L> void make_unique_attribute(util::array<A>& a, - std::vector< std::pair<A,L> >& v, - L l_max, - bool echo) + std::vector< std::pair<A,L> >& v, + L l_max, + bool echo) { // Display attributes. if (echo) - { - std::cout << "(attribute, label) = { "; - for (unsigned i = 1; i <= l_max; ++i) - std::cout << '(' << v[i].first // Attribute (increasing). - << ',' - << v[i].second // Region label. - << ") "; - std::cout << '}' << std::endl - << std::endl; - } + { + std::cout << "(attribute, label) = { "; + for (unsigned i = 1; i <= l_max; ++i) + std::cout << '(' << v[i].first // Attribute (increasing). + << ',' + << v[i].second // Region label. + << ") "; + std::cout << '}' << std::endl + << std::endl; + } std::map<A,A> lut; // old value -> new value for (unsigned l = 1; l <= l_max; ++l) - { - A old_a = v[l].first, - new_a = old_a + l - 1; - lut[old_a] = new_a; - v[l].first = new_a; // new value - } + { + A old_a = v[l].first, + new_a = old_a + l - 1; + lut[old_a] = new_a; + v[l].first = new_a; // new value + } for (unsigned l = 1; l <= l_max; ++l) a[l] = lut[ a[l] ]; } @@ -967,9 +975,7 @@ int main(int argc, char* argv[]) { // First, processing the 1D-faces (edges) of the watershed line. - std::vector< std::vector<E> > lca; - - lca = compute_lca(n_basins, edge, epar); // lca is auxiliary data. + lca_t<L,chl_t,E> lca(n_basins, chl, roots); mln_piter_(g_line_t) e(g_line.domain()); for_all(e) @@ -977,7 +983,7 @@ int main(int argc, char* argv[]) L l1 = adj_line(e).first(), l2 = adj_line(e).second(); mln_invariant(l1 != 0 && l2 > l1); - E e_ = lca[l1][l2]; + E e_ = lca(edge[l1],edge[l2]); mln_invariant(is_line(e_)); mln_invariant(aa(e_) != 0); // aa is valid at e_. -- 1.5.6.5
15 years, 11 months
1
0
0
0
3180: Handle rgb and hsl conversions in from_to and remove to_rgb.
by Guillaume Lazzara
* headers.mk: remove to_rgb.hh from distribution. * mln/convert/all.hh: remove to_rgb.hh. * mln/convert/from_to.hxx: add more predeclarations. * mln/convert/impl/from_value_to_value.hh: if no value concept is caught in the dispatch, try to call a from_to_ overload. * mln/fun/v2v/rgb_to_hsl.hh: add new global variables of function converting rgb16 to hsl. * mln/value/hsl.hh, * mln/value/rgb.hh: add new from_to_ overloads. * tests/convert/Makefile.am, * tests/convert/to_hsl.cc, * tests/convert/to_rgb.cc: new tests. Test conversions with rgb<n> and hsl<h,s,l> using from_to. * mln/convert/to_rgb.hh: remove. Useless since conversions are now done thanks to from_to. * tests/unit_test/Makefile.am, * tests/unit_test/mln_convert_to_rgb.cc: remove unit_test related to to_rgb.hh. * mln/fun/v2v/rgb_to_hsl.hh: do not include hsl.hh anymore. --- milena/ChangeLog | 33 ++++ milena/headers.mk | 1 - milena/mln/convert/all.hh | 5 +- milena/mln/convert/from_to.hxx | 25 +++ milena/mln/convert/impl/from_value_to_value.hh | 27 ++- milena/mln/fun/v2v/rgb_to_hsl.hh | 15 +- milena/mln/value/hsl.hh | 195 +++++++++++++++++--- milena/mln/value/rgb.hh | 67 +++++++- milena/tests/convert/Makefile.am | 4 + .../convert/to_rgb.hh => tests/convert/to_hsl.cc} | 75 ++------ .../convert/all.hh => tests/convert/to_rgb.cc} | 43 ++--- milena/tests/unit_test/Makefile.am | 2 - milena/tests/unit_test/mln_convert_to_rgb.cc | 11 - 13 files changed, 364 insertions(+), 139 deletions(-) rename milena/{mln/convert/to_rgb.hh => tests/convert/to_hsl.cc} (54%) copy milena/{mln/convert/all.hh => tests/convert/to_rgb.cc} (68%) delete mode 100644 milena/tests/unit_test/mln_convert_to_rgb.cc diff --git a/milena/ChangeLog b/milena/ChangeLog index 3da59ee..6e30fb1 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,36 @@ +2009-01-20 Guillaume Lazzara <z(a)lrde.epita.fr> + + Handle rgb and hsl conversions in from_to and remove to_rgb. + + * headers.mk: remove to_rgb.hh from distribution. + + * mln/convert/all.hh: remove to_rgb.hh. + + * mln/convert/from_to.hxx: add more predeclarations. + + * mln/convert/impl/from_value_to_value.hh: if no value concept is + caught in the dispatch, try to call a from_to_ overload. + + * mln/fun/v2v/rgb_to_hsl.hh: add new global variables of function + converting rgb16 to hsl. + + * mln/value/hsl.hh, + * mln/value/rgb.hh: add new from_to_ overloads. + + * tests/convert/Makefile.am, + * tests/convert/to_hsl.cc, + * tests/convert/to_rgb.cc: new tests. Test conversions with rgb<n> and + hsl<h,s,l> using from_to. + + * mln/convert/to_rgb.hh: remove. Useless since conversions are now done + thanks to from_to. + + * tests/unit_test/Makefile.am, + * tests/unit_test/mln_convert_to_rgb.cc: remove unit_test related to + to_rgb.hh. + + * mln/fun/v2v/rgb_to_hsl.hh: do not include hsl.hh anymore. + 2009-01-21 Nicolas Ballas <ballas(a)lrde.epita.fr> Externalize element and nelement method in fastest images. diff --git a/milena/headers.mk b/milena/headers.mk index 04c0a73..5babdd4 100644 --- a/milena/headers.mk +++ b/milena/headers.mk @@ -271,7 +271,6 @@ mln/convert/impl/from_int_to_value.hh \ mln/convert/to_dpoint.hh \ mln/convert/to_p_array.hh \ mln/convert/from_to.hxx \ -mln/convert/to_rgb.hh \ mln/convert/essential.hh \ mln/value/shell.hh \ mln/value/float01_f.hh \ diff --git a/milena/mln/convert/all.hh b/milena/mln/convert/all.hh index 0fab453..0336039 100644 --- a/milena/mln/convert/all.hh +++ b/milena/mln/convert/all.hh @@ -1,5 +1,5 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory -// (LRDE) +// Copyright (C) 2007, 2008, 2009 EPITA Research and Development +// Laboratory (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -49,7 +49,6 @@ namespace mln # include <mln/convert/to_dpoint.hh> # include <mln/convert/to_fun.hh> # include <mln/convert/to_image.hh> -# include <mln/convert/to_rgb.hh> # include <mln/convert/to_p_array.hh> # include <mln/convert/to_window.hh> diff --git a/milena/mln/convert/from_to.hxx b/milena/mln/convert/from_to.hxx index e2cbe3d..404a22f 100644 --- a/milena/mln/convert/from_to.hxx +++ b/milena/mln/convert/from_to.hxx @@ -82,6 +82,8 @@ namespace mln namespace value { template <unsigned n> struct rgb; + template <typename H, typename S, typename L> class hsl_; + template <unsigned n> struct int_u; } // end of Forward declarations. @@ -149,6 +151,29 @@ namespace mln void from_to_(bool from, value::rgb<m>& to); + // int_u -> rgb. + template <unsigned m> + void from_to_(const value::int_u<m>& from, value::rgb<m>& to); + + // hsl -> rgb8. + template <typename H, typename S, typename L> + void from_to_(const value::hsl_<H,S,L>&, value::rgb<8>& to); + + // hsl -> rgb16. + template <typename H, typename S, typename L> + void from_to_(const value::hsl_<H,S,L>&, value::rgb<16>& to); + + + // rgb to hsl + template <typename H, typename S, typename L> + void + from_to_(const value::rgb<16>& from, value::hsl_<H,S,L>& to); + + // rgb to hsl + template <typename H, typename S, typename L> + void + from_to_(const value::rgb<8>& from, value::hsl_<H,S,L>& to); + // C-array -> Image. template <typename V, unsigned S, typename I> diff --git a/milena/mln/convert/impl/from_value_to_value.hh b/milena/mln/convert/impl/from_value_to_value.hh index 5879b7a..f5d69fd 100644 --- a/milena/mln/convert/impl/from_value_to_value.hh +++ b/milena/mln/convert/impl/from_value_to_value.hh @@ -1,4 +1,5 @@ -// Copyright (C) 2008 EPITA Research and Development Laboratory +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory +// (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -28,12 +29,12 @@ #ifndef MLN_CONVERT_IMPL_FROM_VALUE_TO_VALUE_HH # define MLN_CONVERT_IMPL_FROM_VALUE_TO_VALUE_HH -/*! \file mln/convert/from_to.hh - * - * \brief General conversion procedure from a value to a value. - * - * \todo Augment code + add checks. - */ +/// \file mln/convert/from_to.hh +/// +/// General conversion procedure from a value to a value. +/// +/// \todo Augment code + add checks. + # include <utility> # include <mln/core/concept/image.hh> @@ -43,7 +44,7 @@ # include <mln/core/site_set/p_run.hh> # include <mln/metal/converts_to.hh> - +# include <mln/convert/from_to.hxx> namespace mln { @@ -88,6 +89,16 @@ namespace mln exact(to) = exact(from).to_equiv(); } + template <typename V, typename W> + inline + void + from_value_to_value_(const Value<V>& from, Value<W>& to) + { + // No concept based conversion. Trying to find more specific + // conversion with other from_to overloads. + convert::over_load::from_to_(exact(from), exact(to)); + } + // Facades. diff --git a/milena/mln/fun/v2v/rgb_to_hsl.hh b/milena/mln/fun/v2v/rgb_to_hsl.hh index a205544..3bfe060 100644 --- a/milena/mln/fun/v2v/rgb_to_hsl.hh +++ b/milena/mln/fun/v2v/rgb_to_hsl.hh @@ -30,17 +30,21 @@ #include <cmath> -#include <mln/value/rgb8.hh> #include <mln/math/round.hh> #include <mln/math/max.hh> #include <mln/math/min.hh> -#include <mln/value/hsl.hh> - namespace mln { + // Forward declaration + namespace value + { + template <unsigned n> struct rgb; + template <typename H, typename S, typename L> class hsl_; + typedef hsl_<float, float, float> hsl_f; + } namespace fun { @@ -73,9 +77,11 @@ namespace mln }; - typedef f_hsl_to_rgb_<value::rgb8> f_hsl_to_rgb_3x8_t; + typedef f_hsl_to_rgb_< value::rgb<8> > f_hsl_to_rgb_3x8_t; + typedef f_hsl_to_rgb_< value::rgb<16> > f_hsl_to_rgb_3x16_t; extern f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8; + extern f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16; # ifndef MLN_INCLUDE_ONLY @@ -85,6 +91,7 @@ namespace mln f_rgb_to_hsl_f_t f_rgb_to_hsl_f; f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8; + f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16; /// \} diff --git a/milena/mln/value/hsl.hh b/milena/mln/value/hsl.hh index 0a48c53..0ac4087 100644 --- a/milena/mln/value/hsl.hh +++ b/milena/mln/value/hsl.hh @@ -25,6 +25,15 @@ // reasons why the executable file might be covered by the GNU General // Public License. +/// \file mln/value/hsl.hh +/// +/// Color class. +/// +/// \todo write a better doc. + +#ifndef MLN_VALUE_HSL_HH +# define MLN_VALUE_HSL_HH + #include <mln/value/ops.hh> #include <mln/value/concept/vectorial.hh> @@ -33,13 +42,45 @@ #include <mln/value/float01_8.hh> -#ifndef MLN_VALUE_HSL_HH -# define MLN_VALUE_HSL_HH +// Used in from_to +#include <mln/fun/v2v/rgb_to_hsl.hh> namespace mln { + // Forward declarations. + namespace value + { + + template <typename H, typename S, typename L> + class hsl_; + + } + + + + namespace convert + { + + namespace over_load + { + + // rgb to hsl + template <typename H, typename S, typename L> + void + from_to_(const value::rgb<16>& from, value::hsl_<H,S,L>& to); + + // rgb to hsl + template <typename H, typename S, typename L> + void + from_to_(const value::rgb<8>& from, value::hsl_<H,S,L>& to); + + } // end of namespace mln::convert::over_load + + } // end of namespace mln::convert + + namespace value { @@ -71,32 +112,14 @@ namespace mln } /// Read-only access to the hue component. - const H& hue() const - { - return this->hue_; - } - const S& sat() const - { - return this->sat_; - } - const L& lum() const - { - return this->lum_; - } + const H& hue() const; + const S& sat() const; + const L& lum() const; /// Read-write access to the hue component. - H& hue() - { - return this->hue_; - } - S& sat() - { - return this->sat_; - } - L& lum() - { - return this->lum_; - } + H& hue(); + S& sat(); + L& lum(); private: H hue_; @@ -108,8 +131,128 @@ namespace mln typedef hsl_<double, double, double> hsl_d; + + /// Print an hsl \p c into the output stream \p ostr. + /// + /// \param[in,out] ostr An output stream. + /// \param[in] c An rgb. + /// + /// \return The modified output stream \p ostr. + template <typename H, typename S, typename L> + std::ostream& operator<<(std::ostream& ostr, const hsl_<H,S,L>& c); + + } // end of namespace mln::value + + + + // More forward declarations + namespace fun + { + namespace v2v + { + + template <typename T_hsl> + struct f_rgb_to_hsl_; + + typedef f_rgb_to_hsl_<value::hsl_f> f_rgb_to_hsl_f_t; + + extern f_rgb_to_hsl_f_t f_rgb_to_hsl_f; + + } + + } + +# ifndef MLN_INCLUDE_ONLY + + + namespace value + { + + template <typename H, typename S, typename L> + const H& + hsl_<H,S,L>::hue() const + { + return this->hue_; + } + + template <typename H, typename S, typename L> + const S& + hsl_<H,S,L>::sat() const + { + return this->sat_; + } + + template <typename H, typename S, typename L> + const L& + hsl_<H,S,L>::lum() const + { + return this->lum_; + } + + template <typename H, typename S, typename L> + H& + hsl_<H,S,L>::hue() + { + return this->hue_; + } + + template <typename H, typename S, typename L> + S& + hsl_<H,S,L>::sat() + { + return this->sat_; + } + + template <typename H, typename S, typename L> + L& + hsl_<H,S,L>::lum() + { + return this->lum_; + } + + + template <typename H, typename S, typename L> + inline + std::ostream& operator<<(std::ostream& ostr, const hsl_<H,S,L>& v) + { + return ostr << '(' << debug::format(v.hue()) + << ',' << debug::format(v.sat()) + << ',' << debug::format(v.lum()) + << ')'; + } + } // end of namespace mln::value + + namespace convert + { + + namespace over_load + { + + template <typename H, typename S, typename L> + void + from_to_(const value::rgb<16>& from, value::hsl_<H,S,L>& to) + { + to = fun::v2v::f_rgb_to_hsl_f(from); + } + + + template <typename H, typename S, typename L> + void + from_to_(const value::rgb<8>& from, value::hsl_<H,S,L>& to) + { + to = fun::v2v::f_rgb_to_hsl_f(from); + } + + } // end of namespace mln::convert::over_load + + } // end of namespace mln::convert + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln #endif // ! MLN_VALUE_HSL_HH diff --git a/milena/mln/value/rgb.hh b/milena/mln/value/rgb.hh index 452031d..6b2a479 100644 --- a/milena/mln/value/rgb.hh +++ b/milena/mln/value/rgb.hh @@ -25,9 +25,6 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_VALUE_RGB_HH -# define MLN_VALUE_RGB_HH - /// \file mln/value/rgb.hh /// /// Color class for red-green-blue where every component is @@ -38,16 +35,42 @@ /// \todo Introduce the concept of Color, then generalize from_to_ to /// colors. +#ifndef MLN_VALUE_RGB_HH +# define MLN_VALUE_RGB_HH + + # include <mln/value/ops.hh> # include <mln/value/concept/vectorial.hh> # include <mln/value/int_u.hh> # include <mln/algebra/vec.hh> +// Needed by from_to_. +# include <mln/fun/v2v/rgb_to_hsl.hh> namespace mln { + namespace fun + { + + namespace v2v + { + + template <typename T_rgb> + struct f_hsl_to_rgb_; + + typedef f_hsl_to_rgb_< value::rgb<8> > f_hsl_to_rgb_3x8_t; + typedef f_hsl_to_rgb_< value::rgb<16> > f_hsl_to_rgb_3x16_t; + + extern f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8; + extern f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16; + + } + + } + + namespace literal { /// \{ Forward declarations. @@ -77,8 +100,11 @@ namespace mln // Forward declaration. - namespace value { + namespace value + { template <unsigned n> struct rgb; + template <typename H, typename S, typename L> class hsl_; + template <unsigned n> struct int_u; } @@ -96,6 +122,18 @@ namespace mln template <unsigned m> void from_to_(bool from, value::rgb<m>& to); + // int_u -> rgb. + template <unsigned m> + void from_to_(const value::int_u<m>& from, value::rgb<m>& to); + + // hsl -> rgb8. + template <typename H, typename S, typename L> + void from_to_(const value::hsl_<H,S,L>&, value::rgb<8>& to); + + // hsl -> rgb16. + template <typename H, typename S, typename L> + void from_to_(const value::hsl_<H,S,L>&, value::rgb<16>& to); + } // end of namespace mln::convert::over_load } // end of namespace mln::convert @@ -711,6 +749,27 @@ namespace mln to = *black_; } + template <unsigned m> + void + from_to_(const value::int_u<m>& from, value::rgb<m>& to) + { + to = value::rgb<m>(from, from, from); + } + + template <typename H, typename S, typename L> + void + from_to_(const value::hsl_<H,S,L>& from, value::rgb<8>& to) + { + to = fun::v2v::f_hsl_to_rgb_3x8(from); + } + + template <typename H, typename S, typename L> + void + from_to_(const value::hsl_<H,S,L>& from, value::rgb<16>& to) + { + to = fun::v2v::f_hsl_to_rgb_3x16(from); + } + } // end of namespace mln::convert::over_load } // end of namespace mln::convert diff --git a/milena/tests/convert/Makefile.am b/milena/tests/convert/Makefile.am index 975305b..bceaf38 100644 --- a/milena/tests/convert/Makefile.am +++ b/milena/tests/convert/Makefile.am @@ -4,14 +4,18 @@ include $(top_srcdir)/milena/tests/tests.mk ##FIXME: re-enable all tests check_PROGRAMS = \ + to_hsl \ to_image \ to_p_array \ to_p_set \ + to_rgb \ to_window +to_hsl_SOURCES = to_hsl.cc to_image_SOURCES = to_image.cc to_p_array_SOURCES = to_p_array.cc to_p_set_SOURCES = to_p_set.cc +to_rgb_SOURCES = to_rgb.cc to_window_SOURCES = to_window.cc TESTS = $(check_PROGRAMS) diff --git a/milena/mln/convert/to_rgb.hh b/milena/tests/convert/to_hsl.cc similarity index 54% rename from milena/mln/convert/to_rgb.hh rename to milena/tests/convert/to_hsl.cc index af396a3..3f24faa 100644 --- a/milena/mln/convert/to_rgb.hh +++ b/milena/tests/convert/to_hsl.cc @@ -1,4 +1,5 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2009 EPITA Research and Development Laboratory +// (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -25,66 +26,26 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_CONVERT_TO_RGB_HH -# define MLN_CONVERT_TO_RGB_HH +/// \file tests/convert/to_hsl.cc +/// +/// Tests on mln::convert::from_to_ for hsl<H,S,L>. -/*! \file mln/convert/to_rgb.hh - * - * \brief Conversions to mln::value::rgb. - * - * \todo Re-write. - */ +#include <mln/core/image/image2d.hh> +#include <mln/value/hsl.hh> +#include <mln/value/rgb8.hh> +#include <mln/convert/to.hh> -# include <mln/value/rgb.hh> -namespace mln +int main() { + using namespace mln; - namespace convert - { + value::rgb8 c1(3,3,3); + value::hsl_f c2 = convert::to<value::hsl_f>(c1); +// mln_assertion(c2 == hsl_f(0,0,3)); //FIXME: wrong result. - using namespace value; + value::hsl_f c3(3,3,3); + c1 = convert::to<value::rgb8>(c3); +// mln_assertion(c1 == rgb8(2,4,0)); //FIXME: wrong result. - /// Convert a int_u \p val into rgb value. - template <unsigned int n> - rgb<n> to_rgb(const int_u<n>& i); - - template <unsigned int n> - rgb<n>& to_rgb(rgb<n>& i); - - template <unsigned int n> - const rgb<n>& to_rgb(const rgb<n>& i); - - -# ifndef MLN_INCLUDE_ONLY - - template <unsigned int n> - inline - rgb<n> to_rgb(const int_u<n>& i) - { - rgb<n> c(i, i, i); - return c; - } - - template <unsigned int n> - inline - rgb<n>& to_rgb(rgb<n>& i) - { - return i; - } - - template <unsigned int n> - inline - const rgb<n>& to_rgb(const rgb<n>& i) - { - return i; - } - -# endif // ! MLN_INCLUDE_ONLY - - } // end of namespace mln::convert - -} // end of namespace mln - - -#endif // ! MLN_CONVERT_TO_WINDOW_HH +} diff --git a/milena/mln/convert/all.hh b/milena/tests/convert/to_rgb.cc similarity index 68% copy from milena/mln/convert/all.hh copy to milena/tests/convert/to_rgb.cc index 0fab453..24c7508 100644 --- a/milena/mln/convert/all.hh +++ b/milena/tests/convert/to_rgb.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// Copyright (C) 2009 EPITA Research and Development Laboratory // (LRDE) // // This file is part of the Olena Library. This library is free @@ -26,32 +26,29 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_CONVERT_ALL_HH -# define MLN_CONVERT_ALL_HH - -/// \file mln/convert/all.hh +/// \file tests/convert/to_rgb.cc /// -/// File that includes all conversion-related routines. - - -namespace mln -{ +/// Tests on mln::convert::from_to_ for rgb<n>. - /// Namespace of conversion routines. - namespace convert {} - -} +#include <mln/core/image/image2d.hh> +#include <mln/value/int_u8.hh> +#include <mln/value/rgb8.hh> +#include <mln/convert/to.hh> -# include <mln/convert/from_to.hh> -# include <mln/convert/to.hh> +int main() +{ + using namespace mln; -# include <mln/convert/to_dpoint.hh> -# include <mln/convert/to_fun.hh> -# include <mln/convert/to_image.hh> -# include <mln/convert/to_rgb.hh> -# include <mln/convert/to_p_array.hh> -# include <mln/convert/to_window.hh> + value::rgb8 c1(3,3,3); + value::rgb8 c2 = convert::to<value::rgb8>(c1); + mln_assertion(c1 == c2); + const value::rgb8 c3(3,3,3); + c2 = convert::to<value::rgb8>(c3); + mln_assertion(c2 == c3); -#endif // ! MLN_CONVERT_ALL_HH + value::int_u8 i = 3; + c2 = convert::to<value::rgb8>(i); + mln_assertion(c2 == value::rgb8(3,3,3)); +} diff --git a/milena/tests/unit_test/Makefile.am b/milena/tests/unit_test/Makefile.am index f7886cd..9398c88 100644 --- a/milena/tests/unit_test/Makefile.am +++ b/milena/tests/unit_test/Makefile.am @@ -267,7 +267,6 @@ mln_convert_impl_from_float_to_value \ mln_convert_impl_from_int_to_value \ mln_convert_to_dpoint \ mln_convert_to_p_array \ -mln_convert_to_rgb \ mln_convert_essential \ mln_value_shell \ mln_value_float01_f \ @@ -1283,7 +1282,6 @@ mln_convert_impl_from_float_to_value_SOURCES = mln_convert_impl_from_float_to_va mln_convert_impl_from_int_to_value_SOURCES = mln_convert_impl_from_int_to_value.cc mln_convert_to_dpoint_SOURCES = mln_convert_to_dpoint.cc mln_convert_to_p_array_SOURCES = mln_convert_to_p_array.cc -mln_convert_to_rgb_SOURCES = mln_convert_to_rgb.cc mln_convert_essential_SOURCES = mln_convert_essential.cc mln_value_shell_SOURCES = mln_value_shell.cc mln_value_float01_f_SOURCES = mln_value_float01_f.cc diff --git a/milena/tests/unit_test/mln_convert_to_rgb.cc b/milena/tests/unit_test/mln_convert_to_rgb.cc deleted file mode 100644 index d98e87a..0000000 --- a/milena/tests/unit_test/mln_convert_to_rgb.cc +++ /dev/null @@ -1,11 +0,0 @@ -// Unit test for mln/convert/to_rgb.hh. -// Generated by ./build_unit_test.sh, do not modify. - -// Include the file twice, so we detect missing inclusion guards. -#include <mln/convert/to_rgb.hh> -#include <mln/convert/to_rgb.hh> - -int main() -{ - // Nothing. -} -- 1.5.6.5
15 years, 11 months
1
0
0
0
3179: Externalize element and nelement method in fastest images.
by Nicolas Ballas
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog from Nicolas Ballas <ballas(a)lrde.epita.fr> Externalize element and nelement method in fastest images. * mln/opt/element.hh: New, define opt::element and opt::nelements. * mln/debug/println_with_border.spe.hh, * mln/debug/println_with_border.hh, * mln/data/paste.spe.hh, * mln/data/fill_with_value.spe.hh, * mln/data/fill_with_image.spe.hh, * mln/data/memcpy_.hh, * mln/data/memset_.hh, * mln/border/fill.hh, * mln/border/duplicate.hh, * mln/border/mirror.hh, * tests/opt/value.cc, * tests/border/duplicate_full.cc, * tests/border/mirror_full.cc, * tests/border/fill_full.cc, * tests/border/duplicate.cc, * tests/border/mirror.cc, * tests/border/fill.cc: Use now opt::element and opt::nelements. * mln/opt/value.hh: Update Copyright. * tests/opt/element.cc: New tests. mln/border/duplicate.hh | 29 +++--- mln/border/fill.hh | 13 +- mln/border/mirror.hh | 33 ++++--- mln/data/fill_with_image.spe.hh | 3 mln/data/fill_with_value.spe.hh | 3 mln/data/memcpy_.hh | 26 ++--- mln/data/memset_.hh | 10 +- mln/data/paste.spe.hh | 3 mln/debug/println_with_border.hh | 3 mln/debug/println_with_border.spe.hh | 3 mln/opt/element.hh | 165 +++++++++++++++++++++++++++++++++++ mln/opt/value.hh | 2 tests/border/duplicate.cc | 51 +++++----- tests/border/duplicate_full.cc | 5 - tests/border/fill.cc | 5 - tests/border/fill_full.cc | 25 ++--- tests/border/mirror.cc | 101 ++++++++++----------- tests/border/mirror_full.cc | 5 - tests/opt/element.cc | 47 +++++++++ tests/opt/value.cc | 4 20 files changed, 390 insertions(+), 146 deletions(-) Index: mln/debug/println_with_border.spe.hh --- mln/debug/println_with_border.spe.hh (revision 3178) +++ mln/debug/println_with_border.spe.hh (working copy) @@ -40,6 +40,7 @@ # include <mln/core/concept/image.hh> # include <mln/core/concept/window.hh> # include <mln/debug/format.hh> +# include <mln/opt/element.hh> namespace mln { @@ -61,7 +62,7 @@ println_with_border(const box2d& b, const I& input) { const unsigned ncols = b.ncols() + 2 * input.border(); - for (size_t i = 0; i < input.nelements(); i++) + for (size_t i = 0; i < opt::nelements(input); i++) { std::cout << format(input.buffer()[i]) << ' '; if (((i + 1) % ncols) == 0) Index: mln/debug/println_with_border.hh --- mln/debug/println_with_border.hh (revision 3178) +++ mln/debug/println_with_border.hh (working copy) @@ -43,6 +43,7 @@ # include <mln/debug/format.hh> // Specializations are in: # include <mln/debug/println_with_border.spe.hh> +# include <mln/opt/element.hh> namespace mln { @@ -66,7 +67,7 @@ void println_with_border(const S&, const I& input) { - for (size_t i = 0; i < input.nelements(); i++) + for (size_t i = 0; i < opt::nelements(input); i++) std::cout << format(input.buffer()[i]) << ' '; std::cout << std::endl; } Index: mln/opt/element.hh --- mln/opt/element.hh (revision 0) +++ mln/opt/element.hh (revision 0) @@ -0,0 +1,165 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// 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_OPT_ELEMENT_HH +# define MLN_OPT_ELEMENT_HH + +/// \file mln/opt/element.hh +/// +/// Define the opt::element and opt::nelements routines. + +# include <mln/core/concept/image.hh> +# include <mln/trait/images.hh> + +namespace mln +{ + + namespace opt + { + + template <typename I> + inline + mln_rvalue(I) element(const Image<I>& ima, unsigned index); + + template <typename I> + inline + mln_lvalue(I) element(Image<I>& ima, unsigned index); + + template <typename I> + inline + unsigned nelements(const Image<I>& ima); + + +# ifndef MLN_INCLUDE_ONLY + + namespace impl + { + + template <typename I> + inline + mln_rvalue(I) element_impl(trait::image::category::domain_morpher, + const Image<I>& ima, unsigned index) + { + return element(*exact(ima).delegatee_()); + } + + template <typename I> + inline + mln_rvalue(I) element_impl(trait::image::category::any, + const Image<I>& ima, unsigned index) + { + mlc_and(mlc_is(mln_trait_image_value_storage(I), + trait::image::value_storage::one_block), + mlc_is(mln_trait_image_value_access(I), + trait::image::value_access::direct))::check(); + + return exact(ima).element(index); + } + + + template <typename I> + inline + mln_lvalue(I) element_impl(trait::image::category::domain_morpher, + Image<I>& ima, unsigned index) + { + return element(*exact(ima).delegatee_()); + } + + template <typename I> + inline + mln_lvalue(I) element_impl(trait::image::category::any, + Image<I>& ima, unsigned index) + { + mlc_and(mlc_is(mln_trait_image_value_storage(I), + trait::image::value_storage::one_block), + mlc_is(mln_trait_image_value_access(I), + trait::image::value_access::direct))::check(); + + return exact(ima).element(index); + } + + + + + template <typename I> + inline + unsigned nelements_impl(trait::image::category::domain_morpher, + const Image<I>& ima) + { + return nelements(*exact(ima).delegatee_()); + } + + template <typename I> + inline + unsigned nelements_impl(trait::image::category::any, + const Image<I>& ima) + { + mlc_is(mln_trait_image_value_storage(I), + trait::image::value_storage::one_block)::check(); + + return exact(ima).nelements(); + } + + + + + + + } // end of namespace mln::opt::impl + + + template <typename I> + inline + mln_rvalue(I) element(const Image<I>& ima, unsigned index) + { + return impl::element_impl(mln_trait_image_category(I)(), ima, index); + } + + template <typename I> + inline + mln_lvalue(I) element(Image<I>& ima, unsigned index) + { + return impl::element_impl(mln_trait_image_category(I)(), ima, index); + } + + + template <typename I> + inline + unsigned nelements(const Image<I>& ima) + { + return impl::nelements_impl(mln_trait_image_category(I)(), ima); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::opt + +} // end of namespace mln + + +#endif // ! MLN_OPT_VALUE_HH Index: mln/opt/value.hh --- mln/opt/value.hh (revision 3178) +++ mln/opt/value.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2008 EPITA Research and Development Laboratory +// Copyright (C) 2009 EPITA Research and Development Laboratory // (LRDE) // // This file is part of the Olena Library. This library is free Index: mln/data/paste.spe.hh --- mln/data/paste.spe.hh (revision 3178) +++ mln/data/paste.spe.hh (working copy) @@ -43,6 +43,7 @@ # include <mln/core/box_runstart_piter.hh> # include <mln/border/get.hh> # include <mln/opt/value.hh> +# include <mln/opt/element.hh> @@ -111,7 +112,7 @@ *(src.address_()) = input.buffer(); *(dst.address_()) = output.buffer(); - memcpy_(dst, src, input.nelements()); + memcpy_(dst, src, opt::nelements(input)); trace::exiting("data::impl::paste_fastest"); } Index: mln/data/fill_with_value.spe.hh --- mln/data/fill_with_value.spe.hh (revision 3178) +++ mln/data/fill_with_value.spe.hh (working copy) @@ -38,6 +38,7 @@ # include <mln/data/memset_.hh> # include <mln/opt/value.hh> +# include <mln/opt/element.hh> # ifndef MLN_INCLUDE_ONLY @@ -89,7 +90,7 @@ trait::image::value_access::direct))::check(); mln_value(I) v = static_cast<mln_value(I)>(val); - data::memset_(ima, ima.point_at_index(0), v, ima.nelements()); + data::memset_(ima, ima.point_at_index(0), v, opt::nelements(ima)); trace::exiting("data::impl::fill_with_value_one_block"); } Index: mln/data/fill_with_image.spe.hh --- mln/data/fill_with_image.spe.hh (revision 3178) +++ mln/data/fill_with_image.spe.hh (working copy) @@ -44,6 +44,7 @@ # include <mln/core/box_runstart_piter.hh> # include <mln/border/get.hh> # include <mln/opt/value.hh> +# include <mln/opt/element.hh> # ifndef MLN_INCLUDE_ONLY @@ -89,7 +90,7 @@ *(src.address_()) = data.buffer(); *(dst.address_()) = ima.buffer(); - memcpy_(dst, src, ima.nelements()); + memcpy_(dst, src, opt::nelements(ima)); trace::exiting("data::impl::fill_with_image_fastest"); } Index: mln/data/memcpy_.hh --- mln/data/memcpy_.hh (revision 3178) +++ mln/data/memcpy_.hh (working copy) @@ -39,6 +39,8 @@ # include <mln/core/concept/image.hh> # include <mln/core/pixel.hh> # include <mln/metal/is_not_const.hh> +# include <mln/opt/element.hh> + namespace mln @@ -126,18 +128,18 @@ mln_precondition(dest.ima().is_valid()); mln_precondition(src.ima().is_valid()); - mln_precondition(&dest.val() >= &dest.ima().element(0)); - mln_precondition(&dest.val() < &dest.ima().element(0) + - dest.ima().nelements()); - - mln_precondition(&dest.val() + n <= &dest.ima().element(0) + - dest.ima().nelements()); - - mln_precondition(&src.val() >= &src.ima().element(0)); - mln_precondition(&src.val() < &src.ima().element(0) + - src.ima().nelements()); - mln_precondition(&src.val() + n <= &src.ima().element(0) + - src.ima().nelements()); + mln_precondition(&dest.val() >= &opt::element(dest.ima(), 0)); + mln_precondition(&dest.val() < &opt::element(dest.ima(), 0) + + opt::nelements(dest.ima())); + + mln_precondition(&dest.val() + n <= &opt::element(dest.ima(), 0) + + opt::nelements(dest.ima())); + + mln_precondition(&src.val() >= &opt::element(src.ima(), 0)); + mln_precondition(&src.val() < &opt::element(src.ima(), 0) + + opt::nelements(src.ima())); + mln_precondition(&src.val() + n <= &opt::element(src.ima(), 0) + + opt::nelements(src.ima())); impl::memcpy__(dest, src, n); Index: mln/data/memset_.hh --- mln/data/memset_.hh (revision 3178) +++ mln/data/memset_.hh (working copy) @@ -38,6 +38,8 @@ # include <mln/core/concept/image.hh> # include <mln/core/pixel.hh> # include <mln/metal/is_not_const.hh> +# include <mln/opt/element.hh> + namespace mln @@ -132,8 +134,10 @@ P& pix = mln::internal::force_exact<P>(pix_); mln_precondition(pix.ima().is_valid()); mln_precondition(& pix.val() >= & pix.ima()[0]); - mln_precondition(& pix.val() < & pix.ima()[0] + pix.ima().nelements()); - mln_precondition(& pix.val() + n <= & pix.ima()[0] + pix.ima().nelements()); + mln_precondition(& pix.val() < & pix.ima()[0] + + opt::nelements(pix.ima())); + mln_precondition(& pix.val() + n <= & pix.ima()[0] + + opt::nelements(pix.ima())); impl::memset__(pix, v, n); @@ -151,7 +155,7 @@ mln_precondition(input.is_valid()); mln_precondition(input.has(p)); - mln_precondition(input.index_of_point(p) + n <= input.nelements()); + mln_precondition(input.index_of_point(p) + n <= opt::nelements(input)); pixel<I> pix(input, p); impl::memset__(pix, v, n); Index: mln/border/fill.hh --- mln/border/fill.hh (revision 3178) +++ mln/border/fill.hh (working copy) @@ -38,6 +38,7 @@ # include <mln/core/concept/image.hh> # include <mln/core/box_runstart_piter.hh> +# include <mln/opt/element.hh> namespace mln @@ -99,14 +100,14 @@ for_all (pl) { unsigned end = ima.index_of_point (pl); - std::memset((void*)&ima.element(st), + std::memset((void*)&opt::element(ima, st), *(const int*)(&v), end - st); st = end + len_r; } - std::memset((void*)&ima.element(st), + std::memset((void*)&opt::element(ima, st), *(const int*)(&v), - ima.nelements () - st); + opt::nelements(ima) - st); trace::exiting("border::impl::fill_size_1"); } @@ -130,11 +131,11 @@ { unsigned end = ima.index_of_point (pl); for (unsigned i = st; i < end; ++i) - ima.element(i) = v; + opt::element(ima, i) = v; st = end + len_r; } - for (unsigned i = st; i < ima.nelements (); ++i) - ima.element(i) = v; + for (unsigned i = st; i < opt::nelements(ima); ++i) + opt::element(ima, i) = v; trace::exiting("border::impl::fill_size_n"); } Index: mln/border/duplicate.hh --- mln/border/duplicate.hh (revision 3178) +++ mln/border/duplicate.hh (working copy) @@ -37,6 +37,7 @@ # include <mln/core/routine/primary.hh> # include <mln/core/box_runstart_piter.hh> # include <mln/border/get.hh> +# include <mln/opt/element.hh> namespace mln @@ -75,11 +76,11 @@ unsigned border = ima.border(); for (unsigned i = 0; i < border; ++i) - ima.element(i) = ima.element(border); + opt::element(ima, i) = opt::element(ima, border); unsigned st = border + len_c - 1; - for (unsigned i = st + 1; i < ima.nelements(); ++i) - ima.element(i) = ima.element(st); + for (unsigned i = st + 1; i < opt::nelements(ima); ++i) + opt::element(ima, i) = opt::element(ima, st); trace::exiting("border::impl::duplicate_1D"); } @@ -104,23 +105,23 @@ { st = ima.index_of_point (pl); for (unsigned i = 1; i <= border; ++i) - ima.element(st - i) = ima.element(st); + opt::element(ima, st - i) = opt::element(ima, st); st = st + len_c - 1; for (unsigned i = 1; i <= border; ++i) - ima.element(st + i) = ima.element(st); + opt::element(ima, st + i) = opt::element(ima, st); } // Duplicate n first * border line st = real_len_c * border; for (unsigned k = 0; k < border; ++k) for (unsigned i = 0; i < real_len_c; ++i) - ima.element(k * real_len_c + i) = ima.element(st + i); + opt::element(ima, k * real_len_c + i) = opt::element(ima, st + i); // Duplicate n last * border line st = real_len_c * (border + len_r - 1); for (unsigned k = 1; k <= border; ++k) for (unsigned i = st; i < st + real_len_c; ++i) - ima.element(k * real_len_c + i) = ima.element(i); + opt::element(ima, k * real_len_c + i) = opt::element(ima, i); trace::exiting("border::impl::duplicate_2D"); } @@ -155,10 +156,10 @@ { st = ima.index_of_point (pl); for (unsigned i = 1; i <= border; ++i) - ima.element(st - i) = ima.element(st); + opt::element(ima, st - i) = opt::element(ima, st); st = st + len_c - 1; for (unsigned i = 1; i <= border; ++i) - ima.element(st + i) = ima.element(st); + opt::element(ima, st + i) = opt::element(ima, st); pl.next(); } @@ -166,26 +167,28 @@ st = border * face + k * face + border * real_len_c ; for (unsigned j = 1; j <= border; ++j) for (unsigned i = 0; i < real_len_c; ++i) - ima.element(st - j * real_len_c + i) = ima.element(st + i); + opt::element(ima, st - j * real_len_c + i) = + opt::element(ima, st + i); // Duplicate n last * border line st = border * face + k * face + (len_r + border - 1) * real_len_c ; for (unsigned j = 1; j <= border; ++j) for (unsigned i = 0; i < real_len_c; ++i) - ima.element(st + j * real_len_c + i) = ima.element(st + i); + opt::element(ima, st + j * real_len_c + i) = + opt::element(ima, st + i); } // Duplicate n first * border face st = border * face; for (unsigned k = 0; k < border; ++k) for (unsigned i = 0; i < face; ++i) - ima.element(k * face + i) = ima.element(st + i); + opt::element(ima, k * face + i) = opt::element(ima, st + i); // Duplicate n last * border face st = (len_s + border - 1) * face; for (unsigned k = 1; k <= border; ++k) for (unsigned i = 0; i < face; ++i) - ima.element(st + k * face + i) = ima.element(st + i); + opt::element(ima, st + k * face + i) = opt::element(ima, st + i); trace::exiting("border::impl::duplicate_3D"); } Index: mln/border/mirror.hh --- mln/border/mirror.hh (revision 3178) +++ mln/border/mirror.hh (working copy) @@ -49,6 +49,8 @@ # include <mln/geom/max_col.hh> # include <mln/geom/ninds.hh> +# include <mln/opt/element.hh> + namespace mln { @@ -95,10 +97,10 @@ { def::coord i = 0; for (; i < min; ++i) - ima.element(border - 1 - i) = ima(point1d(i)); + opt::element(ima, border - 1 - i) = ima(point1d(i)); for (; i < border; ++i) - ima.element(border - 1 - i) = ima(point1d(static_cast<def::coord>(min - 1))); + opt::element(ima, border - 1 - i) = ima(point1d(static_cast<def::coord>(min - 1))); } /// right border @@ -109,12 +111,12 @@ for (; i < min; ++i, --j) - ima.element(border + nbinds + i) = ima(point1d(j)); + opt::element(ima, border + nbinds + i) = ima(point1d(j)); ++j; for (; i < border; ++i) - ima.element(border + nbinds + i) = ima(point1d(j)); + opt::element(ima, border + nbinds + i) = ima(point1d(j)); } trace::exiting("border::impl::mirror_"); } @@ -136,49 +138,56 @@ // mirror top left corner for (unsigned i = 0; i < border; ++i) for (unsigned j = 0; j < border; ++j) - ima.element(i * ((nbcols + 1) + 2 * border) + j) = ima.element(s); + opt::element(ima, i * ((nbcols + 1) + 2 * border) + j) = + opt::element(ima, s); // mirror top left corner s = start + nbcols; for (unsigned i = 0; i < border; ++i) for (unsigned j = 1; j <= border; ++j) - ima.element(i * ((nbcols + 1) + 2 * border) + (nbcols + border + j)) = ima.element(s); + opt::element(ima, i * ((nbcols + 1) + 2 * border) + (nbcols + border + j)) = opt::element(ima, s); // mirror bottom left corner s = start + (nbrows * real_nbcols); for (unsigned i = 1; i <= border; ++i) for (unsigned j = 1; j <= border; ++j) - ima.element(s - i + (j * (real_nbcols))) = ima.element(s); + opt::element(ima, s - i + (j * (real_nbcols))) = + opt::element(ima, s); // mirror bottom right corner s = start + (nbrows * real_nbcols) + nbcols; for (unsigned i = 1; i <= border; ++i) for (unsigned j = 1; j <= border; ++j) - ima.element(s + i + (j * real_nbcols)) = ima.element(s); + opt::element(ima, s + i + (j * real_nbcols)) = + opt::element(ima, s); // mirror top border s = start; for (unsigned i = 0; i <= nbcols; ++i) for (unsigned j = 1; j <= border; ++j) - ima.element(s + i - (j * real_nbcols)) = ima.element(s + i + ((j - 1)* real_nbcols)); + opt::element(ima, s + i - (j * real_nbcols)) = + opt::element(ima, s + i + ((j - 1)* real_nbcols)); // mirror left border s = start; for (unsigned i = 0; i <= nbrows; ++i) for (unsigned j = 1; j <= border; ++j) - ima.element(s + (i * real_nbcols) - j) = ima.element(s + (i * real_nbcols) + (j - 1)); + opt::element(ima, s + (i * real_nbcols) - j) = + opt::element(ima, s + (i * real_nbcols) + (j - 1)); // mirror right border s = start; for (unsigned i = 0; i <= nbrows; ++i) for (unsigned j = 1; j <= border; ++j) - ima.element(s + (i * real_nbcols + nbcols) + j) = ima.element(s + (i * real_nbcols + nbcols) - (j - 1)); + opt::element(ima, s + (i * real_nbcols + nbcols) + j) = + opt::element(ima, s + (i * real_nbcols + nbcols) - (j - 1)); // mirror bottom border s = start + (nbrows * real_nbcols); for (unsigned i = 0; i <= nbcols; ++i) for (unsigned j = 1; j <= border; ++j) - ima.element(s + i + (j * real_nbcols)) = ima.element(s + i - ((j - 1)* real_nbcols)); + opt::element(ima, s + i + (j * real_nbcols)) = + opt::element(ima, s + i - ((j - 1)* real_nbcols)); trace::exiting("border::impl::mirror_"); } Index: tests/opt/value.cc --- tests/opt/value.cc (revision 3178) +++ tests/opt/value.cc (working copy) @@ -26,9 +26,9 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/// \file tests/opt/at.cc +/// \file tests/opt/value.cc /// -/// Tests on mln::opt::at. +/// Tests on mln::opt::value. #include <mln/opt/value.hh> #include <mln/core/image/flat_image.hh> Index: tests/opt/element.cc --- tests/opt/element.cc (revision 0) +++ tests/opt/element.cc (revision 0) @@ -0,0 +1,47 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// 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/opt/value.cc +/// +/// Tests on mln::opt::at. + +#include <mln/opt/element.hh> +#include <mln/core/image/image2d.hh> +#include <mln/trace/all.hh> + + +int main() +{ + using namespace mln; + + image2d<short> ima(12, 12); + + opt::element(ima, 2) = 51; + mln_precondition(opt::element(ima, 2) == 51); + mln_precondition(opt::nelements(ima) == 324); +} Index: tests/border/duplicate_full.cc --- tests/border/duplicate_full.cc (revision 3178) +++ tests/border/duplicate_full.cc (working copy) @@ -36,6 +36,7 @@ #include <mln/border/duplicate.hh> #include <mln/value/int_u8.hh> #include <mln/value/int_s8.hh> +#include <mln/opt/element.hh> namespace mln { @@ -50,7 +51,7 @@ border::duplicate(ima); for (int i = 0; i < c; ++i) - mln_assertion(ima.element(i) == ref[i]); + mln_assertion(opt::element(ima, i) == ref[i]); } template <typename T> @@ -64,7 +65,7 @@ border::duplicate(ima); for (int i = 0; i < c * r; ++i) - mln_assertion(ima.element(i) == ref[i]); + mln_assertion(opt::element(ima, i) == ref[i]); } } Index: tests/border/mirror_full.cc --- tests/border/mirror_full.cc (revision 3178) +++ tests/border/mirror_full.cc (working copy) @@ -36,6 +36,7 @@ #include <mln/border/mirror.hh> #include <mln/value/int_u8.hh> #include <mln/value/int_s8.hh> +#include <mln/opt/element.hh> namespace mln @@ -51,7 +52,7 @@ border::mirror(ima); for (int i = 0; i < c; ++i) - mln_assertion(ima.element(i) == ref[i]); + mln_assertion(opt::element(ima, i) == ref[i]); } template <typename T> @@ -65,7 +66,7 @@ border::mirror(ima); for (int i = 0; i < c * r; ++i) - mln_assertion(ima.element(i) == ref[i]); + mln_assertion(opt::element(ima, i) == ref[i]); } } Index: tests/border/fill_full.cc --- tests/border/fill_full.cc (revision 3178) +++ tests/border/fill_full.cc (working copy) @@ -32,8 +32,10 @@ /// /// \todo Rewrite this non-sense test file!!! + #include <mln/border/fill.hh> #include <mln/data/fill.hh> +#include <mln/opt/element.hh> #include <mln/core/image/image1d.hh> #include <mln/core/image/image2d.hh> #include <mln/core/image/image3d.hh> @@ -47,6 +49,7 @@ #include <mln/value/float01_16.hh> #include <mln/debug/println_with_border.hh> + using namespace mln; @@ -60,13 +63,13 @@ unsigned i = 0; for(i = 0; i < border; ++i) - mln_assertion (ima.element(i) == value); + mln_assertion (opt::element(ima, i) == value); unsigned bo = border + row; for(; i < bo; ++i) - mln_assertion (ima.element(i) == v); + mln_assertion (opt::element(ima, i) == v); bo += border; for(; i < bo; ++i) - mln_assertion (ima.element(i) == value); + mln_assertion (opt::element(ima, i) == value); } template <typename T> @@ -85,18 +88,18 @@ unsigned ww = r * c; for(i = 0; i < bo; ++i) - mln_assertion (ima.element(i) == value); + mln_assertion (opt::element(ima, i) == value); bo += c * row; for(; i < bo; ++i) { unsigned cur = i % c; if (cur < border || cur >= u) - mln_assertion (ima.element(i) == value); + mln_assertion (opt::element(ima, i) == value); else - mln_assertion (ima.element(i) == v); + mln_assertion (opt::element(ima, i) == v); } for(; i < ww; ++i) - mln_assertion (ima.element(i) == value); + mln_assertion (opt::element(ima, i) == value); } template <typename T> @@ -115,18 +118,18 @@ unsigned ww = r * c; for(i = 0; i < bo; ++i) - mln_assertion (ima.element(i) == value); + mln_assertion (opt::element(ima, i) == value); bo += c * row; for(; i < bo; ++i) { unsigned cur = i % c; if (cur < border || cur >= u) - mln_assertion (ima.element(i) == value); + mln_assertion (opt::element(ima, i) == value); else - mln_assertion (ima.element(i) == v); + mln_assertion (opt::element(ima, i) == v); } for(; i < ww; ++i) - mln_assertion (ima.element(i) == value); + mln_assertion (opt::element(ima, i) == value); } Index: tests/border/duplicate.cc --- tests/border/duplicate.cc (revision 3178) +++ tests/border/duplicate.cc (working copy) @@ -34,6 +34,7 @@ #include <mln/core/image/image2d.hh> #include <mln/debug/iota.hh> #include <mln/border/duplicate.hh> +#include <mln/opt/element.hh> using namespace mln; @@ -46,30 +47,30 @@ debug::iota(ima); border::duplicate(ima); - mln_assertion(ima.element( 0) == 1); - mln_assertion(ima.element( 1) == 1); - mln_assertion(ima.element( 2) == 2); - mln_assertion(ima.element( 3) == 3); - mln_assertion(ima.element( 4) == 3); - mln_assertion(ima.element( 5) == 1); - mln_assertion(ima.element( 6) == 1); - mln_assertion(ima.element( 7) == 2); - mln_assertion(ima.element( 8) == 3); - mln_assertion(ima.element( 9) == 3); - mln_assertion(ima.element(10) == 4); - mln_assertion(ima.element(11) == 4); - mln_assertion(ima.element(12) == 5); - mln_assertion(ima.element(13) == 6); - mln_assertion(ima.element(14) == 6); - mln_assertion(ima.element(15) == 7); - mln_assertion(ima.element(16) == 7); - mln_assertion(ima.element(17) == 8); - mln_assertion(ima.element(18) == 9); - mln_assertion(ima.element(19) == 9); - mln_assertion(ima.element(20) == 7); - mln_assertion(ima.element(21) == 7); - mln_assertion(ima.element(22) == 8); - mln_assertion(ima.element(23) == 9); - mln_assertion(ima.element(24) == 9); + mln_assertion(opt::element(ima, 0) == 1); + mln_assertion(opt::element(ima, 1) == 1); + mln_assertion(opt::element(ima, 2) == 2); + mln_assertion(opt::element(ima, 3) == 3); + mln_assertion(opt::element(ima, 4) == 3); + mln_assertion(opt::element(ima, 5) == 1); + mln_assertion(opt::element(ima, 6) == 1); + mln_assertion(opt::element(ima, 7) == 2); + mln_assertion(opt::element(ima, 8) == 3); + mln_assertion(opt::element(ima, 9) == 3); + mln_assertion(opt::element(ima, 10) == 4); + mln_assertion(opt::element(ima, 11) == 4); + mln_assertion(opt::element(ima, 12) == 5); + mln_assertion(opt::element(ima, 13) == 6); + mln_assertion(opt::element(ima, 14) == 6); + mln_assertion(opt::element(ima, 15) == 7); + mln_assertion(opt::element(ima, 16) == 7); + mln_assertion(opt::element(ima, 17) == 8); + mln_assertion(opt::element(ima, 18) == 9); + mln_assertion(opt::element(ima, 19) == 9); + mln_assertion(opt::element(ima, 20) == 7); + mln_assertion(opt::element(ima, 21) == 7); + mln_assertion(opt::element(ima, 22) == 8); + mln_assertion(opt::element(ima, 23) == 9); + mln_assertion(opt::element(ima, 24) == 9); } Index: tests/border/mirror.cc --- tests/border/mirror.cc (revision 3178) +++ tests/border/mirror.cc (working copy) @@ -34,6 +34,7 @@ #include <mln/core/image/image2d.hh> #include <mln/debug/iota.hh> #include <mln/border/mirror.hh> +#include <mln/opt/element.hh> #include <mln/debug/println_with_border.hh> @@ -46,14 +47,14 @@ image1d<int> ima(2, 3); debug::iota(ima); border::mirror(ima); - mln_assertion(ima.element(0) == 2); - mln_assertion(ima.element(1) == 2); - mln_assertion(ima.element(2) == 1); - mln_assertion(ima.element(3) == 1); - mln_assertion(ima.element(4) == 2); - mln_assertion(ima.element(5) == 2); - mln_assertion(ima.element(6) == 1); - mln_assertion(ima.element(7) == 1); + mln_assertion(opt::element(ima, 0) == 2); + mln_assertion(opt::element(ima, 1) == 2); + mln_assertion(opt::element(ima, 2) == 1); + mln_assertion(opt::element(ima, 3) == 1); + mln_assertion(opt::element(ima, 4) == 2); + mln_assertion(opt::element(ima, 5) == 2); + mln_assertion(opt::element(ima, 6) == 1); + mln_assertion(opt::element(ima, 7) == 1); } @@ -62,47 +63,47 @@ debug::iota(ima); border::mirror(ima); - mln_assertion(ima.element( 0) == 1); - mln_assertion(ima.element( 1) == 1); - mln_assertion(ima.element( 2) == 4); - mln_assertion(ima.element( 3) == 5); - mln_assertion(ima.element( 4) == 6); - mln_assertion(ima.element( 5) == 3); - mln_assertion(ima.element( 6) == 3); - mln_assertion(ima.element( 7) == 1); - mln_assertion(ima.element( 8) == 1); - mln_assertion(ima.element( 9) == 1); - mln_assertion(ima.element(10) == 2); - mln_assertion(ima.element(11) == 3); - mln_assertion(ima.element(12) == 3); - mln_assertion(ima.element(13) == 3); - mln_assertion(ima.element(14) == 2); - mln_assertion(ima.element(15) == 1); - mln_assertion(ima.element(16) == 1); - mln_assertion(ima.element(17) == 2); - mln_assertion(ima.element(18) == 3); - mln_assertion(ima.element(19) == 3); - mln_assertion(ima.element(20) == 2); - mln_assertion(ima.element(21) == 5); - mln_assertion(ima.element(22) == 4); - mln_assertion(ima.element(23) == 4); - mln_assertion(ima.element(24) == 5); - mln_assertion(ima.element(25) == 6); - mln_assertion(ima.element(26) == 6); - mln_assertion(ima.element(27) == 5); - mln_assertion(ima.element(28) == 4); - mln_assertion(ima.element(29) == 4); - mln_assertion(ima.element(30) == 4); - mln_assertion(ima.element(31) == 5); - mln_assertion(ima.element(32) == 6); - mln_assertion(ima.element(33) == 6); - mln_assertion(ima.element(34) == 6); - mln_assertion(ima.element(35) == 4); - mln_assertion(ima.element(36) == 4); - mln_assertion(ima.element(37) == 1); - mln_assertion(ima.element(38) == 2); - mln_assertion(ima.element(39) == 3); - mln_assertion(ima.element(40) == 6); - mln_assertion(ima.element(41) == 6); + mln_assertion(opt::element(ima, 0) == 1); + mln_assertion(opt::element(ima, 1) == 1); + mln_assertion(opt::element(ima, 2) == 4); + mln_assertion(opt::element(ima, 3) == 5); + mln_assertion(opt::element(ima, 4) == 6); + mln_assertion(opt::element(ima, 5) == 3); + mln_assertion(opt::element(ima, 6) == 3); + mln_assertion(opt::element(ima, 7) == 1); + mln_assertion(opt::element(ima, 8) == 1); + mln_assertion(opt::element(ima, 9) == 1); + mln_assertion(opt::element(ima, 10) == 2); + mln_assertion(opt::element(ima, 11) == 3); + mln_assertion(opt::element(ima, 12) == 3); + mln_assertion(opt::element(ima, 13) == 3); + mln_assertion(opt::element(ima, 14) == 2); + mln_assertion(opt::element(ima, 15) == 1); + mln_assertion(opt::element(ima, 16) == 1); + mln_assertion(opt::element(ima, 17) == 2); + mln_assertion(opt::element(ima, 18) == 3); + mln_assertion(opt::element(ima, 19) == 3); + mln_assertion(opt::element(ima, 20) == 2); + mln_assertion(opt::element(ima, 21) == 5); + mln_assertion(opt::element(ima, 22) == 4); + mln_assertion(opt::element(ima, 23) == 4); + mln_assertion(opt::element(ima, 24) == 5); + mln_assertion(opt::element(ima, 25) == 6); + mln_assertion(opt::element(ima, 26) == 6); + mln_assertion(opt::element(ima, 27) == 5); + mln_assertion(opt::element(ima, 28) == 4); + mln_assertion(opt::element(ima, 29) == 4); + mln_assertion(opt::element(ima, 30) == 4); + mln_assertion(opt::element(ima, 31) == 5); + mln_assertion(opt::element(ima, 32) == 6); + mln_assertion(opt::element(ima, 33) == 6); + mln_assertion(opt::element(ima, 34) == 6); + mln_assertion(opt::element(ima, 35) == 4); + mln_assertion(opt::element(ima, 36) == 4); + mln_assertion(opt::element(ima, 37) == 1); + mln_assertion(opt::element(ima, 38) == 2); + mln_assertion(opt::element(ima, 39) == 3); + mln_assertion(opt::element(ima, 40) == 6); + mln_assertion(opt::element(ima, 41) == 6); } Index: tests/border/fill.cc --- tests/border/fill.cc (revision 3178) +++ tests/border/fill.cc (working copy) @@ -34,6 +34,7 @@ #include <mln/core/image/image2d.hh> #include <mln/value/int_u8.hh> #include <mln/debug/println_with_border.hh> +#include <mln/opt/element.hh> using namespace mln; @@ -48,11 +49,11 @@ border::fill (ima, 42); for(int i = 0; i < ww; ++i) if ((i / w < border) || (i / w > border + size)) - mln_assertion (ima.element(i) == 42u); + mln_assertion (opt::element(ima, i) == 42u); else if ((i % w < border) && (border + size <= i % w)) - mln_assertion (ima.element(i) == 42u); + mln_assertion (opt::element(ima, i) == 42u); } int
15 years, 11 months
1
0
0
0
3177: Fix mln mean. mln_sum(T) MUST be divisible by unsigned.
by Ugo Jardonnet
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr> Fix mln mean. mln_sum(T) MUST be divisible by unsigned. * mln/accu/mean.hh: Fix here. mean.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: mln/accu/mean.hh --- mln/accu/mean.hh (revision 3177) +++ mln/accu/mean.hh (working copy) @@ -150,7 +150,7 @@ M mean<T,S,M>::to_result() const { - S n = static_cast<S>(count_.to_result()); + unsigned n = count_.to_result(); return static_cast<M>(sum_.to_result() / n); }
15 years, 11 months
1
0
0
0
← Newer
1
...
7
8
9
10
11
12
13
...
16
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Results per page:
10
25
50
100
200