Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
April 2009
- 11 participants
- 187 discussions
Re: [Olena-patches] 3681: Update tutorial - Write "Getting started with Milena".
by Alexandre Duret-Lutz 17 Apr '09
by Alexandre Duret-Lutz 17 Apr '09
17 Apr '09
>>> "z" == Guillaume Lazzara <z(a)lrde.epita.fr> writes:
[...]
z> --- a/milena/doc/examples/Makefile.am
z> +++ b/milena/doc/examples/Makefile.am
[...]
z> +colorize_SOURCES = tuto3/colorize.cc
z> +println_SOURCES = tuto3/println.cc
z> +trace_SOURCES = tuto3/trace.cc
[...]
z> --- a/milena/doc/examples/examples.mk
z> +++ b/milena/doc/examples/examples.mk
[...]
z> +examples/tuto3 \
z> +examples/tuto3/fill_non_generic.cc.raw \
z> +examples/tuto3/colorize.cc \
z> +examples/tuto3/println.cc \
z> +examples/tuto3/trace.cc \
z> +examples/tuto3/first_routine.cc \
Il sert à quoi cet horrible fichier examples.mk ? Si c'est
ce que je crois (une définition de EXTRA_DIST), c'est
monstrueusement evil !
1) Les *.cc qui sont listés dans _SOURCES sont déjà distribués.
2) Les répertoires qui sont listés dans EXTRA_DIST
(e.g. tuto3) sont recursivement distribués.
3) Au total trace.cc/colorize.cc/println.cc sont donc
distribués 3 fois.
Ça veut dire que make dist va copier les fichier trois fois les
écrasant à chaque fois (perte de temps). Et vous aurez
peut-être droit certains bugs de distcheck qui peuvent survenir
lorsqu'un fichier et distribué à la fois implicitement (parce
qu'il fait partie d'un répertoire EXTRA_DISTé) et explicitement.
--
Alexandre Duret-Lutz
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-04-17 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add normalization, broken.
* fabien/igr/Makefile: Update with norm target.
* fabien/igr/all_labels2gif.sh: Update.
* fabien/igr/fun_labels.cc: Update.
* fabien/igr/fun_labels.sh: Update.
* fabien/igr/norm.cc: Normalize plot.
* fabien/igr/time_max.cc: Update.
---
Makefile | 3 +
all_labels2gif.sh | 10 ++---
fun_labels.cc | 8 ++--
fun_labels.sh | 11 +++--
norm.cc | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
time_max.cc | 4 ++
6 files changed, 123 insertions(+), 15 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/time_max.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/time_max.cc (revision 3681)
+++ trunk/milena/sandbox/fabien/igr/time_max.cc (revision 3682)
@@ -73,22 +73,26 @@
unsigned dim3 = arr_ima.nelements();
+
/////////////
// //
// Lissage //
// //
/////////////
+
util::array<image2d<double> > arr_smooth;
arr_smooth.append(arr_ima[0] * 1.0);
for (unsigned k = 1; k < dim3 - 1; ++k)
arr_smooth.append(arr_ima[k] * 0.5 + arr_ima[k - 1] * 0.25 + arr_ima[k + 1] * 0.25);
arr_smooth.append(arr_ima[dim3 - 1] * 1.0);
+
///////////////////////////////////
// //
// Calcul image max et temps max //
// //
///////////////////////////////////
+
image2d<float> ima_c;
initialize(ima_c, arr_smooth[0]);
data::fill(ima_c, 0.0);
Index: trunk/milena/sandbox/fabien/igr/fun_labels.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/fun_labels.cc (revision 3681)
+++ trunk/milena/sandbox/fabien/igr/fun_labels.cc (revision 3682)
@@ -52,7 +52,7 @@
template <typename I, typename L, typename V>
inline
-void plot_label(I ima, L ima_labels, V lbl)
+void plot_label(Image<I>& ima, Image<L>& ima_labels, V lbl)
{
mln_VAR(vol_label, ima | pw::value(ima_labels) == pw::cst(lbl));
util::array<float> arr;
@@ -92,7 +92,7 @@
template <typename I, typename L>
inline
-void plot_all_labels(I ima, L ima_labels, unsigned nlabels)
+void plot_all_labels(Image<I>& ima, Image<L>& ima_labels, unsigned nlabels)
{
util::array<util::array<float> > arrays(nlabels);
accu::mean<int_u12> accu_mean;
@@ -145,7 +145,7 @@
template <typename I, typename L>
inline
-void plot_point(I ima, L ima_labels, point2d point, const char* desc)
+void plot_point(Image<I>& ima, Image<L>& ima_labels, point2d point, const char* desc)
{
util::array<float> arr;
label_16 prev_lbl;
@@ -213,7 +213,7 @@
point2d p_poumon(122, 115);
image3d<L> ima_labels;
io::dump::load(ima_labels, argv[1]);
- image3d<int_u12> ima;
+ image3d<float> ima;
io::dump::load(ima, argv[2]);
mln_VAR(dilate, morpho::elementary::dilation(extend(ima_labels | (pw::value(ima_labels) == 0u), ima_labels), c6()));
data::fill((ima_labels | (pw::value(ima_labels) == 0u)).rw(), dilate);
Index: trunk/milena/sandbox/fabien/igr/norm.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/norm.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/norm.cc (revision 3682)
@@ -0,0 +1,102 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/slice_image.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/alias/window3d.hh>
+
+#include <mln/io/dump/all.hh>
+
+#include <mln/value/int_u12.hh>
+
+#include <mln/accu/image/all.hh>
+#include <mln/accu/mean.hh>
+#include <mln/arith/all.hh>
+#include <mln/data/paste.hh>
+
+// DEBUG
+/*#include <mln/accu/min.hh>
+#include <mln/accu/max.hh>
+#include <mln/level/compute.hh>*/
+
+using namespace mln;
+using value::int_u12;
+
+
+
+template <typename I>
+inline
+image2d<float> mean_slices(Image<I>& ima, int first, int last)
+{
+ image2d<accu::mean<float> > result;
+
+ initialize(result, slice(ima, first));
+
+ accu::image::init(result);
+ for (int i = first; i <= last; ++i)
+ accu::image::take(result, slice(ima, i));
+
+ return accu::image::to_result(result);
+}
+
+template <typename I>
+inline
+image3d<float> normalize(Image<I>& ima, int first, int last)
+{
+
+ int min_sli = geom::bbox(ima).pmin().sli();
+ int max_sli = geom::bbox(ima).pmax().sli();
+
+ mln_precondition(first >= min_sli && first <= max_sli);
+ mln_precondition(last >= min_sli && last <= max_sli);
+
+ image3d<float> ima_f;
+ initialize(ima_f, ima);
+ data::fill(ima_f, ima);
+
+ image2d<float> ima_ini = mean_slices(ima_f, first, last);
+
+ image3d<float> ima_result;
+ initialize(ima_result, ima_f);
+
+ for (int i = min_sli; i <= max_sli; ++i)
+ data::paste((slice(ima_f, i) - ima_ini), slice(ima_result, i).rw());
+
+ // DEBUG
+ /*accu::min<float> accu_min;
+ accu::max<float> accu_max;
+ float min = level::compute(accu_min, ima_ini);
+ float max = level::compute(accu_max, ima_ini);
+ std::cout << "min = " << min << std::endl;
+ std::cout << "max = " << max << std::endl;*/
+
+ return ima_result;
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ if (argc != 3)
+ {
+ std::cout << "Usage: " << argv[0] << " ima.dump output.dump"
+ << std::endl;
+ return 1;
+ }
+
+ image3d<int_u12> ima;
+ io::dump::load(ima, argv[1]);
+ image3d<float> norm = normalize(ima, 1, 8);
+ io::dump::save(norm, argv[2]);
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/igr/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile (revision 3681)
+++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3682)
@@ -54,6 +54,9 @@
label2gif: label2gif.cc
${CXX} -I../../../ ${DICOM} ${CXXFLAGS} $^ -o label2gif
+norm: norm.cc
+ ${CXX} -I../../../ ${CXXFLAGS} $^ -o norm
+
clean:
rm -rf *.dump *.p?m *.plot *.log *.csv *.dSYM
rm seg2d seg3d wsd2d wsd3d nbasins_finder grad clo_vol wst graph med thres matlab time_max first_slice_dicom
Index: trunk/milena/sandbox/fabien/igr/fun_labels.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/fun_labels.sh (revision 3681)
+++ trunk/milena/sandbox/fabien/igr/fun_labels.sh (revision 3682)
@@ -51,7 +51,7 @@
./crop $input 0 50 90 149 230 170 crop.dump
./grad crop.dump $dim
- for lambda_closing in 5000; do
+ for lambda_closing in 10000; do
echo " for lambda_closing = ${lambda_closing}";
./clo_vol grad.dump $dim ${lambda_closing}
nbasins=`./wst clo_vol.dump $dim`
@@ -61,13 +61,14 @@
#../bin/dumpi12_to_png mean_slices.dump $dim mean_slices_${3}_${lambda_closing}.png
#../bin/dumpi12_to_pgm mean_slices.dump $dim mean_slices_${3}_${lambda_closing}.pgm
- ./fun_labels wst.dump crop.dump $nbasins
+ ./norm crop.dump norm.dump
+ ./fun_labels wst.dump norm.dump $nbasins
rename_label_plots ${lambda_closing}
- ./all_labels2gif.sh ima.dump labels.dump $nbasins ${lambda_closing}
+#./all_labels2gif.sh crop.dump labels.dump $nbasins ${lambda_closing}
- mv *.gif results/plots/
- mv *.plot results/plots/
+#mv *.gif results/
+#mv *.plot results/plots/
#reconstruct_plot tumeur ${lambda_closing}
#create_anim tumeur ${lambda_closing}
Index: trunk/milena/sandbox/fabien/igr/all_labels2gif.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/all_labels2gif.sh (revision 3681)
+++ trunk/milena/sandbox/fabien/igr/all_labels2gif.sh (revision 3682)
@@ -8,13 +8,12 @@
for i in debug_label_${4}_*.pgm; do
j=${i:r}.png
convert $i $j
-#rm $i
+ rm $i
sips -r 90 $j -o $j > /dev/null 2> /dev/null
sips -f horizontal $j -o $j > /dev/null 2> /dev/null
done
- echo $4 $5
- convert -delay 10 -loop 0 debug_label_${4}_*.png debug_label_${4}_${5}.gif
-#rm debug_label_${4}_*.png
+ convert -delay 10 -loop 0 debug_label_${4}_*.png debug_${5}_label_${4}.gif
+ rm debug_label_${4}_*.png
}
create_all_labels ()
@@ -31,5 +30,4 @@
echo "./all_labels2gif.sh ima ima_labels nlabels closing"
}
-#create_all_labels $1 $2 $3 $4
-create_label_anim $1 $2 $3 0 $4
+create_all_labels $1 $2 $3 $4
1
0
17 Apr '09
* doc/doxyfuns.sty: add new commands.
* doc/examples/Makefile.am
* doc/examples/examples.mk
* doc/examples/fill.cc
* doc/examples/tuto3/colorize.cc
* doc/examples/tuto3/fill_non_generic.cc.raw
* doc/examples/tuto3/first_routine.cc
* doc/examples/tuto3/println.cc
* doc/examples/tuto3/trace.cc: add new examples used in the doc.
* doc/figures/colorize-1.pgm
* doc/figures/colorize-2.ppm
* doc/figures/figures.mk
* doc/figures/fill-1.ppm
* doc/figures/fill-2.ppm
* doc/outputs/colorize.txt
* doc/outputs/first_routine.txt
* doc/outputs/outputs.mk
* doc/outputs/println.txt
* doc/outputs/trace.txt: add new reference files.
* doc/ref_guide/ref_guide.tex: fix URL and missing spaces.
* doc/tutorial/tutorial.tex: write chapter "Getting started with
Milena".
---
milena/ChangeLog | 31 ++
milena/doc/doxyfuns.sty | 4 +
milena/doc/examples/Makefile.am | 16 +-
milena/doc/examples/examples.mk | 8 +
milena/doc/examples/fill.cc | 17 +
milena/doc/examples/tuto3/colorize.cc | 25 ++
milena/doc/examples/tuto3/fill_non_generic.cc.raw | 8 +
milena/doc/examples/tuto3/first_routine.cc | 98 ++++++
milena/doc/examples/tuto3/println.cc | 33 ++
milena/doc/examples/tuto3/trace.cc | 25 ++
milena/doc/figures/colorize-1.pgm | Bin 0 -> 141 bytes
milena/doc/figures/colorize-2.ppm | Bin 0 -> 191 bytes
milena/doc/figures/figures.mk | 2 +
milena/doc/figures/fill-1.ppm | Bin 0 -> 12406 bytes
milena/doc/figures/fill-2.ppm | Bin 0 -> 12406 bytes
milena/doc/outputs/outputs.mk | 1 +
milena/doc/outputs/println.txt | 22 ++
milena/doc/outputs/trace.txt | 12 +
milena/doc/ref_guide/ref_guide.tex | 22 +-
milena/doc/tutorial/tutorial.tex | 328 ++++++++++++++++++++-
20 files changed, 635 insertions(+), 17 deletions(-)
create mode 100644 milena/doc/examples/tuto3/colorize.cc
create mode 100644 milena/doc/examples/tuto3/fill_non_generic.cc.raw
create mode 100644 milena/doc/examples/tuto3/first_routine.cc
create mode 100644 milena/doc/examples/tuto3/println.cc
create mode 100644 milena/doc/examples/tuto3/trace.cc
create mode 100644 milena/doc/figures/colorize-1.pgm
create mode 100644 milena/doc/figures/colorize-2.ppm
create mode 100644 milena/doc/figures/fill-1.ppm
create mode 100644 milena/doc/figures/fill-2.ppm
create mode 100644 milena/doc/outputs/colorize.txt
create mode 100644 milena/doc/outputs/first_routine.txt
create mode 100644 milena/doc/outputs/println.txt
create mode 100644 milena/doc/outputs/trace.txt
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 6117e06..1c20f7d 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,34 @@
+2009-04-17 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
+ Update tutorial - Write "Getting started with Milena".
+
+ * doc/doxyfuns.sty: add new commands.
+
+ * doc/examples/Makefile.am
+ * doc/examples/examples.mk
+ * doc/examples/fill.cc
+ * doc/examples/tuto3/colorize.cc
+ * doc/examples/tuto3/fill_non_generic.cc.raw
+ * doc/examples/tuto3/first_routine.cc
+ * doc/examples/tuto3/println.cc
+ * doc/examples/tuto3/trace.cc: add new examples used in the doc.
+
+ * doc/figures/colorize-1.pgm
+ * doc/figures/colorize-2.ppm
+ * doc/figures/figures.mk
+ * doc/figures/fill-1.ppm
+ * doc/figures/fill-2.ppm
+ * doc/outputs/colorize.txt
+ * doc/outputs/first_routine.txt
+ * doc/outputs/outputs.mk
+ * doc/outputs/println.txt
+ * doc/outputs/trace.txt: add new reference files.
+
+ * doc/ref_guide/ref_guide.tex: fix URL and missing spaces.
+
+ * doc/tutorial/tutorial.tex: write chapter "Getting started with
+ Milena".
+
2009-04-15 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
Small fixes.
diff --git a/milena/doc/doxyfuns.sty b/milena/doc/doxyfuns.sty
index 5424d05..a5fd47b 100644
--- a/milena/doc/doxyfuns.sty
+++ b/milena/doc/doxyfuns.sty
@@ -225,3 +225,7 @@ $$
\textbf{\textit{#1}}
}
+\newcommand{\B}[1]{
+\textbf{#1}
+}
+
diff --git a/milena/doc/examples/Makefile.am b/milena/doc/examples/Makefile.am
index c343312..57209da 100644
--- a/milena/doc/examples/Makefile.am
+++ b/milena/doc/examples/Makefile.am
@@ -17,6 +17,7 @@ noinst_PROGRAMS = \
fill-subdomain \
fill-subdomain-shorter \
fill-subimage-cfun \
+ first_routine \
forall-piter \
fun-p2v-1 \
graph-data \
@@ -50,6 +51,13 @@ tuto2_first_image \
tuto3_rw_image \
tuto4_genericity_and_algorithms
+# Tuto3
+noinst_PROGRAMS += \
+colorize \
+println \
+trace
+
+
accu_right_instanciation_SOURCES = accu-right-instanciation.cc
borderthickness_SOURCES = borderthickness.cc
box2d_bbox_SOURCES = box2d-bbox.cc
@@ -64,6 +72,7 @@ fill_part_image_SOURCES = fill-part-image.cc
fill_subdomain_SOURCES = fill-subdomain.cc
fill_subdomain_shorter_SOURCES = fill-subdomain-shorter.cc
fill_subimage_cfun_SOURCES = fill-subimage-cfun.cc
+first_routine_SOURCES = tuto3/first_routine.cc
forall_piter_SOURCES = forall-piter.cc
fun_p2v_1_SOURCES = fun-p2v-1.cc
graph_data_SOURCES = graph-data.cc
@@ -95,6 +104,11 @@ tuto2_first_image_SOURCES = tuto2_first_image.cc
tuto3_rw_image_SOURCES = tuto3_rw_image.cc
tuto4_genericity_and_algorithms_SOURCES = tuto4_genericity_and_algorithms.cc
+# Tuto 3
+colorize_SOURCES = tuto3/colorize.cc
+println_SOURCES = tuto3/println.cc
+trace_SOURCES = tuto3/trace.cc
+
all: clean-figures
mkdir -p $(OUTPUTS_BUILDDIR)
mkdir -p $(FIGURES_BUILDDIR)
@@ -171,7 +185,7 @@ fix-refdata:
split-samples:
mkdir -p $(EXAMPLES_BUILDDIR)
@failcom='exit 1'; \
- list='$(EXAMPLES_SRCDIR)/*.cc'; for file in $$list; do \
+ list=`find $(EXAMPLES_SRCDIR) -type f -name '*.cc'`; for file in $$list; do \
$(DOC_SRCDIR)/tools/split_sample.sh $$file cc $(EXAMPLES_BUILDDIR)\
|| eval $$failcom; \
done
diff --git a/milena/doc/examples/examples.mk b/milena/doc/examples/examples.mk
index 65b0a3f..4449d52 100644
--- a/milena/doc/examples/examples.mk
+++ b/milena/doc/examples/examples.mk
@@ -48,13 +48,21 @@ examples/point-1.cc \
examples/box2d-bbox.cc \
examples/forall-piter.cc \
examples/ima-size.cc \
+examples/tuto2 \
examples/examples.mk \
+examples/tuto4 \
examples/borderthickness.cc \
examples/Makefile.in \
examples/ima-load.cc \
examples/ima-has.cc \
examples/win-create-1.cc \
examples/samples.mk \
+examples/tuto3 \
+examples/tuto3/fill_non_generic.cc.raw \
+examples/tuto3/colorize.cc \
+examples/tuto3/println.cc \
+examples/tuto3/trace.cc \
+examples/tuto3/first_routine.cc \
examples/accu-wrong-instanciation.cc.raw \
examples/accu-right-instanciation.cc \
examples/ima2d-5.cc \
diff --git a/milena/doc/examples/fill.cc b/milena/doc/examples/fill.cc
index 0e98634..c4184b4 100644
--- a/milena/doc/examples/fill.cc
+++ b/milena/doc/examples/fill.cc
@@ -1,4 +1,6 @@
#include <mln/essential/2d.hh>
+#include <tests/data.hh>
+#include <doc/tools/sample_utils.hh>
// \{
template <typename I>
@@ -12,4 +14,19 @@ void fill(I& ima, mln_value(I) v)
int main()
{
+ using namespace mln;
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, MLN_IMG_DIR "/small.ppm");
+
+ // \{
+ box2d b(20,20);
+ fill((ima | b).rw(), literal::green);
+ // \}
+ doc::ppmsave(ima, "fill");
+
+ // \{
+ fill(ima, literal::green);
+ // \}
+ doc::ppmsave(ima, "fill");
}
diff --git a/milena/doc/examples/tuto3/colorize.cc b/milena/doc/examples/tuto3/colorize.cc
new file mode 100644
index 0000000..59dba6f
--- /dev/null
+++ b/milena/doc/examples/tuto3/colorize.cc
@@ -0,0 +1,25 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/debug/colorize.hh>
+#include <doc/tools/sample_utils.hh>
+
+int main()
+{
+ using namespace mln;
+ using namespace mln::value;
+
+ // \{
+ int_u8 vals[25] = { 100, 100, 200, 200, 230,
+ 100, 100, 200, 230, 230,
+ 140, 140, 140, 0, 0,
+ 65, 186, 65, 127, 127,
+ 65, 65, 65, 127, 127 };
+
+ image2d<int_u8> ima = make::image2d(vals);
+ image2d<rgb8> ima_color = debug::colorize(rgb8(), ima, 230);
+ // \}
+
+ doc::pgmsave(ima, "colorize");
+ doc::ppmsave(ima_color, "colorize");
+}
diff --git a/milena/doc/examples/tuto3/fill_non_generic.cc.raw b/milena/doc/examples/tuto3/fill_non_generic.cc.raw
new file mode 100644
index 0000000..d2cd39b
--- /dev/null
+++ b/milena/doc/examples/tuto3/fill_non_generic.cc.raw
@@ -0,0 +1,8 @@
+// Java or C -like code
+
+void fill(image ima, unsigned char v)
+{
+ for (int i = 0; i < ima->nrows; ++i)
+ for (int j = 0; j < ima->ncols; ++j)
+ ima->data[i][j] = v;
+}
diff --git a/milena/doc/examples/tuto3/first_routine.cc b/milena/doc/examples/tuto3/first_routine.cc
new file mode 100644
index 0000000..a0eb870
--- /dev/null
+++ b/milena/doc/examples/tuto3/first_routine.cc
@@ -0,0 +1,98 @@
+#include <mln/essential/2d.hh>
+#include <tests/data.hh>
+#include <doc/tools/sample_utils.hh>
+
+// \{
+namespace mln
+{
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ my_algorithm(const Image<I>& ima_,
+ const Neighborhood<N>& nbh_)
+ {
+ trace::entering("my_algorithm");
+
+ const I& ima = exact(ima_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ typedef value::label_8 V;
+ V nlabels;
+ mln_ch_value(I,V) lbl = labeling::blobs(ima, nbh, nlabels);
+ util::array<unsigned>
+ count = labeling::compute(accu::meta::count(), lbl, nlabels);
+
+ mln_concrete(I) output;
+ initialize(output, ima);
+ data::fill(output, literal::one);
+
+ for (unsigned i = 1; i <= nlabels; ++i)
+ if (count[i] < 10u)
+ data::fill((output | pw::value(lbl) == pw::cst(i)).rw(), literal::zero);
+
+ trace::exiting("my_algorithm");
+ return output;
+ }
+
+} // end of namespace mln
+// \}
+
+namespace sandbox
+{
+
+ using namespace mln;
+
+ // \{
+ template <typename I, typename N>
+ mln_concrete(I)
+ my_algorithm(const Image<I>& ima_,
+ const Neighborhood<N>& nbh_)
+ // \}
+ {
+ // \{
+ trace::entering("my_algorithm");
+ // \}
+
+ // \{
+ const I& ima = exact(ima_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(nbh.is_valid());
+ // \}
+
+ // \{
+ typedef value::label_8 V;
+ V nlabels;
+ mln_ch_value(I,V) lbl = labeling::blobs(ima, nbh, nlabels);
+ util::array<unsigned>
+ count = labeling::compute(accu::meta::count(), lbl, nlabels);
+ // \}
+
+ // \{
+ mln_concrete(I) output;
+ initialize(output, ima);
+ data::fill(output, literal::one);
+ // \}
+
+ // \{
+ for (unsigned i = 1; i <= nlabels; ++i)
+ if (count[i] < 10u)
+ data::fill((output | pw::value(lbl) == pw::cst(i)).rw(), literal::zero);
+ // \}
+
+ // \{
+ trace::exiting("my_algorithm");
+ return output;
+ // \}
+ }
+
+} // end of namespace mln
+
+int main()
+{
+ mln::image2d<bool> test(2,2);
+ mln_assertion(sandbox::my_algorithm(test, mln::c4())
+ == mln::my_algorithm(test, mln::c4()));
+}
diff --git a/milena/doc/examples/tuto3/println.cc b/milena/doc/examples/tuto3/println.cc
new file mode 100644
index 0000000..8ee60be
--- /dev/null
+++ b/milena/doc/examples/tuto3/println.cc
@@ -0,0 +1,33 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/data/fill.hh>
+#include <mln/border/fill.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/debug/println.hh>
+#include <mln/debug/println_with_border.hh>
+
+int main()
+{
+ using namespace mln;
+ using namespace mln::value;
+
+ {
+ std::cout << "// \\{" << std::endl;
+ // \{
+ image2d<int_u8> ima(5,5);
+ data::fill(ima, 2);
+ debug::println(ima);
+ // \}
+ std::cout << "// \\}" << std::endl;
+ }
+
+ {
+ std::cout << "// \\{" << std::endl;
+ // \{
+ image2d<int_u8> ima(5,5);
+ data::fill(ima, 2);
+ border::fill(ima, 7);
+ debug::println_with_border(ima);
+ // \}
+ std::cout << "// \\}" << std::endl;
+ }
+}
diff --git a/milena/doc/examples/tuto3/trace.cc b/milena/doc/examples/tuto3/trace.cc
new file mode 100644
index 0000000..3e0cd41
--- /dev/null
+++ b/milena/doc/examples/tuto3/trace.cc
@@ -0,0 +1,25 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/value/label_8.hh>
+#include <mln/labeling/blobs.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/geom/bbox.hh>
+
+int main()
+{
+ using namespace mln;
+ using namespace mln::value;
+
+ image2d<bool> ima(200,300);
+ label_8 nlabels;
+ // \{
+ // ...
+ trace::quiet = false;
+
+ labeling::blobs(ima, c4(), nlabels);
+
+ trace::quiet = true;
+
+ geom::bbox(ima);
+ // ...
+ // \}
+}
diff --git a/milena/doc/figures/colorize-1.pgm b/milena/doc/figures/colorize-1.pgm
new file mode 100644
index 0000000000000000000000000000000000000000..d7222c74ff5c14fbc536a26736f4f4a3d9427ee7
GIT binary patch
literal 141
zcmWGA<x*B~Pt8j$N-RlDQAny(@XgFg%}Z1;)H6^}$S5f(u+rDh2Z`wA6s4r<r50qC
zB<iIV0d=_sc!oGC1f>?ICKe@UC?w{kD7d7SrRL-p<fi78DEK5M<pT}PFRE0~@CkBp
m)#Nf&Fy%5bHRVc4IdS3{ka+g2r>BR3!Eu*keZ8Y2kN^O=qA;8Q
literal 0
HcmV?d00001
diff --git a/milena/doc/figures/colorize-2.ppm b/milena/doc/figures/colorize-2.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..c7b0c0151897e22f7a089ef8d7f16af669a11061
GIT binary patch
literal 191
zcmWGA<5E^|Pt8j$N-RlDQAny(@XgFg%}Z1;)H6^}$S5f(u+rDh2Z`wA6s4r<r50qC
zB<iIV0d=_sc!oGC1f>?ICKe@UC?w{kD7d7SrRL-p<fi78DEK5M<pT}PFRE0~@CkBp
z)#Nf&Fy%5bHRTeKkOCq<#jQZ3ILQpo1+szYV$L!MVgQ3p2d@_fhyuy?T3dh!$bcXS
F7XaWkM92UD
literal 0
HcmV?d00001
diff --git a/milena/doc/figures/figures.mk b/milena/doc/figures/figures.mk
index 41dba2b..42d8724 100644
--- a/milena/doc/figures/figures.mk
+++ b/milena/doc/figures/figures.mk
@@ -27,6 +27,7 @@ figures/logical-not-3.pbm \
figures/tuto4_genericity_and_algorithms-3.pbm \
figures/tuto4_genericity_and_algorithms-1.ppm \
figures/extend-4.ppm \
+figures/fill-2.ppm \
figures/tuto4_genericity_and_algorithms-8.ppm \
figures/labeling-compute-1.pbm \
figures/tuto3_rw_image-3.ppm \
@@ -35,4 +36,5 @@ figures/tuto4_genericity_and_algorithms-8.pgm \
figures/extend-2.ppm \
figures/tuto4_genericity_and_algorithms-2.ppm \
figures/fill-subdomain-1.pbm \
+figures/fill-1.ppm \
figures/tuto3_rw_image-2.ppm
diff --git a/milena/doc/figures/fill-1.ppm b/milena/doc/figures/fill-1.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..ce4039f142f1e01315853e4bfbac4a24efa81e6f
GIT binary patch
literal 12406
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
G@c#vb$#MJu
literal 0
HcmV?d00001
diff --git a/milena/doc/figures/fill-2.ppm b/milena/doc/figures/fill-2.ppm
new file mode 100644
index 0000000000000000000000000000000000000000..4d4213108284b26441c0e14fdac067d72373e8c0
GIT binary patch
literal 12406
zcmeIu!3u&v6oui|^As1_)Ml(u7wrNi0t1m=V9Xl|rZNqIPha*HEq*ww1LrKhGBs;C
z>!98RZKR&%+Vwg(+1s5+8^UyqqVd<*-ZyG>>VmTmzpV1|ayv<-FLnOjiW?fq^sW6k
zJ#`3DxO!YpM?cG^sIq)((pb{i9FoMWJ}ZI%0tg_000IagfB*srAb<b@2q1s}0tg_0
n00IagfB*srAb<b@2q1s}0tg_000IagfB*srAb<b@e=hI^FboyG
literal 0
HcmV?d00001
diff --git a/milena/doc/outputs/colorize.txt b/milena/doc/outputs/colorize.txt
new file mode 100644
index 0000000..e69de29
diff --git a/milena/doc/outputs/first_routine.txt b/milena/doc/outputs/first_routine.txt
new file mode 100644
index 0000000..e69de29
diff --git a/milena/doc/outputs/outputs.mk b/milena/doc/outputs/outputs.mk
index 1e4c9cf..bb57832 100644
--- a/milena/doc/outputs/outputs.mk
+++ b/milena/doc/outputs/outputs.mk
@@ -7,6 +7,7 @@ outputs/accu-right-instanciation.txt \
outputs/extend.txt \
outputs/ima2d-1.txt \
outputs/borderthickness.txt \
+outputs/first_routine.txt \
outputs/ima-save.txt \
outputs/fill-subimage-cfun.txt \
outputs/labeling-compute.txt \
diff --git a/milena/doc/outputs/println.txt b/milena/doc/outputs/println.txt
new file mode 100644
index 0000000..307681c
--- /dev/null
+++ b/milena/doc/outputs/println.txt
@@ -0,0 +1,22 @@
+// \{
+2 2 2 2 2
+2 2 2 2 2
+2 2 2 2 2
+2 2 2 2 2
+2 2 2 2 2
+
+// \}
+// \{
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 2 2 2 2 2 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+7 7 7 7 7 7 7 7 7 7 7
+
+// \}
diff --git a/milena/doc/outputs/trace.txt b/milena/doc/outputs/trace.txt
new file mode 100644
index 0000000..f1506c7
--- /dev/null
+++ b/milena/doc/outputs/trace.txt
@@ -0,0 +1,12 @@
+labeling::blobs {
+ core::initialize {}
+ data::fill {
+ data::fill_with_value {
+ data::impl::fill_with_value_one_block {
+ data::memset_ {
+ data::impl::memset_ {}
+ } data::memset_
+ } data::impl::fill_with_value_one_block
+ } data::fill_with_value
+ } data::fill
+} labeling::blobs - 0.08s
diff --git a/milena/doc/ref_guide/ref_guide.tex b/milena/doc/ref_guide/ref_guide.tex
index 59b6199..1464207 100644
--- a/milena/doc/ref_guide/ref_guide.tex
+++ b/milena/doc/ref_guide/ref_guide.tex
@@ -140,8 +140,8 @@ A copy of the license is provided in the file COPYING.DOC.
The latest version of Olena is available at the following addresses:
\begin{itemize}
- \item http://www.lrde.epita.fr/dload/olena/olena.tar.gz
- \item http://www.lrde.epita.fr/dload/olena/olena.tar.bz2
+ \item \href{http://www.lrde.epita.fr/dload/olena/olena.tar.gz}{http://www.lrde.epita.fr/dload/olena/olena.tar.gz}
+ \item \href{http://www.lrde.epita.fr/dload/olena/olena.tar.bz2}{http://www.lrde.epita.fr/dload/olena/olena.tar.bz2}
\end{itemize}
@@ -151,19 +151,19 @@ The latest version of Olena is available at the following addresses:
First uncompress the archive. According to the downloaded archive, the options
are different.
\begin{verbatim}
-$tar zxvf olena.tar.gz
+$ tar zxvf olena.tar.gz
\end{verbatim}
Or
\begin{verbatim}
-$tar jxvf olena.tar.bz2
+$ tar jxvf olena.tar.bz2
\end{verbatim}
Then follow these steps:
\begin{verbatim}
-$mkdir olena-build
-$cd olena-build
-$../olena-1.0/configure && make
-$sudo make install
+$ mkdir olena-build
+$ cd olena-build
+$ ../olena-1.0/configure && make
+$ sudo make install
\end{verbatim}
@@ -241,7 +241,7 @@ Before writing your first program, please be ware of these hints:
slow down a program though and these tests can be disabled by compiling
using \code{-DNDEBUG}.
\begin{verbatim}
-g++ -DNDEBUG -Ipath/to/mln my_program.cc
+$ g++ -DNDEBUG -Ipath/to/mln my_program.cc
\end{verbatim}
\item If you decide to use optimization flags to compile for debugging,
@@ -1681,7 +1681,7 @@ You can extend the range of supported files by installing third-parties librarie
\end{itemize}
\doxysection{ioim}{ImageMagick}
- \href{http://www.imagemagick.org/}{http://www.imagemagick.org/}
+ \href{http://www.imagemagick.org}{http://www.imagemagick.org}
You have to install ImageMagick with Magick++ support. You will be able to
load every file recognized as an image by ImageMagick.
@@ -1701,7 +1701,7 @@ You can extend the range of supported files by installing third-parties librarie
installation.
\doxysection{iodcm}{GDCM}
- \href{http://apps.sourceforge.net/mediawiki/gdcm/}{http://apps.sourceforge.net/mediawiki/gdcm/}
+ \href{http://apps.sourceforge.net/mediawiki/gdcm}{http://apps.sourceforge.net/mediawiki/gdcm}
GDCM is a library for manipulating DICOM files. DICOM files are used in
medical imaging.
diff --git a/milena/doc/tutorial/tutorial.tex b/milena/doc/tutorial/tutorial.tex
index 3326b24..a69e28f 100644
--- a/milena/doc/tutorial/tutorial.tex
+++ b/milena/doc/tutorial/tutorial.tex
@@ -466,18 +466,18 @@ There are other ways to get to know what is the status of the project.
\begin{itemize}
\item Olena's trac\\
- \href{https://trac.lrde.org/olena} \\
+ \href{https://trac.lrde.org/olena}{https://trac.lrde.org/olena} \\
Here is the roadmap, the current open tickets/bugs/improvements which
are taken in consideration. A source browser is also available.
\item Olena's Buildfarm \\
- \href{https://buildfarm.lrde.org/buildfarm/oln/} \\
+ \href{https://buildfarm.lrde.org/buildfarm/oln/}{https://buildfarm.lrde.org/buildfarm/oln/} \\
The official buildfarm. Every night and after each commit, tests
are compiled and run. The buildfarm can show you whether it is safe
to update your svn copy of Milena or not\ldots
\item Test failures
- \href{http://www.lrde.epita.fr/dload/olena/test-failures-daily.html}
+ \href{http://www.lrde.epita.fr/dload/olena/test-failures-daily.html}{http://www.lrde.epita.fr/dload/olena/test-failures-daily.html} \\
Through this page, you can see exactly which tests do not compile or pass.
This page is updated every night.
@@ -703,13 +703,18 @@ Text and image outputs will be respectively stored in
Few tools are provided with Milena. They can be considered as full program
examples.
-Currently two tools are available:
+Currently two tools are available: \\
+
\begin{tabular}{l l}
area\_flooding.cc & FIXME:description \\
\hline
seed2tiling.cc & FIXME:description \\
\end{tabular}
+%
+\bigskip
+%
+
To build these tools, run:
\begin{verbatim}
$ cd /my/path/to/olena-1.0/build/milena/tools
@@ -749,7 +754,319 @@ In the installed path prefix, Milena's files are located in:
%====================================
\doxychapter{tuto3}{Getting started with Milena}
-** intent
+\doxysection{getfamiliargen}{Getting familiar with genericity}
+
+One of Milena's main features is its genericity. In order to understand how to
+take benefit of it, let's see what genericity really means for us and how it is
+illustrated in the library.
+
+A \B{Generic algorithm} is written once, without duplicates, and works on
+different kind of input.
+
+Let's have a look to a small example. In any image processing library, we may be
+interested in a small routine to fill an image with data. A common
+implementation would look like this one:
+
+\doxyrawcode{tuto3/fill_non_generic}
+
+In this example, there are a lot of \B{implicit} assumptions about the input:
+\begin{itemize}
+ \item The input image has to be 2D;
+ \item Its definition domain has to be a rectangle starting at (0,0);
+ \item Data cannot be of a different type than \type{unsigned char};
+ \item Image data need to be stored as a 2D array in RAM.
+\end{itemize}
+So, what would happen if we would like to use it for 3D images, use rgb8 as
+value or even work on a region of interest?
+
+This implementation would require to be reimplemented and the user would have to
+deal with the various version of the fill routine. For the developer, it is error
+prone, redundant and hard to maintain. For the user, it is confusing and forces
+to always think about what he is manipulating.
+According to our definition, this algorithm is clearly \B{not} generic.
+
+This is not acceptable and that's why Milena is developped considering
+genericity and user/developer friendlyness.
+
+With Milena, the previous example would be written as follow:
+
+\doxycode{fill}
+
+In this version, the routine can take any kind of image types as arguments. So
+it is for the values: The expected type depends on the value used in the
+given image.
+The \code{for\_all} loop is also significantly generic to support any kind of
+images since the iterator guarantees it will pass through every sites.
+
+This code is more generic and remains really close to the common description of
+the generic algorithm.
+
+As a result, with this algorithm we can fill an image,...
+\doxycode[2]{fill}
+\doxyfigure[1]{fill}{3cm}
+
+... Or fill only a region of interest (a set of points).
+\doxycode[3]{fill}
+\doxyfigure[2]{fill}{3cm}
+
+
+
+\doxysection{firstgenalgo}{First generic algorithm}
+In this section, we will introduce several routines/tools which are useful while
+writing generic algorithms. It is more important to focus on these
+routines/tools than what this program actually does.
+
+
+Here is the full example:
+
+\doxycode[1]{first_routine}
+Let's see the different parts of the algorithm.
+
+
+\doxycode[2]{first_routine}
+The prototype is restrictive enough, readable and still generic.
+We use concepts to statically check that the generic type passed as
+parameter is what the routine expects. The ``exact'' image type is \type{I}. For
+instance an image of type \type{image2d} inherits from \type{Image<image2d>}. So
+an \type{image2d} is an \type{Image<I>}.
+Note that the return type of this function is defined by a macro.
+\code{mln\_concrete} is a macro hidding tricky mechanisms (traits) used in Milena.
+The important point to remember is that a generic function should not return
+\type{I} directly but \code{mln\_concrete(I)} instead.
+
+
+\doxycode[3]{first_routine}
+Like any Milena's routine, note that we use \code{trace}. This debugging tool
+will be detailled in section \ref{debughints}.
+
+
+\doxycode[4]{first_routine}
+Since the function take some arguments thanks their concept, these object cannot
+be used as such. Indeed, concepts are empty shells only used for dispatching and
+concept checking, that's the reason why they are parameterized with their exact
+type. The exact type let us know what is the real type of the object. To get an
+objet with the exact type, simply call \code{exact()}.
+Of course, it is always a good idea to add few preconditions to help during
+debug.
+
+
+\doxycode[5]{first_routine}
+In this portion of code, the image is labeled and the number of site per label
+is computed. This code does not depend on the image type at all. Again, a macro
+\code{mln\_ch\_value} (``mln change value'') helps us. \code{labeling::blobs} is a routine returning an
+image of the same kind as the input image but with a different value.
+\code{mln\_ch\_value} enables the possibility of doing that, whatever the image type
+\type{I} and whatever its value type, it returns the same image type with a
+different value type.
+
+
+\doxycode[6]{first_routine}
+The output image is declared here. Like any variable, it must be initialized at
+some point. To do so, \code{initialize()} is provided. It is a generic routine
+which can initialize the geometry any kind of image with another image of the
+same kind.
+After this call, \var{output} has a valid domain and is valid. It can be used in
+an algorithm, here \code{data::fill}, to have its values modified.
+Note that the value passed to \code{data::fill} is also generic. The library
+includes few generic common values from which any value type can convert to.
+
+
+\doxycode[7]{first_routine}
+In this part, every region from the labeled image, of which cardinality is lower
+than 10 sites, is set to \val{literal::zero} in \var{output}.
+Once again, a generic value is used in order to avoid a constraints on the image
+value type.
+
+
+\doxycode[8]{first_routine}
+Don't forget to close the trace before exiting the function. Then return the
+result.
+
+
+
+%FIXME: add an example to show how a routine behavior depends on its arguments.
+% => cf. des images etendues ou non et un parcours de voisinage.
+
+
+\doxysection{compilhints}{Compilation}
+
+\doxysubsection{howtocompile}{Include path}
+
+If Milena has been installed in a custom directory, e.g. not /usr/include or
+/usr/local/include, the path to the library headers must be passed to the
+compiler.
+
+With g++ and MinGW, the option is \B{-I<path>}.
+\begin{verbatim}
+$ g++ -Ipath/to/mln my_program.cc
+\end{verbatim}
+
+For other compilers, please look at the documentation and search for ``include
+path''.
+
+
+\doxysubsection{liblink}{Library linking}
+As it is usually expected when using a library, no library linking is needed for
+the library itself.
+Milena is a ``header only'' library and is compiled ``on demand'' with your
+program.
+
+If you use specific input/output you may need to link your program with the
+right graphic library. For more information, please refer to section
+\doxyref{inputoutput} in the Quick Reference Guide.
+
+
+\doxysubsection{compildndebug}{Disable Debug}
+By default, Olena enables a lot of internal pre and post conditions. Usually,
+this is a useful feature and it should be enabled. It can heavily slow down a
+program though and these tests can be disabled by compiling using -DNDEBUG:
+
+\begin{verbatim}
+$ g++ -DNDEBUG -Ipath/to/mln my_program.cc
+\end{verbatim}
+
+\doxysubsection{compoptimflags}{Compiler optimization flags}
+
+In this section you will find remarks about the compiler optimization flags and
+their impact on the compilation and execution time.
+
+
+\doxysubsubsection{compoptimgcc}{GCC}
+
+\begin{itemize}
+ \item \B{-O0}, combined with -DNDEBUG, it leads to the fastest compilation
+ time. The execution is somewhat slow though since dispatch functions and one
+ line members are not inlined by the compiler.
+ \item \B{-O1}, best compromise between compilation time and execution time.
+ \item \B{-O2}, \B{-O3}, combined with -DNDEBUG, it leads to the best execution
+ time. However these optimizations dramatically slow down the compilation and
+ requires much more memory at compile time.
+\end{itemize}
+
+\doxysubsubsection{compoptimother}{Other compilers}
+
+Currently, have not tested different optimization flags with other compilers. If
+you did, please report us your results.
+
+
+
+\doxysection{debughints}{Debug hints}
+
+\doxysubsection{gdbhints}{Using assertions and GDB}
+As said above, Milena already includes a lot of post and pre conditions.
+Thus, if you made a mistake in your code there is a high probability that it
+will be detected at run time. If an assertion fail, we advice you to compile
+with the following options:
+
+\begin{verbatim}
+$ g++ -ggdb -Ipath/to/mln my_program.cc
+\end{verbatim}
+
+Note that you \B{MUST NOT} compile \var{-DNDEBUG} other the assertions will be
+deactivated.
+Once compiled, restart the program with GDB.
+
+\begin{verbatim}
+$ gdb ./my_program
+\end{verbatim}
+
+In the GDB console, run it again.
+\begin{verbatim}
+(gdb) run <any parameter you may want to pass to the program>
+\end{verbatim}
+
+When an assertion fails, in the GDB console simply type:
+\begin{verbatim}
+(gdb) bt
+\end{verbatim}
+
+The full backtrace will be printed out and you will be able to find from where
+the error come from. The filenames, the line numbers and the parameters values
+are printed out in the backtrace as you can see in the following example:
+
+\begin{verbatim}
+#0 0xffffe410 in __kernel_vsyscall ()
+#1 0xb7d00640 in raise () from /lib/i686/cmov/libc.so.6
+#2 0xb7d02018 in abort () from /lib/i686/cmov/libc.so.6
+#3 0xb7cf95be in __assert_fail () from /lib/i686/cmov/libc.so.6
+#4 0x0804e094 in mln::image2d<bool>::has (this=0xbff32f34, p=@0xbff32f3c)
+ at /lrde/stockholm/lazzara/svn/olena/git/oln/milena/mln/core/image/image2d.hh:442
+#5 0x0804e6d7 in mln::image2d<bool>::operator() (this=0xbff32f34, p=@0xbff32f3c)
+ at /lrde/stockholm/lazzara/svn/olena/git/oln/milena/mln/core/image/image2d.hh:460
+#6 0x080490b0 in main () at test.cc:18
+\end{verbatim}
+
+
+
+\doxysubsection{traces}{Traces}
+Sometimes, compiling for GDB without optimization flags and with debug
+assertions enabled could lead to execution time dramaticaly high.
+If the function parameter values are not necessary for debbuging,
+a good alternative is the trace system provided in Milena.
+Each time a routine is called, a trace log is written.
+
+This trace allows to follow the stack trace at runtime. It also provides the
+time passed in each function call if the call last at least 10ms.
+
+In order to enable traces in a program, set the related global variable to
+true:
+\begin{verbatim}
+...
+trace::quiet = true;
+...
+\end{verbatim}
+
+Since it's a global variable, at anytime in the source code, the trace can be
+disabled.
+
+\doxycode[1]{trace}
+
+The previous code will produce the following trace:
+
+\begin{verbatim}
+labeling::blobs {
+ core::initialize {}
+ data::fill {
+ data::fill_with_value {
+ data::impl::fill_with_value_one_block {
+ data::memset_ {
+ data::impl::memset_ {}
+ } data::memset_
+ } data::impl::fill_with_value_one_block
+ } data::fill_with_value
+ } data::fill
+} labeling::blobs - 0.08s
+\end{verbatim}
+
+As you can see, \code{labeling::blobs} is located just after having set
+\var{trace::quiet} to \val{true} so its trace is part of the output.
+\code{geom::bbox}'s trace is not part of the output though since traces have
+been disabled just before it is called.
+
+
+\doxysubsection{debugroutines}{Debug routines}
+Milena also provides a lot of debug tools. Here is a small list of the tools:
+\begin{itemize}
+ \item mln::debug::println, print an image in the console.
+ \doxycode[1]{println}
+ \doxymoutput[1]{println}
+
+ \item mln::debug::println\_with\_border, print an image in the console withs
+ its border.
+ \doxycode[2]{println}
+ \doxymoutput[2]{println}
+
+ \item mln::debug::colorize, colorize a label image with random colors.
+ \doxycode[1]{colorize}
+
+ \begin{center}
+ \begin{tabular}{c c c}
+ \doxyfigure[1]{colorize}{3cm} & ~\huge{$\rightarrow$}~ &
+ \doxyfigure[2]{colorize}{3cm} \\
+ \end{tabular}
+ \end{center}
+\end{itemize}
+
A very simple processing chain; the target is the end-user!
@@ -763,6 +1080,7 @@ compilation time w.r.t compilation options (O1, DNDEBUG).
+
%====================================
\doxychapter{tuto4}{Step 4: Load and save images}
--
1.5.6.5
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-04-16 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add functions to plot labels.
* fabien/bin/Makefile: Update with Makefile.rules
* fabien/bin/dumpi12_to_pgm.cc: Update.
* fabien/igr/Makefile.rules: Update.
* fabien/igr/Makefile: Update.
* fabien/igr/all_labels2gif.sh: Create animated gif for labels.
* fabien/igr/crop.cc: Crop tool.
* fabien/igr/fun_labels.cc: Plot labels.
* fabien/igr/fun_labels.sh: IGR current processing chain.
* fabien/igr/grad.cc: Update.
* fabien/igr/label2gif.cc: Create animated gif for label.
* fabien/igr/mean_slices.cc: Create mean image.
* fabien/igr/space_smooth/linear.cc: Update.
* fabien/igr/space_smooth/morpho.cc: Update.
* fabien/igr/time_smooth/linear.cc: Update.
* fabien/igr/wst.cc: Update.
---
TODO | 6 +
bin/Makefile | 18 ----
bin/dumpi12_to_pgm.cc | 9 +-
igr/Makefile | 13 ++-
igr/Makefile.rules | 2
igr/all_labels2gif.sh | 35 ++++++++
igr/crop.cc | 58 ++++++++++++++
igr/fun_labels.cc | 182 +++++++++++++++++++++++++++++++++------------
igr/fun_labels.sh | 71 ++++++++++++++++-
igr/grad.cc | 12 +-
igr/label2gif.cc | 102 +++++++++++++++++++++++++
igr/mean_slices.cc | 88 +++++++++++++++++++++
igr/space_smooth/linear.cc | 8 -
igr/space_smooth/morpho.cc | 24 +++--
igr/time_smooth/linear.cc | 6 -
igr/wst.cc | 2
16 files changed, 537 insertions(+), 99 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/crop.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/crop.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/crop.cc (revision 3680)
@@ -0,0 +1,58 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/alias/window3d.hh>
+
+#include <mln/io/dicom/load.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/int_u12.hh>
+
+
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dcm s_min r_min c_min s_max r_max c_max output.dump" << std::endl;
+ abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u12;
+
+ if (argc != 9)
+ usage(argv);
+
+ image3d<int_u12> vol;
+ io::dicom::load(vol, argv[1]);
+
+ int
+ s_min = atoi(argv[2]),
+ r_min = atoi(argv[3]),
+ c_min = atoi(argv[4]),
+
+ s_max = atoi(argv[5]),
+ r_max = atoi(argv[6]),
+ c_max = atoi(argv[7]);
+
+ box3d b = make::box3d(s_min, r_min, c_min, s_max, r_max, c_max);
+
+ image3d<int_u12> ima(b);
+ data::fill(ima, vol);
+ io::dump::save(ima, argv[8]);
+}
Index: trunk/milena/sandbox/fabien/igr/fun_labels.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/fun_labels.cc (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/fun_labels.cc (revision 3680)
@@ -5,6 +5,8 @@
#include <mln/core/image/image_if.hh>
#include <mln/core/image/slice_image.hh>
#include <mln/core/routine/duplicate.hh>
+#include <mln/core/routine/extend.hh>
+#include <mln/core/var.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/core/alias/window2d.hh>
@@ -12,19 +14,24 @@
#include <mln/core/alias/window3d.hh>
#include <mln/geom/nslis.hh>
+#include <mln/geom/bbox.hh>
#include <mln/io/dump/all.hh>
-#include <mln/io/dicom/load.hh>
+//#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
#include <mln/io/plot/save.hh>
#include <mln/value/int_u8.hh>
#include <mln/value/int_u12.hh>
#include <mln/value/label_16.hh>
-#include <mln/value/label_32.hh>
#include <mln/accu/mean.hh>
#include <mln/accu/median_h.hh>
+#include <mln/data/fill.hh>
#include <mln/level/compute.hh>
+#include <mln/level/stretch.hh>
+#include <mln/make/box3d.hh>
+#include <mln/morpho/elementary/dilation.hh>
#include <mln/pw/all.hh>
#include <mln/util/array.hh>
#include <mln/util/set.hh>
@@ -35,67 +42,149 @@
using value::int_u8;
using value::int_u12;
using value::label_16;
-using value::label_32;
+////////////////
+// //
+// Plot label //
+// //
+////////////////
+
template <typename I, typename L, typename V>
inline
void plot_label(I ima, L ima_labels, V lbl)
{
- I ima_spe = duplicate(ima | pw::value(ima_labels) == pw::cst(lbl));
+ mln_VAR(vol_label, ima | pw::value(ima_labels) == pw::cst(lbl));
util::array<float> arr;
- for (int i = 0; i < ima_spe.domain().pmin().sli(); ++i)
+ int sli_min = geom::bbox(vol_label).pmin().sli();
+ int sli_max = geom::bbox(vol_label).pmax().sli();
+
+ for (int i = geom::bbox(ima).pmin().sli(); i < sli_min; ++i)
arr.append(0.0);
- for (int sli = ima_spe.domain().pmin().sli(); sli <= ima_spe.domain().pmax().sli(); ++sli)
- {
- image2d<int_u12> tmp_slice = duplicate(slice(ima_spe, sli));
+
+ int min_row = geom::bbox(vol_label).pmin().row();
+ int min_col = geom::bbox(vol_label).pmin().col();
+ int max_row = geom::bbox(vol_label).pmax().row();
+ int max_col = geom::bbox(vol_label).pmax().col();
+ for (int sli = sli_min; sli <= sli_max; ++sli)
+ {
+ box3d slice = make::box3d(sli, min_row, min_col,
+ sli, max_row, max_col);
+ mln_VAR(slice_label, vol_label | slice);
accu::mean<int_u12> accu_mean;
- float mean = level::compute(accu_mean, tmp_slice);
+ float mean = level::compute(accu_mean, slice_label);
arr.append(mean);
}
- for (int i = ima_spe.domain().pmax().sli() + 1; i <= ima.domain().pmax().sli(); ++i)
+
+ for (int i = sli_max + 1; i <= geom::bbox(ima).pmax().sli(); ++i)
arr.append(0.0);
+
std::ostringstream slabel;
- slabel << "label_" << lbl << ".plot";
+ slabel << "label_";
+ if (lbl < 100)
+ slabel << "0";
+ if (lbl < 10)
+ slabel << "0";
+ // FIXME: insert label location
+ slabel << lbl << ".plot";
io::plot::save(arr, slabel.str());
}
+template <typename I, typename L>
+inline
+void plot_all_labels(I ima, L ima_labels, unsigned nlabels)
+{
+ util::array<util::array<float> > arrays(nlabels);
+ accu::mean<int_u12> accu_mean;
+
+ label_16 l = 0;
+ int max_slice = ima.domain().pmax().sli();
+ for (int sli = ima.domain().pmin().sli(); sli < max_slice; ++sli)
+ {
+ for (unsigned l = 0; l < nlabels; ++l)
+ {
+ image2d<int_u12> ima_slice = duplicate(slice(ima, sli));
+ image2d<label_16> lbl_slice = duplicate(slice(ima_labels, sli));
+ float mean = level::compute(accu_mean, ima_slice | pw::value(lbl_slice) == pw::cst(l));
+ arrays[l].append(mean);
+ }
+ }
+
+ for (unsigned l = 0; l < nlabels; ++l)
+ {
+ std::ostringstream slabel;
+ slabel << "label_";
+ if (l < 100)
+ slabel << "0";
+ if (l < 10)
+ slabel << "0";
+ // FIXME: insert label location
+ slabel << l << ".plot";
+ io::plot::save(arrays[l], slabel.str());
+ }
+}
+
+
+////////////////
+// //
+// Plot point //
+// //
+////////////////
+
+template <typename L>
+inline
+void save_label_plot(int count, const char* desc, L prev_lbl, util::array<float> arr, int start)
+{
+ std::ostringstream slabel;
+ if (count < 10)
+ slabel << desc << "_0" << count << "_label_" << prev_lbl << ".plot";
+ else
+ slabel << desc << "_" << count << "_label_" << prev_lbl << ".plot";
+ io::plot::save(arr, slabel.str(), start);
+}
template <typename I, typename L>
inline
void plot_point(I ima, L ima_labels, point2d point, const char* desc)
{
util::array<float> arr;
- label_32 prev_lbl;
+ label_16 prev_lbl;
int start = 0;
int count = 1;
+
for (unsigned sli = 0; sli < geom::nslis(ima); ++sli)
{
image2d<int_u12> ima_slice = duplicate(slice(ima, sli));
- image2d<label_32> lbl_slice = duplicate(slice(ima_labels, sli));
+ image2d<label_16> lbl_slice = duplicate(slice(ima_labels, sli));
if (sli == 0)
prev_lbl = lbl_slice(point);
if (lbl_slice(point) != prev_lbl)
{
- std::ostringstream slabel;
- slabel << desc << "_" << count << "_label_" << prev_lbl << ".plot";
- count++;
- io::plot::save(arr, slabel.str(), start);
+ save_label_plot(count, desc, prev_lbl, arr, start);
+ ++count;
arr.clear();
start = sli + 1;
}
- // Taking the mean value of the region.
- accu::mean<int_u12> accu_mean;
- float mean = level::compute(accu_mean, ima_slice | pw::value(lbl_slice) == pw::cst(lbl_slice(point)));
- arr.append(mean);
+ // Taking the median value of the region.
+ accu::median_h<int_u12> accu_med;
+ int_u12 median = level::compute(accu_med, ima_slice | pw::value(lbl_slice) == pw::cst(lbl_slice(point)));
+ arr.append(median);
prev_lbl = lbl_slice(point);
+
+ // Saving a image of the selected label in the current slice for debug.
+ data::fill((ima_slice | pw::value(lbl_slice) == pw::cst(prev_lbl)).rw(), 1750);
+ std::ostringstream str_ima;
+ str_ima << "debug_" << desc << "_";
+ if (sli < 100)
+ str_ima << "0";
+ if (sli < 10)
+ str_ima << "0";
+ str_ima << sli << ".pgm";
+ io::pgm::save(level::stretch(int_u8(), ima_slice), str_ima.str());
}
+
if (!arr.is_empty())
- {
- std::ostringstream slabel;
- slabel << desc << "_" << count << "_label_" << prev_lbl << ".plot";
- io::plot::save(arr, slabel.str(), start);
- }
+ save_label_plot(count, desc, prev_lbl, arr, start);
}
@@ -108,41 +197,39 @@
int main(int argc, char *argv[])
{
- typedef label_32 L;
+ typedef label_16 L;
- if (argc != 5)
+ if (argc != 4)
{
- std::cout << "Usage: " << argv[0] << " <ima.dump> <dimensions> <ima.dcm> <nbasins>"
+ std::cout << "Usage: " << argv[0] << " <ima.dump> <source.dump> <nbasins>"
<< std::endl;
return 1;
}
- unsigned dim = atoi(argv[2]);
- if (dim != 2 && dim != 3)
- {
- std::cout << "<dimensions> invalid" << std::endl;
- return 1;
- }
-
- L nlabels = atoi(argv[4]);
+ L nlabels = atoi(argv[3]);
- if (dim == 2)
- {
- // FIXME
- }
- else
- {
point2d p_tumeur(156, 114);
point2d p_air(34, 94);
point2d p_poumon(122, 115);
image3d<L> ima_labels;
io::dump::load(ima_labels, argv[1]);
image3d<int_u12> ima;
- io::dicom::load(ima, argv[3]);
+ io::dump::load(ima, argv[2]);
+ mln_VAR(dilate, morpho::elementary::dilation(extend(ima_labels | (pw::value(ima_labels) == 0u), ima_labels), c6()));
+ data::fill((ima_labels | (pw::value(ima_labels) == 0u)).rw(), dilate);
+
+ //plot_all_labels(ima, ima_labels, nlabels);
+
+ L l = 0;
+ for (unsigned i = 0; i < nlabels; ++i, l = i)
+ plot_label(ima, ima_labels, l);
+
+ io::dump::save(ima_labels, "labels.dump");
+
+ //plot_point(ima, ima_labels, p_tumeur, "tumeur");
+ //plot_point(ima, ima_labels, p_air, "air");
+ //plot_point(ima, ima_labels, p_poumon, "poumon");
- plot_point(ima, ima_labels, p_tumeur, "tumeur");
- plot_point(ima, ima_labels, p_air, "air");
- plot_point(ima, ima_labels, p_poumon, "poumon");
/*util::set<L> lbl_set;
for (int sli = 0; sli < geom::nslis(ima_labels); ++sli)
{
@@ -157,7 +244,6 @@
{
plot_label(ima, ima_labels, siter.element());
}*/
- }
return 0;
}
Index: trunk/milena/sandbox/fabien/igr/wst.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/wst.cc (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/wst.cc (revision 3680)
@@ -32,7 +32,7 @@
using value::int_u12;
using value::label_16;
using value::label_32;
- typedef label_32 L;
+ typedef label_16 L;
if (argc != 3)
{
Index: trunk/milena/sandbox/fabien/igr/label2gif.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/label2gif.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/label2gif.cc (revision 3680)
@@ -0,0 +1,102 @@
+#include <iostream>
+#include <sstream>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/core/image/slice_image.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/core/routine/extend.hh>
+#include <mln/core/var.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/alias/window3d.hh>
+
+#include <mln/geom/nslis.hh>
+#include <mln/geom/bbox.hh>
+
+#include <mln/io/dump/all.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+#include <mln/value/label_32.hh>
+
+#include <mln/accu/mean.hh>
+#include <mln/accu/median_h.hh>
+#include <mln/data/fill.hh>
+#include <mln/level/compute.hh>
+#include <mln/level/stretch.hh>
+#include <mln/make/box3d.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/pw/all.hh>
+#include <mln/util/array.hh>
+#include <mln/util/set.hh>
+
+using namespace mln;
+using value::int_u8;
+using value::int_u12;
+using value::label_16;
+
+
+
+template <typename I, typename L>
+inline
+void label2gif(I ima, L ima_labels, label_16 label)
+{
+ util::array<float> arr;
+
+ for (unsigned sli = 0; sli < geom::nslis(ima); ++sli)
+ {
+ image2d<int_u12> ima_slice = duplicate(slice(ima, sli));
+ image2d<label_16> lbl_slice = duplicate(slice(ima_labels, sli));
+
+ // Saving a image of the selected label in the current slice for debug.
+ data::fill((ima_slice | pw::value(lbl_slice) == pw::cst(label)).rw(), 1750);
+ std::ostringstream str_ima;
+ str_ima << "debug_label_" << label << "_";
+
+ if (sli < 100)
+ str_ima << "0";
+ if (sli < 10)
+ str_ima << "0";
+
+ str_ima << sli << ".pgm";
+ io::pgm::save(level::stretch(int_u8(), ima_slice), str_ima.str());
+ }
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ typedef label_16 L;
+
+ if (argc != 5)
+ {
+ std::cout << "Usage: " << argv[0] << " <labels.dump> <source.dump> <nbasins> <label>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned nlabels = atoi(argv[3]);
+ L label = atoi(argv[4]);
+
+ image3d<L> ima_labels;
+ io::dump::load(ima_labels, argv[1]);
+ image3d<int_u12> ima;
+ io::dump::load(ima, argv[2]);
+
+ label2gif(ima, ima_labels, label);
+
+ return 0;
+}
+
Index: trunk/milena/sandbox/fabien/igr/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3680)
@@ -16,7 +16,7 @@
${CXX} -I../../../ ${DICOM} ${CXXFLAGS} $^ -o nbasins_finder
grad: grad.cc
- ${CXX} -I../../../ ${DICOM} ${CXXFLAGS} $^ -o grad
+ ${CXX} -I../../../ ${CXXFLAGS} $^ -o grad
clo_vol: clo_vol.cc
${CXX} -I../../../ ${CXXFLAGS} $^ -o clo_vol
@@ -43,7 +43,16 @@
${CXX} -I../../../ ${DICOM} ${MAGICK} ${CXXFLAGS} -lm $^ -o first_slice_dicom
fun_labels: fun_labels.cc
- ${CXX} -I../../../ ${DICOM} ${CXXFLAGS} $^ -o fun_labels
+ ${CXX} -I../../../ ${CXXFLAGS} $^ -o fun_labels
+
+mean_slices: mean_slices.cc
+ ${CXX} -I../../../ ${DICOM} ${CXXFLAGS} $^ -o mean_slices
+
+crop: crop.cc
+ ${CXX} -I../../../ ${DICOM} ${CXXFLAGS} $^ -o crop
+
+label2gif: label2gif.cc
+ ${CXX} -I../../../ ${DICOM} ${CXXFLAGS} $^ -o label2gif
clean:
rm -rf *.dump *.p?m *.plot *.log *.csv *.dSYM
Index: trunk/milena/sandbox/fabien/igr/fun_labels.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/fun_labels.sh (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/fun_labels.sh (revision 3680)
@@ -1,20 +1,83 @@
#!/bin/zsh
+reconstruct_plot ()
+{
+ rm -f ${1}_${2}.plot
+ for i in ${1}_*_label*; do
+ cat $i >> ${1}_${2}.plot
+ done
+}
+
+rename_label_plots ()
+{
+ for i in label_*.plot; do
+ mv $i ${1}_$i
+ done
+}
+
+create_anim ()
+{
+ echo " Creating ${1} animation..."
+ for i in debug_${1}_*.pgm; do
+ j=${i:r}.png
+ convert $i $j
+ rm $i
+ sips -r 90 $j -o $j > /dev/null 2> /dev/null
+ sips -f horizontal $j -o $j > /dev/null 2> /dev/null
+ done
+ convert -delay 10 -loop 0 debug_${1}_*.png debug_${1}_${2}.gif
+ rm debug_${1}_*.png
+}
+
+create_label_anim ()
+{
+ echo " Creating ${1} animation..."
+ for i in debug_${1}_*.pgm; do
+ j=${i:r}.png
+ convert $i $j
+ rm $i
+ sips -r 90 $j -o $j > /dev/null 2> /dev/null
+ sips -f horizontal $j -o $j > /dev/null 2> /dev/null
+ done
+ convert -delay 10 -loop 0 debug_${1}_*.png debug_${1}_${2}.gif
+ rm debug_${1}_*.png
+}
+
process_file ()
{
echo "Processing $3..."
input=$1
dim=$2
- ./grad $input $dim
+ ./crop $input 0 50 90 149 230 170 crop.dump
+ ./grad crop.dump $dim
for lambda_closing in 5000; do
echo " for lambda_closing = ${lambda_closing}";
./clo_vol grad.dump $dim ${lambda_closing}
nbasins=`./wst clo_vol.dump $dim`
echo " nbasins = $nbasins"
-#../bin/dumpl32_to_colorize wst.dump $dim $nbasins colorize_${3}_${lambda_closing}.ppm
- ./fun_labels wst.dump $dim $input $nbasins
+
+#./mean_slices wst.dump $input
+#../bin/dumpi12_to_png mean_slices.dump $dim mean_slices_${3}_${lambda_closing}.png
+#../bin/dumpi12_to_pgm mean_slices.dump $dim mean_slices_${3}_${lambda_closing}.pgm
+
+ ./fun_labels wst.dump crop.dump $nbasins
+ rename_label_plots ${lambda_closing}
+
+ ./all_labels2gif.sh ima.dump labels.dump $nbasins ${lambda_closing}
+
+ mv *.gif results/plots/
+ mv *.plot results/plots/
+
+#reconstruct_plot tumeur ${lambda_closing}
+#create_anim tumeur ${lambda_closing}
+#reconstruct_plot air ${lambda_closing}
+#create_anim air ${lambda_closing}
+#reconstruct_plot poumon ${lambda_closing}
+#create_anim poumon ${lambda_closing}
+
done
}
-process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0052.dcm" 3 "52"
+# 3D (2D + t) images only
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0052.dcm" 3 52
Index: trunk/milena/sandbox/fabien/igr/space_smooth/morpho.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/space_smooth/morpho.cc (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/space_smooth/morpho.cc (revision 3680)
@@ -1,5 +1,5 @@
#include <mln/core/image/image1d.hh>
-#include <mln/core/alias/neighb1d.hh>
+#include <mln/core/alias/neighb2d.hh>
#include <mln/core/image/image2d.hh>
#include <mln/core/image/image3d.hh>
#include <mln/core/image/image_if.hh>
@@ -61,14 +61,11 @@
// //
////////////
util::array<image2d<int_u12> > ima_morpho;
- mln_piter_(image2d<int_u12>) p(ima_morpho.domain());
- for_all(p)
+ for (unsigned i = 0; i < arr_ima.nelements(); ++i)
{
- image1d<int_u12> tmp_ima;
- convert::from_to(ima_arr(p), tmp_ima);
- tmp_ima = morpho::closing::area(tmp_ima, c2(), 3);
- tmp_ima = morpho::opening::area(tmp_ima, c2(), 3);
- ima_morpho(p) = tmp_ima;
+ image2d<int_u12> tmp_ima = morpho::closing::area(arr_ima[i], c4(), 3);
+ tmp_ima = morpho::opening::area(tmp_ima, c4(), 3);
+ ima_morpho.append(tmp_ima);
}
/////////////
@@ -87,10 +84,15 @@
mln_site_(image2d<bool>) pend(vmax);
draw::line(ima_color, pbeg, pend, literal::red);
io::magick::save(ima_color, "test.png");*/
+ image2d<util::array<float> > ima_result(input.nrows(), input.ncols());
+ mln_piter_(image2d<util::array<float> >) p(ima_morpho[0].domain());
+ for_all(p)
+ for (int i = 0; i < ima_morpho.nelements(); ++i)
+ ima_result(p).append(ima_morpho[i](p));
- io::plot::save(ima_morpho(point2d(160, 120)), "morpho_tumeur.plot");
- io::plot::save(ima_morpho(point2d(34, 94)), "morpho_air.plot");
- io::plot::save(ima_morpho(point2d(122, 115)), "morpho_poumon.plot");
+ io::plot::save(ima_result(point2d(156, 114)), "morpho_tumeur.plot");
+ io::plot::save(ima_result(point2d(34, 94)), "morpho_air.plot");
+ io::plot::save(ima_result(point2d(122, 115)), "morpho_poumon.plot");
return 0;
}
Index: trunk/milena/sandbox/fabien/igr/space_smooth/linear.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/space_smooth/linear.cc (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/space_smooth/linear.cc (revision 3680)
@@ -48,9 +48,9 @@
// Linear convolution //
// //
////////////////////////
- float ws[] = { 0, 1/8.f, 0,
- 1/8.f, 1/2.f, 1/8.f,
- 0, 1/8.f, 0 };
+ float ws[] = { 0.f, 0.125, 0.f,
+ 0.125, 0.5, 0.125,
+ 0.f, 0.125, 0.f };
util::array<image2d<float> > ima_linear;
for (unsigned i = 0; i < arr_ima.nelements(); ++i)
@@ -67,7 +67,7 @@
for (int i = 0; i < ima_linear.nelements(); ++i)
ima_result(p).append(ima_linear[i](p));
- io::plot::save(ima_result(point2d(160, 120)), "linear_tumeur.plot");
+ io::plot::save(ima_result(point2d(156, 114)), "linear_tumeur.plot");
io::plot::save(ima_result(point2d(34, 94)), "linear_air.plot");
io::plot::save(ima_result(point2d(122, 115)), "linear_poumon.plot");
Index: trunk/milena/sandbox/fabien/igr/time_smooth/linear.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/time_smooth/linear.cc (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/time_smooth/linear.cc (revision 3680)
@@ -66,11 +66,11 @@
// Outputs //
// //
/////////////
- //io::plot::save(ima_arr(point2d(160, 120)), "ref_tumeur.plot");
+ io::plot::save(ima_arr(point2d(156, 114)), "ref_tumeur.plot");
io::plot::save(ima_linear(point2d(156, 114)), "linear_tumeur.plot");
- //io::plot::save(ima_arr(point2d(34, 94)), "ref_air.plot");
+ io::plot::save(ima_arr(point2d(34, 94)), "ref_air.plot");
io::plot::save(ima_linear(point2d(34, 94)), "linear_air.plot");
- //io::plot::save(ima_arr(point2d(122, 115)), "ref_poumon.plot");
+ io::plot::save(ima_arr(point2d(122, 115)), "ref_poumon.plot");
io::plot::save(ima_linear(point2d(122, 115)), "linear_poumon.plot");
return 0;
Index: trunk/milena/sandbox/fabien/igr/grad.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/grad.cc (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/grad.cc (revision 3680)
@@ -7,10 +7,10 @@
#include <mln/core/alias/neighb3d.hh>
#include <mln/core/alias/window3d.hh>
-#include <mln/io/dicom/load.hh>
-#include <mln/io/dump/save.hh>
+//#include <mln/io/dicom/load.hh>
+#include <mln/io/dump/all.hh>
-#include <mln/value/int_u8.hh>
+//#include <mln/value/int_u8.hh>
#include <mln/value/int_u12.hh>
#include <mln/morpho/elementary/gradient.hh>
@@ -27,7 +27,7 @@
int main(int argc, char *argv[])
{
using namespace mln;
- using value::int_u8;
+ //using value::int_u8;
using value::int_u12;
if (argc != 3)
@@ -47,14 +47,14 @@
if (dim == 2)
{
image2d<int_u12> dcm2;
- io::dicom::load(dcm2, argv[1]);
+ io::dump::load(dcm2, argv[1]);
image2d<int_u12> grad2 = morpho::elementary::gradient(dcm2, c4());
io::dump::save(grad2, "grad.dump");
}
else
{
image3d<int_u12> dcm3;
- io::dicom::load(dcm3, argv[1]);
+ io::dump::load(dcm3, argv[1]);
image3d<int_u12> grad3 = morpho::elementary::gradient(dcm3, c6());
io::dump::save(grad3, "grad.dump");
}
Index: trunk/milena/sandbox/fabien/igr/Makefile.rules
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile.rules (revision 3679)
+++ trunk/milena/sandbox/fabien/igr/Makefile.rules (revision 3680)
@@ -1,5 +1,5 @@
CXX = llvm-g++
-CXXFLAGS = -DNDEBUG -O4
+CXXFLAGS = -Wall -Wextra -DNDEBUG -O4
DICOM_INC = -I/usr/local/include/gdcm-2.0
DICOM_LIBS = -lgdcmCommon -lgdcmDICT -lgdcmDSED -lgdcmIOD -lgdcmMSFF -lgdcmexpat -lgdcmjpeg12 -lgdcmjpeg16 -lgdcmjpeg8 -lgdcmopenjpeg -lgdcmuuid -lgdcmzlib \
Index: trunk/milena/sandbox/fabien/igr/mean_slices.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/mean_slices.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/mean_slices.cc (revision 3680)
@@ -0,0 +1,88 @@
+#include <iostream>
+#include <sstream>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/core/image/slice_image.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/core/routine/extend.hh>
+#include <mln/core/var.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/alias/window3d.hh>
+
+#include <mln/geom/nslis.hh>
+
+#include <mln/io/dump/all.hh>
+#include <mln/io/dicom/load.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+#include <mln/value/label_32.hh>
+
+#include <mln/accu/mean.hh>
+#include <mln/accu/median_h.hh>
+#include <mln/labeling/relabel.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/level/compute.hh>
+#include <mln/make/image3d.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/pw/all.hh>
+#include <mln/util/array.hh>
+#include <mln/util/set.hh>
+
+
+
+using namespace mln;
+using value::int_u8;
+using value::int_u12;
+using value::label_16;
+using value::label_32;
+
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ typedef label_32 L;
+
+ if (argc != 3)
+ {
+ std::cout << "Usage: " << argv[0] << " <ima.dump> <ima.dcm>"
+ << std::endl;
+ return 1;
+ }
+
+ L nlabels = 0;
+
+ image3d<L> ima_labels;
+ io::dump::load(ima_labels, argv[1]);
+ image3d<int_u12> ima;
+ io::dicom::load(ima, argv[2]);
+ util::array<image2d<int_u12> > arr;
+ mln_VAR(dilate, morpho::elementary::dilation(extend(ima_labels | (pw::value(ima_labels) == 0u), ima_labels), c6()));
+ data::fill((ima_labels | (pw::value(ima_labels) == 0u)).rw(), dilate);
+
+ for (unsigned i = 0; i < ima.nslices(); ++i)
+ {
+ image2d<int_u12> sli = duplicate(slice(ima, i));
+ image2d<L> sli_labels = duplicate(slice(ima_labels, i));
+ image2d<L> labels = labeling::relabel(sli_labels, nlabels);
+ mln_VAR(mean_slice, labeling::mean_values(sli, labels, nlabels));
+ arr.append(mean_slice);
+ }
+
+ image3d<int_u12> vol = make::image3d(arr);
+ io::dump::save(vol, "mean_slices.dump");
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/igr/all_labels2gif.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/all_labels2gif.sh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/all_labels2gif.sh (revision 3680)
@@ -0,0 +1,35 @@
+#!/bin/zsh
+
+
+create_label_anim ()
+{
+ echo " Creating label ${4} animation..."
+ ./label2gif $2 $1 $3 $4
+ for i in debug_label_${4}_*.pgm; do
+ j=${i:r}.png
+ convert $i $j
+#rm $i
+ sips -r 90 $j -o $j > /dev/null 2> /dev/null
+ sips -f horizontal $j -o $j > /dev/null 2> /dev/null
+ done
+ echo $4 $5
+ convert -delay 10 -loop 0 debug_label_${4}_*.png debug_label_${4}_${5}.gif
+#rm debug_label_${4}_*.png
+}
+
+create_all_labels ()
+{
+ count=0;
+ while [ $count -lt $3 ]; do
+ create_label_anim $1 $2 $3 $count $4
+ count=$(($count + 1))
+ done
+}
+
+usage ()
+{
+ echo "./all_labels2gif.sh ima ima_labels nlabels closing"
+}
+
+#create_all_labels $1 $2 $3 $4
+create_label_anim $1 $2 $3 0 $4
Property changes on: trunk/milena/sandbox/fabien/igr/all_labels2gif.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/fabien/TODO
===================================================================
--- trunk/milena/sandbox/fabien/TODO (revision 3679)
+++ trunk/milena/sandbox/fabien/TODO (revision 3680)
@@ -44,3 +44,9 @@
[X] Fast projected histogram
[ ] Triple histogram
[X] Create plot for each kind of point with each method
+[ ] Fix mean slices values
+[X] Compatibility Windows
+[X] Fix spatial smooth
+[ ] Crop volume 52
+[ ] Plot all labels (3, 4 labels for tumeur)
+[ ] Prepare data for IGR
Index: trunk/milena/sandbox/fabien/bin/dumpi12_to_pgm.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dumpi12_to_pgm.cc (revision 3679)
+++ trunk/milena/sandbox/fabien/bin/dumpi12_to_pgm.cc (revision 3680)
@@ -4,7 +4,6 @@
#include <mln/value/int_u8.hh>
#include <mln/value/int_u12.hh>
-#include <mln/value/label_32.hh>
#include <mln/io/dump/load.hh>
#include <mln/io/pgm/save.hh>
@@ -25,7 +24,6 @@
using namespace mln;
using value::int_u8;
using value::int_u12;
- using value::label_32;
using value::rgb8;
if (argc != 4)
@@ -48,7 +46,12 @@
}
else
{
- // FIXME
+ image3d<int_u12> ima3d;
+ io::dump::load(ima3d, argv[1]);
+ image3d<int_u8> ima_pgm = level::stretch(int_u8(), ima3d);
+
+ image2d<int_u8> ima_result = debug::slices_2d(ima_pgm, 1.f, 0);
+ io::pgm::save(ima_result, argv[3]);
}
return 0;
Index: trunk/milena/sandbox/fabien/bin/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/bin/Makefile (revision 3679)
+++ trunk/milena/sandbox/fabien/bin/Makefile (revision 3680)
@@ -1,18 +1,4 @@
-GDCM_SRC_DIR = /Users/HiSoKa/Downloads/gdcm-2.0.10
-GDCM_BIN_DIR = /Users/HiSoKa/Downloads/gdcmbin
-
-DICOM_INC = -I${GDCM_SRC_DIR}/Source/Common/ \
- -I${GDCM_BIN_DIR}/Source/Common/ \
- -I${GDCM_SRC_DIR}/Source/DataDictionary/ \
- -I${GDCM_SRC_DIR}/Source/MediaStorageAndFileFormat/ \
- -I${GDCM_SRC_DIR}/Source/DataStructureAndEncodingDefinition/
-
-# "-framework CoreFoundation" is a Mac OS X specific flag
-DICOM_LIB = -L${GDCM_BIN_DIR}/bin \
- -lgdcmCommon -lgdcmDICT -lgdcmDSED -lgdcmIOD -lgdcmMSFF -lgdcmexpat -lgdcmjpeg12 -lgdcmjpeg16 -lgdcmjpeg8 -lgdcmopenjpeg -lgdcmuuid -lgdcmzlib \
- -framework CoreFoundation
-
-CXXFLAGS = -DNDEBUG -O1
+include ../igr/Makefile.rules
all: mask dump
@@ -20,7 +6,7 @@
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o dicom_mask
dump: dicom2dump.cc
- g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o dicom2dump
+ ${CXX} -I../../../ ${CXXFLAGS} ${DICOM} $^ -o dicom2dump
pgm: dicom2pgm.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o dicom2pgm
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-04-16 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Clean dead code, and optimize components retrieving.
* edwin/tree/propagate_value.hh: Remove.
* edwin/tree/propagate_leaf.hh: Remove.
* edwin/tree/propagate_node.hh,
* edwin/tree/propagation.cc,
* edwin/tree/run.hh,
* edwin/tree/sharp.cc,
* edwin/tree/components.hh: Some minor fixes + component retrieving
optimisation.
---
components.hh | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
propagate_node.hh | 2
propagation.cc | 38 -------
run.hh | 1
sharp.cc | 155 ++++++++++++++++++++++--------
5 files changed, 396 insertions(+), 78 deletions(-)
Index: trunk/milena/sandbox/edwin/tree/propagate_leaf.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/edwin/tree/propagate_value.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/edwin/tree/sharp.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/sharp.cc (revision 3678)
+++ trunk/milena/sandbox/edwin/tree/sharp.cc (revision 3679)
@@ -12,20 +12,15 @@
/* Component trees */
#include <mln/morpho/tree/data.hh>
#include <mln/morpho/tree/compute_attribute_image.hh>
-#include "run.hh"
+#include "components.hh"
#include "propagate.hh"
-#include "accumulator/arg_max.hh"
/* Attributes */
#include <mln/morpho/attribute/sharpness.hh>
-#include <mln/morpho/attribute/card.hh>
-
/* io */
-#include <mln/io/ppm/load.hh>
#include <mln/io/pgm/load.hh>
#include <mln/io/pgm/save.hh>
-#include <mln/io/pbm/save.hh>
/* data & pw */
#include <mln/core/concept/function.hh>
@@ -99,8 +94,69 @@
}
return output;
}
+
+ template <typename P2V>
+ struct height_wrapper_ : Function_p2v< height_wrapper_<P2V> >
+ {
+ typedef unsigned result;
+
+ height_wrapper_(const Function_p2v<P2V>& f) :
+ f_ (exact(f))
+ {
+ mlc_is_a(mln_result(P2V), Accumulator)::check();
}
+ template <typename P>
+ unsigned operator() (const P& p) const
+ {
+ return f_(p).height();
+ }
+
+ private:
+ const P2V& f_;
+ };
+
+ template <typename P2V>
+ inline
+ height_wrapper_<P2V>
+ height_wrapper(const Function_p2v<P2V>& f)
+ {
+ return height_wrapper_<P2V>(f);
+ }
+
+ template <typename P2V>
+ struct card_wrapper_ : Function_p2v< card_wrapper_<P2V> >
+ {
+ typedef unsigned result;
+
+ card_wrapper_(const Function_p2v<P2V>& f) :
+ f_ (exact(f))
+ {
+ mlc_is_a(mln_result(P2V), Accumulator)::check();
+ }
+
+ template <typename P>
+ unsigned operator() (const P& p) const
+ {
+ return f_(p).area();
+ }
+
+ private:
+ const P2V& f_;
+ };
+
+ template <typename P2V>
+ inline
+ card_wrapper_<P2V>
+ card_wrapper(const Function_p2v<P2V>& f)
+ {
+ return card_wrapper_<P2V>(f);
+ }
+
+}
+
+
+
@@ -112,6 +168,7 @@
std::string arg;
unsigned nb_components = 0;
unsigned card = 0;
+ unsigned height = 0;
double sharpness = 0;
if (argc < 2)
@@ -130,46 +187,60 @@
card = atoi(argv[++i]);
else if (arg == "--trace")
trace::quiet = false;
+ else if (arg == "-h")
+ height = atoi(argv[++i]);
else
usage (argv);
}
+ /********************/
+ /* Load & Pre-treat */
+ /********************/
-
- /* Image loadin' */
- image2d<rgb8> input_;
- io::ppm::load(input_, argv[1]);
+ if (mydebug)
+ dsp("Load & Pre-treat");
typedef image2d<int_u8> I;
- I input = dist_on_pixels(input_, c4());
+ I input;
+ io::pgm::load(input, argv[1]);
- if (mydebug)
- io::pgm::save(input, "input.pgm");
+ /***************************/
+ /* Component tree creation */
+ /***************************/
+ if (mydebug)
+ dsp("Component tree creation");
- /* Component tree creation */
typedef p_array< mln_site_(I) > S;
typedef morpho::tree::data<I,S> tree_t;
S sorted_sites = level::sort_psites_decreasing(input);
tree_t tree(input, sorted_sites, c4());
+
+ /******************************/
/* Compute Attribute On Image */
+ /******************************/
+ if (mydebug)
+ dsp("Image sharp attribute");
// TODO: l'attribut devrait favoriser les composantes plus larges
// dans son calcul. Ainsi au lieu de faire un sharpness, on aurait
- // un ratio sharpness / largeur de composante (reprendre l'idee du
+ // un ratio sharpness / hauteur de composante (reprendre l'idee du
// log utilise pour INIM).
typedef morpho::attribute::sharpness<I> sharp_t;
typedef mln_ch_value_(I, double) A;
+ typedef mln_ch_value_(I, sharp_t) B;
- if (mydebug)
- dsp("Image sharp attribute");
+ B a_img;
+ A a = morpho::tree::compute_attribute_image(sharp_t (), tree, &a_img);
+ // Note: then we work on nodes (component representant so we don't
+ // need to propagate the representant value to the component sites.
- A a = morpho::tree::compute_attribute_image(sharp_t (), tree);
- morpho::tree::propagate_representant(tree, a);
- /* We don't want little components */
+ /***********************************/
+ /* Components Filtering */
+ /***********************************/
// So we compute card attribute and we filter big components
// FIXME: some attributes are compositions of attributes, here
@@ -179,27 +250,33 @@
if (card)
{
- typedef morpho::attribute::card<I> card_t;
- typedef mln_ch_value_(tree_t::function, mln_result_(card_t)) B;
-
if (mydebug)
dsp("Image card attribute");
- B b = morpho::tree::compute_attribute_image(card_t (), tree);
- morpho::tree::propagate_representant(tree, b);
-
- a = duplicate((fun::p2v::ternary(pw::value(b) > pw::cst(card), pw::value(a), pw::cst(0.0))) | a.domain());
+ a = duplicate((fun::p2v::ternary(card_wrapper(pw::value(a_img)) > pw::cst(card),
+ pw::value(a),
+ pw::cst(0.0))) | a.domain());
}
+ if (height)
+ {
if (mydebug)
- io::pgm::save(level::stretch(int_u8(), a), "attr_image.pgm");
+ dsp("Image height attribute");
+ a = duplicate((fun::p2v::ternary(height_wrapper(pw::value(a_img)) > pw::cst(height),
+ pw::value(a),
+ pw::cst(0.0))) | a.domain());
+ }
+
+ /************************************************/
+ /* Retrieve Components (Maximising the criteria) */
+ /************************************************/
- /* Run max accumulator */
accumulator::arg_max<A> argmax(a);
p_array< mln_psite_(A) > obj_array; // Array of object components.
if (mydebug) {
- std::stringstream s("Run max accumulator, look for ", std::stringstream::out|std::stringstream::in|std::stringstream::ate);
+ std::stringstream s("Run max accumulator, look for ", std::stringstream::out|std::stringstream::in|
+ std::stringstream::ate);
if (nb_components)
s << nb_components << " components.";
else if (sharpness)
@@ -210,12 +287,12 @@
}
if (nb_components) {
- obj_array = morpho::tree::run_ntimes(tree, a, argmax, nb_components);
+ obj_array = morpho::tree::get_components(tree, a, nb_components);
} else if (sharpness > 0) {
mln_VAR(predicate, pw::value(a) > pw::cst(sharpness));
- obj_array = morpho::tree::run_while(tree, a, argmax, predicate);
+ obj_array = morpho::tree::get_components(tree, a, predicate);
} else {
- obj_array = morpho::tree::run_until_glutted_leaves(tree, a, argmax);
+ obj_array = morpho::tree::get_components(tree, a);
}
@@ -227,16 +304,21 @@
std::cout << c;
}
- /* Now Back Propagate to component */
+ /***********************************/
+ /* Use components in output image */
+ /***********************************/
if (mydebug) {
dsp("Create mask and propagate");
}
+ // Note: now we must propagate the representant value to the other components sites.
A pre_output = morpho::tree::set_value_to_components(a, tree, obj_array, 0);
- I output = level::stretch(int_u8(), pre_output);
+ I output = level::stretch(int_u8(), pre_output); //adapt to 0-255
io::pgm::save(output, "components.pgm");
+ /* EXTRA */
+
// typedef mln_ch_value_(I, bool) M;
// M mask;
// initialize(mask, a);
@@ -252,9 +334,6 @@
// mask now contains all nodes related to objects
-
- /* EXTRA */
-
// /* Labeling */
// typedef mln_ch_value_(I, value::label<8>) L;
// value::label<8> nlabel;
Index: trunk/milena/sandbox/edwin/tree/run.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/run.hh (revision 3678)
+++ trunk/milena/sandbox/edwin/tree/run.hh (revision 3679)
@@ -120,7 +120,6 @@
namespace internal
{
-
template <typename T, typename A, typename ACC, typename P2B>
p_array< mln_psite(A) >
run_while(const T& tree,
Index: trunk/milena/sandbox/edwin/tree/components.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/components.hh (revision 0)
+++ trunk/milena/sandbox/edwin/tree/components.hh (revision 3679)
@@ -0,0 +1,278 @@
+// 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.
+
+#ifndef COMPONENTS_HH_
+# define COMPONENTS_HH_
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/function.hh>
+# include <mln/data/fill.hh>
+
+# include <mln/morpho/tree/data.hh>
+# include "propagate_node.hh"
+
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
+
+
+
+namespace mln {
+ namespace morpho {
+ namespace tree {
+
+ template <typename T, typename A>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image);
+
+ template <typename T, typename A>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image, unsigned n);
+
+ template <typename T, typename A, typename P2B>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image, const Function_p2b<P2B>& pred);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+ template <typename P, typename I>
+ struct desc_sort
+ {
+ bool operator()(const P& p1, const P& p2) const
+ {
+ return ima(p1) > ima(p2);
+ }
+ const I& ima;
+
+ desc_sort(const I& ima) : ima(ima) {}
+ };
+
+ template <typename P, typename I>
+ inline
+ void
+ sort(p_array<P>& arr, const I& ima_)
+ {
+ mlc_converts_to(P, mln_psite(I))::check();
+
+ const I& ima = exact(ima_);
+ std::vector<P>& v = arr.hook_std_vector_();
+ std::sort(v.begin(), v.end(), desc_sort<P,I>(ima));
+ }
+
+ template <typename A>
+ inline
+ bool
+ get_max(const p_array< mln_psite(A) >& arr, const A& activity, unsigned& pos)
+ {
+ while (pos < arr.nsites() && !activity(arr[pos]))
+ ++pos;
+ return (pos < arr.nsites());
+ }
+
+
+ //////////////////////////
+ // Predifined predicate //
+ //////////////////////////
+
+ /// Predicate used to gets components until tree leaves last.
+ template <typename T>
+ class pred_tree_leaves_last
+ {
+ public:
+ pred_tree_leaves_last(const T& tree) :
+ n_ (tree.leaves().nsites())
+ {
+ }
+
+ template <typename P>
+ bool operator() (const P& p, unsigned n, unsigned* nb_leaves) const
+ {
+ (void)p;
+ (void)n;
+ mln_assertion(nb_leaves != 0);
+
+ return (*nb_leaves < n_);
+ }
+
+
+ private:
+ unsigned n_;
+ };
+
+ /// Predicate used to get n components.
+ class pred_n_components
+ {
+ public:
+ pred_n_components(unsigned n) :
+ n_(n)
+ {
+ }
+
+ template <typename P>
+ bool operator() (const P& p, unsigned n, unsigned* nb_leaves) const
+ {
+ (void)p;
+ (void)nb_leaves;
+
+ return (n < n_);
+ }
+
+
+ private:
+ unsigned n_;
+ };
+
+ /// Predicate used to get components that check a p2b function predicate.
+ template <typename P2B>
+ class pred_p2b
+ {
+ public:
+ pred_p2b(const P2B& f) :
+ f_ (f)
+ {
+ }
+
+ template <typename P>
+ bool operator() (const P& p, unsigned n, unsigned* nb_leaves) const
+ {
+ (void)n;
+ (void)nb_leaves;
+
+ return (f_(p));
+ }
+
+
+ private:
+ const P2B& f_;
+ };
+
+
+
+
+ template <typename T, typename A, class P>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const A& a, const P& pred, bool uses_leaves = 0)
+ {
+
+ mln_psite(A) p;
+ p_array< mln_psite(A) > components;
+ mln_ch_value(A, bool) activity;
+ p_array< mln_psite(A) > max_arr = tree.nodes();
+ unsigned arr_pos = 0; //position in max_array
+ unsigned n = 0;
+ unsigned* nb_leaves = uses_leaves ? new unsigned(0) : 0;
+
+ initialize(activity, a);
+ data::fill(activity, true);
+ internal::sort(max_arr, a);
+
+ do
+ {
+ if (!internal::get_max(max_arr, activity, arr_pos))
+ break;
+ p = max_arr[arr_pos];
+ if (a(p) == 0)
+ break;
+ components.insert(p);
+ morpho::tree::propagate_node_to_descendants(p, tree, activity, false, nb_leaves);
+ morpho::tree::propagate_node_to_ancestors(p, tree, activity, false);
+ activity(p) = false;
+ mln_assertion(nb_leaves == 0 || *nb_leaves <= n);
+ }
+ while (pred(p, n, nb_leaves));
+
+ if (uses_leaves)
+ delete nb_leaves;
+ return components;
+ }
+
+ } // end of namespace mln::morpho::tree::internal
+
+
+ template <typename T, typename A>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image)
+ {
+ trace::entering("mln::morpho::tree::get_components");
+
+ const A& a = exact(attr_image);
+ mln_precondition(tree.f().domain() == a.domain());
+ mln_precondition(a.is_valid());
+
+ p_array< mln_psite(A) > components =
+ internal::get_components<T, A>(tree, a, internal::pred_tree_leaves_last<T>(tree), true);
+
+ trace::exiting("mln::morpho::tree::get_components");
+ return components;
+ }
+
+
+ template <typename T, typename A>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image, unsigned n)
+ {
+ trace::entering("mln::morpho::tree::get_components");
+
+ const A& a = exact(attr_image);
+ mln_precondition(tree.f().domain() == a.domain());
+ mln_precondition(a.is_valid());
+
+ p_array< mln_psite(A) > components =
+ internal::get_components(tree, a, internal::pred_n_components(n), false);
+
+ trace::exiting("mln::morpho::tree::get_components");
+ return components;
+ }
+
+ template <typename T, typename A, typename P2B>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image, const Function_p2b<P2B>& pred)
+ {
+ trace::entering("mln::morpho::tree::get_components");
+
+ const A& a = exact(attr_image);
+ const P2B& predicate = exact(pred);
+ mln_precondition(tree.f().domain() == a.domain());
+ mln_precondition(a.is_valid());
+
+ p_array< mln_psite(A) > components =
+ internal::get_components(tree, a, internal::pred_p2b<P2B>(predicate), false);
+
+ trace::exiting("mln::morpho::tree::get_components");
+ return components;
+ }
+
+ } // end of namespace mln::morpho::tree
+ } // end of namespace mln::morpho
+} // end of namespace mln
+
+# endif /* !MLN_INCLUDE_ONLY */
+
+#endif /* !COMPONENTS_HH_ */
Index: trunk/milena/sandbox/edwin/tree/propagate_node.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate_node.hh (revision 3678)
+++ trunk/milena/sandbox/edwin/tree/propagate_node.hh (revision 3679)
@@ -136,7 +136,7 @@
pp.start(); // We don't set n to v.
if (nb_leaves)
- *nb_leaves = t.is_a_leaf(pp);
+ *nb_leaves += t.is_a_leaf(pp);
for (pp.next(); pp.is_valid(); pp.next())
{
Index: trunk/milena/sandbox/edwin/tree/propagation.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagation.cc (revision 3678)
+++ trunk/milena/sandbox/edwin/tree/propagation.cc (revision 3679)
@@ -40,23 +40,6 @@
<< "*********************" << std::endl;
}
-template <typename I>
-void print(I& img, mln_psite(I) p)
-{
- using namespace mln;
-
- std::cout << p << " -> ";
- mln_fwd_piter(p_array<mln_psite(I)>) it(img(p));
-// for_all(it)
-// std::cout << it << " ";
-// std::cout << std::endl;
- for_all(it)
- print(img, it);
-}
-
-using namespace mln;
-
-
int main(int argc, char* argv[])
{
using namespace mln;
@@ -101,7 +84,6 @@
dsp("Propagate node to descendants : (point2d(0, 2), tree, dup)");
display_tree_attributes(tree, dup);
-
dup = duplicate(input);
morpho::tree::propagate_if_value(tree, dup, morpho::tree::asc_propagation (), 117, 0);
dsp("Propagate value to ancestors : (117, tree, dup, 0)");
@@ -121,26 +103,6 @@
morpho::tree::propagate_if_value(tree, dup, morpho::tree::desc_propagation (), 117);
dsp("Propagate value to descendants : (117, tree, dup)");
display_tree_attributes(tree, dup);
-
-
- accumulator::arg_max<I> mmax;
- p_array< mln_psite_(I) > tabmax;
- mln_fwd_piter_(p_array< mln_psite_(I) >) pit(tabmax);
-
- dup = duplicate(input);
- tabmax = morpho::tree::run_ntimes(tree, dup, mmax, 5);
- for_all(pit)
- std::cout << pit << std::endl;
- dsp("Run ntimes : (tree, dup, max, 5)");
- display_tree_attributes(tree, dup);
-
-
- dup = duplicate(input);
- tabmax = morpho::tree::run_while_treshold(tree, dup, mmax, 20);
- for_all(pit)
- std::cout << pit << std::endl;
- dsp("Run with treshold : (tree, dup, max, 20)");
- display_tree_attributes(tree, dup);
}
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Grouping ICDAR files into appropriate directories.
Dibco stuff.
* icdar/2009/dibco: New directory.
* icdar/2009/README: New.
* theo/icdar/dibco/main.cc: Remove, obsolete.
This method can be found in...
* scribo/binarization/simple.hh: ...this file.
* theo/icdar/dibco/wst-based.sh,
* lazzara/icdar/quasi.cc,
* lazzara/icdar/binarization.cc: Rename as...
* icdar/2009/dibco/wst-based.sh,
* icdar/2009/dibco/quasi.cc,
* icdar/2009/dibco/binarization.cc: ...these.
* icdar/2009/dibco/svg.1.binarization.cc: New.
* icdar/2009/dibco/svg.2.binarization.cc: New.
* icdar/2009/dibco/svg.3.binarization.cc: New.
Hsc stuff.
* icdar/2009/hsc/first_attempts: New directory.
* theo/icdar/hsc/fuzzy.sh,
* theo/icdar/hsc/reduce.sh,
* theo/icdar/hsc/exec/iz_lines.cc,
* theo/icdar/hsc/exec/relabel_lines.cc,
* theo/icdar/hsc/exec/show_lines_pbm.cc,
* theo/icdar/hsc/exec/show_lines.cc,
* theo/icdar/hsc/boxes.cc,
* theo/icdar/hsc/words.sh,
* theo/icdar/hsc/main.cc,
* theo/icdar/hsc/dist.sh: Rename as...
* icdar/2009/hsc/first_attempts/fuzzy.sh,
* icdar/2009/hsc/first_attempts/reduce.sh,
* icdar/2009/hsc/first_attempts/boxes.cc,
* icdar/2009/hsc/first_attempts/exec,
* icdar/2009/hsc/first_attempts/words.sh,
* icdar/2009/hsc/first_attempts/main.cc,
* icdar/2009/hsc/first_attempts/dist.sh: ...these.
Get rid of private stuff.
* theo/icdar/hsc,
* theo/icdar/hsc/exec,
* theo/icdar/dibco,
* theo/icdar,
* lazzara/icdar: Remove directories.
README | 13
dibco/svg.1.binarization.cc | 464 +++++++++++++++++++++++
dibco/svg.2.binarization.cc | 737 +++++++++++++++++++++++++++++++++++++
dibco/svg.3.binarization.cc | 858 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 2072 insertions(+)
Property changes on: icdar/2009/dibco/wst-based.sh
___________________________________________________________________
Added: svn:mergeinfo
Property changes on: icdar/2009/dibco/quasi.cc
___________________________________________________________________
Added: svn:mergeinfo
Index: icdar/2009/dibco/svg.1.binarization.cc
--- icdar/2009/dibco/svg.1.binarization.cc (revision 0)
+++ icdar/2009/dibco/svg.1.binarization.cc (revision 0)
@@ -0,0 +1,464 @@
+#include <mln/core/var.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/alias/neighb1d.hh>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/site_set/p_queue.hh>
+
+#include <mln/pw/all.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/data/fill.hh>
+
+#include <mln/core/site_set/p_edges.hh>
+#include <mln/core/site_set/p_vertices.hh>
+#include <mln/core/image/graph_elt_neighborhood.hh>
+
+#include <mln/io/essential.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/label_16.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/histo/compute.hh>
+
+#include <mln/morpho/elementary/gradient_internal.hh>
+#include <mln/morpho/closing/volume.hh>
+#include <mln/morpho/closing/height.hh>
+#include <mln/morpho/watershed/flooding.hh>
+
+#include <mln/make/rag_and_labeled_wsl.hh>
+#include <mln/util/graph.hh>
+#include <mln/util/couple.hh>
+#include <mln/debug/colorize.hh>
+#include <mln/fun/i2v/array.hh>
+
+#include <mln/labeling/compute.hh>
+#include <mln/labeling/regional_minima.hh>
+
+# include <mln/linear/gaussian_1d.hh>
+
+#include <mln/accu/center.hh>
+#include <mln/accu/median_h.hh>
+#include <mln/accu/mean.hh>
+
+#include <mln/math/abs.hh>
+#include <mln/literal/colors.hh>
+#include <mln/debug/draw_graph.hh>
+
+
+
+
+
+namespace mln
+{
+
+ struct edge_values : Function_vv2v<edge_values>
+ {
+ typedef value::int_u8 result;
+ typedef void mutable_result;
+
+ value::int_u8 operator()(const value::int_u8& v1,
+ const value::int_u8& v2) const
+ { return math::abs(v1 - v2); }
+
+ };
+
+
+ template <typename I, typename V>
+ class edge_to_color : public Function_p2v< edge_to_color<I,V> >
+ {
+ public:
+ typedef V result;
+
+ edge_to_color(const I& ima_e) : ima_e_(ima_e)
+ {}
+
+ V
+ operator()(const unsigned& e) const
+ { return convert::to<V>(ima_e_.function()(e)); }
+
+ private:
+ const I& ima_e_;
+ };
+
+
+ namespace make
+ {
+
+ template <typename G, typename P>
+ p_edges<G,pw::cst_<P> >
+ dummy_pedges(const Graph<G>& g_, const P& dummy_value)
+ {
+ trace::entering("dummy_pedges");
+
+ const G& g = exact(g_);
+ mln_precondition(g.is_valid());
+ p_edges<G,pw::cst_<P> > pe(g, pw::cst(dummy_value));
+
+ trace::exiting("dummy_pedges");
+ return pe;
+ }
+
+ template <typename FVV, typename G, typename V2P, typename E2P, typename FVE>
+ pw::image<fun::i2v::array<mln_result(FVE)>,p_edges<G,E2P> >
+ edge_image(const pw::image<FVV,p_vertices<G,V2P> >& vertex_image,
+ const p_edges<G,E2P>& pe,
+ const Function_vv2v<FVE>& edge_value_)
+ {
+ trace::entering("edge_image");
+
+ const FVE& edge_value = exact(edge_value_);
+ mln_precondition(vertex_image.is_valid());
+ mln_precondition(pe.is_valid());
+
+ typedef fun::i2v::array<mln_result(FVE)> edge_values_t;
+ edge_values_t edge_values(pe.nsites());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, p_edges<G,E2P> > ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e)
+ ima_e(e) = edge_value(vertex_image.function()(e.element().v1()),
+ vertex_image.function()(e.element().v2()));
+
+ trace::exiting("edge_image");
+ return ima_e;
+ }
+
+
+ template <typename W, typename G>
+ inline
+ p_vertices<util::graph, fun::i2v::array<mln_site(W)> >
+ common_pvertices(const Image<W>& wst, const mln_value(W)& nbasins,
+ const Graph<G>& g_)
+ {
+ trace::entering("common_pvertices");
+
+ const G& g = exact(g_);
+ mln_precondition(g.is_valid());
+
+ typedef fun::i2v::array<mln_site(W)> vertex_sites_t;
+ vertex_sites_t vertex_sites;
+ convert::from_to(labeling::compute(accu::center<mln_site(W)>(), wst, nbasins),
+ vertex_sites);
+
+ p_vertices<util::graph, vertex_sites_t> pv(g, vertex_sites);
+
+ trace::exiting("common_pvertices");
+ return pv;
+ }
+
+
+ template <typename A, typename G, typename F, typename I, typename W>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<G,F> >
+ vertex_image(const Accumulator<A>& accu,
+ const p_vertices<G,F>& pv,
+ const Image<I>& input_,
+ const Image<W>& wst_,
+ const mln_value(W)& nbasins)
+ {
+ trace::entering("vertex_image");
+
+ const I& input = exact(input_);
+ const W& wst = exact(wst_);
+ mln_precondition(input.is_valid());
+ mln_precondition(wst.is_valid());
+ mln_precondition(pv.is_valid());
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(labeling::compute(accu, input, wst, nbasins),
+ vertex_values);
+
+ pw::image<fun::i2v::array<mln_value(I)>,
+ p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ ima_vertex = vertex_values | pv;
+
+ trace::exiting("vertex_image");
+ return ima_vertex;
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ mln_concrete(I)
+ debug_graph_image(const Image<I>& input_,
+ const Image<V>& ima_v_, const Image<E>& ima_e_,
+ unsigned box_size, const mln_value(I)& bg)
+ {
+ trace::entering("debug_graph_image");
+
+ const I& input = exact(input_);
+ const V& ima_v = exact(ima_v_);
+ const E& ima_e = exact(ima_e_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(ima_v.is_valid());
+ mln_precondition(ima_e.is_valid());
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ data::fill(output, bg);
+ debug::draw_graph(output, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box<mln_site(I)> b(p + tl, p + br);
+ b.crop_wrt(output.domain());
+ data::fill((output | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ trace::exiting("debug_graph_image");
+ return output;
+ }
+
+ } // end of namespace mln::make
+
+ int
+ find_threshold(const histo::array<value::int_u8>& h)
+ {
+
+ const float sigma = 5; // FIXME: hard-coded!
+
+ util::array<point1d> c;
+ value::label_8 n;
+
+ {
+ image1d<unsigned> h_, hs_;
+ image1d<value::label_8> l;
+
+ convert::from_to(h, h_);
+ hs_ = linear::gaussian_1d(h_, sigma, 0);
+ l = labeling::regional_minima(hs_, c2(), n);
+
+ {
+// debug::println("l", l);
+// debug::histo(h, "tmp_h.txt");
+
+// std::ofstream file("tmp_hs.txt");
+// mln_piter_(box1d) p(h_.domain());
+// for_all(p)
+// file << p.ind() << ' ' << hs_(p) << std::endl;
+// file.close();
+ }
+
+ accu::center<point1d, point1d> a;
+ c = labeling::compute(a, l, n);
+
+ c[0] = point1d(0); // Force a neutral value for the non-label value (0).
+
+ // std::cout << "c = " << c << std::endl;
+ }
+
+
+ int threshold;
+
+ {
+ std::vector<int> v;
+ for (unsigned i = 0; i <= n; ++i)
+ v.push_back(c[i].ind());
+ std::sort(v.begin(), v.end());
+
+ for (unsigned i = 0; i <= n; ++i)
+ if (v[i] != 0)
+ {
+ threshold = v[i];
+ break;
+ }
+
+ std::cout << "threshold = " << threshold << std::endl;
+ }
+
+ return threshold;
+ }
+
+
+ image2d<bool> contours(const image2d<value::int_u8>& f, unsigned& threshold)
+ {
+ using value::int_u8;
+ typedef int_u8 V;
+ histo::array<V> h;
+
+ image2d<int_u8> g;
+ g = morpho::elementary::gradient_internal(f, c4());
+ g = morpho::closing::height(g, c4(), 3); // FIXME: hard-coded!
+
+ unsigned nbasins;
+ image2d<unsigned> w = morpho::watershed::flooding(g, c4(), nbasins);
+
+ h = histo::compute(g | (pw::value(w) == pw::cst(0)));
+
+ threshold = find_threshold(h);
+
+ return duplicate((pw::value(g) > pw::cst(threshold)) | f.domain());
+ }
+
+} // end of namespace mln
+
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using namespace value;
+
+ if (argc != 4)
+ {
+ std::cout << argv[0] << " input.pgm lambda_grad lambda_graph" << std::endl;
+ return 1;
+ }
+
+ int lambda_grad = std::atoi(argv[2]);
+ int lambda_graph = std::atoi(argv[3]);
+
+
+ image2d<int_u8> input;
+ io::pgm::load(input, argv[1]);
+
+ image2d<int_u8> grad = morpho::elementary::gradient_internal(input, c4());
+// io::pgm::save(grad, "binarization_grad.pgm");
+
+ image2d<int_u8> clo_vol = morpho::closing::volume(grad, c4(), lambda_grad);
+// io::pgm::save(clo_vol, "binarization_clo.pgm");
+
+ label_16 nbasins;
+ image2d<label_16> wst = morpho::watershed::flooding(clo_vol, c4(), nbasins);
+// io::ppm::save(debug::colorize(rgb8(), wst, nbasins), "binarization_wst.ppm");
+
+
+ util::couple<util::graph, image2d<label_16> >
+ rag_data = make::rag_and_labeled_wsl(wst, c4(), nbasins);
+
+// io::pgm::save(rag_data.second(), "binarization_lwsl.pgm");
+
+
+ unsigned threshold;
+ contours(input, threshold);
+
+
+ typedef accu::median_h<int_u8> A;
+ typedef fun::i2v::array<point2d> F;
+
+
+ util::array<int_u8> basin_med = labeling::compute(A(), input, wst, nbasins);
+ basin_med[0] = 0;
+
+ {
+ util::graph& gr = rag_data.first();
+
+ fun::i2v::array<int_u8> f_med;
+ convert::from_to(basin_med, f_med);
+
+ // io::pgm::save(level::transform(wst, f_med), "basin_med.pgm");
+
+ p_vertices<util::graph, fun::i2v::array<point2d> >
+ pv = make::common_pvertices(wst, nbasins, rag_data.first());
+
+ mln_VAR( med, f_med | pv );
+
+ int_u8
+ object = 255,
+ background = 0,
+ unknown = 128;
+
+ med_t out;
+ initialize(out, med);
+ data::fill(out, unknown);
+
+ typedef graph_elt_neighborhood<util::graph, F> N;
+ N nbh;
+
+ // Initialization.
+
+ mln_piter_(med_t) p(med.domain());
+ mln_niter_(N) n(nbh, p);
+ for_all(p)
+ for_all(n)
+ {
+ int d = math::diff_abs(med(p), med(n));
+// if (2 * d > 3 * threshold)
+ if (d > threshold)
+ {
+ if (med(p) < med(n))
+ {
+ out(p) = object;
+ out(n) = background;
+ }
+ else
+ {
+ out(n) = object;
+ out(p) = background;
+ }
+ break;
+ }
+ }
+
+ io::pgm::save(level::transform(wst, out.function()),
+ "temp_out.pgm");
+
+ // Enqueuing.
+
+ typedef mln_psite_(med_t) P;
+ p_queue<P> q;
+
+ for_all(p)
+ {
+ if (out(p) != unknown)
+ continue;
+ for_all(n)
+ if (out(n) != unknown)
+ {
+ q.insert(p);
+ break;
+ }
+ }
+
+ // Propagation.
+
+ P p_;
+ mln_niter_(N) n_(nbh, p_);
+ while (! q.is_empty())
+ {
+ p_ = q.pop_front();
+
+ if (out(p_) != unknown)
+ continue; // std::cerr << "oops! (1)" << std::endl;
+
+ unsigned d = 256, id;
+ for_all(n_)
+ {
+ if (out(n_) == unknown)
+ {
+ q.insert(n_);
+ continue;
+ }
+ unsigned d_ = math::diff_abs(med(p_), med(n_));
+ if (d_ < d)
+ {
+ d = d_;
+ id = out(n_);
+ }
+ }
+ if (d == 256)
+ std::cerr << "oops! (2)" << std::endl;
+
+ out(p_) = id; // object or background.
+ }
+
+ io::pgm::save(level::transform(wst, out.function()),
+ "temp_out_2.pgm");
+
+ }
+
+}
Index: icdar/2009/dibco/svg.2.binarization.cc
--- icdar/2009/dibco/svg.2.binarization.cc (revision 0)
+++ icdar/2009/dibco/svg.2.binarization.cc (revision 0)
@@ -0,0 +1,737 @@
+#include <mln/core/var.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/alias/neighb1d.hh>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/make/double_neighb2d.hh>
+
+#include <mln/pw/all.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/core/site_set/p_queue.hh>
+
+#include <mln/core/routine/extend.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/data/fill.hh>
+
+#include <mln/core/site_set/p_edges.hh>
+#include <mln/core/site_set/p_vertices.hh>
+#include <mln/core/image/graph_elt_neighborhood.hh>
+
+#include <mln/io/essential.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/label_16.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/literal/colors.hh>
+
+#include <mln/histo/compute.hh>
+
+#include <mln/morpho/erosion.hh>
+#include <mln/morpho/dilation.hh>
+#include <mln/morpho/elementary/gradient_internal.hh>
+#include <mln/morpho/closing/volume.hh>
+#include <mln/morpho/closing/height.hh>
+#include <mln/morpho/watershed/flooding.hh>
+
+#include <mln/make/rag_and_labeled_wsl.hh>
+#include <mln/util/graph.hh>
+#include <mln/util/couple.hh>
+#include <mln/debug/colorize.hh>
+#include <mln/fun/i2v/array.hh>
+
+#include <mln/labeling/compute.hh>
+#include <mln/labeling/regional_minima.hh>
+#include <mln/labeling/wrap.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/convert.hh>
+
+#include <mln/linear/gaussian_1d.hh>
+
+#include <mln/accu/center.hh>
+#include <mln/accu/median_h.hh>
+#include <mln/accu/mean.hh>
+
+#include <mln/math/abs.hh>
+#include <mln/debug/draw_graph.hh>
+
+
+
+
+
+namespace mln
+{
+
+ struct edge_values : Function_vv2v<edge_values>
+ {
+ typedef value::int_u8 result;
+ typedef void mutable_result;
+
+ value::int_u8 operator()(const value::int_u8& v1,
+ const value::int_u8& v2) const
+ { return math::abs(v1 - v2); }
+
+ };
+
+
+ template <typename I, typename V>
+ class edge_to_color : public Function_p2v< edge_to_color<I,V> >
+ {
+ public:
+ typedef V result;
+
+ edge_to_color(const I& ima_e) : ima_e_(ima_e)
+ {}
+
+ V
+ operator()(const unsigned& e) const
+ { return convert::to<V>(ima_e_.function()(e)); }
+
+ private:
+ const I& ima_e_;
+ };
+
+
+ namespace make
+ {
+
+ template <typename G, typename P>
+ p_edges<G,pw::cst_<P> >
+ dummy_pedges(const Graph<G>& g_, const P& dummy_value)
+ {
+ trace::entering("dummy_pedges");
+
+ const G& g = exact(g_);
+ mln_precondition(g.is_valid());
+ p_edges<G,pw::cst_<P> > pe(g, pw::cst(dummy_value));
+
+ trace::exiting("dummy_pedges");
+ return pe;
+ }
+
+ template <typename FVV, typename G, typename V2P, typename E2P, typename FVE>
+ pw::image<fun::i2v::array<mln_result(FVE)>,p_edges<G,E2P> >
+ edge_image(const pw::image<FVV,p_vertices<G,V2P> >& vertex_image,
+ const p_edges<G,E2P>& pe,
+ const Function_vv2v<FVE>& edge_value_)
+ {
+ trace::entering("edge_image");
+
+ const FVE& edge_value = exact(edge_value_);
+ mln_precondition(vertex_image.is_valid());
+ mln_precondition(pe.is_valid());
+
+ typedef fun::i2v::array<mln_result(FVE)> edge_values_t;
+ edge_values_t edge_values(pe.nsites());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, p_edges<G,E2P> > ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e)
+ ima_e(e) = edge_value(vertex_image.function()(e.element().v1()),
+ vertex_image.function()(e.element().v2()));
+
+ trace::exiting("edge_image");
+ return ima_e;
+ }
+
+
+ template <typename W, typename G>
+ inline
+ p_vertices<util::graph, fun::i2v::array<mln_site(W)> >
+ common_pvertices(const Image<W>& wst, const mln_value(W)& nbasins,
+ const Graph<G>& g_)
+ {
+ trace::entering("common_pvertices");
+
+ const G& g = exact(g_);
+ mln_precondition(g.is_valid());
+
+ typedef fun::i2v::array<mln_site(W)> vertex_sites_t;
+ vertex_sites_t vertex_sites;
+ convert::from_to(labeling::compute(accu::center<mln_site(W)>(), wst, nbasins),
+ vertex_sites);
+
+ p_vertices<util::graph, vertex_sites_t> pv(g, vertex_sites);
+
+ trace::exiting("common_pvertices");
+ return pv;
+ }
+
+
+ template <typename A, typename G, typename F, typename I, typename W>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<G,F> >
+ vertex_image(const Accumulator<A>& accu,
+ const p_vertices<G,F>& pv,
+ const Image<I>& input_,
+ const Image<W>& wst_,
+ const mln_value(W)& nbasins)
+ {
+ trace::entering("vertex_image");
+
+ const I& input = exact(input_);
+ const W& wst = exact(wst_);
+ mln_precondition(input.is_valid());
+ mln_precondition(wst.is_valid());
+ mln_precondition(pv.is_valid());
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(labeling::compute(accu, input, wst, nbasins),
+ vertex_values);
+
+ pw::image<fun::i2v::array<mln_value(I)>,
+ p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ ima_vertex = vertex_values | pv;
+
+ trace::exiting("vertex_image");
+ return ima_vertex;
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ mln_concrete(I)
+ debug_graph_image(const Image<I>& input_,
+ const Image<V>& ima_v_, const Image<E>& ima_e_,
+ unsigned box_size, const mln_value(I)& bg)
+ {
+ trace::entering("debug_graph_image");
+
+ const I& input = exact(input_);
+ const V& ima_v = exact(ima_v_);
+ const E& ima_e = exact(ima_e_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(ima_v.is_valid());
+ mln_precondition(ima_e.is_valid());
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ data::fill(output, bg);
+ debug::draw_graph(output, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box<mln_site(I)> b(p + tl, p + br);
+ b.crop_wrt(output.domain());
+ data::fill((output | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ trace::exiting("debug_graph_image");
+ return output;
+ }
+
+ } // end of namespace mln::make
+
+ int
+ find_threshold(const histo::array<value::int_u8>& h)
+ {
+
+ const float sigma = 5; // FIXME: hard-coded!
+
+ util::array<point1d> c;
+ value::label_8 n;
+
+ {
+ image1d<unsigned> h_, hs_;
+ image1d<value::label_8> l;
+
+ convert::from_to(h, h_);
+ hs_ = linear::gaussian_1d(h_, sigma, 0);
+ l = labeling::regional_minima(hs_, c2(), n);
+
+ {
+// debug::println("l", l);
+// debug::histo(h, "tmp_h.txt");
+
+// std::ofstream file("tmp_hs.txt");
+// mln_piter_(box1d) p(h_.domain());
+// for_all(p)
+// file << p.ind() << ' ' << hs_(p) << std::endl;
+// file.close();
+ }
+
+ accu::center<point1d, point1d> a;
+ c = labeling::compute(a, l, n);
+
+ c[0] = point1d(0); // Force a neutral value for the non-label value (0).
+
+ // std::cout << "c = " << c << std::endl;
+ }
+
+
+ int threshold;
+
+ {
+ std::vector<int> v;
+ for (unsigned i = 0; i <= n; ++i)
+ v.push_back(c[i].ind());
+ std::sort(v.begin(), v.end());
+
+ for (unsigned i = 0; i <= n; ++i)
+ if (v[i] != 0)
+ {
+ threshold = v[i];
+ break;
+ }
+
+ std::cout << "threshold = " << threshold << std::endl;
+ }
+
+ return threshold;
+ }
+
+
+ image2d<bool> contours(const image2d<value::int_u8>& f, unsigned& threshold)
+ {
+ using value::int_u8;
+ typedef int_u8 V;
+ histo::array<V> h;
+
+ image2d<int_u8> g;
+ g = morpho::elementary::gradient_internal(f, c4());
+ g = morpho::closing::height(g, c4(), 3); // FIXME: hard-coded!
+
+ unsigned nbasins;
+ image2d<unsigned> w = morpho::watershed::flooding(g, c4(), nbasins);
+
+ h = histo::compute(g | (pw::value(w) == pw::cst(0)));
+
+ threshold = find_threshold(h);
+
+ return duplicate((pw::value(g) > pw::cst(threshold)) | f.domain());
+ }
+
+
+ // Distances.
+
+ value::int_u8 dist(const value::int_u8& g1, const value::int_u8& g2)
+ {
+ return math::diff_abs(g1, g2);
+ }
+
+ value::int_u8 dist(const value::rgb8& c1, const value::rgb8& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+ if (d_ > d)
+ d = d_;
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // Functions.
+
+ inline
+ bool is_row_odd(const point2d& p)
+ {
+ return p.row() % 2;
+ }
+
+ inline
+ bool is_square(const point2d& p)
+ {
+ return p.row() % 2 == 0 && p.col() % 2 == 0;
+ }
+
+ inline
+ bool is_edge(const point2d& p)
+ {
+ return p.row() % 2 + p.col() % 2 == 1;
+ }
+
+ inline
+ bool is_point(const point2d& p)
+ {
+ return p.row() % 2 && p.col() % 2;
+ }
+
+
+ // Neighborhoods.
+
+ typedef neighb< win::multiple<window2d, bool(*)(const point2d&)> > dbl_neighb2d;
+
+ const dbl_neighb2d& e2c()
+ {
+ static bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ static bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+ static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2c_h, e2c_v);
+ return nbh;
+ }
+
+ const dbl_neighb2d& e2e()
+ {
+ static 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 };
+ static 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 };
+ static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2e_h, e2e_v);
+ return nbh;
+ }
+
+
+ // Transforms.
+
+ template <typename T>
+ image2d<T>
+ image2full(const image2d<T>& input)
+ {
+ 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)
+ opt::at(output, 2 * row, 2 * col) = opt::at(input, row, col);
+ return output;
+ }
+
+ template <typename T>
+ image2d<T>
+ full2image(const image2d<T>& input)
+ {
+ 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)
+ opt::at(output, row / 2, col / 2) =
+ opt::at(input, row, col);
+ return output;
+ }
+
+
+ // Display.
+
+ 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;
+ }
+
+
+
+ // Distance, stored on edges, of a couple of colors.
+
+ template <typename I, typename N>
+ image2d<value::int_u8>
+ dist_on_edges(const I& input, const N& nbh)
+ {
+ image2d<value::int_u8> output;
+ initialize(output, input);
+ data::fill(output, 0);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ n.start();
+ mln_value(I) c1 = input(n);
+ n.next();
+ mln_value(I) c2 = input(n);
+ output(p) = dist(c1, c2);
+ }
+
+ // io::pgm::save(output, "temp_dist.pgm");
+
+ return output;
+ }
+
+
+ value::int_u8 L_to_int_u8(unsigned l)
+ {
+ return l == 0 ?
+ 0 : // wshed line
+ 1 + (l - 1) % 255; // basin
+ }
+
+
+} // end of namespace mln
+
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using namespace value;
+
+ if (argc != 5)
+ {
+ std::cout << argv[0] << " input.pgm lambda echo output.pbm" << std::endl;
+ return 1;
+ }
+
+ int lambda_grad = std::atoi(argv[2]);
+ int echo = std::atoi(argv[3]);
+
+
+ if (echo != 0 && echo != 1)
+ {
+ std::cout << argv[0] << " input.pgm lambda echo output.pbm" << std::endl;
+ return 1;
+ }
+
+
+ image2d<int_u8> input;
+ io::pgm::load(input, argv[1]);
+
+ image2d<int_u8> input_ = image2full(input); // Larger to make room to edges.
+
+ image2d<int_u8> grad_;
+ {
+ grad_ = dist_on_edges(extend(input_ | is_edge, pw::value(input_)),
+ e2c());
+ }
+
+ // io::pgm::save(grad_, "grad_.pgm");
+
+ mln_VAR(grad, grad_ | is_edge);
+ typedef grad_t E;
+
+ grad = morpho::closing::volume(grad,
+ e2e(),
+ lambda_grad);
+
+ // io::pgm::save(grad.unmorph_(), "grad.pgm");
+
+ typedef label_16 L; // Label type.
+
+ L nbasins;
+
+ typedef mln_ch_value_(E, L) EL;
+
+ EL wst = morpho::watershed::flooding(grad,
+ e2e(),
+ nbasins);
+
+ std::cout << "n basins = " << nbasins << std::endl;
+
+
+ if (echo)
+ {
+ io::ppm::save(display_edge(debug::colorize(rgb8(),
+ wst,
+ nbasins).unmorph_(),
+ literal::black,
+ 3),
+ "temp_wst_edges.ppm");
+ }
+
+
+ image2d<L> w_all = wst.unmorph_();
+
+ // edges -> squares
+ mln_VAR(w_squares, w_all | is_square);
+ data::paste(morpho::dilation(extend(w_squares, pw::value(w_all)),
+ c4().win()),
+ w_all);
+ // edges -> points
+ mln_VAR(w_points, w_all | is_point);
+ data::paste(morpho::erosion(extend(w_points, pw::value(w_all)),
+ c4().win()),
+ w_all);
+
+ image2d<L> ws = full2image(w_all);
+
+ if (echo)
+ {
+ io::ppm::save(debug::colorize(rgb8(), ws, nbasins),
+ "temp_ws.ppm");
+ }
+
+ util::couple<util::graph, image2d<L> >
+ rag_data = make::rag_and_labeled_wsl(w_all, c8(), nbasins);
+
+ if (echo)
+ io::pgm::save(labeling::wrap(int_u8(),
+ rag_data.second()),
+ "temp_lwsl.pgm");
+
+
+ unsigned threshold;
+ contours(input, threshold);
+
+
+ typedef accu::median_h<int_u8> A;
+ typedef fun::i2v::array<point2d> F;
+
+
+ util::array<int_u8> basin_med = labeling::compute(A(), input, ws, nbasins);
+ basin_med[0] = 0;
+
+
+
+ if (echo)
+ io::ppm::save(debug::colorize(rgb8(), w_all, nbasins),
+ "temp_w_all.ppm");
+
+
+
+ // ----------------------------- R A G --------------------------------
+
+
+ util::graph& gr = rag_data.first();
+
+ fun::i2v::array<int_u8> f_med;
+ convert::from_to(basin_med, f_med);
+
+ if (echo)
+ {
+ io::pgm::save(level::transform(w_all, f_med),
+ "temp_w_all.pgm");
+ io::pgm::save(level::transform(ws, f_med), "temp_basin_med.pgm");
+ }
+
+ p_vertices<util::graph, fun::i2v::array<point2d> >
+ pv = make::common_pvertices(ws, nbasins, rag_data.first());
+
+ mln_VAR( med, f_med | pv );
+
+ int_u8
+ object = 255,
+ background = 0,
+ unknown = 128;
+
+ med_t out;
+ initialize(out, med);
+ data::fill(out, unknown);
+
+ typedef graph_elt_neighborhood<util::graph, F> N;
+ N nbh;
+
+ // Initialization.
+
+ mln_piter_(med_t) p(med.domain());
+ mln_niter_(N) n(nbh, p);
+ for_all(p)
+ for_all(n)
+ {
+ int d = math::diff_abs(med(p), med(n));
+ // if (2 * d > 3 * threshold)
+ if (d > threshold)
+ {
+ if (med(p) < med(n))
+ {
+ out(p) = object;
+ out(n) = background;
+ }
+ else
+ {
+ out(n) = object;
+ out(p) = background;
+ }
+ break;
+ }
+ }
+
+ if (echo)
+ {
+ io::pgm::save(level::transform(ws, out.function()),
+ "temp_out.pgm");
+ }
+
+ // Enqueuing.
+
+ typedef mln_psite_(med_t) P;
+ p_queue<P> q;
+
+ for_all(p)
+ {
+ if (out(p) != unknown)
+ continue;
+ for_all(n)
+ if (out(n) != unknown)
+ {
+ q.insert(p);
+ break;
+ }
+ }
+
+ // Propagation.
+
+ P p_;
+ mln_niter_(N) n_(nbh, p_);
+ while (! q.is_empty())
+ {
+ p_ = q.pop_front();
+
+ if (out(p_) != unknown)
+ continue; // std::cerr << "oops! (1)" << std::endl;
+
+ unsigned d = 256, id;
+ for_all(n_)
+ {
+ if (out(n_) == unknown)
+ {
+ q.insert(n_);
+ continue;
+ }
+ unsigned d_ = math::diff_abs(med(p_), med(n_));
+ if (d_ < d)
+ {
+ d = d_;
+ id = out(n_);
+ }
+ }
+ if (d == 256)
+ std::cerr << "oops! (2)" << std::endl;
+
+ out(p_) = id; // object or background.
+ }
+
+ if (echo)
+ {
+ io::pgm::save(level::transform(ws, out.function()),
+ "temp_out_2.pgm");
+ }
+
+ io::pbm::save((pw::value(level::transform(ws,
+ out.function())) == pw::cst(255))
+ | input.domain(),
+ argv[4]);
+}
Index: icdar/2009/dibco/svg.3.binarization.cc
--- icdar/2009/dibco/svg.3.binarization.cc (revision 0)
+++ icdar/2009/dibco/svg.3.binarization.cc (revision 0)
@@ -0,0 +1,858 @@
+#include <mln/core/var.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/alias/neighb1d.hh>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/make/double_neighb2d.hh>
+
+#include <mln/pw/all.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/core/site_set/p_queue.hh>
+
+#include <mln/core/routine/extend.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/data/fill.hh>
+
+#include <mln/core/site_set/p_edges.hh>
+#include <mln/core/site_set/p_vertices.hh>
+#include <mln/core/image/graph_elt_neighborhood.hh>
+
+#include <mln/io/essential.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/label_16.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/literal/colors.hh>
+
+#include <mln/histo/compute.hh>
+
+#include <mln/morpho/erosion.hh>
+#include <mln/morpho/dilation.hh>
+#include <mln/morpho/elementary/gradient_internal.hh>
+#include <mln/morpho/closing/volume.hh>
+#include <mln/morpho/closing/height.hh>
+#include <mln/morpho/watershed/flooding.hh>
+
+#include <mln/make/rag_and_labeled_wsl.hh>
+#include <mln/util/graph.hh>
+#include <mln/util/couple.hh>
+#include <mln/debug/colorize.hh>
+#include <mln/fun/i2v/array.hh>
+
+#include <mln/labeling/compute.hh>
+#include <mln/labeling/regional_minima.hh>
+#include <mln/labeling/wrap.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/convert.hh>
+
+#include <mln/linear/gaussian_1d.hh>
+
+#include <mln/accu/center.hh>
+#include <mln/accu/median_h.hh>
+#include <mln/accu/mean.hh>
+
+#include <mln/math/abs.hh>
+#include <mln/debug/draw_graph.hh>
+
+
+
+
+
+namespace mln
+{
+
+ struct edge_values : Function_vv2v<edge_values>
+ {
+ typedef value::int_u8 result;
+ typedef void mutable_result;
+
+ value::int_u8 operator()(const value::int_u8& v1,
+ const value::int_u8& v2) const
+ { return math::abs(v1 - v2); }
+
+ };
+
+
+ template <typename I, typename V>
+ class edge_to_color : public Function_p2v< edge_to_color<I,V> >
+ {
+ public:
+ typedef V result;
+
+ edge_to_color(const I& ima_e) : ima_e_(ima_e)
+ {}
+
+ V
+ operator()(const unsigned& e) const
+ { return convert::to<V>(ima_e_.function()(e)); }
+
+ private:
+ const I& ima_e_;
+ };
+
+
+ namespace make
+ {
+
+ template <typename G, typename P>
+ p_edges<G,pw::cst_<P> >
+ dummy_pedges(const Graph<G>& g_, const P& dummy_value)
+ {
+ trace::entering("dummy_pedges");
+
+ const G& g = exact(g_);
+ mln_precondition(g.is_valid());
+ p_edges<G,pw::cst_<P> > pe(g, pw::cst(dummy_value));
+
+ trace::exiting("dummy_pedges");
+ return pe;
+ }
+
+ template <typename FVV, typename G, typename V2P, typename E2P, typename FVE>
+ pw::image<fun::i2v::array<mln_result(FVE)>,p_edges<G,E2P> >
+ edge_image(const pw::image<FVV,p_vertices<G,V2P> >& vertex_image,
+ const p_edges<G,E2P>& pe,
+ const Function_vv2v<FVE>& edge_value_)
+ {
+ trace::entering("edge_image");
+
+ const FVE& edge_value = exact(edge_value_);
+ mln_precondition(vertex_image.is_valid());
+ mln_precondition(pe.is_valid());
+
+ typedef fun::i2v::array<mln_result(FVE)> edge_values_t;
+ edge_values_t edge_values(pe.nsites());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, p_edges<G,E2P> > ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e)
+ ima_e(e) = edge_value(vertex_image.function()(e.element().v1()),
+ vertex_image.function()(e.element().v2()));
+
+ trace::exiting("edge_image");
+ return ima_e;
+ }
+
+
+ template <typename W, typename G>
+ inline
+ p_vertices<util::graph, fun::i2v::array<mln_site(W)> >
+ common_pvertices(const Image<W>& wst, const mln_value(W)& nbasins,
+ const Graph<G>& g_)
+ {
+ trace::entering("common_pvertices");
+
+ const G& g = exact(g_);
+ mln_precondition(g.is_valid());
+
+ typedef fun::i2v::array<mln_site(W)> vertex_sites_t;
+ vertex_sites_t vertex_sites;
+ convert::from_to(labeling::compute(accu::center<mln_site(W)>(), wst, nbasins),
+ vertex_sites);
+
+ p_vertices<util::graph, vertex_sites_t> pv(g, vertex_sites);
+
+ trace::exiting("common_pvertices");
+ return pv;
+ }
+
+
+ template <typename A, typename G, typename F, typename I, typename W>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<G,F> >
+ vertex_image(const Accumulator<A>& accu,
+ const p_vertices<G,F>& pv,
+ const Image<I>& input_,
+ const Image<W>& wst_,
+ const mln_value(W)& nbasins)
+ {
+ trace::entering("vertex_image");
+
+ const I& input = exact(input_);
+ const W& wst = exact(wst_);
+ mln_precondition(input.is_valid());
+ mln_precondition(wst.is_valid());
+ mln_precondition(pv.is_valid());
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(labeling::compute(accu, input, wst, nbasins),
+ vertex_values);
+
+ pw::image<fun::i2v::array<mln_value(I)>,
+ p_vertices<util::graph, fun::i2v::array<mln_site(I)> > >
+ ima_vertex = vertex_values | pv;
+
+ trace::exiting("vertex_image");
+ return ima_vertex;
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ mln_concrete(I)
+ debug_graph_image(const Image<I>& input_,
+ const Image<V>& ima_v_, const Image<E>& ima_e_,
+ unsigned box_size, const mln_value(I)& bg)
+ {
+ trace::entering("debug_graph_image");
+
+ const I& input = exact(input_);
+ const V& ima_v = exact(ima_v_);
+ const E& ima_e = exact(ima_e_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(ima_v.is_valid());
+ mln_precondition(ima_e.is_valid());
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ data::fill(output, bg);
+ debug::draw_graph(output, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box<mln_site(I)> b(p + tl, p + br);
+ b.crop_wrt(output.domain());
+ data::fill((output | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ trace::exiting("debug_graph_image");
+ return output;
+ }
+
+ } // end of namespace mln::make
+
+ int
+ find_threshold(const histo::array<value::int_u8>& h)
+ {
+
+ const float sigma = 5; // FIXME: hard-coded!
+
+ util::array<point1d> c;
+ value::label_8 n;
+
+ {
+ image1d<unsigned> h_, hs_;
+ image1d<value::label_8> l;
+
+ convert::from_to(h, h_);
+ hs_ = linear::gaussian_1d(h_, sigma, 0);
+ l = labeling::regional_minima(hs_, c2(), n);
+
+ {
+// debug::println("l", l);
+// debug::histo(h, "tmp_h.txt");
+
+// std::ofstream file("tmp_hs.txt");
+// mln_piter_(box1d) p(h_.domain());
+// for_all(p)
+// file << p.ind() << ' ' << hs_(p) << std::endl;
+// file.close();
+ }
+
+ accu::center<point1d, point1d> a;
+ c = labeling::compute(a, l, n);
+
+ c[0] = point1d(0); // Force a neutral value for the non-label value (0).
+
+ // std::cout << "c = " << c << std::endl;
+ }
+
+
+ int threshold;
+
+ {
+ std::vector<int> v;
+ for (unsigned i = 0; i <= n; ++i)
+ v.push_back(c[i].ind());
+ std::sort(v.begin(), v.end());
+
+ for (unsigned i = 0; i <= n; ++i)
+ if (v[i] != 0)
+ {
+ threshold = v[i];
+ break;
+ }
+
+ std::cout << "threshold = " << threshold << std::endl;
+ }
+
+ return threshold;
+ }
+
+
+ image2d<bool> contours(const image2d<value::int_u8>& f, unsigned& threshold)
+ {
+ using value::int_u8;
+ typedef int_u8 V;
+ histo::array<V> h;
+
+ image2d<int_u8> g;
+ g = morpho::elementary::gradient_internal(f, c4());
+ g = morpho::closing::height(g, c4(), 3); // FIXME: hard-coded!
+
+ unsigned nbasins;
+ image2d<unsigned> w = morpho::watershed::flooding(g, c4(), nbasins);
+
+ h = histo::compute(g | (pw::value(w) == pw::cst(0)));
+
+ threshold = find_threshold(h);
+
+ return duplicate((pw::value(g) > pw::cst(threshold)) | f.domain());
+ }
+
+
+ // Distances.
+
+ value::int_u8 dist(const value::int_u8& g1, const value::int_u8& g2)
+ {
+ return math::diff_abs(g1, g2);
+ }
+
+ value::int_u8 dist(const value::rgb8& c1, const value::rgb8& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+ if (d_ > d)
+ d = d_;
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // Functions.
+
+ inline
+ bool is_row_odd(const point2d& p)
+ {
+ return p.row() % 2;
+ }
+
+ inline
+ bool is_square(const point2d& p)
+ {
+ return p.row() % 2 == 0 && p.col() % 2 == 0;
+ }
+
+ inline
+ bool is_edge(const point2d& p)
+ {
+ return p.row() % 2 + p.col() % 2 == 1;
+ }
+
+ inline
+ bool is_point(const point2d& p)
+ {
+ return p.row() % 2 && p.col() % 2;
+ }
+
+
+ // Neighborhoods.
+
+ typedef neighb< win::multiple<window2d, bool(*)(const point2d&)> > dbl_neighb2d;
+
+ const dbl_neighb2d& e2c()
+ {
+ static bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ static bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+ static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2c_h, e2c_v);
+ return nbh;
+ }
+
+ const dbl_neighb2d& e2e()
+ {
+ static 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 };
+ static 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 };
+ static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2e_h, e2e_v);
+ return nbh;
+ }
+
+
+ // Transforms.
+
+ template <typename T>
+ image2d<T>
+ image2full(const image2d<T>& input)
+ {
+ 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)
+ opt::at(output, 2 * row, 2 * col) = opt::at(input, row, col);
+ return output;
+ }
+
+ template <typename T>
+ image2d<T>
+ full2image(const image2d<T>& input)
+ {
+ 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)
+ opt::at(output, row / 2, col / 2) =
+ opt::at(input, row, col);
+ return output;
+ }
+
+
+ // Display.
+
+ 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;
+ }
+
+
+
+ // Distance, stored on edges, of a couple of colors.
+
+ template <typename I, typename N>
+ image2d<value::int_u8>
+ dist_on_edges(const I& input, const N& nbh)
+ {
+ image2d<value::int_u8> output;
+ initialize(output, input);
+ data::fill(output, 0);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ n.start();
+ mln_value(I) c1 = input(n);
+ n.next();
+ mln_value(I) c2 = input(n);
+ output(p) = dist(c1, c2);
+ }
+
+ // io::pgm::save(output, "temp_dist.pgm");
+
+ return output;
+ }
+
+
+ value::int_u8 L_to_int_u8(unsigned l)
+ {
+ return l == 0 ?
+ 0 : // wshed line
+ 1 + (l - 1) % 255; // basin
+ }
+
+
+
+ // Quasi-Regional Minima Labeling.
+
+ template <typename I>
+ struct quasi_regional_minima_functor
+ {
+ typedef mln_psite(I) P;
+
+ const I& input;
+ unsigned threshold;
+
+ void init()
+ {
+ data::fill(attr, true);
+ }
+
+ bool handles(const P&) const { return true; }
+ bool labels(const P& p) const { return attr(p); }
+
+ bool equiv(const P& n, const P& p) const
+ {
+ if (attr(p) == false)
+ return false;
+
+ mln_invariant(input(n) <= input(p));
+ if (input(n) > input(p))
+ std::cout << "oups!" << std::endl;
+
+ std::cout << "UNION: n=" << n << " [" << input(n)
+ << "] p=" << p << " [" << input(p)
+ << "] equiv=" << (input(p) < input(n) + threshold)
+ << " " << threshold
+ << std::endl;
+
+// return input(p) == input(n);
+ return input(p) < input(n) + threshold;
+ }
+
+ void do_no_union(const P& n, const P& p)
+ {
+ if (input(n) > input(p))
+ std::cout << "oups!" << std::endl;
+
+ if (input(p) < input(n) + threshold)
+ std::cout << "oups!" << std::endl;
+
+ mln_invariant(input(p) >= input(n) + threshold);
+ (void)n;
+ attr(p) = false;
+
+ std::cout << "INVALID: n=" << n << " (" << input(n)
+ << ") p=" << p << " (" << input(p)
+ << std::endl;
+
+ }
+
+ void init_attr(const P&)
+ {}
+
+ void merge_attr(const P& r, const P& p)
+ {
+ attr(p) = attr(p) && attr(r);
+ }
+
+ mln_ch_value(I, bool) attr;
+
+ quasi_regional_minima_functor(const I& input, unsigned threshold)
+ : input(input),
+ threshold(threshold)
+ {
+ initialize(attr, input);
+ }
+ };
+
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ labeling__quasi_regional_minima(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ unsigned threshold,
+ L& nlabels)
+ {
+ trace::entering("labeling__quasi_regional_minima");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(input.is_valid());
+
+ // FIXME: abort if L is not wide enough to encode the set of
+ // minima.
+
+ typedef quasi_regional_minima_functor<I> F;
+ F f(exact(input), threshold);
+ mln_ch_value(I, L) output = canvas::labeling_sorted(input, nbh, nlabels,
+ f, false);
+
+ trace::exiting("labeling__quasi_regional_minima");
+ return output;
+ }
+
+
+} // end of namespace mln
+
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using namespace value;
+
+ // trace::quiet = false;
+
+ if (argc != 5)
+ {
+ std::cout << argv[0] << " input.pgm lambda echo output.pbm" << std::endl;
+ return 1;
+ }
+
+ int lambda_grad = std::atoi(argv[2]);
+ int echo = std::atoi(argv[3]);
+
+
+ if (echo != 0 && echo != 1)
+ {
+ std::cout << argv[0] << " input.pgm lambda echo output.pbm" << std::endl;
+ return 1;
+ }
+
+
+ image2d<int_u8> input;
+ io::pgm::load(input, argv[1]);
+
+ image2d<int_u8> input_ = image2full(input); // Larger to make room to edges.
+
+ image2d<int_u8> grad_;
+ {
+ grad_ = dist_on_edges(extend(input_ | is_edge, pw::value(input_)),
+ e2c());
+ }
+
+ // io::pgm::save(grad_, "grad_.pgm");
+
+ mln_VAR(grad, grad_ | is_edge);
+ typedef grad_t E;
+
+ grad = morpho::closing::volume(grad,
+ e2e(),
+ lambda_grad);
+
+ // io::pgm::save(grad.unmorph_(), "grad.pgm");
+
+ typedef label_16 L; // Label type.
+
+ L nbasins;
+
+ typedef mln_ch_value_(E, L) EL;
+
+ EL wst = morpho::watershed::flooding(grad,
+ e2e(),
+ nbasins);
+
+ std::cout << "n basins = " << nbasins << std::endl;
+
+
+ if (echo)
+ {
+ io::ppm::save(display_edge(debug::colorize(rgb8(),
+ wst,
+ nbasins).unmorph_(),
+ literal::black,
+ 3),
+ "temp_wst_edges.ppm");
+ }
+
+
+ image2d<L> w_all = wst.unmorph_();
+
+ // edges -> squares
+ mln_VAR(w_squares, w_all | is_square);
+ data::paste(morpho::dilation(extend(w_squares, pw::value(w_all)),
+ c4().win()),
+ w_all);
+ // edges -> points
+ mln_VAR(w_points, w_all | is_point);
+ data::paste(morpho::erosion(extend(w_points, pw::value(w_all)),
+ c4().win()),
+ w_all);
+
+ image2d<L> ws = full2image(w_all);
+
+ if (echo)
+ {
+ io::ppm::save(debug::colorize(rgb8(), ws, nbasins),
+ "temp_ws.ppm");
+ }
+
+ util::couple<util::graph, image2d<L> >
+ rag_data = make::rag_and_labeled_wsl(w_all, c8(), nbasins);
+
+ if (echo)
+ io::pgm::save(labeling::wrap(int_u8(),
+ rag_data.second()),
+ "temp_lwsl.pgm");
+
+
+ unsigned threshold;
+ contours(input, threshold);
+
+
+ typedef accu::median_h<int_u8> A;
+ typedef fun::i2v::array<point2d> F;
+
+
+ util::array<int_u8> basin_med = labeling::compute(A(), input, ws, nbasins);
+ basin_med[0] = 0;
+
+
+
+ if (echo)
+ io::ppm::save(debug::colorize(rgb8(), w_all, nbasins),
+ "temp_w_all.ppm");
+
+
+
+ // ----------------------------- R A G --------------------------------
+
+
+ util::graph& gr = rag_data.first();
+
+ fun::i2v::array<int_u8> f_med;
+ convert::from_to(basin_med, f_med);
+
+ if (echo)
+ {
+ io::pgm::save(level::transform(w_all, f_med),
+ "temp_w_all.pgm");
+ io::pgm::save(level::transform(ws, f_med), "temp_basin_med.pgm");
+ }
+
+ p_vertices<util::graph, fun::i2v::array<point2d> >
+ pv = make::common_pvertices(ws, nbasins, rag_data.first());
+
+ mln_VAR( med, f_med | pv );
+
+
+ typedef graph_elt_neighborhood<util::graph, F> N;
+ N nbh;
+
+ threshold = 25; // FIXME
+
+ L n_objects;
+ mln_VAR( lab, labeling__quasi_regional_minima(med, nbh, threshold, n_objects) );
+
+
+ io::pbm::save((pw::value(level::transform(ws,
+ lab.function())) != pw::cst(0))
+ | input.domain(),
+ argv[4]);
+
+
+ /*
+
+ int_u8
+ object = 255,
+ background = 0,
+ unknown = 128;
+
+ med_t out;
+ initialize(out, med);
+ data::fill(out, unknown);
+
+ // Initialization.
+
+ mln_piter_(med_t) p(med.domain());
+ mln_niter_(N) n(nbh, p);
+ for_all(p)
+ for_all(n)
+ {
+ int d = math::diff_abs(med(p), med(n));
+ // if (2 * d > 3 * threshold)
+ if (d > threshold)
+ {
+ if (med(p) < med(n))
+ {
+ out(p) = object;
+ out(n) = background;
+ }
+ else
+ {
+ out(n) = object;
+ out(p) = background;
+ }
+ break;
+ }
+ }
+
+ if (echo)
+ {
+ io::pgm::save(level::transform(ws, out.function()),
+ "temp_out.pgm");
+ }
+
+
+ // Enqueuing.
+
+ typedef mln_psite_(med_t) P;
+ p_queue<P> q;
+
+ for_all(p)
+ {
+ if (out(p) != unknown)
+ continue;
+ for_all(n)
+ if (out(n) != unknown)
+ {
+ q.insert(p);
+ break;
+ }
+ }
+
+ // Propagation.
+
+ P p_;
+ mln_niter_(N) n_(nbh, p_);
+ while (! q.is_empty())
+ {
+ p_ = q.pop_front();
+
+ if (out(p_) != unknown)
+ continue; // std::cerr << "oops! (1)" << std::endl;
+
+ unsigned d = 256, id;
+ for_all(n_)
+ {
+ if (out(n_) == unknown)
+ {
+ q.insert(n_);
+ continue;
+ }
+ unsigned d_ = math::diff_abs(med(p_), med(n_));
+ if (d_ < d)
+ {
+ d = d_;
+ id = out(n_);
+ }
+ }
+ if (d == 256)
+ std::cerr << "oops! (2)" << std::endl;
+
+ out(p_) = id; // object or background.
+ }
+
+ if (echo)
+ {
+ io::pgm::save(level::transform(ws, out.function()),
+ "temp_out_2.pgm");
+ }
+
+ io::pbm::save((pw::value(level::transform(ws,
+ out.function())) == pw::cst(255))
+ | input.domain(),
+ argv[4]);
+
+ */
+
+}
Property changes on: icdar/2009/dibco/binarization.cc
___________________________________________________________________
Added: svn:mergeinfo
Property changes on: icdar/2009/hsc/first_attempts/fuzzy.sh
___________________________________________________________________
Added: svn:mergeinfo
Property changes on: icdar/2009/hsc/first_attempts/reduce.sh
___________________________________________________________________
Added: svn:mergeinfo
Property changes on: icdar/2009/hsc/first_attempts/boxes.cc
___________________________________________________________________
Added: svn:mergeinfo
Property changes on: icdar/2009/hsc/first_attempts/words.sh
___________________________________________________________________
Added: svn:mergeinfo
Property changes on: icdar/2009/hsc/first_attempts/main.cc
___________________________________________________________________
Added: svn:mergeinfo
Property changes on: icdar/2009/hsc/first_attempts/dist.sh
___________________________________________________________________
Added: svn:mergeinfo
Index: icdar/2009/README
--- icdar/2009/README (revision 0)
+++ icdar/2009/README (revision 0)
@@ -0,0 +1,13 @@
+ -*- outline -*-
+
+* hsc
+Handwriting Segmentation Contest
+http://www.iit.demokritos.gr/~bgat/HandSegmCont2009/index.html
+
+* dibco
+Document Image Binarization Contest
+http://www.iit.demokritos.gr/~bgat/DIBCO2009/
+
+* pscomp
+Page Segmentation Competition
+http://www.cse.salford.ac.uk/prima/ICDAR2009_pscomp/
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
New exe source files dedicated to color images.
* theo/exec/color_labeling_mean.cc: New.
* theo/exec/color_internal_gradient.cc: New.
* theo/color/filter_rgb_pixels.cc: Rename as...
* theo/color/filter_meandist_rgb_pixels.cc: ...this.
* folio/test/histo/classify_with_histo_rgb.cc
(main): Use dilation to get rid of watershed line.
Add 3rd arg to set output file and fix usage.
* folio/mln/histo/classify_with_histo_rgb.hh: Remove blank line.
folio/mln/histo/classify_with_histo_rgb.hh | 1
folio/test/histo/classify_with_histo_rgb.cc | 16 +--
theo/exec/color_internal_gradient.cc | 148 ++++++++++++++++++++++++++++
theo/exec/color_labeling_mean.cc | 49 +++++++++
4 files changed, 206 insertions(+), 8 deletions(-)
Index: theo/exec/color_labeling_mean.cc
--- theo/exec/color_labeling_mean.cc (revision 0)
+++ theo/exec/color_labeling_mean.cc (revision 0)
@@ -0,0 +1,49 @@
+#include <mln/core/image/image2d.hh>
+
+#include <mln/estim/min_max.hh>
+#include <mln/labeling/compute.hh>
+#include <mln/accu/mean.hh>
+#include <mln/level/transform.hh>
+
+#include <mln/value/label_8.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/ppm/save.hh>
+
+
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::label_8;
+ using value::rgb8;
+
+ image2d<int_u8> lab;
+ io::pgm::load(lab, argv[1]);
+
+ int_u8 min, nlabels;
+ estim::min_max(lab, min, nlabels);
+
+ std::cout << min << ' ' << nlabels << std::endl;
+
+ image2d<rgb8> ima;
+ io::ppm::load(ima, argv[2]);
+
+ accu::mean<rgb8> m_;
+ typedef algebra::vec<3,float> V;
+ util::array<V> m = labeling::compute(m_, ima, lab, nlabels);
+
+ util::array<rgb8> c(nlabels + 1);
+ for (unsigned l = 0; l <= nlabels; ++l)
+ {
+ c[l].red() = m[l][0];
+ c[l].green() = m[l][1];
+ c[l].blue() = m[l][2];
+ }
+
+ io::ppm::save(level::transform(lab, c), argv[3]);
+}
Index: theo/exec/color_internal_gradient.cc
--- theo/exec/color_internal_gradient.cc (revision 0)
+++ theo/exec/color_internal_gradient.cc (revision 0)
@@ -0,0 +1,148 @@
+#include "filetype.hh"
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/elementary/gradient_internal.hh>
+#include <mln/math/diff_abs.hh>
+
+#include <mln/accu/image/init.hh>
+#include <mln/accu/image/take.hh>
+#include <mln/accu/image/to_result.hh>
+
+#include <mln/accu/max.hh>
+
+
+
+namespace mln
+{
+
+ value::int_u8
+ dist(const value::rgb8& c1,
+ const value::rgb8& c2)
+ {
+ unsigned d = 0;
+ d += math::diff_abs(c1.red(), c2.red());
+ d += math::diff_abs(c1.green(), c2.green());
+ d += math::diff_abs(c1.blue(), c2.blue());
+ if (d > 255)
+ d = 255;
+ return d;
+ }
+
+ template <typename N>
+ image2d<value::int_u8>
+ color_gradient(const image2d<value::rgb8>& input,
+ const N& nbh)
+ {
+ using value::int_u8;
+ image2d<int_u8> output(input.domain());
+
+ mln_piter(box2d) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ int_u8 d = 0u;
+ for_all(n) if (input.domain().has(n))
+ {
+ int_u8 d_ = dist(input(p), input(n));
+ if (d_ > d)
+ d = d_;
+ }
+ output(p) = d;
+ }
+
+ return output;
+ }
+
+
+
+ template <typename I>
+ image2d<value::int_u8>
+ get_red(const I& input)
+ {
+ typedef image2d<value::int_u8> J;
+ J output(input.domain());
+
+ mln_pixter(const I) p_in(input);
+ mln_pixter(J) p_out(output);
+ for_all_2(p_in, p_out)
+ p_out.val() = p_in.val().red();
+ return output;
+ }
+
+ template <typename I>
+ image2d<value::int_u8>
+ get_green(const I& input)
+ {
+ typedef image2d<value::int_u8> J;
+ J output(input.domain());
+
+ mln_pixter(const I) p_in(input);
+ mln_pixter(J) p_out(output);
+ for_all_2(p_in, p_out)
+ p_out.val() = p_in.val().green();
+ return output;
+ }
+
+ template <typename I>
+ image2d<value::int_u8>
+ get_blue(const I& input)
+ {
+ typedef image2d<value::int_u8> J;
+ J output(input.domain());
+
+ mln_pixter(const I) p_in(input);
+ mln_pixter(J) p_out(output);
+ for_all_2(p_in, p_out)
+ p_out.val() = p_in.val().blue();
+ return output;
+ }
+
+
+} // mln
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.ppm output.pgm" << std::endl
+ << " Color gradient." << std::endl;
+ std::abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::rgb8;
+ using value::int_u8;
+
+ if (argc != 3)
+ usage(argv);
+
+ trace::entering("main");
+
+ image2d<rgb8> ima;
+ io::ppm::load(ima, argv[1]);
+
+ typedef accu::max<int_u8> A;
+ image2d<A> grad(ima.domain());
+
+ using morpho::elementary::gradient_internal;
+
+ accu::image::init(grad);
+
+ accu::image::take(grad,
+ gradient_internal(get_red(ima),
+ c4()));
+ accu::image::take(grad,
+ gradient_internal(get_green(ima),
+ c4()));
+ accu::image::take(grad,
+ gradient_internal(get_blue(ima),
+ c4()));
+
+ io::pgm::save(accu::image::to_result(grad),
+ argv[2]);
+
+ trace::exiting("main");
+}
Property changes on: theo/color/filter_meandist_rgb_pixels.cc
___________________________________________________________________
Added: svn:mergeinfo
Index: folio/test/histo/classify_with_histo_rgb.cc
--- folio/test/histo/classify_with_histo_rgb.cc (revision 3676)
+++ folio/test/histo/classify_with_histo_rgb.cc (working copy)
@@ -15,9 +15,11 @@
#include <mln/arith/revert.hh>
#include <mln/core/alias/neighb3d.hh>
-#include <mln/morpho/closing/volume.hh>
#include <mln/value/label_8.hh>
+
+#include <mln/morpho/closing/volume.hh>
#include <mln/morpho/watershed/flooding.hh>
+#include <mln/morpho/elementary/dilation.hh>
#include "../../mln/histo/compute_histo_rgb.hh"
#include "../../mln/histo/classify_with_histo_rgb.hh"
@@ -42,10 +44,10 @@
using namespace mln;
// check arguments
- if (argc < 3)
+ if (argc != 4)
{
std::cerr << "Usage:" << std::endl
- << " ./a.out ../../../../lena.ppm 51" << std::endl
+ << " ./a.out ../../../../lena.ppm 51 out.pgm" << std::endl
<< std::endl
<< "BTW, the number is the closure's lambda." << std::endl;
exit(1);
@@ -79,11 +81,11 @@
image3d<value::label_8> labels = morpho::watershed::flooding(closed, c6(), nbasin);
std::cout << "found " << nbasin << " labels" << std::endl;
+ labels = morpho::elementary::dilation(labels, c18());
+
std::cout << " => computing output labelized image..." << std::endl;
image2d<value::label_8> out = histo::classify_with_histo_rgb(ima, labels);
- std::cout << " => saving out.ppm..." << std::endl;
- io::pgm::save(out, "out.ppm");
-
- return 0;
+ std::cout << " => saving " << argv[3] << "..." << std::endl;
+ io::pgm::save(out, argv[3]);
}
Index: folio/mln/histo/classify_with_histo_rgb.hh
--- folio/mln/histo/classify_with_histo_rgb.hh (revision 3676)
+++ folio/mln/histo/classify_with_histo_rgb.hh (working copy)
@@ -26,7 +26,6 @@
{
// get 3d point in regions image.
point3d p3 = point3d(ref(p).red(), ref(p).green(), ref(p).blue());
-
out(p) = regions(p3); // copy the label in out's pixel.
}
1
0
* mln/accu/label_used.hh: add missing includes.
* mln/canvas/browsing/depth_first_search.hh,
* mln/io/pgm/save.hh: add preconditions.
* mln/make/influence_zone_adjacency_graph.hh: rename the routine in
order to have the same name as the file name.
* mln/make/rag_and_labeled_wsl.hh: Add more doc.
* mln/value/lut_vec.hh: add a constructor overload for util::array
which is now considered as a function.
* tests/make/Makefile.am: update test name entry for
influence_zone_adjacency_graph.
* tests/morpho/attribute/sum.cc,
* tests/morpho/line_graph_image_wst.cc: avoid warnings.
---
milena/ChangeLog | 23 ++++++++++
milena/mln/accu/label_used.hh | 1 +
milena/mln/canvas/browsing/depth_first_search.hh | 1 +
milena/mln/io/pgm/save.hh | 3 +
milena/mln/make/influence_zone_adjacency_graph.hh | 49 +++++++++++---------
milena/mln/make/rag_and_labeled_wsl.hh | 47 +++++++++++---------
milena/mln/value/lut_vec.hh | 26 ++++++++++-
milena/tests/make/Makefile.am | 5 +-
milena/tests/morpho/attribute/sum.cc | 2 +-
milena/tests/morpho/line_graph_image_wst.cc | 4 +-
10 files changed, 111 insertions(+), 50 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 06dba5b..6117e06 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,28 @@
2009-04-15 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+ Small fixes.
+
+ * mln/accu/label_used.hh: add missing includes.
+
+ * mln/canvas/browsing/depth_first_search.hh,
+ * mln/io/pgm/save.hh: add preconditions.
+
+ * mln/make/influence_zone_adjacency_graph.hh: rename the routine in
+ order to have the same name as the file name.
+
+ * mln/make/rag_and_labeled_wsl.hh: Add more doc.
+
+ * mln/value/lut_vec.hh: add a constructor overload for util::array
+ which is now considered as a function.
+
+ * tests/make/Makefile.am: update test name entry for
+ influence_zone_adjacency_graph.
+
+ * tests/morpho/attribute/sum.cc,
+ * tests/morpho/line_graph_image_wst.cc: avoid warnings.
+
+2009-04-15 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
Add a routine to generate formatted debug filenames.
* mln/debug/filename.hh: new routine.
diff --git a/milena/mln/accu/label_used.hh b/milena/mln/accu/label_used.hh
index 6323d3e..fe3553f 100644
--- a/milena/mln/accu/label_used.hh
+++ b/milena/mln/accu/label_used.hh
@@ -36,6 +36,7 @@
# include <mln/accu/internal/base.hh>
# include <mln/core/concept/meta_accumulator.hh>
# include <mln/math/max.hh>
+# include <mln/fun/i2v/array.hh>
namespace mln
diff --git a/milena/mln/canvas/browsing/depth_first_search.hh b/milena/mln/canvas/browsing/depth_first_search.hh
index 2880397..818e44b 100644
--- a/milena/mln/canvas/browsing/depth_first_search.hh
+++ b/milena/mln/canvas/browsing/depth_first_search.hh
@@ -101,6 +101,7 @@ namespace mln
trace::entering("canvas::browsing::depth_first_search");
const G& g = exact(g_);
+ mln_precondition(g.is_valid());
f.init(g); // <--- init
diff --git a/milena/mln/io/pgm/save.hh b/milena/mln/io/pgm/save.hh
index 5e7df76..0137580 100644
--- a/milena/mln/io/pgm/save.hh
+++ b/milena/mln/io/pgm/save.hh
@@ -82,6 +82,9 @@ namespace mln
// FIXME: Is it exhaustive?
mlc_is_not_a(mln_value(I), value::Vectorial)::check();
mlc_converts_to(mln_value(I),unsigned)::check();
+ /// Make sure this is a low quantification value type
+ /// (mln_card returns 0 if it is not)
+ metal::bool_<mln_card(mln_value(I)) != 0>::check();
trace::entering("mln::io::pgm::save");
io::pnm::save(PGM, exact(ima), filename);
diff --git a/milena/mln/make/influence_zone_adjacency_graph.hh b/milena/mln/make/influence_zone_adjacency_graph.hh
index 9c0f33e..7113962 100644
--- a/milena/mln/make/influence_zone_adjacency_graph.hh
+++ b/milena/mln/make/influence_zone_adjacency_graph.hh
@@ -26,10 +26,10 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_MAKE_GRAPH_HH
-# define MLN_MAKE_GRAPH_HH
+#ifndef MLN_MAKE_INFLUENCE_ZONE_ADJACENCY_GRAPH_HH
+# define MLN_MAKE_INFLUENCE_ZONE_ADJACENCY_GRAPH_HH
-/// \file mln/make/graph.hh
+/// \file mln/make/influence_zone_adjacency_graph.hh
///
/// Create a graph from an influence zone image.
///
@@ -59,8 +59,9 @@ namespace mln
/// \return util::graph Graph based on the adjacency of the influence zones.
template <typename I, typename N>
util::graph
- graph(const Image<I>& iz_, const Neighborhood<N>& nbh,
- mln_value(I) nlabels);
+ influence_zone_adjacency_graph(const Image<I>& iz_,
+ const Neighborhood<N>& nbh,
+ mln_value(I) nlabels);
@@ -72,8 +73,9 @@ namespace mln
template <typename I, typename N>
void
- graph_tests(const Image<I>& iz, const Neighborhood<N>& nbh,
- mln_value(I))
+ influence_zone_adjacency_graph_tests(const Image<I>& iz,
+ const Neighborhood<N>& nbh,
+ mln_value(I))
{
mln_precondition(exact(iz).is_valid());
mln_precondition(exact(nbh).is_valid());
@@ -92,12 +94,13 @@ namespace mln
template <typename I, typename N>
util::graph
- graph(const Image<I>& iz_, const Neighborhood<N>& nbh_,
- mln_value(I) nlabels)
+ influence_zone_adjacency_graph(const Image<I>& iz_,
+ const Neighborhood<N>& nbh_,
+ mln_value(I) nlabels)
{
- trace::entering("make::impl::generic::graph");
+ trace::entering("make::impl::generic::influence_zone_adjacency_graph");
- internal::graph_tests(iz_, nbh_, nlabels);
+ internal::influence_zone_adjacency_graph_tests(iz_, nbh_, nlabels);
const I& iz = exact(iz_);
const N& nbh = exact(nbh_);
@@ -136,7 +139,7 @@ namespace mln
if (adj(point2d(i,j)))
g.add_edge(i, j);
- trace::exiting("make::impl::generic::graph");
+ trace::exiting("make::impl::generic::influence_zone_adjacency_graph");
return g;
}
@@ -151,10 +154,11 @@ namespace mln
template <typename I, typename N>
util::graph
- graph_dispatch(const Image<I>& iz, const Neighborhood<N>& nbh,
- mln_value(I) nlabels)
+ influence_zone_adjacency_graph_dispatch(const Image<I>& iz,
+ const Neighborhood<N>& nbh,
+ mln_value(I) nlabels)
{
- return make::impl::generic::graph(iz, nbh, nlabels);
+ return make::impl::generic::influence_zone_adjacency_graph(iz, nbh, nlabels);
}
} // end of namespace mln::make::internal
@@ -166,16 +170,17 @@ namespace mln
template <typename I, typename N>
inline
util::graph
- graph(const Image<I>& iz, const Neighborhood<N>& nbh,
- mln_value(I) nlabels)
+ influence_zone_adjacency_graph(const Image<I>& iz,
+ const Neighborhood<N>& nbh,
+ mln_value(I) nlabels)
{
- trace::entering("make::graph");
+ trace::entering("make::influence_zone_adjacency_graph");
- internal::graph_tests(iz, nbh, nlabels);
+ internal::influence_zone_adjacency_graph_tests(iz, nbh, nlabels);
- util::graph g = internal::graph_dispatch(iz, nbh, nlabels);
+ util::graph g = internal::influence_zone_adjacency_graph_dispatch(iz, nbh, nlabels);
- trace::exiting("make::graph");
+ trace::exiting("make::influence_zone_adjacency_graph");
return g;
}
@@ -188,4 +193,4 @@ namespace mln
} // end of namespace mln
-#endif // ! MLN_MAKE_GRAPH_HH
+#endif // ! MLN_MAKE_INFLUENCE_ZONE_ADJACENCY_GRAPH_HH
diff --git a/milena/mln/make/rag_and_labeled_wsl.hh b/milena/mln/make/rag_and_labeled_wsl.hh
index 7ace36f..1ad3705 100644
--- a/milena/mln/make/rag_and_labeled_wsl.hh
+++ b/milena/mln/make/rag_and_labeled_wsl.hh
@@ -65,27 +65,32 @@ namespace mln
/// image with a labeled watershed line.
/*!
**
- ** |-----------------| |-----------------| \n
- ** | 1 1 1 0 2 2 0 3 | | . . . 1 . . 2 . | \n
- ** | 1 1 0 2 2 2 0 3 | | . . 1 . . . 2 . | \n
- ** | 1 0 4 0 2 0 3 3 | ----> | . 1 . 3 . 4 . . | \n
- ** | 0 4 4 4 0 5 0 3 | | 1 . . . 5 . 6 . | \n
- ** |-----------------| |-----------------| \n
- ** \n
- ** Watershed image Labeled watershed line \n
- ** (watershed line labeled with 0) \n
- ** \n
- ** \n
- ** | \n
- ** | \n
- ** | \n
- ** v \n
- ** \n
- ** 1 -- 2 - 3 \n
- ** \ / / \n
- ** 4 -- 5 \n
- ** \n
- ** Region Adjacency graph (RAG) \n
+ ** \verbatim
+ **
+ ** |-----------------| |-----------------|
+ ** | 1 1 1 0 2 2 0 3 | | . . . 1 . . 2 . |
+ ** | 1 1 0 2 2 2 0 3 | | . . 1 . . . 2 . |
+ ** | 1 0 4 0 2 0 3 3 | ----> | . 1 . 3 . 4 . . |
+ ** | 0 4 4 4 0 5 0 3 | | 1 . . . 5 . 6 . |
+ ** |-----------------| |-----------------|
+ **
+ ** Watershed image Labeled watershed line
+ ** (watershed line labeled with 0)
+ **
+ **
+ ** |
+ ** |
+ ** |
+ ** v
+ **
+ ** 1 -- 2 - 3
+ ** \ / /
+ ** 4 -- 5
+ **
+ ** Region Adjacency graph (RAG)
+ **
+ ** \endverbatim
+ **
*/
template <typename I, typename N>
util::couple<util::graph,mln_concrete(I)>
diff --git a/milena/mln/value/lut_vec.hh b/milena/mln/value/lut_vec.hh
index 8c817a2..a88db43 100644
--- a/milena/mln/value/lut_vec.hh
+++ b/milena/mln/value/lut_vec.hh
@@ -51,6 +51,9 @@ namespace mln
template <typename T> class array;
} // end of namespace mln::fun::i2v
} // end of namespace mln::fun
+ namespace util{
+ template <typename T> class array;
+ } // end of namespace mln::util
namespace value
{
@@ -93,14 +96,21 @@ namespace mln
/// Give the index of value \p v in this set.
unsigned index_of(const value& v) const;
- /// Ctor. FIXME!
+ /// Constructors
+ /// @{
+ /// Constructor from a Site_set and any Function_v2v.
template <typename F>
lut_vec(const S& vset, const Function_v2v<F>& f);
- /// Ctor. FIXME!
+ /// Constructor from a Site_set and any fun::i2v::array.
template <typename V>
lut_vec(const S& vset, const Function_v2v< fun::i2v::array<V> >& f);
+ /// Constructor from a Site_set and any util::array.
+ template <typename V>
+ lut_vec(const S& vset, const Function_v2v< util::array<V> >& f);
+ /// @}
+
protected:
const S& vset_;
@@ -159,6 +169,18 @@ namespace mln
}
template <typename S, typename T>
+ template <typename V>
+ inline
+ lut_vec<S,T>::lut_vec(const S& vset, const Function_v2v< util::array<V> >& f)
+ : vset_(vset)
+ {
+ const util::array<V>& f_ = exact(f);
+ n_ = f_.size();
+ vec_ = f_.std_vector();
+ }
+
+
+ template <typename S, typename T>
inline
T
lut_vec<S,T>::operator()(const mln_value(S)& val) const
diff --git a/milena/tests/make/Makefile.am b/milena/tests/make/Makefile.am
index ba517cd..f83f95c 100644
--- a/milena/tests/make/Makefile.am
+++ b/milena/tests/make/Makefile.am
@@ -6,7 +6,7 @@ check_PROGRAMS = \
dual_neighb \
dummy_p_edges \
dummy_p_vertices \
- graph \
+ influence_zone_adjacency_graph \
h_mat \
image2d \
image3d \
@@ -18,10 +18,11 @@ check_PROGRAMS = \
w_window \
w_window_directional
+dual_neighb_SOURCES = dual_neighb.c
dual_neighb_SOURCES = dual_neighb.cc
dummy_p_edges_SOURCES = dummy_p_edges.cc
dummy_p_vertices_SOURCES = dummy_p_vertices.cc
-graph_SOURCES = graph.cc
+influence_zone_adjacency_graph_SOURCES = influence_zone_adjacency_graph.cc
h_mat_SOURCES = h_mat.cc
image2d_SOURCES = image2d.cc
image3d_SOURCES = image3d.cc
diff --git a/milena/tests/morpho/attribute/sum.cc b/milena/tests/morpho/attribute/sum.cc
index 330b10f..85a1d2e 100644
--- a/milena/tests/morpho/attribute/sum.cc
+++ b/milena/tests/morpho/attribute/sum.cc
@@ -49,5 +49,5 @@ int main()
s.take(px);
s.take(px);
s.take(px);
- mln_assertion(s == 51);
+ mln_assertion(s == 51u);
}
diff --git a/milena/tests/morpho/line_graph_image_wst.cc b/milena/tests/morpho/line_graph_image_wst.cc
index 6df2052..afc39ba 100644
--- a/milena/tests/morpho/line_graph_image_wst.cc
+++ b/milena/tests/morpho/line_graph_image_wst.cc
@@ -108,11 +108,11 @@ int main()
typedef fun::i2v::array<int> edge_values_t;
edge_values_t edge_values(10);
- static const int values[] = { 0, 10, 5, 2, 4, 6, 0, 3, 5, 2 };
+ static const unsigned values[] = { 0, 10, 5, 2, 4, 6, 0, 3, 5, 2 };
for (unsigned i = 0; i < edge_values.size(); ++i)
edge_values(i) = values[i];
- typedef vertex_image< P, int, util::line_graph<util::graph> > ima_t;
+ typedef vertex_image< P, unsigned, util::line_graph<util::graph> > ima_t;
ima_t ima(lg, sites, edge_values);
--
1.5.6.5
1
0
15 Apr '09
* mln/debug/filename.hh: new routine.
---
milena/ChangeLog | 6 ++
milena/mln/debug/filename.hh | 107 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 113 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/debug/filename.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index ef8857b..06dba5b 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,11 @@
2009-04-15 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+ Add a routine to generate formatted debug filenames.
+
+ * mln/debug/filename.hh: new routine.
+
+2009-04-15 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
Add graph::compute and few related functors.
* mln/canvas/browsing/depth_first_search.hh: update and add more doc.
diff --git a/milena/mln/debug/filename.hh b/milena/mln/debug/filename.hh
new file mode 100644
index 0000000..fe64adb
--- /dev/null
+++ b/milena/mln/debug/filename.hh
@@ -0,0 +1,107 @@
+// 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_DEBUG_FILENAME_HH
+# define MLN_DEBUG_FILENAME_HH
+
+/// \file mln/debug/filename.hh
+///
+/// Constructs and returns a formatted output file name.
+
+
+# include <string>
+# include <sstream>
+
+
+namespace mln
+{
+
+ namespace debug
+ {
+
+ /// Constructs and returns a formatted output file name.
+ /*!
+ ** The file name is formatted as follow:
+ **
+ ** `filename_prefix`_`id`_`filename`_`postfix_id`
+ **
+ ** Where:
+ ** - `filename_prefix` can be set through the global variable
+ ** debug::internal::filename_prefix.
+ ** - `id` is auto-incremented and cannot be controlled.
+ ** - `filename` is the given filename
+ ** - `postfix_id` is an optional counter which can be controlled contrary
+ ** to `id`.
+ */
+ std::string
+ filename(const std::string& filename, int postfix_id);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ std::string filename_prefix = "";
+
+ } // end of namespace scribo::make::internal
+
+
+ std::string
+ filename(const std::string& filename, int postfix_id = -1)
+ {
+ static int file_id = 1;
+
+ std::ostringstream os;
+
+ if (! internal::filename_prefix.empty())
+ os << internal::filename_prefix << "_";
+
+ if (file_id < 10)
+ os << "0";
+ if (file_id < 100)
+ os << "0";
+
+ os << file_id++
+ << "_"
+ << filename;
+
+ if (postfix_id >= 0)
+ os << "_" << postfix_id;
+
+ return os.str();
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::debug
+
+} // end of namespace mln
+
+#endif // ! MLN_DEBUG_FILENAME_HH
--
1.5.6.5
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-04-15 Warren Seine <soow(a)lrde.epita.fr>
inim: Initial commit for "boxes".
* .: New.
* Makefile: New. Stolen from Edwin.
* boxes.cc: New. Stolen from Theo.
* configure: New. Stolen from Edwin.
---
Makefile | 47 ++++++++++++++++++++++++++
boxes.cc | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
configure | 22 ++++++++++++
3 files changed, 178 insertions(+)
Index: trunk/milena/sandbox/inim/2010/boxes/configure
===================================================================
--- trunk/milena/sandbox/inim/2010/boxes/configure (revision 0)
+++ trunk/milena/sandbox/inim/2010/boxes/configure (revision 3674)
@@ -0,0 +1,22 @@
+#! /bin/bash
+
+for arg in "$@"; do
+ if [ "$arg" == "--debug" ]; then
+ debug=1;
+ elif [ "$arg" == "--release" ]; then
+ release=1;
+ elif [ "${arg#--mln-dir=}" ]; then
+ MLN_DIR=${arg#--mln-dir=}
+ fi
+done
+
+rm -f Makefile.rules
+touch Makefile.rules
+
+if [ "$debug" ]; then
+ echo 'DEBUG = 1' > Makefile.rules
+fi
+if [ "$release" ]; then
+ echo 'RELEASE = 1' > Makefile.rules
+fi
+echo "MLN_DIR = $MLN_DIR" > Makefile.rules
Property changes on: trunk/milena/sandbox/inim/2010/boxes/configure
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/inim/2010/boxes/boxes.cc
===================================================================
--- trunk/milena/sandbox/inim/2010/boxes/boxes.cc (revision 0)
+++ trunk/milena/sandbox/inim/2010/boxes/boxes.cc (revision 3674)
@@ -0,0 +1,109 @@
+// Copyright (C) 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 <iostream>
+
+#include <mln/essential/2d.hh>
+#include <mln/debug/colorize.hh>
+#include <mln/debug/println.hh>
+
+#include <scribo/text/extract_bboxes.hh>
+#include <scribo/text/grouping/group_with_single_left_link.hh>
+#include <scribo/text/grouping/group_with_single_right_link.hh>
+#include <scribo/debug/save_linked_textbboxes_image.hh>
+#include <scribo/text/grouping/group_from_double_link.hh>
+#include <scribo/filter/small_components.hh>
+
+#include <scribo/debug/save_textbboxes_image.hh>
+#include <scribo/make/debug_filename.hh>
+
+#include <mln/logical/not.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/io/pgm/save.hh>
+#include <mln/fun/l2l/wrap.hh>
+
+
+int usage(const char *name)
+{
+ std::cout << "Usage: " << name << " input.pbm output.dump" << std::endl;
+ return 1;
+}
+
+
+int main(int argc, char* argv[])
+{
+ using namespace scribo;
+ using namespace mln;
+
+ if (argc != 3)
+ return usage(argv[0]);
+
+ scribo::make::internal::debug_filename_prefix = "extract_text_double_link";
+
+ image2d<bool> input;
+ io::pbm::load(input, argv[1]);
+
+ logical::not_inplace(input);
+
+ value::label_16 nbboxes;
+ scribo::util::text<image2d<value::label_16> >
+ text = text::extract_bboxes(input, c8(), nbboxes);
+
+ text = filter::small_components(text,4);
+
+ mln::util::array<unsigned>
+ left_link = text::grouping::group_with_single_left_link(text, 30),
+ right_link = text::grouping::group_with_single_right_link(text, 30);
+
+ std::cout << "BEFORE - nbboxes = " << nbboxes << std::endl;
+
+
+ scribo::debug::save_linked_textbboxes_image(input,
+ text, left_link, right_link,
+ literal::red, literal::cyan, literal::yellow,
+ literal::green,
+ scribo::make::debug_filename("links.ppm"));
+
+ // Validation.
+ scribo::util::text<image2d<value::label_16> > grouped_text
+ = text::grouping::group_from_double_link(text, left_link, right_link);
+
+ std::cout << "AFTER double grouping - nbboxes = " << grouped_text.bboxes().nelements() << std::endl;
+
+ io::dump::save(grouped_text.label_image(), argv[2]);
+
+ io::pgm::save(level::transform(grouped_text.label_image(),
+ fun::l2l::wrap<value::int_u8>()),
+ "tmp.pgm");
+
+ scribo::debug::save_textbboxes_image(input, grouped_text.bboxes(),
+ literal::red,
+ scribo::make::debug_filename("boxes.ppm"));
+
+}
+
Index: trunk/milena/sandbox/inim/2010/boxes/Makefile
===================================================================
--- trunk/milena/sandbox/inim/2010/boxes/Makefile (revision 0)
+++ trunk/milena/sandbox/inim/2010/boxes/Makefile (revision 3674)
@@ -0,0 +1,47 @@
+include makefile.rules
+TARGET=boxes
+
+boxes_SRC=boxes.cc
+boxes_OBJS=${boxes_SRC:.cc=.o}
+
+OLN_DIR=$(MLN_DIR)/..
+SBX_DIR=$(MLN_DIR)/sandbox/
+
+CXXFLAGS=-I $(MLN_DIR) -I ./ -I$(SBX_DIR) -W -Wall
+
+
+CXXFLAGS += $(if $(DEBUG), -g -ggdb, -DNDEBUG\
+ $(if $(RELEASE), -O3, -O1))
+
+CXX=g++
+LD=g++
+LDFLAGS=
+
+all: $(TARGET)
+
+
+$(TARGET): $($(TARGET)_OBJS) $($(TARGET)_SRC)
+ $(LD) $(LDFLAGS) -o $@ $($(TARGET)_OBJS)
+
+
+%.o: %.cc
+ $(CXX) $(CXXFLAGS) -c $<
+
+
+%.o: %.hh
+ $(CXX) $(CXXFLAGS) -c $<
+
+
+depend:
+ makedepend -- $(CXXFLAGS) -- -v $($(TARGET)_SRC)
+
+
+distclean: clean
+ rm -f Makefile.rules
+
+
+clean:
+ rm -f *.o $(TARGET)
+ #rm -f *.pbm
+ #find -name "*.pgm" \! -regex ".*/affiche2?.pgm" -delete
+# DO NOT DELETE
--
:: Warren Seine // SooW ::
:: warren.seine @ gmail.com ::
:: EPITA CSI 2010 ::
1
0