* README.green: New.
* demo/annotating/bic/Makefile.am: New.
* demo/annotating/bic/bic.cc: New.
* demo/annotating/hsv/Makefile.am: New.
* demo/annotating/hsv/hsv.cc: New.
* demo/annotating/lep/Makefile.am: New.
* demo/annotating/lep/lep.cc: New.
* demo/annotating/nb_color/Makefile.am: New.
* demo/annotating/nb_color/nb_color.cc: New.
* demo/annotating/project/Makefile.am: New.
* demo/annotating/project/project.cc: New.
* demo/annotating/rgb_64/Makefile.am: New.
* demo/annotating/rgb_64/rgb_64.cc: New.
* demo/annotating/rgb_64_9/Makefile.am: New.
* demo/annotating/rgb_64_9/rgb_64_9.cc: New.
* demo/annotating/stddev_color/Makefile.am: New.
* demo/annotating/stddev_color/stddev_color.cc: New.
* demo/annotating/stddev_color_16/Makefile.am: New.
* demo/annotating/stddev_color_16/stddev_color_16.cc: New.
* exp/annotating/achromastism/Makefile.am: New.
* exp/annotating/achromastism/achromastism.cc: New.
* exp/annotating/achromastism/text-color.txt: New.
* exp/annotating/achromastism/text-img.txt: New.
* exp/annotating/achromastism/text-only.txt: New.
* exp/annotating/bench/Makefile.am: New.
* exp/annotating/bench/bench.cc: New.
* exp/annotating/error/Makefile.am: New.
* exp/annotating/error/error.cc: New.
* exp/annotating/histo/Makefile.am: New.
* exp/annotating/histo/histo.cc: New.
* exp/annotating/hsv/Makefile.am: New.
* exp/annotating/hsv/hsv.cc: New.
* exp/annotating/hue/Makefile.am: New.
* exp/annotating/hue/hue.cc: New.
* exp/annotating/hue/text-color.txt: New.
* exp/annotating/hue/text-img.txt: New.
* exp/annotating/hue/text-only.txt: New.
* exp/annotating/nb_color/Makefile.am: New.
* exp/annotating/nb_color/nb_color.cc: New.
* exp/annotating/saturation/Makefile.am: New.
* exp/annotating/saturation/saturation.cc: New.
* exp/annotating/saturation/text-color.txt: New.
* exp/annotating/saturation/text-img.txt: New.
* exp/annotating/saturation/text-only.txt: New.
* exp/annotating/stddev_color/Makefile.am: New.
* exp/annotating/stddev_color/stddev_color.cc: New.
* exp/annotating/stddev_color_16/Makefile.am: New.
* exp/annotating/stddev_color_16/stddev_color_16.cc: New.
* exp/annotating/value/Makefile.am: New.
* exp/annotating/value/text-color.txt: New.
* exp/annotating/value/text-img.txt: New.
* exp/annotating/value/text-only.txt: New.
* exp/annotating/value/value.cc: New.
* mln/clustering/kmean2d.hh: New.
* mln/fun/p2b/achromatic.hh: New.
* mln/fun/v2v/hue_concentration.hh: New.
* mln/fun/v2v/rgb_to_achromatism_map.hh: New.
* mln/fun/v2v/rgb_to_hsv.hh: New.
---
scribo/sandbox/green/ChangeLog | 64 +
scribo/sandbox/green/README.green | 507 +++++++-
.../kmean1d => annotating/bic}/Makefile.am | 0
scribo/sandbox/green/demo/annotating/bic/bic.cc | 122 ++
.../kmean1d => annotating/hsv}/Makefile.am | 0
scribo/sandbox/green/demo/annotating/hsv/hsv.cc | 721 ++++++++++
.../kmean1d => annotating/lep}/Makefile.am | 0
scribo/sandbox/green/demo/annotating/lep/lep.cc | 127 ++
.../kmean1d => annotating/nb_color}/Makefile.am | 0
.../green/demo/annotating/nb_color/nb_color.cc | 143 ++
.../kmean1d => annotating/project}/Makefile.am | 0
.../green/demo/annotating/project/project.cc | 275 ++++
.../kmean1d => annotating/rgb_64}/Makefile.am | 0
.../sandbox/green/demo/annotating/rgb_64/rgb_64.cc | 80 ++
.../kmean1d => annotating/rgb_64_9}/Makefile.am | 0
.../green/demo/annotating/rgb_64_9/rgb_64_9.cc | 132 ++
.../stddev_color}/Makefile.am | 0
.../demo/annotating/stddev_color/stddev_color.cc | 191 +++
.../stddev_color_16}/Makefile.am | 0
.../annotating/stddev_color_16/stddev_color_16.cc | 261 ++++
.../achromastism}/Makefile.am | 0
.../exp/annotating/achromastism/achromastism.cc | 179 +++
.../exp/annotating/achromastism/text-color.txt | 0
.../green/exp/annotating/achromastism/text-img.txt | 0
.../exp/annotating/achromastism/text-only.txt | 0
.../bench}/Makefile.am | 0
scribo/sandbox/green/exp/annotating/bench/bench.cc | 1450 ++++++++++++++++++++
.../error}/Makefile.am | 0
scribo/sandbox/green/exp/annotating/error/error.cc | 833 +++++++++++
.../histo}/Makefile.am | 0
scribo/sandbox/green/exp/annotating/histo/histo.cc | 366 +++++
.../hsv}/Makefile.am | 0
scribo/sandbox/green/exp/annotating/hsv/hsv.cc | 912 ++++++++++++
.../hue}/Makefile.am | 0
scribo/sandbox/green/exp/annotating/hue/hue.cc | 402 ++++++
.../green/exp/annotating/hue}/text-color.txt | 0
.../sandbox/green/exp/annotating/hue}/text-img.txt | 0
.../green/exp/annotating/hue}/text-only.txt | 0
.../nb_color}/Makefile.am | 0
.../green/exp/annotating/nb_color/nb_color.cc | 171 +++
.../saturation}/Makefile.am | 0
.../green/exp/annotating/saturation/saturation.cc | 175 +++
.../exp/annotating/saturation}/text-color.txt | 0
.../green/exp/annotating/saturation}/text-img.txt | 0
.../green/exp/annotating/saturation}/text-only.txt | 0
.../stddev_color}/Makefile.am | 0
.../exp/annotating/stddev_color/stddev_color.cc | 216 +++
.../stddev_color_16}/Makefile.am | 0
.../annotating/stddev_color_16/stddev_color_16.cc | 277 ++++
.../value}/Makefile.am | 0
.../green/exp/annotating/value}/text-color.txt | 0
.../green/exp/annotating/value}/text-img.txt | 0
.../green/exp/annotating/value}/text-only.txt | 0
scribo/sandbox/green/exp/annotating/value/value.cc | 468 +++++++
scribo/sandbox/green/mln/clustering/kmean2d.hh | 4 +-
scribo/sandbox/green/mln/fun/p2b/achromatic.hh | 20 +-
.../sandbox/green/mln/fun/v2v/hue_concentration.hh | 10 +
.../green/mln/fun/v2v/rgb_to_achromatism_map.hh | 5 +
scribo/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh | 15 +-
59 files changed, 8105 insertions(+), 21 deletions(-)
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/bic}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/bic/bic.cc
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/hsv}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/hsv/hsv.cc
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/lep}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/lep/lep.cc
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/nb_color}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/nb_color/nb_color.cc
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/project}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/project/project.cc
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/rgb_64}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/rgb_64/rgb_64.cc
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/rgb_64_9}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/rgb_64_9/rgb_64_9.cc
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/stddev_color}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/stddev_color/stddev_color.cc
copy scribo/sandbox/green/demo/{clustering/kmean1d => annotating/stddev_color_16}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/demo/annotating/stddev_color_16/stddev_color_16.cc
copy scribo/sandbox/green/exp/{regional_maxima => annotating/achromastism}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/achromastism/achromastism.cc
copy {milena => scribo}/sandbox/green/exp/annotating/achromastism/text-color.txt (100%)
copy {milena => scribo}/sandbox/green/exp/annotating/achromastism/text-img.txt (100%)
copy {milena => scribo}/sandbox/green/exp/annotating/achromastism/text-only.txt (100%)
copy scribo/sandbox/green/exp/{regional_maxima => annotating/bench}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/bench/bench.cc
copy scribo/sandbox/green/exp/{regional_maxima => annotating/error}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/error/error.cc
copy scribo/sandbox/green/exp/{regional_maxima => annotating/histo}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/histo/histo.cc
copy scribo/sandbox/green/exp/{regional_maxima => annotating/hsv}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/hsv/hsv.cc
copy scribo/sandbox/green/exp/{regional_maxima => annotating/hue}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/hue/hue.cc
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/hue}/text-color.txt (100%)
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/hue}/text-img.txt (100%)
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/hue}/text-only.txt (100%)
copy scribo/sandbox/green/exp/{regional_maxima => annotating/nb_color}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/nb_color/nb_color.cc
copy scribo/sandbox/green/exp/{regional_maxima => annotating/saturation}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/saturation/saturation.cc
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/saturation}/text-color.txt (100%)
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/saturation}/text-img.txt (100%)
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/saturation}/text-only.txt (100%)
copy scribo/sandbox/green/exp/{regional_maxima => annotating/stddev_color}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/stddev_color/stddev_color.cc
copy scribo/sandbox/green/exp/{regional_maxima => annotating/stddev_color_16}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/stddev_color_16/stddev_color_16.cc
copy scribo/sandbox/green/exp/{regional_maxima => annotating/value}/Makefile.am (100%)
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/value}/text-color.txt (100%)
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/value}/text-img.txt (100%)
copy {milena/sandbox/green/exp/annotating/achromastism => scribo/sandbox/green/exp/annotating/value}/text-only.txt (100%)
create mode 100644 scribo/sandbox/green/exp/annotating/value/value.cc
diff --git a/scribo/sandbox/green/ChangeLog b/scribo/sandbox/green/ChangeLog
index 5e4cb27..6210a79 100644
--- a/scribo/sandbox/green/ChangeLog
+++ b/scribo/sandbox/green/ChangeLog
@@ -1,3 +1,67 @@
+2010-09-08 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Import annotating sources from milena green's sandbox.
+
+ * README.green: New.
+ * demo/annotating/bic/Makefile.am: New.
+ * demo/annotating/bic/bic.cc: New.
+ * demo/annotating/hsv/Makefile.am: New.
+ * demo/annotating/hsv/hsv.cc: New.
+ * demo/annotating/lep/Makefile.am: New.
+ * demo/annotating/lep/lep.cc: New.
+ * demo/annotating/nb_color/Makefile.am: New.
+ * demo/annotating/nb_color/nb_color.cc: New.
+ * demo/annotating/project/Makefile.am: New.
+ * demo/annotating/project/project.cc: New.
+ * demo/annotating/rgb_64/Makefile.am: New.
+ * demo/annotating/rgb_64/rgb_64.cc: New.
+ * demo/annotating/rgb_64_9/Makefile.am: New.
+ * demo/annotating/rgb_64_9/rgb_64_9.cc: New.
+ * demo/annotating/stddev_color/Makefile.am: New.
+ * demo/annotating/stddev_color/stddev_color.cc: New.
+ * demo/annotating/stddev_color_16/Makefile.am: New.
+ * demo/annotating/stddev_color_16/stddev_color_16.cc: New.
+ * exp/annotating/achromastism/Makefile.am: New.
+ * exp/annotating/achromastism/achromastism.cc: New.
+ * exp/annotating/achromastism/text-color.txt: New.
+ * exp/annotating/achromastism/text-img.txt: New.
+ * exp/annotating/achromastism/text-only.txt: New.
+ * exp/annotating/bench/Makefile.am: New.
+ * exp/annotating/bench/bench.cc: New.
+ * exp/annotating/error/Makefile.am: New.
+ * exp/annotating/error/error.cc: New.
+ * exp/annotating/histo/Makefile.am: New.
+ * exp/annotating/histo/histo.cc: New.
+ * exp/annotating/hsv/Makefile.am: New.
+ * exp/annotating/hsv/hsv.cc: New.
+ * exp/annotating/hue/Makefile.am: New.
+ * exp/annotating/hue/hue.cc: New.
+ * exp/annotating/hue/text-color.txt: New.
+ * exp/annotating/hue/text-img.txt: New.
+ * exp/annotating/hue/text-only.txt: New.
+ * exp/annotating/nb_color/Makefile.am: New.
+ * exp/annotating/nb_color/nb_color.cc: New.
+ * exp/annotating/saturation/Makefile.am: New.
+ * exp/annotating/saturation/saturation.cc: New.
+ * exp/annotating/saturation/text-color.txt: New.
+ * exp/annotating/saturation/text-img.txt: New.
+ * exp/annotating/saturation/text-only.txt: New.
+ * exp/annotating/stddev_color/Makefile.am: New.
+ * exp/annotating/stddev_color/stddev_color.cc: New.
+ * exp/annotating/stddev_color_16/Makefile.am: New.
+ * exp/annotating/stddev_color_16/stddev_color_16.cc: New.
+ * exp/annotating/value/Makefile.am: New.
+ * exp/annotating/value/text-color.txt: New.
+ * exp/annotating/value/text-img.txt: New.
+ * exp/annotating/value/text-only.txt: New.
+ * exp/annotating/value/value.cc: New.
+ * mln/clustering/kmean2d.hh: New.
+ * mln/fun/p2b/achromatic.hh: New.
+ * mln/fun/v2v/hue_concentration.hh: New.
+ * mln/fun/v2v/rgb_to_achromatism_map.hh: New.
+ * mln/fun/v2v/rgb_to_hsv.hh: New.
+
+
2010-07-07 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
Import regional maxima sources from milena green's sandbox.
diff --git a/scribo/sandbox/green/README.green b/scribo/sandbox/green/README.green
index 7886914..5d6e147 100644
--- a/scribo/sandbox/green/README.green
+++ b/scribo/sandbox/green/README.green
@@ -685,21 +685,6 @@ rechercher dans les derniers répertoires mp00042c et mp00307c.
* doc/labeling/mp00307c: Test sur la representativité des couleurs trouvées.
-Faire le changelog, il y a de l'aide dans git/doc/Changelog
-... et commiter
-
-
-XI ANNOTATING
---------------
-
-==> to do
-
-
-
-* doc/annotating
-
-
-
XI AUTRES ASPECTS DOCUMENTAIRES
-------------------------------
@@ -732,3 +717,495 @@ l'effort.
* doc/formulae: LaTex directory.
* doc/quick_tour: LaTex directory.
+
+XII ANNOTATING
+--------------
+
+Tout d'abord, voici les notes documentaires qui ont été réalisées sur
+la problématique d'annotation d'image. On trouvera un fichier
+class.txt qui a pour but de poser quelques réflexions sur les types de
+classes de document. Les informations ne sont pas abouties mais
+permettent de défricher un peu le terrain. Le document
+syntheseMillet2008 est un compte-rendu de lecture des parties
+relatives à nos travaux dans la thèse de Millet. Pour bien comprendre
+mon travail, il est impératif de lire les travaux de Millet, ou
+simplement ce compte-rendu. Le dernier document est moins intéressant,
+il s'agit d'une note de travail sur les indicateurs de Millet bruts de
+fonderie (testMillet2008). Cette note n'est ni achevée, ni
+aboutie. Elle conclue sur le fait que les indicateurs et les seuils
+donnés par Millet dans sa thèse sont complètement à revoir pour nos
+besoins. Notemment, des tests sur la détection des images par rapport
+aux cliparts nous ont convaincu que certaines images AFP contiennent
+des de grandes zones homogènes qui induisent des erreurs dans les
+prédicteurs de Millet. Néanmoins, les cas particuliers qui
+contredisent les aspects opérationnnels de Millet n'enlèvent pas sa
+réflexion: Les images noir/blanc (ou monochromes) ont une très faible
+saturation, et/ou une forte concentration de la teinte. Les cliparts
+ont une forte concentration de niveaux de gris autour d'un pic.
+
+* doc/annotating: La documentation relative à l'annotation.
+
+
+Après la lecture des descripteurs de Millet, un des premiers réflexe a
+été d'en implémenter plusieurs pour voir ce qu'ils pouvaient ressortir
+sur les images que nous avions. Le descripteur BIC sépare une image en
+deux ensembles de pixels, les points intérieurs et les points
+extérieurs. Les points intérieurs ont la propriété d'être de même
+couleur que leur 4-voisins. Attention, la couleur est évaluée dans un
+espace RGB à 3 bits.
+
+* demo/annotating/bic: Histogrammes des points intérieurs et extérieurs.
+
+
+Le descripteur LEP, lui, propose de seuiller par sobel l'image et de
+faire l'histogramme des configurations du voisinage des points
+seuillés. Pour ce faire, on utilise une convolution un peu spéciale
+qui va attribué un unique id en fonction du voisinage.
+
+* demo/annotating/lep: Histogramme des configurations des voisinages des pixels.
+
+
+Un autre descripteur simple est le nombre de couleur dans une
+image. Pour cela, il est possible de construire l'histogramme des
+couleurs et de compter les cellules pleines. On peut éventuellement
+appliquer une quantification sur l'espace des couleurs. La
+compilation laisse place à d'étranges warnings sur une comparaison
+entre entiers signés et non signés, mais je n'ai pas la main dans mon
+code (ou je ne sais pas comment faire) pour enlever ces warnings. Ils
+sont récents, je n'avais pas souvenir de les avoir eu.
+
+* demo/annotating/nb_color: Compte le nombre de couleurs dans une image.
+* exp/annotating/nb_color: Adaptation pour fonctionner sur une base d'image.
+
+
+L'histogramme RGB-64 est un descripteur simple qui quantifie les
+couleurs sur 2 bits et réalise l'histogramme dans cet espace. C'est
+bien sûr une classification gros grain, mais ajouté au reste ... La
+version RGB-64-9 ajoute une phase de division de l'image en 9 sous
+images. De cette manière, l'histogramme RGB-64 est construit sur les 9
+sous images. Pour former le descripteur final, on fusionne les neufs
+histogrammes.
+
+* demo/annotating/rgb_64: Histogramme couleur dans l'espace RGB-64 (2 bits/axe).
+* demo/annotating/rgb_64_9: Histogramme RGB-64 sur les 9 sous images.
+
+
+Le descripteur de projection relaté par Millet est particulier. En
+premier lieu l'image est sous échantillonnée pour réduire sa dimension
+à 100 x 100 de manière à borner la taille des vecteurs obtenus au
+final. Puis l'image est seuillée par sobel (threshold = 100). L'image
+est d'abord divisée horizontalement en deux. Puis on établit la
+projecton perpendiculairement à la séparation de manière à obtenir
+deux vecteurs de 100 valeurs chacunes. On recommence l'opération en
+divisant maintenant l'image verticalement. L'union des 4 vecteurs
+forme le descripteur de projection. L'information condensée dans ces
+vecteurs est simplement la répartition des contours de manière
+horizontale ou verticale.
+
+* demo/annotating/project: Répartition des contours horizontaux et verticaux.
+
+
+La reconnaissance des cliparts s'appuie sur une analyse d'histogramme
+qui est fournie dans le code suivant. L'idée est de dire qu'une image
+de type clipart va être reconnaissable surtout à l'aide de ces
+contours. La couleur existe mais est très grossière. Le faitde
+dessiner à la main implique de simplifier énormément, de caricaturer,
+le remplissage. Du coup, une analyse en niveau de gris de
+l'histogramme révèle très peu de nuances. Il peut cependant en avoir
+un peu. Néanmoins, il existe des logiciels pour aider à la fabrication
+des cliparts qui proposent l'usage de dégradé, ce qui nuit à cette
+méthode de reconnaissance. Millet analyze l'histogramme normalisé
+(histogramme divisé par son pic) et regarde si son energie ne serait
+pas concentrée autour du pic (5 pixels de chaque côté
+maximum). Parfois cette méthode ne fonctionne pas correctement sur des
+photographies qui ont un cadre uniforme. La méthode trouve un pic (le
+cadre) et vérifie alors qu'une proportion non négligeable des pixels
+sont bien autour de ce pic (tout dépend de l'épaisseur du cadre). Pour
+palier à cet inconvénient, Millet propose d'utiliser ce test, non plus
+sur l'image entière, mais sur chacune des 16 sous images après un
+découpage géométrique régulier. De facto, la contribution du cadre
+diminue suffisemment pour repasser en dessous du seuil de
+reconnaissance.
+
+* demo/annotating/stddev_color: Descripteur utilisé reconnaitre des cliparts.
+* exp/annotating/stddev_color_16: Adaptation pour le travail sur base.
+* demo/annotating/stddev_color_16: Descripteur pour cliparts avec 16 imagettes.
+* exp/annotating/stddev_color: Adaptation pour le travail sur une base d'image.
+
+
+A partir de maintenant, tous les morceaux de codes réalisés préparent
+directement ou indirectement le résultat de la classification des
+bases (exp/annotating/bench).
+
+Plus de temps pour faire le code use correspondant aux fichiers
+librairies. Tout le code pour le faire est dans hsv. Rien de
+compliqué, mais allons à l'essentiel.
+
+Le but du code HSV est d'effectuer les tests de Millet ou des
+améliorations sur ces tests. Le premier test proposé par Millet est
+l'achromaticité. Il s'agit de regarder s'il existe une faible
+variation entre les trois canaux (R/G/B) pour un grand nombre de
+pixels. Si c'est le cas, c'est que l'image est presque en niveau de
+gris et peut être remplacée facilement par une image grisée sans trop
+de distorsions au niveau de la couleur. Nous avons essayer de
+généraliser un peu le test de manière à produire, non pas seulement
+une réponse sur l'achromaticité de l'image, mais aussi avoir une vue
+d'ensemble (sous forme d'image) des variations entre les cannaux pour
+chaque pixel. Il n'est pas utile d'analyser les différences sur chacun
+des canaux, prendre la différence absolue entre le canal min et le
+canal max suffit pour définir le test d'achromaticité.
+
+Les autres tests de Millet sont la faible saturation et la dominance
+de la teinte. Pour savoir si la saturation est faible, il faut
+utiliser un histogramme du canal dédié à la saturation. Si 95% des
+pixels sont en dessous de 100, alors l'image est faiblement saturée,
+elle est en noir et blanc. De la même manière, on regarde la dominance
+de la teinte. Pour ce faire, il faut voir si l'histogramme de la
+teinte ne possède pas un pic avec une très faible variance (tout
+rapproché autour du pic). Si c'est le cas, la dominance de la teinte
+est avérée et l'on peut calculé la couleur dominante. L'image est en
+niveau de gris, mais colorisé autour d'une couleur (par cepia, vert
+...).
+
+Ce programme est très très sujet à changements, il m'a servit de test
+et je ne peux pas juré qu'il est complètement sain au niveau du
+traitement. D'autres versions sont potentiellement plus
+stables. Notemment celle dans exp/annotating/hsv.
+
+* mln/fun/v2v/rgb_to_achromatism_map.hh : Distance pour l'achromaticité.
+* mln/fun/v2v/achromatic.hh : Define the achromatic map.
+* mln/fun/v2v/hue_concentration.hh : Define the distance hue/peak map.
+* mln/fun/p2b/achromatic.hh : Say if a site is achromatic.
+* demo/annotating/hsv: Code des différents tests de Millet.
+
+
+Dans le répertoire exp/annotating/hue, on trouve 3 fichiers textes qui
+rassemblent des classes d'images. Tout d'abord les images ICDAR
+n'ayant que du texte et des traces de couleurs (lettrine de couleur,
+trait, petit bandeau), un fichier où il n'y a que du texte noir &
+blanc et un fichier contenant les images couleurs (avec photographies
+ou dessins). Cette classification a été effectuée de manière manuelle.
+Le code hue test la proportion de pixels étant autour du pic de
+teinte. Il s'agit de savoir si la dominance d'une teinte est
+avérée. Le code renvoit la proportion de pixels agglomérés autour du
+pic. Le but est de généralisé les tests de millets pour qu'ils se
+ressemblent le plus possible.
+
+* exp/annotating/hue: Implémentation de la généralisation du test de Millet.
+* mln/fun/v2v/rgb_to_hue_map.hh : Construction de la map de teinte.
+
+
+On retrouve les trois fichiers permettant de classifier la base ICDAR
+en trois sous populations. Le test de saturation consiste simplement à
+regarder si une certaine quantité de la population de l'histogramme de
+saturation est en dessous d'un certain seuil. La généralisation du
+test ne porte pas sur le test en lui-même, mais sur la forme dans
+lequel le test est fait.
+
+* exp/annotating/saturation: Implémentation de la généralisation du test.
+* mln/fun/v2v/rgb_to_saturation_map.hh : Construction de la map de saturation.
+
+
+Le test de value a déjà été décrit précédemment dans
+stddev_color. L'idée est toujours la même, mais cette fois il est
+effectué dans l'espace des valeurs (HSV). Cela ne change pas grand
+chose, puisqu'il était utilisé sur des images en niveau de gris. C'est
+l'un des tests importants car il réagit à la différentiation entre une
+image type photographie et une image plus stylisée comme un
+clipart. Ce test a aussi des vertus pour la distinction entre du noir
+& blanc et de la couleur. Il s'avère que les images type photographie
+avec pleins de couleurs ont un histogramme moins sujet aux pics que
+les histogrammes noir & blanc. De facto, l'énergie de l'histogramme
+est distribué sur l'ensemble de la plage contrairement aux images noir
+& blanc où il y a une concentration de chaque côté de l'histogramme
+(bipolarité).
+
+* exp/annotating/value: Implémentation de la généralisation du test de Millet.
+* mln/fun/v2v/rgb_to_value_map.hh : Transformation d'espace.
+
+
+Le programme hsv reprend les tests préalablement élaborés auparavant
+sur les plans H, S puis V. Il combine tout en un seul programme pour
+avoir une vision plus synthétique de ce qui se passe sur les 3 espaces
+simultanément.
+
+Les tests incorpore mes transformations. C'est à dire que l'on
+effectue une série de test équivalent à ceux de Millet (au moins dans
+l'idée et le plus souvent, il s'agit d'une réecriture sous une autre
+forme) en partant des histogrammes normalisés. Un histogramme
+normalisé est un histogramme de flottant qui contient l'histogramme
+classique divisé par le nombre total de pixels. En faisant cela, on se
+déplace dans l'espace des distributions. Si l'histogramme n'a qu'un
+seul pic et que ce dernier contient tous les pixels (pic de dirac par
+exemple), alors l'histogramme normalisé donnera 1 comme valeur de
+proportion à ce pic. En fait, l'intégrale d'une distribution vaut
+1. Le but des distributions est de s'affranchir des caractéristiques
+de taille de l'image, ce qui permet de comparer les histogrammes entre
+eux. On peut ainsi comparer les histogrammes d'une photo AFP petit
+format avec celui d'une image grand format de la base ICDAR. Le but du
+jeu est de garder les idées de Millet dans ce nouvel espace. Les tests
+obtenus sont équivalents mais pas identiques.
+
+Pour la teinte, une fois l'histogramme normalisé obtenu, on cherche à
+savoir s'il existe un pic avec une forte proportion de l'histogramme
+autour de ce pic. Plutôt que le pic, nous prenons la moyenne qui est
+un opérateur un peu plus robuste et nous calculons la proportion de
+l'histogramme autour (un seuil donné en paramètre défini le périmètre
+du calcul). L'expression sous forme de proportion plutôt que sous la
+forme d'une variance rend le test homogène avec les autres tests.
+
+Pour la saturation, après normalisation, on regarde la proportion de
+l'histogramme en dessous d'un certain seuil. Il n'y a pas de
+changement significatif par rapport au test de Millet. Le seuil
+initialement proposé par Millet était 100, il a été adapté car nos
+bases sont différentes des siennes (le notre est à 25).
+
+Le test sur les valeurs (cliparts contre photos) a vraiment un intérêt
+au delà de ce cas d'utilisation. Il nous renseigne sur la
+concentration autour d'un pic de l'histogramme ou non. Nous préferrons
+la mesure de similarité à l'équi-répartition des densités, mais l'idée
+est exactement la même. Est-ce que notre histogramme est plat ou
+inversement, est-ce que les contributions sont rassemblées autour d'un
+pic? Si une image est noir et blanc, il existera un pic correspondant
+au fond et la densité s'éloignera fortement de la distribution
+équiprobable. Dans le cas maintenant d'une image couleur, la
+répartition est plus homogène, couvrant un large spectre dans le
+domaine de l'histogramme. Du coup, la distribution semblera davantage
+equi-répartie. On notera que nous prenons le test à l'envers de ce que
+propose Millet. Il essaye de voir si il y a un pic et calcule une
+forme de contribution normalisée autour de ce pic. Nous au contraire,
+on regarde l'absence de pic et on calcule la différence entre la
+densité et cette absence de pic. Notre avantage par rapport à Millet
+est démontré particulièrement dans les cas où il existe plusieurs
+grosses distributions. A contrario, notre test souffre des cas où il
+existe de nombreuses petites distributions.
+
+
+Voici un premier retour sur les expériementations:
+La discrimination entre la base AFP et la base ICDAR peut se faire en
+étudiant la forme des densités des niveaux de gris. Les images
+naturelles semblent avoir un spectre recouvrant en général les 256
+niveaux de gris alors que les images de documents ont une présence
+importante du fond. Dans le cadre d'une densité, ce qui est alloué sur
+le fond ne peut se retrouver ailleurs. Une comparaison avec la densité
+équiprobable nous renseigne donc sur la nature des images. Il semble
+néanmoins qu'un certain nombre d'images défient ce dispositif. Par
+exemple des gros plans sur des zones mono-teintée (ski, voile,site
+web).
+
+* exp/annotating/hsv: Code unifiant les trois tests sur chacun des plans HSV.
+* mln/fun/v2v/rgb_to_hue_map.hh : Transformation d'espace.
+* mln/fun/v2v/rgb_to_saturation_map.hh : Transformation d'espace.
+* mln/fun/v2v/rgb_to_value_map.hh : Transformation d'espace.
+
+
+Le test sur l'achromatisme des images est décrit dans le code
+suivant. Il a été purement et simplement abandonné dans la mesure où
+c'est un cas très particulier qui est repris par une saturation très
+faible. La saturation s'exprime comme 1 - min(channel)/max(channel),
+mais dans le cas où le min(channel) == max(channel), la saturation
+vaut 0. Le problème vient plutôt du calcul de la teine qui ne peut pas
+admettre que le min soit égal au max. Pour ce calcul, on se débrouille
+pour gérer le cas et renvoyer une valeur standardisée, Millet
+proposait -1.
+
+* exp/annotating/achromatism: Détection d'image couleur en niveau de gris.
+* mln/fun/v2v/rgb_to_achromatism_map.hh : Transformation d'espace.
+
+
+Ce programme a pour but de créer les histogrammes normalisés en rafale
+pour les bases AFP et ICDAR. Il assure leur création dans les six
+plans possibles R,G,B,H,S,V. De cette manière il est possible de
+vérifier les corrélations éventuelles entre le canal B et G. Par
+ailleurs, après visionnement de tous les histogrammes, on note des
+spécificités dans les deux bases sur les plans S et V. Certaines
+images ont des réactions très fortes sur le plan H, mais ce n'est pas
+une caractéristique pour une base (seulement pour ces images en
+question). Les résultats ont déjà été sauvegardés dans le répertoire
+image du LRDE. Des infos sont notés à ce sujet dans README.result. Le
+seul but de ce calcul est de maîtriser csujet dans README.result. Le
+seul but de ce calcul est de maîtriser ce qui se passe dans ces
+espaces, pas simplement de supposer ce qu'il pourrait s'y passer. La
+comparaison des images est rendu possible quelque soit la base
+d'origine par le fait qu'elles sont normalisées. Chaque fréquence des
+histogrammes est divisée par la somme des fréquences. On obtient donc
+une version discrète des densitées. La somme des nouvelles fréquences
+vaut 1. On voit davantage si les densités se rapprochent d'une
+équi-répartition ou non. La négative implique un ou plusieurs pics. Le
+cas défavorable dans mon approche (qui existe pour certaines images)
+est une multitude de tout petits pics autour de l'équi-répartition. Ce
+n'est pas équi-répartie pour les calculs mais ce n'est clairement pas
+la manisfestation d'une concentration de l'énergie quelque part.
+
+* exp/annotating/histo: Creation des histogrammes normalisés.
+* mln/fun/v2v/rgb_to_hue_map.hh: Transformation d'espace.
+* mln/fun/v2v/rgb_to_saturation_map.hh: Transformation d'espace.
+* mln/fun/v2v/rgb_to_value_map.hh: Transformation d'espace.
+
+
+Dans le programme erreur, on teste l'idée de jonathan. Une référence à
+ce sujet peut être trouvée dans README.img. Les bases AFP et ICDAR
+sont retravaillées à l'aide de ImageMagick et de Gimp pour diminuer le
+nombre de couleurs initiales. On oblige à n'avoir que 30, 20 ou 10
+couleurs pour chaque base. Il y a donc 4 versions de chacune des bases
+en comptant la version originale des images. Les algorithmes utilisés
+par Gimp et ImageMagick sont très différents. L'idée de Jonathan était
+de dire que lorsqu'une image est couleur, plus on réduit le nombre de
+couleur, plus elle change vis-à-vis de l'image originale. Inversement,
+si une image possède peu de couleurs (noir & blanc), sa dégradation ne
+l'altérera pas tant que cela. Prenons une image d'un skieur de la base
+AFP, en réduisant le nombre de couleurs, la combinaison marron va
+devenir marron strictement homogène et la perception que nous en avons
+est visuellement très altérée. A contrario, une image en noir & blanc
+ne semble pas bouger d'un pouce. La comparaison avec la discrimination
+sur la saturation ou la valeur montrera des résultats un peu meilleur
+plus tard mais il impossible de préjuger a priori des résultats
+futurs. L'erreur entre l'image initiale et l'image dégradée est
+calculée avec le PNSNR (compression p278 Handbook Color). Le programme
+calcule la dégradation et essaie de trouver automatiquement des seuils
+de séparation pour les deux bases. 4 détection de seuils sont testées.
+Ces seuils sont calculées avec deux bases représentatives des bases à
+discriminer. En mode production, le seuil est vu comme une constante
+pour le programme. Les deux premières classifications renvoient un
+seuil calculée comme une moyenne pondérée des moyennes des populations
+à discriminer. Le premier détecteur pondère par la déviation standard
+et le second par la variance. Le troisième simule deux populations
+gaussiennes de variances différentes et résoud l'équation de second
+degré qui en résulte. Enfin, le dernier test ne préjuge pas des
+distributions statistiques et réalise la minimisation de l'erreur de
+classification. Pour cela, il suffit de compter le nombre d'images
+bien classées et mal classées sur les bases d'apprentissage des
+populations. On utilise pour cela la méthode Otsu. Le détecteur PNSRN
+renvoie une valeur. Pour chaque population (AFP, ICDAR), on construit
+l'histogramme de des valeurs obtenues. A noter, qu'il faut que les
+valeurs du PNSNR soient ramenées entre 0 et 255. En pratique ce n'est
+pas un problème, mais il faut le mettre en oeuvre, dans mon code, ce
+n'est pas fait (les valeurs ne posaient pas de problème). Donc, pour
+chaque seuil possible (de 0 à 256), on étudie la matrice de classement
+(groupe 1 - détecté groupe 1, groupe 1 - détecté groupe 2, groupe 2 -
+détecté groupe 1, groupe 2 - détecté groupe 2). L'erreur est
+simplement la somme des quantités groupe x - détecté groupe y avec x
+!= y. Finalement, pour chaque seuil, il est possible de connaitre
+l'erreur. Le processus de minimisation de l'erreur revient à chercher
+le seuil associé à l'erreur minimale. C'est ce dernier test que nous
+préconisons. Il faut mettre en lumière que ces quatre tests renvoient
+à peu près les mêmes seuils. La minimisation de l'erreur étant le
+meilleur de tous puisqu'il minimise directement l'erreur de
+classification et c'est ce que nous cherchions en fin de compte. Un
+cinquième test a été fait avec une analyse de fisher sur l'histogramme
+des populations mélangées, mais c'est une idée saugrenue car nous
+disposons à ce niveau des populations séparées et évidemment les
+résultats sont moins bons.
+
+Petit rappel. Un vieux problème a été mis à jour ici. Lorsqu'on
+calcule des informations sur un histogramme, le type temporaire qui
+contient les résultats ne doit pas être le type qui encode les valeurs
+des résultats. Par exemple, un histogramme de byte, un calcul de
+variance tout simple où il faut stocker la valeur des pixels au carré
+multiplié par leur occurrence tiendra facilement dans un long mais pas
+dans un byte. Le sucre avec les acesseurs des itérateurs tend à
+mélanger les genres. Une solution simple est de stocker la valeur de
+l'histogramme dans un type pouvant effectuer les calculs et ensuite
+retravailler avec ce type. Nous avions déjà discuté de ce problème et
+je ne sais pas si tu avais pu corriger le problème. Si la
+classification renvoit n'importe quoi, il se peut que cela provienne
+de ce problème. Le problème ne se voit pas sur des calculs de
+moyennes, il ne s'observe que sur certains calculs de variance (dépend
+de la formule utilisée).
+
+* exp/annotating/error: Test de l'idée de jonathan (dégradation des couleurs)
+
+
+Le travail dans bench.cc reprend toute sorte de travaux déjà réalisés
+dans d'autres fichiers. Il a pour but de comparer ensemble tous les
+descripteurs pour la reconnaissance de base de données entre l'AFP et
+l'ICDAR.
+
+Le travail commence avec un certain nombres de routines travaillant
+sur les histogrammes permettant de trouver le pic, la moyenne, la
+variance et d'autres éléments. Les routines étaient éparpillées dans
+le code, du coup je les ai regroupées au même endroit. Il y a des
+redondances de code correspondant à des copier/coller ou à différents
+essais. Prendre les versions les plus génériques et en faire des
+accumulateurs serait un riche idée.
+
+Huit détecteurs sont comparés ensembles:
+- hue1, détection d'un pic de teinte très dense par la méthode de Millet.
+- sat1, détection d'une densité importante dans les saturations basses (Millet).
+- lvl0, comptage du nombre de niveau de gris (idée de Millet).
+- hue0, détection d'un pic de teinte par la méthode des densités.
+- sat0, détection d'une forte basse saturation par la méthode des densités.
+- val0, détection d'un pic de niveau de gris par la méthode des densités.
+- val1, détection d'un pic de niveau de gris par la méthode de Millet.
+- err, PNSNR (idée de jonathan).
+
+FIXME: Attention, le PNSNR n'est pas borné, il faut le faire, il doit avoir
+au maximum 255 comme valeur.
+
+Tous les détecteurs ont été expliqués en large, en long et en travers
+dans les sources précédentes. LIRE le chapitre XII (ANNOTATING) de ce fichier
+en entier.
+
+Ensuite vient les séparateurs de population statistiques qui ont été
+déjà introduit dans le fichier error. Bien que tous soient présent,
+c'est la minimisation de l'erreur qui est utilisée.
+
+Enfin vient le front end, l'un des plus complexes que j'ai écrit cette
+année. Le main lui même, n'est pas la partie la plus complexe. Il
+définit les actions fonctionnelles à réaliser et la structure de
+donnée réalisée pour garder la trace de tous les résultats.
+- File_name : Cette variable retient le nom des fichiers. C'est un tableau
+de la taille du nombre d'images rencontrées toute base confondue. Comme on
+ne parcourt qu'une fois les répertoires, il faut pouvoir retenir cette
+information qui servira éventuellement pour la nomenclature des dumps
+par la suite.
+- Result : Cette variable contient toutes les informations du traitement.
+C'est un tableau à deux dimensions, une pour les images et une autre pour
+les descripteurs. L'index d'image est le même que pour file_name.
+- Size : Cette variable contient le nombre d'images par database.
+- Threshold : Cette variable va stocker les seuils calculés sur chacun
+des descripteurs. Ces seuils sont sensés effectuer la séparation entre les
+deux bases.
+- Cxx : variables de comptage des images bien ou mal classées relativement
+à la position des seuils et à l'appartenance d'origine des images. Cette
+appartenance d'origine est calculée à l'aide Size qui contient le nombre
+d'image par base de données. Comme les images sont vues dans l'ordre, les X
+premières appartiennent à la base ICDAR et les Y suivantes à la base AFP.
+- histo : Variable servant à effectuer par database et par descripteur un
+histogramme utilisé ensuite lors de la discrimination des bases.
+
+La partie compute_descriptors a pour mission de passer une fois sur
+toutes les images et de calculer les descripteurs associés. A l'issue
+de cette passe file_name, result et size sont remplis et pourront être
+utilisés par les autres routines.
+
+La partie dump_descriptors a pour but de réaliser un tracé en gnuplot,
+avec une couleur différente pour chaque base. Le graphe montre les
+valeurs utilisées par chaque descripteur pour toutes les images de la
+base.
+
+La partie correction des descripteurs est optionnelle et force un
+certain nombre de valeurs pour être inférieures à 256. Le but était de
+pouvoir travaillé, même si les descripteurs n'étaient pas complètement
+opérationnels. Elle sert donc pour le debug.
+
+La partie calcul des histogrammes sert à obtenir la distribution des
+valeurs de chacun des descripteurs en fonction des bases
+utilisées. C'est une étape préliminaire à l'analyse des populations et
+au calcul des seuils.
+
+La partie calcul des seuils repose sur la minimisation des erreurs de
+classification. Cette méthode ne fonctionne bien si la classe zéro à
+une moyenne inférieure à la classe un. Du coup, il n'est pas possible
+de déterminer de manière simple si la classe 0 correspond à l'AFP ou à
+l'ICDAR. Pour chaque descripteur, les cartes sont rebattues.
+
+Enfin, tous les histogrammes sont sauvés pour pouvoir comprendre et
+visualiser les résultats.
+
+Le main2 ne sert à rien, juste pour des essais.
+
+Attention, modification VAL0/VAL1, vérifiez que le bon descripteur est
+au bon endroit dans le tableau.
+
+* exp/annotating/bench: Comparaison des détecteurs pour la classif. ICDAR/AFP.
\ No newline at end of file
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/bic/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/bic/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/bic/bic.cc b/scribo/sandbox/green/demo/annotating/bic/bic.cc
new file mode 100644
index 0000000..f63d260
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/bic/bic.cc
@@ -0,0 +1,122 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet BIC descriptor [millet.phd.2008.pdf]
+///
+/// This is an image descriptor. It quantifies the three channels on 3
+/// bits, then builds two histograms with the interior pixels and the
+/// exterior ones. The interior pixels are those where color value is
+/// the same as their 4 neighbouring pixels. The descriptor is the
+/// fusion of the two histograms.
+
+#include <iostream>
+
+#include <mln/accu/stat/histo3d_rgb.hh>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/routine/initialize.hh>
+#include <mln/core/var.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/convert.hh>
+#include <mln/data/transform.hh>
+#include <mln/data/fill.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/value/rgb.hh>
+#include <mln/value/rgb8.hh>
+
+/// \brief Main entry.
+///
+/// Load the images, compute the interior and the exterior with the
+/// predicate, then compute the two histograms separately.
+int main()
+{
+ typedef mln::value::rgb<3> t_rgb3;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::neighb2d t_neighb2d;
+ typedef mln::image2d<t_rgb3> t_image2d_rgb3;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image3d<unsigned> t_histo3d;
+ typedef mln::fun::v2v::rgb8_to_rgbn<3> t_rgb8_to_rgb3;
+ typedef mln::accu::meta::stat::histo3d_rgb t_histo3d_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_rgb3 input_rgb3;
+ t_image2d_rgb3 interior_rgb3;
+ t_image2d_rgb3 exterior_rgb3;
+ t_histo3d histo_exterior;
+ t_histo3d histo_interior;
+
+ // IMAGE LOADING PHASE
+ std::cout << "Image loading phase ..." << std::endl;
+ mln::io::ppm::load(input_rgb8, ICDAR_50P_PPM_IMG_PATH"/mp00082c_50p.ppm");
+ input_rgb3 = mln::data::transform(input_rgb8, t_rgb8_to_rgb3());
+
+ mln::initialize(interior_rgb3, input_rgb3);
+ mln::initialize(exterior_rgb3, input_rgb3);
+
+ mln::data::fill(interior_rgb3, mln::literal::black);
+ mln::data::fill(exterior_rgb3, mln::literal::black);
+
+ mln_piter_(t_image2d_rgb3) p(input_rgb3.domain());
+ mln_niter_(t_neighb2d) n(mln::c4(), p);
+
+ for_all(p)
+ {
+ bool is_interior = true;
+
+ for_all(n)
+ is_interior = is_interior && (input_rgb3(p) == input_rgb3(n));
+
+ if (is_interior)
+ interior_rgb3(p) = input_rgb3(p);
+ else
+ exterior_rgb3(p) = input_rgb3(p);
+ }
+
+ histo_interior = mln::data::compute(t_histo3d_fun(), interior_rgb3);
+ histo_exterior = mln::data::compute(t_histo3d_fun(), exterior_rgb3);
+
+ //mln::io::plot::save_image_sh(histo, "histo.sh");
+
+ // PRINTING PHASE
+ mln::debug::println(histo_interior);
+ mln::debug::println(histo_exterior);
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/hsv/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/hsv/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/hsv/hsv.cc b/scribo/sandbox/green/demo/annotating/hsv/hsv.cc
new file mode 100644
index 0000000..e87ab2d
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/hsv/hsv.cc
@@ -0,0 +1,721 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet HSV operator [millet.phd.2008.pdf]
+///
+/// This is the Millet code for moving from RGB space to HSV
+/// one. Formulae are classical, we can find them on the web.
+///
+// Val = max(R,G,B).
+// Sat = (max(R,G,B) - min(R,G,B))/max(R,G,B).
+// IF R = max(R,G,B) THEN Hue = 60 * [(V-B)/(max(R,G,B)-min(R,G,B))].
+// IF G = max(R,G,B) THEN Hue = 60 * [2 + (B-R)/(max(R,G,B)-min(R,G,B))].
+// IF B = max(R,G,B) THEN Hue = 60 * [4 + (R-G)/(max(R,G,B)-min(R,G,B))].
+///
+/// \fixme: This code is unstable. It was using to make a lot of tests.
+/// Don't use it, we have more stable version of it.
+#include <iostream>
+#include <fstream>
+
+#include <mln/accu/max_site.hh>
+#include <mln/accu/math/count.hh>
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/binarization/threshold.hh>
+
+#include <mln/core/alias/point1d.hh>
+#include <mln/core/alias/box1d.hh>
+#include <mln/core/concept/image.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/transform.hh>
+#include <mln/data/compute.hh>
+#include <mln/data/stretch.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/literal/colors.hh>
+#include <mln/literal/grays.hh>
+
+#include <mln/fun/v2v/rgb_to_hsv.hh>
+#include <mln/fun/v2v/rgb_to_achromatism_map.hh>
+#include <mln/fun/v2v/achromatism.hh>
+#include <mln/fun/v2v/hue_concentration.hh>
+#include <mln/fun/p2b/component_equals.hh>
+#include <mln/fun/p2b/achromatic.hh>
+#include <mln/fun/v2v/component.hh>
+
+#include <mln/geom/nsites.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/io/plot/save_image_sh.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/pbm/save.hh>
+
+#include <mln/pw/cst.hh>
+#include <mln/pw/value.hh>
+//#include <mln/trace/quiet.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/hsv.hh>
+
+
+/// \brief Classify a rgb a value with a color of reference.
+///
+/// \param[in] rgb a rgb8 value.
+///
+/// \return a rgb8 initialize with the selecting literal.
+///
+/// This classification of the RGB color space is based on the
+/// Millet's work. It uses the hue wheel to do it and make new
+/// distinction as brown/orange for instance.
+mln::value::rgb8 label_color(const mln::value::rgb8 rgb)
+{
+ mln::value::hsv_f hsv = mln::fun::v2v::f_rgb_to_hsv_f(rgb);
+
+ mln::value::rgb8 result;
+
+ // Is it a gray level ?
+ if (0 == hsv.sat())
+ {
+ // which result one ?
+ if (82 > hsv.sat())
+ result = mln::literal::black;
+ else if (179 > hsv.sat())
+ result= mln::literal::medium_gray;
+ else
+ result = mln::literal::white;
+ }
+ // Is it a true result color ?
+ else if (14 > hsv.hue())
+ result = mln::literal::red;
+ else if (29 > hsv.hue())
+ {
+ // Is is brown or orange ?
+ unsigned dist_orange = mln::math::abs(hsv.sat() - 184)
+ + mln::math::abs(hsv.val() - 65);
+
+ unsigned dist_brown = mln::math::abs(hsv.sat() - 255)
+ + mln::math::abs(hsv.val() - 125);
+
+ if (dist_orange < dist_brown)
+ result = mln::literal::orange;
+ else
+ result = mln::literal::brown;
+ }
+ else if (45 > hsv.hue())
+ {
+ // Is it green or yellow ?
+ if (80 > hsv.val())
+ result = mln::literal::green;
+ else
+ result = mln::literal::yellow;
+ }
+ else if (113 > hsv.hue())
+ result = mln::literal::green;
+ else if (149 > hsv.hue())
+ result = mln::literal::cyan;
+ else if (205 > hsv.hue())
+ result = mln::literal::blue;
+ else if (235 > hsv.hue())
+ result = mln::literal::violet;
+ else if (242 > hsv.hue())
+ result = mln::literal::pink;
+ else
+ result = mln::literal::red;
+
+ return result;
+}
+
+/// \brief Sum all the bins of the histogram.
+///
+/// \param[in] img the histogram based on image.
+///
+/// \return the sum of the overall bins.
+///
+/// Sum evry bins and return the result.
+template <typename I>
+unsigned count_histo(const mln::Image<I>& img_)
+{
+ const I& img = exact(img_);
+
+ mln_precondition(img.is_valid());
+
+ unsigned result = 0;
+ mln_piter(I) p(img.domain());
+
+ for_all(p)
+ result += img(p);
+
+ return result;
+}
+
+
+/// \brief The R function of Millet
+///
+/// \param[in] p the position of the pic.
+/// \param[in] histo_p the histo value of the pic.
+/// \param[in] x the position of the element which we compute the contrib.
+/// \param[in] histo_x the histo value of that element.
+///
+/// \result the contribution of the element x.
+///
+/// This function compute the variance-like contribution of an element
+/// x linked to the pic of the histogram. In fact, every thing is like
+/// we compute a square distance-like between the element x and the
+/// pic in the normalized histogram. Notice that the normalized
+/// histogram is the histogram divide by the value of it's pic. So at
+/// the pic, the value equals 1. It's a current representation of the
+/// histogram in image processing, we can find it in gimp for exemple.
+float r(short p, unsigned histo_p, short x, unsigned histo_x)
+{
+ float result = mln::math::sqr(((float)histo_x / histo_p) * (x-p));
+
+ return result;
+}
+
+
+/// \brief Find the peak of the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the bin which contains the greatest value.
+///
+/// Compute the position of the peak of the histogram. To do this, we
+/// view evrey bin and we maintain the maxima of the values and the
+/// position. At the end, we return the position which contains the
+/// greatest value.
+template <typename I>
+unsigned peak_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the peak of the histogram
+ unsigned v_max = mln::opt::at(histo, 0);
+ short p_max = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ return p_max;
+}
+
+
+/// Brief compute the whole deviation of Millet
+///
+/// \param[in] image the input image to analyze.
+///
+/// \return the deviation.
+///
+/// The deviation uses the R function. It stats by finding the pic. If
+/// the pic is near the rigth border of the histo, compute the R
+/// function on the left neighbouring of the pic. If the pic is near
+/// the left border of the histo, compute the R function on the right
+/// neigbouring. Otherwise, compute the average of the right and left
+/// results. The selected neighbouring is composed of five pixels at
+/// the right or at the left of the pic. The detection of clipart
+/// assumes that the majority of the energy of the histogram is closed
+/// to the pic (five pixels around it).
+// unsigned stddev_color(mln::image2d<mln::value::int_u8> input_int_u8,
+// const char *name_histo,
+// const char *name_image)
+// {
+// typedef mln::point1d t_point1d;
+// typedef mln::value::rgb8 t_rgb8;
+// typedef mln::value::int_u8 t_int_u8;
+// typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+// typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+// typedef mln::image1d<unsigned> t_histo1d;
+// typedef mln::fun::v2v::rgb8_to_int_u8 t_rgb8_to_int_u8;
+// typedef mln::accu::meta::stat::histo1d t_histo1d_fun;
+// typedef mln::accu::max_site<t_histo1d> t_max_site_fun;
+
+// t_histo1d histo;
+
+// std::cout << "histo : " << name_histo << std::endl;
+// std::cout << "image : " << name_image << std::endl;
+
+// histo = mln::data::compute(t_histo1d_fun(), input_int_u8);
+
+// mln::io::pgm::save(input_int_u8, name_image);
+// mln::io::plot::save_image_sh(histo, name_histo);
+// mln::debug::println(histo);
+
+// // Find the peak of the histogram
+// unsigned v_max = mln::opt::at(histo, 0);
+// short p_max = 0;
+
+// mln_piter_(t_histo1d) p(histo.domain());
+
+// for_all(p)
+// {
+// if (v_max < histo(p))
+// {
+// v_max = histo(p);
+// p_max = p.ind();
+// }
+// }
+
+// // Compute the specific stddev
+
+// float stddev_low = 0.0;
+// float stddev_up = 0.0;
+// float stddev = 0.0;
+
+// if (250 > p_max)
+// for (short i = p_max+1; i < p_max+6; ++i)
+// stddev_up += r(p_max, mln::opt::at(histo,p_max),
+// i, mln::opt::at(histo,i));
+
+// if (5 < p_max)
+// for (short i = p_max-1; i > p_max-6; --i)
+// stddev_low += r(p_max, mln::opt::at(histo,p_max),
+// i, mln::opt::at(histo,i));
+
+// stddev = (250 < p_max)? stddev_low : (5 > p_max)? stddev_up :
+// (stddev_low + stddev_up)/2;
+
+// std::cout << "max_site : " << p_max << std::endl;
+// std::cout << "h(max_site) : " << v_max << std::endl;
+// std::cout << "stddev_up : " << stddev_up << std::endl;
+// std::cout << "stddev_low : " << stddev_low << std::endl;
+// std::cout << "stddev : " << stddev << std::endl;
+
+// return 0;
+// }
+
+
+// -------------------------------------
+// input image <name>.ppm
+// map <name>-<map>.pgm
+// thresholded map <name>-<map>.pbm
+// histogram <name>-<map>.sh
+// decision <name>-<map>.txt
+// -------------------------------------
+// Achromatism <name>-achromatism.pgm
+// call achromatism(input_rgb8, 7, 99.0)
+
+
+/// \brief Decide if an image is achromatic or not [Millet].
+///
+/// \param[in] input_rgb8 the input image.
+/// \param[in] threshold the distance threshold used for equality.
+/// \param[in] percentage the percentage of pixels that very the test.
+///
+/// This is an improving of the Millet test. The original test
+/// compares rgb values to each other and look at differences greater
+/// than the threshold. If the number of pixel that pass the test are
+/// greater than 99.0, then the image is declared achromatic. In fact,
+/// there is few variations between the three channels, so we can say
+/// that it is like a grey image. We can with no too distortions
+/// replace the color image by the grey one. The improving is in first
+/// creating a map of the difference. As we can't keep the free
+/// differences between channels, we look at reducing the test and we
+/// find an equivalent one based on the difference between minima
+/// channel value and the maxima channel value. After the map is
+/// ready, we make binarization with the threshold. Then we compute
+/// the histogram 1d for every pixels of the map that are greater the
+/// threshold. Then, we count pixels in the histogram and traduce the
+/// count in percentage to compare to the second threshold. Details
+/// are saved in files and printed in the screen.
+void achromatism(mln::image2d<mln::value::rgb8> input_rgb8,
+ mln::value::int_u8 threshold,
+ float percentage)
+{
+ typedef mln::fun::v2v::rgb_to_achromatism_map<8> t_rgb_to_achromatism_map;
+
+ mln::image2d<mln::value::int_u8> map;
+ mln::image2d<mln::value::int_u8> view;
+ mln::image2d<bool> mask;
+ mln::image1d<unsigned> histo;
+ unsigned cnt1;
+ unsigned cnt2;
+ float prop;
+ bool result;
+
+
+ map = mln::data::transform(input_rgb8, t_rgb_to_achromatism_map());
+ view = mln::data::stretch(mln::value::int_u8(), map);
+ mask = mln::binarization::threshold(map, threshold);
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(),
+ map | (mln::pw::value(mask) == true));
+ cnt1 = count_histo(histo);
+ cnt2 = mln::geom::nsites(input_rgb8);
+ prop = (100.0 * (cnt2 - cnt1) / cnt2);
+ result = (prop > percentage);
+
+
+ std::ofstream txt_stream("achromatism.txt");
+ txt_stream << "Achromatism" << std::endl;
+
+ txt_stream << "Nbre pixels : " << cnt2 << std::endl;
+ txt_stream << "Nbre pixels achromatiques : " << (cnt2-cnt1)<< std::endl;
+ txt_stream << "Percentage : " << prop << std::endl;
+ txt_stream << "Image achromatique : " << result << std::endl;
+ txt_stream << std::endl;
+
+ txt_stream.flush();
+ txt_stream.close();
+
+ mln::io::pgm::save(view, "achromatism.pgm");
+ mln::io::plot::save_image_sh(histo, "achromatism.sh");
+ mln::io::pbm::save(mask, "achromatism.pbm");
+}
+
+
+/// \brief Decide if an image is low saturate or not and so b/w [Millet].
+///
+/// \param[in] input_hsvf the input image in the HSV space.
+/// \param[in] achromatism_mask the mask to prevent computing bad saturation.
+/// \param[in] threshold the distance threshold used for equality.
+/// \param[in] percentage the percentage of pixels that very the test.
+///
+/// As we are in the HSV space, we can just isolate saturation
+/// channel. The original idea of Millet is to build histogram bound
+/// to 256 for the saturation. If a great percentage (95%) of the
+/// population are under a threshold (100), then the image has got low
+/// saturation. So, it is b/w image. Low saturation is sometimes
+/// redundant with the achromatism test but not every time.
+
+// call low_saturation(input_rgb8, achromatism_mask, 100, 95.0)
+void low_saturation(mln::image2d<mln::value::hsv_f> input_hsvf,
+ mln::image2d<bool> achromatism_mask,
+ mln::value::int_u8 threshold,
+ float percentage)
+{
+ typedef mln::value::hsv_f t_hsvf;
+ typedef mln::value::hsv_f::s_type t_sat;
+ typedef mln::fun::v2v::component<t_hsvf,1> t_component_s;
+
+ mln::image2d<t_sat> map;
+ mln::image2d<mln::value::int_u8> view;
+ mln::image2d<bool> mask;
+ mln::image1d<unsigned> histo;
+ unsigned cnt1;
+ unsigned cnt2;
+ float prop;
+ bool result;
+
+
+ map = mln::data::transform(input_hsvf, t_component_s());
+ view = mln::data::stretch(mln::value::int_u8(), map);
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(),
+ view|(mln::pw::value(achromatism_mask) == true));
+ prop = (100.0 * (cnt2 - cnt1) / cnt2);
+ result = (prop > percentage);
+
+ std::cout << "Saturation" << std::endl;
+
+ cnt1 = count_histo(histo | mln::box1d(mln::point1d(0),mln::point1d(100)));
+ cnt2= mln::geom::nsites(achromatism_mask|
+ (mln::pw::value(achromatism_mask)==false));
+
+ std::ofstream txt_stream("saturation.txt");
+ txt_stream << "Saturation" << std::endl;
+
+ txt_stream << "Nbre pixels : " << cnt2 << std::endl;
+ txt_stream << "Nbre p faiblement saturés : " << cnt1 << std::endl;
+ txt_stream << "Pourcentage : " << prop << std::endl;
+ txt_stream << "Image faiblement saturé : " << result << std::endl;
+ txt_stream << std::endl;
+
+ txt_stream.flush();
+ txt_stream.close();
+
+ mln::io::pgm::save(view, "saturation.pgm");
+ mln::io::plot::save_image_sh(histo, "saturation.sh");
+ mln::io::pbm::save(mask, "saturation.pbm");
+}
+
+/* This is a classification of the ICDAR base in 3 modalities.
+// COLOR
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00032c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00042c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00076c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00082c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00142c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00215c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00228c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00234c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00248c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00252c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00253c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00255c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00259c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00271c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00290c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00293c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00304c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00307c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00376c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00411c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00419c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00447c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00498c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00510c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00550c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00573c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00589c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00592c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00597c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00599c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00600c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00031c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00034c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00043c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00063c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00065c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00072c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00081c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00083c_20p.ppm");
+
+// BLACK AND WHITE
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00329c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00036c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00037c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00039c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00040c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00049c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00055c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00057c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00068c_20p.ppm");
+
+
+// A LITTLE BIT OF COLOR
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00262c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00263c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00311c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00319c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00440c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00608c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00630c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00631c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00028c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00046c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00073c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00089c_20p.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/ta00090c_20p.ppm");
+*/
+
+
+/// \brief The main entry and the whole processing routine
+///
+/// This is the routine which works on Millet test. First compute the
+/// achromatic mask. Then build the transfer between RGB and HSV. Then
+/// isolate each channel to work on it. Each separate channel is bound
+/// between 0 and 255. Then keep only pixels low saturated (< 100 in S
+/// canal) in a specefic map. Build the 3 histograms without the
+/// achromatic pixels based on the 3 separated channels (H/S/V). Build the
+/// 3 maps (hue_concentration, low_saturation and achromatism). Then do
+/// the 3 tests of Millet with the thow thresolded pass (threshold,percentage).
+int main()
+{
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::value::hsv_f t_hsvf;
+ typedef mln::value::hsv_f::h_type t_hue;
+ typedef mln::value::hsv_f::s_type t_sat;
+ typedef mln::value::hsv_f::v_type t_val;
+ typedef mln::image2d<t_hue> t_image2d_hue;
+ typedef mln::image2d<t_sat> t_image2d_sat;
+ typedef mln::image2d<t_val> t_image2d_val;
+ typedef mln::image2d<t_hsvf> t_image2d_hsvf;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<float> t_image2d_float;
+ typedef mln::image1d<unsigned> t_histo1d;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image2d<bool> t_mask;
+ typedef mln::fun::v2v::f_rgb_to_hsv_f_t t_rgb8_to_hsv;
+ typedef mln::accu::math::count<t_hsvf> t_count;
+ typedef mln::fun::v2v::component<t_hsvf,0> t_component_h;
+ typedef mln::fun::v2v::component<t_hsvf,1> t_component_s;
+ typedef mln::fun::v2v::component<t_hsvf,2> t_component_v;
+ typedef mln::fun::p2b::component_equals<t_image2d_hsvf,0> t_component_eq0;
+ typedef mln::fun::p2b::component_equals<t_image2d_hsvf,1> t_component_eq1;
+ typedef mln::fun::p2b::component_equals<t_image2d_hsvf,2> t_component_eq2;
+ typedef mln::fun::p2b::achromatic<t_rgb8> t_achromatic;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_hsvf input_hsvf;
+
+ t_mask achromatic;
+ t_mask low_saturation;
+
+ t_image2d_float achromatism1;
+ t_image2d_int_u8 achromatism2;
+ t_image2d_float hue_concentration1;
+ t_image2d_int_u8 hue_concentration2;
+
+ t_image2d_hue input_h;
+ t_image2d_hue input_h2;
+ t_image2d_sat input_s;
+ t_image2d_val input_v;
+
+ t_image2d_int_u8 input_h8;
+ t_image2d_int_u8 input_s8;
+ t_image2d_int_u8 input_v8;
+
+ t_histo1d histo_h;
+ t_histo1d histo_s;
+ t_histo1d histo_v;
+
+ unsigned cnt1;
+ unsigned cnt2;
+ float percentage;
+ bool result;
+
+
+
+ // IMAGE LOADING PHASE
+ std::cout << "Image loading phase ..." << std::endl;
+// mln::io::ppm::load(input_rgb8, ANNOTATING_1_BILL_IMG_PATH"/bill03.ppm");
+ mln::io::ppm::load(input_rgb8, ICDAR_20P_PPM_IMG_PATH"/mp00082c_20p.ppm");
+
+
+// achromatism(input_rgb8,7,99.0);
+// exit(-1);
+
+ // REPERAGE DES PIXELS ACHROMATICS
+ std::cout << "Init achromatic mask ..." << std::endl;
+ initialize(achromatic, input_rgb8);
+ mln::data::fill(achromatic, false);
+ mln::data::fill((achromatic | t_achromatic(input_rgb8, 0.03)).rw(), true);
+
+ mln::io::pbm::save(achromatic, "achromatic.pbm");
+
+ std::cout << "Achieve canal forking ..." << std::endl;
+ input_hsvf = mln::data::transform(input_rgb8, t_rgb8_to_hsv());
+ input_h = mln::data::transform(input_hsvf, t_component_h());
+ input_s = mln::data::transform(input_hsvf, t_component_s());
+ input_v = mln::data::transform(input_hsvf, t_component_v());
+
+ // quid of achromatic pixels ???
+ input_h8 = mln::data::stretch(t_int_u8(), input_h);
+ input_s8 = mln::data::stretch(t_int_u8(), input_s);
+ input_v8 = mln::data::stretch(t_int_u8(), input_v);
+
+ // IDENTIFY LOW SATURATED PIXELS
+ std::cout << "Init low saturation mask ..." << std::endl;
+ initialize(low_saturation, input_s8);
+ mln::data::fill(low_saturation, false);
+ mln::data::fill((low_saturation|(mln::pw::value(input_s8) <
+ mln::pw::cst(100u))).rw(), true);
+
+ mln::io::pbm::save(low_saturation, "low_saturation.pbm");
+
+ std::cout << "Compute histograms ..." << std::endl;
+ histo_h = mln::data::compute(mln::accu::meta::stat::histo1d(),
+ input_h8|(mln::pw::value(achromatic)==false));
+
+ histo_s = mln::data::compute(mln::accu::meta::stat::histo1d(),
+ input_s8|(mln::pw::value(achromatic)==false));
+
+ histo_v = mln::data::compute(mln::accu::meta::stat::histo1d(),
+ input_v8|(mln::pw::value(achromatic)==false));
+
+
+ // Study the maps
+ hue_concentration1=mln::data::transform(input_h,
+ mln::fun::v2v::hue_concentration(histo_h));
+ achromatism1=mln::data::transform(input_rgb8,mln::fun::v2v::achromatism());
+
+ hue_concentration2= mln::data::stretch(t_int_u8(), hue_concentration1);
+ achromatism2= mln::data::stretch(t_int_u8(), achromatism1);
+
+ mln::io::pgm::save(achromatism2, "achromatism_map.pgm");
+ mln::io::pgm::save(hue_concentration2, "hue_concentration_map.pgm");
+ mln::io::pgm::save(input_s8, "saturation_map.pgm");
+
+// cnt1 = mln::data::compute(t_count(),
+// (input_hsvf|t_component_eq0(input_hsvf,-1)).rw());
+
+
+ // (I) ACHROMATISM
+ std::cout << "Achromatism" << std::endl;
+ cnt1 = count_histo(histo_h);
+ cnt2 = mln::geom::nsites(input_h);
+
+ percentage = (100.0 * (cnt2 - cnt1) / cnt2);
+ result = percentage > 99.0;
+
+ std::cout << "Nbre pixels : " << cnt2 << std::endl;
+ std::cout << "Nbre pixels achromatiques : " << (cnt2-cnt1)<< std::endl;
+ std::cout << "Percentage : " << percentage << std::endl;
+ std::cout << "Image achromatique : " << result << std::endl;
+ std::cout << std::endl;
+
+ // (II) LOW SATURATION
+ std::cout << "Saturation" << std::endl;
+
+ cnt1 = count_histo(histo_s | mln::box1d(mln::point1d(0),mln::point1d(100)));
+
+ cnt2= mln::geom::nsites(achromatic | (mln::pw::value(achromatic)==false));
+
+ percentage = (100.0 * cnt1 / cnt2);
+ result = percentage > 95.0;
+
+ std::cout << "Nbre pixels : " << cnt2 << std::endl;
+ std::cout << "Nbre p faiblement saturés : " << cnt1 << std::endl;
+ std::cout << "Percentage : " << percentage << std::endl;
+ std::cout << "Image faiblement saturé : " << result << std::endl;
+ std::cout << std::endl;
+
+ // (III) HIGH HUE CONCENTRATION
+ mln::debug::println(histo_h);
+ unsigned peak = peak_histo(histo_h);
+
+ cnt1 = count_histo(histo_h | mln::box1d(mln::point1d(peak-20),
+ mln::point1d(peak+20)));
+
+ cnt2= count_histo(histo_h);
+
+ percentage = (100.0 * cnt1 / cnt2);
+ result = percentage > 95.0;
+
+ std::cout << "Position du pic : " << peak << std::endl;
+ std::cout << "Nbre pixels : " << cnt2 << std::endl;
+ std::cout << "Nbre pixels proches pic : " << cnt1 << std::endl;
+ std::cout << "Percentage : " << percentage << std::endl;
+ std::cout << "Image fortement teintée : " << result << std::endl;
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/lep/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/lep/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/lep/lep.cc b/scribo/sandbox/green/demo/annotating/lep/lep.cc
new file mode 100644
index 0000000..981a369
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/lep/lep.cc
@@ -0,0 +1,127 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet LEP descriptor [millet.phd.2008.pdf]
+///
+/// This is an image descriptor. It works on grey level image. First,
+/// Sobel is applied on the image. Then a specific window is build to
+/// be convolved on the image. The aim of the convolution is to mark
+/// the configuration of the neighbouring for this thresholded image.
+/// Histogram of the configuration is then created and that's all.
+
+#include <iostream>
+
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/binarization/threshold.hh>
+
+#include <mln/core/alias/w_window2d_int.hh>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/convert.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/linear/ch_convolve.hh>
+#include <mln/linear/convolve.hh>
+#include <mln/linear/sobel_2d.hh>
+
+#include <mln/make/w_window2d.hh>
+
+#include <mln/value/rgb.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+
+#include <mln/core/var.hh>
+
+/// \brief Main entry.
+///
+/// Load the pgm image. Threshold it. Identifie the pixel
+/// configuration with specific convolution filter. Build 1d histogram.
+
+int main()
+{
+ using namespace mln;
+
+ typedef mln::w_window2d_int t_win2d;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::value::int_u<9> t_int_u9;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image2d<t_int_u9> t_image2d_int_u9;
+ typedef mln::image2d<int> t_image2d_int;
+ typedef mln::image2d<unsigned> t_image2d_unsigned;
+ typedef mln::image2d<float> t_image2d_float;
+ typedef mln::image2d<double> t_image2d_double;
+ typedef mln::image2d<bool> t_image2d_bool;
+ typedef mln::image1d<unsigned> t_histo1d;
+ typedef mln::accu::meta::stat::histo1d t_histo1d_fun;
+
+ t_image2d_int_u8 input_int_u8;
+ t_image2d_int input_int;
+ t_image2d_unsigned input_unsigned;
+ t_image2d_float sobel;
+ t_image2d_bool thresh_bool;
+ t_image2d_int_u8 thresh_int_u8;
+ t_image2d_float conf_float;
+ t_image2d_int_u9 conf_int_u9;
+ t_histo1d histo;
+
+ // IMAGE LOADING PHASE
+ std::cout << "Image loading phase ..." << std::endl;
+ mln::io::pgm::load(input_int_u8,ICDAR_50P_PGM_IMG_PATH"/mp00082c_50p.pgm");
+
+ sobel = mln::linear::sobel_2d_l1_norm(input_int_u8);
+
+ //mln::io::plot::save_image_sh(sobel, "sobel.sh");
+ thresh_bool = mln::binarization::threshold(sobel, 100);
+ thresh_int_u8 = mln::data::convert(mln::value::int_u8(), thresh_bool);
+ //mln::io::plot::save_image_sh(thresh, "thresh.sh");
+
+ int ws[] = { 1, 2, 4,
+ 8, 256, 16,
+ 32, 64, 128 };
+
+ t_win2d win2d = mln::make::w_window2d(ws);
+ conf_float = mln::linear::convolve(thresh_int_u8, win2d);
+ conf_int_u9 = mln::data::convert(t_int_u9(), conf_float);
+ histo = mln::data::compute(t_histo1d_fun(), conf_int_u9);
+
+ mln::io::plot::save_image_sh(histo, "histo.sh");
+
+ // PRINTING PHASE
+ mln::debug::println(histo);
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/nb_color/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/nb_color/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/nb_color/nb_color.cc b/scribo/sandbox/green/demo/annotating/nb_color/nb_color.cc
new file mode 100644
index 0000000..acc64e9
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/nb_color/nb_color.cc
@@ -0,0 +1,143 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Compute the number of colors in an image.
+///
+/// Build histogram of colors and count the bins different from zero.
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/math/sum.hh>
+#include <mln/accu/math/count.hh>
+#include <mln/accu/stat/histo3d_rgb.hh>
+#include <mln/accu/stat/mean.hh>
+#include <mln/accu/stat/variance.hh>
+
+#include <mln/algebra/vec.hh>
+
+#include <mln/arith/diff_abs.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/core/routine/initialize.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/labeling/regional_maxima.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/labeling/compute.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/morpho/opening/volume.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/pw/cst.hh>
+
+#include <mln/util/array.hh>
+#include <mln/util/timer.hh>
+
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/value/rgb.hh>
+#include <mln/value/int_u.hh>
+
+/// \brief Count the colors.
+///
+/// \param[in] image the name of the image to process.
+///
+/// \return the number of colors.
+///
+/// Count the color by building histogram. Quantification is done to
+/// reduce the size of the histogram.
+///
+/// \fixme: Strange compilation warning, I don't know how to solve it!
+
+// n < 8, n is the degree of quantification
+template <unsigned n>
+unsigned count_image_color(const std::string& image)
+{
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<n> t_rgbn;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgbn> t_image2d_rgbn;
+ typedef mln::image3d<unsigned> t_histo3d;
+ typedef mln::fun::v2v::rgb8_to_rgbn<n> t_rgb8_to_rgbn;
+ typedef mln::accu::meta::stat::histo3d_rgb t_histo3d_fun;
+ typedef mln::accu::meta::math::count t_count_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_rgbn input_rgbn;
+ t_image2d_rgbn output_rgbn;
+ t_histo3d histo;
+ t_histo3d opened;
+
+ mln::io::ppm::load(input_rgb8, image.c_str());
+
+// unsigned nb_pixel = input_rgb8.ncols() * input_rgb8.nrows();
+// unsigned min_volume = (unsigned)(nb_pixel * 0.054);
+ unsigned nb_color = 0;
+
+ input_rgbn = mln::data::transform(input_rgb8, t_rgb8_to_rgbn());
+ histo = mln::data::compute(t_histo3d_fun(), input_rgbn);
+ nb_color = mln::data::compute(t_count_fun(),
+ (histo | (mln::pw::value(histo) != 0)).rw());
+
+ return nb_color;
+}
+
+
+/// \brief Main entry.
+///
+/// Print the number of colors.
+int main()
+{
+ unsigned val=count_image_color<8>(ANNOTATING_1_PHOTO_IMG_PATH "/photo01.ppm");
+
+ std::cout << "nb color : " << val << std::endl;
+
+ return 0;
+}
+
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/project/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/project/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/project/project.cc b/scribo/sandbox/green/demo/annotating/project/project.cc
new file mode 100644
index 0000000..4cab73c
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/project/project.cc
@@ -0,0 +1,275 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet PROJECT descriptor [millet.phd.2008.pdf]
+///
+/// This is an image descriptor. It works a grey level image. First,
+/// we make subsampling of the image to the size 100x100. Then Sobel
+/// is applied. After that, we divide the image in 2 sub-images with
+/// horizontal or vertical splitting. Projection (summing along a
+/// direction) is done in a way that preserves a vector of size
+/// 100. Finally, it results 4 vector of size 100 which are concatened
+/// to build the descriptor.
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/accu/image/init.hh>
+#include <mln/accu/image/take.hh>
+#include <mln/accu/image/to_result.hh>
+#include <mln/accu/stat/mean.hh>
+
+#include <mln/binarization/threshold.hh>
+
+#include <mln/core/alias/box2d.hh>
+#include <mln/core/alias/point2d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/core/routine/initialize.hh>
+#include <mln/core/image/dmorph/unproject_image.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/convert.hh>
+#include <mln/data/paste.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/fun/v2v/projection.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/pbm/save.hh>
+
+#include <mln/linear/sobel_2d.hh>
+
+#include <mln/opt/at.hh>
+
+/// \brief get the sub-image name.
+///
+/// \param[in] base the common part of the name.
+/// \param[in] i the column.
+/// \param[in] j the line.
+///
+/// \result the complete name of the sub-image.
+///
+/// This function builds the complete name of a sub-image by making
+/// explicit its position in the array.
+const char *get_name(const char *base, const unsigned i, const unsigned j)
+{
+ std::ostringstream name;
+
+ name << base;
+ name << i;
+ name << "_";
+ name << j;
+ name << ".ppm";
+
+ return name.str().c_str();
+}
+
+
+/// \brief Project row data.
+///
+/// \param[in] img the binary image converted to u_int8.
+///
+/// \ return a vector.
+///
+/// This routine "eats" one dimension of the image by making a
+/// projection. The projection sums the pixel along a specific
+/// direction. It results a vector.
+mln::image1d<mln::value::int_u8>
+project_row(const mln::image2d<mln::value::int_u8>& img)
+{
+ typedef mln::accu::math::sum<mln::value::int_u8,mln::value::int_u8> t_sum;
+ typedef mln::fun::v2v::projection<mln::point2d,0> t_projection;
+
+ mln::image1d<t_sum> img_accu(img.ncols());
+
+ mln::accu::image::init(img_accu);
+
+ mln::accu::image::take(unproject(img_accu,
+ img.domain(),
+ t_projection()).rw(),
+ img);
+
+ return mln::accu::image::to_result(img_accu);
+}
+
+
+/// \brief Project column data.
+///
+/// \param[in] img the binary image converted to u_int8.
+///
+/// \ return a vector.
+///
+/// This routine "eats" one dimension of the image by making a
+/// projection. The projection sums the pixel along a specific
+/// direction. It results a vector.
+mln::image1d<mln::value::int_u8>
+project_col(const mln::image2d<mln::value::int_u8>& img)
+{
+ typedef mln::accu::math::sum<mln::value::int_u8,mln::value::int_u8> t_sum;
+ typedef mln::fun::v2v::projection<mln::point2d,1> t_projection;
+
+ mln::image1d<t_sum> img_accu(img.nrows());
+
+ mln::accu::image::init(img_accu);
+
+ mln::accu::image::take(unproject(img_accu,
+ img.domain(),
+ t_projection()).rw(),
+ img);
+
+ return mln::accu::image::to_result(img_accu);
+}
+
+
+/// \brief The image processing routine.
+///
+/// Describe the processing chain. First subsample the input image to
+/// 100x100. This is done by splitting the image and then compute the
+/// mean of the subimage. The result is a pixel of the subsample
+/// image. Then apply Sobel and threshold. Then split in two
+/// (vertically or horizontally), it results 4 images. Finally, make
+/// the projection.
+int main()
+{
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::algebra::vec<3,float> t_vec3f;
+ typedef mln::algebra::vec<3,unsigned> t_vec3u;
+ typedef mln::image2d<float> t_image2d_float;
+ typedef mln::image2d<bool> t_image2d_bool;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::accu::meta::stat::mean t_mean_fun;
+ typedef mln::accu::math::sum<t_int_u8,t_int_u8> t_sum;
+ typedef mln::image1d<t_int_u8> t_image1d_int_u8;
+
+ t_image2d_int_u8 input_int_u8;
+ t_image2d_float sobel;
+ t_image2d_bool thresh_bool;
+ t_image2d_int_u8 thresh_int_u8;
+
+ // IMAGE LOADING PHASE
+ std::cout << "Image loading phase ..." << std::endl;
+ mln::io::pgm::load(input_int_u8,ICDAR_50P_PGM_IMG_PATH"/mp00082c_50p.pgm");
+
+
+ // IMAGE SPLITTING PHASE
+ t_image2d_int_u8 subimg_int_u8(mln::box2d(mln::point2d(0,0),
+ mln::point2d(100,100)));
+
+ mln::box2d domain = input_int_u8.domain();
+ mln::point2d pmin = domain.pmin();
+ mln::point2d pmax = domain.pmax();
+
+ unsigned sz_row = (pmax.row() - pmin.row())/ 100;
+ unsigned sz_col = (pmax.col() - pmin.col())/ 100;
+
+ std::cout << domain << std::endl;
+
+ // Subsampling in 100x100
+ // FIXME Test that is it a subsampling, not a upsampling!
+ for (unsigned i = 0; i < 100; ++i)
+ for (unsigned j = 0; j < 100; ++j)
+ {
+ mln::point2d min(pmin.row()+sz_row*i,pmin.col()+sz_col*j);
+ mln::point2d max(pmin.row()+sz_row*(i+1),pmin.col()+sz_col*(j+1));
+ mln::box2d dom(min,max);
+
+ std::cout << dom << std::endl;
+
+ // Save it
+ t_image2d_int_u8 input_part_int_u8(dom);
+
+ mln::data::paste(input_int_u8 | dom, input_part_int_u8);
+ //mln::io::pgm::save(input_part_int_u8, get_name("output",i,j));
+ float mean = mln::data::compute(t_mean_fun(), input_part_int_u8);
+ t_int_u8 val = static_cast<t_int_u8>(mean);
+ mln::opt::at(subimg_int_u8, i,j) = val;
+ }
+
+ mln::io::pgm::save(subimg_int_u8, "subimg.pgm");
+
+ sobel = mln::linear::sobel_2d_l1_norm(subimg_int_u8);
+ thresh_bool = mln::binarization::threshold(sobel, 100);
+ thresh_int_u8 = mln::data::convert(t_int_u8(), thresh_bool);
+
+ mln::io::pbm::save(thresh_bool, "subimg.pbm");
+
+ // Define img_up, img_down, img_left, img_right
+ t_image2d_int_u8 img_up(mln::box2d(mln::point2d(0,0),
+ mln::point2d(49,99)));
+
+ mln::data::paste(thresh_int_u8 | img_up.domain(), img_up);
+
+
+ t_image2d_int_u8 img_down(mln::box2d(mln::point2d(50,0),
+ mln::point2d(99,99)));
+
+ mln::data::paste(thresh_int_u8 | img_down.domain(), img_down);
+
+ t_image2d_int_u8 img_left(mln::box2d(mln::point2d(0,0),
+ mln::point2d(99,49)));
+
+ mln::data::paste(thresh_int_u8 | img_left.domain(), img_left);
+
+
+ t_image2d_int_u8 img_right(mln::box2d(mln::point2d(0,50),
+ mln::point2d(99,99)));
+
+ mln::data::paste(thresh_int_u8 | img_right.domain(), img_right);
+
+
+ // Define project_up, project_down, project_left, project_right
+ t_image1d_int_u8 project_up = project_row(img_up);
+ t_image1d_int_u8 project_down = project_row(img_down);
+ t_image1d_int_u8 project_left = project_col(img_left);
+ t_image1d_int_u8 project_right = project_col(img_right);
+
+ mln::io::pgm::save(img_up, "up.pgm");
+ mln::io::pgm::save(img_down, "down.pgm");
+ mln::io::pgm::save(img_left, "left.pgm");
+ mln::io::pgm::save(img_right, "right.pgm");
+
+ // PRINTING PHASE
+
+ std::cout << std::endl << "UP" << std::endl;
+ mln::debug::println(project_up);
+
+ std::cout << std::endl << "DOWN" << std::endl;
+ mln::debug::println(project_down);
+
+ std::cout << std::endl << "LEFT" << std::endl;
+ mln::debug::println(project_left);
+
+ std::cout << std::endl << "RIGHT" << std::endl;
+ mln::debug::println(project_right);
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/rgb_64/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/rgb_64/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/rgb_64/rgb_64.cc b/scribo/sandbox/green/demo/annotating/rgb_64/rgb_64.cc
new file mode 100644
index 0000000..b49f979
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/rgb_64/rgb_64.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet RGB-64 descriptor [millet.phd.2008.pdf]
+///
+/// This is an image descriptor. It works by making 2 bits
+/// quantification on each channel. It result a processing in RGB-64
+/// space. Then we build the color histogram.
+
+#include <iostream>
+
+#include <mln/accu/stat/histo3d_rgb.hh>
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/io/ppm/load.hh>
+
+#include <mln/value/rgb.hh>
+#include <mln/value/rgb8.hh>
+
+/// \brief Main entry.
+///
+/// Loading, Quantifiying in two bits each channel, then building
+/// color histogram.
+int main()
+{
+ typedef mln::fun::v2v::rgb8_to_rgbn<2> t_rgb8_to_rgb2;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<2> t_rgb2;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgb2> t_image2d_rgb2;
+ typedef mln::image3d<unsigned> t_histo3d;
+ typedef mln::accu::meta::stat::histo3d_rgb t_histo3d_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_rgb2 input_rgb2;
+ t_histo3d histo;
+
+ // IMAGE LOADING PHASE
+ std::cout << "Image loading phase ..." << std::endl;
+ mln::io::ppm::load(input_rgb8, ICDAR_50P_PPM_IMG_PATH"/mp00082c_50p.ppm");
+ input_rgb2 = mln::data::transform(input_rgb8, t_rgb8_to_rgb2());
+ histo = mln::data::compute(t_histo3d_fun(), input_rgb2);
+
+ // PRINTING PHASE
+ mln::debug::println(histo);
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/rgb_64_9/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/rgb_64_9/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/rgb_64_9/rgb_64_9.cc b/scribo/sandbox/green/demo/annotating/rgb_64_9/rgb_64_9.cc
new file mode 100644
index 0000000..355cbfd
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/rgb_64_9/rgb_64_9.cc
@@ -0,0 +1,132 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet RGB-64 descriptor [millet.phd.2008.pdf]
+///
+/// This is an image descriptor. It works by making 2 bits
+/// quantification on each channel. It result a processing in RGB-64
+/// space. Then we build the color histogram.
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/accu/stat/histo3d_rgb.hh>
+
+#include <mln/core/alias/box2d.hh>
+#include <mln/core/alias/point2d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/core/routine/initialize.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/paste.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/value/rgb.hh>
+#include <mln/value/rgb8.hh>
+
+/// \brief Get the sub image name.
+///
+/// \return the name of the ith/jth sub image of the array.
+const char *get_name(const char *base, const unsigned i, const unsigned j)
+{
+ std::ostringstream name;
+
+ name << base;
+ name << i;
+ name << "_";
+ name << j;
+ name << ".ppm";
+
+ return name.str().c_str();
+}
+
+/// \brief Same code as rgb-64 but divide the wall image in nine.
+///
+/// Adding a splitting phase for image rgb-64 code reference.
+int main()
+{
+ typedef mln::fun::v2v::rgb8_to_rgbn<2> t_rgb8_to_rgb2;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<2> t_rgb2;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgb2> t_image2d_rgb2;
+ typedef mln::image3d<unsigned> t_histo3d;
+ typedef mln::accu::meta::stat::histo3d_rgb t_histo3d_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_rgb2 input_rgb2;
+ t_histo3d histo;
+
+ // IMAGE LOADING PHASE
+ std::cout << "Image loading phase ..." << std::endl;
+ mln::io::ppm::load(input_rgb8, ICDAR_50P_PPM_IMG_PATH"/mp00082c_50p.ppm");
+
+ input_rgb2 = mln::data::transform(input_rgb8, t_rgb8_to_rgb2());
+
+ // IMAGE SPLITTING PHASE
+ mln::box2d domain = input_rgb2.domain();
+ mln::point2d pmin = domain.pmin();
+ mln::point2d pmax = domain.pmax();
+
+ unsigned sz_row = (pmax.row() - pmin.row())/ 3;
+ unsigned sz_col = (pmax.col() - pmin.col())/ 3;
+
+ std::cout << domain << std::endl;
+
+ // Divide the domain in nine sub-domains.
+ for (unsigned i = 0; i < 3; ++i)
+ for (unsigned j = 0; j < 3; ++j)
+ {
+ mln::point2d min(pmin.row()+sz_row*i,pmin.col()+sz_col*j);
+ mln::point2d max(pmin.row()+sz_row*(i+1),pmin.col()+sz_col*(j+1));
+ mln::box2d dom(min,max);
+
+ std::cout << dom << std::endl;
+
+ // Save it
+ t_image2d_rgb2 input_1o9_rgb2(dom);
+
+ mln::data::paste(input_rgb2 | dom, input_1o9_rgb2);
+ mln::io::ppm::save(input_1o9_rgb2, get_name("output",i,j));
+
+ histo = mln::data::compute(t_histo3d_fun(), input_1o9_rgb2);
+
+ // PRINTING PHASE
+ mln::debug::println(histo);
+ }
+
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/stddev_color/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/stddev_color/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/stddev_color/stddev_color.cc b/scribo/sandbox/green/demo/annotating/stddev_color/stddev_color.cc
new file mode 100644
index 0000000..549834f
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/stddev_color/stddev_color.cc
@@ -0,0 +1,191 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet clipart detection [millet.phd.2008.pdf]
+///
+/// The aim of this descriptor is to recognize clipart. To do this, we
+/// assume that clipart have their histogram concentrated around their
+/// mode. This is particularly true if the clipart is design by hand,
+/// because a very small number of grey tones or colors are used to
+/// draw it. But sometimes, computer assists their creation and we can
+/// find some continuous set of tones and this artefact create noise
+/// for the detection technique describe bellow.
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/max_site.hh>
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb8_to_int_u8.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/math/sqr.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u.hh>
+
+
+
+/// \brief The R function of Millet
+///
+/// \param[in] p the position of the pic.
+/// \param[in] histo_p the histo value of the pic.
+/// \param[in] x the position of the element which we compute the contrib.
+/// \param[in] histo_x the histo value of that element.
+///
+/// \result the contribution of the element x.
+///
+/// This function compute the variance-like contribution of an element
+/// x linked to the pic of the histogram. In fact, every thing is like
+/// we compute a square distance-like between the element x and the
+/// pic in the normalized histogram. Notice that the normalized
+/// histogram is the histogram divide by the value of it's pic. So at
+/// the pic, the value equals 1. It's a current representation of the
+/// histogram in image processing, we can find it in gimp for exemple.
+float r(short p, unsigned histo_p, short x, unsigned histo_x)
+{
+ float result = mln::math::sqr(((float)histo_x / histo_p) * (x-p));
+
+ return result;
+}
+
+/// Brief compute the whole deviation of Millet
+///
+/// \param[in] image the input image to analyze.
+///
+/// \return the deviation.
+///
+/// The deviation uses the R function. It stats by finding the pic. If
+/// the pic is near the rigth border of the histo, compute the R
+/// function on the left neighbouring of the pic. If the pic is near
+/// the left border of the histo, compute the R function on the right
+/// neigbouring. Otherwise, compute the average of the right and left
+/// results. The selected neighbouring is composed of five pixels at
+/// the right or at the left of the pic. The detection of clipart
+/// assumes that the majority of the energy of the histogram is closed
+/// to the pic (five pixels around it).
+unsigned stddev_color(const std::string& image)
+{
+ typedef mln::point1d t_point1d;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image1d<unsigned> t_histo1d;
+ typedef mln::fun::v2v::rgb8_to_int_u8 t_rgb8_to_int_u8;
+ typedef mln::accu::meta::stat::histo1d t_histo1d_fun;
+ typedef mln::accu::max_site<t_histo1d> t_max_site_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_int_u8 input_int_u8;
+ t_histo1d histo;
+ t_point1d max_site;
+
+ mln::io::ppm::load(input_rgb8, image.c_str());
+ input_int_u8 = mln::data::transform(input_rgb8, t_rgb8_to_int_u8());
+ histo = mln::data::compute(t_histo1d_fun(), input_int_u8);
+
+ mln::io::pgm::save(input_int_u8, "tmp.pgm");
+ mln::io::plot::save_image_sh(histo, "histo.sh");
+ mln::debug::println(histo);
+
+ // Find the peak of the histogram
+ unsigned v_max = mln::opt::at(histo, 0);
+ short p_max = 0;
+
+ mln_piter_(t_histo1d) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ // Compute the specific stddev
+
+ float stddev_low = 0.0;
+ float stddev_up = 0.0;
+ float stddev = 0.0;
+
+ if (250 > p_max)
+ for (short i = p_max+1; i < p_max+6; ++i)
+ stddev_up += r(p_max, mln::opt::at(histo,p_max),
+ i, mln::opt::at(histo,i));
+
+ if (5 < p_max)
+ for (short i = p_max-1; i > p_max-6; --i)
+ stddev_low += r(p_max, mln::opt::at(histo,p_max),
+ i, mln::opt::at(histo,i));
+
+ stddev = (250 < p_max)? stddev_low : (5 > p_max)? stddev_up :
+ (stddev_low + stddev_up)/2;
+
+ std::cout << "max_site : " << p_max << std::endl;
+ std::cout << "h(max_site) : " << v_max << std::endl;
+ std::cout << "stddev_up : " << stddev_up << std::endl;
+ std::cout << "stddev_low : " << stddev_low << std::endl;
+ std::cout << "stddev : " << stddev << std::endl;
+
+ return 0;
+}
+
+
+/// \brief Main entry.
+///
+/// Front end for image processing.
+int main()
+{
+// unsigned val = stdev_color(ANNOTATING_1_PHOTO_IMG_PATH "/photo01.ppm");
+ unsigned val = stddev_color(ANNOTATING_1_LOGO_IMG_PATH "/logo06.ppm");
+
+// std::cout << "nb color : " << val << std::endl;
+
+ return 0;
+}
+
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/annotating/stddev_color_16/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/demo/annotating/stddev_color_16/Makefile.am
diff --git a/scribo/sandbox/green/demo/annotating/stddev_color_16/stddev_color_16.cc b/scribo/sandbox/green/demo/annotating/stddev_color_16/stddev_color_16.cc
new file mode 100644
index 0000000..98d94fd
--- /dev/null
+++ b/scribo/sandbox/green/demo/annotating/stddev_color_16/stddev_color_16.cc
@@ -0,0 +1,261 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet clipart detection [millet.phd.2008.pdf]
+///
+/// The aim of this descriptor is to recognize clipart. To do this, we
+/// assume that clipart have their histogram concentrated around their
+/// mode. This is particularly true if the clipart is design by hand,
+/// because a very small number of grey tones or colors are used to
+/// draw it. But sometimes, computer assists their creation and we can
+/// find some continuous set of tones and this artefact create noise
+/// for the detection technique describe bellow. When photographies
+/// has some large uniform border, the detection can fail. To improve
+/// the method, Millet decide to subdivise the image in 16 sub images
+/// on which it applies the test.
+#include <iostream>
+#include <sstream>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/max_site.hh>
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/transform.hh>
+#include <mln/data/paste.hh>
+
+#include <mln/fun/v2v/rgb8_to_int_u8.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/math/sqr.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u.hh>
+
+
+/// \brief The R function of Millet
+///
+/// \param[in] p the position of the pic.
+/// \param[in] histo_p the histo value of the pic.
+/// \param[in] x the position of the element which we compute the contrib.
+/// \param[in] histo_x the histo value of that element.
+///
+/// \result the contribution of the element x.
+///
+/// This function compute the variance-like contribution of an element
+/// x linked to the pic of the histogram. In fact, every thing is like
+/// we compute a square distance-like between the element x and the
+/// pic in the normalized histogram. Notice that the normalized
+/// histogram is the histogram divide by the value of it's pic. So at
+/// the pic, the value equals 1. It's a current representation of the
+/// histogram in image processing, we can find it in gimp for exemple.
+float r(short p, unsigned histo_p, short x, unsigned histo_x)
+{
+ float result = mln::math::sqr(((float)histo_x / histo_p) * (x-p));
+
+ return result;
+}
+
+/// Brief compute the whole deviation of Millet
+///
+/// \param[in] input_int_u8 the 8 bits input image to analyze.
+/// \param[in] name_histo the name of the output histogram.
+/// \param[in] name_image the name of the ouput sub image.
+///
+/// \return the deviation, but at this time nothing..
+///
+/// The deviation uses the R function. It stats by finding the pic. If
+/// the pic is near the rigth border of the histo, compute the R
+/// function on the left neighbouring of the pic. If the pic is near
+/// the left border of the histo, compute the R function on the right
+/// neigbouring. Otherwise, compute the average of the right and left
+/// results. The selected neighbouring is composed of five pixels at
+/// the right or at the left of the pic. The detection of clipart
+/// assumes that the majority of the energy of the histogram is closed
+/// to the pic (five pixels around it).
+unsigned stddev_color(mln::image2d<mln::value::int_u8> input_int_u8,
+ const char *name_histo,
+ const char *name_image)
+{
+ typedef mln::point1d t_point1d;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image1d<unsigned> t_histo1d;
+ typedef mln::fun::v2v::rgb8_to_int_u8 t_rgb8_to_int_u8;
+ typedef mln::accu::meta::stat::histo1d t_histo1d_fun;
+ typedef mln::accu::max_site<t_histo1d> t_max_site_fun;
+
+ t_histo1d histo;
+
+ std::cout << "histo : " << name_histo << std::endl;
+ std::cout << "image : " << name_image << std::endl;
+
+ histo = mln::data::compute(t_histo1d_fun(), input_int_u8);
+
+ mln::io::pgm::save(input_int_u8, name_image);
+ mln::io::plot::save_image_sh(histo, name_histo);
+ mln::debug::println(histo);
+
+ // Find the peak of the histogram
+ unsigned v_max = mln::opt::at(histo, 0);
+ short p_max = 0;
+
+ mln_piter_(t_histo1d) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ // Compute the specific stddev
+
+ float stddev_low = 0.0;
+ float stddev_up = 0.0;
+ float stddev = 0.0;
+
+ if (250 > p_max)
+ for (short i = p_max+1; i < p_max+6; ++i)
+ stddev_up += r(p_max, mln::opt::at(histo,p_max),
+ i, mln::opt::at(histo,i));
+
+ if (5 < p_max)
+ for (short i = p_max-1; i > p_max-6; --i)
+ stddev_low += r(p_max, mln::opt::at(histo,p_max),
+ i, mln::opt::at(histo,i));
+
+ stddev = (250 < p_max)? stddev_low : (5 > p_max)? stddev_up :
+ (stddev_low + stddev_up)/2;
+
+ std::cout << "max_site : " << p_max << std::endl;
+ std::cout << "h(max_site) : " << v_max << std::endl;
+ std::cout << "stddev_up : " << stddev_up << std::endl;
+ std::cout << "stddev_low : " << stddev_low << std::endl;
+ std::cout << "stddev : " << stddev << std::endl;
+
+ return 0;
+}
+
+
+/// \brief Divide the image in 16 sub images.
+///
+/// \param[in] image the input image.
+///
+/// \result nothing.
+///
+/// Divive the input image in 16 by uniform and geometrical
+/// method. When a sub image is ready, call the stddev routine to show
+/// stats on it.
+unsigned stddev_color_16(const std::string& image)
+{
+ typedef mln::point1d t_point1d;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image1d<unsigned> t_histo1d;
+ typedef mln::fun::v2v::rgb8_to_int_u8 t_rgb8_to_int_u8;
+ typedef mln::accu::meta::stat::histo1d t_histo1d_fun;
+ typedef mln::accu::max_site<t_histo1d> t_max_site_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_int_u8 input_int_u8;
+
+ mln::io::ppm::load(input_rgb8, image.c_str());
+ input_int_u8 = mln::data::transform(input_rgb8, t_rgb8_to_int_u8());
+
+ // IMAGE SPLITTING PHASE
+ mln::box2d domain = input_int_u8.domain();
+ mln::point2d pmin = domain.pmin();
+ mln::point2d pmax = domain.pmax();
+
+ unsigned sz_row = (pmax.row() - pmin.row())/ 4;
+ unsigned sz_col = (pmax.col() - pmin.col())/ 4;
+
+ std::cout << domain << std::endl;
+
+ // Divide the domain in nine sub-domains.
+ for (unsigned i = 0; i < 4; ++i)
+ for (unsigned j = 0; j < 4; ++j)
+ {
+ mln::point2d min(pmin.row()+sz_row*i,pmin.col()+sz_col*j);
+ mln::point2d max(pmin.row()+sz_row*(i+1),pmin.col()+sz_col*(j+1));
+ mln::box2d dom(min,max);
+
+ std::cout << dom << std::endl;
+
+ // Save it
+ t_image2d_int_u8 input_1o16_int_u8(dom);
+ std::ostringstream name_histo("");
+ std::ostringstream name_image("");
+
+ name_histo << "histo" << i << "_" << j << ".sh";
+ name_image << "image" << i << "_" << j << ".ppm";
+
+ mln::data::paste(input_int_u8 | dom, input_1o16_int_u8);
+
+ stddev_color(input_1o16_int_u8,
+ name_histo.str().c_str(),
+ name_image.str().c_str());
+ }
+
+ return 0;
+}
+
+
+/// \brief Main entry.
+///
+/// Just a front end for image processing routine.
+int main()
+{
+// unsigned val = stddev_color_16(ANNOTATING_1_PHOTO_IMG_PATH "/photo01.ppm");
+ unsigned val = stddev_color_16(ANNOTATING_1_LOGO_IMG_PATH "/logo06.ppm");
+
+// std::cout << "nb color : " << val << std::endl;
+
+ return 0;
+}
+
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/achromastism/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/achromastism/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/achromastism/achromastism.cc b/scribo/sandbox/green/exp/annotating/achromastism/achromastism.cc
new file mode 100644
index 0000000..3486b20
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/achromastism/achromastism.cc
@@ -0,0 +1,179 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+
+/// \file
+///
+/// \brief Implement the Millet achromatism operator [millet.phd.2008.pdf]
+///
+/// An image is said to be achromatic when have the RGB channel which
+/// are quite identicals.
+
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/stretch.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/math/max.hh>
+#include <mln/math/min.hh>
+
+#include <mln/geom/nsites.hh>
+
+#include <mln/fun/v2v/rgb_to_achromatism_map.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/value/rgb8.hh>
+
+
+/// \brief Sum all the bins of the histogram.
+///
+/// \param[in] img the histogram based on image.
+///
+/// \return the sum of the overall bins.
+///
+/// Sum evry bins and return the result.
+template <typename I>
+unsigned count_histo(const mln::Image<I>& img_)
+{
+ const I& img = exact(img_);
+
+ mln_precondition(img.is_valid());
+
+ unsigned result = 0;
+
+ mln_piter(I) p(img.domain());
+
+ for_all(p)
+ result += img(p);
+
+ return result;
+}
+
+/// \brief Decide if an image is achromatic or not [Millet].
+///
+/// \param[in] input the input image.
+/// \param[in] output the histogram of the achromatic map.
+/// \param[in] threshold the distance threshold used for equality.
+///
+/// This is an improving of the Millet test. The original test
+/// compares rgb values to each other and look at differences greater
+/// than the threshold. If the number of pixel that pass the test are
+/// greater than 99.0, then the image is declared achromatic. In fact,
+/// there is few variations between the three channels, so we can say
+/// that it is like a grey image. We can with no too distortions
+/// replace the color image by the grey one. The improving is in first
+/// creating a map of the difference. As we can't keep the free
+/// differences between channels, we look at reducing the test and we
+/// find an equivalent one based on the difference between minima
+/// channel value and the maxima channel value. After the map is
+/// ready, we make binarization with the threshold. Then we compute
+/// the histogram 1d for every pixels of the map that are greater the
+/// threshold. Then, we count pixels in the histogram and traduce the
+/// count in percentage to compare to the second threshold. Details
+/// are saved in files and printed in the screen.
+float achromatism_test(const std::string input,
+ const std::string output,
+ const unsigned threshold)
+
+{
+ typedef mln::fun::v2v::rgb_to_achromatism_map<8> t_rgb_to_achromatism_map;
+
+ mln::image2d<mln::value::rgb8> input_rgb8;
+ mln::image2d<mln::value::int_u8> map;
+ mln::image1d<unsigned> histo;
+ unsigned cnt1;
+ unsigned cnt2;
+ float prop;
+
+ mln::io::ppm::load(input_rgb8, input.c_str());
+
+ map = mln::data::transform(input_rgb8, t_rgb_to_achromatism_map());
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), map);
+ cnt1 = count_histo(histo | mln::box1d(mln::point1d(0),
+ mln::point1d(threshold)));
+ cnt2 = mln::geom::nsites(input_rgb8);
+ prop = ((100.0 * cnt1) / cnt2);
+
+ mln::io::plot::save_image_sh(histo, output.c_str());
+
+ return prop;
+}
+
+
+/// \brief The main entry.
+///
+/// Deal with boost library for walking over image database
+/// directories. Call the image processing routine and compute some
+/// stats on the result.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+ t_path full_path[] = {t_path(ICDAR_20P_PPM_IMG_PATH)};
+
+ for (int i = 0; i < 1; ++i)
+ {
+ std::cout << "entering " << full_path[i] << std::endl;
+
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ float prop = 0.0;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ // concatenation de chaine
+ t_path directory(ANNOTATING_RET_PATH);
+ t_path leaf = dir_iter->path().leaf();
+ t_path output = change_extension(directory / leaf, ".sh");
+
+ prop = achromatism_test(dir_iter->path().string(),
+ output.string(),
+ 11);
+
+ std::cout << output << " : " << prop << std::endl;
+ std::cerr << output << " : " << prop << std::endl;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-color.txt b/scribo/sandbox/green/exp/annotating/achromastism/text-color.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-color.txt
copy to scribo/sandbox/green/exp/annotating/achromastism/text-color.txt
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-img.txt b/scribo/sandbox/green/exp/annotating/achromastism/text-img.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-img.txt
copy to scribo/sandbox/green/exp/annotating/achromastism/text-img.txt
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-only.txt b/scribo/sandbox/green/exp/annotating/achromastism/text-only.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-only.txt
copy to scribo/sandbox/green/exp/annotating/achromastism/text-only.txt
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/bench/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/bench/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/bench/bench.cc b/scribo/sandbox/green/exp/annotating/bench/bench.cc
new file mode 100644
index 0000000..102a896
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/bench/bench.cc
@@ -0,0 +1,1450 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// This file is the final work to differentiate between the two image
+/// databases AFP and ICDAR. Several tests are used to show
+/// improvement of detection. The jonathan's tests are put together to
+/// compare them to the others (in fact, to the low saturation one).
+
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/algebra/vec.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/stat/mean.hh>
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/arith/minus.hh>
+#include <mln/arith/times.hh>
+#include <mln/arith/diff_abs.hh>
+#include <mln/arith/div.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/core/alias/point1d.hh>
+#include <mln/core/alias/box1d.hh>
+
+#include <mln/data/transform.hh>
+#include <mln/data/compute.hh>
+#include <mln/data/convert.hh>
+#include <mln/data/stretch.hh>
+#include <mln/data/fill.hh>
+
+#include <mln/fun/v2v/component.hh>
+#include <mln/fun/v2v/rgb_to_hue_map.hh>
+#include <mln/fun/v2v/rgb_to_saturation_map.hh>
+#include <mln/fun/v2v/rgb_to_value_map.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/literal/zero.hh>
+
+#include <mln/math/ceil.hh>
+#include <mln/math/floor.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/trait/value_.hh>
+
+#include <mln/value/rgb8.hh>
+
+
+#include <mln/value/int_u8.hh>
+
+/// Histogram part.
+///
+/// We regroup here the routines that work on histogram, count_histo,
+/// sum_frequency_histo, peak_histo, count_null_frequency_histo,
+/// cmp_equi_frequency_histo and others (variance
+/// operators). count_histo and sum_frequency_histo count the overall
+/// frequency in the domain. peak_histo find the peak of the
+/// histogram. count_null_frequency_histo compute the number of non
+/// grey levels. cmp_equi_frequency_histo compare a histogram with
+/// the one with the same frequency everywhere.
+/// \{
+template <typename I>
+mln_value(I) count_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) result = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ result += histo(p);
+
+ return result;
+}
+
+
+template <typename I>
+mln_value(I) sum_frequency_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) sum = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ sum += histo(p);
+
+ return sum;
+}
+
+
+template <typename I>
+mln_coord(mln_site_(I)) peak_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the peak of the histogram
+ mln_value(I) v_max = mln::opt::at(histo, mln::literal::zero);
+ mln_coord(mln_site_(I)) p_max = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ return p_max;
+}
+
+template <typename I>
+mln_value(I) count_null_frequency_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) count = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ if (0 == histo(p))
+ count++;
+
+ return count;
+}
+
+template <typename I>
+float cmp_equi_frequency_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ float sum = 0;
+ float var = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum ++;
+ var += mln::math::sqr(histo(p) - (1/256.0));
+ }
+
+ var = var / sum;
+
+ return var;
+}
+
+template <typename I>
+mln_value(I) cnt_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) sum = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum += histo(p);
+ }
+
+ return sum;
+}
+
+template <typename I>
+mln_value(I) sum_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ pos = p.ind();
+ sum += pos*histo(p);
+ }
+
+ return sum;
+}
+
+template <typename I>
+mln_value(I) avg_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_value(I) cnt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ pos = p.ind();
+ cnt += histo(p);
+ sum += pos*histo(p);
+ }
+
+ return (0 == cnt)? 0 : sum/cnt;
+}
+
+template <typename I>
+mln_value(I) var3_histo(const mln::Image<I>& histo_, float mean)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_value(I) cnt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ cnt += histo(p);
+ sum += (mln::math::sqr(p.ind()-mean)*histo(p));
+ }
+
+ return (0 == cnt)? 0 : sum/cnt;
+}
+
+template <typename I>
+mln_value(I) var2_histo(const mln::Image<I>& histo_, float mean)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_value(I) sqr = mln::literal::zero;
+ mln_value(I) cnt = mln::literal::zero;
+ mln_value(I) dlt = mln::literal::zero;
+ mln_value(I) mxt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ pos = p.ind();
+ cnt += (histo(p));
+ sum += (histo(p)*pos);
+ mxt += (histo(p)*pos*mean);
+ sqr += (histo(p)*mln::math::sqr(pos));
+ dlt += (histo(p)*mln::math::sqr(pos - mean));
+
+ std::cout << "p = " << pos << std::endl;
+ std::cout << "p² = " << mln::math::sqr(pos) << std::endl;
+ std::cout << "p*mean = " << (pos*mean) << std::endl;
+ std::cout << "p-mean = " << (pos-mean) << std::endl;
+ std::cout << "(p-mean)² = " << mln::math::sqr(pos-mean) << std::endl;
+ std::cout << "histo(p) = " << histo(p) << std::endl;
+ std::cout << "histo(p)*p = " << (pos*histo(p)) << std::endl;
+ std::cout << "histo(p)*p²= " << (mln::math::sqr(pos)*histo(p))
+ << std::endl;
+ std::cout << "cnt = " << cnt << std::endl;
+ std::cout << "sum = " << sum << std::endl;
+ std::cout << "sqr = " << sqr << std::endl;
+ std::cout << "dlt = " << dlt << std::endl;
+ std::cout << "mxt = " << mxt << std::endl;
+ std::cout << std::endl;
+ }
+
+ std::cout << "sqr/cnt = " << (sqr/cnt) << std::endl;
+ std::cout << "sum/cnt = " << (sum/cnt) << std::endl;
+ std::cout << "(sum/cnt)² = " << mln::math::sqr(sum/cnt) << std::endl;
+ std::cout << "dlt/cnt = " << dlt/cnt << std::endl;
+ std::cout << "mxt/cnt = " << mxt/cnt << std::endl;
+ std::cout << std::endl;
+
+ std::cout << "sqr = "
+ << (sqr) << std::endl;
+ std::cout << "dlt = "
+ << (dlt) << std::endl;
+ std::cout << "cnt*avg² = "
+ << (mln::math::sqr(sum/cnt)*cnt) << std::endl;
+ std::cout << "2*mxt = "
+ << (2*mxt) << std::endl;
+ std::cout << "sqr - cnt*avg² = "
+ << (sqr/cnt - mln::math::sqr(sum/cnt)) << std::endl;
+ std::cout << "(sqr -2*mxt + cnt*avg²) = "
+ << ((sqr - 2*mxt + mln::math::sqr(sum/cnt))/cnt) << std::endl;
+ std::cout << std::endl;
+ return (0 == cnt)? 0 : sqr/cnt - mln::math::sqr(sum/cnt);
+}
+
+template <typename I>
+mln_value(I) var_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_value(I) sqr = mln::literal::zero;
+ mln_value(I) cnt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ pos = p.ind();
+ cnt += (histo(p));
+ sum += (histo(p)*pos);
+ sqr += (histo(p)*mln::math::sqr(pos));
+ }
+
+ return (0 == cnt)? 0 : sqr/cnt - mln::math::sqr(sum/cnt);
+}
+
+template <typename I>
+mln_value(I) sqr_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) sum = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ sum += (mln::math::sqr(p.ind())*histo(p));
+
+ return sum;
+}
+/// \}
+
+
+/// \brief Millet Hue detector.
+///
+/// \param[in] histo the histogram image on which applying the detector.
+/// \param[in] threshold a way to adapt the test to the population.
+///
+/// \return the proportion of population that verify the hue detector.
+///
+/// This test is used for discrimination between black and white pictures and
+/// color ones. Some colored Black and white pictures have their energy near
+/// the peak.
+float hue1_descriptor(mln::image1d<unsigned> histo, const short threshold)
+{
+ float cnt1;
+ float cnt2;
+ float prop;
+ short peak;
+ mln::point1d inf;
+ mln::point1d sup;
+
+ peak = peak_histo(histo);
+ inf = mln::point1d(mln::math::max(0, peak-threshold));
+ sup = mln::point1d(mln::math::min(255, peak+threshold));
+ cnt1 = count_histo(histo|mln::box1d(inf,sup));
+ cnt2 = count_histo(histo);
+ prop = ((255.0 * cnt1) / cnt2);
+
+ return prop;
+}
+
+
+/// \brief Saturation detector.
+///
+/// \param[in] histo the histogram image on which applying the detector.
+/// \param[in] threshold a way to adapt the test to the population.
+///
+/// \return the proportion of population that verify the hue detector.
+///
+/// This test is used for discrimination between black and white pictures and
+/// color ones. Black and white pictures have their energy in the low saturation
+/// band.
+float sat1_descriptor(mln::image1d<unsigned> histo, const short threshold)
+{
+ float cnt1;
+ float cnt2;
+ float result;
+
+ cnt1 = count_histo(histo | mln::box1d(mln::point1d(0),
+ mln::point1d(threshold)));
+ cnt2 = count_histo(histo);
+ result = ((255.0 * cnt1) / cnt2);
+
+ return result;
+}
+
+
+/// \brief Counting grey levels descriptor.
+///
+/// \param[in] histo the histogram image on which applying the detector.
+///
+/// \return the number of grey levels.
+///
+/// This test aims at compute the number of grey levels. Photographies tends to
+/// use all the levels or many of them.
+float lvl0_descriptor(mln::image1d<unsigned> histo)
+{
+ float result;
+
+ // FIXME 255
+ result = 255-count_null_frequency_histo(histo);
+
+ return result;
+}
+
+
+/// \brief Density hue detector.
+///
+/// \param[in] histo the histogram image on which applying the detector.
+///
+/// \return the proportion of population that verify the hue detector.
+///
+/// This test works on density histogram and compare to the
+/// equi-frequency histogram. If the normalized histogram show a peak,
+/// it will differ from the reference density.
+float hue0_descriptor(mln::image1d<unsigned> histo)
+{
+ mln::image1d<float> histo_float;
+ float sum;
+ float result;
+
+ sum = sum_frequency_histo(histo);
+ histo_float = mln::data::convert(float(), histo) / sum;
+ result = cmp_equi_frequency_histo(histo_float);
+
+ return result*255;
+}
+
+
+/// \brief Density saturation detector.
+///
+/// \param[in] histo the histogram image on which applying the detector.
+///
+/// \return the proportion of population that verify the hue detector.
+///
+/// This test works on density histogram and compare to the
+/// equi-frequency histogram. If the normalized histogram show a peak,
+/// it will differ from the reference density.
+float sat0_descriptor(mln::image1d<unsigned> histo)
+{
+ mln::image1d<float> histo_float;
+ float sum;
+ float result;
+
+ sum = sum_frequency_histo(histo);
+ histo_float = mln::data::convert(float(), histo) / sum;
+ result = cmp_equi_frequency_histo(histo_float);
+
+ return result*255;
+}
+
+
+/// \brief Density value detector.
+///
+/// \param[in] histo the histogram image on which applying the detector.
+///
+/// \return the proportion of population that verify the hue detector.
+///
+/// This test works on density histogram and compare to the
+/// equi-frequency histogram. If the normalized histogram show a peak,
+/// it will differ from the reference density.
+float val0_descriptor(mln::image1d<unsigned> histo)
+{
+ mln::image1d<float> histo_float;
+ float sum;
+ float result;
+
+ sum = sum_frequency_histo(histo);
+ histo_float = mln::data::convert(float(), histo) / sum;
+ result = cmp_equi_frequency_histo(histo_float);
+
+ return result*255;
+}
+
+
+/// \brief The R function of Millet
+///
+/// \param[in] p the position of the pic.
+/// \param[in] histo_p the histo value of the pic.
+/// \param[in] x the position of the element which we compute the contrib.
+/// \param[in] histo_x the histo value of that element.
+///
+/// \result the contribution of the element x.
+///
+/// This function compute the variance-like contribution of an element
+/// x linked to the pic of the histogram. In fact, every thing is like
+/// we compute a square distance-like between the element x and the
+/// pic in the normalized histogram. Notice that the normalized
+/// histogram is the histogram divide by the value of it's pic. So at
+/// the pic, the value equals 1. It's a current representation of the
+/// histogram in image processing, we can find it in gimp for exemple.
+float r(short p, unsigned histo_p, short x, unsigned histo_x)
+{
+ float result = mln::math::sqr(((float)histo_x / histo_p) * (x-p));
+
+ return result;
+}
+
+/// \brief The stddev3 is an internal stuff.
+///
+/// \param[in] histo_ the image which represents the histogram.
+/// \param[in] peak the position of the histogram peak.
+///
+/// \return simple computing of deviation.
+///
+/// This is an internal stuff. It splits the computing for easy
+/// reusing practice. Sum the R contribution.
+template <typename I>
+float stddev3(const mln::Image<I>& histo_, unsigned peak)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Compute stddev
+
+ float stddev = 0.0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ stddev += r((short)peak, mln::opt::at(histo,peak), p.ind(), histo(p));
+ }
+
+ return stddev;
+}
+
+/// Brief compute the whole deviation of Millet
+///
+/// \param[in] image the input image to analyze.
+/// \param[in] peak the peak of the histogram.
+/// \param[in] limit the threshold to compute the contribution.
+///
+/// \return the deviation.
+///
+/// The deviation uses the R function. It stats by finding the pic. If
+/// the pic is near the rigth border of the histo, compute the R
+/// function on the left neighbouring of the pic. If the pic is near
+/// the left border of the histo, compute the R function on the right
+/// neigbouring. Otherwise, compute the average of the right and left
+/// results. The selected neighbouring is composed of five pixels at
+/// the right or at the left of the pic. The detection of clipart
+/// assumes that the majority of the energy of the histogram is closed
+/// to the pic (five pixels around it). The test is generalized by
+/// making constants as parameters.
+template <typename I>
+float stddev2(const mln::Image<I>& histo_, unsigned peak, unsigned limit)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ float stddev_low = 0.0;
+ float stddev_up = 0.0;
+ float ret = 0.0;
+
+ // A transformer avec des iterators
+
+ if (250 > peak)
+ stddev_up = stddev3(histo |mln::box1d(mln::point1d(peak+1),
+ mln::point1d(peak+limit)), peak);
+
+ if (5 < peak)
+ stddev_low = stddev3(histo |mln::box1d(mln::point1d(peak-limit),
+ mln::point1d(peak-1)), peak);
+
+ ret = (250 < peak)? stddev_low : (5 > peak)? stddev_up :
+ (stddev_low + stddev_up)/2;
+
+ return ret;
+}
+
+
+/// \brief Millet value descriptor (cf. Millet.phd.2008)
+///
+/// \param[in] histo the histogram image on which applying the detector.
+/// \param[in] threshold the limit where to compute the contribution.
+///
+/// \return the proportion of population that verify the hue detector.
+///
+/// This test aims at compute some deviation on the peak of the histogram of
+/// the image. Large deviations mean lots of graduation in colors (such as
+/// photos) and small ones mean something like cartoon.
+float val1_descriptor(mln::image1d<unsigned> histo, const short threshold)
+{
+ typedef mln::fun::v2v::rgb_to_value_map<8> t_rgb_to_value_map;
+
+ float result;
+ short peak;
+
+ peak = peak_histo(histo);
+ result = stddev2(histo, peak, threshold);
+
+ return result;
+}
+
+
+/// \brief Error detector (jonathan idea).
+///
+/// \param[in] r_img_map the original red channel.
+/// \param[in] g_img_map the original green channel.
+/// \param[in] b_img_map the original blue channel.
+/// \param[in] r_rdc_map the reduced (in color) red channel.
+/// \param[in] g_rdc_map the reduced (in color) green channel.
+/// \param[in] b_rdc_map the reduced (in color) blue channel.
+///
+/// \return the PNSNR (cf compression p278 Handbook Color).
+///
+/// \fixme the actual PNSNR is unbound, we need to fix its max to
+/// 255. Two images which are the same produces an infinite PNSNR.
+float err_descriptor(mln::image2d<mln::value::int_u8> r_img_map,
+ mln::image2d<mln::value::int_u8> g_img_map,
+ mln::image2d<mln::value::int_u8> b_img_map,
+ mln::image2d<mln::value::int_u8> r_rdc_map,
+ mln::image2d<mln::value::int_u8> g_rdc_map,
+ mln::image2d<mln::value::int_u8> b_rdc_map)
+
+
+{
+ typedef mln::accu::meta::stat::mean t_mean;
+ typedef mln::image2d<mln::value::int_u8> t_map;
+ typedef mln_trait_op_minus_(t_map,t_map) t_minus;
+ typedef mln_trait_op_times_(t_minus,t_minus) t_times;
+
+
+ t_minus minus_red;
+ t_minus minus_green;
+ t_minus minus_blue;
+
+ t_times times_red;
+ t_times times_green;
+ t_times times_blue;
+
+ float error_red;
+ float error_green;
+ float error_blue;
+
+ float error;
+
+ minus_red = (r_img_map - r_rdc_map);
+ times_red = minus_red * minus_red;
+
+ minus_green = (g_img_map - g_rdc_map);
+ times_green = minus_green * minus_green;
+
+ minus_blue = (b_img_map - b_rdc_map);
+ times_blue = minus_blue * minus_blue;
+
+ error_red = mln::data::compute(t_mean(), times_red);
+ error_green = mln::data::compute(t_mean(), times_green);
+ error_blue = mln::data::compute(t_mean(), times_blue);
+
+ error = (error_red + error_green + error_blue)/3.0;
+ error = mln::math::sqrt(error);
+ error = 20 * log(255/error);
+
+// FIXME:
+// SAME IMAGE PRODUCE PNSNR GOING THROW THE INFINITY.
+// DIFFERENT IMAGE PRODUCE PNSNR GOING NEAR ZERO.
+// WE SHOULD KEEP THE PNSNR BELOW 255 FOR COMPARAISON.
+
+ return error;
+}
+
+/// Discriminant operators.
+///
+/// We have some operators that compute the threshold which separate
+/// two sub-populations in a histogram.
+/// /{
+
+/// \brief Compute discrimination threshold.
+/// \param[in] avg1 the mean of the population 1.
+/// \param[in] var1 the variance of the population 1.
+/// \param[in] avg2 the mean of the population 2.
+/// \param[in] var2 the variance of the population 2.
+///
+/// \return the threshold to discriminate the two populations.
+///
+/// Linear discriminant analysis in 1d is done. When two population
+/// have the same variance, the threshold is at (m1+m2)/2. When threre
+/// are different variances, we propose the threshold at the position
+/// (m1*sqrt(v1)+m2*sqrt(v2))/(sqrt(v1)+sqrt(v2)).
+float threshold_histo(float avg1, float var1, float avg2, float var2)
+{
+ float sigma1 = mln::math::sqrt(var1);
+ float sigma2 = mln::math::sqrt(var2);
+ float threshold = (avg1*sigma1+avg2*sigma2)/(sigma1+sigma2);
+
+ return threshold;
+}
+
+/// \brief Compute discrimination threshold.
+/// \param[in] avg1 the mean of the population 1.
+/// \param[in] var1 the variance of the population 1.
+/// \param[in] avg2 the mean of the population 2.
+/// \param[in] var2 the variance of the population 2.
+///
+/// \return the threshold to discriminate the two populations.
+///
+/// Linear discriminant analysis in 1d is done. When two population
+/// have the same variance, the threshold is at (m1+m2)/2. When threre
+/// are different variances, we propose the threshold at the position
+/// (m1*var1+m2*var2)/(sqrt(v1)+sqrt(v2)).
+
+float threshold3_histo(float avg1, float var1, float avg2, float var2)
+{
+ float threshold = (avg1*var1+avg2*var2)/(var1+var2);
+
+ return threshold;
+}
+
+
+/// \brief Compute discrimination threshold.
+/// \param[in] avg1 the mean of the population 1.
+/// \param[in] var1 the variance of the population 1.
+/// \param[in] avg2 the mean of the population 2.
+/// \param[in] var2 the variance of the population 2.
+///
+/// \return the threshold to discriminate the two populations.
+///
+/// Gaussian discriminant analysis in 1d is done. Compute the
+/// discrimanation and solve the parabolic equation.
+float threshold2_histo(float avg1, float var1, float avg2, float var2)
+{
+ float a = var2 - var1;
+ float b = -2 * (avg1 * var2 - avg2 * var1);
+ float c = var2 * mln::math::sqr(avg1) - var1 * mln::math::sqr(avg2);
+ float d = mln::math::sqr(b) - 4 * a * c;
+
+ if (d < 0)
+ std::cout << "delta negatif" << std::endl;
+
+ float x1 = (-b+mln::math::sqrt(d))/(2*a);
+ float x2 = (-b-mln::math::sqrt(d))/(2*a);
+
+ std::cout << "a = " << a << std::endl;
+ std::cout << "b = " << b << std::endl;
+ std::cout << "c = " << c << std::endl;
+ std::cout << "d = " << d << std::endl;
+ std::cout << "x1 = " << x1 << std::endl;
+ std::cout << "x2 = " << x2 << std::endl;
+
+ return x2;
+}
+
+/// \brief Minimisation of the error.
+///
+/// \param[in] histo_grp1 the histogram of the first population.
+/// \param[in] histo_grp2 the histogram of the second population.
+///
+/// \return the threshold.
+///
+/// Computes the error and find the minimum error threshold. It's just
+/// a counting of element in four categories (0 - but detects 1, 1 -
+/// but detects 1, 1 but detects 0, 0 but detects 0). The error is the
+/// sum of missclassifications for the classes 0 and 1. As Otsu done,
+/// we can iterate on the threshold and compute the error associated
+/// to it. The bes threshold is the one that minimize the error.
+short min_error(const mln::image1d<float> histo_grp1,
+ const mln::image1d<float> histo_grp2,
+ float *_c00, float *_c10, float *_c01, float *_c11)
+{
+ float c00[256];
+ float c10[256];
+ float c01[256];
+ float c11[256];
+ float err[256];
+
+ for (short p = 0; p < 256; p++)
+ {
+ c00[p] = cnt_histo(histo_grp1|mln::box1d(mln::point1d(0),
+ mln::point1d(p)));
+
+ c10[p] = cnt_histo(histo_grp1|mln::box1d(mln::point1d(p+1),
+ mln::point1d(255)));
+
+ c01[p] = cnt_histo(histo_grp2|mln::box1d(mln::point1d(0),
+ mln::point1d(p)));
+
+ c11[p] = cnt_histo(histo_grp2|mln::box1d(mln::point1d(p+1),
+ mln::point1d(255)));
+ }
+
+ short threshold = 0;
+ float error = c01[0] + c01[0] + c00[0] + c11[0];
+
+ for(short p = 0; p < 256; p++)
+ {
+ err[p] = c10[p] + c01[p];
+
+// std::cout << " p = " << p
+// << ";c00 = " << c00[p]
+// << ";c10 = " << c10[p]
+// << ";c01 = " << c01[p]
+// << ";c11 = " << c11[p]
+// << std::endl;
+// std::cout << "err[" << p << "] = " << err[p] << std::endl;
+
+ if (error > err[p])
+ {
+ error = err[p];
+ threshold = p;
+ }
+ }
+
+ *_c00 = c00[threshold];
+ *_c10 = c10[threshold];
+ *_c01 = c01[threshold];
+ *_c11 = c11[threshold];
+
+ return threshold;
+}
+
+
+/// \brief Fisher analysis.
+///
+/// \param[in] histo the histogram of the mixed population.
+///
+/// \return the threshold.
+///
+/// This routine is less performant than the others because it starts
+/// with a mixed population, but we know exactly the two separated
+/// population. It was just a test. Don't take it in production
+/// environement, it doesn't help you.
+short fisher_analysis(const mln::image1d<float> histo)
+{
+ typedef mln::value::int_u8 t_int_u8;
+
+ // FIXE ME SIZE const short a = mln_min(t_int_u8);
+ // float cnt1[a];
+
+ float cnt1[256];
+ float sum1[256];
+ float sqr1[256];
+ float avg1[256];
+ float var1[256];
+
+ float cnt2[256];
+ float sum2[256];
+ float sqr2[256];
+ float avg2[256];
+ float var2[256];
+
+ float cnt0[256]; // count of points
+ float sum0[256]; // sum of population
+ float sqr0[256]; // sqr of population
+ float avg0[256]; // average of the population
+ float v_in[256]; // variance with-in class
+ float v_bw[256]; // variance between class
+ float var0[256]; // variance of the population
+ short threshold;
+ float pos;
+ float min_var;
+
+ // Assign the first elements
+ cnt1[0] = 0;
+ sum1[0] = 0;
+ sqr1[0] = 0;
+ avg1[0] = 0;
+ var1[0] = 0;
+
+ // Compute the stats of the wall histogram
+ cnt2[0] = 0;
+ sum2[0] = 0;
+ sqr2[0] = 0;
+
+ for(short p = 0; p < 256; p++)
+ {
+ pos = p;
+ cnt2[0] += mln::opt::at(histo,p);
+ sum2[0] += (pos * mln::opt::at(histo,p));
+ sqr2[0] += (mln::math::sqr(pos) * mln::opt::at(histo,p));
+ }
+
+ avg2[0] = (0 == cnt2[0])? 0 : sum2[0] / cnt2[0];
+ var2[0] = (0 == cnt2[0])? 0 : sqr2[0] / cnt2[0] - mln::math::sqr(avg2[0]);
+
+ // watch the array limits
+ for (short p = 1; p < 256; p++)
+ {
+ pos = p;
+
+ // Assign the statistics to the primary class
+ cnt1[p] = cnt1[p-1] + mln::opt::at(histo, p);
+ sum1[p] = sum1[p-1] + pos * mln::opt::at(histo, p);
+ sqr1[p] = sqr1[p-1] + mln::math::sqr(pos) * mln::opt::at(histo, p);
+ avg1[p] = (0 == cnt1[p])? 0 : (sum1[p] / cnt1[p]);
+ var1[p] = (0 == cnt1[p])? 0 : ((sqr1[p] / cnt1[p])-mln::math::sqr(avg1[p]));
+
+ // Assign the statistics to the second class
+ cnt2[p] = cnt2[p-1] - mln::opt::at(histo, p);;
+ sum2[p] = sum2[p-1] - p * mln::opt::at(histo, p);;
+ sqr2[p] = sqr2[p-1] - mln::math::sqr(p) * mln::opt::at(histo, p);;
+ avg2[p] = (0 == cnt2[p])? 0 : (sum2[p] / cnt2[p]);
+ var2[p] = (0 == cnt2[p])? 0 : ((sqr2[p] / cnt2[p])-mln::math::sqr(avg2[p]));
+
+ // Lets compute the invariants
+ cnt0[p] = cnt1[p] + cnt2[p];
+ sum0[p] = sum1[p] + sum2[p];
+ sqr0[p] = sqr1[p] + sqr2[p];
+ avg0[p] = (cnt1[p] * avg1[p] + cnt2[p] * avg2[p])/cnt0[p];
+ v_in[p] = (cnt1[p] * var1[p] + cnt2[p] * var2[p])/cnt0[p];
+ v_bw[p] = (cnt1[p] * mln::math::sqr(avg1[p]-avg0[p]) +
+ cnt2[p] * mln::math::sqr(avg2[p]-avg0[p]))/cnt0[p];
+ var0[p] = v_in[p] + v_bw[p];
+ }
+
+ // Find the threshold that minimizes the intra-class variance
+ min_var = cnt2[0]*var2[0];
+ threshold = 0;
+
+ for(short p = 0; p < 256; p++)
+ {
+ // Compute the intra-class variance
+ v_in[p] = cnt1[p]*var1[p] + cnt2[p]*var2[p];
+// std::cout << "var intra[" << p << "]= " << v_in[p] << std::endl;
+
+ if (min_var > v_in[p])
+ {
+ min_var = v_in[p];
+ threshold = p;
+ }
+ }
+
+ return threshold;
+}
+/// /}
+
+
+/// Launching part.
+///
+/// In this part, we have the front end that walk over the image
+/// databases and start to compute information that we pass to
+/// previous routines.
+/// \{
+
+#define LVL0_DESCR 0 // Number of grey available
+#define HUE0_DESCR 1 // Density histogram hue analysis
+#define HUE1_DESCR 2 // Millet Hue analysis
+#define SAT0_DESCR 3 // Density histogram saturation analysis
+#define SAT1_DESCR 4 // Millet saturation analysis
+#define VAL0_DESCR 5 // Density histogram grey level analysis
+#define VAL1_DESCR 6 // Millet grey level analysis
+#define GMP0_DESCR 7 // PNSNR with GIMP compression
+#define GMP1_DESCR 8 // PNSNR with GIMP compression
+#define GMP2_DESCR 9 // PNSNR with GIMP compression
+#define MGK0_DESCR 9 // PNSNR with ImageMagick compression
+#define MGK1_DESCR 10 // PNSNR with ImageMagick compression
+#define MGK2_DESCR 11 // PNSNR with ImageMagick compression
+
+#define MGK_DESCR(version) (MGK0_DESCR + version)
+#define GMP_DESCR(version) (GMP0_DESCR + version)
+
+#define NB_DESCR 12 // Number of descriptors
+#define NB_DATABASE 2 // Number of image databases : AFP,ICDAR
+#define NB_IMAGE 110 // Number of images
+#define NB_VERSION 3 // Number of compression by GIMP or ImageMagick
+
+/// \brief Make sure that the result is between 0 and 255.
+///
+/// \param[in] file_name the name of the analysis files.
+/// \param[in] result the values for each image and each descriptors.
+/// \param[in] size the number of image by each database.
+///
+/// Correct the descriptors if there is overflow values. Just used in
+/// debug mode.
+void init_descriptors(std::string file_name[],
+ float result[][NB_DESCR],
+ int size[])
+{
+ for (int i = 0; i < NB_IMAGE; i++)
+ {
+ file_name[i] = std::string("PGM");
+
+ for (int d = 0; d < NB_DESCR; d++)
+ result[i][d] = (i*d) % 256;
+ }
+
+ size[0] = 62;
+ size[1] = 48;
+}
+
+
+/// \brief Dump gnuplot file for vizualisation of results.
+///
+/// \param[in] file_name the name of the analysis files.
+/// \param[in] result the values for each image and each descriptors.
+/// \param[in] size the number of image by each database.
+///
+/// This routine aimed at plotting the result with one graph. Each
+/// database has got its color. We can see the values used by each
+/// descriptors along the image of each database.
+void dump_descriptors(const std::string file_name[],
+ const float result[][NB_DESCR],
+ const int size[])
+{
+ std::cout << "#!/usr/bin/gnuplot" << std::endl;
+ std::cout << "set terminal x11 persist 1" << std::endl;
+ std::cout << "plot '-' using 2 with point title 'ICDAR',\\" << std::endl;
+ std::cout << " '-' using 2 with point title 'AFP'" << std::endl;
+
+ int num = 0;
+
+ for (int db = 0; db < NB_DATABASE; db++)
+ {
+ for (int i = 0; i < size[db]; i++)
+ {
+ std::cout << result[num][LVL0_DESCR] << " ";
+ std::cout << result[num][HUE0_DESCR] << " ";
+ std::cout << result[num][HUE1_DESCR] << " ";
+ std::cout << result[num][SAT0_DESCR] << " ";
+ std::cout << result[num][SAT1_DESCR] << " ";
+ std::cout << result[num][VAL0_DESCR] << " ";
+ std::cout << result[num][VAL1_DESCR] << " ";
+ std::cout << result[num][GMP0_DESCR] << " ";
+ std::cout << result[num][GMP1_DESCR] << " ";
+ std::cout << result[num][GMP2_DESCR] << " ";
+ std::cout << result[num][MGK0_DESCR] << " ";
+ std::cout << result[num][MGK1_DESCR] << " ";
+ std::cout << result[num][MGK2_DESCR] << " ";
+ std::cout << " # " << file_name[num] << std::endl;
+ num++;
+ }
+
+ std::cout << "e" << std::endl;
+ }
+}
+
+
+/// \brief Compute the descriptor histograms for each database.
+///
+/// \param[in] result the result values of each descriptors.
+/// \param[in] size the number of images by database.
+/// \param[out] histo the computed histograms.
+///
+/// This routine compute a histograms for each database and each descriptors.
+/// So we can see the distribution of descriptor values over each database.
+/// Result values are transform from float to int for histograms.
+void compute_histo(const float result[][NB_DESCR],
+ const int size[],
+ mln::image1d<float> histo[][NB_DATABASE])
+{
+ for (int i = 0; i < NB_DESCR; i++)
+ for (int db = 0; db < NB_DATABASE; db++)
+ {
+ histo[i][db].init_(mln::box1d(mln::point1d(0),mln::point1d(255)));
+
+ mln::data::fill(histo[i][db], mln::literal::zero);
+ }
+
+ short v;
+ int num = 0;
+
+ for (int db = 0; db < NB_DATABASE; db++)
+ {
+ for (int i = 0; i < size[db]; i++)
+ {
+ v = (short)mln::math::floor(result[num][VAL0_DESCR]+0.4999);
+ mln::opt::at(histo[VAL0_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][LVL0_DESCR]+0.4999);
+ mln::opt::at(histo[LVL0_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][HUE0_DESCR]+0.4999);
+ mln::opt::at(histo[HUE0_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][HUE1_DESCR]+0.4999);
+ mln::opt::at(histo[HUE1_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][SAT0_DESCR]+0.4999);
+ mln::opt::at(histo[SAT0_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][SAT1_DESCR]+0.4999);
+ mln::opt::at(histo[SAT1_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][VAL1_DESCR]+0.4999);
+ mln::opt::at(histo[VAL1_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][GMP0_DESCR]+0.4999);
+ mln::opt::at(histo[GMP0_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][GMP1_DESCR]+0.4999);
+ mln::opt::at(histo[GMP1_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][GMP2_DESCR]+0.4999);
+ mln::opt::at(histo[GMP2_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][MGK0_DESCR]+0.4999);
+ mln::opt::at(histo[MGK0_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][MGK1_DESCR]+0.4999);
+ mln::opt::at(histo[MGK1_DESCR][db],v)++;
+
+ v = (short)mln::math::floor(result[num][MGK2_DESCR]+0.4999);
+ mln::opt::at(histo[MGK2_DESCR][db],v)++;
+
+ num++;
+ }
+ }
+}
+
+
+/// Compute the threshold for discrimination between ICDAR and AFP.
+///
+/// \param[in] histo the histogram for each descriptor and for each database.
+/// \param[out] threshold computed values to discriminate between ICDAR/AFP.
+/// \param[out] c00 say CLASS 1 but CLASS 1.
+/// \param[out] c10 say CLASS 2 but CLASS 1.
+/// \param[out] c01 say CLASS 1 but CLASS 2.
+/// \param[out] c11 say CLASS 2 but CLASS 2.
+///
+/// Compute the threshold by the minimum of error of
+/// classification. Population are inverted in function of average,
+/// technical solution to prevent min_error crashed. The bad thing is
+/// now, the class 0 can be either ICDAR of AFP, depends on descriptors.
+void compute_thresholds(const mln::image1d<float> histo[][NB_DATABASE],
+ short threshold[],
+ float c00[],
+ float c10[],
+ float c01[],
+ float c11[])
+{
+ for (int i = 0; i < NB_DESCR; i++)
+ {
+ float avg0 = avg_histo(histo[i][0]);
+ float avg1 = avg_histo(histo[i][1]);
+
+ if (avg0 < avg1)
+ {
+ threshold[i] = min_error(histo[i][0], histo[i][1],
+ &c00[i], &c10[i], &c01[i], &c11[i]);
+ }
+ else
+ {
+ threshold[i] = min_error(histo[i][1], histo[i][0],
+ &c00[i], &c10[i], &c01[i], &c11[i]);
+ }
+
+ std::cerr << " i = " << i
+ << "; c00 = " << c00[i]
+ << "; c10 = " << c10[i]
+ << "; c01 = " << c01[i]
+ << "; c11 = " << c11[i]
+ << "; threshold " << threshold[i]
+ << std::endl;
+
+ }
+}
+
+
+/// \brief Walk over the database directories.
+///
+/// \param[out] file_name the array of the image name.
+/// \param[out] result the descriptors values for each image.
+/// \param[out] size the number of image for each database.
+///
+/// This is the front end part to access to the database directories. We use
+/// boost library to do it. First we explore ICDAR database en then the AFP one.
+/// For each valid image, we compute all the descriptors. Histograms are
+/// computed at this level because we can do that thing one time for every
+/// density descriptors. Every parameters are updated to retrurn the values.
+void compute_descriptors(std::string file_name[],
+ float result[][NB_DESCR],
+ int size[])
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+ typedef mln::image1d<unsigned> t_histo;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_int_u8> t_map;
+ typedef mln::image2d<t_rgb8> t_input;
+ typedef mln::fun::v2v::rgb_to_hue_map<8> t_rgb_2_hue;
+ typedef mln::fun::v2v::rgb_to_saturation_map<8> t_rgb_2_sat;
+ typedef mln::fun::v2v::rgb_to_value_map<8> t_rgb_2_val;
+ typedef mln::fun::v2v::component<t_rgb8,0> t_rgb_2_red;
+ typedef mln::fun::v2v::component<t_rgb8,1> t_rgb_2_green;
+ typedef mln::fun::v2v::component<t_rgb8,2> t_rgb_2_blue;
+ typedef mln::accu::meta::stat::histo1d t_accu_histo;
+
+
+ t_path img_path[2] = { ICDAR_20P_INPUT_IMG_PATH, AFP_PPM_IMG_PATH};
+ t_path mgk_path[3][2] = {{ICDAR_20P_MGK30_IMG_PATH, AFP_MGK30_IMG_PATH},
+ {ICDAR_20P_MGK20_IMG_PATH, AFP_MGK20_IMG_PATH},
+ {ICDAR_20P_MGK10_IMG_PATH, AFP_MGK10_IMG_PATH}};
+ t_path gmp_path[3][2] = {{ICDAR_20P_GMP30_IMG_PATH, AFP_GMP30_IMG_PATH},
+ {ICDAR_20P_GMP20_IMG_PATH, AFP_GMP20_IMG_PATH},
+ {ICDAR_20P_GMP10_IMG_PATH, AFP_GMP10_IMG_PATH}};
+
+ int num = 0;
+ int cnt = 0;
+
+ for (int db = 0; db < NB_DATABASE; db++)
+ {
+ if (boost::filesystem::exists(img_path[db]) &&
+ boost::filesystem::is_directory(img_path[db]))
+ {
+ boost::filesystem::system_complete(img_path[db]);
+
+ const t_iter_path end_iter;
+
+ cnt = 0;
+
+ for (t_iter_path dir_iter(img_path[db]); end_iter != dir_iter; ++dir_iter)
+ {
+ t_path img_file = dir_iter->path().leaf();
+ t_path dir_file = dir_iter->path();
+ t_input img_input;
+
+ mln::io::ppm::load(img_input, dir_file.string().c_str());
+
+ t_map h_img_map = mln::data::transform(img_input, t_rgb_2_hue());
+ t_map s_img_map = mln::data::transform(img_input, t_rgb_2_sat());
+ t_map v_img_map = mln::data::transform(img_input, t_rgb_2_val());
+ t_map r_img_map = mln::data::transform(img_input, t_rgb_2_red());
+ t_map g_img_map = mln::data::transform(img_input, t_rgb_2_green());
+ t_map b_img_map = mln::data::transform(img_input, t_rgb_2_blue());
+ t_histo h_img_hst = mln::data::compute(t_accu_histo(), h_img_map);
+ t_histo s_img_hst = mln::data::compute(t_accu_histo(), s_img_map);
+ t_histo v_img_hst = mln::data::compute(t_accu_histo(), v_img_map);
+ t_histo r_img_hst = mln::data::compute(t_accu_histo(), r_img_map);
+ t_histo g_img_hst = mln::data::compute(t_accu_histo(), g_img_map);
+ t_histo b_img_hst = mln::data::compute(t_accu_histo(), b_img_map);
+
+ std::cerr << dir_iter->path() << std::endl;
+
+ file_name[num] = img_file.string();
+
+ // descriptors
+ result[num][LVL0_DESCR] = lvl0_descriptor(v_img_hst);
+ result[num][HUE0_DESCR] = hue0_descriptor(h_img_hst);
+ result[num][HUE1_DESCR] = hue1_descriptor(h_img_hst,20);
+ result[num][SAT0_DESCR] = sat0_descriptor(s_img_hst);
+ result[num][SAT1_DESCR] = sat1_descriptor(s_img_hst,50);
+ result[num][VAL0_DESCR] = val0_descriptor(v_img_hst);
+ //result[num][VAL1_DESCR] = val1_descriptor(v_img_hst, 15);
+ result[num][VAL1_DESCR] = 0;
+
+ // for gimp and magick
+ for (int v = 0; v < NB_VERSION; v++)
+ {
+ if (boost::filesystem::exists(mgk_path[v][db]) &&
+ boost::filesystem::exists(gmp_path[v][db]) &&
+ boost::filesystem::is_directory(mgk_path[v][db]) &&
+ boost::filesystem::is_directory(gmp_path[v][db]))
+ {
+ t_path mgk_file = mgk_path[v][db] / img_file;
+ t_path gmp_file = gmp_path[v][db] / img_file;
+ t_input gmp_input;
+
+ mln::io::ppm::load(gmp_input, gmp_file.string().c_str());
+
+ t_map r_gmp_map = mln::data::transform(gmp_input,t_rgb_2_red());
+ t_map g_gmp_map = mln::data::transform(gmp_input,t_rgb_2_green());
+ t_map b_gmp_map = mln::data::transform(gmp_input,t_rgb_2_blue());
+
+ result[num][GMP_DESCR(v)]= err_descriptor(r_img_map,
+ g_img_map,
+ b_img_map,
+ r_gmp_map,
+ g_gmp_map,
+ b_gmp_map);
+
+ t_input mgk_input;
+
+ mln::io::ppm::load(mgk_input, mgk_file.string().c_str());
+
+ t_map r_mgk_map = mln::data::transform(mgk_input,t_rgb_2_red());
+ t_map g_mgk_map = mln::data::transform(mgk_input,t_rgb_2_green());
+ t_map b_mgk_map = mln::data::transform(mgk_input,t_rgb_2_blue());
+
+ result[num][MGK_DESCR(v)]= err_descriptor(r_img_map,
+ g_img_map,
+ b_img_map,
+ r_mgk_map,
+ g_mgk_map,
+ b_mgk_map);
+ }
+ }
+
+ num++;
+ cnt++;
+ }
+ }
+
+ size[db] = cnt;
+ }
+}
+
+/// \brief Just for debugging purpose and tests.
+int main2()
+{
+ typedef mln::image1d<unsigned> t_histo;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_int_u8> t_map;
+ typedef mln::image2d<t_rgb8> t_input;
+ typedef mln::fun::v2v::rgb_to_hue_map<8> t_rgb_2_hue;
+ typedef mln::fun::v2v::rgb_to_saturation_map<8> t_rgb_2_sat;
+ typedef mln::fun::v2v::rgb_to_value_map<8> t_rgb_2_val;
+ typedef mln::fun::v2v::component<t_rgb8,0> t_rgb_2_red;
+ typedef mln::fun::v2v::component<t_rgb8,1> t_rgb_2_green;
+ typedef mln::fun::v2v::component<t_rgb8,2> t_rgb_2_blue;
+ typedef mln::accu::meta::stat::histo1d t_accu_histo;
+
+ t_input img_input;
+
+ mln::io::ppm::load(img_input, ICDAR_20P_INPUT_IMG_PATH"/mp00032c_20p.ppm");
+ //mln::io::ppm::load(img_input, AFP_PPM_IMG_PATH"/000_Del218430.ppm");
+
+
+
+ t_map h_img_map = mln::data::transform(img_input, t_rgb_2_hue());
+ t_map s_img_map = mln::data::transform(img_input, t_rgb_2_sat());
+ t_map v_img_map = mln::data::transform(img_input, t_rgb_2_val());
+ t_map r_img_map = mln::data::transform(img_input, t_rgb_2_red());
+ t_map g_img_map = mln::data::transform(img_input, t_rgb_2_green());
+ t_map b_img_map = mln::data::transform(img_input, t_rgb_2_blue());
+ t_histo h_img_hst = mln::data::compute(t_accu_histo(), h_img_map);
+ t_histo s_img_hst = mln::data::compute(t_accu_histo(), s_img_map);
+ t_histo v_img_hst = mln::data::compute(t_accu_histo(), v_img_map);
+ t_histo r_img_hst = mln::data::compute(t_accu_histo(), r_img_map);
+ t_histo g_img_hst = mln::data::compute(t_accu_histo(), g_img_map);
+ t_histo b_img_hst = mln::data::compute(t_accu_histo(), b_img_map);
+
+
+ std::cout << "sat2 : " << sat0_descriptor(s_img_hst) << std::endl;
+
+ return 0;
+}
+
+
+/// \brief Main entry.
+///
+/// This is the front end for every routines.
+/// - compute descriptors.
+/// - dump descriptors.
+/// - compute histograms.
+/// - compute thresholds.
+/// - save results.
+///
+/// Global data used:
+/// - file_name : all the initial images name, mixed every image database.
+/// - result : all the result values for every descriptors and for every images.
+/// - histo : the histograms ny database and by descriptors.
+/// - size : the number of image by database.
+/// - threshold : the computed histogram separation on each descriptors.
+/// - cxx : the count of well/bad classified images function of threshold info.
+int main()
+{
+ std::string file_name[NB_IMAGE];
+ float result[NB_IMAGE][NB_DESCR];
+ int size[NB_DATABASE];
+ mln::image1d<float> histo[NB_DESCR][NB_DATABASE];
+ short threshold[NB_DESCR];
+ float c00[NB_DESCR];
+ float c10[NB_DESCR];
+ float c01[NB_DESCR];
+ float c11[NB_DESCR];
+
+ std::cerr << "DESCRIPTORS" << std::endl;
+ compute_descriptors(file_name,result,size);
+// std::cout << "DUMPING" << std::endl;
+// init_descriptors(file_name,result,size);
+ dump_descriptors(file_name,result,size);
+ std::cerr << "HISTO" << std::endl;
+ compute_histo(result,size,histo);
+ std::cerr << "THRESHOLD" << std::endl;
+ compute_thresholds(histo,threshold,c00,c10,c01,c11);
+
+ mln::io::plot::save_image_sh(histo[LVL0_DESCR][0], "lvl0_histo1.sh");
+ mln::io::plot::save_image_sh(histo[HUE0_DESCR][0], "hue0_histo1.sh");
+ mln::io::plot::save_image_sh(histo[HUE1_DESCR][0], "hue1_histo1.sh");
+ mln::io::plot::save_image_sh(histo[SAT0_DESCR][0], "sat0_histo1.sh");
+ mln::io::plot::save_image_sh(histo[SAT1_DESCR][0], "sat1_histo1.sh");
+ mln::io::plot::save_image_sh(histo[VAL0_DESCR][0], "val0_histo1.sh");
+ mln::io::plot::save_image_sh(histo[VAL1_DESCR][0], "val1_histo1.sh");
+ mln::io::plot::save_image_sh(histo[GMP0_DESCR][0], "gmp0_histo1.sh");
+ mln::io::plot::save_image_sh(histo[GMP1_DESCR][0], "gmp1_histo1.sh");
+ mln::io::plot::save_image_sh(histo[GMP2_DESCR][0], "gmp2_histo1.sh");
+ mln::io::plot::save_image_sh(histo[MGK0_DESCR][0], "mgk0_histo1.sh");
+ mln::io::plot::save_image_sh(histo[MGK1_DESCR][0], "mgk1_histo1.sh");
+ mln::io::plot::save_image_sh(histo[MGK2_DESCR][0], "mgk2_histo1.sh");
+
+ mln::io::plot::save_image_sh(histo[LVL0_DESCR][1], "lvl0_histo2.sh");
+ mln::io::plot::save_image_sh(histo[HUE0_DESCR][1], "hue0_histo2.sh");
+ mln::io::plot::save_image_sh(histo[HUE1_DESCR][1], "hue1_histo2.sh");
+ mln::io::plot::save_image_sh(histo[SAT0_DESCR][1], "sat0_histo2.sh");
+ mln::io::plot::save_image_sh(histo[SAT1_DESCR][1], "sat1_histo2.sh");
+ mln::io::plot::save_image_sh(histo[VAL0_DESCR][1], "val0_histo2.sh");
+ mln::io::plot::save_image_sh(histo[VAL1_DESCR][1], "val1_histo2.sh");
+ mln::io::plot::save_image_sh(histo[GMP0_DESCR][1], "gmp0_histo2.sh");
+ mln::io::plot::save_image_sh(histo[GMP1_DESCR][1], "gmp1_histo2.sh");
+ mln::io::plot::save_image_sh(histo[GMP2_DESCR][1], "gmp2_histo2.sh");
+ mln::io::plot::save_image_sh(histo[MGK0_DESCR][1], "mgk0_histo2.sh");
+ mln::io::plot::save_image_sh(histo[MGK1_DESCR][1], "mgk1_histo2.sh");
+ mln::io::plot::save_image_sh(histo[MGK2_DESCR][1], "mgk2_histo2.sh");
+
+ return 0;
+}
+/// \}
+
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/error/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/error/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/error/error.cc b/scribo/sandbox/green/exp/annotating/error/error.cc
new file mode 100644
index 0000000..949b51b
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/error/error.cc
@@ -0,0 +1,833 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// This file is a prelude just before using the bench source. It puts
+/// the light on the Jonathan's idea which wants to compare ICDAR and
+/// AFP image database with difference between original image and
+/// color reducted one. The key point is to say that when a color
+/// image is degraded, the visual quality fall quickly in function of
+/// the number of colors left. A contrario, when an image is black and
+/// white, this kind of degradation doesn't change the original visual
+/// quality. The PNSNR detector is build and learning threshold for
+/// automatic classification is done (four algorithms are tested).
+
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/algebra/vec.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/stat/mean.hh>
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/arith/minus.hh>
+#include <mln/arith/times.hh>
+#include <mln/arith/diff_abs.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/core/alias/point1d.hh>
+#include <mln/core/alias/box1d.hh>
+
+#include <mln/data/transform.hh>
+#include <mln/data/compute.hh>
+#include <mln/data/stretch.hh>
+#include <mln/data/fill.hh>
+
+#include <mln/fun/v2v/component.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/literal/zero.hh>
+
+#include <mln/math/ceil.hh>
+#include <mln/math/floor.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/trait/value_.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+
+/// Work on histogram.
+/// \brief Different routines are presented for computing mean, variance ...
+/// \{
+
+/// \brief Counting the number of pixels in the histogram.
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the number of pixels in the histogram.
+///
+/// Such routine is a generic and is generally applied on a portion of
+/// the real domain.
+template <typename I>
+mln_value(I) cnt_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) sum = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum += histo(p);
+ }
+
+ return sum;
+}
+
+/// \brief Summing the values ponderated by their occurences.
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the sum ponderated of values by their occurences.
+///
+/// This method is not a production routine, it's just a test to debug
+/// histogram problem. When we compute something over the histogram,
+/// we need to take care of the intermediate type that contains the
+/// temporary result. If not the case, the type used is the one of the
+/// value of the histogram and we can go to some overflow
+/// problems. The trick is to store the value returned by the iterator
+/// in some temporary computing type (look at pos in the code).
+template <typename I>
+mln_value(I) sum_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ pos = p.ind();
+ sum += pos*histo(p);
+ }
+
+ return sum;
+}
+
+/// \brief Summing the values ponderated by their occurences.
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the sum ponderated of values by their occurences.
+template <typename I>
+mln_value(I) avg_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_value(I) cnt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ pos = p.ind();
+ cnt += histo(p);
+ sum += pos*histo(p);
+ }
+
+ return (0 == cnt)? 0 : sum/cnt;
+}
+
+/// \brief Computing the variance
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the variance of the histogram.
+///
+/// This computing is safe because the quantity of information stored
+/// in sum is low. This formulae doesn't show the overflow problem.
+template <typename I>
+mln_value(I) var3_histo(const mln::Image<I>& histo_, float mean)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_value(I) cnt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ cnt += histo(p);
+ sum += (mln::math::sqr(p.ind()-mean)*histo(p));
+ }
+
+ return (0 == cnt)? 0 : sum/cnt;
+}
+
+/// \brief Computing the variance
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the variance of the histogram.
+///
+/// This is the debugging code to observe overflow problem.
+template <typename I>
+mln_value(I) var2_histo(const mln::Image<I>& histo_, float mean)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_value(I) sqr = mln::literal::zero;
+ mln_value(I) cnt = mln::literal::zero;
+ mln_value(I) dlt = mln::literal::zero;
+ mln_value(I) mxt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ pos = p.ind();
+ cnt += (histo(p));
+ sum += (histo(p)*pos);
+ mxt += (histo(p)*pos*mean);
+ sqr += (histo(p)*mln::math::sqr(pos));
+ dlt += (histo(p)*mln::math::sqr(pos - mean));
+
+ std::cout << "p = " << pos << std::endl;
+ std::cout << "p² = " << mln::math::sqr(pos) << std::endl;
+ std::cout << "p*mean = " << (pos*mean) << std::endl;
+ std::cout << "p-mean = " << (pos-mean) << std::endl;
+ std::cout << "(p-mean)² = " << mln::math::sqr(pos-mean) << std::endl;
+ std::cout << "histo(p) = " << histo(p) << std::endl;
+ std::cout << "histo(p)*p = " << (pos*histo(p)) << std::endl;
+ std::cout << "histo(p)*p²= " << (mln::math::sqr(pos)*histo(p))
+ << std::endl;
+ std::cout << "cnt = " << cnt << std::endl;
+ std::cout << "sum = " << sum << std::endl;
+ std::cout << "sqr = " << sqr << std::endl;
+ std::cout << "dlt = " << dlt << std::endl;
+ std::cout << "mxt = " << mxt << std::endl;
+ std::cout << std::endl;
+ }
+
+ std::cout << "sqr/cnt = " << (sqr/cnt) << std::endl;
+ std::cout << "sum/cnt = " << (sum/cnt) << std::endl;
+ std::cout << "(sum/cnt)² = " << mln::math::sqr(sum/cnt) << std::endl;
+ std::cout << "dlt/cnt = " << dlt/cnt << std::endl;
+ std::cout << "mxt/cnt = " << mxt/cnt << std::endl;
+ std::cout << std::endl;
+
+ std::cout << "sqr = "
+ << (sqr) << std::endl;
+ std::cout << "dlt = "
+ << (dlt) << std::endl;
+ std::cout << "cnt*avg² = "
+ << (mln::math::sqr(sum/cnt)*cnt) << std::endl;
+ std::cout << "2*mxt = "
+ << (2*mxt) << std::endl;
+ std::cout << "sqr - cnt*avg² = "
+ << (sqr/cnt - mln::math::sqr(sum/cnt)) << std::endl;
+ std::cout << "(sqr -2*mxt + cnt*avg²) = "
+ << ((sqr - 2*mxt + mln::math::sqr(sum/cnt))/cnt) << std::endl;
+ std::cout << std::endl;
+ return (0 == cnt)? 0 : sqr/cnt - mln::math::sqr(sum/cnt);
+}
+
+/// \brief Computing the variance
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the variance of the histogram.
+///
+/// My standard code for the variance.
+template <typename I>
+mln_value(I) var_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) pos = mln::literal::zero;
+ mln_value(I) sum = mln::literal::zero;
+ mln_value(I) sqr = mln::literal::zero;
+ mln_value(I) cnt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ pos = p.ind();
+ cnt += (histo(p));
+ sum += (histo(p)*pos);
+ sqr += (histo(p)*mln::math::sqr(pos));
+ }
+
+ return (0 == cnt)? 0 : sqr/cnt - mln::math::sqr(sum/cnt);
+}
+/// \}
+
+
+/// Classify.
+/// \brief Classification routines that compute threshold.
+/// \{
+
+/// \brief Compute discrimination threshold.
+/// \param[in] avg1 the mean of the population 1.
+/// \param[in] var1 the variance of the population 1.
+/// \param[in] avg2 the mean of the population 2.
+/// \param[in] var2 the variance of the population 2.
+///
+/// \return the threshold to discriminate the two populations.
+///
+/// Linear discriminant analysis in 1d is done. When two population
+/// have the same variance, the threshold is at (m1+m2)/2. When threre
+/// are different variances, we propose the threshold at the position
+/// (m1*sqrt(v1)+m2*sqrt(v2))/(sqrt(v1)+sqrt(v2)).
+float threshold_histo(float avg1, float var1, float avg2, float var2)
+{
+ float sigma1 = mln::math::sqrt(var1);
+ float sigma2 = mln::math::sqrt(var2);
+ float threshold = (avg1*sigma1+avg2*sigma2)/(sigma1+sigma2);
+
+ return threshold;
+}
+
+/// \brief Compute discrimination threshold.
+/// \param[in] avg1 the mean of the population 1.
+/// \param[in] var1 the variance of the population 1.
+/// \param[in] avg2 the mean of the population 2.
+/// \param[in] var2 the variance of the population 2.
+///
+/// \return the threshold to discriminate the two populations.
+///
+/// Linear discriminant analysis in 1d is done. When two population
+/// have the same variance, the threshold is at (m1+m2)/2. When threre
+/// are different variances, we propose the threshold at the position
+/// (m1*var1+m2*var2)/(sqrt(v1)+sqrt(v2)).
+float threshold3_histo(float avg1, float var1, float avg2, float var2)
+{
+ float threshold = (avg1*var1+avg2*var2)/(var1+var2);
+
+ return threshold;
+}
+
+
+
+/// \brief Compute discrimination threshold.
+/// \param[in] avg1 the mean of the population 1.
+/// \param[in] var1 the variance of the population 1.
+/// \param[in] avg2 the mean of the population 2.
+/// \param[in] var2 the variance of the population 2.
+///
+/// \return the threshold to discriminate the two populations.
+///
+/// Gaussian discriminant analysis in 1d is done. Compute the
+/// discrimanation and solve the parabolic equation.
+float threshold2_histo(float avg1, float var1, float avg2, float var2)
+{
+ float a = var2 - var1;
+ float b = -2 * (avg1 * var2 - avg2 * var1);
+ float c = var2 * mln::math::sqr(avg1) - var1 * mln::math::sqr(avg2);
+ float d = mln::math::sqr(b) - 4 * a * c;
+
+ if (d < 0)
+ std::cout << "delta negatif" << std::endl;
+
+ float x1 = (-b+mln::math::sqrt(d))/(2*a);
+ float x2 = (-b-mln::math::sqrt(d))/(2*a);
+
+ std::cout << "a = " << a << std::endl;
+ std::cout << "b = " << b << std::endl;
+ std::cout << "c = " << c << std::endl;
+ std::cout << "d = " << d << std::endl;
+ std::cout << "x1 = " << x1 << std::endl;
+ std::cout << "x2 = " << x2 << std::endl;
+
+ return x2;
+}
+
+/// \brief Compute the other proportion of histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the ponderated sum of the sqrt values.
+///
+/// This is a test. Don't take this routine in production.
+template <typename I>
+mln_value(I) sqr_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) sum = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ sum += (mln::math::sqr(p.ind())*histo(p));
+
+ return sum;
+}
+
+/// \brief Minimisation of the error.
+///
+/// \param[in] histo_grp1 the histogram of the first population.
+/// \param[in] histo_grp2 the histogram of the second population.
+///
+/// \return the threshold.
+///
+/// Computes the error and find the minimum error threshold. It's just
+/// a counting of element in four categories (0 - but detects 1, 1 -
+/// but detects 1, 1 but detects 0, 0 but detects 0). The error is the
+/// sum of missclassifications for the classes 0 and 1. As Otsu done,
+/// we can iterate on the threshold and compute the error associated
+/// to it. The bes threshold is the one that minimize the error.
+short min_error(const mln::image1d<float> histo_grp1,
+ const mln::image1d<float> histo_grp2)
+{
+ float c00[256];
+ float c10[256];
+ float c01[256];
+ float c11[256];
+ float err[256];
+
+ for (short p = 0; p < 256; p++)
+ {
+ c00[p] = cnt_histo(histo_grp1|mln::box1d(mln::point1d(0),
+ mln::point1d(p)));
+
+ c10[p] = cnt_histo(histo_grp1|mln::box1d(mln::point1d(p+1),
+ mln::point1d(255)));
+
+ c01[p] = cnt_histo(histo_grp2|mln::box1d(mln::point1d(0),
+ mln::point1d(p)));
+
+ c11[p] = cnt_histo(histo_grp2|mln::box1d(mln::point1d(p+1),
+ mln::point1d(255)));
+ }
+
+ short threshold = 0;
+ float error = c01[0] + c01[0] + c00[0] + c11[0];
+
+ for(short p = 0; p < 256; p++)
+ {
+ err[p] = c10[p] + c01[p];
+
+ std::cout << " p = " << p
+ << ";c00 = " << c00[p]
+ << ";c10 = " << c10[p]
+ << ";c01 = " << c01[p]
+ << ";c11 = " << c11[p]
+ << std::endl;
+// std::cout << "err[" << p << "] = " << err[p] << std::endl;
+
+ if (error > err[p])
+ {
+ error = err[p];
+ threshold = p;
+ }
+ }
+
+ return threshold;
+}
+
+/// \brief Fisher analysis.
+///
+/// \param[in] histo the histogram of the mixed population.
+///
+/// \return the threshold.
+///
+/// This routine is less performant than the others because it starts
+/// with a mixed population, but we know exactly the two separated
+/// population. It was just a test. Don't take it in production
+/// environement, it doesn't help you.
+short fisher_analysis(const mln::image1d<float> histo)
+{
+ typedef mln::value::int_u8 t_int_u8;
+
+ // FIXE ME SIZE const short a = mln_min(t_int_u8);
+ // float cnt1[a];
+
+ float cnt1[256];
+ float sum1[256];
+ float sqr1[256];
+ float avg1[256];
+ float var1[256];
+
+ float cnt2[256];
+ float sum2[256];
+ float sqr2[256];
+ float avg2[256];
+ float var2[256];
+
+ float cnt0[256]; // count of points
+ float sum0[256]; // sum of population
+ float sqr0[256]; // sqr of population
+ float avg0[256]; // average of the population
+ float v_in[256]; // variance with-in class
+ float v_bw[256]; // variance between class
+ float var0[256]; // variance of the population
+ short threshold;
+ float pos;
+ float min_var;
+
+ // Assign the first elements
+ cnt1[0] = 0;
+ sum1[0] = 0;
+ sqr1[0] = 0;
+ avg1[0] = 0;
+ var1[0] = 0;
+
+ // Compute the stats of the wall histogram
+ cnt2[0] = 0;
+ sum2[0] = 0;
+ sqr2[0] = 0;
+
+ for(short p = 0; p < 256; p++)
+ {
+ pos = p;
+ cnt2[0] += mln::opt::at(histo,p);
+ sum2[0] += (pos * mln::opt::at(histo,p));
+ sqr2[0] += (mln::math::sqr(pos) * mln::opt::at(histo,p));
+ }
+
+ avg2[0] = (0 == cnt2[0])? 0 : sum2[0] / cnt2[0];
+ var2[0] = (0 == cnt2[0])? 0 : sqr2[0] / cnt2[0] - mln::math::sqr(avg2[0]);
+
+ // watch the array limits
+ for (short p = 1; p < 256; p++)
+ {
+ pos = p;
+
+ // Assign the statistics to the primary class
+ cnt1[p] = cnt1[p-1] + mln::opt::at(histo, p);
+ sum1[p] = sum1[p-1] + pos * mln::opt::at(histo, p);
+ sqr1[p] = sqr1[p-1] + mln::math::sqr(pos) * mln::opt::at(histo, p);
+ avg1[p] = (0 == cnt1[p])? 0 : (sum1[p] / cnt1[p]);
+ var1[p] = (0 == cnt1[p])? 0 : ((sqr1[p] / cnt1[p])-mln::math::sqr(avg1[p]));
+
+ // Assign the statistics to the second class
+ cnt2[p] = cnt2[p-1] - mln::opt::at(histo, p);;
+ sum2[p] = sum2[p-1] - p * mln::opt::at(histo, p);;
+ sqr2[p] = sqr2[p-1] - mln::math::sqr(p) * mln::opt::at(histo, p);;
+ avg2[p] = (0 == cnt2[p])? 0 : (sum2[p] / cnt2[p]);
+ var2[p] = (0 == cnt2[p])? 0 : ((sqr2[p] / cnt2[p])-mln::math::sqr(avg2[p]));
+
+ // Lets compute the invariants
+ cnt0[p] = cnt1[p] + cnt2[p];
+ sum0[p] = sum1[p] + sum2[p];
+ sqr0[p] = sqr1[p] + sqr2[p];
+ avg0[p] = (cnt1[p] * avg1[p] + cnt2[p] * avg2[p])/cnt0[p];
+ v_in[p] = (cnt1[p] * var1[p] + cnt2[p] * var2[p])/cnt0[p];
+ v_bw[p] = (cnt1[p] * mln::math::sqr(avg1[p]-avg0[p]) +
+ cnt2[p] * mln::math::sqr(avg2[p]-avg0[p]))/cnt0[p];
+ var0[p] = v_in[p] + v_bw[p];
+ }
+
+ // Find the threshold that minimizes the intra-class variance
+ min_var = cnt2[0]*var2[0];
+ threshold = 0;
+
+ for(short p = 0; p < 256; p++)
+ {
+ // Compute the intra-class variance
+ v_in[p] = cnt1[p]*var1[p] + cnt2[p]*var2[p];
+// std::cout << "var intra[" << p << "]= " << v_in[p] << std::endl;
+
+ if (min_var > v_in[p])
+ {
+ min_var = v_in[p];
+ threshold = p;
+ }
+ }
+
+ return threshold;
+}
+/// \}
+
+/// \brief ERROR (MSE, PNSNR) compression p278 Handbook Color.
+/// \param[in] original the original image.
+/// \param[in] reduced the image with a reduced number of colors.
+///
+/// \return the PNSNR.
+///
+/// Compute the PNSNR. First compute the square difference in each
+/// channel. Then compute the mean of those square differences and get
+/// the mean over the three channels. Then, get the sqrt of that to
+/// have a distance. The PNSNR is a logarithmic quantity of that distance.
+float error_test(const std::string original,
+ const std::string reduced)
+
+{
+
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::fun::v2v::component<t_rgb8,0> t_component_red;
+ typedef mln::fun::v2v::component<t_rgb8,1> t_component_green;
+ typedef mln::fun::v2v::component<t_rgb8,2> t_component_blue;
+ typedef mln::accu::meta::stat::mean t_mean;
+ typedef mln::accu::meta::stat::histo1d t_histo;
+ typedef mln::image2d<t_int_u8> t_img;
+ typedef mln_trait_op_minus_(t_img,t_img) t_minus;
+ typedef mln_trait_op_times_(t_minus,t_minus) t_times;
+
+ mln::image2d<mln::value::rgb8> original_rgb8;
+ mln::image2d<mln::value::rgb8> reduced_rgb8;
+
+ mln::image2d<mln::value::int_u8> original_red;
+ mln::image2d<mln::value::int_u8> original_green;
+ mln::image2d<mln::value::int_u8> original_blue;
+
+ mln::image2d<mln::value::int_u8> reduced_red;
+ mln::image2d<mln::value::int_u8> reduced_green;
+ mln::image2d<mln::value::int_u8> reduced_blue;
+
+// mln::image2d<mln::value::int_u8> map_red;
+// mln::image2d<mln::value::int_u8> map_green;
+// mln::image2d<mln::value::int_u8> map_blue;
+
+// mln::image1d<unsigned> histo_red;
+// mln::image1d<unsigned> histo_green;
+// mln::image1d<unsigned> histo_blue;
+
+ t_minus minus_red;
+ t_minus minus_green;
+ t_minus minus_blue;
+
+ t_times times_red;
+ t_times times_green;
+ t_times times_blue;
+
+ float error_red;
+ float error_green;
+ float error_blue;
+
+ float error;
+
+
+ mln::io::ppm::load(original_rgb8, original.c_str());
+ mln::io::ppm::load(reduced_rgb8, reduced.c_str());
+
+ original_red = mln::data::transform(original_rgb8, t_component_red());
+ original_green = mln::data::transform(original_rgb8, t_component_green());
+ original_blue = mln::data::transform(original_rgb8, t_component_blue());
+
+ reduced_red = mln::data::transform(reduced_rgb8, t_component_red());
+ reduced_green = mln::data::transform(reduced_rgb8, t_component_green());
+ reduced_blue = mln::data::transform(reduced_rgb8, t_component_blue());
+
+ minus_red = (original_red - reduced_red);
+ times_red = minus_red * minus_red;
+
+ minus_green = (original_green - reduced_green);
+ times_green = minus_green * minus_green;
+
+ minus_blue = (original_blue - reduced_blue);
+ times_blue = minus_blue * minus_blue;
+
+ error_red = mln::data::compute(t_mean(), times_red);
+ error_green = mln::data::compute(t_mean(), times_green);
+ error_blue = mln::data::compute(t_mean(), times_blue);
+
+// map_red = mln::data::stretch(t_int_u8(), times_red);
+// map_green = mln::data::stretch(t_int_u8(), times_blue);
+// map_blue = mln::data::stretch(t_int_u8(), times_green);
+
+// histo_red = mln::data::compute(t_histo(), map_red);
+// histo_green = mln::data::compute(t_histo(), map_green);
+// histo_blue = mln::data::compute(t_histo(), map_blue);
+
+// mln::io::plot::save_image_sh(histo_red, "histo_red.sh");
+// mln::io::plot::save_image_sh(histo_green,"histo_green.sh");
+// mln::io::plot::save_image_sh(histo_blue, "histo_blue.sh");
+
+// mln::io::pgm::save(map_red, "red.pgm");
+// mln::io::pgm::save(map_green,"green.pgm");
+// mln::io::pgm::save(map_blue, "blue.pgm");
+
+ error = (error_red + error_green + error_blue)/3.0;
+ error = mln::math::sqrt(error);
+ error = 20 * log(255/error);
+
+// Le PNSNR semble offrir plus d'espace pour la discrimination
+// Si les images sont identiques ==> PNSNR = +inf
+// Si les images sont très différentes ==> PNSNR = 0
+
+ return error;
+}
+
+
+/// \brief The main entry.
+///
+/// This is the front end for error classification. This is the big
+/// loop where we walk other image data bases. Computation of
+/// automatic thresholds are called from here.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+ mln::image1d<float> histo(256);
+ mln::image1d<float> histo_grp[2]; // histo by group
+
+ histo_grp[0].init_(mln::box1d(mln::point1d(0),mln::point1d(255)));
+ histo_grp[1].init_(mln::box1d(mln::point1d(0),mln::point1d(255)));
+
+ mln::data::fill(histo, mln::literal::zero);
+ mln::data::fill(histo_grp[0], mln::literal::zero);
+ mln::data::fill(histo_grp[1], mln::literal::zero);
+
+ t_path original_path[] = {ICDAR_20P_INPUT_IMG_PATH,
+ AFP_PPM_IMG_PATH};
+
+// t_path reduced1_path[] = {ICDAR_20P_MGK30_IMG_PATH,
+// AFP_MGK30_IMG_PATH};
+
+// t_path reduced1_path[] = {ICDAR_20P_MGK20_IMG_PATH,
+// AFP_MGK20_IMG_PATH};
+
+ t_path reduced1_path[] = {ICDAR_20P_MGK10_IMG_PATH,
+ AFP_MGK10_IMG_PATH};
+
+// t_path reduced2_path[] = {ICDAR_20P_GMP30_IMG_PATH,
+// AFP_GMP30_IMG_PATH};
+
+// t_path reduced2_path[] = {ICDAR_20P_GMP20_IMG_PATH,
+// AFP_GMP20_IMG_PATH};
+
+ t_path reduced2_path[] = {ICDAR_20P_GMP10_IMG_PATH,
+ AFP_GMP10_IMG_PATH};
+
+
+ std::cout << "#!/usr/bin/gnuplot" << std::endl;
+ std::cout << "set terminal x11 persist 1" << std::endl;
+ std::cout << "ERROR" << std::endl;
+ std::cout << "plot '-' using 1 with point notitle,\\" << std::endl;
+ std::cout << " '-' using 1 with point notitle" << std::endl;
+
+ for (int i = 0; i < 2; i++)
+ {
+ if (boost::filesystem::exists(original_path[i]) &&
+ boost::filesystem::exists(reduced1_path[i]) &&
+ boost::filesystem::exists(reduced2_path[i]) &&
+ boost::filesystem::is_directory(original_path[i]) &&
+ boost::filesystem::is_directory(reduced1_path[i]) &&
+ boost::filesystem::is_directory(reduced2_path[i]))
+ {
+ boost::filesystem::system_complete(original_path[i]);
+ const t_iter_path end_iter;
+ float error1 = 0.0;
+ float error2 = 0.0;
+ t_path leaf;
+ t_path reduced1_file;
+ t_path reduced2_file;
+
+ for (t_iter_path dir_iter(original_path[i]);end_iter!=dir_iter;++dir_iter)
+ {
+ leaf = dir_iter->path().leaf();
+ reduced1_file = reduced1_path[i] / leaf;
+ reduced2_file = reduced2_path[i] / leaf;
+
+ error1 = error_test(dir_iter->path().string(), reduced1_file.string());
+ error2 = error_test(dir_iter->path().string(), reduced2_file.string());
+
+ float a1 = 1;
+ short v1 = (short)mln::math::floor(error2+0.4999);
+ mln::opt::at(histo,v1) += a1;
+ mln::opt::at(histo_grp[i],v1) += a1;
+
+// float a1 = error2 - mln::math::floor(error2);
+// float a2 = mln::math::ceil(error2) - error2;
+// short v1 = (short)mln::math::floor(error2);
+// short v2 = (short)mln::math::ceil(error2);
+// mln::opt::at(histo,v1) += a1;
+// mln::opt::at(histo,v2) += a2;
+// mln::opt::at(histo_grp[i],v1) += a1;
+// mln::opt::at(histo_grp[i],v2) += a2;
+
+ std::cout << error1 << " ";
+ std::cout << error2 << " ";
+ std::cout << "# " << dir_iter->path().leaf() << std::endl;
+ }
+ std::cout << "e" << std::endl;
+ }
+ }
+
+ mln::io::plot::save_image_sh(histo, "histo.sh");
+ mln::io::plot::save_image_sh(histo_grp[1], "histo_grp1.sh");
+ mln::io::plot::save_image_sh(histo_grp[0], "histo_grp2.sh");
+
+ float threshold = fisher_analysis(histo);
+ float threshold2 = threshold_histo(avg_histo(histo_grp[1]),
+ var_histo(histo_grp[1]),
+ avg_histo(histo_grp[0]),
+ var_histo(histo_grp[0]));
+ float threshold3 = threshold2_histo(avg_histo(histo_grp[1]),
+ var_histo(histo_grp[1]),
+ avg_histo(histo_grp[0]),
+ var_histo(histo_grp[0]));
+ float threshold4 = min_error(histo_grp[1],histo_grp[0]);
+
+ std::cout << "threshold = " << threshold << std::endl;
+ std::cout << "threshold2 = " << threshold2 << std::endl;
+ std::cout << "threshold3 = " << threshold3 << std::endl;
+ std::cout << "threshold4 = " << threshold4 << std::endl;
+ std::cout << "avg_grp1 = " << avg_histo(histo_grp[1]) << std::endl;
+ std::cout << "avg_grp2 = " << avg_histo(histo_grp[0]) << std::endl;
+
+ // compute the classification matrix
+ // for each sub population
+
+ float c00 = cnt_histo(histo_grp[1] | mln::box1d(mln::point1d(0),
+ mln::point1d(threshold)));
+
+ float c10 = cnt_histo(histo_grp[1] | mln::box1d(mln::point1d(threshold+1),
+ mln::point1d(255)));
+
+ float c01 = cnt_histo(histo_grp[0] | mln::box1d(mln::point1d(0),
+ mln::point1d(threshold)));
+
+ float c11 = cnt_histo(histo_grp[0] | mln::box1d(mln::point1d(threshold+1),
+ mln::point1d(255)));
+
+
+ std::cout << "pop0 = " << cnt_histo(histo_grp[1]) << std::endl;
+ std::cout << "pop1 = " << cnt_histo(histo_grp[0]) << std::endl;
+ std::cout << std::endl;
+
+ std::cout << "c00 = " << c00 << std::endl;
+ std::cout << "c10 = " << c10 << std::endl;
+ std::cout << "c01 = " << c01 << std::endl;
+ std::cout << "c11 = " << c11 << std::endl;
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/histo/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/histo/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/histo/histo.cc b/scribo/sandbox/green/exp/annotating/histo/histo.cc
new file mode 100644
index 0000000..90b18e4
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/histo/histo.cc
@@ -0,0 +1,366 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Build normalized histograms for visualization only.
+///
+/// The goal of this code is to build every normalized histograms of
+/// an image database for visual inspection. It enables the
+/// comparaison of the densities of each image database and the
+/// understanding of the differences in this space.
+
+
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/arith/minus.hh>
+#include <mln/arith/div.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/convert.hh>
+#include <mln/data/compute.hh>
+#include <mln/data/stretch.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/literal/zero.hh>
+#include <mln/literal/colors.hh>
+#include <mln/literal/grays.hh>
+
+#include <mln/math/max.hh>
+#include <mln/math/min.hh>
+#include <mln/math/sqr.hh>
+#include <mln/math/sqrt.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/geom/nsites.hh>
+
+#include <mln/fun/v2v/rgb_to_hue_map.hh>
+#include <mln/fun/v2v/rgb_to_saturation_map.hh>
+#include <mln/fun/v2v/rgb_to_value_map.hh>
+#include <mln/fun/v2v/component.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/value/rgb8.hh>
+
+//============================================================================//
+// HISTOGRAM
+//============================================================================//
+
+/// \brief Count the number of pixel in the histogram.
+///
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the number of pixels in the domain.
+///
+/// This is simple counting routine that compute the number of pixels
+/// in the domain of the histogram. For each site, it sums the
+/// frequencies associated to its site.
+template <typename I>
+mln_value(I) cnt_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) cnt = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ cnt += histo(p);
+ }
+
+ return cnt;
+}
+
+/// \brief The computing of the normalized histogram.
+///
+/// \param[in] input the name of the input image.
+/// \param[in] output_map the name of the specific map (hue,sat,val,R,G,B).
+/// \param[in] output_histo the name of the output normalized histogram.
+/// \param[in] space the name of the studied channel (R,G,B,H,S,V).
+///
+/// Compute the normalized histogram in the given channel. First get
+/// the channel from the RGB space or the HSV space and then compute
+/// its normalized histogram. Normalization is done by dividing each
+/// frequency by the sum of frequencies. It's a way to make the
+/// histogram independant from the dimension of the input image and
+/// then to compare different image databases together.
+void histo(const std::string input,
+ const std::string output_map,
+ const std::string output_histo,
+ const char space)
+
+{
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::fun::v2v::rgb_to_hue_map<8> t_rgb_to_hue_map;
+ typedef mln::fun::v2v::rgb_to_saturation_map<8> t_rgb_to_sat_map;
+ typedef mln::fun::v2v::rgb_to_value_map<8> t_rgb_to_val_map;
+ typedef mln::fun::v2v::component<t_rgb8,0> t_component_r;
+ typedef mln::fun::v2v::component<t_rgb8,1> t_component_g;
+ typedef mln::fun::v2v::component<t_rgb8,2> t_component_b;
+
+ mln::image2d<mln::value::rgb8> input_rgb8;
+ mln::image2d<mln::value::int_u8> map;
+ mln::image1d<unsigned> histo;
+ mln::image1d<float> histo_float;
+ float sum;
+
+ mln::io::ppm::load(input_rgb8, input.c_str());
+
+ switch(space)
+ {
+ case 'h': map = mln::data::transform(input_rgb8, t_rgb_to_hue_map()); break;
+ case 's': map = mln::data::transform(input_rgb8, t_rgb_to_sat_map()); break;
+ case 'v': map = mln::data::transform(input_rgb8, t_rgb_to_val_map()); break;
+ case 'r': map = mln::data::transform(input_rgb8, t_component_r()); break;
+ case 'g': map = mln::data::transform(input_rgb8, t_component_g()); break;
+ case 'b': map = mln::data::transform(input_rgb8, t_component_b()); break;
+ default: break;// crash
+ }
+
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), map);
+ sum = cnt_histo(histo);
+ histo_float = mln::data::convert(float(), histo) / sum;
+
+ mln::io::pgm::save(map, output_map.c_str());
+ mln::io::plot::save_image_sh(histo_float, output_histo.c_str());
+}
+
+//============================================================================//
+// MAIN
+//============================================================================//
+
+
+/// \brief The main entry.
+///
+/// This a front end to compute histogram with boost plumberies. There
+/// is 2 uses cases, the computing over the icdar database and over
+/// the afp database. We force the computing over the six channel
+/// (H,S,V,R,G,B) in order to select the channel the most specific for
+/// a database. It seems that saturation channel and value channel are
+/// the most specific to describe each database. Take care to
+/// coherence of the output directories for each source of images.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+// t_path full_path[] = {t_path(ICDAR_20P_TEXT_ONLY_IMG_PATH),
+// t_path(ICDAR_20P_TEXT_COLOR_IMG_PATH),
+// t_path(ICDAR_20P_TEXT_PHOTO_IMG_PATH)};
+
+// t_path full_path[] = {t_path(AFP_INPUT_IMG_PATH)};
+// t_path full_path[] = {t_path(AFP_GMP30_IMG_PATH)};
+// t_path full_path[] = {t_path(AFP_GMP20_IMG_PATH)};
+// t_path full_path[] = {t_path(AFP_GMP10_IMG_PATH)};
+// t_path full_path[] = {t_path(AFP_MGK30_IMG_PATH)};
+// t_path full_path[] = {t_path(AFP_MGK20_IMG_PATH)};
+// t_path full_path[] = {t_path(AFP_MGK10_IMG_PATH)};
+
+// t_path full_path[] = {t_path(ICDAR_20P_INPUT_IMG_PATH)};
+// t_path full_path[] = {t_path(ICDAR_20P_GMP30_IMG_PATH)};
+ t_path full_path[] = {t_path(ICDAR_20P_GMP20_IMG_PATH)};
+// t_path full_path[] = {t_path(ICDAR_20P_GMP10_IMG_PATH)};
+// t_path full_path[] = {t_path(ICDAR_20P_MGK30_IMG_PATH)};
+// t_path full_path[] = {t_path(ICDAR_20P_MGK20_IMG_PATH)};
+// t_path full_path[] = {t_path(ICDAR_20P_MGK10_IMG_PATH)};
+
+ for (int i = 0; i < 1; ++i)
+ {
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ t_path directory;
+ t_path leaf;
+ t_path output_map;
+ t_path output_histo;
+
+ std::cerr << "entering " << full_path[i] << std::endl;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ std::cerr << dir_iter->path() << std::endl;
+
+ leaf = dir_iter->path().leaf();
+
+// directory = ANNOTATING_AFP_R_INPUT_RET_PATH;
+// directory = ANNOTATING_AFP_R_GMP30_RET_PATH;
+// directory = ANNOTATING_AFP_R_GMP20_RET_PATH;
+// directory = ANNOTATING_AFP_R_GMP10_RET_PATH;
+// directory = ANNOTATING_AFP_R_MGK30_RET_PATH;
+// directory = ANNOTATING_AFP_R_MGK20_RET_PATH;
+// directory = ANNOTATING_AFP_R_MGK10_RET_PATH;
+
+// directory = ANNOTATING_ICDAR_R_INPUT_RET_PATH;
+// directory = ANNOTATING_ICDAR_R_GMP30_RET_PATH;
+ directory = ANNOTATING_ICDAR_R_GMP20_RET_PATH;
+// directory = ANNOTATING_ICDAR_R_GMP10_RET_PATH;
+// directory = ANNOTATING_ICDAR_R_MGK30_RET_PATH;
+// directory = ANNOTATING_ICDAR_R_MGK20_RET_PATH;
+// directory = ANNOTATING_ICDAR_R_MGK10_RET_PATH;
+ output_histo = change_extension(directory / leaf, ".sh");
+ output_map = change_extension(directory / leaf, ".pgm");
+
+ histo(dir_iter->path().string(),
+ output_map.string(),
+ output_histo.string(),
+ 'r');
+
+// directory = ANNOTATING_AFP_G_INPUT_RET_PATH;
+// directory = ANNOTATING_AFP_G_GMP30_RET_PATH;
+// directory = ANNOTATING_AFP_G_GMP20_RET_PATH;
+// directory = ANNOTATING_AFP_G_GMP10_RET_PATH;
+// directory = ANNOTATING_AFP_G_MGK30_RET_PATH;
+// directory = ANNOTATING_AFP_G_MGK20_RET_PATH;
+// directory = ANNOTATING_AFP_G_MGK10_RET_PATH;
+
+// directory = ANNOTATING_ICDAR_G_INPUT_RET_PATH;
+// directory = ANNOTATING_ICDAR_G_GMP30_RET_PATH;
+ directory = ANNOTATING_ICDAR_G_GMP20_RET_PATH;
+// directory = ANNOTATING_ICDAR_G_GMP10_RET_PATH;
+// directory = ANNOTATING_ICDAR_G_MGK30_RET_PATH;
+// directory = ANNOTATING_ICDAR_G_MGK20_RET_PATH;
+// directory = ANNOTATING_ICDAR_G_MGK10_RET_PATH;
+ output_histo = change_extension(directory / leaf, ".sh");
+ output_map = change_extension(directory / leaf, ".pgm");
+
+ histo(dir_iter->path().string(),
+ output_map.string(),
+ output_histo.string(),
+ 'g');
+
+// directory = ANNOTATING_AFP_B_INPUT_RET_PATH;
+// directory = ANNOTATING_AFP_B_GMP30_RET_PATH;
+// directory = ANNOTATING_AFP_B_GMP20_RET_PATH;
+// directory = ANNOTATING_AFP_B_GMP10_RET_PATH;
+// directory = ANNOTATING_AFP_B_MGK30_RET_PATH;
+// directory = ANNOTATING_AFP_B_MGK20_RET_PATH;
+// directory = ANNOTATING_AFP_B_MGK10_RET_PATH;
+
+// directory = ANNOTATING_ICDAR_B_INPUT_RET_PATH;
+// directory = ANNOTATING_ICDAR_B_GMP30_RET_PATH;
+ directory = ANNOTATING_ICDAR_B_GMP20_RET_PATH;
+// directory = ANNOTATING_ICDAR_B_GMP10_RET_PATH;
+// directory = ANNOTATING_ICDAR_B_MGK30_RET_PATH;
+// directory = ANNOTATING_ICDAR_B_MGK20_RET_PATH;
+// directory = ANNOTATING_ICDAR_B_MGK10_RET_PATH;
+ output_histo = change_extension(directory / leaf, ".sh");
+ output_map = change_extension(directory / leaf, ".pgm");
+
+ histo(dir_iter->path().string(),
+ output_map.string(),
+ output_histo.string(),
+ 'b');
+
+// directory = ANNOTATING_AFP_H_INPUT_RET_PATH;
+// directory = ANNOTATING_AFP_H_GMP30_RET_PATH;
+// directory = ANNOTATING_AFP_H_GMP20_RET_PATH;
+// directory = ANNOTATING_AFP_H_GMP10_RET_PATH;
+// directory = ANNOTATING_AFP_H_MGK30_RET_PATH;
+// directory = ANNOTATING_AFP_H_MGK20_RET_PATH;
+// directory = ANNOTATING_AFP_H_MGK10_RET_PATH;
+
+// directory = ANNOTATING_ICDAR_H_INPUT_RET_PATH;
+// directory = ANNOTATING_ICDAR_H_GMP30_RET_PATH;
+ directory = ANNOTATING_ICDAR_H_GMP20_RET_PATH;
+// directory = ANNOTATING_ICDAR_H_GMP10_RET_PATH;
+// directory = ANNOTATING_ICDAR_H_MGK30_RET_PATH;
+// directory = ANNOTATING_ICDAR_H_MGK20_RET_PATH;
+// directory = ANNOTATING_ICDAR_H_MGK10_RET_PATH;
+ output_histo = change_extension(directory / leaf, ".sh");
+ output_map = change_extension(directory / leaf, ".pgm");
+
+ histo(dir_iter->path().string(),
+ output_map.string(),
+ output_histo.string(),
+ 'h');
+
+// directory = ANNOTATING_AFP_S_INPUT_RET_PATH;
+// directory = ANNOTATING_AFP_S_GMP30_RET_PATH;
+// directory = ANNOTATING_AFP_S_GMP20_RET_PATH;
+// directory = ANNOTATING_AFP_S_GMP10_RET_PATH;
+// directory = ANNOTATING_AFP_S_MGK30_RET_PATH;
+// directory = ANNOTATING_AFP_S_MGK20_RET_PATH;
+// directory = ANNOTATING_AFP_S_MGK10_RET_PATH;
+
+// directory = ANNOTATING_ICDAR_S_INPUT_RET_PATH;
+// directory = ANNOTATING_ICDAR_S_GMP30_RET_PATH;
+ directory = ANNOTATING_ICDAR_S_GMP20_RET_PATH;
+// directory = ANNOTATING_ICDAR_S_GMP10_RET_PATH;
+// directory = ANNOTATING_ICDAR_S_MGK30_RET_PATH;
+// directory = ANNOTATING_ICDAR_S_MGK20_RET_PATH;
+// directory = ANNOTATING_ICDAR_S_MGK10_RET_PATH;
+ output_histo = change_extension(directory / leaf, ".sh");
+ output_map = change_extension(directory / leaf, ".pgm");
+
+ histo(dir_iter->path().string(),
+ output_map.string(),
+ output_histo.string(),
+ 's');
+
+// directory = ANNOTATING_AFP_V_INPUT_RET_PATH;
+// directory = ANNOTATING_AFP_V_GMP30_RET_PATH;
+// directory = ANNOTATING_AFP_V_GMP20_RET_PATH;
+// directory = ANNOTATING_AFP_V_GMP10_RET_PATH;
+// directory = ANNOTATING_AFP_V_MGK30_RET_PATH;
+// directory = ANNOTATING_AFP_V_MGK20_RET_PATH;
+// directory = ANNOTATING_AFP_V_MGK10_RET_PATH;
+
+// directory = ANNOTATING_ICDAR_V_INPUT_RET_PATH;
+// directory = ANNOTATING_ICDAR_V_GMP30_RET_PATH;
+ directory = ANNOTATING_ICDAR_V_GMP20_RET_PATH;
+// directory = ANNOTATING_ICDAR_V_GMP10_RET_PATH;
+// directory = ANNOTATING_ICDAR_V_MGK30_RET_PATH;
+// directory = ANNOTATING_ICDAR_V_MGK20_RET_PATH;
+// directory = ANNOTATING_ICDAR_V_MGK10_RET_PATH;
+ output_histo = change_extension(directory / leaf, ".sh");
+ output_map = change_extension(directory / leaf, ".pgm");
+
+ histo(dir_iter->path().string(),
+ output_map.string(),
+ output_histo.string(),
+ 'v');
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/hsv/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/hsv/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/hsv/hsv.cc b/scribo/sandbox/green/exp/annotating/hsv/hsv.cc
new file mode 100644
index 0000000..507d07b
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/hsv/hsv.cc
@@ -0,0 +1,912 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet HSV operator [millet.phd.2008.pdf]
+///
+/// This is the Millet code for moving from RGB space to Hue
+/// one. Formulae are classical, we can find them on the web.
+///
+/// Val = max(R,G,B).
+/// Sat = (max(R,G,B) - min(R,G,B))/max(R,G,B).
+/// IF R = max(R,G,B) THEN Hue = 60 * [(V-B)/(max(R,G,B)-min(R,G,B))].
+/// IF G = max(R,G,B) THEN Hue = 60 * [2 + (B-R)/(max(R,G,B)-min(R,G,B))].
+/// IF B = max(R,G,B) THEN Hue = 60 * [4 + (R-G)/(max(R,G,B)-min(R,G,B))].
+///
+/// This operator try to integrate many processing in one shot, after
+/// HSV transformation.
+
+
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/arith/minus.hh>
+#include <mln/arith/div.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/convert.hh>
+#include <mln/data/compute.hh>
+#include <mln/data/stretch.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/literal/zero.hh>
+#include <mln/literal/colors.hh>
+#include <mln/literal/grays.hh>
+
+#include <mln/math/max.hh>
+#include <mln/math/min.hh>
+#include <mln/math/sqr.hh>
+#include <mln/math/sqrt.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/geom/nsites.hh>
+
+#include <mln/fun/v2v/rgb_to_hue_map.hh>
+#include <mln/fun/v2v/rgb_to_saturation_map.hh>
+#include <mln/fun/v2v/rgb_to_value_map.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/value/rgb8.hh>
+
+//============================================================================//
+// HISTOGRAM
+//============================================================================//
+
+/// Histogram
+/// \{
+/// \brief Histogram processing methods.
+///
+/// In this part, we define methods for histogram processing as average,
+/// peak, variance etc ...
+
+
+/// \brief Sum all the bins of the histogram.
+///
+/// \param[in] img the histogram based on image.
+///
+/// \return the sum of the overall bins.
+///
+/// Sum evry bins and return the result.
+template <typename I>
+mln_value(I) count_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) result = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ result += histo(p);
+
+ return result;
+}
+
+/// \brief Sum the whole frequencies.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the number of pixels in the domain.
+///
+/// By summing all the frequencies of the domain, we count in fact the
+/// number of pixels in the image.
+template <typename I>
+mln_value(I) sum_frequency_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) sum = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ sum += histo(p);
+
+ return sum;
+}
+
+/// \brief Count the null frequencies.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the number of null frequencies.
+///
+/// It's a way to access the number of distinct colors in the
+/// histogram by comparing it with the histogram domain.
+template <typename I>
+mln_value(I) count_null_frequency_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ mln_value(I) count = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ if (0 == histo(p))
+ count++;
+
+ return count;
+}
+
+/// \brief Find the peak of the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the bin which contains the greatest value.
+///
+/// Compute the position of the peak of the histogram. To do this, we
+/// view evrey bin and we maintain the maxima of the values and the
+/// position. At the end, we return the position which contains the
+/// greatest value.
+template <typename I>
+mln_coord(mln_site_(I)) peak_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the peak of the histogram
+ mln_value(I) v_max = mln::opt::at(histo, mln::literal::zero);
+ mln_coord(mln_site_(I)) p_max = mln::literal::zero;
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ return p_max;
+}
+
+/// \brief Find the maximum frequency of the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the maximum frequency of the histogram.
+///
+/// Find the peak and return its value, not its position. We use that
+/// function to normalize histograms.
+template <typename I>
+mln_value(I) max_frequency_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the value of the peak from the histogram
+ mln_value(I) max = mln::opt::at(histo, mln::literal::zero);
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ max = mln::math::max(histo(p),max);
+ }
+
+ return max;
+}
+
+/// \brief Find the mean of the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the aveerage of the histogram.
+///
+/// Compute the mean.
+template <typename I>
+float mean_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the mean of the histogram
+ float sum = 0;
+ float mean = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum += histo(p);
+ mean += p.ind()*histo(p);
+ }
+
+ mean = mean / sum;
+
+ return mean;
+}
+
+/// \brief Compare the histogram with the equi distributed histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the distance between the equi distributed histogram.
+///
+/// Compute the square euclidian distance between histogram and the
+/// equi distributed histogram. The equi distributed histogram is an
+/// histogram in which each bin has the same frequency (id est 1/256
+/// for instance). The integral equals one for this two
+/// histograms. This is a major contribution test to differentiate
+/// image database.
+template <typename I>
+float cmp_equi_frequency_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the mean of the histogram
+ float sum = 0;
+ float var = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum += histo(p);
+ var += mln::math::sqr(histo(p) - (1/256.0));
+ }
+
+ var = var / sum;
+
+ return var;
+}
+
+/// \brief Compute the variance on the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the variance.
+///
+/// Compute the variance by substracting the mean.
+template <typename I>
+float var_histo(const mln::Image<I>& histo_, float mean)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the mean of the histogram
+ float sum = 0;
+ float var = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum += histo(p);
+ var += mln::math::sqr(p.ind() - mean) * histo(p);
+ }
+
+ var = var / sum;
+
+ return var;
+}
+
+/// \brief Find the mean of the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the aveerage of the histogram.
+///
+/// Compute the mean.
+template <typename I>
+float mean_frequency_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the mean of the histogram
+ float sum = 0;
+ float mean = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum++;
+ mean += histo(p);
+ }
+
+ mean = mean / sum;
+
+ return mean;
+}
+
+/// \brief Compute the standard deviation on the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the dstandard deviation.
+///
+/// Compute the standard deviation by substracting the mean
+template <typename I>
+float stddev_frequency_histo(const mln::Image<I>& histo_, float mean)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the var of the histogram
+ float sum = 0;
+ float var = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum++;
+ var += mln::math::sqr(histo(p)-mean);
+ }
+
+ var = mln::math::sqrt(var / sum);
+
+ return var;
+}
+/// \}
+
+//============================================================================//
+// HUE TEST
+//============================================================================//
+
+/// Hue test
+/// \{
+/// \brief Hue test image processing stuff.
+///
+/// In this part, we define every thing that is correlated to the hue analysis.
+
+
+/// \brief Label a grey value.
+///
+/// \param[in] int_u8 the grey value.
+///
+/// \return the reference color for this grey value.
+///
+/// Classify grey value in three class, white, black and medium_gray.
+mln::value::rgb8 label_val(const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (82 > val)
+ result = mln::literal::black;
+ else if (179 > val)
+ result= mln::literal::medium_gray;
+ else
+ result = mln::literal::white;
+
+ return result;
+}
+
+
+/// \brief Label color with orange reference or brown reference.
+///
+/// \param[in] color the rgb8 color.
+/// \param[in] sat the HSV saturation.
+/// \param[in] val the HSV value.
+///
+/// \return the reference color with which it has been associated to.
+mln::value::rgb8 label_orange_or_brown(const mln::value::rgb8 color,
+ const mln::value::int_u8 sat,
+ const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (mln::literal::orange == color)
+ {
+ unsigned dist_orange = mln::math::abs(sat - 184)
+ + mln::math::abs(val - 65);
+
+ unsigned dist_brown = mln::math::abs(sat - 255)
+ + mln::math::abs(val - 125);
+
+ if (dist_orange < dist_brown)
+ result = mln::literal::orange;
+ else
+ result = mln::literal::brown;
+ }
+ else
+ result = color;
+
+ return result;
+}
+
+
+/// \brief Label between yellow and green color.
+///
+/// \param[in] color the rgb8 color.
+/// \param[in] val the HSV value.
+///
+/// \return the reference color associated to that color.
+mln::value::rgb8 label_yellow_or_green(const mln::value::rgb8 color,
+ const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (mln::literal::yellow == color)
+ {
+ // Is it green or yellow ?
+ if (80 > val)
+ result = mln::literal::green;
+ else
+ result = mln::literal::yellow;
+ }
+ else
+ return color;
+
+ return result;
+}
+
+
+/// \brief Label hue color.
+///
+/// \param[in] hue the HSV hue canal for a pixel.
+///
+/// \return a hue segmentation of the hue wheel.
+///
+/// The old classification given by Millet is commented. Mine is ready
+/// to use. We need to change reference colors to make the
+/// primary colors, the secondary ones, etc...
+mln::value::rgb8 label_hue(const mln::value::int_u8 hue)
+{
+ mln::value::rgb8 result;
+
+
+ if (10 > hue)
+ result = mln::literal::red;
+ else if (32 > hue)
+ result = mln::literal::orange;
+ else if (53 > hue)
+ result = mln::literal::yellow;
+ else if (74 > hue)
+ result = mln::literal::green; // chartreuse
+ else if (96 > hue)
+ result = mln::literal::green;
+ else if (116 > hue)
+ result = mln::literal::green;// turquoise, aigue-marine
+ else if (138 > hue)
+ result = mln::literal::green; // cyan
+ else if (159 > hue)
+ result = mln::literal::blue; // azur
+ else if (181 > hue)
+ result = mln::literal::blue;
+ else if (202 > hue)
+ result = mln::literal::violet;
+ else if (223 > hue)
+ result = mln::literal::pink;
+ else // if (244 > hue)
+ result = mln::literal::red;
+
+ return result;
+}
+
+/// \brief The hue test.
+///
+/// \param[in] input the name of the input image.
+/// \param[in] output the name of the histogram to output.
+/// \param[in] tmp the name of the hue map to output.
+/// \param[in] threshold the limit to compute the histogram contribution.
+///
+/// \return the proportion of pixels that pass the test.
+///
+/// This is an augmented test. We first normalized the histogram to
+/// obtain a discrete distribution. Then we compute the mean (or the
+/// peak, i don't really know what is the best) and we look at the
+/// proportion of the pixels around the mean or the peak. This
+/// proportion tell us how histogram distribution is concentrated
+/// around the modal value. If a hue modal value exist, we can say
+/// that the image is colorized.
+float hue_test(const std::string input,
+ const std::string output,
+ const std::string tmp,
+ const short threshold)
+
+{
+ typedef mln::fun::v2v::rgb_to_hue_map<8> t_rgb_to_hue_map;
+
+ mln::image2d<mln::value::rgb8> input_rgb8;
+ mln::image2d<mln::value::int_u8> map;
+ mln::image1d<unsigned> histo;
+ mln::image1d<float> histo_float;
+ float cnt1;
+ float cnt2;
+ float prop;
+ short peak;
+ mln::value::rgb8 color;
+ float sum;
+ mln::point1d inf;
+ mln::point1d sup;
+
+ mln::io::ppm::load(input_rgb8, input.c_str());
+
+ map = mln::data::transform(input_rgb8, t_rgb_to_hue_map());
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), map);
+ sum = sum_frequency_histo(histo);
+ histo_float = mln::data::convert(float(), histo) / sum;
+ peak = mean_histo(histo); //peak_histo(histo);
+ color = label_hue(peak);
+ inf = mln::point1d(mln::math::max(0, peak-threshold));
+ sup = mln::point1d(mln::math::min(255, peak+threshold));
+ cnt1 = count_histo(histo_float|mln::box1d(inf,sup));
+ cnt2 = count_histo(histo_float);
+ prop = ((100.0 * cnt1) / cnt2);
+
+ mln::io::plot::save_image_sh(histo_float, output.c_str());
+ mln::io::pgm::save(map, tmp.c_str());
+// std::cout << "peak = " << peak << std::endl;
+// std::cout << "color = " << color << std::endl;
+
+ return prop;
+}
+/// \}
+
+//============================================================================//
+// SATURATION TEST
+//============================================================================//
+
+/// Saturation test
+/// \{
+/// \brief Saturation test image processing stuff.
+///
+/// In this part, we define every thing that is correlated to the
+/// saturation analysis.
+
+
+/// \brief The saturation test.
+///
+/// \param[in] input the name of the input image.
+/// \param[in] output the name of the histogram to output.
+/// \param[in] tmp the name of the hue map to output.
+/// \param[in] threshold for deciding which is low saturation or not.
+///
+/// \return the proportion of pixels which pass the test.
+///
+/// This is the augmented test, we normalized the histogram and then
+/// we count the proportion of the histogram below the threshold.
+float saturation_test(const std::string input,
+ const std::string output,
+ const std::string tmp,
+ const short threshold)
+
+{
+ typedef mln::fun::v2v::rgb_to_saturation_map<8> t_rgb_to_saturation_map;
+
+ mln::image2d<mln::value::rgb8> input_rgb8;
+ mln::image2d<mln::value::int_u8> map;
+ mln::image1d<unsigned> histo;
+ mln::image1d<float> histo_float;
+ float cnt1;
+ float cnt2;
+ float sum;
+ float prop;
+
+ mln::io::ppm::load(input_rgb8, input.c_str());
+
+ map = mln::data::transform(input_rgb8, t_rgb_to_saturation_map());
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), map);
+ sum = sum_frequency_histo(histo);
+ histo_float = mln::data::convert(float(), histo) / sum;
+ cnt1 = count_histo(histo_float | mln::box1d(mln::point1d(0),
+ mln::point1d(threshold)));
+ cnt2 = count_histo(histo_float);
+ prop = ((100.0 * cnt1) / cnt2);
+
+ mln::io::plot::save_image_sh(histo_float, output.c_str());
+ mln::io::pgm::save(map, tmp.c_str());
+
+ return prop;
+}
+/// \}
+
+//============================================================================//
+// VALUE TEST
+//============================================================================//
+
+/// Value test
+/// \{
+/// \brief Value test image processing stuff.
+///
+/// In this part, we define every thing that is correlated to the
+/// value analysis.
+
+
+
+/// \brief The R function of Millet
+///
+/// \param[in] p the position of the pic.
+/// \param[in] histo_p the histo value of the pic.
+/// \param[in] x the position of the element which we compute the contrib.
+/// \param[in] histo_x the histo value of that element.
+///
+/// \result the contribution of the element x.
+///
+/// This function compute the variance-like contribution of an element
+/// x linked to the pic of the histogram. In fact, every thing is like
+/// we compute a square distance-like between the element x and the
+/// pic in the normalized histogram. Notice that the normalized
+/// histogram is the histogram divide by the value of it's pic. So at
+/// the pic, the value equals 1. It's a current representation of the
+/// histogram in image processing, we can find it in gimp for exemple.
+float r(short p, unsigned histo_p, short x, unsigned histo_x)
+{
+ float result = mln::math::sqr(((float)histo_x / histo_p) * (x-p));
+
+ return result;
+}
+
+/// \brief The stddev3 is an internal stuff.
+///
+/// \param[in] histo_ the image which represents the histogram.
+/// \param[in] peak the position of the histogram peak.
+///
+/// \return simple computing of deviation.
+///
+/// This is an internal stuff. It splits the computing for easy
+/// reusing practice. Sum the R contribution.
+template <typename I>
+float stddev3(const mln::Image<I>& histo_, unsigned peak)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Compute stddev
+
+ float stddev = 0.0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ stddev += r((short)peak, mln::opt::at(histo,peak), p.ind(), histo(p));
+ }
+
+ return stddev;
+}
+
+/// Brief compute the whole deviation of Millet
+///
+/// \param[in] image the input image to analyze.
+///
+/// \return the deviation.
+///
+/// The deviation uses the R function. It stats by finding the pic. If
+/// the pic is near the rigth border of the histo, compute the R
+/// function on the left neighbouring of the pic. If the pic is near
+/// the left border of the histo, compute the R function on the right
+/// neigbouring. Otherwise, compute the average of the right and left
+/// results. The selected neighbouring is composed of five pixels at
+/// the right or at the left of the pic. The detection of clipart
+/// assumes that the majority of the energy of the histogram is closed
+/// to the pic (five pixels around it). The test is generalized by
+/// making constants as parameters.
+template <typename I>
+float stddev2(const mln::Image<I>& histo_, unsigned peak, unsigned limit)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ float stddev_low = 0.0;
+ float stddev_up = 0.0;
+ float ret = 0.0;
+
+ // A transformer avec des iterators
+
+ if (250 > peak)
+ stddev_up = stddev3(histo |mln::box1d(mln::point1d(peak+1),
+ mln::point1d(peak+limit)), peak);
+
+ if (5 < peak)
+ stddev_low = stddev3(histo |mln::box1d(mln::point1d(peak-limit),
+ mln::point1d(peak-1)), peak);
+
+ ret = (250 < peak)? stddev_low : (5 > peak)? stddev_up :
+ (stddev_low + stddev_up)/2;
+
+ return ret;
+}
+
+
+/// \brief This is the Value test.
+///
+/// \param[in] input the name of the input image.
+/// \param[in] output the name of result histogram.
+/// \param[in] tmp the name of the output value (HSV) map.
+/// \param[in] threshold the range around the peak where R is computed.
+///
+/// \return the proportion of pixels that pass the test.
+///
+/// This is the augmented version of the Millet test. This code is not
+/// stable. There is a lots of tests on. The Millet test is computed
+/// with stddev2 call. We test simple counting around the pic as we
+/// do for other tests but it's not really insteresting. The prop4 is
+/// the best for me. We test the difference between the distribution and the
+/// equi-distribution.
+float value_test(const std::string input,
+ const std::string output,
+ const std::string tmp,
+ const short threshold)
+
+{
+ typedef mln::fun::v2v::rgb_to_value_map<8> t_rgb_to_value_map;
+
+ mln::image2d<mln::value::rgb8> input_rgb8;
+ mln::image2d<mln::value::int_u8> map;
+ mln::image1d<unsigned> histo;
+ mln::image1d<float> histo_float;
+ float cnt1;
+ float cnt2;
+ float prop;
+ float sum;
+ float prop4;
+ short peak;
+ mln::point1d inf;
+ mln::point1d sup;
+
+
+ mln::io::ppm::load(input_rgb8, input.c_str());
+
+ map = mln::data::transform(input_rgb8, t_rgb_to_value_map());
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), map);
+ sum = sum_frequency_histo(histo);
+ histo_float = mln::data::convert(float(), histo) / sum;
+ prop4 = cmp_equi_frequency_histo(histo_float);
+ peak = peak_histo(histo); // mean_histo(histo);
+ //prop = stddev2(histo, peak, threshold);
+ inf = mln::point1d(mln::math::max(0, peak-threshold));
+ sup = mln::point1d(mln::math::min(255, peak+threshold));
+ cnt1 = count_histo(histo_float|mln::box1d(inf,sup));
+ cnt2 = count_histo(histo_float);
+ prop = ((100.0 * cnt1) / cnt2);
+
+ std::cerr << "peak = " << peak << std::endl;
+ std::cerr << "inf = " << inf << std::endl;
+ std::cerr << "sup = " << sup << std::endl;
+ std::cerr << "cnt1 = " << cnt1 << std::endl;
+ std::cerr << "cnt2 = " << cnt2 << std::endl;
+ std::cerr << "prop = " << prop << std::endl;
+ std::cerr << "prop4= " << prop4 << std::endl;
+
+ mln::io::plot::save_image_sh(histo_float, output.c_str());
+ mln::io::pgm::save(map, tmp.c_str());
+
+ return prop;
+}
+
+//============================================================================//
+// MAIN
+//============================================================================//
+
+
+/// \brief The main entry.
+///
+/// This is a front end for launching image processing test. We deal
+/// with boost library to walk on image database directories. Nothing
+/// very interesting here, it is a lot of plumberies.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+// t_path full_path[] = {t_path(ICDAR_20P_TEXT_ONLY_IMG_PATH),
+// t_path(ICDAR_20P_TEXT_COLOR_IMG_PATH),
+// t_path(ICDAR_20P_TEXT_PHOTO_IMG_PATH)};
+
+ t_path full_path[] = {t_path(AFP_PPM_IMG_PATH)};
+
+ std::cout << "#!/usr/bin/gnuplot" << std::endl;
+ std::cout << "set terminal x11 persist 1" << std::endl;
+ std::cout << "#HUE - SATURATION - VALUE" << std::endl;
+ std::cout << "plot '-' using 1:2 with point notitle,\\" << std::endl;
+ std::cout << " '-' using 1:2 with point notitle,\\" << std::endl;
+ std::cout << " '-' using 1:2 with point notitle" << std::endl;
+
+ for (int i = 0; i < 1; ++i)
+ {
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ float prop = 0.0;
+ t_path directory;
+ t_path leaf;
+ t_path output;
+ t_path tmp;
+
+ std::cerr << "entering " << full_path[i] << std::endl;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ std::cerr << dir_iter->path() << std::endl;
+ // concatenation de chaine
+// directory = (ANNOTATING_ICDAR_H_INPUT_RET_PATH);
+ directory = (ANNOTATING_AFP_H_INPUT_RET_PATH);
+ leaf = dir_iter->path().leaf();
+ output = change_extension(directory / leaf, ".sh");
+ tmp = change_extension(directory / leaf, ".pgm");
+
+ prop = hue_test(dir_iter->path().string(),
+ output.string(),
+ tmp.string(),
+ 20);
+
+ std::cout << prop << " ";
+
+// directory = (ANNOTATING_ICDAR_S_INPUT_RET_PATH);
+ directory = (ANNOTATING_AFP_S_INPUT_RET_PATH);
+ leaf = dir_iter->path().leaf();
+ output = change_extension(directory / leaf, ".sh");
+ tmp = change_extension(directory / leaf, ".pgm");
+
+ prop = saturation_test(dir_iter->path().string(),
+ output.string(),
+ tmp.string(),
+ 25);
+
+ std::cout << prop << " ";
+
+// directory = (ANNOTATING_ICDAR_V_INPUT_RET_PATH);
+ directory = (ANNOTATING_AFP_V_INPUT_RET_PATH);
+ leaf = dir_iter->path().leaf();
+ output = change_extension(directory / leaf, ".sh");
+ tmp = change_extension(directory / leaf, ".pgm");
+
+ prop = value_test(dir_iter->path().string(),
+ output.string(),
+ tmp.string(),
+ 15);
+
+ std::cout << prop << " ";
+ std::cout << "# " << dir_iter->path().leaf() << std::endl;
+ }
+ std::cout << "e" << std::endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/hue/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/hue/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/hue/hue.cc b/scribo/sandbox/green/exp/annotating/hue/hue.cc
new file mode 100644
index 0000000..6e1195c
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/hue/hue.cc
@@ -0,0 +1,402 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet hue operator [millet.phd.2008.pdf]
+///
+/// This is the Millet code for moving from RGB space to Hue
+/// one. Formulae are classical, we can find them on the web.
+///
+/// Val = max(R,G,B).
+/// Sat = (max(R,G,B) - min(R,G,B))/max(R,G,B).
+/// IF R = max(R,G,B) THEN Hue = 60 * [(V-B)/(max(R,G,B)-min(R,G,B))].
+/// IF G = max(R,G,B) THEN Hue = 60 * [2 + (B-R)/(max(R,G,B)-min(R,G,B))].
+/// IF B = max(R,G,B) THEN Hue = 60 * [4 + (R-G)/(max(R,G,B)-min(R,G,B))].
+
+
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/stretch.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/literal/colors.hh>
+#include <mln/literal/grays.hh>
+
+#include <mln/math/max.hh>
+#include <mln/math/min.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/geom/nsites.hh>
+
+#include <mln/fun/v2v/rgb_to_hue_map.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+
+
+/// \brief Label a grey value.
+///
+/// \param[in] int_u8 the grey value.
+///
+/// \return the reference color for this grey value.
+///
+/// Classify grey value in three class, white, black and medium_gray.
+mln::value::rgb8 label_val(const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (82 > val)
+ result = mln::literal::black;
+ else if (179 > val)
+ result= mln::literal::medium_gray;
+ else
+ result = mln::literal::white;
+
+ return result;
+}
+
+
+/// \brief Label color with orange reference or brown reference.
+///
+/// \param[in] color the rgb8 color.
+/// \param[in] sat the HSV saturation.
+/// \param[in] val the HSV value.
+///
+/// \return the reference color with which it has been associated to.
+mln::value::rgb8 label_orange_or_brown(const mln::value::rgb8 color,
+ const mln::value::int_u8 sat,
+ const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (mln::literal::orange == color)
+ {
+ unsigned dist_orange = mln::math::abs(sat - 184)
+ + mln::math::abs(val - 65);
+
+ unsigned dist_brown = mln::math::abs(sat - 255)
+ + mln::math::abs(val - 125);
+
+ if (dist_orange < dist_brown)
+ result = mln::literal::orange;
+ else
+ result = mln::literal::brown;
+ }
+ else
+ result = color;
+
+ return result;
+}
+
+/// \brief Label between yellow and green color.
+///
+/// \param[in] color the rgb8 color.
+/// \param[in] val the HSV value.
+///
+/// \return the reference color associated to that color.
+mln::value::rgb8 label_yellow_or_green(const mln::value::rgb8 color,
+ const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (mln::literal::yellow == color)
+ {
+ // Is it green or yellow ?
+ if (80 > val)
+ result = mln::literal::green;
+ else
+ result = mln::literal::yellow;
+ }
+ else
+ return color;
+
+ return result;
+}
+
+
+/// \brief Label hue color.
+///
+/// \param[in] hue the HSV hue canal for a pixel.
+///
+/// \return a hue segmentation of the hue wheel.
+///
+/// The old classification given by Millet is commented. Mine is ready
+/// to use. We need to change reference colors to make the
+/// primary colors, the secondary ones, etc...
+mln::value::rgb8 label_hue(const mln::value::int_u8 hue)
+{
+ mln::value::rgb8 result;
+
+
+ if (10 > hue)
+ result = mln::literal::red;
+ else if (32 > hue)
+ result = mln::literal::orange;
+ else if (53 > hue)
+ result = mln::literal::yellow;
+ else if (74 > hue)
+ result = mln::literal::green; // chartreuse
+ else if (96 > hue)
+ result = mln::literal::green;
+ else if (116 > hue)
+ result = mln::literal::green;// turquoise, aigue-marine
+ else if (138 > hue)
+ result = mln::literal::green; // cyan
+ else if (159 > hue)
+ result = mln::literal::blue; // azur
+ else if (181 > hue)
+ result = mln::literal::blue;
+ else if (202 > hue)
+ result = mln::literal::violet;
+ else if (223 > hue)
+ result = mln::literal::pink;
+ else // if (244 > hue)
+ result = mln::literal::red;
+
+
+// if (14 > hue)
+// result = mln::literal::red;
+// else if (29 > hue)
+// result = mln::literal::orange;
+// else if (45 > hue)
+// result = mln::literal::yellow;
+// else if (113 > hue)
+// result = mln::literal::green;
+// else if (149 > hue)
+// result = mln::literal::cyan;
+// else if (205 > hue)
+// result = mln::literal::blue;
+// else if (235 > hue)
+// result = mln::literal::violet;
+// else if (242 > hue)
+// result = mln::literal::pink;
+// else
+// result = mln::literal::red;
+
+ return result;
+}
+
+
+/// \brief Sum all the bins of the histogram.
+///
+/// \param[in] img the histogram based on image.
+///
+/// \return the sum of the overall bins.
+///
+/// Sum evry bins and return the result.
+template <typename I>
+unsigned count_histo(const mln::Image<I>& img_)
+{
+ const I& img = exact(img_);
+
+ mln_precondition(img.is_valid());
+
+ unsigned result = 0;
+
+ mln_piter(I) p(img.domain());
+
+ for_all(p)
+ result += img(p);
+
+ return result;
+}
+
+/// \brief Find the peak of the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the bin which contains the greatest value.
+///
+/// Compute the position of the peak of the histogram. To do this, we
+/// view evrey bin and we maintain the maxima of the values and the
+/// position. At the end, we return the position which contains the
+/// greatest value.
+template <typename I>
+unsigned peak_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the peak of the histogram
+ unsigned v_max = mln::opt::at(histo, 0);
+ short p_max = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ return p_max;
+}
+
+/// \brief Compute the average of the histogram.
+///
+/// \param[in] histo_ the histogram.
+///
+/// \return the average of the histogram.
+///
+/// Compute the mean of the histogram by summing the values of each
+/// bin ponderated by its frequency. The result is divided by the sum
+/// of the frequencies.
+template <typename I>
+unsigned mean_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the mean of the histogram
+ float sum = 0;
+ float mean = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum += histo(p);
+ mean += p.ind()*histo(p);
+ }
+
+ mean = mean / sum;
+
+ return mean;
+}
+
+
+/// \brief The hue test.
+///
+/// \param[in] input the name of the input image.
+/// \param[in] output the name of the histogram to output.
+/// \param[in] tmp the name of the hue map to output.
+///
+/// \return the proportion of pixels that pass the test.
+///
+/// Load the input image, transform it to get the hue_map and compute
+/// the histogram. Then count the number of pixels that are between
+/// peak-threshold and peak +threshold. Print the peak and the
+/// percentage of pixels around the pic.
+float hue_test(const std::string input,
+ const std::string output,
+ const std::string tmp,
+ const unsigned threshold)
+
+{
+ typedef mln::fun::v2v::rgb_to_hue_map<8> t_rgb_to_hue_map;
+
+ mln::image2d<mln::value::rgb8> input_rgb8;
+ mln::image2d<mln::value::int_u8> map;
+ mln::image1d<unsigned> histo;
+ unsigned cnt1;
+ unsigned cnt2;
+ float prop;
+ unsigned peak;
+ mln::value::rgb8 color;
+
+ mln::io::ppm::load(input_rgb8, input.c_str());
+
+ map = mln::data::transform(input_rgb8, t_rgb_to_hue_map());
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), map);
+ peak = mean_histo(histo); //peak_histo(histo);
+ color = label_hue(peak);
+ cnt1 = count_histo(histo | mln::box1d(mln::point1d(peak-threshold),
+ mln::point1d(peak+threshold)));
+ cnt2 = mln::geom::nsites(input_rgb8);
+ prop = ((100.0 * cnt1) / cnt2);
+
+ mln::io::plot::save_image_sh(histo, output.c_str());
+ mln::io::pgm::save(map, tmp.c_str());
+ std::cout << "peak = " << peak << std::endl;
+ std::cout << "color = " << color << std::endl;
+
+ return prop;
+}
+
+
+/// \brief Main entry.
+///
+/// It is a front end which managing the iteration through one image
+/// data base with boost. Save hue map and hue histogram.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+ t_path full_path[] = {t_path(ICDAR_20P_PPM_IMG_PATH)};
+
+ for (int i = 0; i < 1; ++i)
+ {
+ std::cout << "entering " << full_path[i] << std::endl;
+
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ float prop = 0.0;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ // concatenation de chaine
+ t_path directory(ANNOTATING_ICDAR_RET_PATH);
+ t_path leaf = dir_iter->path().leaf();
+ t_path output = change_extension(directory / leaf, ".sh");
+ t_path tmp = change_extension(directory / leaf, ".pgm");
+
+ prop = hue_test(dir_iter->path().string(),
+ output.string(),
+ tmp.string(),
+ 20);
+
+ std::cout << output << " : " << prop << std::endl;
+ std::cerr << output << " : " << prop << std::endl;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-color.txt b/scribo/sandbox/green/exp/annotating/hue/text-color.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-color.txt
copy to scribo/sandbox/green/exp/annotating/hue/text-color.txt
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-img.txt b/scribo/sandbox/green/exp/annotating/hue/text-img.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-img.txt
copy to scribo/sandbox/green/exp/annotating/hue/text-img.txt
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-only.txt b/scribo/sandbox/green/exp/annotating/hue/text-only.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-only.txt
copy to scribo/sandbox/green/exp/annotating/hue/text-only.txt
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/nb_color/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/nb_color/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/nb_color/nb_color.cc b/scribo/sandbox/green/exp/annotating/nb_color/nb_color.cc
new file mode 100644
index 0000000..2331c61
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/nb_color/nb_color.cc
@@ -0,0 +1,171 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Compute the number of colors in an image.
+///
+/// Build histogram of colors and count the bins different from zero.
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/math/count.hh>
+#include <mln/accu/stat/histo3d_rgb.hh>
+
+#include <mln/binarization/threshold.hh>
+
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+// #include <mln/morpho/opening/volume.hh>
+
+#include <mln/io/ppm/load.hh>
+
+#include <mln/pw/value.hh>
+#include <mln/pw/cst.hh>
+
+#include <mln/util/timer.hh>
+
+#include <mln/value/rgb8.hh>
+//#include <mln/value/rgb.hh>
+
+
+/// \brief Count the colors.
+///
+/// \param[in] image the name of the image to process.
+///
+/// \return the number of colors.
+///
+/// Count the color by building histogram. Strange filtering is
+/// done. We use also the technique of regional maxima in
+/// comment. Quantification is done to reduce the size of the
+/// histogram as well.
+
+// n < 8, n is the degree of quantification
+template <unsigned n>
+unsigned count_image_color(const std::string& image)
+{
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<n> t_rgbn;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgbn> t_image2d_rgbn;
+ typedef mln::image3d<unsigned> t_histo3d;
+ typedef mln::image3d<bool> t_histo3d_bool;
+ typedef mln::fun::v2v::rgb8_to_rgbn<n> t_rgb8_to_rgbn;
+ typedef mln::accu::meta::stat::histo3d_rgb t_histo3d_fun;
+ typedef mln::accu::meta::math::count t_count_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_rgbn input_rgbn;
+ t_image2d_rgbn output_rgbn;
+ t_histo3d histo;
+// t_histo3d opened;
+ t_histo3d_bool filtered;
+
+ mln::io::ppm::load(input_rgb8, image.c_str());
+
+ unsigned nb_pixel = input_rgb8.ncols() * input_rgb8.nrows();
+ unsigned min_volume = (unsigned)(nb_pixel * 0.0001);
+ unsigned nb_color = 0;
+
+// input_rgbn = mln::data::transform(input_rgb8, t_rgb8_to_rgbn());
+ histo = mln::data::compute(t_histo3d_fun(), input_rgb8);
+// opened = mln::morpho::opening::volume(histo, mln::c6(), min_volume);
+ filtered = mln::binarization::threshold(histo, min_volume);
+ nb_color = mln::data::compute(t_count_fun(),
+ (filtered|(mln::pw::value(filtered)!=0)).rw());
+
+ return nb_color;
+}
+
+
+/// \brief Main entry.
+///
+/// The main routine makes the base driver job. It looks after many
+/// directories and lists every images in it. We use the boost library
+/// to do it. Statistics are computed on the number of colors. The
+/// first idea was to answer the question is this descriptor allow to
+/// recognize a specific base.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ //typedef boost::filesystem::initial_path<t_path()> t_init_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+ t_path full_path[] = {t_path(ANNOTATING_1_BILL_IMG_PATH),
+ t_path(ANNOTATING_1_FAX_IMG_PATH),
+ t_path(ANNOTATING_1_HANDWRITTEN_IMG_PATH),
+ t_path(ANNOTATING_1_LOGO_IMG_PATH),
+ t_path(ANNOTATING_1_MAP_IMG_PATH),
+ t_path(ANNOTATING_1_PHOTO_IMG_PATH),
+ t_path(ANNOTATING_1_SCREENSHOT_IMG_PATH),
+ t_path(ANNOTATING_1_SLIDE_IMG_PATH),
+ t_path(ANNOTATING_1_TYPED_IMG_PATH)};
+
+ for (int i = 0; i < 9; ++i)
+ {
+ std::cerr << "entering " << full_path[i] << std::endl;
+ std::cout << "entering " << full_path[i] << std::endl;
+
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ unsigned count = 0;
+ unsigned sum1 = 0;
+ unsigned sum2 = 0;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ unsigned val = count_image_color<8>(dir_iter->path().string());
+
+ ++count;
+ sum1 += val;
+ sum2 += val*val;
+
+ std::cout << dir_iter->path().string() << " => " << val << std::endl;
+ }
+
+ float mean = sum1 / count;
+ float var = ((float)sum2 / count) - (mean * mean);
+
+ std::cout << "mean : " << mean << std::endl;
+ std::cout << "var : " << var << std::endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/saturation/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/saturation/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/saturation/saturation.cc b/scribo/sandbox/green/exp/annotating/saturation/saturation.cc
new file mode 100644
index 0000000..b5834a1
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/saturation/saturation.cc
@@ -0,0 +1,175 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet saturation operator [millet.phd.2008.pdf]
+///
+/// This is the Millet code for moving from RGB space to Sat
+/// one. Formulae are classical, we can find them on the web.
+///
+/// Val = max(R,G,B).
+/// Sat = (max(R,G,B) - min(R,G,B))/max(R,G,B).
+/// IF R = max(R,G,B) THEN Hue = 60 * [(V-B)/(max(R,G,B)-min(R,G,B))].
+/// IF G = max(R,G,B) THEN Hue = 60 * [2 + (B-R)/(max(R,G,B)-min(R,G,B))].
+/// IF B = max(R,G,B) THEN Hue = 60 * [4 + (R-G)/(max(R,G,B)-min(R,G,B))].
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/stretch.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/math/max.hh>
+#include <mln/math/min.hh>
+
+#include <mln/geom/nsites.hh>
+
+#include <mln/fun/v2v/rgb_to_saturation_map.hh>
+
+#include <mln/io/ppm/load.hh>
+//#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/value/rgb8.hh>
+
+/// \brief Sum all the bins of the histogram.
+///
+/// \param[in] img the histogram based on image.
+///
+/// \return the sum of the overall bins.
+///
+/// Sum evry bins and return the result.
+template <typename I>
+unsigned count_histo(const mln::Image<I>& img_)
+{
+ const I& img = exact(img_);
+
+ mln_precondition(img.is_valid());
+
+ unsigned result = 0;
+
+ mln_piter(I) p(img.domain());
+
+ for_all(p)
+ result += img(p);
+
+ return result;
+}
+
+/// \brief The saturation test.
+///
+/// \param[in] input the name of the input image.
+/// \param[in] output the name of the histogram to output.
+/// \param[in] threshold for deciding which is low saturation or not.
+///
+/// \return the proportion of pixels that pass the test.
+///
+/// Load the input image, transform it to get the saturation_map and compute
+/// the histogram. Then count the number of pixels that are under the threshold.
+/// Then return the proportion of pixels.
+float saturation_test(const std::string input,
+ const std::string output,
+// const std::string tmp,
+ const unsigned threshold)
+
+{
+ typedef mln::fun::v2v::rgb_to_saturation_map<8> t_rgb_to_saturation_map;
+
+ mln::image2d<mln::value::rgb8> input_rgb8;
+ mln::image2d<mln::value::int_u8> map;
+ mln::image1d<unsigned> histo;
+ unsigned cnt1;
+ unsigned cnt2;
+ float prop;
+
+ mln::io::ppm::load(input_rgb8, input.c_str());
+
+ map = mln::data::transform(input_rgb8, t_rgb_to_saturation_map());
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), map);
+ cnt1 = count_histo(histo | mln::box1d(mln::point1d(0),
+ mln::point1d(threshold)));
+ cnt2 = mln::geom::nsites(input_rgb8);
+ prop = ((100.0 * cnt1) / cnt2);
+
+ mln::io::plot::save_image_sh(histo, output.c_str());
+// mln::io::pgm::save(map, tmp.c_str());
+
+ return prop;
+}
+
+
+/// \brief the main entry.
+///
+/// This is a front end for image processing routine. It manages the
+/// calling of every image in the database.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+ t_path full_path[] = {t_path(ICDAR_20P_PPM_IMG_PATH)};
+
+ for (int i = 0; i < 1; ++i)
+ {
+ std::cout << "entering " << full_path[i] << std::endl;
+
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ float prop = 0.0;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ // concatenation de chaine
+ t_path directory(ANNOTATING_ICDAR_RET_PATH);
+ t_path leaf = dir_iter->path().leaf();
+ t_path output = change_extension(directory / leaf, ".sh");
+ t_path tmp = change_extension(directory / leaf, ".pgm");
+
+ prop = saturation_test(dir_iter->path().string(),
+ output.string(),
+// tmp.string(),
+ 25);
+
+ std::cout << output << " : " << prop << std::endl;
+ std::cerr << output << " : " << prop << std::endl;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-color.txt b/scribo/sandbox/green/exp/annotating/saturation/text-color.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-color.txt
copy to scribo/sandbox/green/exp/annotating/saturation/text-color.txt
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-img.txt b/scribo/sandbox/green/exp/annotating/saturation/text-img.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-img.txt
copy to scribo/sandbox/green/exp/annotating/saturation/text-img.txt
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-only.txt b/scribo/sandbox/green/exp/annotating/saturation/text-only.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-only.txt
copy to scribo/sandbox/green/exp/annotating/saturation/text-only.txt
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/stddev_color/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/stddev_color/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/stddev_color/stddev_color.cc b/scribo/sandbox/green/exp/annotating/stddev_color/stddev_color.cc
new file mode 100644
index 0000000..365a9c3
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/stddev_color/stddev_color.cc
@@ -0,0 +1,216 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet clipart detection [millet.phd.2008.pdf]
+///
+/// The aim of this descriptor is to recognize clipart. To do this, we
+/// assume that clipart have their histogram concentrated around their
+/// mode. This is particularly true if the clipart is design by hand,
+/// because a very small number of grey tones or colors are used to
+/// draw it. But sometimes, computer assists their creation and we can
+/// find some continuous set of tones and this artefact create noise
+/// for the detection technique describe bellow.
+
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/max_site.hh>
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb8_to_int_u8.hh>
+
+#include <mln/io/ppm/load.hh>
+
+#include <mln/math/sqr.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u.hh>
+
+/// \brief The R function of Millet
+///
+/// \param[in] p the position of the pic.
+/// \param[in] histo_p the histo value of the pic.
+/// \param[in] x the position of the element which we compute the contrib.
+/// \param[in] histo_x the histo value of that element.
+///
+/// \result the contribution of the element x.
+///
+/// This function compute the variance-like contribution of an element
+/// x linked to the pic of the histogram. In fact, every thing is like
+/// we compute a square distance-like between the element x and the
+/// pic in the normalized histogram. Notice that the normalized
+/// histogram is the histogram divide by the value of it's pic. So at
+/// the pic, the value equals 1. It's a current representation of the
+/// histogram in image processing, we can find it in gimp for exemple.
+float r(short p, unsigned histo_p, short x, unsigned histo_x)
+{
+ float result = mln::math::sqr(((float)histo_x / histo_p) * (x-p));
+
+ return result;
+}
+
+/// Brief compute the whole deviation of Millet
+///
+/// \param[in] image the input image to analyze.
+///
+/// \return the deviation.
+///
+/// The deviation uses the R function. It stats by finding the pic. If
+/// the pic is near the rigth border of the histo, compute the R
+/// function on the left neighbouring of the pic. If the pic is near
+/// the left border of the histo, compute the R function on the right
+/// neigbouring. Otherwise, compute the average of the right and left
+/// results. The selected neighbouring is composed of five pixels at
+/// the right or at the left of the pic. The detection of clipart
+/// assumes that the majority of the energy of the histogram is closed
+/// to the pic (five pixels around it).
+float stddev_color(const std::string& image)
+{
+ typedef mln::point1d t_point1d;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image1d<unsigned> t_histo1d;
+ typedef mln::fun::v2v::rgb8_to_int_u8 t_rgb8_to_int_u8;
+ typedef mln::accu::meta::stat::histo1d t_histo1d_fun;
+ typedef mln::accu::max_site<t_histo1d> t_max_site_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_int_u8 input_int_u8;
+ t_histo1d histo;
+ t_point1d max_site;
+
+ mln::io::ppm::load(input_rgb8, image.c_str());
+ input_int_u8 = mln::data::transform(input_rgb8, t_rgb8_to_int_u8());
+ histo = mln::data::compute(t_histo1d_fun(), input_int_u8);
+
+ // Find the peak of the histogram
+ unsigned v_max = mln::opt::at(histo, 0);
+ short p_max = 0;
+
+ mln_piter_(t_histo1d) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ // Compute the specific stddev
+
+ float stddev_low = 0.0;
+ float stddev_up = 0.0;
+ float stddev = 0.0;
+
+ if (250 > p_max)
+ for (short i = p_max+1; i < p_max+6; ++i)
+ stddev_up += r(p_max, mln::opt::at(histo,p_max),
+ i, mln::opt::at(histo,i));
+
+ if (5 < p_max)
+ for (short i = p_max-1; i > p_max-6; --i)
+ stddev_low += r(p_max, mln::opt::at(histo,p_max),
+ i, mln::opt::at(histo,i));
+
+ stddev = (250 < p_max)? stddev_low : (5 > p_max)? stddev_up :
+ (stddev_low + stddev_up)/2;
+
+ return stddev;
+}
+
+
+/// \brief Main entry.
+///
+/// Front end for image processing. It is in the main routine where we
+/// go through the image data base (using boost to do it).
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+ t_path full_path[] = {t_path(ANNOTATING_1_BILL_IMG_PATH),
+ t_path(ANNOTATING_1_FAX_IMG_PATH),
+ t_path(ANNOTATING_1_HANDWRITTEN_IMG_PATH),
+ t_path(ANNOTATING_1_LOGO_IMG_PATH),
+ t_path(ANNOTATING_1_MAP_IMG_PATH),
+ t_path(ANNOTATING_1_PHOTO_IMG_PATH),
+ t_path(ANNOTATING_1_SCREENSHOT_IMG_PATH),
+ t_path(ANNOTATING_1_SLIDE_IMG_PATH),
+ t_path(ANNOTATING_1_TYPED_IMG_PATH)};
+
+ for (int i = 0; i < 9; ++i)
+ {
+ std::cerr << "entering " << full_path[i] << std::endl;
+ std::cout << "entering " << full_path[i] << std::endl;
+
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ float count = 0;
+ float sum1 = 0;
+ float sum2 = 0;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ float val = stddev_color(dir_iter->path().string());
+
+ ++count;
+ sum1 += val;
+ sum2 += val*val;
+
+ std::cout << dir_iter->path().string() << " => " << val << std::endl;
+ }
+
+ float mean = sum1 / count;
+ float var = ((float)sum2 / count) - (mean * mean);
+
+ std::cout << "mean : " << mean << std::endl;
+ std::cout << "var : " << var << std::endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/stddev_color_16/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/stddev_color_16/Makefile.am
diff --git a/scribo/sandbox/green/exp/annotating/stddev_color_16/stddev_color_16.cc b/scribo/sandbox/green/exp/annotating/stddev_color_16/stddev_color_16.cc
new file mode 100644
index 0000000..fc55547
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/stddev_color_16/stddev_color_16.cc
@@ -0,0 +1,277 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet clipart detection [millet.phd.2008.pdf]
+///
+/// The aim of this descriptor is to recognize clipart. To do this, we
+/// assume that clipart have their histogram concentrated around their
+/// mode. This is particularly true if the clipart is design by hand,
+/// because a very small number of grey tones or colors are used to
+/// draw it. But sometimes, computer assists their creation and we can
+/// find some continuous set of tones and this artefact create noise
+/// for the detection technique describe bellow. When photographies
+/// has some large uniform border, the detection can fail. To improve
+/// the method, Millet decide to subdivise the image in 16 sub images
+/// on which it applies the test.
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/max_site.hh>
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/transform.hh>
+#include <mln/data/paste.hh>
+
+#include <mln/fun/v2v/rgb8_to_int_u8.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/math/sqr.hh>
+#include <mln/math/max.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u.hh>
+
+/// \brief The R function of Millet
+///
+/// \param[in] p the position of the pic.
+/// \param[in] histo_p the histo value of the pic.
+/// \param[in] x the position of the element which we compute the contrib.
+/// \param[in] histo_x the histo value of that element.
+///
+/// \result the contribution of the element x.
+///
+/// This function compute the variance-like contribution of an element
+/// x linked to the pic of the histogram. In fact, every thing is like
+/// we compute a square distance-like between the element x and the
+/// pic in the normalized histogram. Notice that the normalized
+/// histogram is the histogram divide by the value of it's pic. So at
+/// the pic, the value equals 1. It's a current representation of the
+/// histogram in image processing, we can find it in gimp for exemple.
+float r(short p, unsigned histo_p, short x, unsigned histo_x)
+{
+ float result = mln::math::sqr(((float)histo_x / histo_p) * (x-p));
+
+ return result;
+}
+
+/// Brief compute the whole deviation of Millet
+///
+/// \param[in] input_int_u8 the 8 bits input image to analyze.
+/// \param[in] name_histo the name of the output histogram.
+/// \param[in] name_image the name of the ouput sub image.
+///
+/// \return the deviation, but at this time nothing..
+///
+/// The deviation uses the R function. It stats by finding the pic. If
+/// the pic is near the rigth border of the histo, compute the R
+/// function on the left neighbouring of the pic. If the pic is near
+/// the left border of the histo, compute the R function on the right
+/// neigbouring. Otherwise, compute the average of the right and left
+/// results. The selected neighbouring is composed of five pixels at
+/// the right or at the left of the pic. The detection of clipart
+/// assumes that the majority of the energy of the histogram is closed
+/// to the pic (five pixels around it).
+float stddev_color(mln::image2d<mln::value::int_u8> input_int_u8)
+{
+ typedef mln::point1d t_point1d;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image1d<unsigned> t_histo1d;
+ typedef mln::fun::v2v::rgb8_to_int_u8 t_rgb8_to_int_u8;
+ typedef mln::accu::meta::stat::histo1d t_histo1d_fun;
+ typedef mln::accu::max_site<t_histo1d> t_max_site_fun;
+
+ t_histo1d histo;
+
+ histo = mln::data::compute(t_histo1d_fun(), input_int_u8);
+
+ // Find the peak of the histogram
+ unsigned v_max = mln::opt::at(histo, 0);
+ short p_max = 0;
+
+ mln_piter_(t_histo1d) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ // Compute the specific stddev
+
+ float stddev_low = 0.0;
+ float stddev_up = 0.0;
+ float stddev = 0.0;
+
+ if (250 > p_max)
+ for (short i = p_max+1; i < p_max+6; ++i)
+ stddev_up += r(p_max, mln::opt::at(histo,p_max),
+ i, mln::opt::at(histo,i));
+
+ if (5 < p_max)
+ for (short i = p_max-1; i > p_max-6; --i)
+ stddev_low += r(p_max, mln::opt::at(histo,p_max),
+ i, mln::opt::at(histo,i));
+
+ stddev = (250 < p_max)? stddev_low : (5 > p_max)? stddev_up :
+ (stddev_low + stddev_up)/2;
+
+ return stddev;
+}
+
+/// \brief Divide the image in 16 sub images.
+///
+/// \param[in] image the input image.
+///
+/// \result nothing.
+///
+/// Divive the input image in 16 by uniform and geometrical
+/// method. When a sub image is ready, call the stddev routine to show
+/// stats on it.
+float stddev_color_16(const std::string& image)
+{
+ typedef mln::point1d t_point1d;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image1d<unsigned> t_histo1d;
+ typedef mln::fun::v2v::rgb8_to_int_u8 t_rgb8_to_int_u8;
+ typedef mln::accu::meta::stat::histo1d t_histo1d_fun;
+ typedef mln::accu::max_site<t_histo1d> t_max_site_fun;
+
+ t_image2d_rgb8 input_rgb8;
+ t_image2d_int_u8 input_int_u8;
+
+ mln::io::ppm::load(input_rgb8, image.c_str());
+ input_int_u8 = mln::data::transform(input_rgb8, t_rgb8_to_int_u8());
+
+ // IMAGE SPLITTING PHASE
+ mln::box2d domain = input_int_u8.domain();
+ mln::point2d pmin = domain.pmin();
+ mln::point2d pmax = domain.pmax();
+
+ unsigned sz_row = (pmax.row() - pmin.row())/ 4;
+ unsigned sz_col = (pmax.col() - pmin.col())/ 4;
+ float stddev = 0.0;
+
+ // Divide the domain in nine sub-domains.
+ for (unsigned i = 0; i < 4; ++i)
+ for (unsigned j = 0; j < 4; ++j)
+ {
+ mln::point2d min(pmin.row()+sz_row*i,pmin.col()+sz_col*j);
+ mln::point2d max(pmin.row()+sz_row*(i+1),pmin.col()+sz_col*(j+1));
+ mln::box2d dom(min,max);
+
+ // Save it
+ t_image2d_int_u8 input_1o16_int_u8(dom);
+
+ mln::data::paste(input_int_u8 | dom, input_1o16_int_u8);
+
+ stddev = mln::math::max(stddev, stddev_color(input_1o16_int_u8));
+ }
+
+ return stddev;
+}
+
+
+/// \brief Main entry.
+///
+/// Just a front end for image processing routine. Use boost to go
+/// through the image database.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+ t_path full_path[] = {t_path(ANNOTATING_1_BILL_IMG_PATH),
+ t_path(ANNOTATING_1_FAX_IMG_PATH),
+ t_path(ANNOTATING_1_HANDWRITTEN_IMG_PATH),
+ t_path(ANNOTATING_1_LOGO_IMG_PATH),
+ t_path(ANNOTATING_1_MAP_IMG_PATH),
+ t_path(ANNOTATING_1_PHOTO_IMG_PATH),
+ t_path(ANNOTATING_1_SCREENSHOT_IMG_PATH),
+ t_path(ANNOTATING_1_SLIDE_IMG_PATH),
+ t_path(ANNOTATING_1_TYPED_IMG_PATH)};
+
+ for (int i = 0; i < 9; ++i)
+ {
+ std::cerr << "entering " << full_path[i] << std::endl;
+ std::cout << "entering " << full_path[i] << std::endl;
+
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ float count = 0;
+ float sum1 = 0;
+ float sum2 = 0;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ float val = stddev_color_16(dir_iter->path().string());
+
+ ++count;
+ sum1 += val;
+ sum2 += val*val;
+
+ std::cout << dir_iter->path().string() << " => " << val << std::endl;
+ }
+
+ float mean = sum1 / count;
+ float var = ((float)sum2 / count) - (mean * mean);
+
+ std::cout << "mean : " << mean << std::endl;
+ std::cout << "var : " << var << std::endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/exp/regional_maxima/Makefile.am b/scribo/sandbox/green/exp/annotating/value/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/exp/regional_maxima/Makefile.am
copy to scribo/sandbox/green/exp/annotating/value/Makefile.am
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-color.txt b/scribo/sandbox/green/exp/annotating/value/text-color.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-color.txt
copy to scribo/sandbox/green/exp/annotating/value/text-color.txt
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-img.txt b/scribo/sandbox/green/exp/annotating/value/text-img.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-img.txt
copy to scribo/sandbox/green/exp/annotating/value/text-img.txt
diff --git a/milena/sandbox/green/exp/annotating/achromastism/text-only.txt b/scribo/sandbox/green/exp/annotating/value/text-only.txt
similarity index 100%
copy from milena/sandbox/green/exp/annotating/achromastism/text-only.txt
copy to scribo/sandbox/green/exp/annotating/value/text-only.txt
diff --git a/scribo/sandbox/green/exp/annotating/value/value.cc b/scribo/sandbox/green/exp/annotating/value/value.cc
new file mode 100644
index 0000000..cade88b
--- /dev/null
+++ b/scribo/sandbox/green/exp/annotating/value/value.cc
@@ -0,0 +1,468 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Implement the Millet value operator [millet.phd.2008.pdf]
+///
+/// This is the Millet code for moving from RGB space to value
+/// one. Formulae are classical, we can find them on the web.
+///
+/// Val = max(R,G,B).
+/// Sat = (max(R,G,B) - min(R,G,B))/max(R,G,B).
+/// IF R = max(R,G,B) THEN Hue = 60 * [(V-B)/(max(R,G,B)-min(R,G,B))].
+/// IF G = max(R,G,B) THEN Hue = 60 * [2 + (B-R)/(max(R,G,B)-min(R,G,B))].
+/// IF B = max(R,G,B) THEN Hue = 60 * [4 + (R-G)/(max(R,G,B)-min(R,G,B))].
+#include <iostream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <mln/img_path.hh>
+
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/data/stretch.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/literal/colors.hh>
+#include <mln/literal/grays.hh>
+
+#include <mln/math/max.hh>
+#include <mln/math/min.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/geom/nsites.hh>
+
+#include <mln/fun/v2v/rgb_to_value_map.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/value/rgb8.hh>
+
+/// \brief Label the value.
+///
+/// \param[in] val the value in [0..255].
+///
+/// \return the reference color.
+///
+/// Segment the grey value in three classes.
+mln::value::rgb8 label_val(const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (82 > val)
+ result = mln::literal::black;
+ else if (179 > val)
+ result= mln::literal::medium_gray;
+ else
+ result = mln::literal::white;
+
+ return result;
+}
+
+
+/// \brief Label color with orange reference or brown reference.
+///
+/// \param[in] color the rgb8 color.
+/// \param[in] sat the HSV saturation.
+/// \param[in] val the HSV value.
+///
+/// \return the reference color with which it has been associated to.
+///
+/// Discriminate between orange and brown colors which are at the same
+/// position on the hue wheel.
+mln::value::rgb8 label_orange_or_brown(const mln::value::rgb8 color,
+ const mln::value::int_u8 sat,
+ const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (mln::literal::orange == color)
+ {
+ unsigned dist_orange = mln::math::abs(sat - 184)
+ + mln::math::abs(val - 65);
+
+ unsigned dist_brown = mln::math::abs(sat - 255)
+ + mln::math::abs(val - 125);
+
+ if (dist_orange < dist_brown)
+ result = mln::literal::orange;
+ else
+ result = mln::literal::brown;
+ }
+ else
+ result = color;
+
+ return result;
+}
+
+/// \brief Label between yellow and green color.
+///
+/// \param[in] color the rgb8 color.
+/// \param[in] val the HSV value.
+///
+/// \return the reference color associated to that color.
+///
+/// Segment between yellow and green because the discrimination is not
+/// so easy based on the hue wheel.
+mln::value::rgb8 label_yellow_or_green(const mln::value::rgb8 color,
+ const mln::value::int_u8 val)
+{
+ mln::value::rgb8 result;
+
+ if (mln::literal::yellow == color)
+ {
+ // Is it green or yellow ?
+ if (80 > val)
+ result = mln::literal::green;
+ else
+ result = mln::literal::yellow;
+ }
+ else
+ return color;
+
+ return result;
+}
+
+/// \brief Label hue color.
+///
+/// \param[in] hue the HSV hue canal for a pixel.
+///
+/// \return a hue segmentation of the hue wheel.
+///
+/// The old classification given by Millet is commented. Mine is ready
+/// to use. We need to change reference colors to make the primary
+/// colors, the secondary ones, etc...
+mln::value::rgb8 label_hue(const mln::value::int_u8 hue)
+{
+ mln::value::rgb8 result;
+
+ if (14 > hue)
+ result = mln::literal::red;
+ else if (29 > hue)
+ result = mln::literal::orange;
+ else if (45 > hue)
+ result = mln::literal::yellow;
+ else if (113 > hue)
+ result = mln::literal::green;
+ else if (149 > hue)
+ result = mln::literal::cyan;
+ else if (205 > hue)
+ result = mln::literal::blue;
+ else if (235 > hue)
+ result = mln::literal::violet;
+ else if (242 > hue)
+ result = mln::literal::pink;
+ else
+ result = mln::literal::red;
+
+ return result;
+}
+
+/// \brief Sum all the bins of the histogram.
+///
+/// \param[in] img the histogram based on image.
+///
+/// \return the sum of the overall bins.
+///
+/// Sum evry bins and return the result.
+template <typename I>
+unsigned count_histo(const mln::Image<I>& img_)
+{
+ const I& img = exact(img_);
+
+ mln_precondition(img.is_valid());
+
+ unsigned result = 0;
+
+ mln_piter(I) p(img.domain());
+
+ for_all(p)
+ result += img(p);
+
+ return result;
+}
+
+/// \brief Detect the peak of the histogram.
+///
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the position of the peak.
+///
+/// This is a typical accumulator use case but as it needs the
+/// position it couldn't be one of them. Look at the last maxima in
+/// the curve and return its position.
+template <typename I>
+unsigned peak_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the peak of the histogram
+ unsigned v_max = mln::opt::at(histo, 0);
+ short p_max = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ if (v_max < histo(p))
+ {
+ v_max = histo(p);
+ p_max = p.ind();
+ }
+ }
+
+ return p_max;
+}
+
+/// \brief Compute the average of the histogram.
+///
+/// \param[in] histo_ the image which represents the histogram.
+///
+/// \return the average of the histogram.
+///
+/// This code should be an accumulator. It computes the mean of the
+/// histogram, just stats in loop. Compute the sum, compute the
+/// ponderate sum and divide the second by the first.
+template <typename I>
+unsigned mean_histo(const mln::Image<I>& histo_)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Find the mean of the histogram
+ float sum = 0;
+ float mean = 0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ sum += histo(p);
+ mean += p.ind()*histo(p);
+ }
+
+ mean = mean / sum;
+
+ return mean;
+}
+
+/// \brief The R function of Millet
+///
+/// \param[in] p the position of the pic.
+/// \param[in] histo_p the histo value of the pic.
+/// \param[in] x the position of the element which we compute the contrib.
+/// \param[in] histo_x the histo value of that element.
+///
+/// \result the contribution of the element x.
+///
+/// This function compute the variance-like contribution of an element
+/// x linked to the pic of the histogram. In fact, every thing is like
+/// we compute a square distance-like between the element x and the
+/// pic in the normalized histogram. Notice that the normalized
+/// histogram is the histogram divide by the value of it's pic. So at
+/// the pic, the value equals 1. It's a current representation of the
+/// histogram in image processing, we can find it in gimp for exemple.
+float r(short p, unsigned histo_p, short x, unsigned histo_x)
+{
+ float result = mln::math::sqr(((float)histo_x / histo_p) * (x-p));
+
+ return result;
+}
+
+
+/// \brief The stddev3 is an internal stuff.
+///
+/// \param[in] histo_ the image which represents the histogram.
+/// \param[in] peak the position of the histogram peak.
+///
+/// \return simple computing of deviation.
+///
+/// This is an internal stuff. It splits the computing for easy
+/// reusing practice. Sum the R contribution.
+template <typename I>
+float stddev3(const mln::Image<I>& histo_, unsigned peak)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ // Compute stddev
+
+ float stddev = 0.0;
+
+ mln_piter(I) p(histo.domain());
+
+ for_all(p)
+ {
+ stddev += r((short)peak, mln::opt::at(histo,peak), p.ind(), histo(p));
+ }
+
+ return stddev;
+}
+
+
+/// Brief compute the whole deviation of Millet
+///
+/// \param[in] image the input image to analyze.
+/// \param[in] peak the peak of the histogram.
+/// \param[in] limit the threshold to compute the contribution.
+///
+/// \return the deviation.
+///
+/// The deviation uses the R function. It stats by finding the pic. If
+/// the pic is near the rigth border of the histo, compute the R
+/// function on the left neighbouring of the pic. If the pic is near
+/// the left border of the histo, compute the R function on the right
+/// neigbouring. Otherwise, compute the average of the right and left
+/// results. The selected neighbouring is composed of five pixels at
+/// the right or at the left of the pic. The detection of clipart
+/// assumes that the majority of the energy of the histogram is closed
+/// to the pic (five pixels around it). The test is generalized by
+/// making constants as parameters.
+template <typename I>
+float stddev2(const mln::Image<I>& histo_, unsigned peak, unsigned limit)
+{
+ const I& histo = exact(histo_);
+
+ mln_precondition(histo.is_valid());
+
+ float stddev_low = 0.0;
+ float stddev_up = 0.0;
+ float ret = 0.0;
+
+ // A transformer avec des iterators
+
+ if (250 > peak)
+ stddev_up = stddev3(histo |mln::box1d(mln::point1d(peak+1),
+ mln::point1d(peak+limit)), peak);
+
+ if (5 < peak)
+ stddev_low = stddev3(histo |mln::box1d(mln::point1d(peak-limit),
+ mln::point1d(peak-1)), peak);
+
+ ret = (250 < peak)? stddev_low : (5 > peak)? stddev_up :
+ (stddev_low + stddev_up)/2;
+
+ return ret;
+}
+
+
+/// \brief This is the main Millet test.
+///
+/// \param[in] input the name of the input image.
+/// \param[in] output the name of result histogram.
+/// \param[in] tmp the name of the output value (HSV) map.
+/// \param[in] threshold the range around the peak where R is computed.
+///
+/// \return the proportion of pixels that pass the test.
+float value_test(const std::string input,
+ const std::string output,
+ const std::string tmp,
+ const unsigned threshold)
+
+{
+ typedef mln::fun::v2v::rgb_to_value_map<8> t_rgb_to_value_map;
+
+ mln::image2d<mln::value::rgb8> input_rgb8;
+ mln::image2d<mln::value::int_u8> map;
+ mln::image1d<unsigned> histo;
+ unsigned cnt1;
+ unsigned cnt2;
+ float prop;
+ unsigned peak;
+
+ mln::io::ppm::load(input_rgb8, input.c_str());
+
+ map = mln::data::transform(input_rgb8, t_rgb_to_value_map());
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), map);
+ peak = peak_histo(histo); // mean_histo(histo);
+ prop = stddev2(histo, peak, threshold);
+// cnt1 = count_histo(histo | mln::box1d(mln::point1d(peak-threshold),
+// mln::point1d(peak+threshold)));
+// cnt2 = mln::geom::nsites(input_rgb8);
+// prop = ((100.0 * cnt1) / cnt2);
+
+ mln::io::plot::save_image_sh(histo, output.c_str());
+ mln::io::pgm::save(map, tmp.c_str());
+
+ return prop;
+}
+
+
+/// \brief The main entry.
+///
+/// This is the front end for using directories with boost. It calls
+/// the true image processing routine.
+int main()
+{
+ typedef boost::filesystem::path t_path;
+ typedef boost::filesystem::directory_iterator t_iter_path;
+
+ t_path full_path[] = {t_path(ICDAR_20P_PPM_IMG_PATH)};
+
+ for (int i = 0; i < 1; ++i)
+ {
+ std::cout << "entering " << full_path[i] << std::endl;
+
+ if (boost::filesystem::exists(full_path[i]) &&
+ boost::filesystem::is_directory(full_path[i]))
+ {
+ boost::filesystem::system_complete(full_path[i]);
+ const t_iter_path end_iter;
+ float prop = 0.0;
+
+ for (t_iter_path dir_iter(full_path[i]); end_iter != dir_iter; ++dir_iter)
+ {
+ // concatenation de chaine
+ t_path directory(ANNOTATING_RET_PATH);
+ t_path leaf = dir_iter->path().leaf();
+ t_path output = change_extension(directory / leaf, ".sh");
+ t_path tmp = change_extension(directory / leaf, ".pgm");
+
+ prop = value_test(dir_iter->path().string(),
+ output.string(),
+ tmp.string(),
+ 15);
+
+ std::cout << output << " : " << prop << std::endl;
+ std::cerr << output << " : " << prop << std::endl;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/mln/clustering/kmean2d.hh b/scribo/sandbox/green/mln/clustering/kmean2d.hh
index 51aaf49..4539083 100644
--- a/scribo/sandbox/green/mln/clustering/kmean2d.hh
+++ b/scribo/sandbox/green/mln/clustering/kmean2d.hh
@@ -150,7 +150,7 @@ namespace mln
{
/// Type definitions.
/// \brief A few type definitions to limit the refactoring impact.
- ///{
+ /// \{
typedef value::rgb<8> t_rgb;
typedef value::label<8> t_label;
typedef value::rg<n> t_value;
@@ -179,7 +179,7 @@ namespace mln
typedef util::array<t_mean_set> t_mean_cnv;
typedef image1d<t_result1d> t_variance_val;
typedef util::array<t_variance_val> t_variance_cnv;
- ///}
+ /// \}
/// \brief Constructor.
/// \param[in] point : the image as the population of pixels.
diff --git a/scribo/sandbox/green/mln/fun/p2b/achromatic.hh b/scribo/sandbox/green/mln/fun/p2b/achromatic.hh
index 1f45b2d..91a2dc5 100644
--- a/scribo/sandbox/green/mln/fun/p2b/achromatic.hh
+++ b/scribo/sandbox/green/mln/fun/p2b/achromatic.hh
@@ -44,15 +44,29 @@ namespace mln
namespace p2b
{
- /// \brief Functor that compare the i-th component of a value.
- // V is for the type of the value received
- // i is the ith component to select
+ /// \brief Functor that compare the i-th component with a threshold.
+ ///
+ /// T_rgb is the kind of RGB we use.
template <typename T_rgb>
struct achromatic : public Function_v2b< achromatic<T_rgb> >
{
typedef bool result;
+
+ /// \brief Operator that makes the threshold [millet.phd.2008.pdf]
+ ///
+ /// \param[in] p the selected site
+ ///
+ /// \return if the site is achromatic or not.
+ ///
+ /// This a try for opimized the call to the achromatic
+ /// routine. The goal is to decide if a site has got an
+ /// achromatic status or not. This is the true Millet test.
bool operator()(const point2d& p) const;
+ /// \brief Cstor of the object.
+ ///
+ /// \param[in] img the RGB input image.
+ /// \param[in] threshold the value to compare with.
achromatic(const image2d<T_rgb>& img, const float threshold);
const float threshold_;
diff --git a/scribo/sandbox/green/mln/fun/v2v/hue_concentration.hh b/scribo/sandbox/green/mln/fun/v2v/hue_concentration.hh
index 84d26c8..e776c9a 100644
--- a/scribo/sandbox/green/mln/fun/v2v/hue_concentration.hh
+++ b/scribo/sandbox/green/mln/fun/v2v/hue_concentration.hh
@@ -32,6 +32,10 @@
# include <mln/value/hsv.hh>
# include <mln/value/rgb8.hh>
+/// \file
+///
+/// This is the code for building hue_concentration_map.
+
namespace mln
{
@@ -41,12 +45,18 @@ namespace mln
namespace v2v
{
+ /// \brief internal method for detecting the histogram peak.
+ ///
+ /// \param[in] hue_histo the histogram of hue.
+ ///
+ /// \return the seed of the peek.
unsigned peak_histo(const mln::image1d<unsigned>& hue_histo);
struct hue_concentration : public Function_v2v< hue_concentration >
{
typedef float result;
+ /// \brief Gibe the distance map between actual hue and the peak.
float operator()(const float hue) const;
hue_concentration(const mln::image1d<unsigned>& hue_histo)
diff --git a/scribo/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh
index 6de63ec..126f9bd 100644
--- a/scribo/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh
+++ b/scribo/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh
@@ -49,6 +49,11 @@ namespace mln
/// \brief Convert rgb value to achromatism map.
///
+ /// Convert rgb value to binary achromastism map using the
+ /// rebuilded Millet phd formulae [millet.phd.2008.pdf]. The
+ /// idea is to look at the minimum and maximum of the channels
+ /// and to return the difference.
+ ///
/// \ingroup modfunv2v
template <unsigned n>
diff --git a/scribo/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh
index 3dd8eb0..a191095 100644
--- a/scribo/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh
+++ b/scribo/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh
@@ -34,6 +34,11 @@
#include <mln/value/hsv.hh>
#include <mln/value/rgb.hh>
+/// \fiie
+///
+/// This is the millet [millet.phd.2008.pdf] transformation from RGB
+/// space to HSV space.
+
namespace mln
{
@@ -57,7 +62,15 @@ namespace mln
typedef T_hsv result;
- /// HSV implementation from millet.2008.phd.pdf p67
+ /// \brief HSV implementation from millet.2008.phd.pdf p67
+ ///
+ /// \param[in] rgb the input rgb pixel.
+ ///
+ /// \return a HSV pixel.
+ ///
+ /// This is the Millet implementation of its transformation
+ /// operator to go from RGB space to HSV space. When pixels
+ /// are achromatic, hue equals -1.
template <typename T_rgb>
T_hsv operator()(const T_rgb& rgb) const;
--
1.5.6.5
Implement the first version with vectors and matrices.
* mln/clustering/k_mean.hh: New library component.
* use/clustering/k_mean: New directory.
* use/clustering/k_mean/Makefile.am: New makefile.
* use/clustering/k_mean/k_mean.cc: New source file.
* tests/clustering/k_mean: New directory.
* tests/clustering/k_mean/Makefile.am: New makefile.
* tests/clustering/k_mean/k_mean.cc: New source file.
Implement the second version with image and working in 1d.
* mln/clustering/kmean1d.hh: New library component.
* use/clustering/kmean1d: New directory.
* use/clustering/kmean1d/Makefile.am: New makefile.
* use/clustering/kmean1d/kmean1d.cc: New source file.
* demo/clustering/kmean1d: New directory.
* demo/clustering/kmean1d/Makefile.am: New makefile.
* demo/clustering/kmean1d/kmean1d.cc: New source file.
Implement transformation between RG space and RGB space.
* mln/fun/v2v/rg_to_rgb.hh: New library component.
* use/fun/v2v/rg_to_rgb: New directory.
* use/fun/v2v/rg_to_rgb/Makefile.am: New makefile.
* use/fun/v2v/rg_to_rgb/rg_to_rgb.cc: New source file.
Implement the third version working in 2d (r/g).
* mln/clustering/kmean2d.hh: New library component.
* use/clustering/kmean2d: New directory.
* use/clustering/kmean2d/Makefile.am: New makefile.
* use/clustering/kmean2d/kmean2d.cc: New source file.
* demo/clustering/kmean2d: New directory.
* demo/clustering/kmean2d/Makefile.am: New makefile.
* demo/clustering/kmean2d/kmean2d.cc: New source file.
Implement the fourth version working in 3d (rgb).
* mln/clustering/kmean3d.hh: New library component.
* use/clustering/kmean3d: New directory.
* use/clustering/kmean3d/Makefile.am: New makefile.
* use/clustering/kmean3d/kmean3d.cc: New source file.
* demo/clustering/kmean3d: New directory.
* demo/clustering/kmean3d/Makefile.am: New makefile.
* demo/clustering/kmean3d/kmean3d.cc: New source file.
Implement the fith version as a function (working in rgb space).
* mln/clustering/kmean_rgb.hh: New library component.
* use/clustering/kmean_rgb: New directory.
* use/clustering/kmean_rgb/Makefile.am: New makefile.
* use/clustering/kmean_rgb/kmean_rgb.cc: New source file.
* demo/clustering/kmean_rgb: New directory.
* demo/clustering/kmean_rgb/Makefile.am: New makefile.
* demo/clustering/kmean_rgb/kmean_rgb.cc: New source file.
Benchmark distance algorithm for the kmean algorithm.
* bench/clustering/distance: New directory.
* bench/clustering/distance/Makefile.am: New makefile.
* bench/clustering/distance/distance.cc: New source file.
---
scribo/sandbox/green/ChangeLog | 77 ++
scribo/sandbox/green/README.green | 150 ++++-
.../green/bench/clustering/distance/Makefile.am | 153 ++++
.../green/bench/clustering/distance/distance.cc | 842 ++++++++++++++++++++
.../green/demo/clustering/kmean1d/Makefile.am | 153 ++++
.../green/demo/clustering/kmean1d/kmean1d.cc | 258 ++++++
.../green/demo/clustering/kmean2d/Makefile.am | 153 ++++
.../green/demo/clustering/kmean2d/kmean2d.cc | 278 +++++++
.../green/demo/clustering/kmean3d/Makefile.am | 153 ++++
.../green/demo/clustering/kmean3d/kmean3d.cc | 265 ++++++
.../green/demo/clustering/kmean_rgb/Makefile.am | 153 ++++
.../green/demo/clustering/kmean_rgb/kmean_rgb.cc | 239 ++++++
scribo/sandbox/green/mln/clustering/k_mean.hh | 365 ++++++---
scribo/sandbox/green/mln/clustering/kmean1d.hh | 194 ++---
scribo/sandbox/green/mln/clustering/kmean2d.hh | 329 ++++----
scribo/sandbox/green/mln/clustering/kmean3d.hh | 246 +++---
scribo/sandbox/green/mln/clustering/kmean_rgb.hh | 87 ++-
scribo/sandbox/green/mln/fun/v2v/rg_to_rgb.hh | 59 ++-
.../green/tests/clustering/k_mean/Makefile.am | 13 +-
.../green/tests/clustering/k_mean/k_mean.cc | 395 ++++++----
.../stat/histo1d => clustering/k_mean}/Makefile.am | 0
.../sandbox/green/use/clustering/k_mean/k_mean.cc | 55 ++
.../histo1d => clustering/kmean1d}/Makefile.am | 0
.../green/use/clustering/kmean1d/kmean1d.cc | 50 ++
.../histo1d => clustering/kmean2d}/Makefile.am | 0
.../green/use/clustering/kmean2d/kmean2d.cc | 61 ++
.../histo1d => clustering/kmean3d}/Makefile.am | 0
.../green/use/clustering/kmean3d/kmean3d.cc | 63 ++
.../histo1d => clustering/kmean_rgb}/Makefile.am | 0
.../green/use/clustering/kmean_rgb/kmean_rgb.cc | 63 ++
.../stat/histo1d => fun/v2v/rg_to_rgb}/Makefile.am | 0
.../green/use/fun/v2v/rg_to_rgb/rg_to_rgb.cc | 68 ++
32 files changed, 4224 insertions(+), 698 deletions(-)
create mode 100644 scribo/sandbox/green/bench/clustering/distance/Makefile.am
create mode 100644 scribo/sandbox/green/bench/clustering/distance/distance.cc
create mode 100644 scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
create mode 100644 scribo/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
create mode 100644 scribo/sandbox/green/demo/clustering/kmean2d/Makefile.am
create mode 100644 scribo/sandbox/green/demo/clustering/kmean2d/kmean2d.cc
create mode 100644 scribo/sandbox/green/demo/clustering/kmean3d/Makefile.am
create mode 100644 scribo/sandbox/green/demo/clustering/kmean3d/kmean3d.cc
create mode 100644 scribo/sandbox/green/demo/clustering/kmean_rgb/Makefile.am
create mode 100644 scribo/sandbox/green/demo/clustering/kmean_rgb/kmean_rgb.cc
copy scribo/sandbox/green/use/{accu/stat/histo1d => clustering/k_mean}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/use/clustering/k_mean/k_mean.cc
copy scribo/sandbox/green/use/{accu/stat/histo1d => clustering/kmean1d}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/use/clustering/kmean1d/kmean1d.cc
copy scribo/sandbox/green/use/{accu/stat/histo1d => clustering/kmean2d}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/use/clustering/kmean2d/kmean2d.cc
copy scribo/sandbox/green/use/{accu/stat/histo1d => clustering/kmean3d}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/use/clustering/kmean3d/kmean3d.cc
copy scribo/sandbox/green/use/{accu/stat/histo1d => clustering/kmean_rgb}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/use/clustering/kmean_rgb/kmean_rgb.cc
copy scribo/sandbox/green/use/{accu/stat/histo1d => fun/v2v/rg_to_rgb}/Makefile.am (100%)
create mode 100644 scribo/sandbox/green/use/fun/v2v/rg_to_rgb/rg_to_rgb.cc
diff --git a/scribo/sandbox/green/ChangeLog b/scribo/sandbox/green/ChangeLog
index 7bb6646..4ddaa54 100644
--- a/scribo/sandbox/green/ChangeLog
+++ b/scribo/sandbox/green/ChangeLog
@@ -1,3 +1,80 @@
+2010-06-28 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Implement the kmean algorithh and start to optimize it.
+
+ Implement the first version with vectors and matrices.
+
+ * mln/clustering/k_mean.hh: New library component.
+
+ * use/clustering/k_mean: New directory.
+ * use/clustering/k_mean/Makefile.am: New makefile.
+ * use/clustering/k_mean/k_mean.cc: New source file.
+
+ * tests/clustering/k_mean: New directory.
+ * tests/clustering/k_mean/Makefile.am: New makefile.
+ * tests/clustering/k_mean/k_mean.cc: New source file.
+
+ Implement the second version with image and working in 1d.
+
+ * mln/clustering/kmean1d.hh: New library component.
+
+ * use/clustering/kmean1d: New directory.
+ * use/clustering/kmean1d/Makefile.am: New makefile.
+ * use/clustering/kmean1d/kmean1d.cc: New source file.
+
+ * demo/clustering/kmean1d: New directory.
+ * demo/clustering/kmean1d/Makefile.am: New makefile.
+ * demo/clustering/kmean1d/kmean1d.cc: New source file.
+
+ Implement transformation between RG space and RGB space.
+
+ * mln/fun/v2v/rg_to_rgb.hh: New library component.
+ * use/fun/v2v/rg_to_rgb: New directory.
+ * use/fun/v2v/rg_to_rgb/Makefile.am: New makefile.
+ * use/fun/v2v/rg_to_rgb/rg_to_rgb.cc: New source file.
+
+ Implement the third version working in 2d (r/g).
+
+ * mln/clustering/kmean2d.hh: New library component.
+
+ * use/clustering/kmean2d: New directory.
+ * use/clustering/kmean2d/Makefile.am: New makefile.
+ * use/clustering/kmean2d/kmean2d.cc: New source file.
+
+ * demo/clustering/kmean2d: New directory.
+ * demo/clustering/kmean2d/Makefile.am: New makefile.
+ * demo/clustering/kmean2d/kmean2d.cc: New source file.
+
+ Implement the fourth version working in 3d (rgb).
+
+ * mln/clustering/kmean3d.hh: New library component.
+
+ * use/clustering/kmean3d: New directory.
+ * use/clustering/kmean3d/Makefile.am: New makefile.
+ * use/clustering/kmean3d/kmean3d.cc: New source file.
+
+ * demo/clustering/kmean3d: New directory.
+ * demo/clustering/kmean3d/Makefile.am: New makefile.
+ * demo/clustering/kmean3d/kmean3d.cc: New source file.
+
+ Implement the fith version as a function (working in rgb space).
+
+ * mln/clustering/kmean_rgb.hh: New library component.
+
+ * use/clustering/kmean_rgb: New directory.
+ * use/clustering/kmean_rgb/Makefile.am: New makefile.
+ * use/clustering/kmean_rgb/kmean_rgb.cc: New source file.
+
+ * demo/clustering/kmean_rgb: New directory.
+ * demo/clustering/kmean_rgb/Makefile.am: New makefile.
+ * demo/clustering/kmean_rgb/kmean_rgb.cc: New source file.
+
+ Benchmark distance algorithm for the kmean algorithm.
+
+ * bench/clustering/distance: New directory.
+ * bench/clustering/distance/Makefile.am: New makefile.
+ * bench/clustering/distance/distance.cc: New source file.
+
2010-06-24 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
Define documentation files.
diff --git a/scribo/sandbox/green/README.green b/scribo/sandbox/green/README.green
index 3f3c9a9..02d8654 100644
--- a/scribo/sandbox/green/README.green
+++ b/scribo/sandbox/green/README.green
@@ -33,8 +33,7 @@ n'y a rien à copier. Rendons-nous dans le répertoire de compilation et lançon
le makefile.
#:~/git/olena/scribo/sandbox/green/demo/annotating/hsv$
-cd ../../../build/demo/annotating/hsv
-
+#:cd ../../../build/demo/annotating/hsv
#:~/git/olena/scribo/sandbox/green/build/demo/annotating/hsv$ make clean all
L'exécutable est généré par le makefile, il porte le nom du
@@ -168,6 +167,14 @@ de comptage puisqu'il est décrit sous la forme de triplets de float
contient une séquence d'appels pour les routines permettant de
considérer la dimension de la teinte comme circulaire.
+Après réflexion, le code des histogrammes et tous les accumulateurs
+qui en découlent devraient être rangés dans l'espace de nommage
+mln::accu::histo. Cela permettrait de ne pas parasiter mln::accu::stat
+avec tous les éléments propres aux histogrammes et de ne pas faire un
+espace de nommage à rallonge en introduisant histo dans stat. Donc
+mln::accu::stat semble être une bonne postion pour le rangement final
+du code relatif aux histogrammes.
+
a) version 1d
@@ -198,7 +205,6 @@ c) version 3d RGB
* use/accu/stat/histo3_rgb: Code minimal utilisant un histogramme 3d RGB.
-
d) version 3d HSL
* mln/accu/stat/histo3d_hsl.hh: Accumulateur histogramme image3d HSL.
@@ -245,23 +251,145 @@ IX KMEANS
Ce travail m'avait été demandé par théo. Je le laisse inachevé, quelque part
perdu pendant l'optimisation du code et sa transformation en canevas.
+
+a) Première implémentation avec matrices et vecteurs
+
+Cette version est bien documentée et permet de mieux comprendre les autres
+versions. Par ailleurs, elle n'est pas spécialement optimisée ce qui fait
+qu'elle colle davantage au modèle de l'algorithme kmean traditionnel.
+
* mln/clustering/k_mean.hh: Première implémentation avec matrices et vecteurs.
+* use/clustering/k_mean: Code minimal utilisant cette première implémentation.
+* tests/clustering/k_mean: Tests unitaires sur la permière version.
+
+
+b) Seconde implémentation avec image en 1d
+
+Cette seconde version intègre une optimisation testée par théo il y a
+longtemps. Je me demande si ce n'étais pas pendant sa thèse qu'il
+avait travaillé sur cette version. Bref, dans la mesure où
+l'optimisation passe par la création d'un histogramme, cette version
+devient dépendante des histogrammes réalisés plutôt (il est aussi
+dépendant de la sauvegarde au format gnuplot shell). L'idée générale
+de l'optimisation est de ne plus raisonner sur l'image, mais sur
+l'histogramme. Car à un moment donné, la classification ne tient
+compte que de la valeur du pixel en intensité (pas de ses coordonnées
+dans l'image). Donc tout pixel de même intensité sera classé de
+manière identique. D'où l'intérêt de travailler avec les
+histogrammes. Les limites de cette optimisation se trouvent dans la
+taille des histogrammes. L'optimisation marche à merveille pour de
+faibles quantifications (8 bits c'est parfait). Par contre, lorsque
+l'on passe à un histogramme couleur, la taille de l'histogramme
+devient problématique et peut dépasser la taille de l'image. Cette
+optimisation n'a alors plus aucun sens.
+
* mln/clustering/kmean1d.hh: Implémentation 1d avec des images.
+* use/clustering/kmean1d : Code minimal utilisant cette seconde implémentation.
+* demo/clustering/kmean1d : Demonstrateur.
+
+La visualisation de la convergence des moyennes, générée par le
+démonstrateur, n'est pas très lisible. La lecture textuelle du fichier
+gnuplot shell (mean_cnv.sh) permet d'interpréter ce qui se passe, par
+contre le graphique est à refaire.
+
+
+c) kmean2d
+
+Cette troisième version est identique à la seconde, sauf qu'elle
+permet de faire la classification dans un espace à deux
+dimensions. Malheureusement, un tel travail dans cet espace coûte
+beaucoup plus cher à l'exécution.
+
+* mln/fun/v2v/rg_to_rgb.hh: Transformation de l'espace RG vers l'espace RGB.
+* use/fun/v2v/rg_to_rgb: Exemple de code pour l'utilisation de rg_to_rgb.
+
* mln/clustering/kmean2d.hh: Implémentation 2d avec des images.
-* mln/clustering/kmean3d.hh: Implémentation 3d avec des images.
-* mln/clustering/kmean_rgb.hh: Impl. 3d aplatie et en cours de mise en canevas.
+* use/clustering/kmean2d : Code minimal utilisant cette seconde implémentation.
+* demo/clustering/kmean2d : Demonstrateur.
-* tests/clustering/k_mean: Tests unitaires sur la permière version.
-* tests/clustering/kmean1d: Tests unitaire sur la version 1d.
+La visualisation de la convergence des moyennes est cette fois-ci
+complètement aboutie. Le fichier semble avoir quelques soucis, il
+manque des lignes dans le splot initial, en remettre pour qu'il y en
+ait autant que les blocs de données. L'espace des couleurs étant le
+bicanal r/g, on peut visualiser sur une troisième dimension
+l'évolution des centres dans l'espace initial. L'effet est très réussi
+et aussi très parlant. Chaque run, correspond alors à une trajectoire
+particulière. L'affichage des variations des variances a été rénové et
+est lui aussi beaucoup plus lisible.
+
+
+d) kmean3d
+
+Cette quatrième version est la copie conforme de la version
+précédente. Les problèmes de visualisation sur les fichiés générés
+sont les mêmes. L'affichage des convergences est identique. Le recours
+à une dégradation de l'image d'entrée est impérative pour avoir des
+temps encore acceptables.
-* demo/clustering/kmean1d: Utilisation de la version 1d.
-* demo/clustering/kmean2d: Utilisation de la version 2d.
-* demo/clustering/kmean3d: Utilisation de la version 3d.
+* mln/clustering/kmean3d.hh: Implémentation 3d avec des images.
+* use/clustering/kmean3d : Code minimal utilisant cette quatrième impl.
+* demo/clustering/kmean3d : Demonstrateur.
+
+
+e) kmean aplati
+
+Cette cinquième version est très spéciale. Elle doit permettre de
+gagner du temps d'exécution. Le concept est simple au départ, tout
+écrire d'un seul tenant. L'exercice est fastidieux et difficile
+(intellectuellement). Une fois fait, il faut réfléchir à ce qui peut
+être mis sous forme de canevas. Par exemple, la manière de calculer
+les distances peut être une information paramétrable. Cela pemettrait
+de faire un benchmark in situ. La transcription actuelle compile. Elle
+n'intègre pas tous les outils de debuggage que nous pouvions avoir sur
+les autres versions. Par ailleurs, comme le code est réuni en une
+seule fonction, nous avons pour l'instant une seule sortie, l'image de
+labels de la classification réalisée. A partir de cette image, nous
+pouvons en reconstruire d'autres. Il manque quand même la possibilité
+d'observer les convergences. Le travail était en cours, à prendre donc
+avec beaucoup de pincettes. La dernière exécution house.ppm, 3
+centres, 10 itérations et 10 runs fonctionne parfaitement sur les
+premiers runs puis l'affichage s'emballe sans que l'on y comprenne
+rien. Un dump dans un fichier révèle le non appariement de certaines
+traces (entering/exiting). Une piste à suivre est la sortie anticipée
+d'une de mes boucles sans pour autant fermer une trace ... ???
+
+* mln/clustering/kmean_rgb.hh: Implémentation 3d avec des images.
+* use/clustering/kmean_rgb : Code minimal utilisant cette quatrième impl.
* demo/clustering/kmean_rgb: Utilisation de la version aplatie.
+
+f) optimisation possible
+
+Le calcul des distances entre les points et les différents centres
+peut être réalisé par des transformées. Certes, les distances ne seront
+pas les mêmes que la distance euclidienne, mais elles s'en approchent
+et cela constitue très certainement une très bonne approximation pour
+l'objectif que nous cherchons à atteindre. Le but de ce benchmark est
+de regarder quel type de transformation est le plus rapide pour
+arriver à nos fins en fonction des données d'entrée. Cette
+optimisation n'a pas encore été intégrée dans le code, et reste une
+piste à exploiter.
+
* bench/clustering/distance: Comparaison algorithmes d'évaluation des distances.
-==> to do
+Une routine du benchmark ne compile plus. Il semble qu'il y ait un
+mauvais appel à la fonction at_ dans la routine
+influence_zone_geodesic.hh ligne 127. Le but du benchmark est de
+tester les distances en 2d et 3d pour des voisinages différents (c04,
+c08, c06, c18, c26) sur les routines distance euclidienne classique,
+zone d'influence geodesique et zone d'influence "front". La première
+serie de test vise à garder une taille d' image constante et
+d'augmenter le nombre de centres pour voir comment se comporte les
+algorithmes et la seconde serie, vise à garder un nombre constant de
+centres et à agrandir progressivement l'image. Attention, le benchmark
+essaye d'être assez exhaustif et donc se paye par un temps d'execution
+assez long. Les différents fichiers générés reprennent les différents
+tests effectués et montrent l'évolution du temps de calcul suivant la
+progression du paramètre observé (taille de l'image ou nombre de
+centres).
+
+==> to do : le changelog + commit + give it to scribo-z branch
+
X REGIONAL MAXIMA
-----------------
diff --git a/scribo/sandbox/green/bench/clustering/distance/Makefile.am b/scribo/sandbox/green/bench/clustering/distance/Makefile.am
new file mode 100644
index 0000000..ca5e187
--- /dev/null
+++ b/scribo/sandbox/green/bench/clustering/distance/Makefile.am
@@ -0,0 +1,153 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+#CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/bench
+BUILD__PATTERN= green/build/bench
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/scribo/sandbox/green/bench/clustering/distance/distance.cc b/scribo/sandbox/green/bench/clustering/distance/distance.cc
new file mode 100644
index 0000000..4daea44
--- /dev/null
+++ b/scribo/sandbox/green/bench/clustering/distance/distance.cc
@@ -0,0 +1,842 @@
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#include <mln/core/alias/box3d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/alias/point3d.hh>
+#include <mln/core/alias/w_window2d_int.hh>
+#include <mln/core/alias/w_window3d_int.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/routine/initialize.hh>
+
+#include <mln/data/fill.hh>
+
+#include <mln/io/pgm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/literal/zero.hh>
+
+#include <mln/make/w_window2d_int.hh>
+#include <mln/make/w_window3d_int.hh>
+
+#include <mln/opt/at.hh>
+
+#include <mln/transform/influence_zone_geodesic.hh>
+#include <mln/transform/influence_zone_front.hh>
+
+#include <mln/util/array.hh>
+#include <mln/util/timer.hh>
+
+#include <mln/value/label_8.hh>
+
+
+/// Build inputs, build seeds, count distance.
+/// \{
+/// \brief Build 2d/3d input image and 2d/3d seed image.
+///
+/// Building seeds means making a rectangular grid over a virtual image with
+/// a specific size and collects together in a array each node of this grid.
+/// In the context of the kmean algorithm, seeds are equavalent to centers.
+/// Building input means creating a label image and associates to each seed
+/// a unique label id.
+/// Distance are square euclidian distance in 2d and in 3d.
+mln::image2d<mln::value::label_8> build_input2d(unsigned nb_seed, unsigned size)
+{
+ typedef mln::value::label_8 t_lbl;
+ mln::image2d<t_lbl> input(mln::box2d(mln::point2d(0,0),
+ mln::point2d(size,size)));
+
+ mln::data::fill(input, mln::literal::zero);
+
+ unsigned top = size / nb_seed;
+ unsigned lbl = 0;
+
+ for (unsigned i = top/2; i < size; i += top)
+ for (unsigned j = top/2; j < size; j += top)
+ input(mln::point2d(i,j)) = ++lbl;
+
+ //mln::io::pgm::save(input, "input.pgm");
+
+ return input;
+}
+
+mln::image3d<mln::value::label_8> build_input3d(unsigned nb_seed, unsigned size)
+{
+ typedef mln::value::label_8 t_lbl;
+ mln::image3d<t_lbl> input(mln::box3d(mln::point3d(0,0,0),
+ mln::point3d(size,size,size)));
+
+ mln::data::fill(input, mln::literal::zero);
+
+ unsigned top = size / nb_seed;
+ unsigned lbl = 0;
+
+ for (unsigned i = top/2; i < size; i += top)
+ for (unsigned j = top/2; j < size; j += top)
+ for (unsigned k = top/2; k < size; k += top)
+ input(mln::point3d(k,i,j)) = ++lbl;
+
+ //mln::io::pgm::save(input, "input.pgm");
+
+ return input;
+}
+
+mln::util::array<mln::point3d> build_seed3d(unsigned nb_seed, unsigned size)
+{
+ mln::util::array<mln::point3d> result;
+ unsigned top = size / nb_seed;
+
+ for (unsigned i = top/2; i < size; i += top)
+ for (unsigned j = top/2; j < size; j += top)
+ for (unsigned k = top/2; k < size; k += top)
+ result.append(mln::point3d(k,i,j));
+
+ // std::cout << result << std::endl;
+
+ return result;
+}
+
+mln::util::array<mln::point2d> build_seed2d(unsigned nb_seed, unsigned size)
+{
+ mln::util::array<mln::point2d> result;
+ unsigned top = size / nb_seed;
+
+ for (unsigned i = top/2; i < size; i += top)
+ for (unsigned j = top/2; j < size; j += top)
+ result.append(mln::point2d(j,i));
+
+ // std::cout << result << std::endl;
+
+ return result;
+}
+
+unsigned distance(mln::point3d p1, mln::point3d p2)
+{
+ unsigned row2 = (p1.row() - p2.row())*(p1.row() - p2.row());
+ unsigned col2 = (p1.col() - p2.col())*(p1.col() - p2.col());
+ unsigned sli2 = (p1.sli() - p2.sli())*(p1.sli() - p2.sli());
+ unsigned res = row2 + col2 + sli2;
+
+ return res;
+}
+
+unsigned distance(mln::point2d p1, mln::point2d p2)
+{
+ unsigned row2 = (p1.row() - p2.row())*(p1.row() - p2.row());
+ unsigned col2 = (p1.col() - p2.col())*(p1.col() - p2.col());
+ unsigned res = row2 + col2;
+
+ return res;
+}
+/// \}
+
+/// Benchmark geodesic distance.
+/// \{
+/// \brief The geodesic material for the benchmark process.
+///
+/// This part of the file contains all we need to benchmarck the
+/// geodesic distance. First of all, we have the calling functions
+/// that encapsulate the real call to geodesic routine. They bring us
+/// a clean place where starting and stopping the timer without any
+/// other code interference. Printing results could be done at this step.
+/// At least, we have the test routine that call the previous functions
+/// by passing arguments like different size of inputs and different
+/// neighbouring. The test routines save their results in gnuplot script shell
+/// file that enable to show charts.
+void influence_zone_geodesic_2d(mln::util::timer& timer,
+ const mln::image2d<mln::value::label_8>& input,
+ const mln::neighb2d & neighb)
+{
+ mln::image2d<mln::value::label_8> output;
+
+ timer.start();
+ output = mln::transform::influence_zone_geodesic(input, neighb);
+ timer.stop();
+
+ //mln::io::pgm::save(output, "output.pgm");
+}
+
+/// \fixme influence_zone_geodesic_3d doesn't compile!
+void influence_zone_geodesic_3d(mln::util::timer& timer,
+ const mln::image3d<mln::value::label_8>& input,
+ const mln::neighb3d & neighb)
+{
+ mln::image3d<mln::value::label_8> output;
+
+ timer.start();
+ // FIXME : Problem with the influence_zone_geodesic in 3d (bad call to at_).
+ // output = mln::transform::influence_zone_geodesic(input, neighb);
+ timer.stop();
+
+ //mln::io::pgm::save(output, "output.pgm");
+}
+
+
+int test_influence_zone_geodesic_2d()
+{
+ mln::util::timer timer;
+
+// Test the label c4
+ mln::image1d<float> chart_seed_c04(16*16+2);
+
+ mln::data::fill(chart_seed_c04, mln::literal::zero);
+
+ for (unsigned i = 1; i < 16+1; ++i)
+ {
+ influence_zone_geodesic_2d(timer,build_input2d(i,256),mln::c4());
+ std::cout << "c04|256x256|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c04, i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c04, "geodesic.c04.2d.seed.sh");
+
+ // Test the label c8
+ mln::image1d<float> chart_seed_c08(16*16+2);
+
+ mln::data::fill(chart_seed_c08, mln::literal::zero);
+
+ for (unsigned i = 1; i < 16+1; ++i)
+ {
+ influence_zone_geodesic_2d(timer,build_input2d(i,256),mln::c8());
+ std::cout << "c08|256x256|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c08, i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c08, "geodesic.c08.2d.seed.sh");
+
+ // Test the size of the image
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c04(256+1);
+
+ mln::data::fill(chart_size_c04, mln::literal::zero);
+
+ for (unsigned i = 16; i < 256+1; ++i)
+ {
+ influence_zone_geodesic_2d(timer, build_input2d(4,i),mln::c4());
+ std::cout << "c04|" << i << "x" << i << "|16 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c04, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c04, "geodesic.c04.2d.size.sh");
+
+ // Test the size of the image
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c08(256+1);
+
+ mln::data::fill(chart_size_c08, mln::literal::zero);
+
+ for (unsigned i = 16; i < 256+1; ++i)
+ {
+ influence_zone_geodesic_2d(timer, build_input2d(4,i),mln::c8());
+ std::cout << "c08|" << i << "x" << i << "|16 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c08, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c08, "geodesic.c08.2d.size.sh");
+
+
+ return 0;
+}
+
+
+void test_influence_zone_geodesic_3d()
+{
+ mln::util::timer timer;
+
+ // Test the number of labels c06
+ mln::image1d<float> chart_seed_c06(5*5*5+2);
+
+ mln::data::fill(chart_seed_c06, mln::literal::zero);
+
+ for (unsigned i = 1; i < 5+1; ++i)
+ {
+ influence_zone_geodesic_3d(timer, build_input3d(i,128), mln::c6());
+ std::cout << "c06|128x128x128|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c06, i*i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c06, "geodesic.c06.3d.seed.sh");
+
+ // Test the number of labels c18
+ mln::image1d<float> chart_seed_c18(5*5*5+2);
+
+ mln::data::fill(chart_seed_c18, mln::literal::zero);
+
+ for (unsigned i = 1; i < 5+1; ++i)
+ {
+ influence_zone_geodesic_3d(timer, build_input3d(i,128), mln::c18());
+ std::cout << "c18|128x128x128|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c18, i*i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c18, "geodesic.c18.3d.seed.sh");
+
+ // Test the number of labels c26
+ mln::image1d<float> chart_seed_c26(5*5*5+2);
+
+ mln::data::fill(chart_seed_c26, mln::literal::zero);
+
+ for (unsigned i = 1; i < 5+1; ++i)
+ {
+ influence_zone_geodesic_3d(timer, build_input3d(i,128), mln::c26());
+ std::cout << "c26|128x128x128|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c26, i*i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c26, "geodesic.c26.3d.seed.sh");
+
+ // Test the size of the image c06
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c06(128+1);
+
+ mln::data::fill(chart_size_c06, mln::literal::zero);
+
+ for (unsigned i = 6; i < 128+1; ++i)
+ {
+ influence_zone_geodesic_3d(timer, build_input3d(2,i), mln::c6());
+ std::cout << "c06|" << i << "x" << i << "x" << i << "|8 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c06, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c06, "geodesic.c06.3d.size.sh");
+
+ // Test the size of the image c18
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c18(128+1);
+
+ mln::data::fill(chart_size_c18, mln::literal::zero);
+
+ for (unsigned i = 6; i < 128+1; ++i)
+ {
+ influence_zone_geodesic_3d(timer, build_input3d(2,i), mln::c18());
+ std::cout << "c18|" << i << "x" << i << "x" << i << "|8 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c18, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c18, "geodesic.c18.3d.size.sh");
+
+ // Test the size of the image c26
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c26(128+1);
+
+ mln::data::fill(chart_size_c26, mln::literal::zero);
+
+ for (unsigned i = 6; i < 128+1; ++i)
+ {
+ influence_zone_geodesic_3d(timer, build_input3d(2,i), mln::c26());
+ std::cout << "c26|" << i << "x" << i << "x" << i << "|8 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c26, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c26, "geodesic.c26.3d.size.sh");
+}
+/// \}
+
+/// Benchmark front distance.
+/// \{
+/// \brief The front material for the benchmark process.
+///
+/// This part of the file contains all we need to benchmarck the
+/// front distance. First of all, we have the calling functions
+/// that encapsulate the real call to geodesic routine. They bring us
+/// a clean place where starting and stopping the timer without any
+/// other code interference. Printing results could be done at this step.
+/// At least, we have the test routine that call the previous functions
+/// by passing arguments like different size of inputs and different
+/// neighbouring. The test routines save their results in gnuplot script shell
+/// file that enable to show charts.
+void influence_zone_front_2d(mln::util::timer& timer,
+ const mln::image2d<mln::value::label_8>& input,
+ const mln::neighb2d& neighb,
+ const mln::w_window2d_int& w2d)
+{
+ mln::image2d<mln::value::label_8> output;
+
+ timer.start();
+ output = mln::transform::influence_zone_front(input, neighb, w2d);
+ timer.stop();
+
+ //mln::io::pgm::save(output, "output.pgm");
+}
+
+
+void influence_zone_front_3d(mln::util::timer& timer,
+ const mln::image3d<mln::value::label_8>& input,
+ const mln::neighb3d& neighb,
+ const mln::w_window3d_int& w3d)
+{
+ mln::image3d<mln::value::label_8> output;
+
+ timer.start();
+ output = mln::transform::influence_zone_front(input, neighb, w3d);
+ timer.stop();
+
+ //mln::io::pgm::save(output, "output.pgm");
+}
+
+
+void test_influence_zone_front_3d()
+{
+ mln::util::timer timer;
+
+ int ws_c06[] = {
+ // Internal slice
+ 0, 0, 0,
+ 0, 2, 0,
+ 0, 0, 0,
+ // Middle slice
+ 0, 2, 0,
+ 2, 0, 2,
+ 0, 2, 0,
+ // External slice
+ 0, 0, 0,
+ 0, 2, 0,
+ 0, 0, 0 };
+
+ int ws_c18[] = {
+ // Internal slice
+ 0, 6, 0,
+ 6, 4, 6,
+ 0, 6, 0,
+ // Middle slice
+ 6, 4, 6,
+ 4, 0, 4,
+ 6, 4, 6,
+ // External slice
+ 0, 6, 0,
+ 6, 4, 6,
+ 0, 6, 0 };
+
+ int ws_c26[] = {
+ // Internal slice
+ 7, 6, 7,
+ 6, 4, 6,
+ 7, 6, 7,
+ // Middle slice
+ 6, 4, 6,
+ 4, 0, 4,
+ 6, 4, 6,
+ // External slice
+ 7, 6, 7,
+ 6, 4, 6,
+ 7, 6, 7 };
+
+ mln::w_window3d_int w3d_c06 = mln::make::w_window3d_int(ws_c06);
+ mln::w_window3d_int w3d_c18 = mln::make::w_window3d_int(ws_c18);
+ mln::w_window3d_int w3d_c26 = mln::make::w_window3d_int(ws_c26);
+
+ // Test the number of labels c06
+ mln::image1d<float> chart_seed_c06(5*5*5+2);
+
+ mln::data::fill(chart_seed_c06, mln::literal::zero);
+
+ for (unsigned i = 1; i < 5+1; ++i)
+ {
+ influence_zone_front_3d(timer, build_input3d(i,128), mln::c6(), w3d_c06);
+ std::cout << "c06|128x128x128|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c06, i*i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c06, "front.c06.3d.seed.sh");
+
+ // Test the number of labels c18
+ mln::image1d<float> chart_seed_c18(5*5*5+2);
+
+ mln::data::fill(chart_seed_c18, mln::literal::zero);
+
+ for (unsigned i = 1; i < 5+1; ++i)
+ {
+ influence_zone_front_3d(timer, build_input3d(i,128), mln::c18(), w3d_c18);
+ std::cout << "c18|128x128x128|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c18, i*i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c18, "front.c18.3d.seed.sh");
+
+ // Test the number of labels c26
+ mln::image1d<float> chart_seed_c26(5*5*5+2);
+
+ mln::data::fill(chart_seed_c26, mln::literal::zero);
+
+ for (unsigned i = 1; i < 5+1; ++i)
+ {
+ influence_zone_front_3d(timer, build_input3d(i,128), mln::c26(), w3d_c26);
+ std::cout << "c26|128x128x128|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c26, i*i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c26, "front.c26.3d.seed.sh");
+
+ // Test the size of the image c06
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c06(128+1);
+
+ mln::data::fill(chart_size_c06, mln::literal::zero);
+
+ for (unsigned i = 6; i < 128+1; ++i)
+ {
+ influence_zone_front_3d(timer, build_input3d(2,i), mln::c6(), w3d_c06);
+ std::cout << "c06|" << i << "x" << i << "x" << i << "|8 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c06, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c06, "front.c06.3d.size.sh");
+
+ // Test the size of the image c18
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c18(128+1);
+
+ mln::data::fill(chart_size_c18, mln::literal::zero);
+
+ for (unsigned i = 6; i < 128+1; ++i)
+ {
+ influence_zone_front_3d(timer, build_input3d(2,i), mln::c18(), w3d_c18);
+ std::cout << "c18|" << i << "x" << i << "x" << i << "|8 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c18, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c18, "front.c18.3d.size.sh");
+
+ // Test the size of the image c26
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c26(128+1);
+
+ mln::data::fill(chart_size_c26, mln::literal::zero);
+
+ for (unsigned i = 6; i < 128+1; ++i)
+ {
+ influence_zone_front_3d(timer, build_input3d(2,i), mln::c26(), w3d_c26);
+ std::cout << "c26|" << i << "x" << i << "x" << i << "|8 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c26, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c26, "front.c26.3d.size.sh");
+}
+
+void test_influence_zone_front_2d()
+{
+ mln::util::timer timer;
+
+ int ws_c04[] = {
+ 0, 2, 0,
+ 2, 0, 2,
+ 0, 2, 0};
+
+ int ws_c08[] = {
+ 6, 4, 6,
+ 4, 0, 4,
+ 6, 4, 6};
+
+ mln::w_window2d_int w2d_c04 = mln::make::w_window2d_int(ws_c04);
+ mln::w_window2d_int w2d_c08 = mln::make::w_window2d_int(ws_c08);
+
+ // Test the label c4
+ mln::image1d<float> chart_seed_c04(16*16+2);
+
+ mln::data::fill(chart_seed_c04, mln::literal::zero);
+
+ for (unsigned i = 1; i < 16+1; ++i)
+ {
+ influence_zone_front_2d(timer,build_input2d(i,256),mln::c4(),w2d_c04);
+ std::cout << "c04|256x256|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c04, i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c04, "front.c04.2d.seed.sh");
+
+ // Test the label c8
+ mln::image1d<float> chart_seed_c08(16*16+2);
+
+ mln::data::fill(chart_seed_c08, mln::literal::zero);
+
+ for (unsigned i = 1; i < 16+1; ++i)
+ {
+ influence_zone_front_2d(timer,build_input2d(i,256),mln::c8(),w2d_c08);
+ std::cout << "c08|256x256|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed_c08, i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed_c08, "front.c08.2d.seed.sh");
+
+ // Test the size of the image
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c04(256+1);
+
+ mln::data::fill(chart_size_c04, mln::literal::zero);
+
+ for (unsigned i = 16; i < 256+1; ++i)
+ {
+ influence_zone_front_2d(timer, build_input2d(4,i),mln::c4(),w2d_c04);
+ std::cout << "c04|" << i << "x" << i << "|16 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c04, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c04, "front.c04.2d.size.sh");
+
+ // Test the size of the image
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size_c08(256+1);
+
+ mln::data::fill(chart_size_c08, mln::literal::zero);
+
+ for (unsigned i = 16; i < 256+1; ++i)
+ {
+ influence_zone_front_2d(timer, build_input2d(4,i),mln::c8(),w2d_c08);
+ std::cout << "c08|" << i << "x" << i << "|16 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size_c08, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size_c08, "front.c08.2d.size.sh");
+}
+/// \}
+
+
+
+/// Benchmark euclidian distance.
+/// \{
+/// \brief The euclidian material for the benchmark process.
+///
+/// This part of the file contains all we need to benchmarck the
+/// euclidian distance. First of all, we have the calling functions
+/// that encapsulate the real call to geodesic routine. They bring us
+/// a clean place where starting and stopping the timer without any
+/// other code interference. Printing results could be done at this step.
+/// At least, we have the test routine that call the previous functions
+/// by passing arguments like different size of inputs and different
+/// neighbouring. The test routines save their results in gnuplot script shell
+/// file that enable to show charts.
+void influence_zone_euclidian_2d(mln::util::timer& timer,
+ const mln::image2d<mln::value::label_8>& input,
+ const mln::util::array<mln::point2d>& seed)
+{
+ mln::image2d<mln::value::label_8> output;
+
+ timer.start();
+
+ mln::initialize(output, input);
+
+ mln_piter_(mln::image2d<mln::value::label_8>) p(output.domain());
+ mln_eiter_(mln::util::array<mln::point2d>) e(seed);
+
+ for_all(p)
+ {
+ unsigned d = 0;
+ unsigned min_d = mln_max(unsigned);
+ unsigned min_l = 0;
+
+ for_all(e)
+ {
+ d = distance(p, seed(e.index_()));
+
+ if (min_d > d)
+ {
+ min_d = d;
+ min_l = input(e);
+ }
+ }
+
+ output(p) = min_l;
+ }
+
+ timer.stop();
+
+ //mln::io::pgm::save(output, "output.pgm");
+}
+
+
+void influence_zone_euclidian_3d(mln::util::timer& timer,
+ const mln::image3d<mln::value::label_8>& input,
+ const mln::util::array<mln::point3d>& seed)
+{
+ mln::image3d<mln::value::label_8> output;
+
+ timer.start();
+
+ mln::initialize(output, input);
+
+ mln_piter_(mln::image3d<mln::value::label_8>) p(output.domain());
+ mln_eiter_(mln::util::array<mln::point3d>) e(seed);
+
+ for_all(p)
+ {
+ unsigned d = 0;
+ unsigned min_d = mln_max(unsigned);
+ unsigned min_l = 0;
+
+ for_all(e)
+ {
+ d = distance(p, seed(e.index_()));
+
+ if (min_d > d)
+ {
+ min_d = d;
+ min_l = input(e);
+ }
+ }
+
+ output(p) = min_l;
+ }
+
+ timer.stop();
+}
+
+void test_influence_zone_euclidian_2d()
+{
+ mln::util::timer timer;
+/*
+ // Global test
+ mln::image2d<float> chart(mln::box2d(mln::point2d(0,0),
+ mln::point2d(16*16+2,256+1)));
+
+ mln::data::fill(chart, mln::literal::zero);
+
+ for (unsigned i = 1; i < 256+1; ++i) // size
+ for (unsigned j = 1; j < i*i && j < 16+1; ++j) // seed
+ {
+ influence_zone_euclidian_2d(timer,build_input2d(j,i),build_seed2d(j,i));
+ std::cout << "xxx|" << i << "x" << i << "|" << j << " = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart, j*j,i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart, "chart.sh");
+*/
+
+ // Test the number of labels
+ mln::image1d<float> chart_seed(16*16+2);
+
+ mln::data::fill(chart_seed, mln::literal::zero);
+
+ for (unsigned i = 1; i < 16+1; ++i)
+ {
+ influence_zone_euclidian_2d(timer,build_input2d(i,256),build_seed2d(i,256));
+ std::cout << "xxx|256x256|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed, i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed, "euclidian.2d.seed.sh");
+
+ // Test the size of the image
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size(256+1);
+
+ mln::data::fill(chart_size, mln::literal::zero);
+
+ for (unsigned i = 16; i < 256+1; ++i)
+ {
+ influence_zone_euclidian_2d(timer, build_input2d(4,i), build_seed2d(4,i));
+ std::cout << "xxx|" << i << "x" << i << "|16 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size, "euclidian.2d.size.sh");
+}
+
+void test_influence_zone_euclidian_3d()
+{
+ mln::util::timer timer;
+
+ // Test the number of labels
+ mln::image1d<float> chart_seed(5*5*5+2);
+
+ mln::data::fill(chart_seed, mln::literal::zero);
+
+ for (unsigned i = 1; i < 5+1; ++i)
+ {
+ influence_zone_euclidian_3d(timer,build_input3d(i,128),build_seed3d(i,128));
+ std::cout << "xxx|128x128x128|" << i << " = " << timer.read() << std::endl;
+ mln::opt::at(chart_seed, i*i*i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_seed, "euclidian.3d.seed.sh");
+
+ // Test the size of the image
+ // 1, 2, 4, 8, 16, 32, 64, 128, 256
+ mln::image1d<float> chart_size(128+1);
+
+ mln::data::fill(chart_size, mln::literal::zero);
+
+ for (unsigned i = 6; i < 128+1; ++i)
+ {
+ influence_zone_euclidian_3d(timer, build_input3d(2,i), build_seed3d(2,i));
+ std::cout << "xxx|" << i << "x" << i << "x" << i << "|8 = "
+ << timer.read() << std::endl;
+ mln::opt::at(chart_size, i) = timer.read();
+ }
+
+ mln::io::plot::save_image_sh(chart_size, "euclidian.3d.size.sh");
+}
+/// \}
+
+//------------------------------------------------------------------------------
+// Main
+//
+// Point de fonctionnement du système [image de taille entre 1 et 256]
+// Moins de 16 labels
+//
+//------------------------------------------------------------------------------
+
+/// \brief The main routine that call all the benchmark tests.
+///
+/// This benchmark aim at comparing different kind of distance. It
+/// looks after the influence geodesic, the influence front and
+/// euclidian distance. Many files are generated. Some rules exist to
+/// build the name of the file:
+/// distance.neighbouring.dimension.(size|seed). The distance could be
+/// the front distance (front), the geodesic distance (geodesic) or
+/// the euclidian distance (euclidian). The neighbouring could be c04
+/// or c08 in 2d, c06, c18 or c26 in 3d. The dimension could be 2d or 3d.
+/// Finally, the flag size or seed precises the nature of that test, increasing
+/// gradualy the size of the image or increasing gradualy the number of seeds.
+/// The file contains the time benchmark of the distance studied.
+///
+/// \fixme test_influence_zone_geodesic_3d doesn't compile.
+int main()
+{
+ test_influence_zone_euclidian_2d();
+ test_influence_zone_front_2d();
+ test_influence_zone_geodesic_2d();
+
+ // FIXME : It doesn't compile because of a bad calling function at_ in
+ // FIXME : the influence_zone_geodesic.hh line 127.
+ // test_influence_zone_geodesic_3d();
+ test_influence_zone_front_3d();
+ test_influence_zone_euclidian_3d();
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
new file mode 100644
index 0000000..4455a07
--- /dev/null
+++ b/scribo/sandbox/green/demo/clustering/kmean1d/Makefile.am
@@ -0,0 +1,153 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/demo
+BUILD__PATTERN= green/build/demo
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/scribo/sandbox/green/demo/clustering/kmean1d/kmean1d.cc b/scribo/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
new file mode 100644
index 0000000..22eae91
--- /dev/null
+++ b/scribo/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
@@ -0,0 +1,258 @@
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief This is a demonstrator for kmean1d.
+///
+/// The demonstrator produces five kind of results. The file
+/// "color.ppm" allow us to localize the different center in the
+/// image. There is an equivalent file "label.pgm" that's do the same
+/// thing but inplace of a specific color, it gives the label of each
+/// center. It's quit easy with xv, to transform the label image in
+/// the color one. The file "mean.pgm" replaces each label by the mean
+/// of the points that contributate to their center. It is a kind of
+/// abstraction of the reality of the image, of its complexity. In
+/// file "variance_cnv.sh" abscissa axis stands for the convergence
+/// evolution and the ordinate axis for each runs. The "mean_cnv.sh"
+/// file shows the evolution of the centers, whatever the run. The
+/// x-axis represents the id of the center, the y-axis the iteration
+/// in the convergence process and the z-axis the id of the particular
+/// run. The graphic is very bad, but textual interpretation is still
+/// available.
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/img_path.hh>
+
+#include <mln/clustering/kmean1d.hh>
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/value/int_u8.hh>
+
+
+/// \brief The real code for launching the kmean optimised algorithm.
+///
+/// \param[in] image : the 8 bits greylevel image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// This is the real lauching code. In fact, the stuff consists in loading the
+/// image, setting the parameters, calling the routine, extracting the results
+/// and saving them for the user.
+///
+/// \fixme The result is not safe because we don't test kmean.is_valid()
+
+void do_demo(const std::string& image,
+ const unsigned k_center,
+ const unsigned n_times,
+ const unsigned watch_dog)
+{
+ typedef mln::clustering::kmean1d<double,8> t_kmean;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+
+ t_image2d_int_u8 img;
+
+ mln::io::pgm::load(img, image.c_str());
+
+ t_kmean kmean(img,
+ k_center,
+ watch_dog,
+ n_times);
+
+ //mln::trace::quiet = false;
+
+ kmean.launch_n_times();
+
+ // FIXME : Not safe because we don't test kmean.is_valid()
+
+ t_kmean::t_color_dbg color_img = kmean.get_color_dbg();
+ t_kmean::t_mean_dbg mean_img = kmean.get_mean_dbg();
+ t_kmean::t_label_dbg label_img = kmean.get_label_dbg();
+ t_kmean::t_variance_cnv var_cnv = kmean.get_variance_cnv();
+ t_kmean::t_mean_cnv mean_cnv = kmean.get_mean_cnv();
+
+ mln::io::pgm::save(mean_img, "mean.pgm");
+ mln::io::ppm::save(color_img, "color.ppm");
+ mln::io::pgm::save(label_img, "label.pgm");
+
+ mln::io::plot::save_image_sh(mean_cnv, "mean_cnv.sh");
+ mln::io::plot::save_image_sh(var_cnv, "variance_cnv.sh");
+}
+
+
+/// \brief Front hand for the demonstrator.
+///
+/// \param[in] image : the 8 bits greylevel image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// The front hand enables the setting of the default values for the
+/// parameters. it allows us to print the real parameter set used by
+/// the demonstrator.
+void demo(const std::string& image = OLENA_IMG_PATH"/house.pgm",
+ const unsigned k_center = 3,
+ const unsigned n_times = 10,
+ const unsigned watch_dog = 10)
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "Launching the demo with these parameters" << std::endl;
+ std::cout << "image : " << image << std::endl;
+ std::cout << "k_center : " << k_center << std::endl;
+ std::cout << "n_times : " << n_times << std::endl;
+ std::cout << "watch_dog : " << watch_dog << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+
+ do_demo(image, k_center, n_times, watch_dog);
+}
+
+
+/// \brief Convert character get in the input stream to unsigned integer.
+///
+/// \param[in] status : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+/// \param[out] val : the converted value to output.
+///
+/// \return a flag that tell us if every thing is ok, if the result can be used.
+bool char_to_unsigned(const bool status, const char *arg, unsigned& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ result = !arg_stream.fail();
+ }
+
+ return result;
+}
+
+
+/// \brief Convert character get in the input stream to string.
+///
+/// \param[in] status : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+/// \param[out] val : the converted value to output.
+///
+/// \return a flag that tell us if every thing is ok, if the result can be used.
+bool char_to_string(const bool status, const char *arg, std::string& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ return !arg_stream.fail();
+ }
+
+ return result;
+}
+
+
+/// \brief Print usage recommandation for this binary.
+///
+/// \param[in] argc : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+void usage(const int argc, const char *args[])
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "argc : " << argc << std::endl;
+
+ for (int i = 0; i < argc; ++i)
+ std::cout << "args[" << i << "] : " << args[i] << std::endl;
+
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "usage: kmean1d [image [k_center [n_times [watch_dog]]]]"
+ << std::endl;
+ std::cout << "pbm image (points to work with)" << std::endl;
+ std::cout << "unsigned k_center (number of centers)" << std::endl;
+ std::cout << "unsigned n_times (number of launching)" << std::endl;
+ std::cout << "unsigned watch_dog (convergence loop)" << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+}
+
+
+/// \brief The main routine launchs the kmean optimised algoritm.
+///
+/// \param[in] image : the 8 bits greylevel image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// All the parameters are optional, but we must respect strictly a
+/// specific order. In fact, we can launch five programs with some
+/// default parameters: demo(), demo(image), demo(image,k_center),
+/// demo(image,k_center,n_times) and
+/// demo(image,k_center,n_times,watch_dog).
+int main(const int argc, const char *args[])
+{
+ std::string image("top");
+ unsigned k_center;
+ unsigned watch_dog;
+ unsigned n_times;
+ bool status = true;
+
+ switch (argc)
+ {
+ case 5: status = char_to_unsigned(status, args[4], watch_dog);
+ case 4: status = char_to_unsigned(status, args[3], n_times);
+ case 3: status = char_to_unsigned(status, args[2], k_center);
+ case 2: status = char_to_string(status, args[1], image); break;
+ case 1: status = true; break;
+ default: status = false;
+ }
+
+ if (status)
+ {
+ switch (argc)
+ {
+ case 1: demo(); break;
+ case 2: demo(image); break;
+ case 3: demo(image, k_center); break;
+ case 4: demo(image, k_center, n_times); break;
+ case 5: demo(image, k_center, n_times, watch_dog); break;
+ }
+ }
+ else
+ usage(argc, args);
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean2d/Makefile.am b/scribo/sandbox/green/demo/clustering/kmean2d/Makefile.am
new file mode 100644
index 0000000..4455a07
--- /dev/null
+++ b/scribo/sandbox/green/demo/clustering/kmean2d/Makefile.am
@@ -0,0 +1,153 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/demo
+BUILD__PATTERN= green/build/demo
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/scribo/sandbox/green/demo/clustering/kmean2d/kmean2d.cc b/scribo/sandbox/green/demo/clustering/kmean2d/kmean2d.cc
new file mode 100644
index 0000000..2538dce
--- /dev/null
+++ b/scribo/sandbox/green/demo/clustering/kmean2d/kmean2d.cc
@@ -0,0 +1,278 @@
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief This is a demonstrator for kmean2d.
+///
+/// The demonstrator produces five kind of results. The file
+/// "color.ppm" allow us to localize the different center in the
+/// image. There is an equivalent file "label.pgm" that's do the same
+/// thing but inplace of a specific color, it gives the label of each
+/// center. It's quit easy with xv, to transform the label image in
+/// the color one. The file "mean.pgm" replaces each label by the mean
+/// of the points that contributate to their center. It is a kind of
+/// abstraction of the reality of the image, of its complexity. The
+/// "variance_cnv.sh" changes its representation and becomes more
+/// readable. The "mean_cnv.sh" have got a generation problem. We can
+/// bypass it by adding printing lines in the 'splot'
+/// instruction. However, the graphic is correct and mainly shows the
+/// convergence of the center value. Finally, as the work takes place in
+/// the r/g space, the "point.ppm" file shows us the exact input space.
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/img_path.hh>
+
+#include <mln/clustering/kmean2d.hh>
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb_to_rg.hh>
+#include <mln/fun/v2v/rg_to_rgb.hh>
+
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/rg.hh>
+#include <mln/value/rgb8.hh>
+
+
+/// \brief The real code for launching the kmean optimised algorithm.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// This is the real lauching code. In fact, the stuff consists in loading the
+/// image, setting the parameters, calling the routine, extracting the results
+/// and saving them for the user.
+///
+/// \fixme The result is not safe because we don't test kmean.is_valid()
+void do_demo(const std::string& image,
+ const unsigned k_center,
+ const unsigned n_times,
+ const unsigned watch_dog)
+{
+ typedef mln::clustering::kmean2d<double,8> t_kmean;
+ typedef mln::value::rg<8> t_rg8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rg8> t_image2d_rg8;
+ typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+ typedef mln::fun::v2v::rg_to_rgb<8> t_rg_to_rgb;
+
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rgb8 point_img_rgb8;
+ t_image2d_rgb8 mean_img_rgb8;
+ t_image2d_rgb8 mean_dbg_rgb8;
+ t_image2d_rg8 img_rg8;
+
+ // Read input.
+ mln::io::ppm::load(img_rgb8, image.c_str());
+ img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+
+ // Call kmean.
+ t_kmean kmean(img_rg8, k_center, watch_dog, n_times);
+
+ mln::trace::quiet = false;
+ kmean.launch_n_times();
+
+ // FIXME : Not safe because we don't test kmean.is_valid()
+
+ // Get outputs.
+ t_kmean::t_point_img point_img = kmean.get_point();
+ t_kmean::t_color_dbg color_img = kmean.get_color_dbg();
+ t_kmean::t_mean_dbg mean_img = kmean.get_mean_dbg();
+ t_kmean::t_label_dbg label_img = kmean.get_label_dbg();
+ t_kmean::t_variance_cnv variance_cnv = kmean.get_variance_cnv();
+ t_kmean::t_mean_cnv mean_cnv = kmean.get_mean_cnv();
+
+ // Convert outputs.
+ point_img_rgb8 = mln::data::transform(point_img, t_rg_to_rgb());
+ mean_img_rgb8 = mln::data::transform(mean_img, t_rg_to_rgb());
+
+ mln::io::ppm::save(mean_img_rgb8, "mean.ppm");
+ mln::io::ppm::save(color_img, "color.ppm");
+ mln::io::pgm::save(label_img, "label.pgm");
+ mln::io::ppm::save(point_img_rgb8, "point.ppm");
+
+ mln::io::plot::save_image_sh(mean_cnv, "mean_cnv.sh");
+ mln::io::plot::save_image_sh(variance_cnv, "variance_cnv.sh");
+}
+
+
+/// \brief Front hand for the demonstrator.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// The front hand enables the setting of the default values for the
+/// parameters. it allows us to print the real parameter set used by
+/// the demonstrator.
+void demo(const std::string& image = OLENA_IMG_PATH"/house.ppm",
+ const unsigned k_center = 3,
+ const unsigned n_times = 10,
+ const unsigned watch_dog = 10)
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "Launching the demo with these parameters" << std::endl;
+ std::cout << "image : " << image << std::endl;
+ std::cout << "k_center : " << k_center << std::endl;
+ std::cout << "n_times : " << n_times << std::endl;
+ std::cout << "watch_dog : " << watch_dog << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+
+ do_demo(image, k_center, n_times, watch_dog);
+}
+
+
+/// \brief Convert character get in the input stream to unsigned integer.
+///
+/// \param[in] status : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+/// \param[out] val : the converted value to output.
+///
+/// \return a flag that tell us if every thing is ok, if the result can be used.
+bool char_to_unsigned(const bool status, const char *arg, unsigned& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ result = !arg_stream.fail();
+ }
+
+ return result;
+}
+
+
+/// \brief Convert character get in the input stream to string.
+///
+/// \param[in] status : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+/// \param[out] val : the converted value to output.
+///
+/// \return a flag that tell us if every thing is ok, if the result can be used.
+bool char_to_string(const bool status, const char *arg, std::string& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ return !arg_stream.fail();
+ }
+
+ return result;
+}
+
+
+/// \brief Print usage recommandation for this binary.
+///
+/// \param[in] argc : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+void usage(const int argc, const char *args[])
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "argc : " << argc << std::endl;
+
+ for (int i = 0; i < argc; ++i)
+ std::cout << "args[" << i << "] : " << args[i] << std::endl;
+
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "usage: kmean2d [image [k_center [n_times [watch_dog]]]]"
+ << std::endl;
+ std::cout << "ppm image (points to work with)" << std::endl;
+ std::cout << "unsigned k_center (number of centers)" << std::endl;
+ std::cout << "unsigned n_times (number of launching)" << std::endl;
+ std::cout << "unsigned watch_dog (convergence loop)" << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+}
+
+
+/// \brief The main routine launchs the kmean optimised algoritm.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// All the parameters are optional, but we must respect strictly a
+/// specific order. In fact, we can launch five programs with some
+/// default parameters: demo(), demo(image), demo(image,k_center),
+/// demo(image,k_center,n_times) and
+/// demo(image,k_center,n_times,watch_dog).
+int main(const int argc, const char *args[])
+{
+ std::string image("top");
+ unsigned k_center;
+ unsigned watch_dog;
+ unsigned n_times;
+ bool status = true;
+
+ switch (argc)
+ {
+ case 5: status = char_to_unsigned(status, args[4], watch_dog);
+ case 4: status = char_to_unsigned(status, args[3], n_times);
+ case 3: status = char_to_unsigned(status, args[2], k_center);
+ case 2: status = char_to_string(status, args[1], image); break;
+ case 1: status = true; break;
+ default: status = false;
+ }
+
+ if (status)
+ {
+ switch (argc)
+ {
+ case 1: demo(); break;
+ case 2: demo(image); break;
+ case 3: demo(image, k_center); break;
+ case 4: demo(image, k_center, n_times); break;
+ case 5: demo(image, k_center, n_times, watch_dog); break;
+ }
+ }
+ else
+ usage(argc, args);
+
+ return 0;
+}
+
diff --git a/scribo/sandbox/green/demo/clustering/kmean3d/Makefile.am b/scribo/sandbox/green/demo/clustering/kmean3d/Makefile.am
new file mode 100644
index 0000000..4455a07
--- /dev/null
+++ b/scribo/sandbox/green/demo/clustering/kmean3d/Makefile.am
@@ -0,0 +1,153 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/demo
+BUILD__PATTERN= green/build/demo
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/scribo/sandbox/green/demo/clustering/kmean3d/kmean3d.cc b/scribo/sandbox/green/demo/clustering/kmean3d/kmean3d.cc
new file mode 100644
index 0000000..0e2b16e
--- /dev/null
+++ b/scribo/sandbox/green/demo/clustering/kmean3d/kmean3d.cc
@@ -0,0 +1,265 @@
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief This is a demonstrator for kmean3d.
+///
+/// The demonstrator produces five kind of results. The file
+/// "color.ppm" allow us to localize the different center in the
+/// image. There is an equivalent file "label.pgm" that's do the same
+/// thing but inplace of a specific color, it gives the label of each
+/// center. It's quit easy with xv, to transform the label image in
+/// the color one. The file "mean.pgm" replaces each label by the mean
+/// of the points that contributate to their center. It is a kind of
+/// abstraction of the reality of the image, of its complexity. The
+/// "variance_cnv.sh" changes its representation and becomes more
+/// readable. The "mean_cnv.sh" have got a generation problem. We can
+/// bypass it by adding printing lines in the 'splot'
+/// instruction. However, the graphic is correct and mainly shows the
+/// convergence of the center value.
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/clustering/kmean3d.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb8.hh>
+
+
+/// \brief The real code for launching the kmean optimised algorithm.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// This is the real lauching code. In fact, the stuff consists in loading the
+/// image, setting the parameters, calling the routine, extracting the results
+/// and saving them for the user.
+///
+/// \fixme The result is not safe because we don't test kmean.is_valid()
+void do_demo(const std::string& image,
+ const unsigned k_center,
+ const unsigned n_times,
+ const unsigned watch_dog)
+{
+ typedef mln::clustering::kmean3d<double,5> t_kmean;
+ typedef mln::value::label_8 t_label_8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<5> t_rgb5;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgb5> t_image2d_rgb5;
+
+ t_image2d_rgb8 house_rgb8;
+ t_image2d_rgb5 house_rgb5;
+
+ mln::io::ppm::load(house_rgb8, image.c_str());
+ house_rgb5=mln::data::transform(house_rgb8,mln::fun::v2v::rgb8_to_rgbn<5>());
+
+ t_kmean kmean(house_rgb5, k_center, watch_dog, n_times);
+
+ mln::trace::quiet = false;
+
+ kmean.launch_n_times();
+
+ // FIXME : Not safe because we don't test kmean.is_valid()
+
+ t_kmean::t_color_dbg color_img = kmean.get_color_dbg();
+ t_kmean::t_mean_dbg mean_img = kmean.get_mean_dbg();
+ t_kmean::t_label_dbg label_img = kmean.get_label_dbg();
+ t_kmean::t_variance_cnv variance_cnv = kmean.get_variance_cnv();
+ t_kmean::t_mean_cnv mean_cnv = kmean.get_mean_cnv();
+
+ mln::io::ppm::save(mean_img, "mean.ppm");
+ mln::io::ppm::save(color_img, "color.ppm");
+ mln::io::pgm::save(label_img, "label.pgm");
+
+ mln::io::plot::save_image_sh(mean_img, "mean.sh");
+ mln::io::plot::save_image_sh(mean_cnv, "mean_cnv.sh");
+ mln::io::plot::save_image_sh(variance_cnv, "variance_cnv.sh");
+}
+
+/// \brief Front hand for the demonstrator.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// The front hand enables the setting of the default values for the
+/// parameters. it allows us to print the real parameter set used by
+/// the demonstrator.
+void demo(const std::string& image = OLENA_IMG_PATH"/house.ppm",
+ const unsigned k_center = 3,
+ const unsigned n_times = 10,
+ const unsigned watch_dog = 10)
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "Launching the demo with these parameters" << std::endl;
+ std::cout << "image : " << image << std::endl;
+ std::cout << "k_center : " << k_center << std::endl;
+ std::cout << "n_times : " << n_times << std::endl;
+ std::cout << "watch_dog : " << watch_dog << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+
+ do_demo(image, k_center, n_times, watch_dog);
+}
+
+
+/// \brief Convert character get in the input stream to unsigned integer.
+///
+/// \param[in] status : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+/// \param[out] val : the converted value to output.
+///
+/// \return a flag that tell us if every thing is ok, if the result can be used.
+bool char_to_unsigned(const bool status, const char *arg, unsigned& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ result = !arg_stream.fail();
+ }
+
+ return result;
+}
+
+
+/// \brief Convert character get in the input stream to string.
+///
+/// \param[in] status : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+/// \param[out] val : the converted value to output.
+///
+/// \return a flag that tell us if every thing is ok, if the result can be used.
+bool char_to_string(const bool status, const char *arg, std::string& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ return !arg_stream.fail();
+ }
+
+ return result;
+}
+
+
+/// \brief Print usage recommandation for this binary.
+///
+/// \param[in] argc : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+void usage(const int argc, const char *args[])
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "argc : " << argc << std::endl;
+
+ for (int i = 0; i < argc; ++i)
+ std::cout << "args[" << i << "] : " << args[i] << std::endl;
+
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "usage: kmean1d [image [k_center [n_times [watch_dog]]]]"
+ << std::endl;
+ std::cout << "pbm image (points to work with)" << std::endl;
+ std::cout << "unsigned k_center (number of centers)" << std::endl;
+ std::cout << "unsigned n_times (number of launching)" << std::endl;
+ std::cout << "unsigned watch_dog (convergence loop)" << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+}
+
+
+/// \brief The main routine launchs the kmean optimised algoritm.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// All the parameters are optional, but we must respect strictly a
+/// specific order. In fact, we can launch five programs with some
+/// default parameters: demo(), demo(image), demo(image,k_center),
+/// demo(image,k_center,n_times) and
+/// demo(image,k_center,n_times,watch_dog).
+int main(const int argc, const char *args[])
+{
+ std::string image("top");
+ unsigned k_center;
+ unsigned watch_dog;
+ unsigned n_times;
+ bool status = true;
+
+ switch (argc)
+ {
+ case 5: status = char_to_unsigned(status, args[4], watch_dog);
+ case 4: status = char_to_unsigned(status, args[3], n_times);
+ case 3: status = char_to_unsigned(status, args[2], k_center);
+ case 2: status = char_to_string(status, args[1], image); break;
+ case 1: status = true; break;
+ default: status = false;
+ }
+
+ if (status)
+ {
+ switch (argc)
+ {
+ case 1: demo(); break;
+ case 2: demo(image); break;
+ case 3: demo(image, k_center); break;
+ case 4: demo(image, k_center, n_times); break;
+ case 5: demo(image, k_center, n_times, watch_dog); break;
+ }
+ }
+ else
+ usage(argc, args);
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/demo/clustering/kmean_rgb/Makefile.am b/scribo/sandbox/green/demo/clustering/kmean_rgb/Makefile.am
new file mode 100644
index 0000000..4455a07
--- /dev/null
+++ b/scribo/sandbox/green/demo/clustering/kmean_rgb/Makefile.am
@@ -0,0 +1,153 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/demo
+BUILD__PATTERN= green/build/demo
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/scribo/sandbox/green/demo/clustering/kmean_rgb/kmean_rgb.cc b/scribo/sandbox/green/demo/clustering/kmean_rgb/kmean_rgb.cc
new file mode 100644
index 0000000..d02c497
--- /dev/null
+++ b/scribo/sandbox/green/demo/clustering/kmean_rgb/kmean_rgb.cc
@@ -0,0 +1,239 @@
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief This is a demonstrator for kmean_rgb.
+///
+/// The code is provided as is. It is an alpha version, so very very
+/// experimental. Take care !!
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/clustering/kmean_rgb.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb8.hh>
+
+
+/// \brief The real code for launching the kmean optimised algorithm.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// This is the real lauching code. In fact, the stuff consists in loading the
+/// image, setting the parameters, calling the routine, extracting the results
+/// and saving them for the user.
+///
+/// \fixme The result is not safe because we don't test kmean.is_valid()
+void do_demo(const std::string& image,
+ const unsigned k_center,
+ const unsigned n_times,
+ const unsigned watch_dog)
+{
+ typedef mln::value::label_8 t_lbl8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<5> t_rgb5;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgb5> t_image2d_rgb5;
+ typedef mln::image2d<t_lbl8> t_image2d_lbl8;
+
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rgb5 img_rgb5;
+ t_image2d_lbl8 img_lbl8;
+
+ mln::io::ppm::load(img_rgb8, image.c_str());
+ img_rgb5 = mln::data::transform(img_rgb8,mln::fun::v2v::rgb8_to_rgbn<5>());
+ img_lbl8 = mln::clustering::kmean_rgb<double,5>(img_rgb5,
+ k_center,
+ watch_dog,
+ n_times);
+
+ mln::io::pgm::save(img_lbl8, "label.pgm");
+}
+
+/// \brief Front hand for the demonstrator.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// The front hand enables the setting of the default values for the
+/// parameters. it allows us to print the real parameter set used by
+/// the demonstrator.
+void demo(const std::string& image = OLENA_IMG_PATH"/house.ppm",
+ const unsigned k_center = 3,
+ const unsigned n_times = 3,
+ const unsigned watch_dog = 3)
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "Launching the demo with these parameters" << std::endl;
+ std::cout << "image : " << image << std::endl;
+ std::cout << "k_center : " << k_center << std::endl;
+ std::cout << "n_times : " << n_times << std::endl;
+ std::cout << "watch_dog : " << watch_dog << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+
+ do_demo(image, k_center, n_times, watch_dog);
+}
+
+
+/// \brief Convert character get in the input stream to unsigned integer.
+///
+/// \param[in] status : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+/// \param[out] val : the converted value to output.
+///
+/// \return a flag that tell us if every thing is ok, if the result can be used.
+bool char_to_unsigned(const bool status, const char *arg, unsigned& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ result = !arg_stream.fail();
+ }
+
+ return result;
+}
+
+
+/// \brief Convert character get in the input stream to string.
+///
+/// \param[in] status : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+/// \param[out] val : the converted value to output.
+///
+/// \return a flag that tell us if every thing is ok, if the result can be used.
+bool char_to_string(const bool status, const char *arg, std::string& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ return !arg_stream.fail();
+ }
+
+ return result;
+}
+
+
+/// \brief Print usage recommandation for this binary.
+///
+/// \param[in] argc : the exiting flag tell us to exit without doing any job.
+/// \param[in] arg : the input argument to convert.
+void usage(const int argc, const char *args[])
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "argc : " << argc << std::endl;
+
+ for (int i = 0; i < argc; ++i)
+ std::cout << "args[" << i << "] : " << args[i] << std::endl;
+
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "usage: kmean1d [image [k_center [n_times [watch_dog]]]]"
+ << std::endl;
+ std::cout << "pbm image (points to work with)" << std::endl;
+ std::cout << "unsigned k_center (number of centers)" << std::endl;
+ std::cout << "unsigned n_times (number of launching)" << std::endl;
+ std::cout << "unsigned watch_dog (convergence loop)" << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+}
+
+
+/// \brief The main routine launchs the kmean optimised algoritm.
+///
+/// \param[in] image : the color image.
+/// \param[in] k_center : the number of centers.
+/// \param[in] n_times : the number of launching.
+/// \param[in] watch_dog : the number of iterations to manage the convergence.
+///
+/// All the parameters are optional, but we must respect strictly a
+/// specific order. In fact, we can launch five programs with some
+/// default parameters: demo(), demo(image), demo(image,k_center),
+/// demo(image,k_center,n_times) and
+/// demo(image,k_center,n_times,watch_dog).
+int main(const int argc, const char *args[])
+{
+ std::string image("top");
+ unsigned k_center;
+ unsigned watch_dog;
+ unsigned n_times;
+ bool status = true;
+
+ switch (argc)
+ {
+ case 5: status = char_to_unsigned(status, args[4], watch_dog);
+ case 4: status = char_to_unsigned(status, args[3], n_times);
+ case 3: status = char_to_unsigned(status, args[2], k_center);
+ case 2: status = char_to_string(status, args[1], image); break;
+ case 1: status = true; break;
+ default: status = false;
+ }
+
+ if (status)
+ {
+ switch (argc)
+ {
+ case 1: demo(); break;
+ case 2: demo(image); break;
+ case 3: demo(image, k_center); break;
+ case 4: demo(image, k_center, n_times); break;
+ case 5: demo(image, k_center, n_times, watch_dog); break;
+ }
+ }
+ else
+ usage(argc, args);
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/mln/clustering/k_mean.hh b/scribo/sandbox/green/mln/clustering/k_mean.hh
index db3f34c..74acda7 100644
--- a/scribo/sandbox/green/mln/clustering/k_mean.hh
+++ b/scribo/sandbox/green/mln/clustering/k_mean.hh
@@ -1,6 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -26,43 +24,89 @@
// executable file might be covered by the GNU General Public License.
#ifndef MLN_CLUSTERING_K_MEAN_HH
-#define MLN_CLUSTERING_K_MEAN_HH
+# define MLN_CLUSTERING_K_MEAN_HH
/// \file
///
-/// \brief Implements the K MEAN algorithm.
-/// DO
-/// - ASSIGNEMENT STEP
-/// - UPDATE STEP
-/// LOOP UNTIL CONVERGENCE
+/// \brief Implement the K MEAN algorithm with matrix and vectors.
///
-/// ASSIGNEMENT STEP
+/// This is the first impementation of the kmean algorithm. There is no
+/// specific optimisation but every part of the algorithm is here and
+/// it works. As it used vectors and matrices, it is not very convenient to
+/// work with this version.
+///
+/// \verbatim
+/// This is the main lines of the kmean algorithm:
+///
+/// PROCEDURE MAIN
+/// BEGIN
+/// DO
+/// - CALL ASSIGNEMENT STEP
+/// - CALL UPDATE STEP
+/// LOOP UNTIL CONVERGENCE
+/// END
+///
+/// PROCEDURE ASSIGNEMENT STEP
/// BEGIN
-/// - COMPUTE THE DISTANCE MATRIX FROM POINTS TO CENTERS
-/// - COMPUTE GROUP MATRIX WHERE EACH POINT IS ASSIGNED TO NEAREST CENTER
+/// - COMPUTE THE DISTANCE MATRIX FROM POINTS TO CENTERS
+/// - COMPUTE GROUP MATRIX WHERE EACH POINT IS ASSIGNED TO THE NEAREST CENTER
/// END
///
-/// UPDATE STEP
+/// PROCEDURE UPDATE STEP
/// BEGIN
-/// - COMPUTE THE MEAN OF THE GROUPS WHICH ARE THE NEW CENTERS
+/// - COMPUTE THE MEAN OF THE GROUPS WHICH ARE NOW THE NEW CENTERS
/// END
+/// \endvarbitim
+///
+/// The following sample is the standard use of this first
+/// implementation. The number of centers is a decision left to the
+/// final user. As the representation uses vectors and matices, size
+/// of each objects must be known at compile time, and so NB_POINT must be
+/// a constant expression (mln::geom::nsites couldn't be called).
+///
+/// #include <mln/clustering/k_mean.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/trait/value_.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// #define NB_CENTER 9
+/// #define NB_POINT (128*128)
+/// #define POINT_SIZE mln_dim(mln::value::rgb8)
+/// #define POINT_TYPE double
+///
+/// int main()
+/// {
+/// typedef mln::value::rgb8 t_rgb8;
+/// mln::image2d<t_rgb8> img_rgb8;
+///
+/// mln::io::ppm::load(img_ref, OLENA_IMG_PATH"/house.ppm");
+/// mln::clustering::k_mean<NB_POINT,NB_CENTER,POINT_SIZE,POINT_TYPE> kmean;
+///
+/// kmean.init_point(img_rgb8);
+/// kmean.loop(img_rgb8);
+///
+/// return 0;
+/// }
+
+# include <limits.h>
+# include <iostream>
-#include <limits.h>
-#include <iostream>
-#include <mln/trace/entering.hh>
-#include <mln/trace/exiting.hh>
+# include <mln/algebra/mat.hh>
+# include <mln/algebra/vec.hh>
-#include <mln/core/contract.hh>
-#include <mln/trait/value_.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/contract.hh>
+# include <mln/core/macros.hh>
-#include <mln/algebra/mat.hh>
-#include <mln/algebra/vec.hh>
+# include <mln/math/min.hh>
+# include <mln/norm/l2.hh>
-#include <mln/math/min.hh>
-#include <mln/norm/l2.hh>
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
-#include <mln/core/concept/image.hh>
-#include <mln/core/macros.hh>
+# include <mln/trait/value_.hh>
namespace mln
{
@@ -78,149 +122,221 @@ namespace mln
namespace clustering
{
-
- //
- // PARAM : DIM VECTOR, NUMBER OF CLASSES
- // INPUT : MATRIX 1..N (SAMPLE)
- // WORK
- //
-
- // n is the size of the sample.
- // k is the number of centers.
- // p is the number of attributes for a point.
- // T is the type for computations.
+
+ /// \brief Implements the K MEAN algorithm with matrix and vectors.
+ ///
+ /// Param n is the size of the sample (the number of point to be
+ /// classified). Param k is the number of centers, at the end,
+ /// each point is link to one the nearest center. Param p is the
+ /// number of attributes of a point, in fact its dimension (int_u8
+ /// = 1, rgb8 = 3, etc ...). Param T is the type used for
+ /// computations, the type of the point, typiccaly float or
+ /// double.
+ ///
+ /// \ingroup modclustering
template <unsigned n, unsigned k, unsigned p, typename T>
struct k_mean
{
- //------------------------------------------------------------------------
- // Constructor and destructor
- //------------------------------------------------------------------------
-
+ /// Constructors and destructors.
+ /// \{
+ /// \brief Allocate or deallocate the data structure.
+ ///
+ /// Allocate or deallocate the _point, _distance, _group,
+ /// _center, _variance data structure with the correct size.
k_mean();
~k_mean();
+ /// \}
- //------------------------------------------------------------------------
- // Accessors
- //------------------------------------------------------------------------
-
+ /// Accessors.
+ /// \{
+ /// \brief Hack to view temporary results of the kmean algorithm.
+ ///
+ /// These methods are necessary for unitary testing and debugging.
algebra::mat<n, p, T>& get_point();
algebra::mat<k, p, T>& get_center();
algebra::mat<n, k, T>& get_distance();
algebra::mat<n, k, T>& get_group();
algebra::vec<k, T>& get_variance();
+ /// \}
-
- //------------------------------------------------------------------------
- // Tools
- //------------------------------------------------------------------------
+ /// Tools.
+ /// \{
+ /// \brief Define elementary function that are not available from milena.
+ ///
+ /// These methods are not interesting from the kmean'point of
+ /// view but are required for the gluing process.
- /// \brief Return the euclidian distance beetween vector x and vector y.
+ /// \brief Return the euclidian distance beetween two vectors x and y.
///
/// Compute the f$\sqrt(\sum_{i=0}^P ((x_i - y_i)^2)$f
///
- /// \param[in] x a vector of dimension 1xP.
- /// \param[in] y a second vector of dimension 1xP.
+ /// \param[in] x a vector of dimension p.
+ /// \param[in] y a second vector of dimension p.
/// \return the distance between x and y.
-
mln_sum_product(T,T) euclidian_distance(const algebra::vec<p,T>& x,
const algebra::vec<p,T>& y) const;
- /// \brief Return the ith column.
- ///
- /// \param[in] m a matrix of dimension {N or K}xP.
- /// \return the ith column as a vector of dimension 1xP.
-
- /// \brief Return the ith column.
+ /// \brief Return a stack copy of the ith column.
///
- /// \param[in] m a matrix of dimension {N or K}xP.
- /// \return the ith column as a vector of dimension 1xP.
+ /// \param[in] m a matrix of dimension r x q.
+ /// \param[in] _col the index of the selected column.
+ /// \return a stack copy of the ith column as a vector of dimension q.
template <unsigned q, unsigned r>
algebra::vec<q,T> col(const algebra::mat<r, q, T>& m,
const unsigned _col) const;
+
+ /// \brief Return a heap copy of the ith col.
+ ///
+ /// \param[in] m a matrix of dimension r x q.
+ /// \param[in] _col the index of the selected column.
+ /// \return a heap copy of the ith column as a vector of dimension q.
template <unsigned q, unsigned r>
algebra::vec<q,T>* ptr_col(const algebra::mat<r, q, T>& m,
const unsigned _col) const;
+
+ /// \brief Return a stack copy of the ith row.
+ ///
+ /// \param[in] m a matrix of dimension r x q.
+ /// \param[in] _row the index of the selected row.
+ /// \return a stack copy of the ith row as a vector of dimension q.
template <unsigned q, unsigned r>
algebra::vec<r,T> row(const algebra::mat<r, q, T>& m,
const unsigned _row) const;
+
+ /// \brief Divide inplace a column of the matrix by a scalar.
+ ///
+ /// \param[in] m a matrix of dimension r x q.
+ /// \param[in] _col the index of the selected column.
+ /// \param[in] value the scalar by which dividing the column.
template <unsigned q, unsigned r>
void div_col(algebra::mat<r, q, T>& m,
const unsigned _col,
const T value);
+
+ /// \brief Sum all the elements of one row.
+ ///
+ /// \param[in] m a matrix of dimension r x q.
+ /// \param[in] _row the index of the selected row.
+ /// \return the sum of every attributes of the row.
template <unsigned q, unsigned r>
mln_sum(T) sum_row(const algebra::mat<r, q, T>& m,
const unsigned _row) const;
+
+ /// \brief Return the minimum of a vector.
+ ///
+ /// \param[in] x a vector of dimension q.
+ /// \return the mininum of that input vector.
template <unsigned q, typename M>
M min_col(const algebra::vec<q, M>& x) const;
+ /// \}
- //------------------------------------------------------------------------
- // Initializations of points and centers
- //------------------------------------------------------------------------
-
- /// \brief Initialize the matrix _point with the pixels of an image.
+ /// Initializations.
+ /// \{
+ /// \brief Initialize the _point and _center data structure.
///
- /// \param[in] input an image which contains the data points.
+ /// The _point data structure is fed with the value of the input
+ /// image. The _center data structure is fed with random points
+ /// taken from the input image.
template <typename I>
void init_point(const Image<I>& _input);
void init_center();
+ /// \}
-
- //------------------------------------------------------------------------
- // Computations of distance, group, center, within variance
- //------------------------------------------------------------------------
+ /// Computations.
+ /// \{
+ /// \brief Define the core routines of the kmean algorithm.
+ ///
+ /// The update_distance, update_group, update_center and update_variance
+ /// define the core kmean routines. If some optimization muste be done,
+ /// one may looks here.
+
+
+ /// \brief Update the _distance data structure.
+ ///
+ /// Compute the square distance between each point of the data
+ /// cloud and each center.
void update_distance();
+
+ /// \brief Update the _group data structure.
+ ///
+ /// For each point of the data cloud, find the group which has
+ /// the minimum distance from it.
void update_group();
- void update_center();
- T update_variance();
+ /// \brief Update the _center data structure.
+ ///
+ /// For each group, compute the center of mass in therm of
+ /// points of the data cloud.
+ void update_center();
- //------------------------------------------------------------------------
- // Main loop
- //------------------------------------------------------------------------
+ /// \brief Update the _variance.
+ ///
+ /// Compute the within variance. Sum every shortest distance.
+ T update_variance();
+ /// \}
+ /// \brief Define the orchestration of the kmean core routines.
+ ///
+ /// \param[in] _input the initial image which initialize the data cloud.
+ ///
+ /// The orchestration is in a fact a loop which call one after
+ /// each other the core routines. Ending the loop means managing
+ /// the statistical convergence or having some clues of
+ /// divergence (watch_dog).
template <typename I>
void loop(const Image<I>& _input);
- //void loop();
private:
+ /// \brief watch_dog define the maximum of iterations that can be done.
+ ///
+ /// That constant help us to decide if divergence has been
+ /// occurred or not.
static const unsigned watch_dog = 100;
-
+
+
/// \brief _points contains the concatenation of every data points.
///
- /// One data point is a vector 1xP where P is the number of attributes.
- /// _points is a matrix NxP where N is the number of data points.
+ /// One data point is a vector 1 x p where p is the number of attributes.
+ /// So _points is a matrix n x P where n is the number of data points.
algebra::mat<n, p, T>* _point;
+
/// \brief _distance contains all the euclidian distances between points
/// and the centers.
///
- /// _distance is a matrix NxK where N is the number of data points and
- /// K the number of centers.
+ /// _distance is a matrix n x k where n is the number of data points and
+ /// k the number of centers.
algebra::mat<n, k, mln_sum_product(T,T)>* _distance;
+
/// \brief _group contains the point assignement to one center.
///
- /// _group is a boolean matrix NxK where N is the number of data points
- /// and K the number of centers.
+ /// _group is a boolean matrix n x k where n is the number of data points
+ /// and k the number of centers.
algebra::mat<n, k, T>* _group;
- /// \brief _center contains the coordonnate of the K centers.
+
+ /// \brief _center contains the coordonnate of the k centers.
///
- /// _center is a matrix KxP where K is the number of centers and P is the
- /// number of attributes.
+ /// _center is a matrix k x p where k is the number of centers
+ /// and p is the number of attributes.
algebra::mat<k, p, T>* _center;
+
+ /// \brief _variance contains the variance of each group.
+ ///
+ /// _variance is a vector 1 x k where k is the number of centers.
algebra::vec<k, T>* _variance;
};
@@ -234,7 +350,7 @@ namespace mln
inline
k_mean<n,k,p,T>::k_mean()
{
- trace::entering("mln::clustering::k_mean::k_mean");
+ trace::entering("mln::clustering::k_mean::cstor");
_point = new algebra::mat<n, p, T>();
_distance = new algebra::mat<n, k, mln_sum_product(T,T)>();
@@ -248,14 +364,14 @@ namespace mln
mln_postcondition(_center != 0);
mln_postcondition(_variance != 0);
- trace::exiting("mln::clustering::k_mean::k_mean");
+ trace::exiting("mln::clustering::k_mean::cstor");
}
template <unsigned n, unsigned k, unsigned p, typename T>
inline
k_mean<n,k,p,T>::~k_mean()
{
- trace::entering("mln::clustering::k_mean::~k_mean");
+ trace::entering("mln::clustering::k_mean::dstor");
delete _point;
delete _distance;
@@ -263,7 +379,7 @@ namespace mln
delete _center;
delete _variance;
- trace::exiting("mln::clustering::k_mean::~k_mean");
+ trace::exiting("mln::clustering::k_mean::dstor");
}
//--------------------------------------------------------------------------
@@ -350,7 +466,7 @@ namespace mln
template <unsigned n, unsigned k, unsigned p, typename T>
template <unsigned q, unsigned r>
inline
- algebra::vec<q,T> k_mean<n,k,p,T>::col(const algebra::mat<r, q, T>& m,
+ algebra::vec<q,T> k_mean<n,k,p,T>::col(const algebra::mat<r, q, T>& m,
const unsigned _col) const
{
trace::entering("mln::clustering::k_mean::col");
@@ -368,7 +484,7 @@ namespace mln
template <unsigned n, unsigned k, unsigned p, typename T>
template <unsigned q, unsigned r>
inline
- algebra::vec<q,T>* k_mean<n,k,p,T>::ptr_col(const algebra::mat<r, q, T>& m,
+ algebra::vec<q,T>* k_mean<n,k,p,T>::ptr_col(const algebra::mat<r, q, T>& m,
const unsigned _col) const
{
trace::entering("mln::clustering::k_mean::ptr_col");
@@ -386,7 +502,7 @@ namespace mln
template <unsigned n, unsigned k, unsigned p, typename T>
template <unsigned q, unsigned r>
inline
- mln_sum(T) k_mean<n,k,p,T>::sum_row(const algebra::mat<r, q, T>& m,
+ mln_sum(T) k_mean<n,k,p,T>::sum_row(const algebra::mat<r, q, T>& m,
const unsigned _row) const
{
trace::entering("mln::clustering::k_mean::sum_row");
@@ -404,7 +520,7 @@ namespace mln
template <unsigned n, unsigned k, unsigned p, typename T>
template <unsigned q, unsigned r>
inline
- void k_mean<n,k,p,T>::div_col(algebra::mat<r, q, T>& m,
+ void k_mean<n,k,p,T>::div_col(algebra::mat<r, q, T>& m,
const unsigned _col,
const T value)
{
@@ -422,21 +538,21 @@ namespace mln
inline
M k_mean<n,k,p,T>::min_col(const algebra::vec<q, M>& x) const
{
- trace::entering("mln::clustering::k_mean<n,k,p,T>::min_col");
-
+ trace::entering("mln::clustering::k_mean::min_col");
+
M result = x[0];
for (unsigned i = 1; i < q; ++i)
result = math::min(result, x[i]);
- trace::exiting("mln::clustering::k_mean<n,k,p,T>::min_col");
+ trace::exiting("mln::clustering::k_mean::min_col");
return result;
}
template <unsigned n, unsigned k, unsigned p, typename T>
inline
mln_sum_product(T,T)
- k_mean<n,k,p,T>::euclidian_distance(const algebra::vec<p, T>& x,
+ k_mean<n,k,p,T>::euclidian_distance(const algebra::vec<p, T>& x,
const algebra::vec<p, T>& y) const
{
trace::entering("mln::clustering::k_mean::euclidian_distance");
@@ -458,8 +574,8 @@ namespace mln
inline
void k_mean<n,k,p,T>::init_point(const Image<I>& _input)
{
- trace::entering("mln::clustering::k_mean<n,k,p,T>::init");
-
+ trace::entering("mln::clustering::k_mean::init");
+
const I& input = exact(_input);
algebra::mat<n, p, T>& point = *_point;
@@ -474,28 +590,28 @@ namespace mln
for_all(pi)
{
//std::cout << pi << std::endl;
-
+
++i;
for (unsigned j = 0; j < p; ++j)
{
-
+
point(i,j) = input(pi).comp(j);
//point(i,j) = input(pi);
}
}
- trace::exiting("mln::clustering::k_mean<n,k,p,T>::init");
+ trace::exiting("mln::clustering::k_mean::init");
}
template <unsigned n, unsigned k, unsigned p, typename T>
inline
void k_mean<n,k,p,T>::init_center()
{
- trace::entering("mln::clustering::k_mean<n,k,p,T>::init_center");
-
+ trace::entering("mln::clustering::k_mean::init_center");
+
algebra::mat<n, p, T>& point = *_point;
algebra::mat<k, p, T>& center = *_center;
-
+
// A random point is choosen to be the initial value for a center.
for (unsigned i = 0; i < k; ++i)
{
@@ -503,16 +619,16 @@ namespace mln
for (unsigned j = 0; j < p; ++j)
{
- center(i,j) = point(random, j);
+ center(i,j) = point(random, j);
}
//std::cout << "center(" << i << ")" << col(center, i) << std::endl;
}
- trace::exiting("mln::clustering::k_mean<n,k,p,T>::init_center");
+ trace::exiting("mln::clustering::k_mean::init_center");
}
-
+
//--------------------------------------------------------------------------
// Computations of distance, group, center, within variance
//--------------------------------------------------------------------------
@@ -528,7 +644,7 @@ namespace mln
algebra::mat<n, p, T>& point = *_point;
algebra::mat<n, k, T>& distance = *_distance;
algebra::mat<k, p, T>& center = *_center;
-
+
// for all points in the data cloud.
for (unsigned i = 0; i < n; ++i)
{
@@ -546,7 +662,7 @@ namespace mln
inline
void k_mean<n,k,p,T>::update_group()
{
- trace::entering("mln::clustering::k_mean<n,k,p,T>::update_group");
+ trace::entering("mln::clustering::k_mean::update_group");
algebra::mat<n, k, mln_sum_product(T,T)>& distance = *_distance;
algebra::mat<n, k, T>& group = *_group;
@@ -563,14 +679,14 @@ namespace mln
}
// mln_postcondition(sum(col(distance(i,j)) == 1) Vi
- trace::exiting("mln::clustering::k_mean<n,k,p,T>::update_group");
+ trace::exiting("mln::clustering::k_mean::update_group");
}
template <unsigned n, unsigned k, unsigned p, typename T>
inline
void k_mean<n,k,p,T>::update_center()
{
- trace::entering("mln::clustering::k_mean<n,k,p,T>::update_center");
+ trace::entering("mln::clustering::k_mean::update_center");
algebra::mat<n, p, T>& point = *_point;
algebra::mat<k, p, T>& center = *_center;
@@ -592,14 +708,14 @@ namespace mln
for (unsigned i = 0; i < k; ++i)
div_col(center, i, sum_row(group, i));
- trace::exiting("mln::clustering::k_mean<n,k,p,T>::update_center");
+ trace::exiting("mln::clustering::k_mean::update_center");
}
template <unsigned n, unsigned k, unsigned p, typename T>
inline
T k_mean<n,k,p,T>::update_variance()
{
- trace::entering("mln::clustering::k_mean<n,k,p,T>::update_variance");
+ trace::entering("mln::clustering::k_mean::update_variance");
algebra::vec<k, T>& variance = *_variance;
algebra::mat<n, k, T>& distance = *_distance;
@@ -613,10 +729,10 @@ namespace mln
result += variance[i];
}
- trace::exiting("mln::clustering::k_mean<n,k,p,T>::update_variance");
+ trace::exiting("mln::clustering::k_mean::update_variance");
return result;
- }
-
+ }
+
//--------------------------------------------------------------------------
// Main loop
@@ -626,9 +742,8 @@ namespace mln
template <typename I>
inline
void k_mean<n,k,p,T>::loop(const Image<I>& _input)
- //void k_mean<n,k,p,T>::loop()
{
- trace::entering("mln::clustering::k_mean<n,k,p,T>::loop");
+ trace::entering("mln::clustering::k_mean::loop");
T within_variance = INT_MAX-1;
T old_variance = INT_MAX;
@@ -658,12 +773,10 @@ namespace mln
std::cout << i << " : " << within_variance << std::endl;
}
- trace::exiting("mln::clustering::k_mean<n,k,p,T>::loop");
- }
-
-
+ trace::exiting("mln::clustering::k_mean::loop");
+ }
-#endif // ! MLN_INCLUDE_ONLY
+# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::clustering
diff --git a/scribo/sandbox/green/mln/clustering/kmean1d.hh b/scribo/sandbox/green/mln/clustering/kmean1d.hh
index c3c1add..57d246b 100644
--- a/scribo/sandbox/green/mln/clustering/kmean1d.hh
+++ b/scribo/sandbox/green/mln/clustering/kmean1d.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008,2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -24,7 +24,7 @@
// executable file might be covered by the GNU General Public License.
#ifndef MLN_CLUSTERING_KMEAN1D_HH
-#define MLN_CLUSTERING_KMEAN1D_HH
+# define MLN_CLUSTERING_KMEAN1D_HH
/// \file
///
@@ -34,36 +34,63 @@
/// the greylevel attribute inspite of the pixel attribute. The
/// algorithm is independant from the image dimension. But, we have to
/// compute one time the histogram. In fact, we move a recurrent cost
-/// to a fix cost in the complexity. This version is very adapted to
+/// by a fix cost in the complexity. This version is very adapted to
/// images with small quantification.
+///
+/// The following sample is a typical use of the new kmean implementation.
+///
+/// #include <iostream>
+/// #include <mln/clustering/kmean1d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/pgm/load.hh>
+/// #include <mln/value/int_u8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::int_u8 t_int_u8;
+/// typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+/// t_image2d_int_u8 img_int_u8;
+///
+/// mln::io::pgm::load(img_int_u8, OLENA_IMG_PATH"/house.pgm");
+/// mln::clustering::kmean1d<double, 8> kmean(img_int_u8, 3);
+///
+/// kmean.launch_n_times();
+///
+/// return 0;
+/// }
+
+# include <limits.h>
+# include <iostream>
-#include <limits.h>
-#include <iostream>
-#include <mln/trace/entering.hh>
-#include <mln/trace/exiting.hh>
+# include <mln/accu/stat/histo1d.hh>
-#include <mln/core/contract.hh>
-#include <mln/trait/value_.hh>
-#include <mln/accu/stat/histo1d.hh>
+# include <mln/core/contract.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/macros.hh>
-#include <mln/math/min.hh>
-#include <mln/math/sqr.hh>
-#include <mln/norm/l2.hh>
+# include <mln/data/compute.hh>
+# include <mln/data/fill.hh>
+# include <mln/debug/println.hh>
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/core/macros.hh>
+# include <mln/io/ppm/save.hh>
+# include <mln/io/pgm/save.hh>
-#include <mln/data/compute.hh>
-#include <mln/debug/println.hh>
-#include <mln/data/fill.hh>
-#include <mln/literal/zero.hh>
-#include <mln/labeling/colorize.hh>
-#include <mln/labeling/mean_values.hh>
+# include <mln/literal/zero.hh>
+# include <mln/labeling/colorize.hh>
+# include <mln/labeling/mean_values.hh>
-#include <mln/io/ppm/save.hh>
-#include <mln/io/pgm/save.hh>
+# include <mln/math/min.hh>
+# include <mln/math/sqr.hh>
+# include <mln/norm/l2.hh>
+
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
+
+# include <mln/trait/value_.hh>
+
+# include <mln/value/int_u.hh>
+# include <mln/value/rgb8.hh>
namespace mln
{
@@ -85,8 +112,8 @@ namespace mln
/// temporary images for computations and produces images as result. Images
/// play the role of matrix or vector in standard statistic algoritm.
///
- /// T is the type used for computations (float or double).
- /// n is the quantification for the image grayscale.
+ /// Param T is the type used for computations (float or double).
+ /// Param n is the quantification for the image grayscale.
template <typename T, unsigned n>
struct kmean1d
{
@@ -117,32 +144,22 @@ namespace mln
///}
- //------------------------------------------------------------------------
- // Constructor
- //------------------------------------------------------------------------
-
- /// \brief Constructor
+ /// \brief Constructor.
/// \param[in] point : the image as the population of pixels.
/// \param[in] k_center : the number of centers.
/// \param[in] watch_dog : the limit to observe the convergence (10).
/// \param[in] n_times : the number of times that we executed kmean(10).
-
kmean1d(const t_point_img& point,
const unsigned k_center,
const unsigned watch_dog = 10,
const unsigned n_times = 10);
- //------------------------------------------------------------------------
- // Accessors
- //------------------------------------------------------------------------
-
- /// Mutator and accessors.
+ /// Mutators and accessors.
/// \{
/// \brief Mutator and accessors are required for debugging and testing.
///
/// Testing needs to hack the kmean loop process in order to verify each
/// step of the algorithm.
-
void set_point(t_point_img& point);
void set_histo(t_histo_img& histo);
void set_number(t_number_img& number);
@@ -173,31 +190,21 @@ namespace mln
/// \}
- //------------------------------------------------------------------------
- // Initializations of centers
- //------------------------------------------------------------------------
-
/// Initialization of centers.
/// \{
- /// \brief Two ways: Regular greylevel tick or random greylevel value or.
+ /// \brief Initialize centers by regular tick or random position.
///
/// There is two way to proceed the initialization. First of all, we
/// divide the greyscale in regular tick and we assigne them to the mean
/// of the centers. Finaly, we can ask random initialization along the
/// greyscale axis. The second process is needed to launch_n_times the
/// kmean and converge to the best descent.
-
void init_mean();
void init_mean_regular();
void init_mean_random();
-
/// \}
- //------------------------------------------------------------------------
- // Computations of distance, group, center, within variance
- //------------------------------------------------------------------------
-
/// Computations of distance, group, center, within variance.
/// \{
/// \brief Update the statistical information needed by the kmean process.
@@ -206,36 +213,27 @@ namespace mln
/// first compute. Then we assign the pixels to their nearest center.
/// The new location of each center can then update. Finaly, hommogeneity
/// in group is observed by the within variance.
-
void update_distance();
void update_group();
void update_mean();
void update_variance();
-
/// \}
- //------------------------------------------------------------------------
- // Main loop
- //------------------------------------------------------------------------
/// kmean main loop
/// \{
/// \brief User interface to launch the kmean process.
///
- /// There are two ways to launch the kmean process. The first one allow to
- /// run it one time until convergence. As the process is a descent, it
- /// depends on the initial center locations. The second call allow us to
- /// rerun the process many times and to keep the best result (the one
- /// with the smallest within variance).
-
+ /// There are two ways to launch the kmean process. The first
+ /// one allows to run it one time until convergence. As the
+ /// process is a descent, it depends on the initial center
+ /// location. The second call allow us to rerun the process
+ /// many times and to keep the best result (the one with the
+ /// smallest within variance).
void launch_one_time();
void launch_n_times();
-
/// \}
- //------------------------------------------------------------------------
- // Checking the validiy of the results
- //------------------------------------------------------------------------
/// Checking the validity of the results.
/// \{
@@ -244,15 +242,10 @@ namespace mln
/// After each launching the kmean process one time, we need to know if
/// the descent was successfull or not. The method is_valid_descent do it
/// for us. The method looks for a bad center (a class with no greylevel
- /// associate to it) and a failure in the convergence.
-
+ /// associate to it) or a failure in the convergence.
bool is_descent_valid();
-
/// \}
- //------------------------------------------------------------------------
- // Debugging tools
- //------------------------------------------------------------------------
/// Debugging tools
/// \{
@@ -264,12 +257,10 @@ namespace mln
/// greylevel image. The update_cnv and finalize_cnv methods are used to
/// trace the convergence. They fill two images with the mean info and
/// the within variance info along the convergence and the tries.
-
void build_label_dbg();
void build_all_dbg();
void update_cnv();
void finalize_cnv();
-
/// \}
@@ -279,20 +270,19 @@ namespace mln
/// \brief These parameters control the convergence of the process.
///
/// The first parameter, k_center, defines the number of center for kmean.
- /// In fact, watch_dog limit the number of iteration that a simple kmean
+ /// In fact, watch_dog limits the number of iteration that a simple kmean
/// loop can do. If the process reaches the watch_dog limit, it means
/// that the process will not converge at all. The second parameter
/// n_times is the number of times we launch again and again the simple
/// kmean loop. As the kmean process is a descent, restarting the process
/// from different location will confort us in that we found a global
/// minima, not just a local one.
-
unsigned _k_center;
unsigned _watch_dog;
unsigned _n_times;
-
/// \}
+
/// Convergence information.
/// \{
/// \brief This information is used to follow the convergence.
@@ -300,26 +290,25 @@ namespace mln
/// The within_variance is the homogeniety indicator for the
/// kmean process. The ideal situation is to find the center
/// with the minimum variance around them. The within variance
- /// is just the sum of all variance around the centers. The
- /// current_step variable allows us to remember the current
- /// iteration in the kmean loop. This information is needed by
- /// is_descent_valid routine which decide if convergence occurs
- /// or not. The current_step info explicit where we are in the
- /// kmean iteration. The last information, current_launching,
- /// traces the progress while iterates kmean loop again and
- /// again. The flag is_number_valid is set when a empty class
- /// appears. This flag inhibit the process and force to restart
- /// a try.
-
+ /// is just the sum of all ponderated variances around the
+ /// centers. The current_step variable allows us to remember the
+ /// current iteration in the kmean loop. This information is
+ /// needed by is_descent_valid routine which decide if
+ /// convergence occurs or not. The current_step info explicit
+ /// where we are in the kmean iteration. The last information,
+ /// current_launching, traces the progress while iterates kmean
+ /// loop again and again. The flag is_number_valid is set when a
+ /// empty class appears. This flag inhibit the process and
+ /// force to restart a try.
t_result _within_variance;
unsigned _current_step;
unsigned _current_launching;
bool _is_number_valid;
static const unsigned _N_TRIES = 3;
-
/// \}
+
/// Result of the kmean process.
/// \{
/// \brief The center location are the major results of the kmean process.
@@ -327,23 +316,23 @@ namespace mln
/// The kmean process result is composed by three information. The best
/// launching iteration, the best within variance obtained and the
/// location of the centers associated.
-
unsigned _launching_min;
t_result _variance_min;
t_mean_img _mean_min;
+ /// \}
+
/// Inputs.
/// \{
- /// \brief The inputs are the distribution of the values and the values.
+ /// \brief The inputs are the distribution of the values.
///
/// The point image is a saving data for the real inputs. In fact, we use
/// the histogram information in the optimized kmean process.
-
t_point_img _point;
t_histo_img _histo;
-
///\}
+
/// Centers description.
/// \{
/// \brief Centers are described by the first moment of their group.
@@ -354,13 +343,12 @@ namespace mln
/// convergence. The number of pixels is used as integrity indicator.
/// A center with no point is a non sense. Theses informations are updated
/// after each kmean iteration.
-
t_number_img _number; // k x 1
t_mean_img _mean; // k x 1
t_variance_img _variance; // k x 1 within group
-
/// \}
+
/// Greylevels description.
/// \{
/// \brief The information are concerned with the greylevel input image.
@@ -369,15 +357,14 @@ namespace mln
/// which pixel) is assigned to a center. The distance image give us a
/// clue on how a greylevel could contribute to a center. The summation
/// over the greylevels of a center give us the within variance.
-
t_group_img _group; // g x 1 because dim(t_value) = 1
t_distance_img _distance; // label x graylevel
-
/// \}
+
/// Debugging, calibrating and testing results.
/// \{
- /// \brief Some exports information to control the results.
+ /// \brief Some information exports to control the results.
///
/// We come back in the input space. Label is the image which associates
/// each pixel to its center. Color is the image which gives a random rgb
@@ -385,14 +372,13 @@ namespace mln
/// label (assigned to the same center) in the image. The mean image
/// associate the mean of each pixel center to each pixel. We obtain thus
/// a rebuilded image.
-
t_label_dbg _label_dbg;
t_color_dbg _color_dbg;
t_mean_dbg _mean_dbg;
-
/// \}
- /// Debugging, calibrating and testing convergence.
+
+ /// Variance and center evolutions.
/// \{
/// \brief Trace the variance and the center evolution.
///
@@ -401,10 +387,8 @@ namespace mln
/// kmean loop or along the different launch. The variance_cnv is a trace
/// of the within variance along the kmean loop or along the different
/// launch.
-
t_mean_cnv _mean_cnv;
t_variance_cnv _variance_cnv;
-
/// \}
};
@@ -803,8 +787,6 @@ namespace mln
{
trace::entering("mln::clustering::kmean1d::update_mean");
- /// FIXME VERIFIER QUE L'ON PEUT OBTENIR UNE IMAGE EN NDG SIGNE
-
// avec g le niveau de gris (signed or not signed)
// w[g] la classe de g sous forme d'image
// h[g] l'histogramme de l'image sous forme d'image
@@ -872,7 +854,7 @@ namespace mln
for_all(g)
{
- if (l.ind() == _group(g))
+ if (static_cast<t_label>(l.ind()) == _group(g))
_variance(l) += _distance(point2d(g.ind(), l.ind()));
}
@@ -1091,7 +1073,7 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::launch_n_times");
}
-#endif // ! MLN_INCLUDE_ONLY
+# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::clustering
diff --git a/scribo/sandbox/green/mln/clustering/kmean2d.hh b/scribo/sandbox/green/mln/clustering/kmean2d.hh
index e4918db..51aaf49 100644
--- a/scribo/sandbox/green/mln/clustering/kmean2d.hh
+++ b/scribo/sandbox/green/mln/clustering/kmean2d.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008,2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -24,52 +24,102 @@
// executable file might be covered by the GNU General Public License.
#ifndef MLN_CLUSTERING_KMEAN2D_HH
-#define MLN_CLUSTERING_KMEAN2D_HH
+# define MLN_CLUSTERING_KMEAN2D_HH
/// \file
///
-/// \brief Implements the optimized kmean algorithm.
+/// \brief Implements the optimized kmean algorithm in 2d.
///
/// This algorithm is optimized in the way it proceeds directly with
/// the greylevel attribute inspite of the pixel attribute. The
/// algorithm is independant from the image dimension. But, we have to
/// compute one time the histogram. In fact, we move a recurrent cost
-/// to a fix cost in the complexity. This version is very adapted to
-/// images with small quantification.
-
-#include <limits.h>
-#include <iostream>
-#include <mln/trace/entering.hh>
-#include <mln/trace/exiting.hh>
-
-#include <mln/core/contract.hh>
-#include <mln/trait/value_.hh>
-#include <mln/accu/stat/histo2d.hh>
-
-#include <mln/math/min.hh>
-#include <mln/math/sqr.hh>
-#include <mln/norm/l2.hh>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/concept/image.hh>
-#include <mln/value/int_u.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/value/rg.hh>
-#include <mln/core/macros.hh>
-
-#include <mln/data/compute.hh>
-#include <mln/debug/println.hh>
-#include <mln/data/fill.hh>
-#include <mln/literal/zero.hh>
-#include <mln/literal/one.hh>
-#include <mln/labeling/colorize.hh>
-#include <mln/labeling/mean_values.hh>
-
-#include <mln/io/ppm/save.hh>
-#include <mln/io/pgm/save.hh>
-
-#include <mln/util/array.hh>
-#include <mln/algebra/vec.hh>
+/// by a fix cost in the complexity. This version is very adapted to
+/// images with small quantification. But, in 2d, the execution
+/// becomes very slow. It's just normal because the quantification is
+/// 8 bits per axis. So the actual histogram is bigger than the image.
+///
+/// Take care to the following point: The within variance is still a
+/// scalar value because we take the distance between two points and
+/// the result is a scalar from the geometrical point of view. An
+/// alternative implementation could study the variance/covariance
+/// matrix of each sub data clouds and works with the trace of the
+/// within variance matrix (as we do for the fisher criteria in N-d).
+///
+/// The following sample is a typical use of the new kmean implementation.
+///
+/// #include <iostream>
+/// #include <mln/clustering/kmean2d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb_to_rg.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/rg.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::rg<8> t_rg8;
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+/// typedef mln::image2d<t_rg8> t_image2d_rg8;
+/// typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+///
+/// t_image2d_rgb8 img_rgb8;
+/// t_image2d_rg8 img_rg8;
+///
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+///
+/// img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+///
+/// mln::clustering::kmean2d<double, 8> kmean(img_rg8, 3);
+///
+/// kmean.launch_n_times();
+///
+/// return 0;
+/// }
+
+# include <limits.h>
+# include <iostream>
+
+# include <mln/accu/stat/histo2d.hh>
+
+# include <mln/algebra/vec.hh>
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/contract.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/macros.hh>
+
+# include <mln/data/compute.hh>
+# include <mln/data/fill.hh>
+
+# include <mln/debug/println.hh>
+
+# include <mln/io/pgm/save.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <mln/labeling/colorize.hh>
+# include <mln/labeling/mean_values.hh>
+
+# include <mln/literal/one.hh>
+# include <mln/literal/zero.hh>
+
+# include <mln/math/min.hh>
+# include <mln/math/sqr.hh>
+# include <mln/norm/l2.hh>
+
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
+
+# include <mln/trait/value_.hh>
+
+# include <mln/util/array.hh>
+
+# include <mln/value/int_u.hh>
+# include <mln/value/rgb8.hh>
+# include <mln/value/rg.hh>
namespace mln
{
@@ -85,21 +135,22 @@ namespace mln
namespace clustering
{
+
/// \brief Implements the kmean algorithm in a specific way.
///
- /// This version of the kmean algorithm uses a greyscale image as input,
- /// temporary images for computations and produces images as result. Images
- /// play the role of matrix or vector in standard statistic algoritm.
+ /// This version of the kmean algorithm uses a 2-channels
+ /// (red/green channel) image as input, temporary images for
+ /// computations and produces images as result. Images play the
+ /// role of matrix or vector in standard statistic algoritm.
///
- /// T is the type used for computations (float or double).
- /// n is the quantification for the image grayscale.
+ /// Param T is the type used for computations (float or double).
+ /// Param n is the quantification for the image grayscale.
template <typename T, unsigned n>
struct kmean2d
{
/// Type definitions.
/// \brief A few type definitions to limit the refactoring impact.
///{
-
typedef value::rgb<8> t_rgb;
typedef value::label<8> t_label;
typedef value::rg<n> t_value;
@@ -108,7 +159,7 @@ namespace mln
typedef T t_result1d;
typedef algebra::vec<2,T> t_result2d;
- /// FIXME t_point n'est pas forcément une image 2d, bien au contraire.
+ /// \fixme t_point_img is not an image2d ... but it works like this ...
typedef image2d<t_value> t_point_img;
typedef image2d<unsigned> t_histo_img;
typedef util::array<t_result1d> t_number_img;
@@ -128,35 +179,24 @@ namespace mln
typedef util::array<t_mean_set> t_mean_cnv;
typedef image1d<t_result1d> t_variance_val;
typedef util::array<t_variance_val> t_variance_cnv;
-
///}
- //------------------------------------------------------------------------
- // Constructor
- //------------------------------------------------------------------------
-
- /// \brief Constructor
+ /// \brief Constructor.
/// \param[in] point : the image as the population of pixels.
/// \param[in] k_center : the number of centers.
/// \param[in] watch_dog : the limit to observe the convergence (10).
/// \param[in] n_times : the number of times that we executed kmean(10).
-
kmean2d(const t_point_img& point,
const unsigned k_center,
const unsigned watch_dog = 10,
const unsigned n_times = 10);
- //------------------------------------------------------------------------
- // Accessors
- //------------------------------------------------------------------------
-
- /// Mutator and accessors.
+ /// Mutators and accessors.
/// \{
/// \brief Mutator and accessors are required for debugging and testing.
///
/// Testing needs to hack the kmean loop process in order to verify each
/// step of the algorithm.
-
void set_point(t_point_img& point);
void set_histo(t_histo_img& histo);
void set_number(t_number_img& number);
@@ -187,10 +227,10 @@ namespace mln
/// \}
- //------------------------------------------------------------------------
- // Printing temporary results
- //------------------------------------------------------------------------
-
+ /// Show temporary results.
+ /// \{
+ /// \brief Formating temporary outputs for debugging.
+ ///
void print_mean();
void print_number();
void print_variance();
@@ -198,32 +238,18 @@ namespace mln
void print_group();
void print_point();
void print_histo();
-
- //------------------------------------------------------------------------
- // Initializations of centers
- //------------------------------------------------------------------------
+ /// \}
/// Initialization of centers.
/// \{
- /// \brief Two ways: Regular greylevel tick or random greylevel value or.
+ /// \brief Initialize centers by random position.
///
- /// There is two way to proceed the initialization. First of all, we
- /// divide the greyscale in regular tick and we assigne them to the mean
- /// of the centers. Finaly, we can ask random initialization along the
- /// greyscale axis. The second process is needed to launch_n_times the
- /// kmean and converge to the best descent.
-
+ /// Assign a random position in the 2-channel space to each center.
void init_mean();
- void init_mean_regular();
void init_mean_random();
-
/// \}
- //------------------------------------------------------------------------
- // Computations of distance, group, center, within variance
- //------------------------------------------------------------------------
-
/// Computations of distance, group, center, within variance.
/// \{
/// \brief Update the statistical information needed by the kmean process.
@@ -232,36 +258,27 @@ namespace mln
/// first compute. Then we assign the pixels to their nearest center.
/// The new location of each center can then update. Finaly, hommogeneity
/// in group is observed by the within variance.
-
void update_distance();
void update_group();
void update_mean();
void update_variance();
-
/// \}
- //------------------------------------------------------------------------
- // Main loop
- //------------------------------------------------------------------------
/// kmean main loop
/// \{
/// \brief User interface to launch the kmean process.
///
- /// There are two ways to launch the kmean process. The first one allow to
- /// run it one time until convergence. As the process is a descent, it
- /// depends on the initial center locations. The second call allow us to
- /// rerun the process many times and to keep the best result (the one
- /// with the smallest within variance).
-
+ /// There are two ways to launch the kmean process. The first
+ /// one allows to run it one time until convergence. As the
+ /// process is a descent, it depends on the initial center
+ /// location. The second call allow us to rerun the process
+ /// many times and to keep the best result (the one with the
+ /// smallest within variance).
void launch_one_time();
void launch_n_times();
-
/// \}
- //------------------------------------------------------------------------
- // Checking the validiy of the results
- //------------------------------------------------------------------------
/// Checking the validity of the results.
/// \{
@@ -269,16 +286,11 @@ namespace mln
///
/// After each launching the kmean process one time, we need to know if
/// the descent was successfull or not. The method is_valid_descent do it
- /// for us. The method looks for a bad center (a class with no greylevel
- /// associate to it) and a failure in the convergence.
-
+ /// for us. The method looks for a bad center (a class with no r/g color
+ /// associate to it) or a failure in the convergence.
bool is_descent_valid();
-
/// \}
- //------------------------------------------------------------------------
- // Debugging tools
- //------------------------------------------------------------------------
/// Debugging tools
/// \{
@@ -290,13 +302,11 @@ namespace mln
/// greylevel image. The update_cnv and finalize_cnv methods are used to
/// trace the convergence. They fill two images with the mean info and
/// the within variance info along the convergence and the tries.
-
void build_label_dbg();
void build_mean_dbg();
void build_all_dbg();
void update_cnv();
void finalize_cnv();
-
/// \}
@@ -313,13 +323,12 @@ namespace mln
/// kmean loop. As the kmean process is a descent, restarting the process
/// from different location will confort us in that we found a global
/// minima, not just a local one.
-
unsigned _k_center;
unsigned _watch_dog;
unsigned _n_times;
-
/// \}
+
/// Convergence information.
/// \{
/// \brief This information is used to follow the convergence.
@@ -337,16 +346,15 @@ namespace mln
/// again. The flag is_number_valid is set when a empty class
/// appears. This flag inhibit the process and force to restart
/// a try.
-
t_result1d _within_variance;
unsigned _current_step;
unsigned _current_launching;
bool _is_number_valid;
static const unsigned _N_TRIES = 3;
-
/// \}
+
/// Result of the kmean process.
/// \{
/// \brief The center location are the major results of the kmean process.
@@ -354,10 +362,11 @@ namespace mln
/// The kmean process result is composed by three information. The best
/// launching iteration, the best within variance obtained and the
/// location of the centers associated.
-
unsigned _launching_min;
t_result1d _variance_min;
t_mean_img _mean_min;
+ /// \}
+
/// Inputs.
/// \{
@@ -365,12 +374,11 @@ namespace mln
///
/// The point image is a saving data for the real inputs. In fact, we use
/// the histogram information in the optimized kmean process.
-
t_point_img _point;
t_histo_img _histo;
-
///\}
+
/// Centers description.
/// \{
/// \brief Centers are described by the first moment of their group.
@@ -381,27 +389,25 @@ namespace mln
/// convergence. The number of pixels is used as integrity indicator.
/// A center with no point is a non sense. Theses informations are updated
/// after each kmean iteration.
-
t_number_img _number; // k x 1
- t_mean_img _mean; // k x 1
+ t_mean_img _mean; // k x 2
t_variance_img _variance; // k x 1 within group
-
/// \}
+
/// Greylevels description.
/// \{
- /// \brief The information are concerned with the greylevel input image.
+ /// \brief The information are concerned with the 2-channel input image.
///
- /// The group image allow us to decide which greylevel (and of course
+ /// The group image allow us to decide which r/g value (and of course
/// which pixel) is assigned to a center. The distance image give us a
- /// clue on how a greylevel could contribute to a center. The summation
- /// over the greylevels of a center give us the within variance.
-
- t_group_img _group; // g x 1 because dim(t_value) = 1
- t_distance_img _distance; // label x graylevel
-
+ /// clue on how a r/g value could contribute to a center. The summation
+ /// over the r/g values of a center give us the within variance.
+ t_group_img _group; // g x 2 because dim(t_value) = 2
+ t_distance_img _distance; // label x r/g value
/// \}
+
/// Debugging, calibrating and testing results.
/// \{
/// \brief Some exports information to control the results.
@@ -412,14 +418,13 @@ namespace mln
/// label (assigned to the same center) in the image. The mean image
/// associate the mean of each pixel center to each pixel. We obtain thus
/// a rebuilded image.
-
t_label_dbg _label_dbg;
t_color_dbg _color_dbg;
t_mean_dbg _mean_dbg;
-
/// \}
- /// Debugging, calibrating and testing convergence.
+
+ /// Variance and center evolutions.
/// \{
/// \brief Trace the variance and the center evolution.
///
@@ -428,10 +433,8 @@ namespace mln
/// kmean loop or along the different launch. The variance_cnv is a trace
/// of the within variance along the kmean loop or along the different
/// launch.
-
t_mean_cnv _mean_cnv;
t_variance_cnv _variance_cnv;
-
/// \}
};
@@ -448,7 +451,7 @@ namespace mln
const unsigned watch_dog,
const unsigned n_times)
{
- trace::entering("mln::clustering::kmean2d::kmean2d");
+ trace::entering("mln::clustering::kmean2d::cstor");
mln_precondition(point.is_valid());
_k_center = k_center;
@@ -516,7 +519,7 @@ namespace mln
_mean_cnv.append(mean_set);
}
- trace::exiting("mln::clustering::kmean2d::kmean2d");
+ trace::exiting("mln::clustering::kmean2d::cstor");
}
//--------------------------------------------------------------------------
@@ -796,15 +799,15 @@ namespace mln
{
trace::entering("mln::clustering::kmean2d::print_histo");
- mln_piter(t_histo_img) rgb(_histo.domain());
+ mln_piter(t_histo_img) rg(_histo.domain());
- for_all(rgb)
+ for_all(rg)
{
- if (0 < _histo(rgb))
+ if (0 < _histo(rg))
{
- std::cout << "histo(r=" << rgb.row();
- std::cout << ", g=" << rgb.col();
- std::cout << ")= " << _histo(rgb);
+ std::cout << "histo(r=" << rg.row();
+ std::cout << ", g=" << rg.col();
+ std::cout << ")= " << _histo(rg);
std::cout << std::endl;
}
}
@@ -818,15 +821,15 @@ namespace mln
{
trace::entering("mln::clustering::kmean2d::print_group");
- mln_piter(t_group_img) rgb(_group.domain());
+ mln_piter(t_group_img) rg(_group.domain());
- for_all(rgb)
+ for_all(rg)
{
- if (0 < _histo(rgb))
+ if (0 < _histo(rg))
{
- std::cout << "group(r=" << rgb.row();
- std::cout << ", g=" << rgb.col();
- std::cout << ")= " << _group(rgb);
+ std::cout << "group(r=" << rg.row();
+ std::cout << ", g=" << rg.col();
+ std::cout << ")= " << _group(rg);
std::cout << std::endl;
}
}
@@ -844,16 +847,16 @@ namespace mln
for_all(l)
{
- mln_piter(t_distance_val) rgb(_distance[l.index_()].domain());
+ mln_piter(t_distance_val) rg(_distance[l.index_()].domain());
- for_all(rgb)
+ for_all(rg)
{
- if (0 < _histo(rgb))
+ if (0 < _histo(rg))
{
std::cout << "distance(l=" << l.index_();
- std::cout << ",r=" << rgb.row();
- std::cout << ", g=" << rgb.col();
- std::cout << ")= " << _distance[l.index_()](rgb);
+ std::cout << ",r=" << rg.row();
+ std::cout << ", g=" << rg.col();
+ std::cout << ")= " << _distance[l.index_()](rg);
std::cout << std::endl;
}
}
@@ -960,9 +963,9 @@ namespace mln
{
trace::entering("mln::clustering::kmean2d::update_group");
- mln_piter(t_group_img) rgb(_group.domain());
+ mln_piter(t_group_img) rg(_group.domain());
- for_all(rgb)
+ for_all(rg)
{
mln_eiter(t_distance_img) l(_distance);
t_result1d min = mln_max(t_result1d);
@@ -972,9 +975,9 @@ namespace mln
for_all(l)
{
- if (min > _distance[l.index_()](rgb))
+ if (min > _distance[l.index_()](rg))
{
- min = _distance[l.index_()](rgb);
+ min = _distance[l.index_()](rg);
label = l.index_();
}
@@ -984,7 +987,7 @@ namespace mln
//std::cout << "g = " << g << std::endl;
- _group(rgb) = label;
+ _group(rg) = label;
//std::cout << "group = " << _group(g) << std::endl;
//std::cout << "-----------" << std::endl;
}
@@ -998,8 +1001,6 @@ namespace mln
{
trace::entering("mln::clustering::kmean2d::update_mean");
- /// FIXME VERIFIER QUE L'ON PEUT OBTENIR UNE IMAGE EN NDG SIGNE
-
// avec g le niveau de gris (signed or not signed)
// w[g] la classe de g sous forme d'image
// h[g] l'histogramme de l'image sous forme d'image
@@ -1021,14 +1022,14 @@ namespace mln
_mean[em.index_()] = literal::zero;
}
- mln_piter(t_group_img) rgb(_group.domain());
+ mln_piter(t_group_img) rg(_group.domain());
- for_all(rgb)
+ for_all(rg)
{
// peut être faut-il le decomposer par composantes
- _mean[_group(rgb)][0] += rgb.row() * _histo(rgb);
- _mean[_group(rgb)][1] += rgb.col() * _histo(rgb);
- _number(_group(rgb)) += _histo(rgb);
+ _mean[_group(rg)][0] += rg.row() * _histo(rg);
+ _mean[_group(rg)][1] += rg.col() * _histo(rg);
+ _number(_group(rg)) += _histo(rg);
}
mln_eiter(t_mean_img) l(_mean);
@@ -1072,12 +1073,12 @@ namespace mln
{
_variance[l.index_()] = literal::zero;
- mln_piter(t_group_img) rgb(_group.domain());
+ mln_piter(t_group_img) rg(_group.domain());
- for_all(rgb)
+ for_all(rg)
{
- if (l.index_() == _group(rgb))
- _variance[l.index_()] += _distance[l.index_()](rgb);
+ if (l.index_() == _group(rg))
+ _variance[l.index_()] += _distance[l.index_()](rg);
}
_within_variance += _variance[l.index_()];
@@ -1334,7 +1335,7 @@ namespace mln
trace::exiting("mln::clustering::kmean2d::launch_n_times");
}
-#endif // ! MLN_INCLUDE_ONLY
+# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::clustering
diff --git a/scribo/sandbox/green/mln/clustering/kmean3d.hh b/scribo/sandbox/green/mln/clustering/kmean3d.hh
index fb1a8df..c35d2a7 100644
--- a/scribo/sandbox/green/mln/clustering/kmean3d.hh
+++ b/scribo/sandbox/green/mln/clustering/kmean3d.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008,2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -24,51 +24,102 @@
// executable file might be covered by the GNU General Public License.
#ifndef MLN_CLUSTERING_KMEAN3D_HH
-#define MLN_CLUSTERING_KMEAN3D_HH
+# define MLN_CLUSTERING_KMEAN3D_HH
/// \file
///
-/// \brief Implements the optimized kmean algorithm.
+/// \brief Implements the optimized kmean algorithm in 3d.
///
/// This algorithm is optimized in the way it proceeds directly with
-/// the rgb values inspite of the pixel attribute. The
+/// the rgb value inspite of the pixel attribute. The
/// algorithm is independant from the image dimension. But, we have to
/// compute one time the histogram. In fact, we move a recurrent cost
-/// to a fix cost in the complexity. This version is adapted to
-/// image with small quantification.
-
-#include <limits.h>
-#include <iostream>
-#include <mln/trace/entering.hh>
-#include <mln/trace/exiting.hh>
-
-#include <mln/core/contract.hh>
-#include <mln/trait/value_.hh>
-#include <mln/accu/stat/histo3d_rgb.hh>
-
-#include <mln/math/min.hh>
-#include <mln/math/sqr.hh>
-#include <mln/norm/l2.hh>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/concept/image.hh>
-#include <mln/value/int_u.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/core/macros.hh>
-
-#include <mln/data/compute.hh>
-#include <mln/debug/println.hh>
-#include <mln/data/fill.hh>
-#include <mln/literal/zero.hh>
-#include <mln/literal/one.hh>
-#include <mln/labeling/colorize.hh>
-#include <mln/labeling/mean_values.hh>
-
-#include <mln/io/ppm/save.hh>
-#include <mln/io/pgm/save.hh>
-
-#include <mln/util/array.hh>
-#include <mln/algebra/vec.hh>
+/// by a fix cost in the complexity. This version is very adapted to
+/// images with small quantification. But, in 3d, the execution
+/// becomes very slow. It's just normal because the quantification is
+/// n bits per axis. So the actual histogram may be bigger than the image.
+///
+/// Take care to the following point: The within variance is still a
+/// scalar value because we take the distance between two points and
+/// the result is a scalar from the geometrical point of view. An
+/// alternative implementation could study the variance/covariance
+/// matrix of each sub data clouds and works with the trace of the
+/// within variance matrix (as we do for the fisher criteria in N-d).
+///
+/// The following sample is a typical use of the new kmean implementation.
+///
+/// #include <iostream>
+/// #include <mln/clustering/kmean3d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb8_to_rgbn.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/rgb.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::clustering::kmean3d<double,5> t_kmean;
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::value::rgb<5> t_rgb5;
+/// typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+/// typedef mln::image2d<t_rgb5> t_image2d_rgb5;
+/// typedef mln::fun::v2v::rgb8_to_rgbn<5> t_rgb8_to_rgb5;
+///
+/// t_image2d_rgb8 img_rgb8;
+/// t_image2d_rgb5 img_rgb5;
+///
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+///
+/// img_rgb5=mln::data::transform(img_rgb8, t_rgb8_to_rgb5());
+///
+/// t_kmean kmean(img_rgb5, 3);
+///
+/// kmean.launch_n_times();
+///
+/// return 0;
+/// }
+
+# include <limits.h>
+# include <iostream>
+
+# include <mln/accu/stat/histo3d_rgb.hh>
+
+# include <mln/algebra/vec.hh>
+
+# include <mln/math/min.hh>
+# include <mln/math/sqr.hh>
+# include <mln/norm/l2.hh>
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/contract.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/macros.hh>
+
+# include <mln/data/compute.hh>
+# include <mln/data/fill.hh>
+# include <mln/debug/println.hh>
+
+# include <mln/labeling/colorize.hh>
+# include <mln/labeling/mean_values.hh>
+
+# include <mln/literal/one.hh>
+# include <mln/literal/zero.hh>
+
+# include <mln/io/ppm/save.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
+
+# include <mln/trait/value_.hh>
+
+# include <mln/util/array.hh>
+
+# include <mln/value/int_u.hh>
+# include <mln/value/rgb8.hh>
+
namespace mln
{
@@ -98,7 +149,6 @@ namespace mln
/// Type definitions.
/// \brief A few type definitions to limit the refactoring impact.
///{
-
typedef value::rgb<8> t_rgb;
typedef value::label<8> t_label;
typedef value::rgb<n> t_value;
@@ -108,7 +158,7 @@ namespace mln
typedef T t_result1d;
typedef algebra::vec<3,T> t_result3d;
- /// FIXME t_point n'est pas forcément une image 2d, bien au contraire.
+ /// \fixme t_point is not an image2d, it may be something else ...
typedef image2d<t_value> t_point_img;
typedef image3d<unsigned> t_histo_img;
typedef util::array<t_result1d> t_number_img;
@@ -128,35 +178,26 @@ namespace mln
typedef util::array<t_mean_set> t_mean_cnv;
typedef image1d<t_result1d> t_variance_val;
typedef util::array<t_variance_val> t_variance_cnv;
-
///}
- //------------------------------------------------------------------------
- // Constructor
- //------------------------------------------------------------------------
- /// \brief Constructor
+ /// \brief Constructor.
+ ///
/// \param[in] point : the image as the population of pixels.
/// \param[in] k_center : the number of centers.
/// \param[in] watch_dog : the limit to observe the convergence (10).
/// \param[in] n_times : the number of times that we executed kmean(10).
-
kmean3d(const t_point_img& point,
const unsigned k_center,
const unsigned watch_dog = 10,
const unsigned n_times = 10);
- //------------------------------------------------------------------------
- // Accessors
- //------------------------------------------------------------------------
-
- /// Mutator and accessors.
+ /// Mutators and accessors.
/// \{
/// \brief Mutator and accessors are required for debugging and testing.
///
/// Testing needs to hack the kmean loop process in order to verify each
/// step of the algorithm.
-
void set_point(t_point_img& point);
void set_histo(t_histo_img& histo);
void set_number(t_number_img& number);
@@ -184,13 +225,13 @@ namespace mln
// Normal outputs
t_mean_img& to_result();
-
/// \}
- //------------------------------------------------------------------------
- // Printing temporary results
- //------------------------------------------------------------------------
+ /// Show temporary results.
+ /// \{
+ /// \brief Formating temporary outputs for debugging.
+ ///
void print_mean();
void print_number();
void print_variance();
@@ -198,32 +239,19 @@ namespace mln
void print_group();
void print_point();
void print_histo();
+ /// \}
- //------------------------------------------------------------------------
- // Initializations of centers
- //------------------------------------------------------------------------
/// Initialization of centers.
/// \{
- /// \brief Two ways: Regular greylevel tick or random greylevel value or.
+ /// \brief Initialize centers by random position.
///
- /// There is two way to proceed the initialization. First of all, we
- /// divide the rgb space in regular tick and we assigne them to the mean
- /// of the centers. Finaly, we can ask random initialization along the
- /// greyscale axis. The second process is needed to launch_n_times the
- /// kmean and converge to the best descent.
-
+ /// Assign a random position in the rgb space to each center.
void init_mean();
- void init_mean_regular();
void init_mean_random();
-
/// \}
- //------------------------------------------------------------------------
- // Computations of distance, group, center, within variance
- //------------------------------------------------------------------------
-
/// Computations of distance, group, center, within variance.
/// \{
/// \brief Update the statistical information needed by the kmean process.
@@ -232,36 +260,27 @@ namespace mln
/// first compute. Then we assign the pixels to their nearest center.
/// The new location of each center can then update. Finaly, hommogeneity
/// in group is observed by the within variance.
-
void update_distance();
void update_group();
void update_mean();
void update_variance();
-
/// \}
- //------------------------------------------------------------------------
- // Main loop
- //------------------------------------------------------------------------
/// kmean main loop
/// \{
/// \brief User interface to launch the kmean process.
///
- /// There are two ways to launch the kmean process. The first one allow to
- /// run it one time until convergence. As the process is a descent, it
- /// depends on the initial center locations. The second call allow us to
- /// rerun the process many times and to keep the best result (the one
- /// with the smallest within variance).
-
+ /// There are two ways to launch the kmean process. The first
+ /// one allows to run it one time until convergence. As the
+ /// process is a descent, it depends on the initial center
+ /// location. The second call allow us to rerun the process
+ /// many times and to keep the best result (the one with the
+ /// smallest within variance).
void launch_one_time();
void launch_n_times();
-
/// \}
- //------------------------------------------------------------------------
- // Checking the validiy of the results
- //------------------------------------------------------------------------
/// Checking the validity of the results.
/// \{
@@ -271,32 +290,22 @@ namespace mln
/// the descent was successfull or not. The method is_valid_descent do it
/// for us. The method looks for a bad center (a class with no greylevel
/// associate to it) and a failure in the convergence.
-
bool is_descent_valid();
-
/// \}
- //------------------------------------------------------------------------
- // Debugging tools
- //------------------------------------------------------------------------
-
- /// Debugging tools
+ /// Checking the validity of the results.
/// \{
- /// \brief These methods help to interpret results.
+ /// \brief These methods help us to determine the validity of the results.
///
- /// The methods build_label_dbg and build_all_dbg work in the input data
- /// space. The first one build the 2d image of labels. The second call the
- /// first one and then builds the colorize label' image and the mean
- /// greylevel image. The update_cnv and finalize_cnv methods are used to
- /// trace the convergence. They fill two images with the mean info and
- /// the within variance info along the convergence and the tries.
-
+ /// After each launching the kmean process one time, we need to know if
+ /// the descent was successfull or not. The method is_valid_descent do it
+ /// for us. The method looks for a bad center (a class with no color
+ /// associate to it) or a failure in the convergence.
void build_label_dbg();
void build_mean_dbg();
void build_all_dbg();
void update_cnv();
void finalize_cnv();
-
/// \}
@@ -313,13 +322,12 @@ namespace mln
/// kmean loop. As the kmean process is a descent, restarting the process
/// from different location will confort us in that we found a global
/// minima, not just a local one.
-
unsigned _k_center;
unsigned _watch_dog;
unsigned _n_times;
-
/// \}
+
/// Convergence information.
/// \{
/// \brief This information is used to follow the convergence.
@@ -337,14 +345,12 @@ namespace mln
/// again. The flag is_number_valid is set when a empty class
/// appears. This flag inhibit the process and force to restart
/// a try.
-
t_result1d _within_variance;
unsigned _current_step;
unsigned _current_launching;
bool _is_number_valid;
static const unsigned _N_TRIES = 3;
-
/// \}
/// Result of the kmean process.
@@ -354,10 +360,10 @@ namespace mln
/// The kmean process result is composed by three information. The best
/// launching iteration, the best within variance obtained and the
/// location of the centers associated.
-
unsigned _launching_min;
t_result1d _variance_min;
t_mean_img _mean_min;
+ /// \}
/// Inputs.
/// \{
@@ -365,12 +371,11 @@ namespace mln
///
/// The point image is a saving data for the real inputs. In fact, we use
/// the histogram information in the optimized kmean process.
-
t_point_img _point;
t_histo_img _histo;
-
///\}
+
/// Centers description.
/// \{
/// \brief Centers are described by the first moment of their group.
@@ -381,11 +386,9 @@ namespace mln
/// convergence. The number of pixels is used as integrity indicator.
/// A center with no point is a non sense. Theses informations are updated
/// after each kmean iteration.
-
t_number_img _number; // k x 1
- t_mean_img _mean; // k x 1
+ t_mean_img _mean; // k x 3
t_variance_img _variance; // k x 1 within group
-
/// \}
/// rgb image description.
@@ -396,12 +399,11 @@ namespace mln
/// which pixel) is assigned to a center. The distance image give us a
/// clue on how a greylevel could contribute to a center. The summation
/// over the rgb space of a center give us the within variance.
-
t_group_img _group; // g x 3 because dim(t_value) = 3
t_distance_img _distance; // label x rgb space
-
/// \}
+
/// Debugging, calibrating and testing results.
/// \{
/// \brief Some exports information to control the results.
@@ -412,14 +414,12 @@ namespace mln
/// label (assigned to the same center) in the image. The mean image
/// associate the mean of each pixel center to each pixel. We obtain thus
/// a rebuilded image.
-
t_label_dbg _label_dbg;
t_color_dbg _color_dbg;
t_mean_dbg _mean_dbg;
-
/// \}
- /// Debugging, calibrating and testing convergence.
+ /// Variance and center evolutions.
/// \{
/// \brief Trace the variance and the center evolution.
///
@@ -428,10 +428,8 @@ namespace mln
/// kmean loop or along the different launch. The variance_cnv is a trace
/// of the within variance along the kmean loop or along the different
/// launch.
-
t_mean_cnv _mean_cnv;
t_variance_cnv _variance_cnv;
-
/// \}
};
@@ -448,7 +446,7 @@ namespace mln
const unsigned watch_dog,
const unsigned n_times)
{
- trace::entering("mln::clustering::kmean3d::kmean3d");
+ trace::entering("mln::clustering::kmean3d::cstor");
mln_precondition(point.is_valid());
_k_center = k_center;
@@ -520,7 +518,7 @@ namespace mln
_mean_cnv.append(mean_set);
}
- trace::exiting("mln::clustering::kmean3d::kmean3d");
+ trace::exiting("mln::clustering::kmean3d::cstor");
}
//--------------------------------------------------------------------------
@@ -1338,7 +1336,7 @@ namespace mln
trace::exiting("mln::clustering::kmean3d::launch_n_times");
}
-#endif // ! MLN_INCLUDE_ONLY
+# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::clustering
diff --git a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh b/scribo/sandbox/green/mln/clustering/kmean_rgb.hh
index 253745b..544066b 100644
--- a/scribo/sandbox/green/mln/clustering/kmean_rgb.hh
+++ b/scribo/sandbox/green/mln/clustering/kmean_rgb.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008,2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -28,16 +28,68 @@
/// \file
///
-/// \brief Implements the optimized kmean algorithm.
+/// \brief Implements the optimized kmean algorithm in the 3d-RGB space.
///
/// This algorithm is optimized in the way it proceeds directly with
-/// the rgb values inspite of the pixel attribute. The
+/// the rgb value inspite of the pixel attribute. The
/// algorithm is independant from the image dimension. But, we have to
/// compute one time the histogram. In fact, we move a recurrent cost
-/// to a fix cost in the complexity. This version is adapted to
-/// image with small quantification.
-
-/// APLATISSEMENT DES KMEAN3D
+/// by a fix cost in the complexity. This version is very adapted to
+/// images with small quantification. But, in 3d, the execution
+/// becomes very slow. It's just normal because the quantification is
+/// n bits per axis. So the actual histogram may be bigger than the image.
+///
+/// Take care to the following point: The within variance is still a
+/// scalar value because we take the distance between two points and
+/// the result is a scalar from the geometrical point of view. An
+/// alternative implementation could study the variance/covariance
+/// matrix of each sub data clouds and works with the trace of the
+/// within variance matrix (as we do for the fisher criteria in N-d).
+///
+/// The following sample is a typical use of the functional (versus
+/// object) kmean implementation.
+///
+/// #include <iostream>
+/// #include <mln/clustering/kmean_rgb.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb8_to_rgbn.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/label_8.hh>
+/// #include <mln/value/rgb.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::label_8 t_lbl8;
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::value::rgb<5> t_rgb5;
+/// typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+/// typedef mln::image2d<t_rgb5> t_image2d_rgb5;
+/// typedef mln::image2d<t_lbl8> t_image2d_lbl8;
+/// typedef mln::fun::v2v::rgb8_to_rgbn<5> t_rgb8_to_rgb5;
+///
+/// t_image2d_rgb8 img_rgb8;
+/// t_image2d_rgb5 img_rgb5;
+/// t_image2d_lbl8 img_lbl8;
+///
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+///
+/// img_rgb5 = mln::data::transform(img_rgb8, t_rgb8_to_rgb5());
+/// img_lbl8 = mln::clustering::kmean_rgb<double,5>(img_rgb5, 3);
+///
+/// return 0;
+/// }
+///
+/// \fixme The execution shows a bug in printing outputs and it seems severe.
+///
+/// The last execution with the following set of parameters
+/// {house.ppm,3,10,10} shows that if the binary starts correctly, it
+/// ends before returning the label image and with disturbing outputs.
+/// Dumping the outputs in a file reveals that the number of
+/// trace::entering differs from the number of trace::exiting. May the
+/// program exit from a loop without ending a trace ???
# include <limits.h>
# include <iostream>
@@ -86,7 +138,7 @@
//--------------------------------------------------------------------------
-// CODE APLATI
+// FUNCTIONAL CODE
//--------------------------------------------------------------------------
@@ -95,7 +147,24 @@ namespace mln
namespace clustering
{
-
+ /// \brief Implements the functional kmean algorithm.
+ ///
+ /// This functional version of the kmean is very specific. All the
+ /// code is view as a one-block function. This code is provided as
+ /// is. I (YJ) don't know where i stopped this version. It may not
+ /// work. Debugging tools are not yet provided. This code is just
+ /// the functional transcription of the kmean3d version. The code
+ /// has the very experimental status.
+ ///
+ /// T is the type used for computations (float or double).
+ /// n is the quantification for the rgb image.
+ ///
+ /// \param[in] point : the image as the population of pixels.
+ /// \param[in] k_center : the number of centers.
+ /// \param[in] watch_dog : the limit to observe the convergence (10).
+ /// \param[in] n_times : the number of times that we executed kmean(10).
+ ///
+ /// \return an image which represents the pixel classification.
template <typename T, unsigned n, typename I>
inline
image2d<value::label_8>
diff --git a/scribo/sandbox/green/mln/fun/v2v/rg_to_rgb.hh b/scribo/sandbox/green/mln/fun/v2v/rg_to_rgb.hh
index ca7ba51..e89edad 100644
--- a/scribo/sandbox/green/mln/fun/v2v/rg_to_rgb.hh
+++ b/scribo/sandbox/green/mln/fun/v2v/rg_to_rgb.hh
@@ -1,6 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -34,7 +32,51 @@
/// \file
///
-/// \brief Convert rg value to rgb
+/// \brief Convert a rg value to a rgb value.
+///
+/// This source implements the conversion between rg space and rgb space.
+///
+/// The following sample is a typical use of the rg/rgb conversion function.
+///
+/// #include <iostream>
+/// #include <mln/clustering/kmean2d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb_to_rg.hh>
+/// #include <mln/fun/v2v/rg_to_rgb.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/rg.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::rg<8> t_rg8;
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+/// typedef mln::image2d<t_rg8> t_image2d_rg8;
+/// typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+/// typedef mln::fun::v2v::rg_to_rgb<8> t_rg_to_rgb;
+///
+/// t_image2d_rgb8 img_rgb8;
+/// t_image2d_rgb8 point_img_rgb8;
+/// t_image2d_rg8 img_rg8;
+///
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+///
+/// img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+///
+/// mln::clustering::kmean2d<double, 8> kmean(img_rg8, 3);
+///
+/// kmean.launch_n_times();
+///
+/// mln::clustering::kmean2d<double,8>::t_point_img point_img =
+/// kmean.get_point();
+///
+/// point_img_rgb8 = mln::data::transform(point_img, t_rg_to_rgb());
+///
+/// return 0;
+/// }
namespace mln
{
@@ -47,14 +89,21 @@ namespace mln
/// \brief Convert rg value to rgb.
///
+ /// Param n defines the quantification used for rgb space and rg space.
+ ///
/// \ingroup modfunv2v
-
template <unsigned n>
struct rg_to_rgb : Function_v2v< rg_to_rgb<n> >
{
typedef value::rg<n> argument;
typedef value::rgb<n> result;
+ /// \brief Convert rg value to rgb value.
+ ///
+ /// \param[in] v the rg value to convert.
+ ///
+ /// Conversion is done by calling the rgb constructor and fill
+ /// the empty attirbute by 127.
result operator()(const argument& v) const
{
return value::rgb<n>(v.red(), v.green(), 127);
diff --git a/scribo/sandbox/green/tests/clustering/k_mean/Makefile.am b/scribo/sandbox/green/tests/clustering/k_mean/Makefile.am
index 5f00678..77f9015 100644
--- a/scribo/sandbox/green/tests/clustering/k_mean/Makefile.am
+++ b/scribo/sandbox/green/tests/clustering/k_mean/Makefile.am
@@ -6,8 +6,13 @@
# TOOLS #
#########
-INCLUDES= -I$(HOME)/svn/oln/trunk/milena/sandbox/green
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
ECHO= echo
RM= rm
MKDIR= mkdir -p
@@ -20,10 +25,10 @@ BUILD__PATTERN= green/build/tests
ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
# Case where make is done from build directory.
SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
-BUILD__DIR= $(PWD)
+BUILD__DIR= $(PWD)/
else
# Case where make is done from source directory.
-SOURCE_DIR= $(PWD)
+SOURCE_DIR= $(PWD)/
BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
endif
@@ -89,7 +94,7 @@ $(OBJ_F_PATH):$(SRC_F_PATH)
#########
# Force every time the deletion
-clean: print clean_target clean_obj clean_dst clean_old #clean_make
+clean: clean_target clean_obj clean_dst clean_old #clean_make
clean_target:
diff --git a/scribo/sandbox/green/tests/clustering/k_mean/k_mean.cc b/scribo/sandbox/green/tests/clustering/k_mean/k_mean.cc
index 27751fd..a839ece 100644
--- a/scribo/sandbox/green/tests/clustering/k_mean/k_mean.cc
+++ b/scribo/sandbox/green/tests/clustering/k_mean/k_mean.cc
@@ -1,34 +1,68 @@
-// UNARY TESTS ON K_MEAN
-
-#include <mln/clustering/k_mean.hh>
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief This source manages unitary testing on the kmean implementation.
+///
+/// Tests are performed from 2 bits up to 8 bits quantification. The goal
+/// is to go through each programmatic flow to verify the conformity of the
+/// code. It sounds like a theoritic model of unitary testing for milena.
+/// The last test enables statistic computations on that component.
#include <iostream>
-#include <mln/pw/value.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-
#include <mln/literal/colors.hh>
#include <mln/algebra/vec.hh>
#include <mln/algebra/mat.hh>
+#include <mln/clustering/k_mean.hh>
+
#include <mln/core/macros.hh>
#include <mln/core/contract.hh>
#include <mln/core/image/image2d.hh>
#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/img_path.hh>
+
#include <mln/io/ppm/load.hh>
#include <mln/io/pgm/load.hh>
#include <mln/io/pgm/save.hh>
#include <mln/io/ppm/save.hh>
-#include <mln/data/transform.hh>
-
#include <mln/trait/value/print.hh>
#include <mln/trait/image/print.hh>
+#include <mln/pw/value.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+
#define SIZE_IMAGE 512
#define SIZE_SAMPLE1 (512*512)
#define SIZE_SAMPLE2 4
@@ -44,20 +78,18 @@
#define MAT_GROUP2 mln::algebra::mat<SIZE_SAMPLE2, NB_CENTER, TYPE_POINT>
#define VEC_VAR mln::algebra::vec<NB_CENTER, TYPE_POINT>
-
-void test_instantiation()
-{
- mln::clustering::k_mean<SIZE_SAMPLE2,NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
-
- // test the compilation
-
- std::cout << "test instantiation : ok" << std::endl;
-}
+/// Tools.
+/// \{
+/// \brief Define some tools which are used in unitary testing.
+///
+/// This kind of tools help to fill an image with only 4 tons or
+/// computing a distance between two colors. Just keep an eye, nothing
+/// really difficult in this code.
struct rgb8_to_4colors : mln::Function_v2v<rgb8_to_4colors>
{
typedef mln::value::rgb8 result;
-
+
mln::value::rgb8 operator()(const mln::value::rgb8& color) const
{
mln::value::rgb8 result;
@@ -78,11 +110,12 @@ struct rgb8_to_4colors : mln::Function_v2v<rgb8_to_4colors>
void print_color(const mln::value::rgb8& color)
{
- std::cout << "{r=" << color.red() << ", ";
+ std::cout << "{r=" << color.red() << ", ";
std::cout << "g=" << color.green() << ", ";
std::cout << "b=" << color.blue() << "}" << std::endl;
}
+
void fill_image_with_4colors(mln::image2d<mln::value::rgb8>& img)
{
const mln::value::rgb8 lime = mln::literal::lime;
@@ -98,6 +131,140 @@ void fill_image_with_4colors(mln::image2d<mln::value::rgb8>& img)
//print_color(purple);
}
+
+double dist(mln::value::rgb8 color1, mln::value::rgb8 color2)
+{
+ double red = color1.red() - color2.red();
+ double green = color1.green() - color2.green();
+ double blue = color1.blue() - color2.blue();
+ double result= red * red + green * green + blue * blue;
+
+ return result;
+}
+
+/// \}
+
+
+/// External mutators.
+/// \{
+/// \brief Replace the kmean data structure values.
+///
+/// This is a hack that provides low level routines to access key data
+/// structure like point, center, distance and group.
+
+void set_point(MAT_POINT2& point,
+ const unsigned index,
+ const mln::value::rgb8& color)
+{
+ point(index,0) = color.red();
+ point(index,1) = color.green();
+ point(index,2) = color.blue();
+}
+
+void set_center(MAT_CENTER& center,
+ const unsigned index,
+ const mln::value::rgb8& color)
+{
+ center(index,0) = color.red();
+ center(index,1) = color.green();
+ center(index,2) = color.blue();
+}
+
+void set_distance(MAT_DISTANCE2& distance,
+ const unsigned index,
+ const double d1,
+ const double d2)
+{
+ distance(index,0) = d1;
+ distance(index,1) = d2;
+}
+
+void set_group(MAT_GROUP2& group,
+ const unsigned index,
+ const unsigned min)
+{
+ group(index, min) = 1.0;
+ group(index, 1-min) = 0.0;
+}
+
+/// \}
+
+/// Fake states.
+/// \{
+/// \brief Help to build from scratch temporary states for the kmean algorithm.
+///
+/// This hack allow us to build temporary results used in the previous step to
+/// make us very the behaviour of the current step. There is a fake state for
+/// every key data structure (point, group, center and distance).
+
+void fake_init_point(MAT_POINT2& point,
+ const mln::value::rgb8& point1,
+ const mln::value::rgb8& point2,
+ const mln::value::rgb8& point3,
+ const mln::value::rgb8& point4)
+{
+ set_point(point, 0, point1);
+ set_point(point, 1, point2);
+ set_point(point, 2, point3);
+ set_point(point, 3, point4);
+}
+
+
+void fake_update_group(MAT_GROUP2& group,
+ const unsigned& point1_min,
+ const unsigned& point2_min,
+ const unsigned& point3_min,
+ const unsigned& point4_min)
+{
+ set_group(group, 0, point1_min);
+ set_group(group, 1, point2_min);
+ set_group(group, 2, point3_min);
+ set_group(group, 3, point4_min);
+}
+
+
+void fake_init_center(MAT_CENTER& center,
+ const mln::value::rgb8 center1,
+ const mln::value::rgb8 center2)
+{
+
+ set_center(center, 0, center1);
+ set_center(center, 1, center2);
+}
+
+
+
+
+void fake_update_distance(MAT_DISTANCE2& distance,
+ const mln::value::rgb8& point1,
+ const mln::value::rgb8& point2,
+ const mln::value::rgb8& point3,
+ const mln::value::rgb8& point4,
+ const mln::value::rgb8& center1,
+ const mln::value::rgb8& center2)
+{
+ set_distance(distance, 0, dist(point1, center1), dist(point1, center2));
+ set_distance(distance, 1, dist(point2, center1), dist(point2, center2));
+ set_distance(distance, 2, dist(point3, center1), dist(point3, center2));
+ set_distance(distance, 3, dist(point4, center1), dist(point4, center2));
+
+ /*
+ for (int i = 0; i < SIZE_SAMPLE2; ++i)
+ for (int j = 0; j < NB_CENTER; ++j)
+ std::cout << "d(" << i << "," << j << ") = " << distance(i,j) <<std::endl;
+ */
+}
+
+/// \}
+
+/// Equivalence.
+/// \{
+/// \brief Test equivalence between point and image, center and color.
+///
+/// Two kinds of equivalence are defined here. The first one tests the
+/// equality between the data cloud and the initial image, while the
+/// second one tests the equality between a center and a color.
+
bool is_equivalent(const mln::image2d<mln::value::rgb8>& img,
const MAT_POINT1& point)
{
@@ -118,11 +285,11 @@ bool is_equivalent(const mln::image2d<mln::value::rgb8>& img,
if (!test)
{
std::cout << pi;
- std::cout << "{r=" << img(pi).red() << ", ";
+ std::cout << "{r=" << img(pi).red() << ", ";
std::cout << "g=" << img(pi).green() << ", ";
std::cout << "b=" << img(pi).blue() << "}";
std::cout << index;
- std::cout << "[r=" << point(index,0) << ", ";
+ std::cout << "[r=" << point(index,0) << ", ";
std::cout << "g=" << point(index,1) << ", ";
std::cout << "b=" << point(index,2) << "]" << std::endl;
@@ -135,6 +302,44 @@ bool is_equivalent(const mln::image2d<mln::value::rgb8>& img,
return result;
}
+bool is_equal(const mln::value::rgb8& ref,
+ const MAT_CENTER& center,
+ const unsigned i)
+{
+ bool result = true;
+
+ result = result && (center(i, 0) - ref.red() < 1.0);
+ result = result && (center(i, 1) - ref.green() < 1.0);
+ result = result && (center(i, 2) - ref.blue() < 1.0);
+
+ return result;
+}
+
+/// \}
+
+
+/// kmean unitary testing
+/// \{
+/// \brief This part of the code manages the unitary testing.
+///
+/// Many tests are performed and new kind of unitary testing
+/// appears. In fact, we must simulate the previous steps of the line
+/// currently testing and so making some fake steps. Bad and deep
+/// hacking in data structure are required. We test the instantiation
+/// of the kmean object, its initialization (points and centers), its
+/// core routines (update_center, update_group, update_distance,
+/// update_variance) and the final loop.
+
+void test_instantiation()
+{
+ mln::clustering::k_mean<SIZE_SAMPLE2,NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
+
+ // test the compilation
+
+ std::cout << "test instantiation : ok" << std::endl;
+}
+
+
void test_init_point()
{
typedef mln::value::rgb8 rgb8;
@@ -147,45 +352,12 @@ void test_init_point()
fill_image_with_4colors(img_ref);
kmean.init_point(img_ref);
-
+
mln_assertion(true == is_equivalent(img_ref, kmean.get_point()));
std::cout << "Test init point : ok" << std::endl;
}
-void set_point(MAT_POINT2& point,
- const unsigned index,
- const mln::value::rgb8& color)
-{
- point(index,0) = color.red();
- point(index,1) = color.green();
- point(index,2) = color.blue();
-}
-
-void fake_init_point(MAT_POINT2& point,
- const mln::value::rgb8& point1,
- const mln::value::rgb8& point2,
- const mln::value::rgb8& point3,
- const mln::value::rgb8& point4)
-{
- set_point(point, 0, point1);
- set_point(point, 1, point2);
- set_point(point, 2, point3);
- set_point(point, 3, point4);
-}
-
-bool is_equal(const mln::value::rgb8& ref,
- const MAT_CENTER& center,
- const unsigned i)
-{
- bool result = true;
-
- result = result && (center(i, 0) - ref.red() < 1.0);
- result = result && (center(i, 1) - ref.green() < 1.0);
- result = result && (center(i, 2) - ref.blue() < 1.0);
-
- return result;
-}
void test_init_center()
{
@@ -195,10 +367,10 @@ void test_init_center()
const mln::value::rgb8 brown = mln::literal::brown;
const mln::value::rgb8 teal = mln::literal::teal;
const mln::value::rgb8 purple = mln::literal::purple;
-
+
fake_init_point(kmean.get_point(), lime, brown, teal, purple);
kmean.init_center();
-
+
mln_assertion(is_equal(lime, kmean.get_center(), 0) ||
is_equal(brown, kmean.get_center(), 0) ||
is_equal(teal, kmean.get_center(), 0) ||
@@ -212,34 +384,6 @@ void test_init_center()
std::cout << "Test init center : ok" << std::endl;
}
-void set_center(MAT_CENTER& center,
- const unsigned index,
- const mln::value::rgb8& color)
-{
- center(index,0) = color.red();
- center(index,1) = color.green();
- center(index,2) = color.blue();
-}
-
-void fake_init_center(MAT_CENTER& center,
- const mln::value::rgb8 center1,
- const mln::value::rgb8 center2)
-{
-
- set_center(center, 0, center1);
- set_center(center, 1, center2);
-}
-
-
-double dist(mln::value::rgb8 color1, mln::value::rgb8 color2)
-{
- double red = color1.red() - color2.red();
- double green = color1.green() - color2.green();
- double blue = color1.blue() - color2.blue();
- double result= red * red + green * green + blue * blue;
-
- return result;
-}
void test_update_distance()
{
@@ -269,34 +413,6 @@ void test_update_distance()
std::cout << "Test update distance : ok" << std::endl;
}
-void set_distance(MAT_DISTANCE2& distance,
- const unsigned index,
- const double d1,
- const double d2)
-{
- distance(index,0) = d1;
- distance(index,1) = d2;
-}
-
-void fake_update_distance(MAT_DISTANCE2& distance,
- const mln::value::rgb8& point1,
- const mln::value::rgb8& point2,
- const mln::value::rgb8& point3,
- const mln::value::rgb8& point4,
- const mln::value::rgb8& center1,
- const mln::value::rgb8& center2)
-{
- set_distance(distance, 0, dist(point1, center1), dist(point1, center2));
- set_distance(distance, 1, dist(point2, center1), dist(point2, center2));
- set_distance(distance, 2, dist(point3, center1), dist(point3, center2));
- set_distance(distance, 3, dist(point4, center1), dist(point4, center2));
-
- /*
- for (int i = 0; i < SIZE_SAMPLE2; ++i)
- for (int j = 0; j < NB_CENTER; ++j)
- std::cout << "d(" << i << "," << j << ") = " << distance(i,j) <<std::endl;
- */
-}
void test_update_group()
{
@@ -331,26 +447,6 @@ void test_update_group()
std::cout << "Test update group : ok" << std::endl;
}
-void set_group(MAT_GROUP2& group,
- const unsigned index,
- const unsigned min)
-{
- group(index, min) = 1.0;
- group(index, 1-min) = 0.0;
-}
-
-
-void fake_update_group(MAT_GROUP2& group,
- const unsigned& point1_min,
- const unsigned& point2_min,
- const unsigned& point3_min,
- const unsigned& point4_min)
-{
- set_group(group, 0, point1_min);
- set_group(group, 1, point2_min);
- set_group(group, 2, point3_min);
- set_group(group, 3, point4_min);
-}
void test_update_center()
{
@@ -374,13 +470,14 @@ void test_update_center()
fake_update_distance(kmean.get_distance(), lime, brown, teal, purple, c1, c2);
fake_update_group(kmean.get_group(), pt1_min, pt2_min, pt3_min, pt4_min);
kmean.update_center();
-
+
mln_assertion(is_equal(mean_c1, kmean.get_center(), 0));
mln_assertion(is_equal(mean_c2, kmean.get_center(), 1));
std::cout << "Test update center : ok" << std::endl;
}
+
void test_update_variance()
{
mln::clustering::k_mean<SIZE_SAMPLE2, NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
@@ -405,13 +502,15 @@ void test_update_variance()
fake_update_distance(kmean.get_distance(), lime, brown, teal, purple, c1, c2);
fake_update_group(kmean.get_group(), pt1_min, pt2_min, pt3_min, pt4_min);
kmean.update_variance();
-
+
mln_assertion(v1 == var[0]);
mln_assertion(v2 == var[1]);
std::cout << "Test update variance : ok" << std::endl;
}
+
+/// \fixme this procedure tests actually nothing.
void test_loop()
{
typedef mln::value::rgb8 rgb8;
@@ -426,24 +525,22 @@ void test_loop()
kmean.init_point(img_ref);
kmean.loop(img_ref);
-
- // std::cout << "Test update variance: ok" << std::endl;
+ // \FIXME: Which assertion must we define ?
+ // std::cout << "Test loop : ok" << std::endl;
}
+/// \}
int main()
{
- //test_instantiation();
- //test_init_point();
- //test_init_center();
- //test_update_distance();
- //test_update_group();
- //test_update_center();
- //test_update_variance();
-
- // mln::trace::quiet = false;
-
+ test_instantiation();
+ test_init_point();
+ test_init_center();
+ test_update_distance();
+ test_update_group();
+ test_update_center();
+ test_update_variance();
test_loop();
return 0;
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/clustering/k_mean/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/clustering/k_mean/Makefile.am
diff --git a/scribo/sandbox/green/use/clustering/k_mean/k_mean.cc b/scribo/sandbox/green/use/clustering/k_mean/k_mean.cc
new file mode 100644
index 0000000..9b00037
--- /dev/null
+++ b/scribo/sandbox/green/use/clustering/k_mean/k_mean.cc
@@ -0,0 +1,55 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Minimal code to use the first implementation of the kmean algorithm.
+///
+
+#include <mln/clustering/k_mean.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/trait/value_.hh>
+#include <mln/value/rgb8.hh>
+
+#define NB_CENTER 9
+#define NB_POINT (128*128)
+#define POINT_SIZE mln_dim(mln::value::rgb8)
+#define POINT_TYPE double
+
+int main()
+{
+ typedef mln::value::rgb8 t_rgb8;
+ mln::image2d<t_rgb8> img_rgb8;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+ mln::clustering::k_mean<NB_POINT, NB_CENTER, POINT_SIZE, POINT_TYPE> kmean;
+
+ kmean.init_point(img_rgb8);
+ kmean.loop(img_rgb8);
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/clustering/kmean1d/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/clustering/kmean1d/Makefile.am
diff --git a/scribo/sandbox/green/use/clustering/kmean1d/kmean1d.cc b/scribo/sandbox/green/use/clustering/kmean1d/kmean1d.cc
new file mode 100644
index 0000000..82b13c9
--- /dev/null
+++ b/scribo/sandbox/green/use/clustering/kmean1d/kmean1d.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Minimal code to use the second implementation of the kmean algorithm.
+///
+
+#include <iostream>
+#include <mln/clustering/kmean1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/img_path.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/value/int_u8.hh>
+
+int main()
+{
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ t_image2d_int_u8 img_int_u8;
+
+ mln::io::pgm::load(img_int_u8, OLENA_IMG_PATH"/house.pgm");
+ mln::clustering::kmean1d<double, 8> kmean(img_int_u8, 3);
+
+ kmean.launch_n_times();
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/clustering/kmean2d/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/clustering/kmean2d/Makefile.am
diff --git a/scribo/sandbox/green/use/clustering/kmean2d/kmean2d.cc b/scribo/sandbox/green/use/clustering/kmean2d/kmean2d.cc
new file mode 100644
index 0000000..d6bf05b
--- /dev/null
+++ b/scribo/sandbox/green/use/clustering/kmean2d/kmean2d.cc
@@ -0,0 +1,61 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Minimal code to use the optimized version of the kmean2d algorithm.
+///
+
+#include <iostream>
+#include <mln/clustering/kmean2d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb_to_rg.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/value/rg.hh>
+#include <mln/value/rgb8.hh>
+
+int main()
+{
+ typedef mln::value::rg<8> t_rg8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rg8> t_image2d_rg8;
+ typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rg8 img_rg8;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+
+ img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+
+ mln::clustering::kmean2d<double, 8> kmean(img_rg8, 3);
+
+ kmean.launch_n_times();
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/clustering/kmean3d/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/clustering/kmean3d/Makefile.am
diff --git a/scribo/sandbox/green/use/clustering/kmean3d/kmean3d.cc b/scribo/sandbox/green/use/clustering/kmean3d/kmean3d.cc
new file mode 100644
index 0000000..c57d48a
--- /dev/null
+++ b/scribo/sandbox/green/use/clustering/kmean3d/kmean3d.cc
@@ -0,0 +1,63 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Minimal code to use the optimized version of the kmean3d algorithm.
+///
+
+#include <iostream>
+#include <mln/clustering/kmean3d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/value/rgb.hh>
+#include <mln/value/rgb8.hh>
+
+
+int main()
+{
+ typedef mln::clustering::kmean3d<double,5> t_kmean;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<5> t_rgb5;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgb5> t_image2d_rgb5;
+ typedef mln::fun::v2v::rgb8_to_rgbn<5> t_rgb8_to_rgb5;
+
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rgb5 img_rgb5;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+
+ img_rgb5=mln::data::transform(img_rgb8, t_rgb8_to_rgb5());
+
+ t_kmean kmean(img_rgb5, 3);
+
+ kmean.launch_n_times();
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/clustering/kmean_rgb/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/clustering/kmean_rgb/Makefile.am
diff --git a/scribo/sandbox/green/use/clustering/kmean_rgb/kmean_rgb.cc b/scribo/sandbox/green/use/clustering/kmean_rgb/kmean_rgb.cc
new file mode 100644
index 0000000..3bf2241
--- /dev/null
+++ b/scribo/sandbox/green/use/clustering/kmean_rgb/kmean_rgb.cc
@@ -0,0 +1,63 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Minimal code to use the the functional (versus object) kmean code.
+///
+
+#include <iostream>
+#include <mln/clustering/kmean_rgb.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb.hh>
+#include <mln/value/rgb8.hh>
+
+
+int main()
+{
+ typedef mln::value::label_8 t_lbl8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<5> t_rgb5;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgb5> t_image2d_rgb5;
+ typedef mln::image2d<t_lbl8> t_image2d_lbl8;
+ typedef mln::fun::v2v::rgb8_to_rgbn<5> t_rgb8_to_rgb5;
+
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rgb5 img_rgb5;
+ t_image2d_lbl8 img_lbl8;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+
+ img_rgb5 = mln::data::transform(img_rgb8, t_rgb8_to_rgb5());
+ img_lbl8 = mln::clustering::kmean_rgb<double,5>(img_rgb5, 3, 10, 10);
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/fun/v2v/rg_to_rgb/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/fun/v2v/rg_to_rgb/Makefile.am
diff --git a/scribo/sandbox/green/use/fun/v2v/rg_to_rgb/rg_to_rgb.cc b/scribo/sandbox/green/use/fun/v2v/rg_to_rgb/rg_to_rgb.cc
new file mode 100644
index 0000000..84ae33f
--- /dev/null
+++ b/scribo/sandbox/green/use/fun/v2v/rg_to_rgb/rg_to_rgb.cc
@@ -0,0 +1,68 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief Example of using rg_t_rgb transformation used with kmean2d.
+///
+
+#include <iostream>
+#include <mln/clustering/kmean2d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb_to_rg.hh>
+#include <mln/fun/v2v/rg_to_rgb.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/value/rg.hh>
+#include <mln/value/rgb8.hh>
+
+int main()
+{
+ typedef mln::value::rg<8> t_rg8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rg8> t_image2d_rg8;
+ typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+ typedef mln::fun::v2v::rg_to_rgb<8> t_rg_to_rgb;
+
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rgb8 point_img_rgb8;
+ t_image2d_rg8 img_rg8;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/house.ppm");
+
+ img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+
+ mln::clustering::kmean2d<double, 8> kmean(img_rg8, 3);
+
+ kmean.launch_n_times();
+
+ mln::clustering::kmean2d<double,8>::t_point_img point_img = kmean.get_point();
+
+ point_img_rgb8 = mln::data::transform(point_img, t_rg_to_rgb());
+
+ return 0;
+}
--
1.5.6.5
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch green-regional-maxima has been updated
discards 9ea8474bbe3fbdcfdeba74a7cf2ea602687768ab (commit)
discards 861abf27dc8e90c590b515c5cf0f05111a696220 (commit)
discards 57573abae5803df09f5af2c5fcb15ad4d5a7a397 (commit)
discards 0a1cbd3506e4153a104682280e0bb12d5042613c (commit)
discards 7bc32d5ed6f18ffd43b8512b5a7de4cc26a358ff (commit)
discards a502be9d78730bac9e286324386f0ae4b5f11b88 (commit)
discards ddb6f8cfa75d114ac584c5eabbee8c722fda54d8 (commit)
discards 72bad6e9e8187ee9870f40286db8d4fe4e453425 (commit)
discards 20909f49c35d22b79de8df44915aacca06e71ae0 (commit)
discards 49aaec032034188ccf7694494cddb425bcc352d2 (commit)
discards 110656234b315d15df8617333019265340089d34 (commit)
discards c920529afe338d1120cbc9043394f827a328c368 (commit)
discards 36d40e5b46524d05cfe9d6b8d328cbae09c7e779 (commit)
discards 8c049974295cee70d9d2f235c069f9ed01df30ca (commit)
discards b70dff23b7d1974e60b22b3cb7a196acc3d84946 (commit)
discards 1086f4ed0bec9037a9cff4176b18e49d218bfa6e (commit)
discards d3e640b6eba0ee6d8c52ae1e433ebe7c0be3b15e (commit)
discards 9028f28f51a0a9133e5006917253d386df93ef66 (commit)
discards 34f317bf7800516d03ba9d5cea0f224cca3b9668 (commit)
discards f628029dbf93d9ac7490ea499a64b9794a8168a3 (commit)
discards 8959d2ae95c16fbb28b2a4e98788bdb6463add0f (commit)
discards fe69f742dba2a232cb2f49807ba2879e2325c3b2 (commit)
discards fc278a9509a401b2f9275fa6f39092e77315acd0 (commit)
discards 7af9ecdc4c1b1ed33122c4146f05c55d33e4c5c0 (commit)
discards c6ff97e1bc8ef0e059e1228a3004690f13e2bd56 (commit)
discards d0783cebdffb4c8d8fbcf934bae458684639e325 (commit)
discards 047c90824ecef770ebe8553606bcd2f265c2fa9e (commit)
discards 45cefb4a2e0dd60490e558ca9d04ecac98b2a615 (commit)
discards b5caa8de0eeed69a23d459663fa6dbe0a45980b1 (commit)
discards 7abe6d3e6ecd5341f8b613c072213f454398086c (commit)
discards f2adc9125d01a421487347e72d387488c50fcfce (commit)
discards 988bdbbdf6fe96847ebd00dcced6f8cd4e5682bc (commit)
discards 4e56a00784e19e8e7a2a984aab4f809ec6aee220 (commit)
discards 03c3d97828462c3a070ebb51acc56cded2809b29 (commit)
discards 0c4e1cb4947d09f720a2134c0f8a8702e2bfcd49 (commit)
discards c121636371613a2edb38cb1073e9992833ac5009 (commit)
discards 9e772c65245f643261142cdb7987ed346bfc1a46 (commit)
discards fd0947d2453d62e92681d4a1f0026b42fd5c8024 (commit)
discards 2c3f552813a8b6a51692e8ef4c40a4f8dba933bf (commit)
discards 8c92a3be8ae8f2738b584580b4e39031d6243bcf (commit)
discards 4ee2f2a9467f7ed2ca24c68ac5ef35e12f4faf86 (commit)
via 67b295ee221ad90e1abc475854375a7bc06d7954 (commit)
via 2cfa144eb3d4bb1b1f12655c2e4708771138d23b (commit)
via c670b7e781b64e3e8b4d0b17b5d6fef31d6a8bc6 (commit)
via 49b8dc22e8f9664f7f385496080c06ab80096171 (commit)
via d4f2e4917b95cb92762f0fc82498050789ead89c (commit)
via e9328a0605c308aea46d70abbb73402593b9eb65 (commit)
via 485f8dec942fd56ba950c33c539f7803dfa281d0 (commit)
via 1d23bfaf3e648f96ca2321da52bfc4e7b6f8420c (commit)
via 2c26e604d0e939535f7dff1bfdf0925825b9f307 (commit)
via 174b91703414bb8df7c9fb0922c51aef32c38cb2 (commit)
via ba99cc211570e5854fc6b910a3a634f6d15f1f86 (commit)
via acb2f3dbabfa00da20a7e8e1160fbbd051a1b652 (commit)
via a85f46a9568f5085ca32662e59a545675b70905c (commit)
via a2d33697a1ffc22679540af9cdf899bebf0e5167 (commit)
via 18d1a4203f6577a0602e4c4578dbae57a11a0f02 (commit)
via 3849ff557b11d1542cc38263fae5ea5163899678 (commit)
via 1dff8cf61b25a32a64186ea346ceb14c97f3f63a (commit)
via 40063b84e2132755bb7982fb86f6cd8527399ebd (commit)
via fdf0f76c54e847f00553092d355f752d10a1b835 (commit)
via a3cbabff4529a013fa40dddebbfc63d2eb3667aa (commit)
via 88906972b5285dbd4bff41f6645d09fb182aed1b (commit)
via 444245a639e02fd0ebdfb083c8c551b459a56fb1 (commit)
via 16fbbef7db27689c3728436e7035a5a6549826de (commit)
via 1835af00071ea4e14e1641cb87d118d3ba511f4b (commit)
via 0625137ef6694e51353ea04db9cb62365188c67c (commit)
via c325629baf82f376924de68f8d43133e77c934c1 (commit)
via 1a823f73b8f232149a0e953624d895a29f706a2d (commit)
via 58801223f73cb532e43fac2ca8065a43c8fa6985 (commit)
via 607075682b6992513805c0f5cafd95ded370efab (commit)
via 60307833a3b3ff5e7b5da1e9b333a8404c0040f2 (commit)
via 31f0f731e35d208e89a812ebadddcfcf90ebc667 (commit)
via 6c0fa46bdaaf8619358568aabfcf8a20c6c21ee1 (commit)
via cadda529593468fcd00d0750fda70d4648d3badd (commit)
via 256de5f3eed935fc8229a3800be8cb71937b70ee (commit)
via 00ab9ddbdd78e06f7ebd01c57f5e6f490254fa2c (commit)
via 19825009a7bc9c638226dd2963f1a56679d31757 (commit)
via b6641d4b0fe6550d26d15b837ba65e7279f2298b (commit)
via b1afad461fa1621d1b6c98ae81bcbfc23248f6dd (commit)
via 7404579567f626734d6de94fb6cb62072d97553b (commit)
via 00da4238932f0410315ed16fb7be6869f4d0b381 (commit)
via 59ebeab82ed59260c238a59478a79c30c090584b (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (9ea8474bbe3fbdcfdeba74a7cf2ea602687768ab)
\
N -- N -- N (67b295ee221ad90e1abc475854375a7bc06d7954)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
67b295e Simple integration test.
2cfa144 Fix the way to convert unsigned to float.
c670b7e Add milena library components.
49b8dc2 Work on Millet value descriptor.
d4f2e49 Work on Millet saturation descriptor.
e9328a0 Work on Millet saturation descriptor.
485f8de Work on Millet hsv descriptors.
1d23bfa Work on histograms view as density.
2c26e60 Test error quantification as a color descriptor in our database.
174b917 Benchmark few descriptors.
ba99cc2 Test on image database the achromatism descriptor.
acb2f3d Turn around Millet 2008 hsv descriptors.
a85f46a Delete BUG image file in milena/img.
a2d3369 Save Theo's exhaustive demonstration results.
18d1a42 Fix bugs in the histogram visualization tools.
3849ff5 Fix last details in the image processing chain.
1dff8cf Extend the histogram visualization tools for new projection concept.
40063b8 Build translation table between number of pixels and percentage of
fdf0f76 Split the regional maxima binary in small atomic binaries.
a3cbabf Write the opening volume thresholds for the scribo image mp00082c.ppm.
8890697 Experiment various quantifications on regional maxima labeling.
444245a Experiment variation on regional maxima labeling.
-----------------------------------------------------------------------
Summary of changes:
hooks/post-receive
--
Olena, a generic and efficient image processing platform
* mln/io/plot/save_image_sh.hh: New header file.
Give an example of code.
* use/io/plot/save_image_sh: New directory.
* use/io/plot/save_image_sh/Makefile.am: New makefile.
* use/io/plot/save_image_sh/save_image_sh.cc: New source file.
Make some unitary tests on gnuplot shell export.
* tests/io/plot/save_image_sh: New directory.
* tests/io/plot/save_image_sh/Makefile.am: New makefile.
* tests/io/plot/save_image_sh/save_image_sh.cc: New source file.
---
scribo/sandbox/green/ChangeLog | 109 +++++----
scribo/sandbox/green/README | 52 ++---
scribo/sandbox/green/mln/io/plot/save_image_sh.hh | 36 +++-
.../green/tests/io/plot/save_image_sh/Makefile.am | 13 +-
.../tests/io/plot/save_image_sh/save_image_sh.cc | 284 ++++++++++++++------
.../histo1d => io/plot/save_image_sh}/Makefile.am | 0
.../plot/save_image_sh/save_image_sh.cc} | 4 +-
7 files changed, 329 insertions(+), 169 deletions(-)
copy scribo/sandbox/green/use/{accu/stat/histo1d => io/plot/save_image_sh}/Makefile.am (100%)
copy scribo/sandbox/green/use/{accu/stat/histo1d/histo1d.cc => io/plot/save_image_sh/save_image_sh.cc} (91%)
diff --git a/scribo/sandbox/green/ChangeLog b/scribo/sandbox/green/ChangeLog
index db589a1..5a7ceaa 100644
--- a/scribo/sandbox/green/ChangeLog
+++ b/scribo/sandbox/green/ChangeLog
@@ -1,54 +1,20 @@
-2010-06-24 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+2010-06-23 green <jacquelet(a)lrde.epita.fr>
- Import files from milena/sandbox/green.
+ Define gnuplot shell export format.
- * gaussian.sh: New gnuplot shell file.
- * guassian2d.sh: New gnuplot shell file.
- * test_labelling.cc: New source.
- * tests/clustering/k_mean/Makefile.am: New makefile.
- * tests/clustering/k_mean/k_mean.cc: New source.
- * tests/clustering/kmean1d/Makefile.am: New makefile.
- * tests/clustering/kmean1d/kmean1d.cc: New source.
- * tests/io/plot/save_image_sh/Makefile.am: New makefile.
- * tests/io/plot/save_image_sh/save_image_sh.cc: New source.
+ * mln/io/plot/save_image_sh.hh: New header file.
-2010-06-24 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+ Give an example of code.
- Import files from milena/sandbox/green.
+ * use/io/plot/save_image_sh: New directory.
+ * use/io/plot/save_image_sh/Makefile.am: New makefile.
+ * use/io/plot/save_image_sh/save_image_sh.cc: New source file.
- * mln/accu/stat/histo1d.hh: New header file.
- * mln/accu/stat/histo2d.hh: New header file.
- * mln/accu/stat/histo3d_hsl.hh: New header file.
- * mln/accu/stat/histo3d_rgb.hh: New header file.
- * mln/clustering/k_mean.hh: New header file.
- * mln/clustering/kmean1d.hh: New header file.
- * mln/clustering/kmean2d.hh: New header file.
- * mln/clustering/kmean3d.hh: New header file.
- * mln/clustering/kmean_rgb.hh: New header file.
- * mln/display/display_histo.hh: New header file.
- * mln/display/project_histo.hh: New header file.
- * mln/fun/p2b/achromatic.hh: New header file.
- * mln/fun/p2b/component_equals.hh: New header file.
- * mln/fun/v2v/achromatism.hh: New header file.
- * mln/fun/v2v/hue_concentration.hh: New header file.
- * mln/fun/v2v/int_u16_to_int_u14.hh: New header file.
- * mln/fun/v2v/int_u16_to_int_u14.hh: New header file.
- * mln/fun/v2v/log.hh: New header file.
- * mln/fun/v2v/rg_to_rgb.hh: New header file.
- * mln/fun/v2v/rgb8_to_int_u8: New header file.
- * mln/fun/v2v/rgb_to_achromastism_map.hh: New header file.
- * mln/fun/v2v/rgb_to_hsv.hh: New header file.
- * mln/fun/v2v/rgb_to_hue_map.hh: New header file.
- * mln/fun/v2v/rgb_to_saturation_map.hh: New header file.
- * mln/fun/v2v/rgb_to_value_map.hh: New header file.
- * mln/img_path.hh: New header file.
- * mln/io/plot/save_image_sh.hh: New header file.
- * mln/math/cell.hh: New header file.
- * mln/math/floor.hh: New header file.
- * tests/accu/stat/histo1d/Makefile.am: New makefile.
- * tests/accu/stat/histo1d/histo1d.cc: New source.
- * tests/accu/stat/histo2d/Makefile.am: New makefile.
- * tests/accu/stat/histo2d/histo2d.cc: New source.
+ Make some unitary tests on gnuplot shell export.
+
+ * tests/io/plot/save_image_sh: New directory.
+ * tests/io/plot/save_image_sh/Makefile.am: New makefile.
+ * tests/io/plot/save_image_sh/save_image_sh.cc: New source file.
2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
@@ -130,6 +96,57 @@
* tests/accu/stat/histo3d_hsl/Makefile.am: New makefile.
* tests/accu/stat/histo3d_hsl/histo3d_hsl.cc: New source.
+2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Import files from milena/sandbox/green.
+
+ * gaussian.sh: New gnuplot shell file.
+ * guassian2d.sh: New gnuplot shell file.
+ * test_labelling.cc: New source.
+ * tests/clustering/k_mean/Makefile.am: New makefile.
+ * tests/clustering/k_mean/k_mean.cc: New source.
+ * tests/clustering/kmean1d/Makefile.am: New makefile.
+ * tests/clustering/kmean1d/kmean1d.cc: New source.
+ * tests/io/plot/save_image_sh/Makefile.am: New makefile.
+ * tests/io/plot/save_image_sh/save_image_sh.cc: New source.
+
+2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Import files from milena/sandbox/green.
+
+ * mln/accu/stat/histo1d.hh: New header file.
+ * mln/accu/stat/histo2d.hh: New header file.
+ * mln/accu/stat/histo3d_hsl.hh: New header file.
+ * mln/accu/stat/histo3d_rgb.hh: New header file.
+ * mln/clustering/k_mean.hh: New header file.
+ * mln/clustering/kmean1d.hh: New header file.
+ * mln/clustering/kmean2d.hh: New header file.
+ * mln/clustering/kmean3d.hh: New header file.
+ * mln/clustering/kmean_rgb.hh: New header file.
+ * mln/display/display_histo.hh: New header file.
+ * mln/display/project_histo.hh: New header file.
+ * mln/fun/p2b/achromatic.hh: New header file.
+ * mln/fun/p2b/component_equals.hh: New header file.
+ * mln/fun/v2v/achromatism.hh: New header file.
+ * mln/fun/v2v/hue_concentration.hh: New header file.
+ * mln/fun/v2v/int_u16_to_int_u14.hh: New header file.
+ * mln/fun/v2v/int_u16_to_int_u14.hh: New header file.
+ * mln/fun/v2v/log.hh: New header file.
+ * mln/fun/v2v/rg_to_rgb.hh: New header file.
+ * mln/fun/v2v/rgb8_to_int_u8: New header file.
+ * mln/fun/v2v/rgb_to_achromastism_map.hh: New header file.
+ * mln/fun/v2v/rgb_to_hsv.hh: New header file.
+ * mln/fun/v2v/rgb_to_hue_map.hh: New header file.
+ * mln/fun/v2v/rgb_to_saturation_map.hh: New header file.
+ * mln/fun/v2v/rgb_to_value_map.hh: New header file.
+ * mln/img_path.hh: New header file.
+ * mln/io/plot/save_image_sh.hh: New header file.
+ * mln/math/cell.hh: New header file.
+ * mln/math/floor.hh: New header file.
+ * tests/accu/stat/histo1d/Makefile.am: New makefile.
+ * tests/accu/stat/histo1d/histo1d.cc: New source.
+ * tests/accu/stat/histo2d/Makefile.am: New makefile.
+ * tests/accu/stat/histo2d/histo2d.cc: New source.
2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
diff --git a/scribo/sandbox/green/README b/scribo/sandbox/green/README
index 4b6fb26..03106d3 100644
--- a/scribo/sandbox/green/README
+++ b/scribo/sandbox/green/README
@@ -153,8 +153,8 @@ d'exécution (chmod 755 gnuplot_shell_file.sh). Comme je trouve le format
extrêmement pratique, il se retrouve preque partout dans mes sources.
-V HISTOGRAMMES
---------------
+VI HISTOGRAMMES
+---------------
Un des travaux demandés par théo est la réalisation d'une librairie
d'histogramme permettant de fournir un résultat sous forme d'image.
@@ -173,7 +173,7 @@ a) version 1d
* mln/accu/stat/histo1d.hh: Accumulateur histogramme image1d.
* use/accu/stat/histo1d: Code minimal utilisant un histogramme 1d.
-* tests/accu/stat/histo1d: Test unitaire sur l'histogramme 1d.
+* tests/accu/stat/histo1d: Tests unitaires sur l'histogramme 1d.
b) version 2d
@@ -203,52 +203,42 @@ d) version 3d HSL
* mln/accu/stat/histo3d_hsl.hh: Accumulateur histogramme image3d HSL.
* use/accu/stat/histo3_hsl: Code minimal utilisant un histogramme 3d HSL.
-* tests/accu/stat/histo3d_hsl: Test unitaire sur l'histogramme HSL 3d.
+* tests/accu/stat/histo3d_hsl: Tests unitaires sur l'histogramme HSL 3d.
Le code HSL ne compile plus car l'interface liant la transformation du
domaine et la fonction fold a changée. Je n'ai pas le temps de
regarder plus avant.
+VII SAUVEGARDE FORMAT GNUPLOT SHELL
+-----------------------------------
-V MLN
------
-
-a) La sauvegarde des images au format gnuplot shell
-
-* mln/io/plot/save_image_sh.hh: Librairie sauvegarde format gnuplot shell.
-
-to do ...
-
-
-
-b) Les histogrammes
-
-
-
-
-
-
-
+Ce travail est personnel. Ces développements m'ont été tellement
+utiles que je ne regrette pas l'investissement effectué. L'idée est de
+pouvoir avoir un format d'image en écriture lisible. J'ai pris celui
+de gnuplot, ce qui permet en plus de pouvoir "sucrer" la présentation
+des données à loisir. Les images sont plus lourdes car le codage est
+textuel et un peu plus "verbose" mais se compresse aisément par
+n'importe quel algorithme type huffman (tous les archiveurs en possède un).
+* mln/io/plot/save_image_sh.hh: Librairie de sauvegarde au format gnuplot shell.
+* use/io/plot/save_image_sh: Code simple d'utilisation de la sauvegarde.
+* tests/io/plot/save_image_sh: Tests unitaires sur l'export.
-* tests/accu/stat/histo1d
+VI MLN
+-----
+a) La sauvegarde des images au format gnuplot shell
-* tests/accu/stat/histo2d
+* mln/io/plot/save_image_sh.hh: Librairie sauvegarde format gnuplot shell.
+to do ...
-* use/accu/stat/histo3d_rgb
-* tests/accu/stat/histo3d_rgb
-* use/accu/stat/histo3d_hsl
-* tests/accu/stat/histo3d_hsl
-VI SAUVEGARDE FORMAT GNUPLOT SHELL
-----------------------------------
VII VISUALISATION HISTOGRAMMES 3D
diff --git a/scribo/sandbox/green/mln/io/plot/save_image_sh.hh b/scribo/sandbox/green/mln/io/plot/save_image_sh.hh
index 137f78d..7e28f6f 100644
--- a/scribo/sandbox/green/mln/io/plot/save_image_sh.hh
+++ b/scribo/sandbox/green/mln/io/plot/save_image_sh.hh
@@ -38,6 +38,29 @@
/// The script file call gnuplot in batch mode, the result window persists and
/// that's all.
///
+/// The following sample is a typical use of the gnuplot shell export library.
+///
+/// #include <mln/accu/stat/histo1d.hh>
+/// #include <mln/data/compute.hh>
+/// #include <mln/core/image/image1d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/pgm/load.hh>
+/// #include <mln/io/plot/save_image_sh.hh>
+/// #include <mln/value/int_u8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::int_u8 t_int_u8;
+/// mln::image2d<t_int_u8> img;
+/// mln::image1d<unsigned> histo;
+///
+/// mln::io::pgm::load(img, OLENA_IMG_PATH"/lena.pgm");
+/// histo = mln::data::compute(mln::accu::meta::histo::histo1d(), img);
+/// mln::io::plot::save_image_sh(histo, "histo.sh");
+///
+/// return 0;
+/// }
# include <fstream>
# include <string>
@@ -92,7 +115,6 @@ namespace mln
/// filename parameter as unix path. The script shell file must have the
/// permission to execute (chmod 755). Launch the script shell to call
/// gnuplot in batchmode with fine parameters.
-
template <typename I>
bool save_image_sh(const Image<I>& img, const std::string& filename);
@@ -112,6 +134,18 @@ namespace mln
bool save_image_sh(const util::array< image1d<I> >& stack,
const std::string& filename);
+ /// \brief Save a stack of stack of image.
+ ///
+ /// This is an experimental support.
+ ///
+ /// \param[in] stack the stack of image to save.
+ /// \param[in] filename the name of the unix script shell.
+ /// \return the status of the opening file operation.
+ ///
+ /// The result depends on the permission to save the file with
+ /// filename parameter as unix path. The script shell file must have the
+ /// permission to execute (chmod 755). Launch the script shell to call
+ /// gnuplot in batchmode with fine parameters.
template <typename I>
bool save_image_sh(const util::array< util::array< image1d<I> > >& stack,
const std::string& filename);
diff --git a/scribo/sandbox/green/tests/io/plot/save_image_sh/Makefile.am b/scribo/sandbox/green/tests/io/plot/save_image_sh/Makefile.am
index d970989..77f9015 100644
--- a/scribo/sandbox/green/tests/io/plot/save_image_sh/Makefile.am
+++ b/scribo/sandbox/green/tests/io/plot/save_image_sh/Makefile.am
@@ -6,8 +6,13 @@
# TOOLS #
#########
-INCLUDES= -I$(HOME)/svn/oln/trunk/milena/sandbox/green
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
ECHO= echo
RM= rm
MKDIR= mkdir -p
@@ -20,10 +25,10 @@ BUILD__PATTERN= green/build/tests
ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
# Case where make is done from build directory.
SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
-BUILD__DIR= $(PWD)
+BUILD__DIR= $(PWD)/
else
# Case where make is done from source directory.
-SOURCE_DIR= $(PWD)
+SOURCE_DIR= $(PWD)/
BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
endif
@@ -60,7 +65,7 @@ $(BUILD__DIR):
# Copy, if nessary, all the files, except the Makefile.am
$(BUILD__F_PATH): $(SOURCE_F_PATH)
- $(CP) $(addprefix $(SOURCE_DIR)/,$(@F)) $@
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
# Copy if nessary, the Makefile.am into Makefile
$(BUILD__M_PATH): $(SOURCE_M_PATH)
diff --git a/scribo/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc b/scribo/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc
index c9c817b..c60533e 100644
--- a/scribo/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc
+++ b/scribo/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc
@@ -1,4 +1,36 @@
-/// TEST SAVE_IMAGE_SH.HH
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief This source manages unitary testing on gnuplot shell export library.
+///
+/// Tests are performed in various image format, such as image1d, image2d<bool>,
+/// image2d<int_u8>, image2d<int_u16>, image2d<int_s8>, image2d<int_s16>,
+/// image2d<float>, image2d<double>, image2d<rgb8>, image2d<rgb16>,
+/// image2d<hsl_f>, image2d<hsl_d>, image2d<hsi_f>, image2d<hsi_d>, image3d.
#include <iostream>
#include <limits.h>
@@ -32,9 +64,13 @@
#include <mln/literal/colors.hh>
#include <mln/debug/println.hh>
-//------------------------------------------------------------------------------
-// TEST TO SAVE UNSIGNED 8 BITS 1D GRAYSCALE IMAGE
-//------------------------------------------------------------------------------
+
+/// image1d<int_u8>.
+/// \{
+/// \brief Test saving a grayscale image1d.
+///
+/// As working on the image1d interface is something extremely rare, we need
+/// to use the plot interface to first load some datas and then export them.
mln::image1d<mln::value::int_u8>
convert_array_to_image1d(const mln::util::array<mln::value::int_u8>& array)
@@ -64,7 +100,7 @@ void test_save_image_sh_1d()
image1d img;
array1d array;
-
+
mln::io::plot::load(array, OLENA_IMG_PATH"/fly.plot");
img = convert_array_to_image1d(array);
@@ -73,16 +109,20 @@ void test_save_image_sh_1d()
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img, "fly1d.sh");
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image 1d : ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// Test to save image2d<bool>
-//------------------------------------------------------------------------------
+/// \}
+/// image2d<bool>.
+/// \{
+/// \brief Test saving an image2d<bool>.
+///
+/// Boolean image2d are extremly convenient for storing mask. We have a lots
+/// of example in milena.
void test_save_image2d_bool()
{
@@ -93,22 +133,26 @@ void test_save_image2d_bool()
image2d_bool img_bool;
mln::io::pbm::load(img_bool, OLENA_IMG_PATH"/lena.pbm");
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_bool, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_bool, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<bool>: ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// Test to save image2d<int_u8>
-//------------------------------------------------------------------------------
+/// \}
+/// image2d<int_u8>.
+/// \{
+/// \brief Test saving a grayscale image2d.
+///
+/// Grayscale image2d are very popular in image processing. It's the test we do
+/// not fail!
void test_save_image2d_int_u8()
{
@@ -120,27 +164,36 @@ void test_save_image2d_int_u8()
image2d_int_u8 img_int_u8;
mln::io::pgm::load(img_int_u8, OLENA_IMG_PATH"/lena.pgm");
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_int_u8, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_int_u8, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<int_u8>: ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// Test to save image2d<int_u16>
-//------------------------------------------------------------------------------
+/// \}
+
+/// image2d<int_u16>.
+/// \{
+/// \brief Test saving an extended grayscale image2d.
+///
+/// This kind of image are not so current. But for medical use, we can get now,
+/// some dicom in 12 bits and new generation bring us 16 bits. As 16 bits is a
+/// strange format for image processing people, there is not a common
+/// acceptation for the underline format. Xv or imageMagick doesn't agree for
+/// the representation of the file.
+
struct int_u16_to_int_u8 : mln::Function_v2v< int_u16_to_int_u8 >
{
typedef mln::value::int_u16 argument;
typedef mln::value::int_u8 result;
-
+
result operator()(const argument& c) const
{
result res(c / 256);
@@ -170,22 +223,28 @@ void test_save_image2d_int_u16()
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_int_u16, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<int_u16> : ok" << std::endl;
}
+/// \}
+
+/// image2d<int_s8>.
+/// \{
+/// \brief Test saving an signed image2d.
+///
+/// This kind of image are very artificial. It is given for exhaustivity of
+/// testing. In fact, this kind of image traduces some step in a computing
+/// chain.
-//------------------------------------------------------------------------------
-// Test to save image2d<int_s8>
-//------------------------------------------------------------------------------
struct int_u8_to_int_s8 : mln::Function_v2v< int_u8_to_int_s8 >
{
typedef mln::value::int_u8 argument;
typedef mln::value::int_s8 result;
-
+
result operator()(const argument& c) const
{
argument tmp_int_u8;
@@ -197,7 +256,7 @@ struct int_u8_to_int_s8 : mln::Function_v2v< int_u8_to_int_s8 >
{
res = SCHAR_MAX;
}
- else if (SCHAR_MAX < c)
+ else if (static_cast<unsigned>(SCHAR_MAX) < c)
{
tmp_int_u8 = c - SCHAR_MAX;
res = static_cast<mln::value::int_s8>(tmp_int_u8);
@@ -226,28 +285,34 @@ void test_save_image2d_int_s8()
image2d_int_u8 img_int_u8;
mln::io::pgm::load(img_int_u8, OLENA_IMG_PATH"/lena.pgm");
- img_int_s8 = mln::data::transform(img_int_u8, int_u8_to_int_s8());
-
+ img_int_s8 = mln::data::transform(img_int_u8, int_u8_to_int_s8());
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_int_s8, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_int_s8, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<int_s8>: ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// Test to save image2d<int_s16>
-//------------------------------------------------------------------------------
+/// \}
+
+/// image2d<int_s16>.
+/// \{
+/// \brief Test saving an extended image2d.
+///
+/// This kind of image are very artificial. It is given for exhaustivity of
+/// testing. In fact, this kind of image traduces some step in a computing
+/// chain.
struct int_u16_to_int_s16 : mln::Function_v2v< int_u16_to_int_s16 >
{
typedef mln::value::int_u16 argument;
typedef mln::value::int_s16 result;
-
+
result operator()(const argument& c) const
{
argument tmp_int_u16;
@@ -258,7 +323,7 @@ struct int_u16_to_int_s16 : mln::Function_v2v< int_u16_to_int_s16 >
{
res = SHRT_MAX;
}
- else if (SHRT_MAX < c)
+ else if (static_cast<unsigned>(SHRT_MAX) < c)
{
tmp_int_u16 = c - SHRT_MAX;
res = static_cast<mln::value::int_s16>(tmp_int_u16);
@@ -286,29 +351,33 @@ void test_save_image2d_int_s16()
image2d_int_u16 img_int_u16;
mln::io::pgm::load(img_int_u16, OLENA_IMG_PATH"/lena_16_gnuplot.pgm");
- img_int_s16 = mln::data::transform(img_int_u16, int_u16_to_int_s16());
+ img_int_s16 = mln::data::transform(img_int_u16, int_u16_to_int_s16());
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_int_s16, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_int_s16, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<int_s16> : ok" << std::endl;
}
+/// \}
-//------------------------------------------------------------------------------
-// Test to save image2d<float>
-//------------------------------------------------------------------------------
+/// image2d<float>.
+/// \{
+/// \brief Test saving a float image2d.
+///
+/// This kind of image is a common way to save some attributes localized on
+/// pixels.
struct int_u8_to_float : mln::Function_v2v< int_u8_to_float >
{
typedef mln::value::int_u8 argument;
typedef float result;
-
+
result operator()(const argument& c) const
{
result res = static_cast<float>(c)/3;
@@ -330,27 +399,32 @@ void test_save_image2d_float()
mln::io::pgm::load(img_int_u8, OLENA_IMG_PATH"/lena.pgm");
img_float = mln::data::transform(img_int_u8, int_u8_to_float());
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_float, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_float, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<float> : ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// Test to save image2d<double>
-//------------------------------------------------------------------------------
+/// \}
+
+/// image2d<double>.
+/// \{
+/// \brief Test saving a double image2d.
+///
+/// This kind of image is a common way to save some attributes localized on
+/// pixels.
struct int_u16_to_double : mln::Function_v2v< int_u16_to_double >
{
typedef mln::value::int_u16 argument;
typedef double result;
-
+
result operator()(const argument& c) const
{
result res = static_cast<float>(c)/256;
@@ -372,23 +446,25 @@ void test_save_image2d_double()
mln::io::pgm::load(img_int_u16, OLENA_IMG_PATH"/lena_16_gnuplot.pgm");
img_double = mln::data::transform(img_int_u16, int_u16_to_double());
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_double, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_double, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<double> : ok" << std::endl;
}
+/// \}
-
-//------------------------------------------------------------------------------
-// Test to save image2d<rgb8>
-//------------------------------------------------------------------------------
+/// image2d<rgb8>.
+/// \{
+/// \brief Test saving a RGB color image2d.
+///
+/// This kind of format is extremely popular in image, and in photography.
void test_save_image2d_rgb8()
{
@@ -400,28 +476,33 @@ void test_save_image2d_rgb8()
image2d_rgb8 img_rgb8;
mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_rgb8, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_rgb8, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<rgb8> : ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// Test to save image2d<rgb16>
-//------------------------------------------------------------------------------
+/// \}
+
+/// image2d<rgb16>.
+/// \{
+/// \brief Test saving a 16 bits RGB color image2d.
+///
+/// As this kind of image is less popular, the library enable this export by
+/// the will of exhaustivity.
struct rgb16_to_int_u16 : mln::Function_v2v< rgb16_to_int_u16 >
{
typedef mln::value::rgb16 argument;
typedef mln::value::int_u16 result;
-
+
result operator()(const argument& c) const
{
result res((c.red() + c.green() + c.blue())/3);
@@ -447,23 +528,28 @@ void test_save_image2d_rgb16()
mln::io::ppm::load(img_rgb16, OLENA_IMG_PATH"/lena_16.ppm");
//img_int_u16 = mln::data::transform(img_rgb16, rgb16_to_int_u16());
//mln::io::pgm::save(img_int_u16, "lena_16.pgm");
-
+
// Save it were it is impossible to do it !!
bool ref_false=mln::io::plot::save_image_sh(img_rgb16, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_rgb16, lena);
// mln::io::plot::save_image_sh(img_int_u16, lena2);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<rgb16> : ok" << std::endl;
}
+/// \}
-//------------------------------------------------------------------------------
-// Test to save image2d<hsl_f>
-//------------------------------------------------------------------------------
+/// image2d<hsl_f>.
+/// \{
+/// \brief Test saving a HSL float color image2d.
+///
+/// This kind of image allow to show the power of gnuplot. Raw data
+/// are hsl, then hsl equations are integrated in the gnuplot shell
+/// file. So decoding needs more time.
void test_save_image2d_hsl_f()
{
@@ -484,21 +570,27 @@ void test_save_image2d_hsl_f()
//mln::data::fill(img_rgb8, mln::literal::blue);
img_hsl_f = mln::data::transform(img_rgb8, rgb_to_hsl());
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_hsl_f, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_hsl_f, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<hsl_f> : ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// Test to save image2d<hsl_d>
-//------------------------------------------------------------------------------
+/// \}
+
+/// image2d<hsl_d>.
+/// \{
+/// \brief Test saving a HSL double color image2d.
+///
+/// This kind of image allow to show the power of gnuplot. Raw data
+/// are hsl, then hsl equations are integrated in the gnuplot shell
+/// file. So decoding needs more time.
void test_save_image2d_hsl_d()
{
@@ -519,22 +611,27 @@ void test_save_image2d_hsl_d()
//mln::data::fill(img_rgb16, mln::literal::blue);
img_hsl_d = mln::data::transform(img_rgb16, rgb_to_hsl());
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_hsl_d, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_hsl_d, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<hsl_d> : ok" << std::endl;
}
+/// \}
-//------------------------------------------------------------------------------
-// Test to save image2d<hsi_f>
-//------------------------------------------------------------------------------
+/// image2d<hsi_f>.
+/// \{
+/// \brief Test saving a HSI float color image2d.
+///
+/// This kind of image allow to show the power of gnuplot. Raw data
+/// are hsi, then hsi equations are integrated in the gnuplot shell
+/// file. So decoding needs more time.
void test_save_image2d_hsi_f()
{
@@ -555,21 +652,27 @@ void test_save_image2d_hsi_f()
//mln::data::fill(img_rgb8, mln::literal::blue);
img_hsi_f = mln::data::transform(img_rgb8, rgb_to_hsi());
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_hsi_f, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_hsi_f, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<hsi_f> : ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// Test to save image2d<hsi_d>
-//------------------------------------------------------------------------------
+/// \}
+
+/// image2d<hsi_d>.
+/// \{
+/// \brief Test saving a HSI double color image2d.
+///
+/// This kind of image allow to show the power of gnuplot. Raw data
+/// are hsi, then hsi equations are integrated in the gnuplot shell
+/// file. So decoding needs more time.
void test_save_image2d_hsi_d()
{
@@ -590,21 +693,28 @@ void test_save_image2d_hsi_d()
//mln::data::fill(img_rgb16, mln::literal::blue);
img_hsi_d = mln::data::transform(img_rgb16, rgb_to_hsi());
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img_hsi_d, null_lena);
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img_hsi_d, lena);
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image2d<hsi_d> : ok" << std::endl;
}
-//------------------------------------------------------------------------------
-// TEST TO SAVE 8 BITS 3D RGB IMAGE
-//------------------------------------------------------------------------------
+/// \}
+
+/// image3d<int_8>.
+/// \{
+/// \brief Test saving a grayscale image3d.
+///
+/// It seems important to be able to export in 3d, but it's not so popular
+/// in the team. We try to simulate this functionnality.
+///
+/// \fixme The data visualization is very hard in 3d compact with gnuplot.
void test_save_image_sh_3d()
{
@@ -619,18 +729,20 @@ void test_save_image_sh_3d()
array.append(OLENA_IMG_PATH"/fly.pgm");
mln::io::pgms::load(img, array);
-
+
// Save it were it is impossible to do it !!
bool ref_false = mln::io::plot::save_image_sh(img, "/dev/null/fly3d.sh");
// Save it where we have the full permissions.
bool ref_true = mln::io::plot::save_image_sh(img, "fly3d.sh");
-
+
mln_assertion(true == ref_true);
mln_assertion(false == ref_false);
std::cout << "save image 3d : ok" << std::endl;
}
+/// \}
+
int main()
{
@@ -649,7 +761,7 @@ int main()
test_save_image2d_rgb8();
test_save_image2d_rgb16();
-
+
test_save_image2d_hsl_f();
test_save_image2d_hsl_d();
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/io/plot/save_image_sh/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/io/plot/save_image_sh/Makefile.am
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc b/scribo/sandbox/green/use/io/plot/save_image_sh/save_image_sh.cc
similarity index 91%
copy from scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc
copy to scribo/sandbox/green/use/io/plot/save_image_sh/save_image_sh.cc
index af39d94..bd4b84f 100644
--- a/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc
+++ b/scribo/sandbox/green/use/io/plot/save_image_sh/save_image_sh.cc
@@ -25,7 +25,7 @@
/// \file
///
-/// \brief Minimal code for building 1d image histogram version.
+/// \brief Example of code using the gnuplot shell export library.
///
#include <mln/accu/stat/histo1d.hh>
@@ -34,6 +34,7 @@
#include <mln/core/image/image2d.hh>
#include <mln/img_path.hh>
#include <mln/io/pgm/load.hh>
+#include <mln/io/plot/save_image_sh.hh>
#include <mln/value/int_u8.hh>
@@ -46,6 +47,7 @@ int main()
mln::io::pgm::load(img, OLENA_IMG_PATH"/lena.pgm");
histo = mln::data::compute(mln::accu::meta::stat::histo1d(), img);
+ mln::io::plot::save_image_sh(histo, "histo.sh");
return 0;
}
--
1.5.6.5
* gaussian.sh: New gnuplot shell file.
* guassian2d.sh: New gnuplot shell file.
* test_labelling.cc: New source.
* tests/clustering/k_mean/Makefile.am: New makefile.
* tests/clustering/k_mean/k_mean.cc: New source.
* tests/clustering/kmean1d/Makefile.am: New makefile.
* tests/clustering/kmean1d/kmean1d.cc: New source.
* tests/io/plot/save_image_sh/Makefile.am: New makefile.
* tests/io/plot/save_image_sh/save_image_sh.cc: New source.
---
scribo/sandbox/green/ChangeLog | 14 +
.../histo1d => scribo/sandbox/green}/gaussian.sh | 0
.../histo2d => scribo/sandbox/green}/gaussian2d.sh | 0
scribo/sandbox/green/test_labelling.cc | 336 ++++++++++++++++++++
.../green/tests/clustering/k_mean/Makefile.am | 0
.../green/tests/clustering/k_mean/k_mean.cc | 0
.../green/tests/clustering/kmean1d/Makefile.am | 0
.../green/tests/clustering/kmean1d/kmean1d.cc | 0
.../green/tests/io/plot/save_image_sh}/Makefile.am | 0
.../tests/io/plot/save_image_sh/save_image_sh.cc | 0
10 files changed, 350 insertions(+), 0 deletions(-)
copy {milena/sandbox/green/tests/accu/stat/histo1d => scribo/sandbox/green}/gaussian.sh (100%)
copy {milena/sandbox/green/tests/accu/stat/histo2d => scribo/sandbox/green}/gaussian2d.sh (100%)
create mode 100644 scribo/sandbox/green/test_labelling.cc
copy {milena => scribo}/sandbox/green/tests/clustering/k_mean/Makefile.am (100%)
copy {milena => scribo}/sandbox/green/tests/clustering/k_mean/k_mean.cc (100%)
copy {milena => scribo}/sandbox/green/tests/clustering/kmean1d/Makefile.am (100%)
copy {milena => scribo}/sandbox/green/tests/clustering/kmean1d/kmean1d.cc (100%)
copy {milena/sandbox/green/doc/examples/frac => scribo/sandbox/green/tests/io/plot/save_image_sh}/Makefile.am (100%)
copy {milena => scribo}/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc (100%)
diff --git a/scribo/sandbox/green/ChangeLog b/scribo/sandbox/green/ChangeLog
index 8f5101b..db589a1 100644
--- a/scribo/sandbox/green/ChangeLog
+++ b/scribo/sandbox/green/ChangeLog
@@ -2,6 +2,20 @@
Import files from milena/sandbox/green.
+ * gaussian.sh: New gnuplot shell file.
+ * guassian2d.sh: New gnuplot shell file.
+ * test_labelling.cc: New source.
+ * tests/clustering/k_mean/Makefile.am: New makefile.
+ * tests/clustering/k_mean/k_mean.cc: New source.
+ * tests/clustering/kmean1d/Makefile.am: New makefile.
+ * tests/clustering/kmean1d/kmean1d.cc: New source.
+ * tests/io/plot/save_image_sh/Makefile.am: New makefile.
+ * tests/io/plot/save_image_sh/save_image_sh.cc: New source.
+
+2010-06-24 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Import files from milena/sandbox/green.
+
* mln/accu/stat/histo1d.hh: New header file.
* mln/accu/stat/histo2d.hh: New header file.
* mln/accu/stat/histo3d_hsl.hh: New header file.
diff --git a/milena/sandbox/green/tests/accu/stat/histo1d/gaussian.sh b/scribo/sandbox/green/gaussian.sh
similarity index 100%
copy from milena/sandbox/green/tests/accu/stat/histo1d/gaussian.sh
copy to scribo/sandbox/green/gaussian.sh
diff --git a/milena/sandbox/green/tests/accu/stat/histo2d/gaussian2d.sh b/scribo/sandbox/green/gaussian2d.sh
similarity index 100%
copy from milena/sandbox/green/tests/accu/stat/histo2d/gaussian2d.sh
copy to scribo/sandbox/green/gaussian2d.sh
diff --git a/scribo/sandbox/green/test_labelling.cc b/scribo/sandbox/green/test_labelling.cc
new file mode 100644
index 0000000..6238d2b
--- /dev/null
+++ b/scribo/sandbox/green/test_labelling.cc
@@ -0,0 +1,336 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+
+#include <mln/io/plot/save_histo_sh.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/value/label_8.hh>
+#include <mln/core/alias/neighb1d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/labeling/colorize.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/labeling/regional_maxima.hh>
+#include <mln/make/w_window1d.hh>
+#include <mln/math/pi.hh>
+#include <mln/morpho/watershed/flooding.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/morpho/elementary/closing.hh>
+#include <mln/pw/value.hh>
+#include <mln/linear/convolve.hh>
+#include <mln/linear/gaussian.hh>
+
+
+/// ... to complete
+
+/// \brief Compute the gaussian probability to obtain a given value.
+///
+/// \param[in] x the value from which we want the probability.
+/// \param[in] mean the mean parameter of the gaussian distribution.
+/// \param[in] sigma the sqrt(variance) parameter of the gaussian.
+/// \return the probability to obtain the x value.
+///
+/// Implements the standard equation of the gaussian.
+
+double gaussian_distribution(const double x,
+ const double mean,
+ const double sigma)
+{
+ double num = exp(-0.5*mln::math::sqr((x - mean)/sigma));
+ double denom = sigma*mln::math::sqrt(2*mln::math::pi);
+ double result = num/denom;
+
+ return result;
+}
+
+/// \brief Make a 1d gaussian filter.
+///
+/// \param[out] ws the window (filter) where to put the probability values.
+/// \param[in] size the size of the filter.
+/// \param[in] sigma the gaussian parameter for the standard deviation.
+/// \return the probability to obtain the x value.
+///
+/// Approach the gaussian distribution for a few discrete sites, and
+/// then normilize the results to be sure that the sum obtain 1.
+
+void gaussian_filter(double ws[], const unsigned size, const double sigma)
+{
+ int h = size/2;
+
+ for (int i = -h; i <= h; ++i)
+ {
+ ws[i+h] = gaussian_distribution(i, 0.0, sigma);
+ }
+
+ double sum = 0.0;
+
+ for (unsigned i = 0; i < size; ++i)
+ sum += ws[i];
+
+ for (unsigned i = 0; i < size; ++i)
+ ws[i] /= sum;
+}
+
+/// \brief Make a 1d gaussian filter.
+///
+/// \param[out] ws the window (filter) where to put the probability values.
+/// \param[in] size the size of the filter.
+/// \param[in] sigma the gaussian parameter for the standard deviation.
+/// \return the probability to obtain the x value.
+///
+/// Approach the gaussian distribution for a few discrete sites, and
+/// then normilize the results to be sure that the sum obtain 1.
+
+/// The aim of this function is to rebuild an label image2d from the segmenting
+/// image of the histogram (label) and the original image (input).
+/// label_image2d / for each grey tone, associate its label.
+
+mln::image2d<mln::value::label_8>
+build_8bits(const mln::image2d<mln::value::int_u8>& input,
+ const mln::image1d<mln::value::label_8>& label)
+{
+ mln::trace::entering("build_8bits");
+ mln_precondition(label.is_valid());
+ mln_precondition(input.is_valid());
+
+ mln::image2d<mln::value::label_8> output;
+
+ mln::initialize(output, input);
+
+ mln_piter_(mln::image2d<mln::value::int_u8>) pi(input.domain());
+ mln_piter_(mln::image2d<mln::value::label_8>) po(output.domain());
+
+ for_all_2(pi, po)
+ {
+ mln::value::int_u8 val = input(pi);
+ unsigned grp = label(mln::point1d(val));
+
+ output(po) = grp;
+ }
+
+ mln::trace::exiting("build_8bits");
+ return output;
+}
+
+
+void test_8bits_classifying()
+{
+ typedef mln::value::int_u8 int_u8;
+ typedef mln::value::label_8 label_8;
+ typedef mln::value::rgb8 rgb8;
+ typedef mln::accu::stat::mean<double> mean;
+
+ mln::image2d<int_u8> img_ref;
+ mln::image2d<int_u8> img_out;
+ mln::image2d<rgb8> img_rgb;
+ mln::image1d<unsigned> img_res;
+ mln::image1d<double> img_smooth;
+ mln::image1d<label_8> labels;
+ label_8 nlabels;
+
+ //-----------------------------------------------------
+ // Loading the scribo image and computing its histogram
+ //-----------------------------------------------------
+
+ std::cout << "(08 bits) LOADING HISTOGRAM" << std::endl;
+
+ // mln::io::pgm::load(img_ref, OLENA_IMG_PATH"/lena.pgm");
+ mln::io::pgm::load(img_ref, SCRIBO_IMG_PATH"/mp00082c_50p_8bits.pgm");
+ img_res = mln::data::compute(mln::accu::stat::histo1d<int_u8>(), img_ref);
+ mln::io::plot::save_histo_sh(img_res, "histo0_8bits.sh");
+
+
+ //-----------------------------------------------------
+ // Smoothing the histogram with a gaussian filter
+ //-----------------------------------------------------
+
+ std::cout << "(08 bits) SMOOTHING HISTOGRAM" << std::endl;
+
+ double ws[41];
+ gaussian_filter(ws, 41, 6.0);
+ img_smooth = mln::linear::convolve(img_res, mln::make::w_window1d(ws));
+ mln::io::plot::save_histo_sh(img_smooth, "histo1_8bits.sh");
+
+
+ //-----------------------------------------------------
+ // Segmenting the histogram with the watershed method
+ //-----------------------------------------------------
+
+ std::cout << "SEGMENTING HISTOGRAM" << std::endl;
+
+ /*
+ labels = mln::labeling::regional_maxima(img_smooth, mln::c2(), nlabels);
+ std::cout << "N labels : " << nlabels << std::endl;
+ mln::io::plot::save_histo_sh(labels, "histo2_8bits.sh");
+ */
+
+ // need to revert the histogram
+ labels = mln::morpho::watershed::flooding(img_smooth, mln::c2(), nlabels);
+ std::cout << "N labels : " << nlabels << std::endl;
+ mln::io::plot::save_histo_sh(labels, "histo2_8bits.sh");
+
+
+ //-----------------------------------------------------
+ // Rebuilding the image with the mean of each region
+ //-----------------------------------------------------
+
+ std::cout << "(08 bits) BUILDING OUTPUT" << std::endl;
+
+ mln::image2d<label_8>img_label = build_8bits(img_ref, labels);
+
+ std::cout << "(08 bits) COLORING OUTPUT" << std::endl;
+
+ img_out = mln::labeling::mean_values(img_ref, img_label, nlabels);
+ img_rgb = mln::labeling::colorize(rgb8(), img_label);
+
+ mln::io::pgm::save(img_out, "out_8bits.pgm");
+ mln::io::ppm::save(img_rgb, "color_8bits.pgm");
+
+ //labels = mln::morpho::elementary::dilation(labels, mln::c2());
+ //mln::io::plot::save_histo_sh(labels, "histo3.sh");
+ //mln::io::plot::save(labels, "labelized.data");
+}
+
+
+/// The aim of this function is to rebuild an label image2d from the segmenting
+/// image of the histogram (label) and the original image (input).
+/// label_image2d / for each grey tone, associate its label.
+
+mln::image2d<mln::value::label_8>
+build_14bits(const mln::image2d<mln::value::int_u<14> >& input,
+ const mln::image1d<mln::value::label_8>& label)
+{
+ mln::trace::entering("build_14bits");
+ mln_precondition(label.is_valid());
+ mln_precondition(input.is_valid());
+
+ mln::image2d<mln::value::label_8> output;
+
+ mln::initialize(output, input);
+
+ mln_piter_(mln::image2d<mln::value::int_u<14> >) pi(input.domain());
+ mln_piter_(mln::image2d<mln::value::label_8>) po(output.domain());
+
+ for_all_2(pi, po)
+ {
+ mln::value::int_u<14> val = input(pi);
+ unsigned grp = label(mln::point1d(val));
+
+ output(po) = grp;
+ }
+
+ mln::trace::exiting("build_14bits");
+ return output;
+}
+
+
+void test_14bits_classifying()
+{
+ typedef mln::value::int_u16 int_u16;
+ typedef mln::value::int_u<14> int_u14;
+ typedef mln::value::label_8 label_8;
+ typedef mln::value::rgb8 rgb8;
+ typedef mln::accu::stat::mean<double> mean;
+
+ mln::image2d<int_u16> img_fst;
+ mln::image2d<int_u14> img_ref;
+ mln::image2d<int_u14> img_out;
+ mln::image2d<rgb8> img_rgb;
+ mln::image1d<unsigned> img_res;
+ mln::image1d<double> img_smooth;
+ mln::image1d<label_8> labels;
+ label_8 nlabels;
+
+ //-----------------------------------------------------
+ // Loading the scribo image and computing its histogram
+ //-----------------------------------------------------
+
+ std::cout << "(14 bits) LOADING HISTOGRAM" << std::endl;
+
+ //mln::io::pgm::load(img_fst, OLENA_IMG_PATH"/lena_16.pgm");
+ mln::io::pgm::load(img_fst, SCRIBO_IMG_PATH"/mp00082c_50p_16bits.pgm");
+ img_ref = mln::data::transform(img_fst, mln::fun::v2v::int_u16_to_int_u14());
+ img_res = mln::data::compute(mln::accu::stat::histo1d<int_u14>(), img_ref);
+ mln::io::plot::save_histo_sh(img_res, "histo0_14bits.sh");
+
+
+ //-----------------------------------------------------
+ // Smoothing the histogram with a gaussian filter
+ //-----------------------------------------------------
+
+ std::cout << "(14 bits) SMOOTHING HISTOGRAM" << std::endl;
+
+ double ws[401];
+ gaussian_filter(ws, 401, 50.0);
+ img_smooth = mln::linear::convolve(img_res, mln::make::w_window1d(ws));
+ mln::io::plot::save_histo_sh(img_smooth, "histo1_14bits.sh");
+
+
+ //-----------------------------------------------------
+ // Segmenting the histogram with the watershed method
+ //-----------------------------------------------------
+
+ std::cout << "(14 bits) SEGMENTING HISTOGRAM" << std::endl;
+
+ /*
+ labels = mln::labeling::regional_maxima(img_smooth, mln::c2(), nlabels);
+ std::cout << "N labels : " << nlabels << std::endl;
+ mln::io::plot::save_histo_sh(labels, "histo2.sh");
+ */
+
+
+ labels = mln::morpho::watershed::flooding(img_smooth, mln::c2(), nlabels);
+ std::cout << "N labels : " << nlabels << std::endl;
+ mln::io::plot::save_histo_sh(labels, "histo2_14bits.sh");
+
+
+ //-----------------------------------------------------
+ // Rebuilding the image with the mean of each region
+ //-----------------------------------------------------
+
+ std::cout << "(14 bits) BUILDING OUTPUT" << std::endl;
+
+ mln::image2d<label_8>img_label = build_14bits(img_ref, labels);
+
+ std::cout << "(14 bits) COLORING OUTPUT" << std::endl;
+
+ img_out = mln::labeling::mean_values(img_ref, img_label, nlabels);
+ img_rgb = mln::labeling::colorize(rgb8(), img_label);
+
+ mln::io::pgm::save(img_out, "out_14bits.pgm");
+ mln::io::ppm::save(img_rgb, "color_14bits.pgm");
+
+ //labels = mln::morpho::elementary::dilation(labels, mln::c2());
+ //mln::io::plot::save_histo_sh(labels, "histo3.sh");
+ //mln::io::plot::save(labels, "labelized.data");
+}
+
+int main()
+{
+ test_8bits_classifying();
+
+ test_14bits_classifying();
+
+ return 0;
+}
diff --git a/milena/sandbox/green/tests/clustering/k_mean/Makefile.am b/scribo/sandbox/green/tests/clustering/k_mean/Makefile.am
similarity index 100%
copy from milena/sandbox/green/tests/clustering/k_mean/Makefile.am
copy to scribo/sandbox/green/tests/clustering/k_mean/Makefile.am
diff --git a/milena/sandbox/green/tests/clustering/k_mean/k_mean.cc b/scribo/sandbox/green/tests/clustering/k_mean/k_mean.cc
similarity index 100%
copy from milena/sandbox/green/tests/clustering/k_mean/k_mean.cc
copy to scribo/sandbox/green/tests/clustering/k_mean/k_mean.cc
diff --git a/milena/sandbox/green/tests/clustering/kmean1d/Makefile.am b/scribo/sandbox/green/tests/clustering/kmean1d/Makefile.am
similarity index 100%
copy from milena/sandbox/green/tests/clustering/kmean1d/Makefile.am
copy to scribo/sandbox/green/tests/clustering/kmean1d/Makefile.am
diff --git a/milena/sandbox/green/tests/clustering/kmean1d/kmean1d.cc b/scribo/sandbox/green/tests/clustering/kmean1d/kmean1d.cc
similarity index 100%
copy from milena/sandbox/green/tests/clustering/kmean1d/kmean1d.cc
copy to scribo/sandbox/green/tests/clustering/kmean1d/kmean1d.cc
diff --git a/milena/sandbox/green/doc/examples/frac/Makefile.am b/scribo/sandbox/green/tests/io/plot/save_image_sh/Makefile.am
similarity index 100%
copy from milena/sandbox/green/doc/examples/frac/Makefile.am
copy to scribo/sandbox/green/tests/io/plot/save_image_sh/Makefile.am
diff --git a/milena/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc b/scribo/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc
similarity index 100%
copy from milena/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc
copy to scribo/sandbox/green/tests/io/plot/save_image_sh/save_image_sh.cc
--
1.5.6.5
* mln/img_path.hh: New header file.
Define the 1d component version of the the library.
* mln/accu/stat/histo1d.hh: New header file.
Give an example of code.
* use/accu/stat/histo1d: New directory.
* use/accu/stat/histo1d/Makefile.am: New makefile.
* use/accu/stat/histo1d/histo1d.cc: New source.
Make some unitary tests on histo1d library.
* tests/accu/stat/histo1d: New directory.
* tests/accu/stat/histo1d/Makefile.am: New makefile.
* tests/accu/stat/histo1d/histo1d.cc: New source.
Define the 2d component version of the the library.
* mln/accu/stat/histo2d.hh: New header file.
* mln/value/rg.hh: New header file.
* mln/fun/v2v/rgb_to_rg.hh: New header file.
Give an example of code.
* use/accu/stat/histo2d: New directory.
* use/accu/stat/histo2d/Makefile.am: New makefile.
* use/accu/stat/histo2d/histo2d.cc: New source.
* use/value/rg: New directory.
* use/value/rg/Makefile.am: New makefile.
* use/value/rg/rg.cc: New source.
* use/fun/v2v/rgb_to_rg: New directory.
* use/fun/v2v/rgb_to_rg/Makefile.am: New makefile.
* use/fun/v2v/rgb_to_rg/rgb_to_rg.cc: New source.
Define the RGB 3d component version of the the library.
* mln/accu/stat/histo3d_rgb.hh: New header file.
* mln/fun/v2v/rgb8_to_rgbn.hh: New header file.
Give an example of code.
* use/accu/stat/histo3_rgb: New directory.
* use/accu/stat/histo3d_rgb/Makefile.am: New makefile.
* use/accu/stat/histo3d_rgb/histo3d_rgb.cc: New source.
* use/fun/v2v/rgb8_to_rgbn: New directory.
* use/fun/v2v/rgb8_to_rgbn/Makefile.am: New makefile.
* use/fun/v2v/rgb8_to_rgbn/rgb8_to_rgbn.cc: New source.
Make some unitary tests on histo3d library.
* tests/accu/stat/histo3d_rgb: New directory.
* tests/accu/stat/histo3d_rgb/Makefile.am: New makefile.
* tests/accu/stat/histo3d_rgb/histo3d_rgb.cc: New source.
Define the HSL 3d component version of the the library.
* mln/accu/stat/histo3d_hsl.hh: New header file.
Give an example of code.
* use/accu/stat/histo3_hsl: New directory.
* use/accu/stat/histo3d_hsl/Makefile.am: New makefile.
* use/accu/stat/histo3d_hsl/histo3d_hsl.cc: New source.
Make some unitary tests on histo3d library.
* tests/accu/stat/histo3d_hsl: New directory.
* tests/accu/stat/histo3d_hsl/Makefile.am: New makefile.
* tests/accu/stat/histo3d_hsl/histo3d_hsl.cc: New source.
---
scribo/sandbox/green/ChangeLog | 82 +++-
scribo/sandbox/green/README | 73 +++-
scribo/sandbox/green/mln/accu/stat/histo1d.hh | 32 +-
scribo/sandbox/green/mln/accu/stat/histo2d.hh | 75 ++--
scribo/sandbox/green/mln/accu/stat/histo3d_hsl.hh | 249 +++++-----
scribo/sandbox/green/mln/accu/stat/histo3d_rgb.hh | 138 +++---
scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh | 49 ++-
scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh | 2 -
.../green/tests/accu/stat/histo1d/histo1d.cc | 502 +++++++++++++++++++-
.../accu/stat/{histo1d => histo3d_hsl}/Makefile.am | 0
.../tests/accu/stat/histo3d_hsl/histo3d_hsl.cc | 394 +++++++---------
.../accu/stat/{histo1d => histo3d_rgb}/Makefile.am | 0
.../tests/accu/stat/histo3d_rgb/histo3d_rgb.cc | 355 +++++++-------
.../sandbox/green/use/accu/stat/histo1d/histo1d.cc | 27 +
.../sandbox/green/use/accu/stat/histo2d/histo2d.cc | 25 +
.../accu/stat/{histo1d => histo3d_hsl}/Makefile.am | 0
.../green/use/accu/stat/histo3d_hsl/histo3d_hsl.cc | 56 ++--
.../accu/stat/{histo1d => histo3d_rgb}/Makefile.am | 0
.../green/use/accu/stat/histo3d_rgb/histo3d_rgb.cc | 45 +-
.../histo1d => fun/v2v/rgb8_to_rgbn}/Makefile.am | 0
.../green/use/fun/v2v/rgb8_to_rgbn/rgb8_to_rgbn.cc | 45 +-
.../stat/histo1d => fun/v2v/rgb_to_rg}/Makefile.am | 0
.../green/use/fun/v2v/rgb_to_rg/rgb_to_rg.cc | 51 +-
.../{accu/stat/histo1d => value/rg}/Makefile.am | 0
.../sandbox/green/use/value/rg/rg.cc | 51 +-
25 files changed, 1450 insertions(+), 801 deletions(-)
copy scribo/sandbox/green/tests/accu/stat/{histo1d => histo3d_hsl}/Makefile.am (100%)
copy {milena => scribo}/sandbox/green/tests/accu/stat/histo3d_hsl/histo3d_hsl.cc (73%)
copy scribo/sandbox/green/tests/accu/stat/{histo1d => histo3d_rgb}/Makefile.am (100%)
copy {milena => scribo}/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc (64%)
copy scribo/sandbox/green/use/accu/stat/{histo1d => histo3d_hsl}/Makefile.am (100%)
copy milena/tests/fun/v2v/rgb_to_hsl.cc => scribo/sandbox/green/use/accu/stat/histo3d_hsl/histo3d_hsl.cc (57%)
copy scribo/sandbox/green/use/accu/stat/{histo1d => histo3d_rgb}/Makefile.am (100%)
copy milena/tests/io/ppm/ppm.cc => scribo/sandbox/green/use/accu/stat/histo3d_rgb/histo3d_rgb.cc (63%)
copy scribo/sandbox/green/use/{accu/stat/histo1d => fun/v2v/rgb8_to_rgbn}/Makefile.am (100%)
copy milena/tests/io/ppm/ppm.cc => scribo/sandbox/green/use/fun/v2v/rgb8_to_rgbn/rgb8_to_rgbn.cc (63%)
copy scribo/sandbox/green/use/{accu/stat/histo1d => fun/v2v/rgb_to_rg}/Makefile.am (100%)
copy milena/tests/fun/v2v/hsl_to_rgb.cc => scribo/sandbox/green/use/fun/v2v/rgb_to_rg/rgb_to_rg.cc (59%)
copy scribo/sandbox/green/use/{accu/stat/histo1d => value/rg}/Makefile.am (100%)
copy milena/tests/fun/v2v/hsl_to_rgb.cc => scribo/sandbox/green/use/value/rg/rg.cc (60%)
diff --git a/scribo/sandbox/green/ChangeLog b/scribo/sandbox/green/ChangeLog
index 6a3c8fa..8f5101b 100644
--- a/scribo/sandbox/green/ChangeLog
+++ b/scribo/sandbox/green/ChangeLog
@@ -38,12 +38,84 @@
2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
- Save histogram library.
+ Define accumulator which computes histogram view as image.
+
+ * mln/img_path.hh: New header file.
+
+ Define the 1d component version of the the library.
+
+ * mln/accu/stat/histo1d.hh: New header file.
+
+ Give an example of code.
+
+ * use/accu/stat/histo1d: New directory.
+ * use/accu/stat/histo1d/Makefile.am: New makefile.
+ * use/accu/stat/histo1d/histo1d.cc: New source.
+
+ Make some unitary tests on histo1d library.
+
+ * tests/accu/stat/histo1d: New directory.
+ * tests/accu/stat/histo1d/Makefile.am: New makefile.
+ * tests/accu/stat/histo1d/histo1d.cc: New source.
+
+ Define the 2d component version of the the library.
+
+ * mln/accu/stat/histo2d.hh: New header file.
+ * mln/value/rg.hh: New header file.
+ * mln/fun/v2v/rgb_to_rg.hh: New header file.
+
+ Give an example of code.
+
+ * use/accu/stat/histo2d: New directory.
+ * use/accu/stat/histo2d/Makefile.am: New makefile.
+ * use/accu/stat/histo2d/histo2d.cc: New source.
+
+ * use/value/rg: New directory.
+ * use/value/rg/Makefile.am: New makefile.
+ * use/value/rg/rg.cc: New source.
+
+ * use/fun/v2v/rgb_to_rg: New directory.
+ * use/fun/v2v/rgb_to_rg/Makefile.am: New makefile.
+ * use/fun/v2v/rgb_to_rg/rgb_to_rg.cc: New source.
+
+ Define the RGB 3d component version of the the library.
+
+ * mln/accu/stat/histo3d_rgb.hh: New header file.
+ * mln/fun/v2v/rgb8_to_rgbn.hh: New header file.
+
+ Give an example of code.
+
+ * use/accu/stat/histo3_rgb: New directory.
+ * use/accu/stat/histo3d_rgb/Makefile.am: New makefile.
+ * use/accu/stat/histo3d_rgb/histo3d_rgb.cc: New source.
+
+ * use/fun/v2v/rgb8_to_rgbn: New directory.
+ * use/fun/v2v/rgb8_to_rgbn/Makefile.am: New makefile.
+ * use/fun/v2v/rgb8_to_rgbn/rgb8_to_rgbn.cc: New source.
+
+ Make some unitary tests on histo3d library.
+
+ * tests/accu/stat/histo3d_rgb: New directory.
+ * tests/accu/stat/histo3d_rgb/Makefile.am: New makefile.
+ * tests/accu/stat/histo3d_rgb/histo3d_rgb.cc: New source.
+
+
+ Define the HSL 3d component version of the the library.
+
+ * mln/accu/stat/histo3d_hsl.hh: New header file.
+
+ Give an example of code.
+
+ * use/accu/stat/histo3_hsl: New directory.
+ * use/accu/stat/histo3d_hsl/Makefile.am: New makefile.
+ * use/accu/stat/histo3d_hsl/histo3d_hsl.cc: New source.
+
+ Make some unitary tests on histo3d library.
+
+ * tests/accu/stat/histo3d_hsl: New directory.
+ * tests/accu/stat/histo3d_hsl/Makefile.am: New makefile.
+ * tests/accu/stat/histo3d_hsl/histo3d_hsl.cc: New source.
- * mln/accu/histo/histo1d.hh: New header file.
- * mln/accu/histo/histo2d.hh: New header file.
- * mln/accu/histo/histo3d_rgb.hh: New header file.
- * mln/accu/histo/histo3d_hsl.hh: New header file.
2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
diff --git a/scribo/sandbox/green/README b/scribo/sandbox/green/README
index 3efe50d..4b6fb26 100644
--- a/scribo/sandbox/green/README
+++ b/scribo/sandbox/green/README
@@ -153,18 +153,8 @@ d'exécution (chmod 755 gnuplot_shell_file.sh). Comme je trouve le format
extrêmement pratique, il se retrouve preque partout dans mes sources.
-V MLN
------
-
-a) La sauvegarde des images au format gnuplot shell
-
-* mln/io/plot/save_image_sh.hh: Librairie sauvegarde format gnuplot shell.
-
-to do ...
-
-
-
-b) Les histogrammes
+V HISTOGRAMMES
+--------------
Un des travaux demandés par théo est la réalisation d'une librairie
d'histogramme permettant de fournir un résultat sous forme d'image.
@@ -178,20 +168,67 @@ de comptage puisqu'il est décrit sous la forme de triplets de float
contient une séquence d'appels pour les routines permettant de
considérer la dimension de la teinte comme circulaire.
+
+a) version 1d
+
* mln/accu/stat/histo1d.hh: Accumulateur histogramme image1d.
* use/accu/stat/histo1d: Code minimal utilisant un histogramme 1d.
+* tests/accu/stat/histo1d: Test unitaire sur l'histogramme 1d.
+
+
+b) version 2d
-* mln/accu/stat/histo2d.hh: Accumulateur histogramme image2d.
* mln/value/rg.hh: Définition du type vectoriel 2d rouge/vert (RG).
+* use/value/rg: Exemple de code pour l'utilisation de rg.
+
* mln/fun/v2v/rgb_to_rg.hh: Transformation de l'espace RGB vers l'espace RG.
+* use/fun/v2v/rgb_to_rg: Exemple de code pour l'utilisation de rgb_to_rg.
+
+* mln/accu/stat/histo2d.hh: Accumulateur histogramme image2d.
* use/accu/stat/histo2d: Code minimal utilisant un histogramme 2d.
-* mln/accu/stat/histo3d_rgb.hh: Accumulateur histogramme image3d RGB.
-* mln/accu/stat/histo3d_hsl.hh: Accumulateur histogramme image3d HSL.
+c) version 3d RGB
+
+
+* mln/fun/v2v/rgb8_to_rgbn.hh: Diminution de la quantification (n < 8 bits).
+* use/fun/v2v/rgb8_to_rgbn: Exemple de code pour l'utilisation de rgb8_to_rgbn.
+* mln/accu/stat/histo3d_rgb.hh: Accumulateur histogramme image3d RGB.
* use/accu/stat/histo3_rgb: Code minimal utilisant un histogramme 3d RGB.
+
+
+
+d) version 3d HSL
+
+* mln/accu/stat/histo3d_hsl.hh: Accumulateur histogramme image3d HSL.
* use/accu/stat/histo3_hsl: Code minimal utilisant un histogramme 3d HSL.
+* tests/accu/stat/histo3d_hsl: Test unitaire sur l'histogramme HSL 3d.
+
+Le code HSL ne compile plus car l'interface liant la transformation du
+domaine et la fonction fold a changée. Je n'ai pas le temps de
+regarder plus avant.
+
+
+
+V MLN
+-----
+
+a) La sauvegarde des images au format gnuplot shell
+
+* mln/io/plot/save_image_sh.hh: Librairie sauvegarde format gnuplot shell.
+
+to do ...
+
+
+
+b) Les histogrammes
+
+
+
+
+
+
@@ -210,6 +247,12 @@ considérer la dimension de la teinte comme circulaire.
* use/accu/stat/histo3d_hsl
* tests/accu/stat/histo3d_hsl
+VI SAUVEGARDE FORMAT GNUPLOT SHELL
+----------------------------------
+
+
+VII VISUALISATION HISTOGRAMMES 3D
+---------------------------------
c) La visualisation des histogrammes 3d
diff --git a/scribo/sandbox/green/mln/accu/stat/histo1d.hh b/scribo/sandbox/green/mln/accu/stat/histo1d.hh
index d480cf0..fae94c8 100644
--- a/scribo/sandbox/green/mln/accu/stat/histo1d.hh
+++ b/scribo/sandbox/green/mln/accu/stat/histo1d.hh
@@ -24,7 +24,7 @@
// executable file might be covered by the GNU General Public License.
#ifndef MLN_ACCU_STAT_HISTO1D_HH
-#define MLN_ACCU_STAT_HISTO1D_HH
+# define MLN_ACCU_STAT_HISTO1D_HH
/// \file
///
@@ -64,24 +64,24 @@
/// }
-#include <iostream>
+# include <iostream>
-#include <mln/accu/internal/base.hh>
+# include <mln/accu/internal/base.hh>
-#include <mln/arith/plus.hh>
+# include <mln/arith/plus.hh>
-#include <mln/core/concept/meta_accumulator.hh>
-#include <mln/core/image/image1d.hh>
-#include <mln/core/macros.hh>
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/core/image/image1d.hh>
+# include <mln/core/macros.hh>
-#include <mln/literal/zero.hh>
+# include <mln/literal/zero.hh>
-#include <mln/trace/entering.hh>
-#include <mln/trace/exiting.hh>
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
-#include <mln/trait/value/comp.hh>
+# include <mln/trait/value/comp.hh>
-#include <mln/value/ops.hh>
+# include <mln/value/ops.hh>
namespace mln
{
@@ -168,7 +168,7 @@ namespace mln
typedef image1d<unsigned> result;
typedef result q_result;
- /// Constructors
+ /// Constructors.
/// \{
/// \brief Infer the size of the resulting image1d domain.
///
@@ -201,7 +201,6 @@ namespace mln
///
/// The end user shouldn't call this method. This is part of
/// data compute interface mechanism.
-
void take(const histo1d<V>& other);
/// \}
@@ -231,11 +230,10 @@ namespace mln
///
/// The operator compares all the bins from the two histograms.
/// Nobody uses this method unless unitary tests.
-
template <typename V>
bool operator==(const histo1d<V>& histo1, const histo1d<V>& histo2);
-#ifndef MLN_INCLUDE_ONLY
+# ifndef MLN_INCLUDE_ONLY
template <typename V>
inline
@@ -328,7 +326,7 @@ namespace mln
return result;
}
-#endif // ! MLN_INCLUDE_ONLY
+# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::accu::stat
diff --git a/scribo/sandbox/green/mln/accu/stat/histo2d.hh b/scribo/sandbox/green/mln/accu/stat/histo2d.hh
index c28723c..11a1bb3 100644
--- a/scribo/sandbox/green/mln/accu/stat/histo2d.hh
+++ b/scribo/sandbox/green/mln/accu/stat/histo2d.hh
@@ -73,14 +73,16 @@
# include <mln/accu/internal/base.hh>
+# include <mln/arith/plus.hh>
+
# include <mln/core/macros.hh>
# include <mln/core/image/image2d.hh>
# include <mln/core/alias/point2d.hh>
# include <mln/core/alias/box2d.hh>
-# include <mln/trait/value/comp.hh>
+#include <mln/literal/zero.hh>
-# include <mln/arith/plus.hh>
+# include <mln/trait/value/comp.hh>
# include <mln/trace/entering.hh>
# include <mln/trace/exiting.hh>
@@ -152,13 +154,13 @@ namespace mln
namespace stat
{
- /// \brief Define an histogram which returns an image3d .
+ /// \brief Define a histogram as accumulator which returns an image2d.
///
- /// Param V defines the space in which we count the values.
- /// For instance, this histogram works image2d<rgb<2>> or
- /// image2d<rgb<7>>. The histogram count the occurrence of each value.
- /// The number of bins depends of the grayscale values, for 8 bits there
- /// is 256x3 bins. Note that over
+ /// Param V defines the type of the input image value. It is in
+ /// this space that we count the values. For instance, this
+ /// histogram works well for image2d< rgb<2> > or with image2d<
+ /// rgb<7> >. The number of bins depends directly the values V.
+ /// For 8 bits there is 256x3 bins. Note that less
/// quantification works too.
///
/// \ingroup modaccuvalues
@@ -171,16 +173,15 @@ namespace mln
typedef image2d<unsigned> result;
typedef result q_result;
- /// Constructors
+ /// Constructors.
/// \{
- /// \brief Initialize the size of the resulting image1d.
+ /// \brief Infer the size of the resulting image2d domain.
///
- /// Initialize the size the resulting image from the theorical dynamic
- /// of the greylevel values (Use V to manage it).
+ /// By evaluating the minimum and the maximum of V, we define the domain
+ /// of the resulting image2d.
histo2d();
/// \}
-
/// Manipulators.
/// \{
/// \brief Initialize the histogram with zero value.
@@ -190,23 +191,24 @@ namespace mln
/// density.
void init();
-
- /// \brief Update the histogram with the RGB pixel t.
- /// \param[in] t a greylevel pixel of type V.
+ /// \brief Update the histogram with the RG pixel t.
+ /// \param[in] t a graylevel pixel of type V.
///
/// The end user shouldn't call this method. In place of it, he can
/// go through the data compute interface.
void take(const argument& t);
-
/// \brief Update the histogram with an other histogram.
/// \param[in] other the other histogram.
+ ///
+ /// The end user shouldn't call this method. This is part of
+ /// data compute interface mechanism.
void take(const histo2d<V>& other);
/// \}
/// Accessors.
/// \{
- /// \brief Return the histogram as an image1d.
+ /// \brief Return the histogram as an image2d.
///
/// This is the machinery to communicate with data compute interface.
/// The end user should'nt use it.
@@ -228,19 +230,19 @@ namespace mln
/// \param[in] histo1 the first histogram to compare with.
/// \param[in] histo2 the second histogram.
///
- /// The operator compare all the bins from the two histogram.
-
+ /// The operator compares all the bins from the two histograms.
+ /// Nobody uses this method unless unitary tests.
template <typename V>
bool operator==(const histo2d<V>& histo1,
const histo2d<V>& histo2);
-#ifndef MLN_INCLUDE_ONLY
+# ifndef MLN_INCLUDE_ONLY
template <typename V>
inline
histo2d<V>::histo2d()
{
- trace::entering("mln::accu::stat::histo2d::histo2d");
+ trace::entering("mln::accu::stat::histo2d::cstor");
typedef mln_trait_value_comp(V,0) comp0;
typedef mln_trait_value_comp(V,1) comp1;
@@ -253,31 +255,24 @@ namespace mln
point2d(mln_max(comp0),
mln_max(comp1))));
- trace::exiting("mln::accu::stat::histo2d::histo2d");
+ trace::exiting("mln::accu::stat::histo2d::cstor");
}
template <typename V>
inline
void histo2d<V>::init()
{
- trace::entering("mln::accu::stat::histo2d::init");
-
- data::fill(count_, 0);
- trace::exiting("mln::accu::stat::histo2d::init");
+ data::fill(count_, literal::zero);
}
template <typename V>
inline
void histo2d<V>::take(const argument& t)
{
- trace::entering("mln::accu::stat::histo2d::take");
-
// Just convert a greyscale value (int_u8 like) to a position for an
// iterator on the resulting image.
// Take care to the constructor : Point(slice, row, column)
++count_(point2d(t.red(), t.green()));
-
- trace::exiting("mln::accu::stat::histo2d::take");
}
@@ -285,20 +280,13 @@ namespace mln
inline
void histo2d<V>::take(const histo2d<V>& other)
{
- trace::entering("mln::accu::stat::histo2d::take");
-
count_ += other.count_;
-
- trace::exiting("mln::accu::stat::histo2d::take");
}
template <typename V>
inline
typename histo2d<V>::result histo2d<V>::to_result() const
{
- trace::entering("mln::accu::stat::histo2d::to_result");
-
- trace::exiting("mln::accu::stat::histo2d::to_result");
return count_;
}
@@ -306,9 +294,6 @@ namespace mln
inline
histo2d<V>::operator result() const
{
- trace::entering("mln::accu::stat::histo2d::operator result");
-
- trace::exiting("mln::accu::stat::histo2d::operator result");
return count_;
}
@@ -316,10 +301,8 @@ namespace mln
inline
bool histo2d<V>::is_valid() const
{
- trace::entering("mln::accu::stat::histo2d::is_valid");
bool result = count_.is_valid();
- trace::exiting("mln::accu::stat::histo2d::is_valid");
return result;
}
@@ -327,7 +310,7 @@ namespace mln
bool operator==(const histo2d<V>& histo1,
const histo2d<V>& histo2)
{
- trace::entering("mln::accu::stat::operator==");
+ trace::entering("mln::accu::stat::histo2d::operator==");
bool result = true;
const image2d<unsigned>& res1 = histo1.to_result();
@@ -342,11 +325,11 @@ namespace mln
for_all_2(p1, p2)
result &= (res1(p1) == res2(p2));
- trace::exiting("mln::accu::stat::operator==");
+ trace::exiting("mln::accu::stat::histo2d::operator==");
return result;
}
-#endif // ! MLN_INCLUDE_ONLY
+# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::accu::stat
diff --git a/scribo/sandbox/green/mln/accu/stat/histo3d_hsl.hh b/scribo/sandbox/green/mln/accu/stat/histo3d_hsl.hh
index c84aaa4..35d78e2 100644
--- a/scribo/sandbox/green/mln/accu/stat/histo3d_hsl.hh
+++ b/scribo/sandbox/green/mln/accu/stat/histo3d_hsl.hh
@@ -1,6 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -26,82 +24,115 @@
// executable file might be covered by the GNU General Public License.
#ifndef MLN_ACCU_STAT_HISTO3D_HSL_HH
-#define MLN_ACCU_STAT_HISTO3D_HSL_HH
+# define MLN_ACCU_STAT_HISTO3D_HSL_HH
/// \file
///
-/// \brief Define a histogram as an accumulator which returns an image1d .
+/// \brief Define a histogram as accumulator which returns an HSL image3d.
+///
+/// This source implements the discrete histogram version. It was
+/// created for images which the values are derived from integer
+/// type. The number of bins is given by the user via the q parameter.
+/// It works for HSL space.
///
-/// This source implements the discrete histogram version. The number of beans
-/// is infer from the number of greylevels. A typical int_u8 image has got
-/// 256 bins. An int_u16 image has got 65535 bins.
/// The following sample is a typical use of the histogram.
///
-/// #include <mln/value/int_u8.hh>
-/// #include <mln/core/image/image1d.hh>
+/// #include <mln/accu/stat/histo3d_hsl.hh>
/// #include <mln/core/image/image2d.hh>
-/// #include <mln/io/pgm/load.hh>
-/// #include <mln/accu/stat/histo1d.hh>
+/// #include <mln/core/image/image3d.hh>
/// #include <mln/data/compute.hh>
-/// #include <mln/io/plot/save_histo_sh.hh>
-///
-/// #define OLENA_LENA "/usr/local/share/olena/images/lena.pgm"
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb_to_hsl.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/hsl.hh>
+/// #include <mln/value/rgb8.hh>
///
-/// void test()
+/// int main()
/// {
-/// typedef mln::value::int_u8 int_u8;
-/// mln::image2d<int_u8> img_ref;
-/// mln::image1d<unsigned> img_res;
+/// typedef mln::value::rgb8 t_rgb;
+/// typedef mln::value::hsl_f t_hsl;
+/// typedef mln::fun::v2v::f_rgb_to_hsl_<t_hsl> t_rgb_to_hsl;
+/// mln::image2d<t_rgb> img_rgb;
+/// mln::image2d<t_hsl> img_hsl;
+/// mln::image3d<unsigned> histo;
+///
+/// mln::io::ppm::load(img_rgb, OLENA_IMG_PATH"/lena.ppm");
+/// img_hsl = mln::data::transform(img_rgb, t_rgb_to_hsl());
+/// histo=mln::data::compute(mln::accu::meta::stat::histo3d_hsl<7>(),img_hsl);
///
-/// mln::io::pgm::load(img_ref, OLENA_LENA);
-/// img_res = mln::data::compute(mln::accu::stat::histo1d<int_u8>(), img_ref);
+/// return 0;
/// }
+///
+/// \fixme This implementation is very doubtfull ! Be carefull !!
+/// \fixme This code should be compile, but it doesn't!
+/// \fixme The fold interface has changed v2v -> p2p or the inverse.
+
+# include <iostream>
-#include <iostream>
+# include <mln/accu/internal/base.hh>
-#include <mln/accu/internal/base.hh>
+# include <mln/arith/plus.hh>
-#include <mln/core/macros.hh>
-#include <mln/core/image/image3d.hh>
-#include <mln/core/alias/point3d.hh>
-#include <mln/core/alias/box3d.hh>
+# include <mln/core/alias/point3d.hh>
+# include <mln/core/alias/box3d.hh>
+# include <mln/core/image/image3d.hh>
+# include <mln/core/image/dmorph/transformed_image.hh>
+# include <mln/core/macros.hh>
-#include <mln/value/int_u.hh>
-#include <mln/trait/value/comp.hh>
+# include <mln/fun/p2p/fold.hh>
-#include <mln/arith/plus.hh>
+# include <mln/literal/zero.hh>
-#include <mln/trace/entering.hh>
-#include <mln/trace/exiting.hh>
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
-#include <mln/value/ops.hh>
+# include <mln/trait/value/comp.hh>
-// make hue cyclic
-#include <mln/fun/p2p/fold.hh>
-#include <mln/core/image/dmorph/transformed_image.hh>
+# include <mln/value/int_u.hh>
+# include <mln/value/ops.hh>
namespace mln
{
-
+
namespace accu
{
-
+
namespace stat
{
-
+
// Forward declaration
template <unsigned q, typename V>
struct histo3d_hsl;
} // end of namespace mln::accu::stat
-
- } // end of namespace mln::accu
+ namespace meta
+ {
+
+ namespace stat
+ {
+
+ template <unsigned q>
+ struct histo3d_hsl : public Meta_Accumulator< histo3d_hsl<q> >
+ {
+ template <typename V>
+ struct with
+ {
+ typedef accu::stat::histo3d_hsl<q,V> ret;
+ };
+ };
+
+ } // end of namespace mln::accu::meta::stat
+
+ } // end of namespace mln::accu::meta
+
+ } // end of namespace mln::accu
namespace trait
{
-
+
template <unsigned q, typename V>
struct accumulator_< mln::accu::stat::histo3d_hsl<q,V> >
{
@@ -112,65 +143,59 @@ namespace mln
};
template <unsigned q, typename V>
- struct set_precise_binary_<op::eq,
+ struct set_precise_binary_<op::eq,
accu::stat::histo3d_hsl<q,V>,
accu::stat::histo3d_hsl<q,V> >
{
typedef bool ret;
};
-
+
} // end of namespace mln::trait
namespace accu
{
-
+
namespace stat
- {
+ {
- /// \brief Define an histogram which returns an image1d .
+
+ /// \brief Define a histogram as accumulator which returns an image3d.
///
- /// Param V defines the space in which we count the values.
- /// For instance, this histogram works image2d<int_u8> or
- /// image1d<int_u16>. The histogram count the occurrence of each value.
- /// The number of bins depends of the greyscale values, for 8 bits there
- /// is 256 bins, for 16 bits there is 65536 bins. Note that over
- /// quantification works too.
+ /// Param q defines the number of bins per axe.
+ /// Param V defines the type of the input image value. We assume that
+ /// V is a kind of hsl_<float,float,float>.
///
/// \ingroup modaccuvalues
-
- /// q is the number of bins per axe because quantification info are died.
- /// we assume that V is a kind of hsl_<float,float,float>
-
template <unsigned q, typename V>
- struct histo3d_hsl :
+ struct histo3d_hsl :
public mln::accu::internal::base<image3d<unsigned>, histo3d_hsl<q,V> >
{
typedef V argument;
typedef image3d<unsigned> result;
typedef result q_result;
- /// Constructors
+ /// Constructors.
/// \{
- /// \brief Initialize the size of the resulting image1d.
+ /// \brief Infer the size of the resulting image3d domain.
///
- /// Initialize the size the resulting image from the theorical dynamic
- /// of the greylevel values (Use V to manage it).
+ /// By evaluating the minimum and the maximum of V, we define the domain
+ /// of the resulting image3d.
histo3d_hsl();
/// \}
-
+
/// Manipulators.
/// \{
/// \brief Initialize the histogram with zero value.
///
- /// This method must be called just before starting the use of the
- /// histogram. If it's not, resulting values won't converge to the
+ /// This method must be called just before starting the use of the
+ /// histogram. If it's not, resulting values won't converge to the
/// density.
void init();
-
+
/// \brief Update the histogram with the RGB pixel t.
- /// \param[in] t a greylevel pixel of type V.
+ /// \param[in] t a graylevel pixel of type V.
///
/// The end user shouldn't call this method. In place of it, he can
/// go through the data compute interface.
@@ -179,12 +204,15 @@ namespace mln
/// \brief Update the histogram with an other histogram.
/// \param[in] other the other histogram.
+ ///
+ /// The end user shouldn't call this method. This is part of
+ /// data compute interface mechanism.
void take(const histo3d_hsl<q,V>& other);
/// \}
/// Accessors.
/// \{
- /// \brief Return the histogram as an image1d.
+ /// \brief Return the histogram as an HSL image3d.
///
/// This is the machinery to communicate with data compute interface.
/// The end user should'nt use it.
@@ -208,31 +236,31 @@ namespace mln
const float min_sat;
const float max_sat;
float step_sat;
- result count_;
+ result count_;
};
/// \brief Check wethever an histogram is equal to an other one.
/// \param[in] histo1 the first histogram to compare with.
/// \param[in] histo2 the second histogram.
///
- /// The operator compare all the bins from the two histogram.
-
+ /// The operator compares all the bins from the two histograms.
+ /// Nobody uses this method unless unitary tests.
template <unsigned q, typename V>
- bool operator==(const histo3d_hsl<q,V>& histo1,
+ bool operator==(const histo3d_hsl<q,V>& histo1,
const histo3d_hsl<q,V>& histo2);
-#ifndef MLN_INCLUDE_ONLY
+# ifndef MLN_INCLUDE_ONLY
template <unsigned q, typename V>
inline
histo3d_hsl<q,V>::histo3d_hsl() : min_hue(0.0), max_hue(360.0),
- min_lum(0.0), max_lum(1.0),
- min_sat(0.0), max_sat(1.0)
+ min_lum(0.0), max_lum(1.0),
+ min_sat(0.0), max_sat(1.0)
{
- trace::entering("mln::accu::stat::histo3d_hsl<q,V>::histo3d_hsl");
-
- // As there is no info about preceding color space
- // we ask the end user to specify the quantification he's looking for.
+ trace::entering("mln::accu::stat::histo3d_hsl::cstor");
+
+ /// As there is no info about preceding color space
+ /// we ask the end user to specify the quantification he's looking for.
count_.init_(box3d(point3d(mln_min(value::int_u<q>),
mln_min(value::int_u<q>),
@@ -241,7 +269,7 @@ namespace mln
mln_max(value::int_u<q>),
mln_max(value::int_u<q>))));
- // Make the hue domain cyclic
+ /// Make the hue domain cyclic
fun::p2p::fold<point3d,1,0,0> fold_(count_.domain());
transform_domain(count_, fold_);
@@ -249,39 +277,34 @@ namespace mln
step_lum = (max_lum - min_lum)/q;
step_sat = (max_sat - min_sat)/q;
- trace::exiting("mln::accu::stat::histo3d_hsl<q,V>::histo3d_hsl");
+ trace::exiting("mln::accu::stat::histo3d_hsl::cstor");
}
template <unsigned q, typename V>
inline
void histo3d_hsl<q,V>::init()
{
- trace::entering("mln::accu::stat::histo3d_hsl<q,V>::init");
-
- data::fill(count_, 0);
- trace::exiting("mln::accu::stat::histo3d_hsl<q,V>::init");
+ data::fill(count_, literal::zero);
}
template <unsigned q, typename V>
inline
void histo3d_hsl<q,V>::take(const argument& t)
{
- trace::entering("mln::accu::stat::histo3d_hsl<q,V>::take");
-
- // Just convert a greyscale value (int_u8 like) to a position for an
+ // Just convert a greyscale value (int_u8 like) to a position for an
// iterator on the resulting image.
//++count_(point3d(t.red(), t.green(), t.blue()));
-
-
+
+
// Technical way to access i° component without kwnowing the name
// mln::trait::value_<argument>::get_comp_0(t);
-
+
// is def::coord1d the type of x, y, z ??
unsigned x = (t.hue() - min_hue)/step_hue;
- unsigned y = (t.lum() - min_lum)/step_lum;
- unsigned z = (t.sat() - min_sat)/step_sat;
+ unsigned y = (t.sat() - min_sat)/step_sat;
+ unsigned z = (t.lum() - min_lum)/step_lum;
/*
-
+
std::cout << "H : " << t.hue() << std::endl;
std::cout << "L : " << t.lum() << std::endl;
std::cout << "S : " << t.sat() << std::endl;
@@ -295,66 +318,50 @@ namespace mln
std::cout << "Z : " << z << std::endl;
*/
- // faire attention avec les histoires de points et leurs coordonnées
++count_(point3d(z, x, y));
- //++count_(point3d(t.hue(), t.sat(), t.lum()));
-
- trace::exiting("mln::accu::stat::histo3d_hsl<q,V>::take");
}
-
+
template <unsigned q, typename V>
inline
void histo3d_hsl<q,V>::take(const histo3d_hsl<q,V>& other)
{
- trace::entering("mln::accu::stat::histo3d_hsl<q,V>::take");
-
count_ += other.count_;
-
- trace::exiting("mln::accu::stat::histo3d_hsl<q,V>::take");
}
-
+
template <unsigned q, typename V>
inline
typename histo3d_hsl<q,V>::result histo3d_hsl<q,V>::to_result() const
{
- trace::entering("mln::accu::stat::histo3d_hsl<q,V>::to_result");
-
- trace::exiting("mln::accu::stat::histo3d_hsl<q,V>::to_result");
return count_;
}
-
+
template <unsigned q, typename V>
inline
histo3d_hsl<q,V>::operator result() const
{
- trace::entering("mln::accu::stat::histo3d_rgb<q,V>::operator result");
-
- trace::exiting("mln::accu::stat::histo3d_rgb<q,V>::operator result");
return count_;
- }
+ }
template <unsigned q, typename V>
inline
bool histo3d_hsl<q,V>::is_valid() const
{
- trace::entering("mln::accu::stat::histo3d_hsl<q,V>::is_valid");
bool result = count_.is_valid();
-
- trace::exiting("mln::accu::stat::histo3d_hsl<q,V>::is_valid");
+
return result;
}
template <unsigned q, typename V>
- bool operator==(const histo3d_hsl<q,V>& histo1,
+ bool operator==(const histo3d_hsl<q,V>& histo1,
const histo3d_hsl<q,V>& histo2)
{
- trace::entering("mln::accu::stat::operator==");
+ trace::entering("mln::accu::stat::histo3d_hsl::operator==");
bool result = true;
const image3d<unsigned>& res1 = histo1.to_result();
const image3d<unsigned>& res2 = histo2.to_result();
-
+
mln_precondition(res1.is_valid());
mln_precondition(res2.is_valid());
@@ -364,11 +371,11 @@ namespace mln
for_all_2(p1, p2)
result &= (res1(p1) == res2(p2));
- trace::exiting("mln::accu::stat::operator==");
+ trace::exiting("mln::accu::stat::histo3d_hsl::operator==");
return result;
}
-#endif // ! MLN_INCLUDE_ONLY
+# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::accu::stat
@@ -377,4 +384,4 @@ namespace mln
} // end of namespace mln
-#endif // ! MLN_ACCU_STAT_HISTO3D_RGB_HH
+#endif // ! MLN_ACCU_STAT_HISTO3D_HSL_HH
diff --git a/scribo/sandbox/green/mln/accu/stat/histo3d_rgb.hh b/scribo/sandbox/green/mln/accu/stat/histo3d_rgb.hh
index 48c49da..6a48024 100644
--- a/scribo/sandbox/green/mln/accu/stat/histo3d_rgb.hh
+++ b/scribo/sandbox/green/mln/accu/stat/histo3d_rgb.hh
@@ -1,6 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -26,54 +24,67 @@
// executable file might be covered by the GNU General Public License.
#ifndef MLN_ACCU_STAT_HISTO3D_RGB_HH
-#define MLN_ACCU_STAT_HISTO3D_RGB_HH
+# define MLN_ACCU_STAT_HISTO3D_RGB_HH
/// \file
///
-/// \brief Define a histogram as an accumulator which returns an image1d .
+/// \brief Define a histogram as accumulator which returns an image3d.
+///
+/// This source implements the discrete histogram version. It was
+/// created for images which the values are derived from integer
+/// type. The number of bins is directly infered from the cardinality
+/// of the image value. It works for RGB space. See histo1d.hh for limitations
+/// of such implementation. 8 bits quantification is very
+/// expensive, it produces image3d with [0..255,0..255,0..255] as domain.
///
-/// This source implements the discrete histogram version. The number of beans
-/// is infer from the number of greylevels. A typical rgb8 image has got
-/// 256x3 bins. Working with a 8 bit quantification in rgb is very costly.
/// The following sample is a typical use of the histogram.
///
-/// #include <mln/value/rgb.hh>
-/// #include <mln/core/image/image1d.hh>
-/// #include <mln/core/image/image3d.hh>
-/// #include <mln/io/ppm/load.hh>
/// #include <mln/accu/stat/histo3d_rgb.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/core/image/image3d.hh>
/// #include <mln/data/compute.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb8_to_rgbn.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/rgb.hh>
+/// #include <mln/value/rgb8.hh>
///
-/// #define OLENA_LENA ""/usr/local/share/olena/images/lena.ppm"
-///
-/// void test()
+/// int main()
/// {
-/// typedef mln::value::rgb<7> rgb7;
-/// mln::image2d<rgb7> img_ref;
-/// mln::image3d<unsigned> img_res;
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::value::rgb<7> t_rgb7;
+/// mln::image2d<t_rgb8> img_rgb8;
+/// mln::image2d<t_rgb7> img_rgb7;
+/// mln::image3d<unsigned> histo;
///
-/// mln::io::ppm::load(img_ref, OLENA_LENA);
-/// img_res=mln::data::compute(mln::accu::meta::stat::histo3d_rgb(),img_ref);
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+/// img_rgb7 =mln::data::transform(img_rgb8,mln::fun::v2v::rgb8_to_rgbn<7>());
+/// histo = mln::data::compute(mln::accu::meta::stat::histo3d_rgb(),img_rgb7);
+///
+/// return 0;
/// }
-#include <iostream>
+# include <iostream>
+
+# include <mln/accu/internal/base.hh>
-#include <mln/accu/internal/base.hh>
+# include <mln/arith/plus.hh>
-#include <mln/core/macros.hh>
-#include <mln/core/image/image3d.hh>
-#include <mln/core/alias/point3d.hh>
-#include <mln/core/alias/box3d.hh>
+# include <mln/core/macros.hh>
+# include <mln/core/image/image3d.hh>
+# include <mln/core/alias/point3d.hh>
+# include <mln/core/alias/box3d.hh>
-#include <mln/trait/value/comp.hh>
+# include <mln/literal/zero.hh>
-#include <mln/arith/plus.hh>
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
-#include <mln/trace/entering.hh>
-#include <mln/trace/exiting.hh>
+# include <mln/trait/value/comp.hh>
-#include <mln/value/ops.hh>
+# include <mln/value/ops.hh>
namespace mln
{
@@ -140,13 +151,13 @@ namespace mln
namespace stat
{
- /// \brief Define an histogram which returns an image3d .
+ /// \brief Define a histogram as accumulator which returns an image3d.
///
- /// Param V defines the space in which we count the values.
- /// For instance, this histogram works image2d<rgb<2>> or
- /// image2d<rgb<7>>. The histogram count the occurrence of each value.
- /// The number of bins depends of the grayscale values, for 8 bits there
- /// is 256x3 bins. Note that over
+ /// Param V defines the type of the input image value. It is in
+ /// this space that we count the values. For instance, this
+ /// histogram works well for image2d< rgb<2> > or with image2d<
+ /// rgb<7> >. The number of bins depends directly the values V.
+ /// For 8 bits there is 256x3 bins. Note that less
/// quantification works too.
///
/// \ingroup modaccuvalues
@@ -159,16 +170,15 @@ namespace mln
typedef image3d<unsigned> result;
typedef result q_result;
- /// Constructors
+ /// Constructors.
/// \{
- /// \brief Initialize the size of the resulting image1d.
+ /// \brief Infer the size of the resulting image3d domain.
///
- /// Initialize the size the resulting image from the theorical dynamic
- /// of the greylevel values (Use V to manage it).
+ /// By evaluating the minimum and the maximum of V, we define the domain
+ /// of the resulting image3d.
histo3d_rgb();
/// \}
-
/// Manipulators.
/// \{
/// \brief Initialize the histogram with zero value.
@@ -180,7 +190,7 @@ namespace mln
/// \brief Update the histogram with the RGB pixel t.
- /// \param[in] t a greylevel pixel of type V.
+ /// \param[in] t a graylevel pixel of type V.
///
/// The end user shouldn't call this method. In place of it, he can
/// go through the data compute interface.
@@ -189,12 +199,15 @@ namespace mln
/// \brief Update the histogram with an other histogram.
/// \param[in] other the other histogram.
+ ///
+ /// The end user shouldn't call this method. This is part of
+ /// data compute interface mechanism.
void take(const histo3d_rgb<V>& other);
/// \}
/// Accessors.
/// \{
- /// \brief Return the histogram as an image1d.
+ /// \brief Return the histogram as an RGB image3d.
///
/// This is the machinery to communicate with data compute interface.
/// The end user should'nt use it.
@@ -216,19 +229,19 @@ namespace mln
/// \param[in] histo1 the first histogram to compare with.
/// \param[in] histo2 the second histogram.
///
- /// The operator compare all the bins from the two histogram.
-
+ /// The operator compares all the bins from the two histograms.
+ /// Nobody uses this method unless unitary tests.
template <typename V>
bool operator==(const histo3d_rgb<V>& histo1,
const histo3d_rgb<V>& histo2);
-#ifndef MLN_INCLUDE_ONLY
+# ifndef MLN_INCLUDE_ONLY
template <typename V>
inline
histo3d_rgb<V>::histo3d_rgb()
{
- trace::entering("mln::accu::stat::histo3d_rgb<V>::histo3d_rgb");
+ trace::entering("mln::accu::stat::histo3d_rgb::cstor");
typedef mln_trait_value_comp(V,0) comp0;
typedef mln_trait_value_comp(V,1) comp1;
typedef mln_trait_value_comp(V,2) comp2;
@@ -244,31 +257,24 @@ namespace mln
mln_max(comp1),
mln_max(comp2))));
- trace::exiting("mln::accu::stat::histo3d_rgb<V>::histo3d_rgb");
+ trace::exiting("mln::accu::stat::histo3d_rgb::cstor");
}
template <typename V>
inline
void histo3d_rgb<V>::init()
{
- trace::entering("mln::accu::stat::histo3d_rgb<V>::init");
-
- data::fill(count_, 0);
- trace::exiting("mln::accu::stat::histo3d_rgb<V>::init");
+ data::fill(count_, literal::zero);
}
template <typename V>
inline
void histo3d_rgb<V>::take(const argument& t)
{
- trace::entering("mln::accu::stat::histo3d_rgb<V>::take");
-
// Just convert a greyscale value (int_u8 like) to a position for an
// iterator on the resulting image.
// Take care to the constructor : Point(slice, row, column)
++count_(point3d(t.blue(), t.red(), t.green()));
-
- trace::exiting("mln::accu::stat::histo3d_rgb<V>::take");
}
@@ -276,20 +282,13 @@ namespace mln
inline
void histo3d_rgb<V>::take(const histo3d_rgb<V>& other)
{
- trace::entering("mln::accu::stat::histo3d_rgb<V>::take");
-
count_ += other.count_;
-
- trace::exiting("mln::accu::stat::histo3d_rgb<V>::take");
}
template <typename V>
inline
typename histo3d_rgb<V>::result histo3d_rgb<V>::to_result() const
{
- trace::entering("mln::accu::stat::histo3d_rgb<V>::to_result");
-
- trace::exiting("mln::accu::stat::histo3d_rgb<V>::to_result");
return count_;
}
@@ -297,9 +296,6 @@ namespace mln
inline
histo3d_rgb<V>::operator result() const
{
- trace::entering("mln::accu::stat::histo3d_rgb<V>::operator result");
-
- trace::exiting("mln::accu::stat::histo3d_rgb<V>::operator result");
return count_;
}
@@ -307,10 +303,8 @@ namespace mln
inline
bool histo3d_rgb<V>::is_valid() const
{
- trace::entering("mln::accu::stat::histo3d_rgb<V>::is_valid");
bool result = count_.is_valid();
- trace::exiting("mln::accu::stat::histo3d_rgb<V>::is_valid");
return result;
}
@@ -318,7 +312,7 @@ namespace mln
bool operator==(const histo3d_rgb<V>& histo1,
const histo3d_rgb<V>& histo2)
{
- trace::entering("mln::accu::stat::operator==");
+ trace::entering("mln::accu::stat::histo3d_rgb::operator==");
bool result = true;
const image3d<unsigned>& res1 = histo1.to_result();
@@ -333,11 +327,11 @@ namespace mln
for_all_2(p1, p2)
result &= (res1(p1) == res2(p2));
- trace::exiting("mln::accu::stat::operator==");
+ trace::exiting("mln::accu::stat::histo3d_rgb::operator==");
return result;
}
-#endif // ! MLN_INCLUDE_ONLY
+# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::accu::stat
diff --git a/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh b/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
index 2918b1a..acf1b5e 100644
--- a/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
+++ b/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
@@ -1,6 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -35,6 +33,37 @@
/// \file
///
/// \brief Convert rgb8 value to rgbn, n < 8.
+///
+/// The source implements the reduction of quantification for any size less 8.
+///
+/// The following sample is a typical use of the histogram.
+///
+/// #include <mln/accu/stat/histo3d_rgb.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/core/image/image3d.hh>
+/// #include <mln/data/compute.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb8_to_rgbn.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/rgb.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::value::rgb<7> t_rgb7;
+/// mln::image2d<t_rgb8> img_rgb8;
+/// mln::image2d<t_rgb7> img_rgb7;
+/// mln::image3d<unsigned> histo;
+///
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+/// img_rgb7 =mln::data::transform(img_rgb8,mln::fun::v2v::rgb8_to_rgbn<7>());
+/// histo = mln::data::compute(mln::accu::meta::stat::histo3d_rgb(),img_rgb7);
+///
+/// return 0;
+/// }
+
namespace mln
{
@@ -45,16 +74,24 @@ namespace mln
namespace v2v
{
- /// \brief Convert rgb8 value to rgbn, n < 8.
+ /// \brief Convert a rgb8 value to a rgn, n < 8.
+ ///
+ /// Param n defines the output quantification used for the transformation.
///
/// \ingroup modfunv2v
-
template <unsigned n>
struct rgb8_to_rgbn : Function_v2v< rgb8_to_rgbn<n> >
{
typedef value::rgb8 argument;
typedef value::rgb<n> result;
+ /// \brief Convert a rgb8 value to a rgn, n < 8.
+ ///
+ /// \param[in] v the rgb8 value to convert.
+ ///
+ /// Conversion is done by computing the size by which we
+ /// divide each rgb component.
+
result operator()(const argument& c) const
{
mln_precondition(8 > n);
@@ -65,7 +102,7 @@ namespace mln
std::cout << "red : " << c.red() << std::endl;
std::cout << "size : " << size << std::endl;
std::cout << "res : " << (c.red() / size) << std::endl;
- std::cout << "max : " << (mln_max(mln::value::int_u<n>)) << std::endl;
+ std::cout << "max : " << (mln_max(mln::value::int_u<n>))<< std::endl;
*/
result res(c.red() / size, c.green() / size, c.blue() / size);
diff --git a/scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh
index d4c1e46..e9450e1 100644
--- a/scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh
+++ b/scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh
@@ -81,7 +81,6 @@ namespace mln
/// Param n defines the quantification used for rgb space and rg space.
///
/// \ingroup modfunv2v
-
template <unsigned n>
struct rgb_to_rg : Function_v2v< rgb_to_rg<n> >
{
@@ -95,7 +94,6 @@ namespace mln
/// Conversion is done by calling the rg constructor. There is
/// no modification of values. The red/green fields from rgb the value
/// are preserved. Blue value is dropped.
-
result operator()(const argument& v) const
{
return value::rg<n>(v);
diff --git a/scribo/sandbox/green/tests/accu/stat/histo1d/histo1d.cc b/scribo/sandbox/green/tests/accu/stat/histo1d/histo1d.cc
index 5a5c4c4..2fdc7dd 100644
--- a/scribo/sandbox/green/tests/accu/stat/histo1d/histo1d.cc
+++ b/scribo/sandbox/green/tests/accu/stat/histo1d/histo1d.cc
@@ -1,21 +1,507 @@
-/// TEST HISTO1D
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// \brief This source manages unitary testing on image1d histogram component.
+///
+/// Tests are performed in 8 bits and also in 14 bits quantification. The goal
+/// is to go through each programmatic flow to verify the conformity of the
+/// code. It sounds like a theoritic model of unitary testing for milena.
+/// The last test enables statistic computations on that component.
+
+#include <mln/accu/math/count.hh>
+#include <mln/accu/math/sum.hh>
#include <mln/accu/stat/histo1d.hh>
+#include <mln/accu/stat/mean.hh>
+#include <mln/accu/stat/variance.hh>
+
+#include <mln/core/alias/box1d.hh>
+#include <mln/core/alias/point1d.hh>
+#include <mln/core/contract.hh>
+#include <mln/core/grids.hh>
+#include <mln/core/routine/initialize.hh>
+
#include <mln/data/compute.hh>
-#include <mln/core/image/image1d.hh>
-#include <mln/core/image/image2d.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/int_u16_to_int_u14.hh>
+
#include <mln/img_path.hh>
+
#include <mln/io/pgm/load.hh>
+
+#include <mln/math/sqr.hh>
+#include <mln/math/abs.hh>
+
#include <mln/value/int_u8.hh>
+#include <mln/value/int_u16.hh>
+
+
+/// Specific histogram accumulators.
+/// \{
+/// \brief Define statistical accumulator for histogram.
+///
+/// Here, some histogram accumulators are defined, the sum of the frequencies,
+/// the average, the variance.
+
+double count_histo(const mln::image1d<unsigned> img)
+{
+ mln_precondition(img.is_valid());
+
+ double result = 0.0;
+ double value = 0.0;
+ mln_piter_(mln::image1d<unsigned>) p(img.domain());
+
+ for_all(p)
+ {
+ value = img(p);
+ result += value;
+ }
+
+ return result;
+}
+
+double mean_histo(mln::image1d<unsigned> img)
+{
+ mln_precondition(img.is_valid());
+
+ double value = 0.0;
+ double site = 0.0;
+ double count = 0.0;
+ double sum = 0.0;
+ double result = 0.0;
+ mln_piter_(mln::image1d<unsigned>) p(img.domain());
+
+ for_all(p)
+ {
+ value = img(p);
+ site = p.ind();
+ count += value;
+ sum += site * value;
+ }
+
+ result = sum / count;
+
+ return result;
+}
+
+
+/// \fixme there is a conversion type problem with the interface of iterator p.
+
+double var_histo(const mln::image1d<unsigned> img)
+{
+ mln_precondition(img.is_valid());
+
+ double value = 0.0;
+ double site = 0.0;
+ // FIXME: such variables value and site are necessary to obtain the
+ // well computation of the variance.
+
+ double count = 0.0;
+ double sum = 0.0;
+ double sum2 = 0.0;
+ double result = 0.0;
+ mln_piter_(mln::image1d<unsigned>) p(img.domain());
+
+ for_all(p)
+ {
+ value = img(p);
+ site = p.ind();
+ count += value;
+ sum += site * value;
+ sum2 += mln::math::sqr(site) * value;
+ }
+
+ result = sum2 / count - (sum / count) * (sum / count);
+
+ return result;
+}
+
+
+/// \fixme there is a conversion type problem with the interface of iterator p.
+
+double var_histo2(const mln::image1d<unsigned> img)
+{
+ mln_precondition(img.is_valid());
+
+ double value = 0.0;
+ double site = 0.0;
+ // FIXME: such variables value and site are necessary to obtain the
+ // well computation of the variance.
+
+ double count = count_histo(img);
+ double mean = mean_histo(img);
+ double result = 0.0;
+ mln_piter_(mln::image1d<unsigned>) p(img.domain());
+
+ for_all(p)
+ {
+ value = img(p);
+ site = p.ind();
+ result += value * mln::math::sqr(site - mean);
+ }
+
+ result /= count;
+
+ return result;
+}
+
+/// \}
+
+
+/// 8-bits testing
+/// \{
+/// \brief This part of the code manages the 8-bits unitary testing.
+///
+/// Many tests are performed such equalities between two histograms,
+/// instantiation without argument, initialization, take interface and
+/// integration.
+///
+/// \fixme the operator != isn't infer from the operator ==.
+
+void test_8bits_operator_equal()
+{
+ using namespace mln::accu::stat;
+
+ typedef mln::value::int_u8 int_u8;
+ mln::accu::stat::histo1d<int_u8> histo1;
+ mln::accu::stat::histo1d<int_u8> histo2;
+ int_u8 val = 3;
+
+ histo1.init();
+ histo2.init();
+
+ mln_assertion(histo1 == histo2);
+
+ histo1.take(val);
+
+ mln_assertion(!(histo1 == histo2));
+ // mln_assertion(histo1 != histo2);
+ // FIXME: DOESN'T WORK !!
+
+ histo2.take(val);
+
+ mln_assertion(histo1 == histo2);
+
+ std::cout << "(08 bits) histo == histo : ok" << std::endl;
+}
+
+void test_8bits_instantiation_without_argument()
+{
+ typedef mln::value::int_u8 int_u8;
+ const mln::accu::stat::histo1d<int_u8> histo;
+ const mln::image1d<unsigned>& res = histo.to_result();
+ const mln::point1d& min = mln::point1d(mln_min(int_u8));
+ const mln::point1d& max = mln::point1d(mln_max(int_u8));
+ const mln::box1d& ref = mln::box1d(min, max);
+
+ mln_assertion(ref == res.domain());
+ mln_assertion(res.is_valid());
+
+ std::cout << "(08 bits) histo<T> histo : ok" << std::endl;
+}
+
+
+void test_8bits_initialization()
+{
+ typedef mln::value::int_u8 int_u8;
+ mln::accu::stat::histo1d<int_u8> histo;
+ mln::image1d<unsigned> img_res = histo.to_result();
+ mln::image1d<unsigned> img_ref;
+
+ mln::initialize(img_ref, img_res);
+ mln::data::fill(img_ref, 0);
+ histo.init();
+
+ unsigned res = mln::data::compute(mln::accu::math::sum<int_u8>(), img_res);
+ unsigned ref = mln::data::compute(mln::accu::math::sum<int_u8>(), img_ref);
+
+ mln_assertion(ref == res);
+
+ std::cout << "(08 bits) histo.init() : ok" << std::endl;
+}
+
+
+void test_8bits_take_argument()
+{
+ typedef mln::value::int_u8 int_u8;
+ mln::accu::stat::histo1d<int_u8> histo1;
+ mln::accu::stat::histo1d<int_u8> histo2;
+ int_u8 val = 3;
+
+ histo1.init();
+ histo2.init();
+ histo1.take(val);
+
+ const mln::image1d<unsigned> img1 = histo1.to_result();
+ const mln::image1d<unsigned> img2 = histo2.to_result();
+
+ const unsigned res = mln::data::compute(mln::accu::math::sum<int_u8>(), img1);
+ const unsigned ref = mln::data::compute(mln::accu::math::sum<int_u8>(), img2);
+
+ mln_assertion(ref == res-1);
+ mln_assertion(1 == img1(mln::point1d(val)));
+
+ std::cout << "(08 bits) histo.take(argument) : ok" << std::endl;
+}
+
+
+void test_8bits_take_other()
+{
+ typedef mln::value::int_u8 int_u8;
+ mln::accu::stat::histo1d<int_u8> histo1;
+ mln::accu::stat::histo1d<int_u8> histo2;
+ mln::accu::stat::histo1d<int_u8> histo3;
+ int_u8 val = 3;
+
+ histo1.init();
+ histo2.init();
+ histo3.init();
+
+ histo1.take(val);
+ histo1.take(val);
+ histo3.take(val);
+ histo2.take(val);
+ histo2.take(histo3);
+
+ mln_assertion(histo1 == histo2);
+
+ std::cout << "(08 bits) histo.take(other) : ok" << std::endl;
+}
+
+void test_8bits_integration()
+{
+ typedef mln::value::int_u8 int_u8;
+ typedef mln::accu::math::count<double> count;
+ typedef mln::accu::math::sum<double> sum;
+ typedef mln::accu::stat::mean<double> mean;
+ typedef mln::accu::stat::variance<double> variance;
+
+ mln::image2d<int_u8> img_ref;
+ mln::image1d<unsigned> img_res;
+
+ mln::io::pgm::load(img_ref, OLENA_IMG_PATH"/lena.pgm");
+
+ const double count_ref = mln::data::compute(count(), img_ref);
+ const double mean_ref = mln::data::compute(mean(), img_ref);
+ const double var_ref = mln::data::compute(variance(), img_ref);
+
+ img_res = mln::data::compute(mln::accu::meta::stat::histo1d(), img_ref);
+
+ const double count_res = count_histo(img_res);
+ const double mean_res = mean_histo(img_res);
+ const double var_res = var_histo(img_res);
+
+ mln_assertion(count_ref == count_res);
+ mln_assertion( mean_ref == mean_res );
+
+ // std::cout << "var_ref : " << var_ref << std::endl;
+ // std::cout << "var_res : " << var_res << std::endl;
+
+ mln_assertion(0.0001 > mln::math::abs(var_ref - var_res));
+
+ std::cout << "(08 bits) test integration : ok" << std::endl;
+}
+
+/// \}
+
+/// 14-bits testing
+/// \{
+/// \brief This part of the code manages the 14-bits unitary testing.
+///
+/// Many tests are performed such equalities between two histograms,
+/// instantiation without argument, initialization, take interface and
+/// integration.
+///
+/// \fixme the operator != isn't infer from the operator ==.
+
+void test_14bits_operator_equal()
+{
+ using namespace mln::accu::stat;
+
+ typedef mln::value::int_u<14> int_u14;
+ mln::accu::stat::histo1d<int_u14> histo1;
+ mln::accu::stat::histo1d<int_u14> histo2;
+ int_u14 val = 3;
+
+ histo1.init();
+ histo2.init();
+
+ mln_assertion(histo1 == histo2);
+
+ histo1.take(val);
+
+ /// FIXME: mln_assertion(histo1 != histo2); doesn't work!!
+ mln_assertion(!(histo1 == histo2));
+
+ histo2.take(val);
+
+ mln_assertion(histo1 == histo2);
+
+ std::cout << "(14 bits) histo == histo : ok" << std::endl;
+}
+
+void test_14bits_instantiation_without_argument()
+{
+ typedef mln::value::int_u<14> int_u14;
+ const mln::accu::stat::histo1d<int_u14> histo;
+ const mln::image1d<unsigned>& res = histo.to_result();
+ const mln::point1d& min =mln::point1d(mln_min(int_u14));
+ const mln::point1d& max =mln::point1d(mln_max(int_u14));
+ const mln::box1d& ref = mln::box1d(min, max);
+
+ mln_assertion(ref == res.domain());
+ mln_assertion(res.is_valid());
+
+ std::cout << "(14 bits) histo<T> histo : ok" << std::endl;
+}
+
+
+void test_14bits_initialization()
+{
+ typedef mln::value::int_u<14> int_u14;
+ mln::accu::stat::histo1d<int_u14> histo;
+ mln::image1d<unsigned> img_res = histo.to_result();
+ mln::image1d<unsigned> img_ref;
+
+ mln::initialize(img_ref, img_res);
+ mln::data::fill(img_ref, 0);
+ histo.init();
+
+ unsigned res = mln::data::compute(mln::accu::math::sum<int_u14>(), img_res);
+ unsigned ref = mln::data::compute(mln::accu::math::sum<int_u14>(), img_ref);
+
+ mln_assertion(ref == res);
+
+ std::cout << "(14 bits) histo.init() : ok" << std::endl;
+}
+
+
+void test_14bits_take_argument()
+{
+ typedef mln::value::int_u<14> int_u14;
+ mln::accu::stat::histo1d<int_u14> histo1;
+ mln::accu::stat::histo1d<int_u14> histo2;
+ int_u14 val = 3;
+
+ histo1.init();
+ histo2.init();
+ histo1.take(val);
+
+ const mln::image1d<unsigned> img1 = histo1.to_result();
+ const mln::image1d<unsigned> img2 = histo2.to_result();
+
+ const unsigned res = mln::data::compute(mln::accu::math::sum<int_u14>(),img1);
+ const unsigned ref = mln::data::compute(mln::accu::math::sum<int_u14>(),img2);
+
+ mln_assertion(ref == res-1);
+ mln_assertion(1 == img1(mln::point1d(val)));
+
+ std::cout << "(14 bits) histo.take(argument) : ok" << std::endl;
+}
+
+
+void test_14bits_take_other()
+{
+ typedef mln::value::int_u<14> int_u14;
+ mln::accu::stat::histo1d<int_u14> histo1;
+ mln::accu::stat::histo1d<int_u14> histo2;
+ mln::accu::stat::histo1d<int_u14> histo3;
+ int_u14 val = 3;
+
+ histo1.init();
+ histo2.init();
+ histo3.init();
+
+ histo1.take(val);
+ histo1.take(val);
+ histo3.take(val);
+ histo2.take(val);
+ histo2.take(histo3);
+
+ mln_assertion(histo1 == histo2);
+
+ std::cout << "(14 bits) histo.take(other) : ok" << std::endl;
+}
+
+void test_14bits_integration()
+{
+ typedef mln::value::int_u16 int_u16;
+ typedef mln::value::int_u<14> int_u14;
+ typedef mln::accu::math::count<double> count;
+ typedef mln::accu::math::sum<double> sum;
+ typedef mln::accu::stat::mean<double> mean;
+ typedef mln::accu::stat::variance<double> variance;
+
+ mln::image2d<int_u16> img_fst;
+ mln::image2d<int_u14> img_ref;
+ mln::image1d<unsigned> img_res;
+
+ mln::io::pgm::load(img_fst, OLENA_IMG_PATH"/lena_16_imageMagick.pgm");
+ img_ref = mln::data::transform(img_fst, mln::fun::v2v::int_u16_to_int_u14());
+
+ const double count_ref = mln::data::compute(count(), img_ref);
+ const double mean_ref = mln::data::compute(mean(), img_ref);
+ const double var_ref = mln::data::compute(variance(), img_ref);
+
+ img_res = mln::data::compute(mln::accu::stat::histo1d<int_u14>(), img_ref);
+
+ const double count_res = count_histo(img_res);
+ const double mean_res = mean_histo(img_res);
+ const double var_res = var_histo2(img_res);
+
+ //std::cout << "var_res : " << var_res << std::endl;
+ //std::cout << "var_ref : " << var_ref << std::endl;
+
+ mln_assertion(count_ref == count_res);
+ mln_assertion( mean_ref == mean_res );
+ mln_assertion(0.0001 > abs(var_ref - var_res));
+
+ std::cout << "(14 bits) test integration : ok" << std::endl;
+}
+
+/// \}
int main()
{
- typedef mln::value::int_u8 t_int_u8;
- mln::image2d<t_int_u8> img;
- mln::image1d<unsigned> histo;
+ test_8bits_operator_equal();
+ test_8bits_instantiation_without_argument();
+ test_8bits_initialization();
+ test_8bits_take_argument();
+ test_8bits_take_other();
+ test_8bits_operator_equal();
+ test_8bits_integration();
- mln::io::pgm::load(img, OLENA_IMG_PATH"/lena.pgm");
- histo = mln::data::compute(mln::accu::meta::stat::histo1d(), img);
+ test_14bits_instantiation_without_argument();
+ test_14bits_initialization();
+ test_14bits_take_argument();
+ test_14bits_take_other();
+ test_14bits_operator_equal();
+ test_14bits_integration();
return 0;
}
diff --git a/scribo/sandbox/green/tests/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/tests/accu/stat/histo3d_hsl/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/tests/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/tests/accu/stat/histo3d_hsl/Makefile.am
diff --git a/milena/sandbox/green/tests/accu/stat/histo3d_hsl/histo3d_hsl.cc b/scribo/sandbox/green/tests/accu/stat/histo3d_hsl/histo3d_hsl.cc
similarity index 73%
copy from milena/sandbox/green/tests/accu/stat/histo3d_hsl/histo3d_hsl.cc
copy to scribo/sandbox/green/tests/accu/stat/histo3d_hsl/histo3d_hsl.cc
index 0a12706..eed377c 100644
--- a/milena/sandbox/green/tests/accu/stat/histo3d_hsl/histo3d_hsl.cc
+++ b/scribo/sandbox/green/tests/accu/stat/histo3d_hsl/histo3d_hsl.cc
@@ -1,66 +1,189 @@
-/// TEST HISTO3D_HSL
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief This source manages unitary testing on rgb image3d histogram.
+///
+/// Tests are performed from 2 bits up to 8 bits quantification. The goal
+/// is to go through each programmatic flow to verify the conformity of the
+/// code. It sounds like a theoritic model of unitary testing for milena.
+/// The last test enables statistic computations on that component.
-#include <mln/img_path.hh>
-
-#include <mln/io/plot/save_histo_sh.hh>
+#include <mln/accu/math/sum.hh>
+#include <mln/accu/math/count.hh>
#include <mln/accu/stat/histo3d_hsl.hh>
-#include <mln/fun/v2v/rgb8_to_rgbn.hh>
-#include <mln/fun/v2v/rgb_to_hsl.hh>
+#include <mln/accu/stat/mean.hh>
+#include <mln/accu/stat/variance.hh>
+#include <mln/accu/stat/var.hh>
-#include <mln/io/ppm/load.hh>
-#include <mln/io/ppm/save.hh>
-#include <mln/io/pfm/save.hh>
-#include <mln/io/plot/save.hh>
+#include <mln/core/alias/box3d.hh>
+#include <mln/core/alias/point3d.hh>
+#include <mln/core/contract.hh>
+#include <mln/core/grids.hh>
+#include <mln/core/routine/initialize.hh>
#include <mln/data/compute.hh>
-#include <mln/data/transform.hh>
#include <mln/data/fill.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb_to_hsl.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/io/ppm/load.hh>
+
+#include <mln/literal/zero.hh>
+
+#include <mln/math/sqr.hh>
+#include <mln/math/abs.hh>
-#include <mln/value/label_8.hh>
#include <mln/value/rgb8.hh>
#include <mln/value/hsl.hh>
-#include <mln/value/rgb.hh>
-#include <mln/value/int_u.hh>
-#include <mln/core/alias/neighb3d.hh>
-#include <mln/core/alias/box3d.hh>
-#include <mln/core/alias/point3d.hh>
+/// Specific histogram accumulators.
+/// \{
+/// \brief Define statistical accumulator for histogram.
+///
+/// Here, some histogram accumulators are defined, the sum of the frequencies,
+/// the average, the variance.
-#include <mln/core/routine/initialize.hh>
-#include <mln/core/contract.hh>
-#include <mln/core/grids.hh>
+double count_histo(const mln::image3d<unsigned>& img)
+{
+ mln_precondition(img.is_valid());
-#include <mln/accu/math/sum.hh>
-#include <mln/accu/math/count.hh>
-#include <mln/accu/stat/mean.hh>
-#include <mln/accu/stat/variance.hh>
-#include <mln/accu/stat/var.hh>
+ double result = 0.0;
+ mln_piter_(mln::image3d<unsigned>) p(img.domain());
-#include <mln/morpho/watershed/flooding.hh>
-#include <mln/morpho/elementary/dilation.hh>
-#include <mln/morpho/elementary/closing.hh>
+ for_all(p)
+ result += img(p);
-#include <mln/literal/zero.hh>
-#include <mln/linear/convolve.hh>
-#include <mln/linear/gaussian.hh>
-#include <mln/labeling/regional_maxima.hh>
-#include <mln/labeling/colorize.hh>
-#include <mln/labeling/mean_values.hh>
+ return result;
+}
-#include <mln/make/w_window3d.hh>
+mln::algebra::vec<3,float> conv(const mln::algebra::vec<3,float>& vec,
+ const unsigned q)
+{
+ mln::algebra::vec<3,float> result;
-#include <mln/math/sqr.hh>
-#include <mln/math/pi.hh>
-#include <mln/math/abs.hh>
+ /*
+ result[0] = vec[2] * (360.0/q);
+ result[1] = vec[0] * (1.0/q);
+ result[2] = vec[1] * (1.0/q);
+ */
+
+ result[0] = (vec[0]+0.5) * (360.0/q);
+ result[1] = (vec[1]+0.5) * (1.0/q);
+ result[2] = (vec[2]+0.5) * (1.0/q);
+
+ return result;
+}
+
+mln::algebra::vec<3,float> mean_histo(const mln::image3d<unsigned>& img,
+ const unsigned q)
+{
+ mln_precondition(img.is_valid());
+ typedef mln::algebra::vec<3,float> vec3f;
+ double count = 0.0;
+ vec3f sum = mln::literal::zero;
+ vec3f result;
+
+ mln_piter_(mln::image3d<unsigned>) p(img.domain());
+
+ for_all(p)
+ {
+ count += img(p);
+ sum += conv((vec3f)p, q) * img(p);
+ }
+
+ result = sum / count;
+
+ return result;
+}
+
+mln::algebra::mat<3,3,float> var_histo(const mln::image3d<unsigned>& img,
+ const unsigned q)
+{
+ mln_precondition(img.is_valid());
+ typedef mln::algebra::vec<3,float> vec3f;
+ typedef mln::algebra::mat<3,3,float> mat3f;
+
+ double count = count_histo(img);
+ vec3f mean = mean_histo(img,q);
+ vec3f point;
+ mat3f result = mln::literal::zero;
+ mln_piter_(mln::image3d<unsigned>) p(img.domain());
+
+ for_all(p)
+ {
+ point = conv((vec3f)p, q) - mean;
+ result += img(p) * (point * point.t());
+ }
-#include <mln/core/image/dmorph/image_if.hh>
-#include <mln/pw/value.hh>
+ result /= count;
+
+ return result;
+}
-#include <mln/trait/image/print.hh>
-#include <mln/trait/value_.hh>
-#include <mln/core/concept/function.hh>
+/// \}
+
+struct hslf_2_vec3f : public mln::Function_v2v< hslf_2_vec3f >
+{
+ typedef mln::algebra::vec<3,float> result;
+ result operator()(const mln::value::hsl_f& hsl) const;
+};
+
+mln::algebra::vec<3,float>
+hslf_2_vec3f::operator()(const mln::value::hsl_f& hsl) const
+{
+ return mln::make::vec(hsl.hue(), hsl.lum(), hsl.sat());
+}
+
+struct hslf_2_h : public mln::Function_v2v< hslf_2_h >
+{
+ typedef float result;
+ result operator()(const mln::value::hsl_f& hsl) const;
+};
+
+float
+hslf_2_h::operator()(const mln::value::hsl_f& hsl) const
+{
+ return hsl.hue();
+}
+/// n-bits testing
+/// \{
+/// \brief This part of the code manages the n-bits unitary testing.
+///
+/// Many tests are performed such equalities between two histograms,
+/// instantiation without argument, initialization, take interface and
+/// integration.
+///
+/// \fixme the operator != isn't infer from the operator ==.
+
template <unsigned n>
void test_operator_equal()
{
@@ -129,7 +252,7 @@ void test_initialization()
unsigned res = mln::data::compute(mln::accu::math::sum<int_un>(), img_res);
unsigned ref = mln::data::compute(mln::accu::math::sum<int_un>(), img_ref);
-
+
mln_assertion(ref == res);
std::cout << "(" << n << " bits) histo.init() : ok" << std::endl;
@@ -184,131 +307,6 @@ void test_take_other()
std::cout << "(" << n << " bits) histo.take(other) : ok" << std::endl;
}
-double count_histo(const mln::image3d<unsigned>& img)
-{
- mln_precondition(img.is_valid());
-
- double result = 0.0;
- mln_piter_(mln::image3d<unsigned>) p(img.domain());
-
- for_all(p)
- result += img(p);
-
- return result;
-}
-
-mln::algebra::vec<3,float> conv(const mln::algebra::vec<3,float>& vec,
- const unsigned q)
-{
- mln::algebra::vec<3,float> result;
-
- /*
- result[0] = vec[2] * (360.0/q);
- result[1] = vec[0] * (1.0/q);
- result[2] = vec[1] * (1.0/q);
- */
-
- result[0] = (vec[0]+0.5) * (360.0/q);
- result[1] = (vec[1]+0.5) * (1.0/q);
- result[2] = (vec[2]+0.5) * (1.0/q);
-
- return result;
-}
-
-mln::algebra::vec<3,float> mean_histo(const mln::image3d<unsigned>& img,
- const unsigned q)
-{
- mln_precondition(img.is_valid());
- typedef mln::algebra::vec<3,float> vec3f;
- double count = 0.0;
- vec3f sum = mln::literal::zero;
- vec3f result;
-
- mln_piter_(mln::image3d<unsigned>) p(img.domain());
-
- for_all(p)
- {
- count += img(p);
- sum += conv((vec3f)p, q) * img(p);
- }
-
- result = sum / count;
-
- return result;
-}
-
-
-double var_histo(const mln::image3d<unsigned>& img)
-{
- mln_precondition(img.is_valid());
- typedef mln::algebra::vec<3,float> vec3f;
- typedef mln::algebra::mat<3,3,float> mat3f;
- double count = 0.0;
- double sum = 0.0;
- double sum2 = 0.0;
- double result = 0.0;
- mln_piter_(mln::image3d<unsigned>) p(img.domain());
-
- for_all(p)
- {
- count += img(p);
- sum += p[0] * img(p);
- sum2 += p[0] * p[0] * img(p);
- }
-
- result = sum2 / count - (sum / count) * (sum / count);
-
- return result;
-}
-
-mln::algebra::mat<3,3,float> var_histo2(const mln::image3d<unsigned>& img,
- const unsigned q)
-{
- mln_precondition(img.is_valid());
- typedef mln::algebra::vec<3,float> vec3f;
- typedef mln::algebra::mat<3,3,float> mat3f;
-
- double count = count_histo(img);
- vec3f mean = mean_histo(img,q);
- vec3f point;
- mat3f result = mln::literal::zero;
- mln_piter_(mln::image3d<unsigned>) p(img.domain());
-
- for_all(p)
- {
- point = conv((vec3f)p, q) - mean;
- result += img(p) * (point * point.t());
- }
-
- result /= count;
-
- return result;
-}
-
-struct hslf_2_vec3f : public mln::Function_v2v< hslf_2_vec3f >
-{
- typedef mln::algebra::vec<3,float> result;
- result operator()(const mln::value::hsl_f& hsl) const;
-};
-
-mln::algebra::vec<3,float>
-hslf_2_vec3f::operator()(const mln::value::hsl_f& hsl) const
-{
- return mln::make::vec(hsl.hue(), hsl.lum(), hsl.sat());
-}
-
-struct hslf_2_h : public mln::Function_v2v< hslf_2_h >
-{
- typedef float result;
- result operator()(const mln::value::hsl_f& hsl) const;
-};
-
-float
-hslf_2_h::operator()(const mln::value::hsl_f& hsl) const
-{
- return hsl.hue();
-}
-
template <unsigned n, unsigned q>
void test_integration()
{
@@ -331,37 +329,27 @@ void test_integration()
mln::image2d<float> img_sav;
mln::io::ppm::load(img_fst, OLENA_IMG_PATH"/lena.ppm");
- //mln::io::ppm::load(img_fst, OLENA_IMG_PATH"/fly.ppm");
- //img_sec = mln::data::transform(img_fst, mln::fun::v2v::rgb8_to_rgbn<n>());
img_thd = mln::data::transform(img_fst,mln::fun::v2v::f_rgb_to_hsl_<hsl_f>());
-
- //img_sav = mln::data::transform(img_thd, hslf_2_h());
- //mln::io::plot::save_histo_sh(img_sav, "lena2.sh");
-
img_ref = mln::data::transform(img_thd, hslf_2_vec3f());
const double count_ref = mln::data::compute(count(), img_ref);
- // const vec3f sum_ref = mln::data::compute(sum(), img_ref);
- const vec3f mean_ref = mln::data::compute(mean(), img_ref);
+ const vec3f mean_ref = mln::data::compute(mean(), img_ref);
const mat3f var_ref = mln::data::compute(var(), img_ref);
- img_res = mln::data::compute(mln::accu::stat::histo3d_hsl<q,hsl_f>(),img_thd);
-
- mln::io::plot::save_histo_sh(img_res, "histo_hsl.sh");
+ img_res = mln::data::compute(mln::accu::meta::stat::histo3d_hsl<q>(),img_thd);
const double count_res = count_histo(img_res);
const vec3f mean_res = mean_histo(img_res, q);
const mat3f var_res = var_histo2(img_res, q);
-
- std::cout << "count_ref : " << count_ref << std::endl;
- std::cout << "mean_ref : " << mean_ref << std::endl;
- std::cout << "var_ref : " << var_ref << std::endl;
- std::cout << "count_res : " << count_res << std::endl;
- std::cout << "mean_res : " << mean_res << std::endl;
- std::cout << "var_res : " << var_res << std::endl;
+ // std::cout << "count_ref : " << count_ref << std::endl;
+ // std::cout << "mean_ref : " << mean_ref << std::endl;
+ // std::cout << "var_ref : " << var_ref << std::endl;
+
+ // std::cout << "count_res : " << count_res << std::endl;
+ // std::cout << "mean_res : " << mean_res << std::endl;
+ // std::cout << "var_res : " << var_res << std::endl;
-
mln_assertion(count_ref == count_res);
/*
@@ -385,39 +373,19 @@ void test_integration()
std::cout << "(" << n << " bits) test integration : ok" << std::endl;
}
-void test()
-{
- typedef mln::value::rgb8 rgb8;
- typedef mln::value::hsl_f hsl_f;
- typedef mln::fun::v2v::f_rgb_to_hsl_<hsl_f> rgb_to_hsl_f;
- mln::image2d<rgb8> img_fst;
- mln::image2d<hsl_f> img_ref;
- rgb_to_hsl_f instance;
- rgb8 rgb(255,127,0);
- hsl_f hsl = instance(rgb);
-
- std::cout << hsl.hue() << std::endl;
- std::cout << hsl.lum() << std::endl;
- std::cout << hsl.sat() << std::endl;
-
+/// \}
- mln::io::ppm::load(img_fst, OLENA_IMG_PATH"/lena.ppm");
- img_ref = mln::data::transform(img_fst, rgb_to_hsl_f());
-
- //mln::accu::stat::histo3d_hsl<hsl_f>();
-
-}
+/// \fixme Should compile but doesn't. Fold problem in histo_hsl.hh.
int main()
{
- /*
+
test_operator_equal<3>();
test_instantiation_without_argument<3>();
test_initialization<3>();
- test_take_argument<3>();
+ test_take_argument<3>();
test_take_other<3>();
- */
test_integration<7,6>();
-
+
return 0;
}
diff --git a/scribo/sandbox/green/tests/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/tests/accu/stat/histo3d_rgb/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/tests/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/tests/accu/stat/histo3d_rgb/Makefile.am
diff --git a/milena/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc b/scribo/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
similarity index 64%
copy from milena/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
copy to scribo/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
index cbf273b..3f87c4d 100644
--- a/milena/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
+++ b/scribo/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
@@ -1,58 +1,152 @@
-/// TEST HISTO3D_RGB
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+///
+/// \brief This source manages unitary testing on rgb image3d histogram.
+///
+/// Tests are performed from 2 bits up to 8 bits quantification. The goal
+/// is to go through each programmatic flow to verify the conformity of the
+/// code. It sounds like a theoritic model of unitary testing for milena.
+/// The last test enables statistic computations on that component.
-#include <mln/img_path.hh>
-
-#include <mln/io/plot/save_histo_sh.hh>
+#include <mln/accu/math/sum.hh>
+#include <mln/accu/math/count.hh>
#include <mln/accu/stat/histo3d_rgb.hh>
-#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+#include <mln/accu/stat/mean.hh>
+#include <mln/accu/stat/variance.hh>
+#include <mln/accu/stat/var.hh>
-#include <mln/io/ppm/load.hh>
-#include <mln/io/ppm/save.hh>
-#include <mln/io/plot/save.hh>
-#include <mln/io/plot/save_histo_sh.hh>
+#include <mln/core/alias/box3d.hh>
+#include <mln/core/alias/point3d.hh>
+#include <mln/core/contract.hh>
+#include <mln/core/grids.hh>
+#include <mln/core/routine/initialize.hh>
#include <mln/data/compute.hh>
-#include <mln/data/transform.hh>
#include <mln/data/fill.hh>
+#include <mln/data/transform.hh>
+
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/io/ppm/load.hh>
+
+#include <mln/literal/zero.hh>
+
+#include <mln/math/sqr.hh>
+#include <mln/math/abs.hh>
-#include <mln/value/label_8.hh>
#include <mln/value/rgb8.hh>
#include <mln/value/rgb.hh>
-#include <mln/value/int_u.hh>
-#include <mln/core/alias/neighb3d.hh>
-#include <mln/core/alias/box3d.hh>
-#include <mln/core/alias/point3d.hh>
+/// Specific histogram accumulators.
+/// \{
+/// \brief Define statistical accumulator for histogram.
+///
+/// Here, some histogram accumulators are defined, the sum of the frequencies,
+/// the average, the variance.
-#include <mln/core/routine/initialize.hh>
-#include <mln/core/contract.hh>
-#include <mln/core/grids.hh>
+double count_histo(const mln::image3d<unsigned>& img)
+{
+ mln_precondition(img.is_valid());
-#include <mln/accu/math/sum.hh>
-#include <mln/accu/math/count.hh>
-#include <mln/accu/stat/mean.hh>
-#include <mln/accu/stat/variance.hh>
-#include <mln/accu/stat/var.hh>
+ double value = 0.0;
+ double result = 0.0;
+ mln_piter_(mln::image3d<unsigned>) p(img.domain());
+
+ for_all(p)
+ {
+ value = img(p);
+ result += value;
+ }
-#include <mln/morpho/watershed/flooding.hh>
-#include <mln/morpho/elementary/dilation.hh>
-#include <mln/morpho/elementary/closing.hh>
+ return result;
+}
-#include <mln/literal/zero.hh>
-#include <mln/linear/convolve.hh>
-#include <mln/linear/gaussian.hh>
-#include <mln/labeling/regional_maxima.hh>
-#include <mln/labeling/colorize.hh>
-#include <mln/labeling/mean_values.hh>
+mln::algebra::vec<3,float> mean_histo(const mln::image3d<unsigned>& img)
+{
+ mln_precondition(img.is_valid());
+ typedef mln::algebra::vec<3,float> vec3f;
+ double value = 0.0;
+ double count = 0.0;
+ vec3f sum = mln::literal::zero;
+ vec3f result;
-#include <mln/make/w_window3d.hh>
+ mln_piter_(mln::image3d<unsigned>) p(img.domain());
-#include <mln/math/sqr.hh>
-#include <mln/math/pi.hh>
-#include <mln/math/abs.hh>
+ for_all(p)
+ {
+ value = img(p);
+ count += value;
+ sum += p.to_vec() * value;
+ }
-#include <mln/core/image/dmorph/image_if.hh>
-#include <mln/pw/value.hh>
+ result = sum / count;
+
+ return result;
+}
+
+
+mln::algebra::mat<3,3,float> var_histo (const mln::image3d<unsigned>& img)
+{
+ mln_precondition(img.is_valid());
+ typedef mln::algebra::vec<3,float> vec3f;
+ typedef mln::algebra::mat<3,3,float> mat3f;
+
+ double value = 0.0;
+ double count = count_histo(img);
+ vec3f mean = mean_histo(img);
+ vec3f point;
+ mat3f result = mln::literal::zero;
+ mln_piter_(mln::image3d<unsigned>) p(img.domain());
+
+ for_all(p)
+ {
+ value = img(p);
+ point = p.to_vec() - mean;
+ result += value * (point * point.t());
+ }
+
+ result /= count;
+
+ return result;
+}
+
+/// \}
+
+/// n-bits testing
+/// \{
+/// \brief This part of the code manages the n-bits unitary testing.
+///
+/// Many tests are performed such equalities between two histograms,
+/// instantiation without argument, initialization, take interface and
+/// integration.
+///
+/// \fixme the operator != isn't infer from the operator ==.
template <unsigned n>
@@ -72,8 +166,10 @@ void test_operator_equal()
histo1.take(val);
- /// FIXME mln_assertion(histo1 != histo2); doesn't work!!
mln_assertion(!(histo1 == histo2));
+ // mln_assertion(histo1 != histo2);
+ // FIXME: DOESN'T WORK !!
+
histo2.take(val);
@@ -118,7 +214,7 @@ void test_initialization()
unsigned res = mln::data::compute(mln::accu::math::sum<int_un>(), img_res);
unsigned ref = mln::data::compute(mln::accu::math::sum<int_un>(), img_ref);
-
+
mln_assertion(ref == res);
std::cout << "(" << n << " bits) histo.init() : ok" << std::endl;
@@ -173,86 +269,7 @@ void test_take_other()
std::cout << "(" << n << " bits) histo.take(other) : ok" << std::endl;
}
-double count_histo(const mln::image3d<unsigned>& img)
-{
- mln_precondition(img.is_valid());
-
- double result = 0.0;
- mln_piter_(mln::image3d<unsigned>) p(img.domain());
-
- for_all(p)
- result += img(p);
-
- return result;
-}
-
-mln::algebra::vec<3,float> mean_histo(const mln::image3d<unsigned>& img)
-{
- mln_precondition(img.is_valid());
- typedef mln::algebra::vec<3,float> vec3f;
- double count = 0.0;
- vec3f sum = mln::literal::zero;
- vec3f result;
-
- mln_piter_(mln::image3d<unsigned>) p(img.domain());
-
- for_all(p)
- {
- count += img(p);
- sum += p.to_vec() * img(p);
- }
-
- result = sum / count;
-
- return result;
-}
-
-
-double var_histo(const mln::image3d<unsigned>& img)
-{
- mln_precondition(img.is_valid());
- typedef mln::algebra::vec<3,float> vec3f;
- typedef mln::algebra::mat<3,3,float> mat3f;
- double count = 0.0;
- double sum = 0.0;
- double sum2 = 0.0;
- double result = 0.0;
- mln_piter_(mln::image3d<unsigned>) p(img.domain());
-
- for_all(p)
- {
- count += img(p);
- sum += p[0] * img(p);
- sum2 += p[0] * p[0] * img(p);
- }
-
- result = sum2 / count - (sum / count) * (sum / count);
-
- return result;
-}
-
-mln::algebra::mat<3,3,float> var_histo2(const mln::image3d<unsigned>& img)
-{
- mln_precondition(img.is_valid());
- typedef mln::algebra::vec<3,float> vec3f;
- typedef mln::algebra::mat<3,3,float> mat3f;
-
- double count = count_histo(img);
- vec3f mean = mean_histo(img);
- vec3f point;
- mat3f result = mln::literal::zero;
- mln_piter_(mln::image3d<unsigned>) p(img.domain());
-
- for_all(p)
- {
- point = p.to_vec() - mean;
- result += img(p) * (point * point.t());
- }
-
- result /= count;
-
- return result;
-}
+/// \fixme When the quantification grows, the computation error grows.
template <unsigned n>
void test_integration()
@@ -277,77 +294,65 @@ void test_integration()
const vec3f sum_ref = mln::data::compute(sum(), img_ref);
const vec3f mean_ref = mln::data::compute(mean(), img_ref);
const mat3f var_ref = mln::data::compute(var(), img_ref);
-
- img_res = mln::data::compute(mln::accu::stat::histo3d_rgb<rgbn>(), img_ref);
- mln::io::plot::save_histo_sh(img_res, "histo_rgb.sh");
+ img_res = mln::data::compute(mln::accu::stat::histo3d_rgb<rgbn>(), img_ref);
const double count_res = count_histo(img_res);
const vec3f mean_res = mean_histo(img_res);
- const mat3f var_res = var_histo2(img_res);
-
- std::cout << "count_ref : " << count_ref << std::endl;
- std::cout << "mean_ref : " << mean_ref << std::endl;
- std::cout << "var_ref : " << var_ref << std::endl;
+ const mat3f var_res = var_histo(img_res);
+
+ // std::cout << "count_ref : " << count_ref << std::endl;
+ // std::cout << "mean_ref : " << mean_ref << std::endl;
+ // std::cout << "var_ref : " << var_ref << std::endl;
+
+ // std::cout << "count_res : " << count_res << std::endl;
+ // std::cout << "mean_res : " << mean_res << std::endl;
+ // std::cout << "var_res : " << var_res << std::endl;
- std::cout << "count_res : " << count_res << std::endl;
- std::cout << "mean_res : " << mean_res << std::endl;
- std::cout << "var_res : " << var_res << std::endl;
-
mln_assertion(count_ref == count_res);
-
- mln_assertion(0.0001 > abs(mean_ref[0] - mean_res[0]));
- mln_assertion(0.0001 > abs(mean_ref[1] - mean_res[1]));
- mln_assertion(0.0001 > abs(mean_ref[2] - mean_res[2]));
- mln_assertion(0.0001 > abs(var_ref(0,0) - var_res(0,0)));
- mln_assertion(0.0001 > abs(var_ref(0,1) - var_res(0,1)));
- mln_assertion(0.0001 > abs(var_ref(1,0) - var_res(1,0)));
+ /// FIXME: The error acceptance seems to high !!
+ mln_assertion(3 > mln::math::abs(mean_ref[0] - mean_res[0]));
+ mln_assertion(3 > mln::math::abs(mean_ref[1] - mean_res[1]));
+ mln_assertion(3 > mln::math::abs(mean_ref[2] - mean_res[2]));
+
+ mln_assertion(3 > mln::math::abs(var_ref(0,0) - var_res(0,0)));
+ mln_assertion(3 > mln::math::abs(var_ref(0,1) - var_res(0,1)));
+ mln_assertion(3 > mln::math::abs(var_ref(1,0) - var_res(1,0)));
- mln_assertion(0.0001 > abs(var_ref(1,1) - var_res(1,1)));
- mln_assertion(0.0001 > abs(var_ref(0,2) - var_res(0,2)));
- mln_assertion(0.0001 > abs(var_ref(2,0) - var_res(2,0)));
+ mln_assertion(3 > mln::math::abs(var_ref(1,1) - var_res(1,1)));
+ mln_assertion(3 > mln::math::abs(var_ref(0,2) - var_res(0,2)));
+ mln_assertion(3 > mln::math::abs(var_ref(2,0) - var_res(2,0)));
+ mln_assertion(3 > mln::math::abs(var_ref(2,2) - var_res(2,2)));
+ mln_assertion(3 > mln::math::abs(var_ref(2,1) - var_res(2,1)));
+ mln_assertion(3 > mln::math::abs(var_ref(1,2) - var_res(1,2)));
- mln_assertion(0.0001 > abs(var_ref(2,2) - var_res(2,2)));
- mln_assertion(0.0001 > abs(var_ref(2,1) - var_res(2,1)));
- mln_assertion(0.0001 > abs(var_ref(1,2) - var_res(1,2)));
-
std::cout << "(" << n << " bits) test integration : ok" << std::endl;
}
+/// \}
+
+/// \fixme Doesn't work with 1 bit, compilation problem.
+
int main()
{
- //
- // Doesn't work with 1 bit, compilation problem
- //
- /*
- test_operator_equal<1>();
- test_instantiation_without_argument<1>();
- test_initialization<1>();
- test_take_argument<1>();
- test_take_other<1>();
- test_integration<1>();
- */
- /*
test_operator_equal<2>();
test_instantiation_without_argument<2>();
test_initialization<2>();
test_take_argument<2>();
test_take_other<2>();
test_integration<2>();
- */
- /*
+
+
test_operator_equal<3>();
test_instantiation_without_argument<3>();
test_initialization<3>();
test_take_argument<3>();
test_take_other<3>();
test_integration<3>();
-
-
test_operator_equal<4>();
test_instantiation_without_argument<4>();
@@ -355,44 +360,38 @@ int main()
test_take_argument<4>();
test_take_other<4>();
test_integration<4>();
-
-
+
test_operator_equal<5>();
test_instantiation_without_argument<5>();
test_initialization<5>();
test_take_argument<5>();
test_take_other<5>();
test_integration<5>();
- */
+
test_operator_equal<6>();
test_instantiation_without_argument<6>();
test_initialization<6>();
test_take_argument<6>();
test_take_other<6>();
test_integration<6>();
-
- /*
+
test_operator_equal<7>();
test_instantiation_without_argument<7>();
test_initialization<7>();
test_take_argument<7>();
test_take_other<7>();
test_integration<7>();
- */
-
+
//
// Do not execute it, unless you have the time :)
//
- /*
- test_operator_equal<8>();
- test_instantiation_without_argument<8>();
- test_initialization<8>();
- test_take_argument<8>();
- test_take_other<8>();
- test_integration<8>();
- */
-
+ // test_operator_equal<8>();
+ // test_instantiation_without_argument<8>();
+ // test_initialization<8>();
+ // test_take_argument<8>();
+ // test_take_other<8>();
+ // test_integration<8>();
return 0;
}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc b/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc
index 1c6176b..af39d94 100644
--- a/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc
+++ b/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc
@@ -1,3 +1,28 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
/// \file
///
/// \brief Minimal code for building 1d image histogram version.
@@ -11,6 +36,8 @@
#include <mln/io/pgm/load.hh>
#include <mln/value/int_u8.hh>
+
+
int main()
{
typedef mln::value::int_u8 t_int_u8;
diff --git a/scribo/sandbox/green/use/accu/stat/histo2d/histo2d.cc b/scribo/sandbox/green/use/accu/stat/histo2d/histo2d.cc
index 6369b5a..2e36867 100644
--- a/scribo/sandbox/green/use/accu/stat/histo2d/histo2d.cc
+++ b/scribo/sandbox/green/use/accu/stat/histo2d/histo2d.cc
@@ -1,3 +1,28 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
/// \file
///
/// \brief Minimal code for building 2d image histogram version.
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/accu/stat/histo3d_hsl/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/accu/stat/histo3d_hsl/Makefile.am
diff --git a/milena/tests/fun/v2v/rgb_to_hsl.cc b/scribo/sandbox/green/use/accu/stat/histo3d_hsl/histo3d_hsl.cc
similarity index 57%
copy from milena/tests/fun/v2v/rgb_to_hsl.cc
copy to scribo/sandbox/green/use/accu/stat/histo3d_hsl/histo3d_hsl.cc
index 6fd9a17..17b12cc 100644
--- a/milena/tests/fun/v2v/rgb_to_hsl.cc
+++ b/scribo/sandbox/green/use/accu/stat/histo3d_hsl/histo3d_hsl.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -23,37 +23,37 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#include <mln/core/image/image2d.hh>
+/// \file
+///
+/// \brief Minimal code for building HSL 3d image histogram version.
+//
+/// \fixme This code should compile but it doesn't.
+///
+#include <mln/accu/stat/histo3d_hsl.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/data/compute.hh>
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb_to_hsl.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
#include <mln/value/hsl.hh>
#include <mln/value/rgb8.hh>
-#include <mln/fun/v2v/rgb_to_hsl.hh>
-
-#include <mln/data/compare.hh>
-#include <mln/data/transform.hh>
-
-#include <mln/make/image.hh>
-
-#include <mln/debug/println.hh>
-
-using mln::value::rgb8;
-using mln::value::hsl_f;
-
-rgb8 dat[][2] = { { rgb8(0,0,0), rgb8(255,255,255) },
- { rgb8(128,128,128), rgb8(90,90, 90) } };
-
-hsl_f ref[][2] = { { hsl_f(0,0,0), hsl_f(0,0,1.0) },
- { hsl_f(0,0,128.0 / 255.0), hsl_f(0,0,90.0 / 255.0) } };
-
int main()
{
- using namespace mln;
-
- image2d<value::rgb8> ima = make::image(dat);
- image2d<hsl_f> ref_ima = make::image(ref);
- image2d<hsl_f> ima_hsl = data::transform(ima,
- fun::v2v::f_rgb_to_hsl_f);
-
- mln_assertion(ima_hsl == ref_ima);
+ typedef mln::value::rgb8 t_rgb;
+ typedef mln::value::hsl_f t_hsl;
+ typedef mln::fun::v2v::f_rgb_to_hsl_<t_hsl> t_rgb_to_hsl;
+ mln::image2d<t_rgb> img_rgb;
+ mln::image2d<t_hsl> img_hsl;
+ mln::image3d<unsigned> histo;
+
+ mln::io::ppm::load(img_rgb, OLENA_IMG_PATH"/lena.ppm");
+ img_hsl = mln::data::transform(img_rgb, t_rgb_to_hsl());
+ //histo =mln::data::compute(mln::accu::meta::stat::histo3d_hsl<7>(), img_hsl);
+ //histo =mln::data::compute(mln::accu::stat::histo3d_hsl<7,t_hsl>(), img_hsl);
+ mln::accu::stat::histo3d_hsl<7,t_hsl>();
+ return 0;
}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/accu/stat/histo3d_rgb/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/accu/stat/histo3d_rgb/Makefile.am
diff --git a/milena/tests/io/ppm/ppm.cc b/scribo/sandbox/green/use/accu/stat/histo3d_rgb/histo3d_rgb.cc
similarity index 63%
copy from milena/tests/io/ppm/ppm.cc
copy to scribo/sandbox/green/use/accu/stat/histo3d_rgb/histo3d_rgb.cc
index c2dac07..20267a0 100644
--- a/milena/tests/io/ppm/ppm.cc
+++ b/scribo/sandbox/green/use/accu/stat/histo3d_rgb/histo3d_rgb.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -23,32 +23,35 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// \brief Minimal code for building 3d image histogram version.
+///
+
+
+#include <mln/accu/stat/histo3d_rgb.hh>
#include <mln/core/image/image2d.hh>
#include <mln/core/image/image3d.hh>
-#include <mln/core/image/dmorph/slice_image.hh>
-#include <mln/value/rgb8.hh>
-
+#include <mln/data/compute.hh>
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+#include <mln/img_path.hh>
#include <mln/io/ppm/load.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/compare.hh>
-
-#include <mln/util/array.hh>
-
-#include <mln/literal/colors.hh>
-
-#include "tests/data.hh"
-
+#include <mln/value/rgb.hh>
+#include <mln/value/rgb8.hh>
int main()
{
- using namespace mln;
- using value::rgb8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<7> t_rgb7;
+ mln::image2d<t_rgb8> img_rgb8;
+ mln::image2d<t_rgb7> img_rgb7;
+ mln::image3d<unsigned> histo;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+ img_rgb7 = mln::data::transform(img_rgb8, mln::fun::v2v::rgb8_to_rgbn<7>());
- image2d<rgb8> lena = io::ppm::load<rgb8>(MLN_IMG_DIR "/lena.ppm");
- io::ppm::save(lena, "out.ppm");
+ histo = mln::data::compute(mln::accu::meta::stat::histo3d_rgb(), img_rgb7);
- image2d<rgb8> lena2;
- io::ppm::load(lena2, "out.ppm");
- mln_assertion(lena2 == lena);
+ return 0;
}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/fun/v2v/rgb8_to_rgbn/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/fun/v2v/rgb8_to_rgbn/Makefile.am
diff --git a/milena/tests/io/ppm/ppm.cc b/scribo/sandbox/green/use/fun/v2v/rgb8_to_rgbn/rgb8_to_rgbn.cc
similarity index 63%
copy from milena/tests/io/ppm/ppm.cc
copy to scribo/sandbox/green/use/fun/v2v/rgb8_to_rgbn/rgb8_to_rgbn.cc
index c2dac07..cec04e7 100644
--- a/milena/tests/io/ppm/ppm.cc
+++ b/scribo/sandbox/green/use/fun/v2v/rgb8_to_rgbn/rgb8_to_rgbn.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -23,32 +23,35 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// \brief Example of using rgb8_t_rgbn transformation to compute 3d histogram.
+///
+
+
+#include <mln/accu/stat/histo3d_rgb.hh>
#include <mln/core/image/image2d.hh>
#include <mln/core/image/image3d.hh>
-#include <mln/core/image/dmorph/slice_image.hh>
-#include <mln/value/rgb8.hh>
-
+#include <mln/data/compute.hh>
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.hh>
+#include <mln/img_path.hh>
#include <mln/io/ppm/load.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/compare.hh>
-
-#include <mln/util/array.hh>
-
-#include <mln/literal/colors.hh>
-
-#include "tests/data.hh"
-
+#include <mln/value/rgb.hh>
+#include <mln/value/rgb8.hh>
int main()
{
- using namespace mln;
- using value::rgb8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<7> t_rgb7;
+ mln::image2d<t_rgb8> img_rgb8;
+ mln::image2d<t_rgb7> img_rgb7;
+ mln::image3d<unsigned> histo;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+ img_rgb7 = mln::data::transform(img_rgb8, mln::fun::v2v::rgb8_to_rgbn<7>());
- image2d<rgb8> lena = io::ppm::load<rgb8>(MLN_IMG_DIR "/lena.ppm");
- io::ppm::save(lena, "out.ppm");
+ histo = mln::data::compute(mln::accu::meta::stat::histo3d_rgb(), img_rgb7);
- image2d<rgb8> lena2;
- io::ppm::load(lena2, "out.ppm");
- mln_assertion(lena2 == lena);
+ return 0;
}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/fun/v2v/rgb_to_rg/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/fun/v2v/rgb_to_rg/Makefile.am
diff --git a/milena/tests/fun/v2v/hsl_to_rgb.cc b/scribo/sandbox/green/use/fun/v2v/rgb_to_rg/rgb_to_rg.cc
similarity index 59%
copy from milena/tests/fun/v2v/hsl_to_rgb.cc
copy to scribo/sandbox/green/use/fun/v2v/rgb_to_rg/rgb_to_rg.cc
index 237e605..8e612b2 100644
--- a/milena/tests/fun/v2v/hsl_to_rgb.cc
+++ b/scribo/sandbox/green/use/fun/v2v/rgb_to_rg/rgb_to_rg.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -23,33 +23,36 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// \brief Example of using rgb_t_rg transformation to compute 2d histogram.
+///
+
+#include <mln/accu/stat/histo2d.hh>
#include <mln/core/image/image2d.hh>
-#include <mln/fun/v2v/hsl_to_rgb.hh>
-#include <mln/data/compare.hh>
+#include <mln/data/compute.hh>
#include <mln/data/transform.hh>
-#include <mln/value/hsl.hh>
+#include <mln/fun/v2v/rgb_to_rg.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/value/rg.hh>
#include <mln/value/rgb8.hh>
-
int main()
{
- using namespace mln;
-
- using mln::value::rgb8;
- using mln::value::hsl_f;
-
- rgb8 ref[][2] = { { rgb8(0,0,0), rgb8(255,255,255) },
- { rgb8(128,128,128), rgb8(90,90, 90) } };
-
- hsl_f dat[][2] = { { hsl_f(0,0,0), hsl_f(0,0,1.0) },
- { hsl_f(0,0,128.0 / 255.0), hsl_f(0,0,90.0 / 255.0) } };
-
- image2d<rgb8> ref_ima = make::image(ref);
- image2d<hsl_f> ima = make::image(dat);
-
- image2d<value::rgb8> ima_rgb = data::transform(ima,
- fun::v2v::f_hsl_to_rgb_3x8);
-
- // mln_assertion(ima_rgb == ref_ima);
- (void) ima_rgb;
+ typedef mln::value::rg<8> t_rg8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+ typedef mln::image2d<t_rg8> t_image2d_rg8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<unsigned> t_histo;
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rg8 img_rg8;
+ t_histo histo;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+ img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+ histo = mln::data::compute(mln::accu::meta::stat::histo2d(), img_rg8);
+
+ return 0;
}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/value/rg/Makefile.am
similarity index 100%
copy from scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
copy to scribo/sandbox/green/use/value/rg/Makefile.am
diff --git a/milena/tests/fun/v2v/hsl_to_rgb.cc b/scribo/sandbox/green/use/value/rg/rg.cc
similarity index 60%
copy from milena/tests/fun/v2v/hsl_to_rgb.cc
copy to scribo/sandbox/green/use/value/rg/rg.cc
index 237e605..b5ea15f 100644
--- a/milena/tests/fun/v2v/hsl_to_rgb.cc
+++ b/scribo/sandbox/green/use/value/rg/rg.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
//
// This file is part of Olena.
//
@@ -23,33 +23,36 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// \brief Example of using rg to compute an 2d histogram.
+///
+
+#include <mln/accu/stat/histo2d.hh>
#include <mln/core/image/image2d.hh>
-#include <mln/fun/v2v/hsl_to_rgb.hh>
-#include <mln/data/compare.hh>
+#include <mln/data/compute.hh>
#include <mln/data/transform.hh>
-#include <mln/value/hsl.hh>
+#include <mln/fun/v2v/rgb_to_rg.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/value/rg.hh>
#include <mln/value/rgb8.hh>
-
int main()
{
- using namespace mln;
-
- using mln::value::rgb8;
- using mln::value::hsl_f;
-
- rgb8 ref[][2] = { { rgb8(0,0,0), rgb8(255,255,255) },
- { rgb8(128,128,128), rgb8(90,90, 90) } };
-
- hsl_f dat[][2] = { { hsl_f(0,0,0), hsl_f(0,0,1.0) },
- { hsl_f(0,0,128.0 / 255.0), hsl_f(0,0,90.0 / 255.0) } };
-
- image2d<rgb8> ref_ima = make::image(ref);
- image2d<hsl_f> ima = make::image(dat);
-
- image2d<value::rgb8> ima_rgb = data::transform(ima,
- fun::v2v::f_hsl_to_rgb_3x8);
-
- // mln_assertion(ima_rgb == ref_ima);
- (void) ima_rgb;
+ typedef mln::value::rg<8> t_rg8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+ typedef mln::image2d<t_rg8> t_image2d_rg8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<unsigned> t_histo;
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rg8 img_rg8;
+ t_histo histo;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+ img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+ histo = mln::data::compute(mln::accu::meta::stat::histo2d(), img_rg8);
+
+ return 0;
}
--
1.5.6.5
* mln/accu/stat/histo1d.hh: New header file.
* mln/accu/stat/histo2d.hh: New header file.
* mln/accu/stat/histo3d_hsl.hh: New header file.
* mln/accu/stat/histo3d_rgb.hh: New header file.
* mln/clustering/k_mean.hh: New header file.
* mln/clustering/kmean1d.hh: New header file.
* mln/clustering/kmean2d.hh: New header file.
* mln/clustering/kmean3d.hh: New header file.
* mln/clustering/kmean_rgb.hh: New header file.
* mln/display/display_histo.hh: New header file.
* mln/display/project_histo.hh: New header file.
* mln/fun/p2b/achromatic.hh: New header file.
* mln/fun/p2b/component_equals.hh: New header file.
* mln/fun/v2v/achromatism.hh: New header file.
* mln/fun/v2v/hue_concentration.hh: New header file.
* mln/fun/v2v/int_u16_to_int_u14.hh: New header file.
* mln/fun/v2v/int_u16_to_int_u14.hh: New header file.
* mln/fun/v2v/log.hh: New header file.
* mln/fun/v2v/rg_to_rgb.hh: New header file.
* mln/fun/v2v/rgb8_to_int_u8: New header file.
* mln/fun/v2v/rgb_to_achromastism_map.hh: New header file.
* mln/fun/v2v/rgb_to_hsv.hh: New header file.
* mln/fun/v2v/rgb_to_hue_map.hh: New header file.
* mln/fun/v2v/rgb_to_saturation_map.hh: New header file.
* mln/fun/v2v/rgb_to_value_map.hh: New header file.
* mln/img_path.hh: New header file.
* mln/io/plot/save_image_sh.hh: New header file.
* mln/math/cell.hh: New header file.
* mln/math/floor.hh: New header file.
* tests/accu/stat/histo1d/Makefile.am: New makefile.
* tests/accu/stat/histo1d/histo1d.cc: New source.
* tests/accu/stat/histo2d/Makefile.am: New makefile.
* tests/accu/stat/histo2d/histo2d.cc: New source.
---
scribo/sandbox/green/ChangeLog | 47 +
scribo/sandbox/green/README | 223 ++++-
scribo/sandbox/green/mln/accu/stat/histo1d.hh | 340 +++++++
scribo/sandbox/green/mln/accu/stat/histo2d.hh | 358 +++++++
.../sandbox/green/mln/accu/stat/histo3d_hsl.hh | 0
.../sandbox/green/mln/accu/stat/histo3d_rgb.hh | 0
.../sandbox/green/mln/clustering/k_mean.hh | 0
.../sandbox/green/mln/clustering/kmean1d.hh | 0
.../sandbox/green/mln/clustering/kmean2d.hh | 0
.../sandbox/green/mln/clustering/kmean3d.hh | 0
.../sandbox/green/mln/clustering/kmean_rgb.hh | 0
.../sandbox/green/mln/display/display_histo.hh | 0
.../sandbox/green/mln/display/project_histo.hh | 0
.../sandbox/green/mln/fun/p2b/achromatic.hh | 0
.../sandbox/green/mln/fun/p2b/component_equals.hh | 0
.../sandbox/green/mln/fun/v2v/achromatism.hh | 0
.../sandbox/green/mln/fun/v2v/hue_concentration.hh | 0
.../green/mln/fun/v2v/int_u16_to_int_u14.hh | 0
.../sandbox/green/mln/fun/v2v/log.hh | 0
.../sandbox/green/mln/fun/v2v/rg_to_rgb.hh | 0
.../sandbox/green/mln/fun/v2v/rgb8_to_int_u8.hh | 0
.../sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh | 0
.../green/mln/fun/v2v/rgb_to_achromatism_map.hh | 0
.../sandbox/green/mln/fun/v2v/rgb_to_hsv.hh | 0
.../sandbox/green/mln/fun/v2v/rgb_to_hue_map.hh | 0
scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh | 111 ++
.../green/mln/fun/v2v/rgb_to_saturation_map.hh | 0
.../sandbox/green/mln/fun/v2v/rgb_to_value_map.hh | 0
{milena => scribo}/sandbox/green/mln/img_path.hh | 0
scribo/sandbox/green/mln/io/plot/save_image_sh.hh | 1056 ++++++++++++++++++++
{milena => scribo}/sandbox/green/mln/math/ceil.hh | 0
{milena => scribo}/sandbox/green/mln/math/floor.hh | 0
{milena => scribo}/sandbox/green/mln/value/hsv.hh | 0
scribo/sandbox/green/mln/value/rg.hh | 175 ++++
.../green/tests/accu/stat/histo1d/Makefile.am | 153 +++
.../green/tests/accu/stat/histo1d/histo1d.cc | 21 +
.../green/use/accu/stat/histo1d/Makefile.am | 153 +++
.../sandbox/green/use/accu/stat/histo1d/histo1d.cc | 24 +
.../green/use/accu/stat/histo2d/Makefile.am | 153 +++
.../sandbox/green/use/accu/stat/histo2d/histo2d.cc | 33 +
40 files changed, 2829 insertions(+), 18 deletions(-)
create mode 100644 scribo/sandbox/green/mln/accu/stat/histo1d.hh
create mode 100644 scribo/sandbox/green/mln/accu/stat/histo2d.hh
copy {milena => scribo}/sandbox/green/mln/accu/stat/histo3d_hsl.hh (100%)
copy {milena => scribo}/sandbox/green/mln/accu/stat/histo3d_rgb.hh (100%)
copy {milena => scribo}/sandbox/green/mln/clustering/k_mean.hh (100%)
copy {milena => scribo}/sandbox/green/mln/clustering/kmean1d.hh (100%)
copy {milena => scribo}/sandbox/green/mln/clustering/kmean2d.hh (100%)
copy {milena => scribo}/sandbox/green/mln/clustering/kmean3d.hh (100%)
copy {milena => scribo}/sandbox/green/mln/clustering/kmean_rgb.hh (100%)
copy {milena => scribo}/sandbox/green/mln/display/display_histo.hh (100%)
copy {milena => scribo}/sandbox/green/mln/display/project_histo.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/p2b/achromatic.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/p2b/component_equals.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/achromatism.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/hue_concentration.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/int_u16_to_int_u14.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/log.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/rg_to_rgb.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/rgb8_to_int_u8.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/rgb_to_hue_map.hh (100%)
create mode 100644 scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh
copy {milena => scribo}/sandbox/green/mln/fun/v2v/rgb_to_saturation_map.hh (100%)
copy {milena => scribo}/sandbox/green/mln/fun/v2v/rgb_to_value_map.hh (100%)
copy {milena => scribo}/sandbox/green/mln/img_path.hh (100%)
create mode 100644 scribo/sandbox/green/mln/io/plot/save_image_sh.hh
copy {milena => scribo}/sandbox/green/mln/math/ceil.hh (100%)
copy {milena => scribo}/sandbox/green/mln/math/floor.hh (100%)
copy {milena => scribo}/sandbox/green/mln/value/hsv.hh (100%)
create mode 100644 scribo/sandbox/green/mln/value/rg.hh
create mode 100644 scribo/sandbox/green/tests/accu/stat/histo1d/Makefile.am
create mode 100644 scribo/sandbox/green/tests/accu/stat/histo1d/histo1d.cc
create mode 100644 scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
create mode 100644 scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc
create mode 100644 scribo/sandbox/green/use/accu/stat/histo2d/Makefile.am
create mode 100644 scribo/sandbox/green/use/accu/stat/histo2d/histo2d.cc
diff --git a/scribo/sandbox/green/ChangeLog b/scribo/sandbox/green/ChangeLog
index ed399c5..6a3c8fa 100644
--- a/scribo/sandbox/green/ChangeLog
+++ b/scribo/sandbox/green/ChangeLog
@@ -1,3 +1,50 @@
+2010-06-24 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Import files from milena/sandbox/green.
+
+ * mln/accu/stat/histo1d.hh: New header file.
+ * mln/accu/stat/histo2d.hh: New header file.
+ * mln/accu/stat/histo3d_hsl.hh: New header file.
+ * mln/accu/stat/histo3d_rgb.hh: New header file.
+ * mln/clustering/k_mean.hh: New header file.
+ * mln/clustering/kmean1d.hh: New header file.
+ * mln/clustering/kmean2d.hh: New header file.
+ * mln/clustering/kmean3d.hh: New header file.
+ * mln/clustering/kmean_rgb.hh: New header file.
+ * mln/display/display_histo.hh: New header file.
+ * mln/display/project_histo.hh: New header file.
+ * mln/fun/p2b/achromatic.hh: New header file.
+ * mln/fun/p2b/component_equals.hh: New header file.
+ * mln/fun/v2v/achromatism.hh: New header file.
+ * mln/fun/v2v/hue_concentration.hh: New header file.
+ * mln/fun/v2v/int_u16_to_int_u14.hh: New header file.
+ * mln/fun/v2v/int_u16_to_int_u14.hh: New header file.
+ * mln/fun/v2v/log.hh: New header file.
+ * mln/fun/v2v/rg_to_rgb.hh: New header file.
+ * mln/fun/v2v/rgb8_to_int_u8: New header file.
+ * mln/fun/v2v/rgb_to_achromastism_map.hh: New header file.
+ * mln/fun/v2v/rgb_to_hsv.hh: New header file.
+ * mln/fun/v2v/rgb_to_hue_map.hh: New header file.
+ * mln/fun/v2v/rgb_to_saturation_map.hh: New header file.
+ * mln/fun/v2v/rgb_to_value_map.hh: New header file.
+ * mln/img_path.hh: New header file.
+ * mln/io/plot/save_image_sh.hh: New header file.
+ * mln/math/cell.hh: New header file.
+ * mln/math/floor.hh: New header file.
+ * tests/accu/stat/histo1d/Makefile.am: New makefile.
+ * tests/accu/stat/histo1d/histo1d.cc: New source.
+ * tests/accu/stat/histo2d/Makefile.am: New makefile.
+ * tests/accu/stat/histo2d/histo2d.cc: New source.
+
+2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Save histogram library.
+
+ * mln/accu/histo/histo1d.hh: New header file.
+ * mln/accu/histo/histo2d.hh: New header file.
+ * mln/accu/histo/histo3d_rgb.hh: New header file.
+ * mln/accu/histo/histo3d_hsl.hh: New header file.
+
2010-06-21 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
Simple integration test.
diff --git a/scribo/sandbox/green/README b/scribo/sandbox/green/README
index 4eb71b7..3efe50d 100644
--- a/scribo/sandbox/green/README
+++ b/scribo/sandbox/green/README
@@ -1,32 +1,219 @@
-Le travail est classé dans deux répertoires ok et ko.
-Le répertoire ok correspond aux sources qui ont été reprises et retestées.
-Le répertoire ko correspond aux sources qui ont été juste transférées.
+I ARBORESCENCE
+--------------
-La première brique logicielle importante sur laquelle s'appuie mes travaux est
-la création d'histogrammes sous forme d'image.
+bench ==> Comparaison d'algorithmes d'un point de vue temps d'exécution.
+bug ==> Bug rencontrés dans milena et archivés sous forme de programme.
+build ==> Répertoire d'exécution, non sauvé dans git.
+demo ==> Première version d'un algorithme pour voir son comportement.
+doc ==> Documentation tex ou code minimal pour de petits exemples.
+exp ==> Version avancée des algorithmes pour traitées les bases de données.
+mln ==> Partie mise en librairie milena des différents travaux.
+tests ==> Tests unitaires sur certains algorithmes.
+tools ==> Découpage de certains algorithmes pour mieux les tester séparément.
+use ==> Test de compilation, code minimal pour compiler un élément.
+II COMPILATION
+--------------
-CREATION DES HISTOGRAMMES
--------------------------
+L'unité minimale de code choisie est le répertoire.
+Donc aller dans le répertoire qui nous interesse,
+par exemple, green/demo/annotating/hsv et lancé le make
-ko/mln/accu/stat/histo1d.hh: histogramme image valeur scalaire.
-ko/mln/accu/stat/histo2d.hh: histogramme image valeur vectorielle 2d.
-ko/mln/accu/stat/histo3d_hsl.hh: histogramme image valeur vectorielle 3d (HSL).
-ko/mln/accu/stat/histo3d_rgb.hh: histogramme image valeur vectorielle 3d (RGB).
+#:~/git/olena/scribo/sandbox/green$cd demo/annotating/hsv
+#:~/git/olena/scribo/sandbox/green/demo/annotating/hsv$ make -f Makefile.am
+Cette opération créé dans build le répertoire de compilation
+green/build/demo/annotating/hsv. Dans ce répertoire aura été copié un
+Makefile et tous les fichiers qui ne sont pas des sources. Par
+exemple, des fichiers de calibration comme gaussian.sh (pour vérifier
+la mire du filtre de gaussienne) ou de la documentation à la sauvette
+sous forme de fichiers textes jetés à la va vite dans le répertoire
+pour ne pas perdre l'information recherchée. En l'occurence, ici, il
+n'y a rien à copier. Rendons-nous dans le répertoire de compilation et lançons
+le makefile.
+#:~/git/olena/scribo/sandbox/green/demo/annotating/hsv$
+cd ../../../build/demo/annotating/hsv
+#:~/git/olena/scribo/sandbox/green/build/demo/annotating/hsv$ make clean all
-ok/mln/accu/histo/histo1d.hh: histogramme image valeur scalaire entière.
-ok/mln/accu/histo/histo2d.hh: histogramme image valeur vectorielle 2d entière.
-ok/mln/accu/histo/histo3d.hh: histogramme image valeur vectorielle 3d entière.
+L'exécutable est généré par le makefile, il porte le nom du
+répertoire. Si il y a besoin de mettre à jour le makefile, le faire
+dans le répertoire des sources en éditant Makefile.am, puis en
+régénérant le Makefile dans le répertoire d'exécution par la commande
+make -f Makefile.am depuis le répertoire source.
-SAUVEGARDE DES HISTOGRAMMES
----------------------------
+III MAKEFILE
+------------
+Les makefiles utilisés sont tous les mêmes avec quelques variables
+dont le contenu change dans leur partie en-tête.
+Pour chaque répertoire, le makefile doit savoir si le chemin courant
+est un répertoire de compilation ou un répertoire de source. Pour les
+identifier, il a recours à un pattern qui malheureusemnt fait
+intervenir le nom de la branche de développement (bench,demo,bug,exp ...).
+SOURCE_PATTERN= green/demo
+BUILD__PATTERN= green/build/demo
-VISUALISATION DES HISTOGRAMMES
-------------------------------
\ No newline at end of file
+Si un makefile ne fonctionne pas, il faut vérifier ceci en premier
+lieu. Ici, le makefile doit être situé dans la branche démo.
+
+Autre élément à savoir, la compilation nécessite d'inclure la
+librairie milena, ainsi que les développements propres en vu de leur
+intégration futur dans milena, ceci est fait par un jeu d'INCLUDES1
+et INCLUDES2.
+
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+
+Suivant l'allure du compte où l'on exécute les makefiles, il faut
+revoir le chemin pour trouver des deux répertoires.
+
+Enfin, les options de compilations ne sont pas toujours les mêmes. Les
+trois lignes possibles sont toutes présentes et seule celle qui est
+utilisée n'est pas commentée. Typiquement, dans la branche de
+développement démo où les perfomances ne sont pas le problème, on
+compilera avec tout le matériel pour utiliser gdb et sans
+optimisation. A l'inverse, dans la branche d'expérimentation, où le
+code a déjà été testé, on cherche à aller vite car on exécute ce code
+sur de nombreuses images. Dans cette optique, pas de débugage, pas de
+traçage, optimisation conséquente.
+
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+
+Une dernière dernière information, dans le cadre des développements
+exp, et tools, on utilise la librairie boost soit pour la
+virtualisation du filesystem, soit pour le formatage des fichiers text
+(réalisation de colonnes, mettre des entiers sur un certain nombre de
+caractères). Une ligne de chargement des librairies peut apparaitre donc.
+
+LOADLIBES= -lboost_filesystem
+
+On retrouvera les includes suivantes dans les sources:
+
+#include <boost/format.hpp>
+#include <boost/filesystem.hpp>
+
+
+IV CHEMINS DES IMAGES
+---------------------
+
+Toutes les images ont toujours été locales sur mon ordinateur. La
+politique a toujours été d'utiliser un fichier img_path pour coder les
+chemins des images. Les chemins étant plutôt long, j'ai toujours eu
+tendance à faire en sorte qu'ils soient compilés en dur (sauf pour la
+partie développement tools qui est vraiment voué à donner des
+exécutables indépendants et génériques). Le fichier mln/img_path.hh
+code la position de toutes les images dans mon arborescence. Il faudra
+donc veiller à changer tous les chemins pour les adapter au compte
+dans lequel on voudra reprendre le code. Dans le code, les références
+aux positions des images sont faites via des macros.
+
+Toutes les images sont située dans git/img. En règle générale, je ne
+traite que des images au format .pgm, .pbm et .ppm. Il m'arrive
+fréquemment de dumper des images au format .sh (gnuplot shell
+image). Pour la branche tools, nous avons utilisé les dumps de milena
+comme format de transfert d'un utilitaire à un autre. Les images sont
+classées suivant leur provenance. Nous avons tout d'abord la base
+OLENA (copie des images de tests milena), la base INIM (très peu
+utilisée voire jamais), la base ICDAR (très utilisée, surtout dans
+exp), la base AFP (très utilisée dans exp) et les bases ANNOTATING1 et
+ANNOTATING2 (pas très utilisées ni l'une, ni l'autre).
+
+La plus part du temps, sauver les résultats dans le répertoire
+d'exécution courant est largement suffisant. Parfois, il est
+nécessaire de sauvegarder de grosses quantités d'informations et de
+les classer comme dans la branche de développement exp. C'est pour
+cela, qu'un certain nombre de macros définissent des endroits pour
+sauvegarder les résultats lors d'expérimentation de grande ampleur sur
+toute la base ICDAR ou AFP.
+
+
+V GNUPLOT SCRIPT SHELL IMAGE FORMAT
+-----------------------------------
+
+J'abrège le nom du format par gnuplot shell format. En fait, c'est un
+format d'image particulier qui a besoin de gnuplot pour être lu. Il
+est donc compatible avec aucun viewer si ce n'est gnuplot, mais a la
+caractéristique d'afficher tous les points de manière visible. Par
+ailleurs, comme il s'agit d'un script gnuplot il permet d'insérer très
+facilement une fonction pour visualiser les données autrement (par
+exemple, changer d'espace: HSL, HSV). Le fichier tire son nom de la
+façon dont il fonctionne. C'est un script shell qui fait un appel à
+gnuplot et lui passe le jeu de données directement à partir de ce même
+fichier, pas besoin de faire appel à un autre fichier. Une fois
+généré, le fichier doit être modifié pour avoir les permissions
+d'exécution (chmod 755 gnuplot_shell_file.sh). Comme je trouve le format
+extrêmement pratique, il se retrouve preque partout dans mes sources.
+
+
+V MLN
+-----
+
+a) La sauvegarde des images au format gnuplot shell
+
+* mln/io/plot/save_image_sh.hh: Librairie sauvegarde format gnuplot shell.
+
+to do ...
+
+
+
+b) Les histogrammes
+
+Un des travaux demandés par théo est la réalisation d'une librairie
+d'histogramme permettant de fournir un résultat sous forme d'image.
+L'intérêt est ensuite de pouvoir filtrer directement ces histogrammes
+par les algorithmes de milena, ou encore d'étudier les valeurs
+caractéristiques par d'autres accumulateurs. Les codes réellement
+utilisés sont histo1d et histo3d RGB. Tous les autres codes sont très
+expérimentaux. Notemment, le code HSL demande de quantifier l'espace
+de comptage puisqu'il est décrit sous la forme de triplets de float
+(les autres sont inférés). Néanmoins, le code est à conserver car il
+contient une séquence d'appels pour les routines permettant de
+considérer la dimension de la teinte comme circulaire.
+
+* mln/accu/stat/histo1d.hh: Accumulateur histogramme image1d.
+* use/accu/stat/histo1d: Code minimal utilisant un histogramme 1d.
+
+* mln/accu/stat/histo2d.hh: Accumulateur histogramme image2d.
+* mln/value/rg.hh: Définition du type vectoriel 2d rouge/vert (RG).
+* mln/fun/v2v/rgb_to_rg.hh: Transformation de l'espace RGB vers l'espace RG.
+* use/accu/stat/histo2d: Code minimal utilisant un histogramme 2d.
+
+
+* mln/accu/stat/histo3d_rgb.hh: Accumulateur histogramme image3d RGB.
+* mln/accu/stat/histo3d_hsl.hh: Accumulateur histogramme image3d HSL.
+
+* use/accu/stat/histo3_rgb: Code minimal utilisant un histogramme 3d RGB.
+* use/accu/stat/histo3_hsl: Code minimal utilisant un histogramme 3d HSL.
+
+
+
+* tests/accu/stat/histo1d
+
+
+
+
+* tests/accu/stat/histo2d
+
+
+
+* use/accu/stat/histo3d_rgb
+* tests/accu/stat/histo3d_rgb
+
+* use/accu/stat/histo3d_hsl
+* tests/accu/stat/histo3d_hsl
+
+
+c) La visualisation des histogrammes 3d
+
+* demo/accu/stat/histo2d
+
+* mln/display/dispay_histo.hh
+* mln/displayproject_histo.hh
diff --git a/scribo/sandbox/green/mln/accu/stat/histo1d.hh b/scribo/sandbox/green/mln/accu/stat/histo1d.hh
new file mode 100644
index 0000000..d480cf0
--- /dev/null
+++ b/scribo/sandbox/green/mln/accu/stat/histo1d.hh
@@ -0,0 +1,340 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_ACCU_STAT_HISTO1D_HH
+#define MLN_ACCU_STAT_HISTO1D_HH
+
+/// \file
+///
+/// \brief Define a histogram as accumulator which returns an image1d.
+///
+/// This source implements the discrete histogram version. It was
+/// created for images which the values are derived from integer
+/// type. The number of bins is directly infered from the cardinality
+/// of the image value. So the int_u8 image has got 256 bins, the
+/// int_u<14> image has got 16384 bins. But, this code doesn't work
+/// for that quantification because of the coord limitation (signed
+/// short, as it is defined in mln/core/def/coord.hh). Take care of
+/// the limitation from the result image value. We hard code unsigned,
+/// but it sometimes not enought to count data in one bin. That last
+/// case has not occured since the beginning of the creation of the type.
+///
+/// The following sample is a typical use of the histogram.
+///
+/// #include <mln/accu/stat/histo1d.hh>
+/// #include <mln/data/compute.hh>
+/// #include <mln/core/image/image1d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/pgm/load.hh>
+/// #include <mln/value/int_u8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::int_u8 t_int_u8;
+/// mln::image2d<t_int_u8> img;
+/// mln::image1d<unsigned> histo;
+///
+/// mln::io::pgm::load(img, OLENA_IMG_PATH"/lena.pgm");
+/// histo = mln::data::compute(mln::accu::meta::histo::histo1d(), img);
+///
+/// return 0;
+/// }
+
+
+#include <iostream>
+
+#include <mln/accu/internal/base.hh>
+
+#include <mln/arith/plus.hh>
+
+#include <mln/core/concept/meta_accumulator.hh>
+#include <mln/core/image/image1d.hh>
+#include <mln/core/macros.hh>
+
+#include <mln/literal/zero.hh>
+
+#include <mln/trace/entering.hh>
+#include <mln/trace/exiting.hh>
+
+#include <mln/trait/value/comp.hh>
+
+#include <mln/value/ops.hh>
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+ namespace stat
+ {
+
+ // Forward declaration
+ template <typename V>
+ struct histo1d;
+
+ } // end of namespace mln::accu::stat
+
+
+ namespace meta
+ {
+
+ namespace stat
+ {
+
+ struct histo1d : public Meta_Accumulator<histo1d>
+ {
+ template <typename V>
+ struct with
+ {
+ typedef accu::stat::histo1d<V> ret;
+ };
+ };
+
+ } // end of namespace mln::accu::meta::stat
+
+ } // end of namespace mln::accu::meta
+
+ } // end of namespace mln::accu
+
+ namespace trait
+ {
+
+ template <typename V>
+ struct accumulator_< mln::accu::stat::histo1d<V> >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+
+ template <typename V>
+ struct set_precise_binary_<op::eq,
+ accu::stat::histo1d<V>,
+ accu::stat::histo1d<V> >
+ {
+ typedef bool ret;
+ };
+
+ } // end of namespace mln::trait
+
+ namespace accu
+ {
+
+ namespace stat
+ {
+
+ /// \brief Define a histogram as accumulator which returns an image1d.
+ ///
+ /// Param V defines the type of the input image value. It is in
+ /// this space that we count the values. For instance, this
+ /// histogram works well for image2d<int_u8> or with
+ /// image2d<int_u<14> >. The number of bins depends directly the
+ /// values V. For 8 bits there is 256 bins, for 14 bits there
+ /// is 16384 bins. Note that over quantification works too (up
+ /// to 14 bits).
+ ///
+ /// \ingroup modaccuvalues
+
+ template <typename V>
+ struct histo1d :
+ public mln::accu::internal::base<image1d<unsigned>, histo1d<V> >
+ {
+ typedef V argument;
+ typedef image1d<unsigned> result;
+ typedef result q_result;
+
+ /// Constructors
+ /// \{
+ /// \brief Infer the size of the resulting image1d domain.
+ ///
+ /// By evaluating the minimum and the maximum of V, we define the domain
+ /// of the resulting image1d.
+ histo1d();
+ /// \}
+
+
+ /// Manipulators.
+ /// \{
+ /// \brief Initialize the histogram with zero value.
+ ///
+ /// This method must be called just before starting the use of the
+ /// histogram. If it's not, resulting values won't converge to the
+ /// density.
+ void init();
+
+
+ /// \brief Update the histogram with the graylevel of the pixel t.
+ /// \param[in] t a graylevel pixel of type V.
+ ///
+ /// The end user shouldn't call this method. In place of it, he can
+ /// go through the data compute interface.
+ void take(const argument& t);
+
+
+ /// \brief Update the histogram with an other histogram.
+ /// \param[in] other the other histogram.
+ ///
+ /// The end user shouldn't call this method. This is part of
+ /// data compute interface mechanism.
+
+ void take(const histo1d<V>& other);
+ /// \}
+
+ /// Accessors.
+ /// \{
+ /// \brief Return the histogram as an image1d.
+ ///
+ /// This is the machinery to communicate with data compute interface.
+ /// The end user should'nt use it.
+ result to_result() const;
+ operator result () const;
+ /// \}
+
+ /// \brief Check whethever this accumulator is able to return a result.
+ ///
+ /// Depends if the resulting image1d is valid. We can assume it is quite
+ /// always the case.
+ bool is_valid() const;
+
+ protected:
+ result count_;
+ };
+
+ /// \brief Check wethever an histogram is equal to an other one.
+ /// \param[in] histo1 the first histogram to compare with.
+ /// \param[in] histo2 the second histogram.
+ ///
+ /// The operator compares all the bins from the two histograms.
+ /// Nobody uses this method unless unitary tests.
+
+ template <typename V>
+ bool operator==(const histo1d<V>& histo1, const histo1d<V>& histo2);
+
+#ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ histo1d<V>::histo1d()
+ {
+ trace::entering("mln::accu::stat::histo1d::cstor");
+ typedef mln_trait_value_comp(V,0) comp;
+ typedef point<grid::tick, V> v_point1d;
+ typedef box<v_point1d> v_box1d;
+
+ // comp keep a trace of the dimension of the theorical image.
+ // mln_min(comp) --> 0
+ // mln_max(comp) --> 2^(n-1) [127 for n=7][255 for n=8] ...
+
+ count_.init_(box1d(point1d(mln_min(comp)),
+ point1d(mln_max(comp))));
+
+ // std::cout << "min : " << mln_min(comp) << std::endl;
+ // std::cout << "max : " << mln_max(comp) << std::endl;
+
+ trace::exiting("mln::accu::stat::histo1d::cstor");
+ }
+
+ template <typename V>
+ inline
+ void histo1d<V>::init()
+ {
+ data::fill(count_, literal::zero);
+ }
+
+ template <typename V>
+ inline
+ void histo1d<V>::take(const argument& t)
+ {
+ // Just convert a graylevel value (int_u8 like) to a position for an
+ // iterator on the resulting image.
+ ++count_(point1d(t));
+ }
+
+
+ template <typename V>
+ inline
+ void histo1d<V>::take(const histo1d<V>& other)
+ {
+ count_ += other.count_;
+ }
+
+ template <typename V>
+ inline
+ typename histo1d<V>::result histo1d<V>::to_result() const
+ {
+ return count_;
+ }
+
+ template <typename V>
+ inline
+ histo1d<V>::operator result() const
+ {
+ return count_;
+ }
+
+ template <typename V>
+ inline
+ bool histo1d<V>::is_valid() const
+ {
+ bool result = count_.is_valid();
+
+ return result;
+ }
+
+ template <typename V>
+ bool operator==(const histo1d<V>& histo1, const histo1d<V>& histo2)
+ {
+ trace::entering("mln::accu::stat::histo1d::operator==");
+
+ bool result = true;
+ const image1d<unsigned>& res1 = histo1.to_result();
+ const image1d<unsigned>& res2 = histo2.to_result();
+
+ mln_precondition(res1.is_valid());
+ mln_precondition(res2.is_valid());
+
+ mln_piter(image1d<unsigned>) p1(res1.domain());
+ mln_piter(image1d<unsigned>) p2(res2.domain());
+
+ for_all_2(p1, p2)
+ result &= (res1(p1) == res2(p2));
+
+ trace::exiting("mln::accu::stat::histo1d::operator==");
+ return result;
+ }
+
+#endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace mln::accu::stat
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+#endif // ! MLN_ACCU_STAT_HISTO1D_HH
diff --git a/scribo/sandbox/green/mln/accu/stat/histo2d.hh b/scribo/sandbox/green/mln/accu/stat/histo2d.hh
new file mode 100644
index 0000000..c28723c
--- /dev/null
+++ b/scribo/sandbox/green/mln/accu/stat/histo2d.hh
@@ -0,0 +1,358 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_ACCU_STAT_HISTO2D_HH
+# define MLN_ACCU_STAT_HISTO2D_HH
+
+/// \file
+///
+/// \brief Define a histogram as accumulator which returns an image2d.
+///
+/// This source implements the discrete histogram version. It was
+/// created for images which the values are derived from integer
+/// type. The number of bins is directly infered from the cardinality
+/// of the image value. It works with vectorial image, typically RGB
+/// space where only RG are preserved. See histo1d.hh for limitations
+/// of such implementation. 8 bits quantification starts to be
+/// expensive, it produces image2d with [0..255,0..255] as domain.
+///
+/// The following sample is a typical use of the histogram.
+///
+/// #include <mln/accu/stat/histo2d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/data/compute.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb_to_rg.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/rg.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::rg<8> t_rg8
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+/// typedef mln::image2d<t_rg8> t_image2d_rg8;
+/// typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+/// typedef mln::image2d<unsigned> t_histo;
+/// t_image2d_rgb8 img_rgb8;
+/// t_image2d_rg8 img_rg8;
+/// t_histo histo;
+///
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+/// img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+/// histo = mln::data::compute(mln::accu::meta::stat::histo2d(), img_rg8);
+///
+/// return 0;
+/// }
+
+# include <iostream>
+
+# include <mln/accu/internal/base.hh>
+
+# include <mln/core/macros.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/alias/point2d.hh>
+# include <mln/core/alias/box2d.hh>
+
+# include <mln/trait/value/comp.hh>
+
+# include <mln/arith/plus.hh>
+
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
+
+# include <mln/value/ops.hh>
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+ namespace stat
+ {
+
+ // Forward declaration
+ template <typename V>
+ struct histo2d;
+
+ } // end of namespace mln::accu::stat
+
+ namespace meta
+ {
+
+ namespace stat
+ {
+
+ struct histo2d : public Meta_Accumulator<histo2d>
+ {
+ template <typename V>
+ struct with
+ {
+ typedef accu::stat::histo2d<V> ret;
+ };
+ };
+
+ } // end of namespace mln::accu::meta::stat
+
+ } // end of namespace mln::accu::meta
+
+ } // end of namespace mln::accu
+
+
+ namespace trait
+ {
+
+ template <typename V>
+ struct accumulator_< mln::accu::stat::histo2d<V> >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+
+ template <typename V>
+ struct set_precise_binary_<op::eq,
+ accu::stat::histo2d<V>,
+ accu::stat::histo2d<V> >
+ {
+ typedef bool ret;
+ };
+
+ } // end of namespace mln::trait
+
+ namespace accu
+ {
+
+ namespace stat
+ {
+
+ /// \brief Define an histogram which returns an image3d .
+ ///
+ /// Param V defines the space in which we count the values.
+ /// For instance, this histogram works image2d<rgb<2>> or
+ /// image2d<rgb<7>>. The histogram count the occurrence of each value.
+ /// The number of bins depends of the grayscale values, for 8 bits there
+ /// is 256x3 bins. Note that over
+ /// quantification works too.
+ ///
+ /// \ingroup modaccuvalues
+
+ template <typename V>
+ struct histo2d :
+ public mln::accu::internal::base<image2d<unsigned>, histo2d<V> >
+ {
+ typedef V argument;
+ typedef image2d<unsigned> result;
+ typedef result q_result;
+
+ /// Constructors
+ /// \{
+ /// \brief Initialize the size of the resulting image1d.
+ ///
+ /// Initialize the size the resulting image from the theorical dynamic
+ /// of the greylevel values (Use V to manage it).
+ histo2d();
+ /// \}
+
+
+ /// Manipulators.
+ /// \{
+ /// \brief Initialize the histogram with zero value.
+ ///
+ /// This method must be called just before starting the use of the
+ /// histogram. If it's not, resulting values won't converge to the
+ /// density.
+ void init();
+
+
+ /// \brief Update the histogram with the RGB pixel t.
+ /// \param[in] t a greylevel pixel of type V.
+ ///
+ /// The end user shouldn't call this method. In place of it, he can
+ /// go through the data compute interface.
+ void take(const argument& t);
+
+
+ /// \brief Update the histogram with an other histogram.
+ /// \param[in] other the other histogram.
+ void take(const histo2d<V>& other);
+ /// \}
+
+ /// Accessors.
+ /// \{
+ /// \brief Return the histogram as an image1d.
+ ///
+ /// This is the machinery to communicate with data compute interface.
+ /// The end user should'nt use it.
+ result to_result() const;
+ operator result () const;
+ /// \}
+
+ /// \brief Check whethever this accumulator is able to return a result.
+ ///
+ /// Depends if the resulting image1d is valid. We can assume it is quite
+ /// always the case.
+ bool is_valid() const;
+
+ protected:
+ result count_;
+ };
+
+ /// \brief Check wethever an histogram is equal to an other one.
+ /// \param[in] histo1 the first histogram to compare with.
+ /// \param[in] histo2 the second histogram.
+ ///
+ /// The operator compare all the bins from the two histogram.
+
+ template <typename V>
+ bool operator==(const histo2d<V>& histo1,
+ const histo2d<V>& histo2);
+
+#ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ histo2d<V>::histo2d()
+ {
+ trace::entering("mln::accu::stat::histo2d::histo2d");
+ typedef mln_trait_value_comp(V,0) comp0;
+ typedef mln_trait_value_comp(V,1) comp1;
+
+ // comp keep a trace of the dimension of the theorical image.
+ // mln_min(comp) --> 0
+ // mln_max(comp) --> 2^(n-1) [127 for n=7][255 for n=8] ...
+
+ count_.init_(box2d(point2d(mln_min(comp0),
+ mln_min(comp1)),
+ point2d(mln_max(comp0),
+ mln_max(comp1))));
+
+ trace::exiting("mln::accu::stat::histo2d::histo2d");
+ }
+
+ template <typename V>
+ inline
+ void histo2d<V>::init()
+ {
+ trace::entering("mln::accu::stat::histo2d::init");
+
+ data::fill(count_, 0);
+ trace::exiting("mln::accu::stat::histo2d::init");
+ }
+
+ template <typename V>
+ inline
+ void histo2d<V>::take(const argument& t)
+ {
+ trace::entering("mln::accu::stat::histo2d::take");
+
+ // Just convert a greyscale value (int_u8 like) to a position for an
+ // iterator on the resulting image.
+ // Take care to the constructor : Point(slice, row, column)
+ ++count_(point2d(t.red(), t.green()));
+
+ trace::exiting("mln::accu::stat::histo2d::take");
+ }
+
+
+ template <typename V>
+ inline
+ void histo2d<V>::take(const histo2d<V>& other)
+ {
+ trace::entering("mln::accu::stat::histo2d::take");
+
+ count_ += other.count_;
+
+ trace::exiting("mln::accu::stat::histo2d::take");
+ }
+
+ template <typename V>
+ inline
+ typename histo2d<V>::result histo2d<V>::to_result() const
+ {
+ trace::entering("mln::accu::stat::histo2d::to_result");
+
+ trace::exiting("mln::accu::stat::histo2d::to_result");
+ return count_;
+ }
+
+ template <typename V>
+ inline
+ histo2d<V>::operator result() const
+ {
+ trace::entering("mln::accu::stat::histo2d::operator result");
+
+ trace::exiting("mln::accu::stat::histo2d::operator result");
+ return count_;
+ }
+
+ template <typename V>
+ inline
+ bool histo2d<V>::is_valid() const
+ {
+ trace::entering("mln::accu::stat::histo2d::is_valid");
+ bool result = count_.is_valid();
+
+ trace::exiting("mln::accu::stat::histo2d::is_valid");
+ return result;
+ }
+
+ template <typename V>
+ bool operator==(const histo2d<V>& histo1,
+ const histo2d<V>& histo2)
+ {
+ trace::entering("mln::accu::stat::operator==");
+
+ bool result = true;
+ const image2d<unsigned>& res1 = histo1.to_result();
+ const image2d<unsigned>& res2 = histo2.to_result();
+
+ mln_precondition(res1.is_valid());
+ mln_precondition(res2.is_valid());
+
+ mln_piter(image2d<unsigned>) p1(res1.domain());
+ mln_piter(image2d<unsigned>) p2(res2.domain());
+
+ for_all_2(p1, p2)
+ result &= (res1(p1) == res2(p2));
+
+ trace::exiting("mln::accu::stat::operator==");
+ return result;
+ }
+
+#endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace mln::accu::stat
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+#endif // ! MLN_ACCU_STAT_HISTO2D_HH
diff --git a/milena/sandbox/green/mln/accu/stat/histo3d_hsl.hh b/scribo/sandbox/green/mln/accu/stat/histo3d_hsl.hh
similarity index 100%
copy from milena/sandbox/green/mln/accu/stat/histo3d_hsl.hh
copy to scribo/sandbox/green/mln/accu/stat/histo3d_hsl.hh
diff --git a/milena/sandbox/green/mln/accu/stat/histo3d_rgb.hh b/scribo/sandbox/green/mln/accu/stat/histo3d_rgb.hh
similarity index 100%
copy from milena/sandbox/green/mln/accu/stat/histo3d_rgb.hh
copy to scribo/sandbox/green/mln/accu/stat/histo3d_rgb.hh
diff --git a/milena/sandbox/green/mln/clustering/k_mean.hh b/scribo/sandbox/green/mln/clustering/k_mean.hh
similarity index 100%
copy from milena/sandbox/green/mln/clustering/k_mean.hh
copy to scribo/sandbox/green/mln/clustering/k_mean.hh
diff --git a/milena/sandbox/green/mln/clustering/kmean1d.hh b/scribo/sandbox/green/mln/clustering/kmean1d.hh
similarity index 100%
copy from milena/sandbox/green/mln/clustering/kmean1d.hh
copy to scribo/sandbox/green/mln/clustering/kmean1d.hh
diff --git a/milena/sandbox/green/mln/clustering/kmean2d.hh b/scribo/sandbox/green/mln/clustering/kmean2d.hh
similarity index 100%
copy from milena/sandbox/green/mln/clustering/kmean2d.hh
copy to scribo/sandbox/green/mln/clustering/kmean2d.hh
diff --git a/milena/sandbox/green/mln/clustering/kmean3d.hh b/scribo/sandbox/green/mln/clustering/kmean3d.hh
similarity index 100%
copy from milena/sandbox/green/mln/clustering/kmean3d.hh
copy to scribo/sandbox/green/mln/clustering/kmean3d.hh
diff --git a/milena/sandbox/green/mln/clustering/kmean_rgb.hh b/scribo/sandbox/green/mln/clustering/kmean_rgb.hh
similarity index 100%
copy from milena/sandbox/green/mln/clustering/kmean_rgb.hh
copy to scribo/sandbox/green/mln/clustering/kmean_rgb.hh
diff --git a/milena/sandbox/green/mln/display/display_histo.hh b/scribo/sandbox/green/mln/display/display_histo.hh
similarity index 100%
copy from milena/sandbox/green/mln/display/display_histo.hh
copy to scribo/sandbox/green/mln/display/display_histo.hh
diff --git a/milena/sandbox/green/mln/display/project_histo.hh b/scribo/sandbox/green/mln/display/project_histo.hh
similarity index 100%
copy from milena/sandbox/green/mln/display/project_histo.hh
copy to scribo/sandbox/green/mln/display/project_histo.hh
diff --git a/milena/sandbox/green/mln/fun/p2b/achromatic.hh b/scribo/sandbox/green/mln/fun/p2b/achromatic.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/p2b/achromatic.hh
copy to scribo/sandbox/green/mln/fun/p2b/achromatic.hh
diff --git a/milena/sandbox/green/mln/fun/p2b/component_equals.hh b/scribo/sandbox/green/mln/fun/p2b/component_equals.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/p2b/component_equals.hh
copy to scribo/sandbox/green/mln/fun/p2b/component_equals.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/achromatism.hh b/scribo/sandbox/green/mln/fun/v2v/achromatism.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/achromatism.hh
copy to scribo/sandbox/green/mln/fun/v2v/achromatism.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/hue_concentration.hh b/scribo/sandbox/green/mln/fun/v2v/hue_concentration.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/hue_concentration.hh
copy to scribo/sandbox/green/mln/fun/v2v/hue_concentration.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/int_u16_to_int_u14.hh b/scribo/sandbox/green/mln/fun/v2v/int_u16_to_int_u14.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/int_u16_to_int_u14.hh
copy to scribo/sandbox/green/mln/fun/v2v/int_u16_to_int_u14.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/log.hh b/scribo/sandbox/green/mln/fun/v2v/log.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/log.hh
copy to scribo/sandbox/green/mln/fun/v2v/log.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/rg_to_rgb.hh b/scribo/sandbox/green/mln/fun/v2v/rg_to_rgb.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/rg_to_rgb.hh
copy to scribo/sandbox/green/mln/fun/v2v/rg_to_rgb.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/rgb8_to_int_u8.hh b/scribo/sandbox/green/mln/fun/v2v/rgb8_to_int_u8.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/rgb8_to_int_u8.hh
copy to scribo/sandbox/green/mln/fun/v2v/rgb8_to_int_u8.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh b/scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
copy to scribo/sandbox/green/mln/fun/v2v/rgb8_to_rgbn.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh
copy to scribo/sandbox/green/mln/fun/v2v/rgb_to_achromatism_map.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh
copy to scribo/sandbox/green/mln/fun/v2v/rgb_to_hsv.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/rgb_to_hue_map.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_hue_map.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/rgb_to_hue_map.hh
copy to scribo/sandbox/green/mln/fun/v2v/rgb_to_hue_map.hh
diff --git a/scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh
new file mode 100644
index 0000000..d4c1e46
--- /dev/null
+++ b/scribo/sandbox/green/mln/fun/v2v/rgb_to_rg.hh
@@ -0,0 +1,111 @@
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_FUN_V2V_RGB_TO_RG_HH
+# define MLN_FUN_V2V_RGB_TO_RG_HH
+
+# include <mln/value/rg.hh>
+# include <mln/value/rgb.hh>
+# include <mln/core/contract.hh>
+
+/// \file
+///
+/// \brief Convert a rgb value to a rg value.
+///
+/// This source implements the conversion between rgb space and rg space.
+///
+/// The following sample is a typical use of the rgb/rg conversion function.
+///
+/// #include <mln/accu/stat/histo2d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/data/compute.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb_to_rg.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/rg.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::rg<8> t_rg8
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+/// typedef mln::image2d<t_rg8> t_image2d_rg8;
+/// typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+/// typedef mln::image2d<unsigned> t_histo;
+/// t_image2d_rgb8 img_rgb8;
+/// t_image2d_rg8 img_rg8;
+/// t_histo histo;
+///
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+/// img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+/// histo = mln::data::compute(mln::accu::meta::stat::histo2d(), img_rg8);
+///
+/// return 0;
+/// }
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace v2v
+ {
+
+ /// \brief Convert a rgb value to a rg value.
+ ///
+ /// Param n defines the quantification used for rgb space and rg space.
+ ///
+ /// \ingroup modfunv2v
+
+ template <unsigned n>
+ struct rgb_to_rg : Function_v2v< rgb_to_rg<n> >
+ {
+ typedef value::rg<n> result;
+ typedef value::rgb<n> argument;
+
+ /// \brief Convert rgb value to rg value.
+ ///
+ /// \param[in] v the rgb value to convert.
+ ///
+ /// Conversion is done by calling the rg constructor. There is
+ /// no modification of values. The red/green fields from rgb the value
+ /// are preserved. Blue value is dropped.
+
+ result operator()(const argument& v) const
+ {
+ return value::rg<n>(v);
+ }
+ };
+
+ } // end of namespace mln::fun::v2v
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+#endif // ! MLN_FUN_V2V_RGB_TO_RG_HH
diff --git a/milena/sandbox/green/mln/fun/v2v/rgb_to_saturation_map.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_saturation_map.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/rgb_to_saturation_map.hh
copy to scribo/sandbox/green/mln/fun/v2v/rgb_to_saturation_map.hh
diff --git a/milena/sandbox/green/mln/fun/v2v/rgb_to_value_map.hh b/scribo/sandbox/green/mln/fun/v2v/rgb_to_value_map.hh
similarity index 100%
copy from milena/sandbox/green/mln/fun/v2v/rgb_to_value_map.hh
copy to scribo/sandbox/green/mln/fun/v2v/rgb_to_value_map.hh
diff --git a/milena/sandbox/green/mln/img_path.hh b/scribo/sandbox/green/mln/img_path.hh
similarity index 100%
copy from milena/sandbox/green/mln/img_path.hh
copy to scribo/sandbox/green/mln/img_path.hh
diff --git a/scribo/sandbox/green/mln/io/plot/save_image_sh.hh b/scribo/sandbox/green/mln/io/plot/save_image_sh.hh
new file mode 100644
index 0000000..137f78d
--- /dev/null
+++ b/scribo/sandbox/green/mln/io/plot/save_image_sh.hh
@@ -0,0 +1,1056 @@
+// Copyright (C) 2007,2008,2009,2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_IO_PLOT_SAVE_IMAGE_SH_HH
+# define MLN_IO_PLOT_SAVE_IMAGE_SH_HH
+
+/// \file
+///
+/// \brief Define some functions to export to gnuplot format as a script shell.
+///
+/// Theses routines are dedicated to image visualization. The aim is to display
+/// image whatever the value used as pixel. The behaviour of gnuplot is more
+/// like xv than imageMagick. A Gnuplot script shell file is a text dump file
+/// with a preambule to let gnuplot interpret data. As a script shell, you can
+/// launch it (don't forget the permissions), and every thing is packed in it.
+/// The script file call gnuplot in batch mode, the result window persists and
+/// that's all.
+///
+
+# include <fstream>
+# include <string>
+
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
+
+# include <mln/core/macros.hh>
+# include <mln/core/contract.hh>
+# include <mln/core/image/image1d.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image3d.hh>
+
+# include <mln/geom/min_ind.hh>
+# include <mln/geom/max_ind.hh>
+# include <mln/geom/min_row.hh>
+# include <mln/geom/max_row.hh>
+# include <mln/geom/min_col.hh>
+# include <mln/geom/max_col.hh>
+
+# include <mln/trait/value_.hh>
+
+# include <mln/value/int_u.hh>
+# include <mln/value/int_s.hh>
+# include <mln/value/rgb.hh>
+# include <mln/value/hsl.hh>
+# include <mln/value/hsi.hh>
+
+# include <mln/util/array.hh>
+
+
+namespace mln
+{
+
+ namespace io
+ {
+
+ namespace plot
+ {
+
+ /// \brief Save an image as a gnuplot script shell.
+ ///
+ /// Every thing is save. The image could be 1d, 2d or 3d. The value of
+ /// the pixels could be int_u<n>, int_s<n>, float, double, hsl_f, hsl_d,
+ /// hsi_f, hsi_d and rgb<n>.
+ ///
+ /// \param[in] img the image which contains the data to save.
+ /// \param[in] filename the name of the unix script shell.
+ /// \return the status of the opening file operation.
+ ///
+ /// The result depends on the permission to save the file with
+ /// filename parameter as unix path. The script shell file must have the
+ /// permission to execute (chmod 755). Launch the script shell to call
+ /// gnuplot in batchmode with fine parameters.
+
+ template <typename I>
+ bool save_image_sh(const Image<I>& img, const std::string& filename);
+
+ /// \brief Save a stack of image.
+ ///
+ /// This is an experimental support.
+ ///
+ /// \param[in] stack the stack of image to save.
+ /// \param[in] filename the name of the unix script shell.
+ /// \return the status of the opening file operation.
+ ///
+ /// The result depends on the permission to save the file with
+ /// filename parameter as unix path. The script shell file must have the
+ /// permission to execute (chmod 755). Launch the script shell to call
+ /// gnuplot in batchmode with fine parameters.
+ template <typename I>
+ bool save_image_sh(const util::array< image1d<I> >& stack,
+ const std::string& filename);
+
+ template <typename I>
+ bool save_image_sh(const util::array< util::array< image1d<I> > >& stack,
+ const std::string& filename);
+
+ } // end of namespace mln::io::plot
+
+ } // end of namespace mln::io
+
+
+ namespace io
+ {
+
+ namespace plot
+ {
+
+#ifndef MLN_INCLUDE_ONLY
+
+ //------------------------------------------------------------------------
+ // Impl.
+ //------------------------------------------------------------------------
+
+ namespace impl
+ {
+
+
+ //----------------------------------------------------------------------
+ // save_image_sh_array_array_image1d(const array<array<image1d<I>>>&,
+ // const string&)
+ //----------------------------------------------------------------------
+
+ template <typename I>
+ inline
+ bool save_image_sh_array_array_image1d(const util::array< util::array<
+ image1d<I> > >& stack,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::"
+ "save_image_sh_array_array_image1d");
+
+ mln_precondition(!stack.is_empty());
+ mln_precondition(!stack[0].is_empty());
+ mln_precondition(stack[0][0].is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+ unsigned min_ind = geom::min_ind(stack[0][0]);
+ unsigned max_ind = geom::max_ind(stack[0][0]);
+
+ if (result)
+ {
+ // Output data prelude (terminal X11, image).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, val) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "set xrange [" << min_ind;
+ out << ":" << max_ind;
+ out << "]" << std::endl;
+ out << "plot '-' with line";
+
+ for (unsigned i = 1; i < stack.size(); ++i)
+ {
+ for (unsigned j = 1; j < stack[i].size(); ++j)
+ {
+
+ out << ",\\" << std::endl;
+ out << " '-' with line";
+ }
+ }
+
+ out << std::endl;
+
+ mln_eiter(util::array< util::array< image1d<I> > >) e0(stack);
+
+ for_all (e0)
+ {
+ mln_eiter(util::array< image1d<I> >) e1(stack[e0.index_()]);
+
+ for_all (e1)
+ {
+ mln_piter(image1d< I >)
+ p(stack[e0.index_()][e1.index_()].domain());
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.ind() << " ";
+ out << stack[e0.index_()][e1.index_()](p) << std::endl;;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ }
+ }
+
+ out << "EOF" << std::endl;
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:" << filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::"
+ "save_image_sh_array_array_image1d");
+
+ return result;
+ }
+
+ //----------------------------------------------------------------------
+ // save_image_sh_array_array_image1d_vec3(
+ // const array<array<image1d<vec<3,T>>>>&,
+ // const string&)
+ //----------------------------------------------------------------------
+
+ template <typename T>
+ inline
+ bool save_image_sh_array_array_image1d_vec3(
+ const util::array<util::array<image1d<algebra::vec<3,T> > > >& stack,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::"
+ "save_image_sh_array_array_image1d_vec3");
+
+ typedef algebra::vec<3,T> t_val;
+ typedef image1d<t_val> t_img;
+ typedef util::array<t_img> t_array;
+ typedef util::array<t_array> t_stack;
+
+ mln_precondition(!stack.is_empty());
+ mln_precondition(!stack[0].is_empty());
+ mln_precondition(stack[0][0].is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+ unsigned min_ind = geom::min_ind(stack[0][0]);
+ unsigned max_ind = geom::max_ind(stack[0][0]);
+
+ if (result)
+ {
+ // Output data prelude (terminal X11, image).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, val) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "set xrange [" << min_ind;
+ out << ":" << max_ind;
+ out << "]" << std::endl;
+ out << "splot '-' with line palette";
+
+ for (unsigned i = 1; i < stack.size(); ++i)
+ {
+ for (unsigned j = 1; j < stack[i].size(); ++j)
+ {
+
+ out << ",\\" << std::endl;
+ out << " '-' with line palette";
+ }
+ }
+
+ out << std::endl;
+
+ mln_eiter(t_stack) e0(stack);
+
+ for_all (e0)
+ {
+ mln_eiter(t_array) e1(stack[e0.index_()]);
+
+ for_all (e1)
+ {
+ mln_piter(t_img) p(stack[e0.index_()][e1.index_()].domain());
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.ind() << " ";
+ out << stack[e0.index_()][e1.index_()](p)[0] << " ";
+ out << stack[e0.index_()][e1.index_()](p)[1] << " ";
+ out << stack[e0.index_()][e1.index_()](p)[2] << std::endl;;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ }
+ }
+
+ out << "EOF" << std::endl;
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:" << filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::"
+ "save_image_sh_array_array_image1d_vec3");
+
+ return result;
+ }
+
+
+ //----------------------------------------------------------------------
+ // save_image_sh_array_array_image1d_vec2(
+ // const array<array<image1d<vec<2,T>>>>&,
+ // const string&)
+ //----------------------------------------------------------------------
+
+ template <typename T>
+ inline
+ bool save_image_sh_array_array_image1d_vec2(
+ const util::array<util::array<image1d<algebra::vec<2,T> > > >& stack,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::"
+ "save_image_sh_array_array_image1d_vec2");
+
+ typedef algebra::vec<2,T> t_val;
+ typedef image1d<t_val> t_img;
+ typedef util::array<t_img> t_array;
+ typedef util::array<t_array> t_stack;
+
+ mln_precondition(!stack.is_empty());
+ mln_precondition(!stack[0].is_empty());
+ mln_precondition(stack[0][0].is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+ unsigned min_ind = geom::min_ind(stack[0][0]);
+ unsigned max_ind = geom::max_ind(stack[0][0]);
+
+ if (result)
+ {
+ // Output data prelude (terminal X11, image).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, val) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "set xrange [" << min_ind;
+ out << ":" << max_ind;
+ out << "]" << std::endl;
+ out << "splot '-' with line";
+
+ for (unsigned i = 1; i < stack.size(); ++i)
+ {
+ for (unsigned j = 1; j < stack[i].size(); ++j)
+ {
+
+ out << ",\\" << std::endl;
+ out << " '-' with line";
+ }
+ }
+
+ out << std::endl;
+
+ mln_eiter(t_stack) e0(stack);
+
+ for_all (e0)
+ {
+ mln_eiter(t_array) e1(stack[e0.index_()]);
+
+ for_all (e1)
+ {
+ mln_piter(t_img) p(stack[e0.index_()][e1.index_()].domain());
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.ind() << " ";
+ out << stack[e0.index_()][e1.index_()](p)[0] << " ";
+ out << stack[e0.index_()][e1.index_()](p)[1] << std::endl;;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ }
+ }
+
+ out << "EOF" << std::endl;
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:" << filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::"
+ "save_image_sh_array_array_image1d_vec2");
+
+ return result;
+ }
+
+ //----------------------------------------------------------------------
+ // save_image_sh_array_image1d(const array<image1d<I>>&, const string&)
+ //----------------------------------------------------------------------
+
+ template <typename I>
+ inline
+ bool save_image_sh_array_image1d(const util::array< image1d<I> >& stack,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::save_image_sh_array_image1d");
+ mln_precondition(!stack.is_empty());
+ mln_precondition(stack[0].is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+ unsigned min_ind = geom::min_ind(stack[0]);
+ unsigned max_ind = geom::max_ind(stack[0]);
+
+ if (result)
+ {
+ // Output data prelude (terminal X11, image).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, val) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "set xrange [" << min_ind;
+ out << ":" << max_ind;
+ out << "]" << std::endl;
+ out << "plot '-' with line";
+
+ for (unsigned i = 1; i < stack.size(); ++i)
+ {
+
+ out << ",\\" << std::endl;
+ out << " '-' with line";
+ }
+
+ out << std::endl;
+
+ mln_eiter(util::array< image1d<I> >) e(stack);
+
+ for_all (e)
+ {
+ mln_piter(image1d< I >) p(stack[e.index_()].domain());
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.ind() << " ";
+ out << stack[e.index_()](p) << std::endl;;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ }
+
+ out << "EOF" << std::endl;
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:" << filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::save_image_sh_array_image1d");
+ return result;
+ }
+
+
+ //----------------------------------------------------------------------
+ // save_image_sh_image2d_rgb(const image2d<rgb<n>>&, const string&)
+ //----------------------------------------------------------------------
+
+ template <unsigned n>
+ inline
+ bool save_image_sh_image2d_rgb(const image2d<value::rgb<n> >& img,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::save_image_sh_image2d_rgb");
+ mln_precondition(img.is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+ unsigned min_row = geom::min_row(img);
+ unsigned max_row = geom::max_row(img);
+ unsigned min_col = geom::min_col(img);
+ unsigned max_col = geom::max_col(img);
+
+ if (result)
+ {
+ mln_piter(image2d< value::rgb<n> >) p(img.domain());
+
+ // Output data prelude (terminal X11, image).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, r, g, b) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "set xrange [" << min_col;
+ out << ":" << max_col;
+ out << "]" << std::endl;
+ out << "set yrange [-" << max_row;
+ out << ":" << min_row;
+ out << "]" << std::endl;
+ out << "plot '-' using 2:(-\\$1):3:4:5 with rgbimage" << std::endl;
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.row() << " ";
+ out << p.col() << " ";
+ out << img(p).red() << " ";
+ out << img(p).green() << " ";
+ out << img(p).blue() << std::endl;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ out << "EOF" << std::endl;
+
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:" << filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::save_image_sh_image2d_rgb");
+ return result;
+ }
+
+ //----------------------------------------------------------------------
+ // save_image_sh_image2d_hsl(const image2d<hsl_<T,T,T>>&, const string&)
+ //----------------------------------------------------------------------
+
+ template <typename T>
+ inline
+ bool save_image_sh_image2d_hsl(const image2d<value::hsl_<T,T,T> >& img,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::save_image_sh_image2d_hsl");
+ mln_precondition(img.is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+ unsigned min_row = geom::min_row(img);
+ unsigned max_row = geom::max_row(img);
+ unsigned min_col = geom::min_col(img);
+ unsigned max_col = geom::max_col(img);
+
+ typedef mln::value::hsl_<T,T,T> hsl;
+
+ if (result)
+ {
+ mln_piter(image2d< hsl >) p(img.domain());
+
+ // Output data prelude (terminal X11, image).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, val) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "q(l,s) = (l < 0.5)? (l*(1+s)):(l+s-(l*s))" << std::endl;
+ out << "p(l,s) = (2.0 * l - q(l,s))" << std::endl;
+ out << "n(x) = (x < 0)?(x+1):(x > 1)?(x-1) : (x)"<< std::endl;
+ out << std::endl;
+ out << "c(p,q,t) = (t <(1.0/6.0))?(p+(q-p)*6.0*t):\\"<< std::endl;
+ out << " (t <(1.0/2.0))?(q) :\\" << std::endl;
+ out << " (t<(2.0/3.0))?(p+(q-p)*6.0*((2.0/3.0)-t)):\\" << std::endl;
+ out << " (p)" << std::endl;
+ out << std::endl;
+ out << "r(h,s,l) = c(p(l,s),q(l,s),n(h/360.0+1.0/3.0))"<< std::endl;
+ out << "g(h,s,l) = c(p(l,s),q(l,s),n(h/360.0))" << std::endl;
+ out << "b(h,s,l) = c(p(l,s),q(l,s),n(h/360.0-1.0/3.0))"<< std::endl;
+ out << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "set palette gray" << std::endl;
+ out << "set xrange [" << min_col;
+ out << ":" << max_col;
+ out << "]" << std::endl;
+ out << "set yrange [-" << max_row;
+ out << ":" << min_row;
+ out << "]" << std::endl;
+ out << "plot '-' using 2:(-\\$1):\\" << std::endl;
+ out << " (r(\\$3,\\$4,\\$5)):\\" << std::endl;
+ out << " (g(\\$3,\\$4,\\$5)):\\" << std::endl;
+ out << " (b(\\$3,\\$4,\\$5)) with rgbimage" << std::endl;
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.row() << " ";
+ out << p.col() << " ";
+ out << img(p).hue() << " ";
+ out << img(p).sat() << " ";
+ out << img(p).lum() << std::endl;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ out << "EOF" << std::endl;
+
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:" << filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::save_image_sh_image2d_hsl");
+ return result;
+ }
+
+ //----------------------------------------------------------------------
+ // save_image_sh_image2d_hsi(const image2d<hsi_<T,T,T>>&, const string&)
+ //----------------------------------------------------------------------
+
+ template <typename T>
+ inline
+ bool save_image_sh_image2d_hsi(const image2d<value::hsi_<T,T,T> >& img,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::save_image_sh_image2d_hsi");
+ mln_precondition(img.is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+ unsigned min_row = geom::min_row(img);
+ unsigned max_row = geom::max_row(img);
+ unsigned min_col = geom::min_col(img);
+ unsigned max_col = geom::max_col(img);
+
+ typedef mln::value::hsi_<T,T,T> hsi;
+
+ if (result)
+ {
+ mln_piter(image2d< hsi >) p(img.domain());
+
+ // Output data prelude (terminal X11, image).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, val) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "teta(h) = (h/180.0) * pi" << std::endl;
+ out << "alpha(s,h) = s*cos(teta(h))" << std::endl;
+ out << "beta(s,h) = s*sin(teta(h))" << std::endl;
+ out << "n(x) = (x < 0)?(x+1) : (x > 1)?(x-1):(x)"<< std::endl;
+ out << std::endl;
+ out << "c(p,q,t) = (t <(1.0/6.0))?(p+(q-p)*6.0*t):\\"<< std::endl;
+ out << " (t <(1.0/2.0))?(q) :\\" << std::endl;
+ out << " (t <(2.0/3.0))?(p+(q-p)*6.0*((2.0/3.0)-t)):\\"<< std::endl;
+ out << " (p)" << std::endl;
+ out << std::endl;
+ out << "r(h,s,i) = (sqrt(3.0)/3.0) * i \\" << std::endl;
+ out << " + (2.0/(sqrt(6.0))) * beta(s,h)" << std::endl;
+ out << "g(h,s,i) = (sqrt(3.0)/3.0) * i \\" << std::endl;
+ out << " + (2.0/(sqrt(2.0))) * alpha(s,h)\\" << std::endl;
+ out << " - (1.0/(sqrt(6.0))) * beta(s,h)" << std::endl;
+ out << "b(h,s,i) = (sqrt(3.0)/3.0) * i \\" << std::endl;
+ out << " - (2.0/(sqrt(2.0))) * alpha(s,h) \\"<< std::endl;
+ out << " - (1.0/(sqrt(6.0))) * beta(s,h)" << std::endl;
+ out << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "set palette gray" << std::endl;
+ out << "set xrange [" << min_col;
+ out << ":" << max_col;
+ out << "]" << std::endl;
+ out << "set yrange [-" << max_row;
+ out << ":" << min_row;
+ out << "]" << std::endl;
+ out << "plot '-' using 2:(-\\$1):\\" << std::endl;
+ out << " (r(\\$3,\\$4,\\$5)):\\" << std::endl;
+ out << " (g(\\$3,\\$4,\\$5)):\\" << std::endl;
+ out << " (b(\\$3,\\$4,\\$5)) with rgbimage" << std::endl;
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.row() << " ";
+ out << p.col() << " ";
+ out << img(p).hue() << " ";
+ out << img(p).sat() << " ";
+ out << img(p).inty() << std::endl;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ out << "EOF" << std::endl;
+
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:" << filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::save_image_sh_image2d_hsi");
+ return result;
+ }
+
+ //----------------------------------------------------------------------
+ // save_image_sh_image2d(const image2d<I>&, const string&)
+ //----------------------------------------------------------------------
+
+ template <typename I>
+ inline
+ bool save_image_sh_image2d(const image2d<I>& img,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::save_image_sh_image2d");
+ mln_precondition(img.is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+ unsigned min_row = geom::min_row(img);
+ unsigned max_row = geom::max_row(img);
+ unsigned min_col = geom::min_col(img);
+ unsigned max_col = geom::max_col(img);
+
+ if (result)
+ {
+ mln_piter(image2d<I>) p(img.domain());
+
+ // Output data prelude (terminal X11, image).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, val) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "set palette gray" << std::endl;
+ out << "set xrange [" << min_col;
+ out << ":" << max_col;
+ out << "]" << std::endl;
+ out << "set yrange [-" << max_row;
+ out << ":" << min_row;
+ out << "]" << std::endl;
+ out << "plot '-' using 2:(-\\$1):3 with image" <<std::endl;
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.row() << " ";
+ out << p.col() << " ";
+ out << img(p) << std::endl;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ out << "EOF" << std::endl;
+
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:"<< filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::save_image_sh_image2d");
+ return result;
+ }
+
+ //----------------------------------------------------------------------
+ // save_image_sh_image1d(const image1d<I>&, const string&)
+ //----------------------------------------------------------------------
+
+ template <typename I>
+ inline
+ bool save_image_sh_image1d(const image1d<I>& img,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::save_image_sh_image1d");
+ mln_precondition(img.is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+
+ if (result)
+ {
+ mln_piter(image1d<I>) p(img.domain());
+
+ // Output data prelude (terminal X11, impulse).
+ out << "#!/bin/sh" << std::endl;
+ out << "##########################" << std::endl;
+ out << "# Two columns = (x, val) #" << std::endl;
+ out << "##########################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "plot '-' with impulse" << std::endl;
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.ind() << " ";
+ out << img(p) << std::endl;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ out << "EOF" << std::endl;
+
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:"<< filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::save_image_sh_image1d");
+ return result;
+ }
+
+ //----------------------------------------------------------------------
+ // save_image_sh_image3d(const image3d<I>&, const string&)
+ //----------------------------------------------------------------------
+
+
+ template <typename I>
+ inline
+ bool save_image_sh_image3d(const image3d<I>& img,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::impl::save_image_sh_image3d");
+ mln_precondition(img.is_valid());
+
+ std::ofstream out(filename.c_str());
+ bool result = !out.fail();
+
+ if (result)
+ {
+ mln_piter(image3d<I>) p(img.domain());
+
+ // Output data prelude (terminal X11, pointtype 0).
+ out << "#!/bin/sh" << std::endl;
+ out << "####################################" << std::endl;
+ out << "# Columns = (x, y, z, val) #" << std::endl;
+ out << "####################################" << std::endl;
+ out << std::endl;
+ out << "gnuplot <<EOF" << std::endl;
+ out << "set terminal x11 persist 1" << std::endl;
+ out << "splot '-' with points palette pointtype 7" << std::endl;
+
+ // Output data.
+ for_all(p)
+ {
+ out << p.row() << " ";
+ out << p.col() << " ";
+ out << p.sli() << " ";
+ out << img(p) << std::endl;
+ }
+
+ // Close gnuplot data stream.
+ out << "e" << std::endl;
+ out << "EOF" << std::endl;
+
+ out.close();
+ }
+ else
+ {
+ std::cerr << "ERROR[mln::io::plot::save_image_sh]:"<< filename;
+ std::cerr << " couldn't be opened !!" << std::endl;
+ }
+
+ trace::exiting("mln::io::plot::impl::save_image_sh_image3d");
+ return result;
+ }
+
+ } // end of namespace impl
+
+
+ //------------------------------------------------------------------------
+ // Internal.
+ //------------------------------------------------------------------------
+
+ namespace internal
+ {
+ template <typename I>
+ inline
+ bool save_image_sh_dispatch(const util::array< image1d<I> >& stack,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_array_image1d(stack, filename);
+ }
+
+ template <typename I>
+ inline
+ bool save_image_sh_dispatch(const util::array<
+ util::array <image1d<I> > >& stack,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_array_array_image1d(stack, filename);
+ }
+
+ template <typename T>
+ inline
+ bool save_image_sh_dispatch(
+ const util::array<util::array<image1d<algebra::vec<3,T> > > >& stack,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_array_array_image1d_vec3(stack, filename);
+ }
+
+ template <typename T>
+ inline
+ bool save_image_sh_dispatch(
+ const util::array<util::array<image1d<algebra::vec<2,T> > > >& stack,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_array_array_image1d_vec2(stack, filename);
+ }
+
+ template <unsigned n>
+ inline
+ bool save_image_sh_dispatch(const image2d<value::rgb<n> >& img,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_image2d_rgb(img, filename);
+ }
+
+ template <typename T>
+ inline
+ bool save_image_sh_dispatch(const image2d<value::hsl_<T,T,T> >& img,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_image2d_hsl(img, filename);
+ }
+
+ template <typename T>
+ inline
+ bool save_image_sh_dispatch(const image2d<value::hsi_<T,T,T> >& img,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_image2d_hsi(img, filename);
+ }
+
+
+ template <typename I>
+ inline
+ bool save_image_sh_dispatch(const image2d<I>& img,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_image2d(img, filename);
+ }
+
+ template <typename I>
+ inline
+ bool save_image_sh_dispatch(const image1d<I>& img,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_image1d(img, filename);
+ }
+
+ template <typename I>
+ inline
+ bool save_image_sh_dispatch(const image3d<I>& img,
+ const std::string& filename)
+ {
+ return impl::save_image_sh_image3d(img, filename);
+ }
+
+ template <typename I>
+ inline
+ bool save_image_sh_dispatch(const Image<I>& img,
+ const std::string& filename)
+ {
+ return save_image_sh_dispatch(exact(img), filename);
+ }
+
+ } // end of namespace mln::io::plot::internal
+
+ //------------------------------------------------------------------------
+ // Facade.
+ //------------------------------------------------------------------------
+
+ template <typename I>
+ inline
+ bool save_image_sh(const Image<I>& img, const std::string& filename)
+ {
+ trace::entering("mln::io::plot::save_image_sh");
+
+ bool result = internal::save_image_sh_dispatch(img, filename);
+
+ trace::exiting("mln::io::plot::save_image_sh");
+ return result;
+ }
+
+ template <typename I>
+ inline
+ bool save_image_sh(const util::array< image1d<I> >& stack,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::save_image_sh");
+
+ bool result = internal::save_image_sh_dispatch(stack, filename);
+
+ trace::exiting("mln::io::plot::save_image_sh");
+ return result;
+ }
+
+ template <typename I>
+ inline
+ bool save_image_sh(const util::array< util::array< image1d<I> > >& stack,
+ const std::string& filename)
+ {
+ trace::entering("mln::io::plot::save_image_sh");
+
+ bool result = internal::save_image_sh_dispatch(stack, filename);
+
+ trace::exiting("mln::io::plot::save_image_sh");
+ return result;
+ }
+
+
+#endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace mln::io::plot
+
+ } // end of namespace mln::io
+
+} // end of namespace mln
+
+#endif // ! MLN_IO_PLOT_SAVE_IMAGE_SH_HH
diff --git a/milena/sandbox/green/mln/math/ceil.hh b/scribo/sandbox/green/mln/math/ceil.hh
similarity index 100%
copy from milena/sandbox/green/mln/math/ceil.hh
copy to scribo/sandbox/green/mln/math/ceil.hh
diff --git a/milena/sandbox/green/mln/math/floor.hh b/scribo/sandbox/green/mln/math/floor.hh
similarity index 100%
copy from milena/sandbox/green/mln/math/floor.hh
copy to scribo/sandbox/green/mln/math/floor.hh
diff --git a/milena/sandbox/green/mln/value/hsv.hh b/scribo/sandbox/green/mln/value/hsv.hh
similarity index 100%
copy from milena/sandbox/green/mln/value/hsv.hh
copy to scribo/sandbox/green/mln/value/hsv.hh
diff --git a/scribo/sandbox/green/mln/value/rg.hh b/scribo/sandbox/green/mln/value/rg.hh
new file mode 100644
index 0000000..d083ffd
--- /dev/null
+++ b/scribo/sandbox/green/mln/value/rg.hh
@@ -0,0 +1,175 @@
+// Copyright (C) 2007, 2008, 2009, 2010 EPITA LRDE
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_VALUE_RG_HH
+# define MLN_VALUE_RG_HH
+
+/// \file
+///
+/// \brief Define the red/green vectorial image type.
+///
+/// This source implements the red/green (RG) vectorial image type. It
+/// is a partial copy of the rgb type. This type doesn't manage
+/// anykind of interaction. Its purpose is limited to store a couple
+/// of values. Do not use it outside this purpose, i can't garantie
+/// the behaviour.
+///
+/// The following sample is a typical use of the rg type.
+///
+/// #include <mln/accu/stat/histo2d.hh>
+/// #include <mln/core/image/image2d.hh>
+/// #include <mln/data/compute.hh>
+/// #include <mln/data/transform.hh>
+/// #include <mln/fun/v2v/rgb_to_rg.hh>
+/// #include <mln/img_path.hh>
+/// #include <mln/io/ppm/load.hh>
+/// #include <mln/value/rg.hh>
+/// #include <mln/value/rgb8.hh>
+///
+/// int main()
+/// {
+/// typedef mln::value::rg<8> t_rg8
+/// typedef mln::value::rgb8 t_rgb8;
+/// typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+/// typedef mln::image2d<t_rg8> t_image2d_rg8;
+/// typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+/// typedef mln::image2d<unsigned> t_histo;
+/// t_image2d_rgb8 img_rgb8;
+/// t_image2d_rg8 img_rg8;
+/// t_histo histo;
+///
+/// mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+/// img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+/// histo = mln::data::compute(mln::accu::meta::stat::histo2d(), img_rg8);
+///
+/// return 0;
+/// }
+
+
+# include <mln/algebra/vec.hh>
+# include <mln/value/concept/vectorial.hh>
+# include <mln/value/int_u.hh>
+# include <mln/value/rgb8.hh>
+# include <mln/trait/value_.hh>
+
+
+namespace mln
+{
+
+ namespace value
+ {
+
+ // Forward declaration.
+ template <unsigned n> struct rg;
+
+ } // end of namespace mln::value
+
+ namespace trait
+ {
+
+ template <unsigned n>
+ struct value_< mln::value::rg<n> >
+ {
+ enum {
+ dim = 2,
+ nbits = dim * n,
+ card = mln_value_card_from_(nbits)
+ };
+
+ typedef trait::value::nature::vectorial nature;
+ typedef trait::value::kind::color kind;
+ typedef trait::value::quant::high quant;
+
+ typedef void comp;
+ typedef mln::value::int_u<n> comp_0;
+ typedef mln::value::int_u<n> comp_1;
+
+ static comp_0 get_comp_0(const mln::value::rg<n>& v){return v.red(); }
+ static comp_1 get_comp_1(const mln::value::rg<n>& v){return v.green();}
+
+ typedef algebra::vec<dim, float> sum;
+
+ static const char* name()
+ {
+ static std::string s = std::string("rg").append(1, 8 + '0');
+ return s.c_str();
+ }
+ };
+
+ } // end of namespace mln::trait
+
+ namespace value
+ {
+
+ /// \brief Define the red/green vectorial image type.
+ ///
+ /// Param n defines the quantification used for red/green space.
+
+ template <unsigned n>
+ struct rg :public mln::value::Vectorial< rg<n> >,
+ public internal::value_like_<
+ algebra::vec< 2, int_u<n> >, // Equivalent.
+ algebra::vec< 2, int_u<n> >, // Encoding.
+ algebra::vec< 2, int >, // Interoperation.
+ rg<n> > // Exact.
+ {
+ typedef int_u<n> t_red;
+ typedef int_u<n> t_green;
+
+ int_u<n> red() const {return this->v_[0];}
+ int_u<n>& red() {return this->v_[0];}
+ int_u<n> green() const {return this->v_[1];}
+ int_u<n>& green() {return this->v_[1];}
+
+ /// Constructors
+ /// \{
+ /// \brief Create a rg value.
+ ///
+ /// Two constructors exist, the first one do nothing and the second one
+ /// initializes the red/green components from a rgb value.
+ rg(){}
+ rg(const rgb8& val){this->v_[0] = val.red(); this->v_[1] = val.green();}
+ /// \}
+
+ /// \brief Affect a rg value to this object.
+ /// \param[in] rhs the value to affect to this object.
+ ///
+ /// If the two objects are different, then then copy the
+ /// underline array of values.
+
+ rg operator=(const rg& rhs)
+ {
+ if (&rhs != this)
+ this->v_ = rhs.v_;
+
+ return *this;
+ }
+ };
+
+ } // end of namespace mln::value
+
+} // end of namespace mln
+
+#endif // ! MLN_VALUE_RG_HH
diff --git a/scribo/sandbox/green/tests/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/tests/accu/stat/histo1d/Makefile.am
new file mode 100644
index 0000000..77f9015
--- /dev/null
+++ b/scribo/sandbox/green/tests/accu/stat/histo1d/Makefile.am
@@ -0,0 +1,153 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/tests
+BUILD__PATTERN= green/build/tests
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/scribo/sandbox/green/tests/accu/stat/histo1d/histo1d.cc b/scribo/sandbox/green/tests/accu/stat/histo1d/histo1d.cc
new file mode 100644
index 0000000..5a5c4c4
--- /dev/null
+++ b/scribo/sandbox/green/tests/accu/stat/histo1d/histo1d.cc
@@ -0,0 +1,21 @@
+/// TEST HISTO1D
+
+#include <mln/accu/stat/histo1d.hh>
+#include <mln/data/compute.hh>
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/img_path.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/value/int_u8.hh>
+
+int main()
+{
+ typedef mln::value::int_u8 t_int_u8;
+ mln::image2d<t_int_u8> img;
+ mln::image1d<unsigned> histo;
+
+ mln::io::pgm::load(img, OLENA_IMG_PATH"/lena.pgm");
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), img);
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am b/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
new file mode 100644
index 0000000..a96b2e9
--- /dev/null
+++ b/scribo/sandbox/green/use/accu/stat/histo1d/Makefile.am
@@ -0,0 +1,153 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/use
+BUILD__PATTERN= green/build/use
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc b/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc
new file mode 100644
index 0000000..1c6176b
--- /dev/null
+++ b/scribo/sandbox/green/use/accu/stat/histo1d/histo1d.cc
@@ -0,0 +1,24 @@
+/// \file
+///
+/// \brief Minimal code for building 1d image histogram version.
+///
+
+#include <mln/accu/stat/histo1d.hh>
+#include <mln/data/compute.hh>
+#include <mln/core/image/image1d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/img_path.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/value/int_u8.hh>
+
+int main()
+{
+ typedef mln::value::int_u8 t_int_u8;
+ mln::image2d<t_int_u8> img;
+ mln::image1d<unsigned> histo;
+
+ mln::io::pgm::load(img, OLENA_IMG_PATH"/lena.pgm");
+ histo = mln::data::compute(mln::accu::meta::stat::histo1d(), img);
+
+ return 0;
+}
diff --git a/scribo/sandbox/green/use/accu/stat/histo2d/Makefile.am b/scribo/sandbox/green/use/accu/stat/histo2d/Makefile.am
new file mode 100644
index 0000000..a96b2e9
--- /dev/null
+++ b/scribo/sandbox/green/use/accu/stat/histo2d/Makefile.am
@@ -0,0 +1,153 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+#LOADLIBES= -lboost_filesystem
+INCLUDES1= -I$(HOME)/git/olena/scribo/sandbox/green
+INCLUDES2= -I$(HOME)/git/olena/milena
+INCLUDES= $(INCLUDES1) $(INCLUDES2)
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O1 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+#CXXFLAGS= -DNDEBUG -O3 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/use
+BUILD__PATTERN= green/build/use
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/scribo/sandbox/green/use/accu/stat/histo2d/histo2d.cc b/scribo/sandbox/green/use/accu/stat/histo2d/histo2d.cc
new file mode 100644
index 0000000..6369b5a
--- /dev/null
+++ b/scribo/sandbox/green/use/accu/stat/histo2d/histo2d.cc
@@ -0,0 +1,33 @@
+/// \file
+///
+/// \brief Minimal code for building 2d image histogram version.
+///
+
+#include <mln/accu/stat/histo2d.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/data/compute.hh>
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb_to_rg.hh>
+#include <mln/img_path.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/value/rg.hh>
+#include <mln/value/rgb8.hh>
+
+int main()
+{
+ typedef mln::value::rg<8> t_rg8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::fun::v2v::rgb_to_rg<8> t_rgb_to_rg;
+ typedef mln::image2d<t_rg8> t_image2d_rg8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<unsigned> t_histo;
+ t_image2d_rgb8 img_rgb8;
+ t_image2d_rg8 img_rg8;
+ t_histo histo;
+
+ mln::io::ppm::load(img_rgb8, OLENA_IMG_PATH"/lena.ppm");
+ img_rg8 = mln::data::transform(img_rgb8, t_rgb_to_rg());
+ histo = mln::data::compute(mln::accu::meta::stat::histo2d(), img_rg8);
+
+ return 0;
+}
--
1.5.6.5