Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 9625 discussions
#216: Color artifacts in HQx
---------------------+------------------------------------------------------
Reporter: freling | Owner: freling
Type: defect | Status: new
Priority: minor | Milestone:
Component: Milena | Version: 1.0
Keywords: |
---------------------+------------------------------------------------------
HQx algorithms have some color artifacts.
--
Ticket URL: <https://trac.lrde.org/olena/ticket/216>
Olena <http://olena.lrde.epita.fr>
Olena, a generic and efficient C++ image processing library.
1
0
* green/doc/formulae/formulae.tex : Correct file.
---
trunk/milena/sandbox/ChangeLog | 6 +
.../milena/sandbox/green/doc/formulae/formulae.tex | 116 ++++++++++----------
2 files changed, 64 insertions(+), 58 deletions(-)
diff --git a/trunk/milena/sandbox/ChangeLog b/trunk/milena/sandbox/ChangeLog
index 6572258..923875c 100644
--- a/trunk/milena/sandbox/ChangeLog
+++ b/trunk/milena/sandbox/ChangeLog
@@ -1,3 +1,9 @@
+2009-09-11 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Correct english writing in the documentation file.
+
+ * green/doc/formulae/formulae.tex : Correct file.
+
2009-09-10 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
Try to fix order problem between points and vectors.
diff --git a/trunk/milena/sandbox/green/doc/formulae/formulae.tex b/trunk/milena/sandbox/green/doc/formulae/formulae.tex
index 52af7a7..655cb1a 100644
--- a/trunk/milena/sandbox/green/doc/formulae/formulae.tex
+++ b/trunk/milena/sandbox/green/doc/formulae/formulae.tex
@@ -41,7 +41,7 @@
\newcommand{\fm}[1]{\mathbb{#1}}
%% \df
-%% input : the set which the dim we are intering in
+%% input : the set whose dimension we are interested in
%%
\newcommand{\df}[1]{|{\mathbb{#1}}|}
@@ -65,20 +65,20 @@ in the development.
\section{Notations}
\begin{itemize}
- \item Use lowercase and normal font for the scalar variables.
- \item Use lowercase and bold font for the vector variables.
- \item Use uppercase and normal font for the matrix variables.
- \item Use uppercase and double font for the set variables.
+ \item Use lowercase and normal font for scalar variables.
+ \item Use lowercase and bold font for vector variables.
+ \item Use uppercase and normal font for matrix variables.
+ \item Use uppercase and double font for set variables.
\end {itemize}
%=================================================================
\subsection{Sets}
-There is three particular sets that we use every time:
+There are three particular sets that we use every time:
\begin{itemize}
- \item The color space $\fm{C}$ in which the pixels take their value.
- \item The dataset $\fm{P}$ which contains every pixel we take care.
- \item The group set $\fm{G}$ that define any splitting of the dataset.
+ \item The color space $\fm{C}$ in which the pixels take their values.
+ \item The dataset $\fm{P}$ which contains every pixel we care about.
+ \item The group set $\fm{G}$ that defines any splitting of the dataset.
\end{itemize}
\begin{tabular}{|c|l|l|c|c|}
@@ -98,15 +98,15 @@ There is three particular sets that we use every time:
%=================================================================
\subsection{Color space}
-We use the euclidian distance.
+We use the Euclidian distance.
-$$
+\[
d(a,b) =
\sqrt{\sum_{i=0}^q (a_i - b_i)^2} =
\sqrt{(a_x - b_x)^2 + (a_y - b_y)^2 + (a_z - b_z)^2}
-$$
+\]
-$$
+\[
d(a,b)^2 =
\left[\begin{array}{ccc}
a_x - b_x & a_y - b_y & a_z - b_z
@@ -117,13 +117,13 @@ d(a,b)^2 =
a_y - b_y \\
a_y - b_z
\end{array}\right]
-$$
+\]
%=================================================================
\subsection{Data points in $\mathbb{R}^3$}
We present the four points of the dataset with their vector representation.
-$$
+\[
\bm{a} =
\left[\begin{array}{c}
a_x \\
@@ -143,9 +143,9 @@ $$
p_{13}
\end{array}\right]
= \bm{p}_1
-$$
+\]
-$$
+\[
\bm{b} =
\left[\begin{array}{c}
b_x \\
@@ -187,9 +187,9 @@ $$
p_{33}
\end{array}\right]
= \bm{p}_3
-$$
+\]
-$$
+\[
\mbox{\boldmath$d$} =
\left[\begin{array}{c}
d_x \\
@@ -209,11 +209,11 @@ $$
p_{43}
\end{array}\right]
= \bm{p}_4
-$$
+\]
One may group the four points in one matrix P :
-$$
+\[
P =
\left[\begin{array}{c}
\bm{a}^t \\
@@ -249,12 +249,12 @@ P =
\bm{p}_3^t \\
\bm{p}_4^t
\end{array}\right]
-$$
+\]
%=================================================================
\subsection{The group}
-We can define the group set $\fm{G}$ in thow context:
+We can define the group set $\fm{G}$ in this context:
\begin{itemize}
\item First, the group set is a partition.
\item Second, the group set if a fuzzy set.
@@ -321,7 +321,7 @@ Let's have a look to the first three moments.
%=================================================================
\subsection{The mean}
-$$
+\[
\mbox{\boldmath$m$} =
\left[\begin{array}{c}
m_x \\
@@ -353,8 +353,8 @@ $$
\mbox{\boldmath$d$})
=
\frac{1}{4}\sum_{i=1}^{4}\mbox{\boldmath$p$}_i
-$$
-$$
+\]
+\[
\mbox{\boldmath$m$} =
\frac{1}{4}
\left[\begin{array}{cccc}
@@ -382,10 +382,10 @@ $$
\end{array}\right]
=
\frac{1}{4} P^t \mbox{\boldmath$ 1$}
-$$
+\]
The mean matrix:
-$$
+\[
M =
\left[\begin{array}{c}
\mbox{\boldmath$m$}^t \\
@@ -407,10 +407,10 @@ M =
m_1 & m_2 & m_3 \\
m_1 & m_2 & m_3
\end{array}\right]
-$$
+\]
We define the difference between a point $\mbox{\boldmath$p$}_i$ and the mean:
-$$
+\[
(\mbox{\boldmath$p$}_i - \mbox{\boldmath$m$}) =
\left[\begin{array}{c}
p_{ix} - m_x \\
@@ -423,11 +423,11 @@ $$
p_{i2} - m_2 \\
p_{i3} - m_3
\end{array}\right]
-$$
+\]
And for all the dataset:
-$$
+\[
(P - M) =
\left[\begin{array}{ccc}
a_x & a_y & a_z \\
@@ -449,12 +449,12 @@ $$
c_x - m_x & c_y - m_y & c_z - m_z \\
d_x - m_x & d_y - m_y & d_z - m_z
\end{array}\right]
-$$
+\]
%=================================================================
\subsection{The variance}
-$$
+\[
\begin{array}{lcl}
V & = &
\left[\begin{array}{ccc}
@@ -501,12 +501,12 @@ V & = &
\frac{1}{4}
(P - M)^t (P - M)
\end{array}
-$$
+\]
%#################################################################
\section{Splitting into groups}
-When we study some mixed population, the total variance can be splitted in the
-the variance between the groups and in the variance whithin each group.
+When we study some mixed population, the total variance can be split in
+the variance between the groups and in the variance within each group.
We define two groups in the population. Each group owns its moments of the
second order.
@@ -514,51 +514,51 @@ second order.
%=================================================================
\subsection{Decomposing the count}
-$$
+\[
\begin{array}{lcl}
n_t & = & n_1 + n_2 \\
& = & \sum_{i=1}^{2} n_i
\end{array}
-$$
+\]
%=================================================================
\subsection{Decomposing the mean}
-$$
+\[
\begin{array}{lcl}
\mbox{\boldmath$m_t$} & = &
\frac{1}{n_t}(n_1 \mbox{\boldmath$m_1$} + n_2 \mbox{\boldmath$m_2$}) \\
& = &
\frac{1}{n_t}\sum_{i=1}^{2} n_i \mbox{\boldmath$m_i$}
\end{array}
-$$
+\]
%=================================================================
\subsection{Decomposing the variance}
-When we study some mixed population, the total variance can be splitted in the
-the variance between the groups and in the variance whithin each group.
+When we study some mixed population, the total variance can be split in
+the variance between the groups and in the variance within each group.
-$$
+\[
V_t = V_i + V_b
-$$
+\]
-$$
+\[
\begin{array}{lcl}
V_i & = & \frac{1}{n_t}(n_1 V_1 + n_2 V_2) \\
& = & \frac{1}{n_t}\sum_{i=1}^2 n_i V_i
\end{array}
-$$
+\]
-$$
+\[
\begin{array}{lcl}
V_b & = & \frac{1}{n_t}(n_1 (\mbox{\boldmath$m_1$} - \mbox{\boldmath$m_t$})^2 +
n_2 (\mbox{\boldmath$m_2$} - \mbox{\boldmath$m_t$})^2 \\
& = & \frac{1}{n_t} \sum_{i=1}^2 n_i
(\mbox{\boldmath$m_i$} - \mbox{\boldmath$m_t$})^2
\end{array}
-$$
+\]
%#################################################################
\section{Basis}
@@ -566,7 +566,7 @@ $$
%%=================================================================
\subsection{Determinant of a square matrix 3x3}
-$$
+\[
\det{V} =
\left|\begin{array}{ccc}
v_{11} & v_{12} & v_{13} \\
@@ -577,12 +577,12 @@ $$
v_{11}(v_{22}v_{33} - v_{32}v_{23})
- v_{12}(v_{21}v_{33} - v_{31}v_{23})
+ v_{13}(v_{21}v_{32} - v_{31}v_{22})
-$$
+\]
%%=================================================================
\subsection{Transpose}
-$
+\[
V^t =
\left[\begin{array}{ccc}
v_{11} & v_{12} & v_{13} \\
@@ -595,7 +595,7 @@ V^t =
v_{12} & v_{22} & v_{32} \\
v_{13} & v_{23} & v_{33}
\end{array}\right]
-$
+\]
%%=================================================================
\subsection{Inverse of a square matrix 3x3}
@@ -759,8 +759,8 @@ $$
%%=================================================================
\subsection{Eigenvalues and eigenvectors}
-We assume that we work on variance/covariance matrix which is real and symetric.
-In this case, all the three eigen values are real.
+We assume that we work on a variance/covariance matrix which is real and
+symmetric. In this case, all the three eigenvalues are real.
$$
V \bm{x} = \lambda \bm{x}
@@ -1089,14 +1089,14 @@ polynomia. The difficulties disappear when we find one of the three roots.
A planar regression allows us to reach the equation of the plane. From the
equation, we can determine its normal vector $\bm{w}$. It satisfies the
following equation $A\bm{w} = \lambda_3\bm{w}$. Thus we know $\lambda_3$.
-By the way, as far as $trace(A) = \lambda_1 + \lambda_2 + \lambda_3$ and
-$det(A) = \lambda_1 \lambda_2 \lambda_3$, then we can access to the value of
+By the way, $trace(A) = \lambda_1 + \lambda_2 + \lambda_3$ and
+$det(A) = \lambda_1 \lambda_2 \lambda_3$, then we can determine the value of
the two others eigenvalues (just solve $\lambda^2 - (trace(A) - \lambda_3)
\lambda + \frac{det(A)}{\lambda_3} = 0$). The knowledge of $\lambda_1$ and
$\lambda_2$ let us find $\bm{u}$ and $\bm{v}$ by the equations $A\bm{u} =
\lambda_1\bm{u}$ and $A\bm{v} = \lambda_2\bm{v}$.
-Let's center the points by susbtracting their center of mass. Now, we have
+Let's center the points by subtracting their center of mass. Now, we have
three equivalent ways to estimate the coefficients of the plane:
\begin{itemize}
\item if not $c = 0$, then $\frac{a}{c}x + \frac{b}{c}y + z = 0$,
--
1.5.6.5
1
0
* green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
(var_histo, mean_histo) : Comment p.to_vec code.
---
trunk/milena/sandbox/ChangeLog | 7 +++++++
.../tests/accu/stat/histo3d_rgb/histo3d_rgb.cc | 2 ++
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/trunk/milena/sandbox/ChangeLog b/trunk/milena/sandbox/ChangeLog
index 8b4d62c..6572258 100644
--- a/trunk/milena/sandbox/ChangeLog
+++ b/trunk/milena/sandbox/ChangeLog
@@ -1,5 +1,12 @@
2009-09-10 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+ Try to fix order problem between points and vectors.
+
+ * green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
+ (var_histo, mean_histo) : Comment p.to_vec code.
+
+2009-09-10 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
Write down the basis of the quick tour summary documentation.
* green/doc/quick_tour : New specific directory.
diff --git a/trunk/milena/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc b/trunk/milena/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
index 37645ef..114a52d 100644
--- a/trunk/milena/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
+++ b/trunk/milena/sandbox/green/tests/accu/stat/histo3d_rgb/histo3d_rgb.cc
@@ -215,6 +215,7 @@ mln::algebra::vec<3,float> mean_histo(const mln::image3d<unsigned>& img)
*/
count += img(p);
sum += conv((vec3f)p) * img(p);
+ // sum += p.to_vec() * img(p);
}
result = sum / count;
@@ -260,6 +261,7 @@ mln::algebra::mat<3,3,float> var_histo2(const mln::image3d<unsigned>& img)
for_all(p)
{
+ // point = p.to_vec() - mean;
point = conv((vec3f)p) - mean;
result += img(p) * (point * point.t());
}
--
1.5.6.5
1
0
* apps/graph-morpho/Makefile.am (complex1d_SOURCES):
Add io.hh and morpho.hh.
* apps/graph-morpho/morpho.hh: Typo.
Aesthetic changes.
---
milena/ChangeLog | 9 +++++++++
milena/apps/graph-morpho/Makefile.am | 2 +-
milena/apps/graph-morpho/morpho.hh | 8 ++++----
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index d40aae2..175d674 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,14 @@
2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+ Misc. changes in apps/graph-morpho.
+
+ * apps/graph-morpho/Makefile.am (complex1d_SOURCES):
+ Add io.hh and morpho.hh.
+ * apps/graph-morpho/morpho.hh: Typo.
+ Aesthetic changes.
+
+2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+
Simplify apps/graph-morpho/complex1d.cc.
* apps/graph-morpho/io.hh (println): Take an extra argument to
diff --git a/milena/apps/graph-morpho/Makefile.am b/milena/apps/graph-morpho/Makefile.am
index faa0fd4..f3440c4 100644
--- a/milena/apps/graph-morpho/Makefile.am
+++ b/milena/apps/graph-morpho/Makefile.am
@@ -21,7 +21,7 @@ APPS_CXXFLAGS = @APPS_CXXFLAGS@
AM_CXXFLAGS = $(APPS_CXXFLAGS)
noinst_PROGRAMS = complex1d
-complex1d_SOURCES = complex1d.cc
+complex1d_SOURCES = complex1d.cc io.hh morpho.hh
TESTS = complex1d
diff --git a/milena/apps/graph-morpho/morpho.hh b/milena/apps/graph-morpho/morpho.hh
index bc9a361..ef11951 100644
--- a/milena/apps/graph-morpho/morpho.hh
+++ b/milena/apps/graph-morpho/morpho.hh
@@ -45,12 +45,12 @@
# include <mln/core/image/complex_neighborhood_piter.hh>
-/*--------------------------.
-| Vertex-edges combinator. |
-`--------------------------*/
+/*----------------------------.
+| Vertices-edges combinator. |
+`----------------------------*/
/// Combine the vertices and the edges of two images to create a new
-/// graph image (operator \f$\ovee\f$).
+/// graph image (``operator'' \f$\ovee\f$).
template <typename I>
inline
mln_concrete(I)
--
1.6.4.2
1
0
* apps/graph-morpho/io.hh (println): Take an extra argument to
print a (leading) message.
* apps/graph-morpho/complex1d.cc: Adjust and simplify.
---
milena/ChangeLog | 8 +++
milena/apps/graph-morpho/complex1d.cc | 83 ++++++++------------------------
milena/apps/graph-morpho/io.hh | 4 +-
3 files changed, 32 insertions(+), 63 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index c48cbd0..d40aae2 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,13 @@
2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+ Simplify apps/graph-morpho/complex1d.cc.
+
+ * apps/graph-morpho/io.hh (println): Take an extra argument to
+ print a (leading) message.
+ * apps/graph-morpho/complex1d.cc: Adjust and simplify.
+
+2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+
Make apps/graph-morpho/complex1d.cc more modular.
* apps/graph-morpho/complex1d.cc: Move I/O-related functions...
diff --git a/milena/apps/graph-morpho/complex1d.cc b/milena/apps/graph-morpho/complex1d.cc
index 9cf23b4..d3650a3 100644
--- a/milena/apps/graph-morpho/complex1d.cc
+++ b/milena/apps/graph-morpho/complex1d.cc
@@ -56,87 +56,46 @@ int main()
// Dilations and erosions. //
// ------------------------ //
- /* Set the values so that X corresponds to the graph X of the ISMM
- 2009 paper from Jean Cousty et al. */
+ /* Create an image corresponding to the graph X of the ISMM 2009
+ paper from Jean Cousty et al. */
image2d<bool> x_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/x.pbm");
ima_t x = make_regular_complex1d_image(x_pbm);
box2d x_box(x_pbm.nrows() / 2 + 1, x_pbm.ncols() / 2 + 1);
- std::cout << "x:" << std::endl;
- println(x, x_box);
+ println("x:", x, x_box);
- ima_t dil_e2v_ima = dilation_e2v(x);
- std::cout << "dil_e2v_ima:" << std::endl;
- println(dil_e2v_ima, x_box);
+ println("dilation_e2v(x):", dilation_e2v(x), x_box);
+ println("erosion_v2e(x):", erosion_v2e(x), x_box);
- ima_t ero_v2e_ima = erosion_v2e(x);
- std::cout << "ero_v2e_ima:" << std::endl;
- println(ero_v2e_ima, x_box);
+ println("erosion_e2v(x):", erosion_e2v(x), x_box);
+ println("dilation_v2e(x):", dilation_v2e(x), x_box);
+ println("dilation_graph(x):", dilation_graph(x), x_box);
+ println("erosion_graph(x):", erosion_graph(x), x_box);
- ima_t ero_e2v_ima = erosion_e2v(x);
- std::cout << "ero_e2v_ima:" << std::endl;
- println(ero_e2v_ima, x_box);
-
- ima_t dil_v2e_ima = dilation_v2e(x);
- std::cout << "dil_v2e_ima:" << std::endl;
- println(dil_v2e_ima, x_box);
-
-
- ima_t dil_ima = dilation_graph(x);
- std::cout << "dil_ima:" << std::endl;
- println(dil_ima, x_box);
-
- ima_t ero_ima = erosion_graph(x);
- std::cout << "ero_ima:" << std::endl;
- println(ero_ima, x_box);
-
-
- ima_t alpha3_ima = alpha3(x);
- std::cout << "alpha3_ima:" << std::endl;
- println(alpha3_ima, x_box);
-
- ima_t beta3_ima = beta3(x);
- std::cout << "beta3_ima:" << std::endl;
- println(beta3_ima, x_box);
+ println("alpha3(x):", alpha3(x), x_box);
+ println("beta3(x):", beta3(x), x_box);
// --------- //
// Filters. //
// --------- //
+ // Create an image corresponding to the graph Y.
image2d<bool> y_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/y.pbm");
ima_t y = make_regular_complex1d_image(y_pbm);
box2d y_box(y_pbm.nrows() / 2 + 1, y_pbm.ncols() / 2 + 1);
- std::cout << "y:" << std::endl;
- println(y, y_box);
-
- ima_t ope_ima = opening_graph(y);
- std::cout << "ope_ima:" << std::endl;
- println(ope_ima, y_box);
-
- ima_t half_ope_ima = half_opening_graph(y);
- std::cout << "half_ope_ima:" << std::endl;
- println(half_ope_ima, y_box);
-
- ima_t beta3_o_alpha3_ima = beta3(alpha3(y));
- std::cout << "beta3_o_alpha3_ima:" << std::endl;
- println(beta3_o_alpha3_ima, y_box);
+ println("y:", y, y_box);
+ println("opening_graph(y):", opening_graph(y), y_box);
+ println("half_opening_graph(y):", half_opening_graph(y), y_box);
+ println("beta3(alpha3(y)):", beta3(alpha3(y)), y_box);
+ // Create an image corresponding to the graph Z.
image2d<bool> z_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/z.pbm");
ima_t z = make_regular_complex1d_image(z_pbm);
box2d z_box(z_pbm.nrows() / 2 + 1, z_pbm.ncols() / 2 + 1);
- std::cout << "z:" << std::endl;
- println(z, z_box);
-
- ima_t clo_ima = closing_graph(z);
- std::cout << "clo_ima:" << std::endl;
- println(clo_ima, z_box);
-
- ima_t half_clo_ima = half_closing_graph(z);
- std::cout << "half_clo_ima:" << std::endl;
- println(half_clo_ima, z_box);
+ println("z:", z, z_box);
- ima_t alpha3_o_beta3_ima = alpha3(beta3(z));
- std::cout << "alpha3_o_beta3_ima:" << std::endl;
- println(alpha3_o_beta3_ima, z_box);
+ println("closing_graph(z):", closing_graph(z), z_box);
+ println("half_closing_graph(z):", half_closing_graph(z), z_box);
+ println("alpha3(beta3(z)):", alpha3(beta3(z)), z_box);
}
diff --git a/milena/apps/graph-morpho/io.hh b/milena/apps/graph-morpho/io.hh
index 5b7a809..f2dfa9a 100644
--- a/milena/apps/graph-morpho/io.hh
+++ b/milena/apps/graph-morpho/io.hh
@@ -155,7 +155,8 @@ make_regular_complex1d_image(const mln::Image<I>& input_)
inline
void
-println(const mln::bin_1complex_image2d& ima, const mln::box2d& support)
+println(const std::string& message, const mln::bin_1complex_image2d& ima,
+ const mln::box2d& support)
{
using namespace mln;
@@ -205,6 +206,7 @@ println(const mln::bin_1complex_image2d& ima, const mln::box2d& support)
}
}
+ std::cout << message << std::endl;
for (int row = vertices.domain().pmin().row();
row <= vertices.domain().pmax().row(); ++row)
{
--
1.6.4.2
1
0
10 Sep '09
* apps/graph-morpho/complex1d.cc: Move I/O-related functions...
* apps/graph-morpho/io.hh: ...here (new file).
* apps/graph-morpho/complex1d.cc: Move morpho-related functions...
* apps/graph-morpho/morpho.hh: ...here (new file).
---
milena/ChangeLog | 9 +
milena/apps/graph-morpho/complex1d.cc | 647 +--------------------------------
milena/apps/graph-morpho/io.hh | 235 ++++++++++++
milena/apps/graph-morpho/morpho.hh | 503 +++++++++++++++++++++++++
4 files changed, 762 insertions(+), 632 deletions(-)
create mode 100644 milena/apps/graph-morpho/io.hh
create mode 100644 milena/apps/graph-morpho/morpho.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 65dfce9..c48cbd0 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,14 @@
2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+ Make apps/graph-morpho/complex1d.cc more modular.
+
+ * apps/graph-morpho/complex1d.cc: Move I/O-related functions...
+ * apps/graph-morpho/io.hh: ...here (new file).
+ * apps/graph-morpho/complex1d.cc: Move morpho-related functions...
+ * apps/graph-morpho/morpho.hh: ...here (new file).
+
+2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+
Alias for binary 1-complex-based images in the dicrete plane.
* mln/core/alias/complex_image.hh (mln::bin_1complex_image2d):
diff --git a/milena/apps/graph-morpho/complex1d.cc b/milena/apps/graph-morpho/complex1d.cc
index e220fca..9cf23b4 100644
--- a/milena/apps/graph-morpho/complex1d.cc
+++ b/milena/apps/graph-morpho/complex1d.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -28,646 +28,29 @@
/// 1-complex images.
///
/// \todo There should be a second version of this program, where the
-/// graph structure is implemented with an actual graph.
-
-#include <mln/core/image/complex_image.hh>
-#include <mln/geom/complex_geometry.hh>
-#include <mln/core/image/complex_neighborhoods.hh>
-#include <mln/core/image/complex_neighborhood_piter.hh>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/point2d.hh>
-#include <mln/core/alias/box2d.hh>
-
-#include <mln/core/site_set/p_set.hh>
-#include <mln/util/site_pair.hh>
-
-#include <mln/core/routine/duplicate.hh>
-
-#include <mln/math/abs.hh>
+/// graph structure is implemented with an actual mln::util::graph.
#include <mln/io/pbm/load.hh>
-#include "apps/data.hh"
-
-using namespace mln;
-
-// A graph is considered as a 1-complex here.
-const unsigned dim = 1;
-typedef topo::complex<dim> complex_t;
-
-// Binary graph-based image with vertices aligned on a discrete 2D grid.
-typedef point2d site_t;
-typedef geom::complex_geometry<dim, site_t> geom_t;
-typedef complex_image<dim, geom_t, bool> ima_t;
-
-// Iterator type on faces (vertices and edges).
-typedef p_n_faces_fwd_piter<dim, geom_t> face_iter;
-// Edge-to-vertices neighborhood.
-typedef complex_lower_neighborhood<dim, geom_t> e2v_t;
-const e2v_t e2v;
-// Vertex-to-edges neighborhood.
-typedef complex_higher_neighborhood<dim, geom_t> v2e_t;
-const v2e_t v2e;
-
-
-// FIXME: We should turn this routine into something much more
-// generic, and move it to the library (into make/).
-ima_t
-build_regular_complex1d_image(const box2d& support)
-{
- unsigned nrows = support.pmax().row() - support.pmin().row() + 1;
- unsigned ncols = support.pmax().col() - support.pmin().col() + 1;
-
- typedef topo::n_face<0, dim> vertex_t;
-
- complex_t c;
- geom_t geom;
-
- // Vertices.
- for (unsigned row = 0; row < nrows; ++row)
- for (unsigned col = 0; col < ncols; ++col)
- {
- c.add_face();
- geom.add_location(point2d(row,col));
- }
-
- // Edges.
- for (unsigned row = 0; row < nrows; ++row)
- {
- // Horizontal edges.
- for (unsigned col = 1; col < ncols; ++col)
- {
- // First vertex.
- vertex_t v1(c, row * ncols + col - 1);
- // Second vertex.
- vertex_t v2(c, row * ncols + col);
- // Edge bewteen V1 and V2.
- c.add_face(v1 + v2);
- }
-
- // Vertical edges.
- if (row != 0)
- for (unsigned col = 0; col < ncols; ++col)
- {
- // First vertex.
- vertex_t v1(c, (row - 1) * ncols + col);
- // Second vertex.
- vertex_t v2(c, row * ncols + col);
- // Edge bewteen V1 and V2.
- c.add_face(v1 + v2);
- }
- }
-
- // Site set (domain) of the image.
- p_complex<dim, geom_t> pc(c, geom);
-
- // Image based on this site set.
- ima_t ima(pc);
- return ima;
-}
-
-template <typename I>
-ima_t
-make_regular_complex1d_image(const Image<I>& input_)
-{
- const I& input = exact(input_);
- const box2d& input_box = input.domain();
- // The input image must have an odd number of rows and columns.
- mln_precondition(input_box.nrows() % 2 == 1);
- mln_precondition(input_box.ncols() % 2 == 1);
-
- // The domain of the graph image is twice as small, since we
- // consider only vertices (edges are set ``between'' vertices).
- box2d output_box(input_box.nrows() / 2 + 1,
- input_box.ncols() / 2 + 1);
- ima_t output = build_regular_complex1d_image(output_box);
-
- // Add values on vertices.
- p_n_faces_fwd_piter<dim, geom_t> v(output.domain(), 0);
- for_all(v)
- {
- mln_site_(geom_t) s(v);
- // Site S is point2d multi-site and should be a singleton (since V
- // iterates on vertices).
- mln_invariant(s.size() == 1);
- point2d p = s.front();
- point2d q(p.row() * 2, p.col() * 2);
- output(v) = input(q);
- }
-
- // Add values on edges.
- p_n_faces_fwd_piter<dim, geom_t> e(output.domain(), 1);
- for_all(e)
- {
- mln_site_(geom_t) s(e);
- // Site S is point2d multi-site and should be a pair (since E
- // iterates on vertices).
- mln_invariant(s.size() == 2);
- point2d p1 = s[0];
- point2d p2 = s[1];
- mln_invariant(math::abs(p1.row() - p2.row()) == 1
- || math::abs(p1.col() - p2.col()) == 1);
- point2d q (p1.row() + p2.row(), p1.col() + p2.col());
- output(e) = input(q);
- }
-
- return output;
-}
-
-
-template <typename T>
-void
-println(const complex_image<dim, geom_t, T>& ima, const box2d& support)
-{
- // These are admittedly loose preconditions, but we cannot check
- // much.
- mln_precondition(ima.nsites() == support.nsites());
-
- image2d<bool> vertices(support);
- image2d<bool> h_edges(box2d(support.pmin(), support.pmax() - dpoint2d(0, 1)));
- image2d<bool> v_edges(box2d(support.pmin(), support.pmax() - dpoint2d(1, 0)));
-
- // Iterator on vertices.
- p_n_faces_fwd_piter<dim, geom_t> v(ima.domain(), 0);
- for_all(v)
- {
- mln_site_(geom_t) s(v);
- // Site S is point2d multi-site and should be a singleton (since V
- // iterates on vertices).
- mln_invariant(s.size() == 1);
- point2d p = s.front();
- vertices(p) = ima(v);
- }
-
- // Iterator on edges.
- p_n_faces_fwd_piter<dim, geom_t> e(ima.domain(), 1);
- for_all(e)
- {
- mln_site_(geom_t) s(e);
- // Site S is point2d multi-site and should be a pair (since E
- // iterates on vertices).
- mln_invariant(s.size() == 2);
- point2d p1 = s[0];
- point2d p2 = s[1];
- if (p1.row() == p2.row())
- {
- // Horizontal edge.
- h_edges(p1) = ima(e);
- }
- else
- {
- // Vertical edge.
- mln_assertion(p1.col() == p2.col());
- v_edges(p1) = ima(e);
- }
- }
-
- for (int row = vertices.domain().pmin().row();
- row <= vertices.domain().pmax().row(); ++row)
- {
- for (int col = vertices.domain().pmin().col();
- col <= vertices.domain().pmax().col(); ++col)
- {
- point2d p(row, col);
- // Vertex.
- std::cout << (vertices(p) ? "O" : ".");
- // Potential horizontal edge on the right of the vertex.
- if (col != vertices.domain().pmax().col())
- std::cout << (h_edges(p) ? " - " : " ");
- }
- std::cout << std::endl;
-
- // Potential vertical edge below the vertices of the current ROW.
- if (row != vertices.domain().pmax().row())
- for (int col = vertices.domain().pmin().col();
- col <= vertices.domain().pmax().col(); ++col)
- {
- point2d p(row, col);
- std::cout << (v_edges(p) ? "| " : " ");
- }
- std::cout << std::endl;
- }
-}
-
-
-/*------------------------------------.
-| Morphological operators on graphs. |
-`------------------------------------*/
-
-// ------------------------ //
-// Dilations and erosions. //
-// ------------------------ //
-
-/* FIXME: By constraining the domain of the input and passing the
- neighborhood, one should be able to use a truly generic dilation
- (resp. erosion), or even use Milena's standard morpho::dilation
- (resp. morpho::erosion). */
-
-/// Dilation from edges to vertices (\f$\delta^\bullet\f$).
-template <typename I>
-mln_concrete(I)
-dilation_e2v(const Image<I>& input_)
-{
- const I& input = exact(input_);
- mln_concrete(I) output;
- initialize(output, input);
- /* FIXME: It'd be better to write something like this:
-
- mln_piter(...) v(output | vertices);
-
- We can actually write this, but `vertices' has to be a predicate
- on sites (p2b function), which is not efficient, since both
- vertices and edges will be browsed.
-
- It would be very nice if `vertices' could be an actual site set,
- so that `output | vertices' creates a morpher smart enough to
- browse /only/ vertices. */
- p_n_faces_fwd_piter<dim, geom_t> v(input.domain(), 0);
- mln_niter_(v2e_t) e(v2e, v);
- for_all(v)
- {
- output(v) = false;
- for_all(e)
- if (input(e))
- {
- output(v) = true;
- break;
- }
- }
- return output;
-}
-
-/// Erosion from vertices to edges (\f$\epsilon^\times\f$).
-template <typename I>
-mln_concrete(I)
-erosion_v2e(const Image<I>& input_)
-{
- const I& input = exact(input_);
- mln_concrete(I) output;
- initialize(output, input);
- p_n_faces_fwd_piter<dim, geom_t> e(input.domain(), 1);
- mln_niter_(e2v_t) v(e2v, e);
- for_all(e)
- {
- output(e) = true;
- for_all(v)
- if (!input(v))
- {
- output(e) = false;
- break;
- }
- }
- return output;
-}
-
-/// Erosion from edges to vertices (\f$\epsilon^\bullet\f$).
-template <typename I>
-mln_concrete(I)
-erosion_e2v(const Image<I>& input_)
-{
- const I& input = exact(input_);
- mln_concrete(I) output;
- initialize(output, input);
- p_n_faces_fwd_piter<dim, geom_t> v(input.domain(), 0);
- mln_niter_(v2e_t) e(v2e, v);
- for_all(v)
- {
- output(v) = true;
- for_all(e)
- if (!input(e))
- {
- output(v) = false;
- break;
- }
- }
- return output;
-}
-
-/// Dilation from vertices to edges (\f$\delta^\times\f$).
-template <typename I>
-mln_concrete(I)
-dilation_v2e(const Image<I>& input_)
-{
- const I& input = exact(input_);
- mln_concrete(I) output;
- initialize(output, input);
- p_n_faces_fwd_piter<dim, geom_t> e(input.domain(), 1);
- mln_niter_(e2v_t) v(e2v, e);
- for_all(e)
- {
- output(e) = false;
- for_all(v)
- if (input(v))
- {
- output(e) = true;
- break;
- }
- }
- return output;
-}
-
-
-/// Vertex dilation (\f$delta\f$).
-template <typename I>
-mln_concrete(I)
-dilation_vertex(const Image<I>& input)
-{
- return dilation_e2v(dilation_v2e(input));
-}
-
-/// Vertex erosion (\f$epsilon\f$).
-template <typename I>
-mln_concrete(I)
-erosion_vertex(const Image<I>& input)
-{
- return erosion_e2v(erosion_v2e(input));
-}
-
-
-/// Edge dilation (\f$Delta\f$).
-template <typename I>
-mln_concrete(I)
-dilation_edge(const Image<I>& input)
-{
- return dilation_v2e(dilation_e2v(input));
-}
-
-/// Edge erosion (\f$Epsilon\f$).
-template <typename I>
-mln_concrete(I)
-erosion_edge(const Image<I>& input)
-{
- return erosion_v2e(erosion_e2v(input));
-}
-
-
-/// Combine the vertices and the edges of two images to create a new
-/// graph image.
-template <typename I>
-mln_concrete(I)
-combine(const Image<I>& vertices_, const Image<I>& edges_)
-{
- const I vertices = exact(vertices_);
- const I edges = exact(edges_);
- mln_precondition(vertices.domain() == edges.domain());
-
- mln_concrete(I) output;
- initialize(output, vertices);
- p_n_faces_fwd_piter<dim, geom_t> v(output.domain(), 0);
- for_all(v)
- output(v) = vertices(v);
- p_n_faces_fwd_piter<dim, geom_t> e(output.domain(), 1);
- for_all(e)
- output(e) = edges(e);
- return output;
-}
-
-
-/// Graph dilation (\f$delta \ovee Delta\f$).
-template <typename I>
-mln_concrete(I)
-dilation_graph(const Image<I>& input)
-{
- return combine(dilation_vertex(input), dilation_edge(input));
-}
-
-/// Graph erosion (\f$epsilon \ovee Epsilon\f$).
-template <typename I>
-mln_concrete(I)
-erosion_graph(const Image<I>& input)
-{
- return combine(erosion_vertex(input), erosion_edge(input));
-}
-
-
-// ------------------------ //
-// Additional adjunctions. //
-// ------------------------ //
-
-template <typename I>
-mln_concrete(I)
-alpha1(const Image<I>& input)
-{
- mln_concrete(I) vertices;
- initialize(vertices, input);
- data::fill(vertices, true);
- return combine(vertices, input);
-}
-
-template <typename I>
-mln_concrete(I)
-beta1(const Image<I>& input)
-{
- return combine(dilation_e2v(input), input);
-}
-
-template <typename I>
-mln_concrete(I)
-alpha2(const Image<I>& input)
-{
- return combine(input, erosion_v2e(input));
-}
-
-template <typename I>
-mln_concrete(I)
-beta2(const Image<I>& input)
-{
- mln_concrete(I) edges;
- initialize(edges, input);
- data::fill(edges, false);
- return combine(input, edges);
-}
-
-template <typename I>
-mln_concrete(I)
-alpha3(const Image<I>& input)
-{
- return combine(erosion_e2v(input), erosion_v2e(erosion_e2v(input)));
-}
-
-template <typename I>
-mln_concrete(I)
-beta3(const Image<I>& input)
-{
- return combine(dilation_e2v(dilation_v2e(input)), dilation_v2e(input));
-}
-
-
-// ----------------------- //
-// Openings and closings. //
-// ----------------------- //
-
-/// Vertex opening (\f$\gamma_1\f$).
-template <typename I>
-mln_concrete(I)
-opening_vertex(const Image<I>& input)
-{
- return dilation_vertex(erosion_vertex(input));
-}
-
-/// Vertex closing (\f$\phi_1\f$).
-template <typename I>
-mln_concrete(I)
-closing_vertex(const Image<I>& input)
-{
- return erosion_vertex(dilation_vertex(input));
-}
-
-
-/// Edge opening (\f$\Gamma_1\f$).
-template <typename I>
-mln_concrete(I)
-opening_edge(const Image<I>& input)
-{
- return dilation_edge(erosion_edge(input));
-}
-
-/// Edge closing (\f$\Phi_1\f$).
-template <typename I>
-mln_concrete(I)
-closing_edge(const Image<I>& input)
-{
- return erosion_edge(dilation_edge(input));
-}
-
-
-/// Graph opening (\f${\gamma \ovee \Gamma}_1\f$).
-template <typename I>
-mln_concrete(I)
-opening_graph(const Image<I>& input)
-{
- return combine(opening_vertex(input), opening_edge(input));
-}
-
-/// Graph closing (\f${\phi \ovee \Phi}_1\f$).
-template <typename I>
-mln_concrete(I)
-closing_graph(const Image<I>& input)
-{
- return combine(closing_vertex(input), closing_edge(input));
-}
-
-
-// --------------------------------- //
-// Half-openings and half-closings. //
-// --------------------------------- //
-
-/// Vertex half-opening (\f$\gamma_{1/2}\f$).
-template <typename I>
-mln_concrete(I)
-half_opening_vertex(const Image<I>& input)
-{
- return dilation_e2v(erosion_v2e(input));
-}
-
-/// Vertex half-closing (\f$\phi_{1/2}\f$).
-template <typename I>
-mln_concrete(I)
-half_closing_vertex(const Image<I>& input)
-{
- return erosion_e2v(dilation_v2e(input));
-}
-
-
-/// Edge half-opening (\f$\Gamma_{1/2}\f$).
-template <typename I>
-mln_concrete(I)
-half_opening_edge(const Image<I>& input)
-{
- return dilation_v2e(erosion_e2v(input));
-}
-
-/// Edge half-closing (\f$\Phi_{1/2}\f$).
-template <typename I>
-mln_concrete(I)
-half_closing_edge(const Image<I>& input)
-{
- return erosion_v2e(dilation_e2v(input));
-}
-
+#include "apps/graph-morpho/morpho.hh"
-/// Graph half-opening (\f${\gamma \ovee \Gamma}_{1/2}\f$).
-template <typename I>
-mln_concrete(I)
-half_opening_graph(const Image<I>& input)
-{
- return combine(half_opening_vertex(input), half_opening_edge(input));
-}
-
-/// Graph half-closing (\f${\phi \ovee \Phi}_{1/2}\f$).
-template <typename I>
-mln_concrete(I)
-half_closing_graph(const Image<I>& input)
-{
- return combine(half_closing_vertex(input), half_closing_edge(input));
-}
-
-
-// ------------------------------------------------------ //
-// Parameterized openings and closings (granulometries). //
-// ------------------------------------------------------ //
-
-/// Opening (\f${\gamma \ovee \Gamma}_{\lambda/2}\f$).
-template <typename I>
-mln_concrete(I)
-opening(const Image<I>& input, unsigned lambda)
-{
- unsigned i = lambda / 2;
- unsigned j = lambda % 2;
- mln_concrete(I) output = duplicate(input);
- for (unsigned m = 0; m < i; ++m)
- output = erosion_graph(output);
- for (unsigned m = 0; m < j; ++m)
- output = half_opening_graph(output);
- for (unsigned m = 0; m < i; ++m)
- output = dilation_graph(output);
- return output;
-}
-
-/// Opening (\f${\phi \ovee \Phi}_{\lambda/2}\f$).
-template <typename I>
-mln_concrete(I)
-closing(const Image<I>& input, unsigned lambda)
-{
- unsigned i = lambda / 2;
- unsigned j = lambda % 2;
- mln_concrete(I) output = duplicate(input);
- for (unsigned m = 0; m < i; ++m)
- output = dilation_graph(output);
- for (unsigned m = 0; m < j; ++m)
- output = half_closing_graph(output);
- for (unsigned m = 0; m < i; ++m)
- output = erosion_graph(output);
- return output;
-}
+#include "apps/graph-morpho/io.hh"
+#include "apps/data.hh"
-// ----------------------------- //
-// Alternate Sequential Filter. //
-// ----------------------------- //
-/// Alternate Sequential Filter (ASF) (\f${ASF}_{\lambda/2}\f$).
-template <typename I>
-mln_concrete(I)
-asf(const Image<I>& input, unsigned lambda)
+int main()
{
- mln_concrete(I) output = duplicate(input);
- for (unsigned m = 0; m < lambda; ++m)
- output = half_opening_graph(half_closing_graph(output));
- return output;
-}
-
-
+ using namespace mln;
-/*-----------------------------------.
-| Applying morphological operators. |
-`-----------------------------------*/
+ // A graph is considered as a 1-complex here.
+ const unsigned dim = 1;
+ typedef topo::complex<dim> complex_t;
+ /* Binary graph-based image with vertices aligned on a discrete 2D grid.
-int main()
-{
- /* Build a ``regular'' graph image. Of course, it would have been
- better, simpler and faster to use a cubical 1-complex here, but
- they are not yet available (as of 2009-09-10). */
+ Of course, it would have been better, simpler and faster to use a
+ cubical 1-complex here, but they are not yet available (as of
+ 2009-09-10). */
+ typedef mln::bin_1complex_image2d ima_t;
// ------------------------ //
// Dilations and erosions. //
diff --git a/milena/apps/graph-morpho/io.hh b/milena/apps/graph-morpho/io.hh
new file mode 100644
index 0000000..5b7a809
--- /dev/null
+++ b/milena/apps/graph-morpho/io.hh
@@ -0,0 +1,235 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (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 APPS_GRAPH_MORPHO_IO_HH
+# define APPS_GRAPH_MORPHO_IO_HH
+
+/// \file apps/graph-morpho/io.hh
+/// \brief I/O routines for graphs (1-complexes).
+
+# include <mln/core/alias/complex_image.hh>
+# include <mln/core/image/image2d.hh>
+
+# include <mln/math/abs.hh>
+
+// FIXME: We should turn these routines into something much more
+// generic, and move it to the library (into make/).
+
+inline
+mln::bin_1complex_image2d
+build_regular_complex1d_image(const mln::box2d& support)
+{
+ using namespace mln;
+
+ unsigned nrows = support.pmax().row() - support.pmin().row() + 1;
+ unsigned ncols = support.pmax().col() - support.pmin().col() + 1;
+
+ const unsigned dim = 1;
+ typedef topo::n_face<0, dim> vertex_t;
+
+ typedef topo::complex<dim> complex_t;
+ complex_t c;
+ typedef geom::complex_geometry<dim, point2d> geom_t;
+ geom_t geom;
+
+ // Vertices.
+ for (unsigned row = 0; row < nrows; ++row)
+ for (unsigned col = 0; col < ncols; ++col)
+ {
+ c.add_face();
+ geom.add_location(point2d(row,col));
+ }
+
+ // Edges.
+ for (unsigned row = 0; row < nrows; ++row)
+ {
+ // Horizontal edges.
+ for (unsigned col = 1; col < ncols; ++col)
+ {
+ // First vertex.
+ vertex_t v1(c, row * ncols + col - 1);
+ // Second vertex.
+ vertex_t v2(c, row * ncols + col);
+ // Edge bewteen V1 and V2.
+ c.add_face(v1 + v2);
+ }
+
+ // Vertical edges.
+ if (row != 0)
+ for (unsigned col = 0; col < ncols; ++col)
+ {
+ // First vertex.
+ vertex_t v1(c, (row - 1) * ncols + col);
+ // Second vertex.
+ vertex_t v2(c, row * ncols + col);
+ // Edge bewteen V1 and V2.
+ c.add_face(v1 + v2);
+ }
+ }
+
+ // Site set (domain) of the image.
+ p_complex<dim, geom_t> pc(c, geom);
+
+ // Image based on this site set.
+ bin_1complex_image2d ima(pc);
+ return ima;
+}
+
+
+template <typename I>
+inline
+mln::bin_1complex_image2d
+make_regular_complex1d_image(const mln::Image<I>& input_)
+{
+ using namespace mln;
+
+ const I& input = exact(input_);
+ const box2d& input_box = input.domain();
+ // The input image must have an odd number of rows and columns.
+ mln_precondition(input_box.nrows() % 2 == 1);
+ mln_precondition(input_box.ncols() % 2 == 1);
+
+ // The domain of the graph image is twice as small, since we
+ // consider only vertices (edges are set ``between'' vertices).
+ box2d output_box(input_box.nrows() / 2 + 1,
+ input_box.ncols() / 2 + 1);
+ bin_1complex_image2d output = build_regular_complex1d_image(output_box);
+
+ const unsigned dim = 1;
+ typedef geom::complex_geometry<dim, point2d> geom_t;
+
+ // Add values on vertices.
+ p_n_faces_fwd_piter<dim, geom_t> v(output.domain(), 0);
+ for_all(v)
+ {
+ mln_site_(geom_t) s(v);
+ // Site S is point2d multi-site and should be a singleton (since V
+ // iterates on vertices).
+ mln_invariant(s.size() == 1);
+ point2d p = s.front();
+ point2d q(p.row() * 2, p.col() * 2);
+ output(v) = input(q);
+ }
+
+ // Add values on edges.
+ p_n_faces_fwd_piter<dim, geom_t> e(output.domain(), 1);
+ for_all(e)
+ {
+ mln_site_(geom_t) s(e);
+ // Site S is point2d multi-site and should be a pair (since E
+ // iterates on vertices).
+ mln_invariant(s.size() == 2);
+ point2d p1 = s[0];
+ point2d p2 = s[1];
+ mln_invariant(math::abs(p1.row() - p2.row()) == 1
+ || math::abs(p1.col() - p2.col()) == 1);
+ point2d q (p1.row() + p2.row(), p1.col() + p2.col());
+ output(e) = input(q);
+ }
+
+ return output;
+}
+
+
+inline
+void
+println(const mln::bin_1complex_image2d& ima, const mln::box2d& support)
+{
+ using namespace mln;
+
+ // These are admittedly loose preconditions, but we cannot check
+ // much anyway.
+ mln_precondition(ima.nsites() == support.nsites());
+
+ image2d<bool> vertices(support);
+ image2d<bool> h_edges(box2d(support.pmin(), support.pmax() - dpoint2d(0, 1)));
+ image2d<bool> v_edges(box2d(support.pmin(), support.pmax() - dpoint2d(1, 0)));
+
+ const unsigned dim = 1;
+ typedef geom::complex_geometry<dim, point2d> geom_t;
+
+ // Iterator on vertices.
+ p_n_faces_fwd_piter<dim, geom_t> v(ima.domain(), 0);
+ for_all(v)
+ {
+ mln_site_(geom_t) s(v);
+ // Site S is point2d multi-site and should be a singleton (since V
+ // iterates on vertices).
+ mln_invariant(s.size() == 1);
+ point2d p = s.front();
+ vertices(p) = ima(v);
+ }
+
+ // Iterator on edges.
+ p_n_faces_fwd_piter<dim, geom_t> e(ima.domain(), 1);
+ for_all(e)
+ {
+ mln_site_(geom_t) s(e);
+ // Site S is point2d multi-site and should be a pair (since E
+ // iterates on vertices).
+ mln_invariant(s.size() == 2);
+ point2d p1 = s[0];
+ point2d p2 = s[1];
+ if (p1.row() == p2.row())
+ {
+ // Horizontal edge.
+ h_edges(p1) = ima(e);
+ }
+ else
+ {
+ // Vertical edge.
+ mln_assertion(p1.col() == p2.col());
+ v_edges(p1) = ima(e);
+ }
+ }
+
+ for (int row = vertices.domain().pmin().row();
+ row <= vertices.domain().pmax().row(); ++row)
+ {
+ for (int col = vertices.domain().pmin().col();
+ col <= vertices.domain().pmax().col(); ++col)
+ {
+ point2d p(row, col);
+ // Vertex.
+ std::cout << (vertices(p) ? "O" : ".");
+ // Potential horizontal edge on the right of the vertex.
+ if (col != vertices.domain().pmax().col())
+ std::cout << (h_edges(p) ? " - " : " ");
+ }
+ std::cout << std::endl;
+
+ // Potential vertical edge below the vertices of the current ROW.
+ if (row != vertices.domain().pmax().row())
+ for (int col = vertices.domain().pmin().col();
+ col <= vertices.domain().pmax().col(); ++col)
+ {
+ point2d p(row, col);
+ std::cout << (v_edges(p) ? "| " : " ");
+ }
+ std::cout << std::endl;
+ }
+}
+
+#endif // ! APPS_GRAPH_MORPHO_IO_HH
diff --git a/milena/apps/graph-morpho/morpho.hh b/milena/apps/graph-morpho/morpho.hh
new file mode 100644
index 0000000..bc9a361
--- /dev/null
+++ b/milena/apps/graph-morpho/morpho.hh
@@ -0,0 +1,503 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (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 APPS_GRAPH_MORPHO_MORPHO_HH
+# define APPS_GRAPH_MORPHO_MORPHO_HH
+
+/** \file apps/graph-morpho/morpho.hh
+ \brief Morphological operators on graphs (1-complexes).
+
+ Reference:
+
+ Jean Cousty, Laurent Najman and Jean Serra. Some morphological
+ operators in graph spaces. In: Proceedings of the Ninth
+ International Symposium on Mathematical Morphology (ISMM), 2009,
+ Groningen, The Netherlands. */
+
+# include <mln/core/concept/image.hh>
+
+# include <mln/core/routine/duplicate.hh>
+
+# include <mln/core/site_set/p_n_faces_piter.hh>
+# include <mln/core/image/complex_neighborhoods.hh>
+# include <mln/core/image/complex_neighborhood_piter.hh>
+
+
+/*--------------------------.
+| Vertex-edges combinator. |
+`--------------------------*/
+
+/// Combine the vertices and the edges of two images to create a new
+/// graph image (operator \f$\ovee\f$).
+template <typename I>
+inline
+mln_concrete(I)
+combine(const mln::Image<I>& vertices_, const mln::Image<I>& edges_)
+{
+ const I vertices = mln::exact(vertices_);
+ const I edges = mln::exact(edges_);
+ mln_precondition(vertices.domain() == edges.domain());
+
+ mln_concrete(I) output;
+ mln::initialize(output, vertices);
+ mln::p_n_faces_fwd_piter<I::dim, mln_geom(I)> v(output.domain(), 0);
+ for_all(v)
+ output(v) = vertices(v);
+ mln::p_n_faces_fwd_piter<I::dim, mln_geom(I)> e(output.domain(), 1);
+ for_all(e)
+ output(e) = edges(e);
+ return output;
+}
+
+
+/*-------------------------.
+| Dilations and erosions. |
+`-------------------------*/
+
+/* FIXME: By constraining the domain of the input and passing the
+ neighborhood, one should be able to use a truly generic dilation
+ (resp. erosion), or even use Milena's standard morpho::dilation
+ (resp. morpho::erosion).
+
+ It'd be convenient to write something like this:
+
+ dilation(ima | vertices);
+
+ We can /actually/ write this, but `vertices' has to be a predicate
+ on sites (p2b function), which is not efficient, since both
+ vertices and edges will be browsed.
+
+ It would be very nice if `vertices' could be an actual site set,
+ so that `ima | vertices' creates a morpher smart enough to
+ browse /only/ vertices. */
+
+/// Dilation from edges to vertices (\f$\delta^\bullet\f$).
+template <typename I>
+inline
+mln_concrete(I)
+dilation_e2v(const mln::Image<I>& input_)
+{
+ const I& input = mln::exact(input_);
+ mln_concrete(I) output;
+ mln::initialize(output, input);
+ // Iterator on vertices.
+ mln::p_n_faces_fwd_piter<I::dim, mln_geom(I)> v(input.domain(), 0);
+ // Vertex-to-edges neighborhood.
+ typedef mln::complex_higher_neighborhood<I::dim, mln_geom(I)> v2e_t;
+ const v2e_t v2e;
+ mln_niter(v2e_t) e(v2e, v);
+ for_all(v)
+ {
+ output(v) = false;
+ for_all(e)
+ if (input(e))
+ {
+ output(v) = true;
+ break;
+ }
+ }
+ return output;
+}
+
+/// Erosion from vertices to edges (\f$\epsilon^\times\f$).
+template <typename I>
+inline
+mln_concrete(I)
+erosion_v2e(const mln::Image<I>& input_)
+{
+ const I& input = mln::exact(input_);
+ mln_concrete(I) output;
+ mln::initialize(output, input);
+ // Iterator on edges.
+ mln::p_n_faces_fwd_piter<I::dim, mln_geom(I)> e(input.domain(), 1);
+ // Edge-to-vertices neighborhood.
+ typedef mln::complex_lower_neighborhood<I::dim, mln_geom(I)> e2v_t;
+ const e2v_t e2v;
+ mln_niter(e2v_t) v(e2v, e);
+ for_all(e)
+ {
+ output(e) = true;
+ for_all(v)
+ if (!input(v))
+ {
+ output(e) = false;
+ break;
+ }
+ }
+ return output;
+}
+
+/// Erosion from edges to vertices (\f$\epsilon^\bullet\f$).
+template <typename I>
+inline
+mln_concrete(I)
+erosion_e2v(const mln::Image<I>& input_)
+{
+ const I& input = mln::exact(input_);
+ mln_concrete(I) output;
+ mln::initialize(output, input);
+ // Iterator on vertices.
+ mln::p_n_faces_fwd_piter<I::dim, mln_geom(I)> v(input.domain(), 0);
+ // Vertex-to-edges neighborhood.
+ typedef mln::complex_higher_neighborhood<I::dim, mln_geom(I)> v2e_t;
+ const v2e_t v2e;
+ mln_niter(v2e_t) e(v2e, v);
+ for_all(v)
+ {
+ output(v) = true;
+ for_all(e)
+ if (!input(e))
+ {
+ output(v) = false;
+ break;
+ }
+ }
+ return output;
+}
+
+/// Dilation from vertices to edges (\f$\delta^\times\f$).
+template <typename I>
+inline
+mln_concrete(I)
+dilation_v2e(const mln::Image<I>& input_)
+{
+ const I& input = mln::exact(input_);
+ mln_concrete(I) output;
+ mln::initialize(output, input);
+ // Iterator on edges.
+ mln::p_n_faces_fwd_piter<I::dim, mln_geom(I)> e(input.domain(), 1);
+ // Edge-to-vertices neighborhood.
+ typedef mln::complex_lower_neighborhood<I::dim, mln_geom(I)> e2v_t;
+ const e2v_t e2v;
+ mln_niter(e2v_t) v(e2v, e);
+ for_all(e)
+ {
+ output(e) = false;
+ for_all(v)
+ if (input(v))
+ {
+ output(e) = true;
+ break;
+ }
+ }
+ return output;
+}
+
+
+/// Vertex dilation (\f$delta\f$).
+template <typename I>
+inline
+mln_concrete(I)
+dilation_vertex(const mln::Image<I>& input)
+{
+ return dilation_e2v(dilation_v2e(input));
+}
+
+/// Vertex erosion (\f$epsilon\f$).
+template <typename I>
+inline
+mln_concrete(I)
+erosion_vertex(const mln::Image<I>& input)
+{
+ return erosion_e2v(erosion_v2e(input));
+}
+
+
+/// Edge dilation (\f$Delta\f$).
+template <typename I>
+inline
+mln_concrete(I)
+dilation_edge(const mln::Image<I>& input)
+{
+ return dilation_v2e(dilation_e2v(input));
+}
+
+/// Edge erosion (\f$Epsilon\f$).
+template <typename I>
+inline
+mln_concrete(I)
+erosion_edge(const mln::Image<I>& input)
+{
+ return erosion_v2e(erosion_e2v(input));
+}
+
+
+/// Graph dilation (\f$delta \ovee Delta\f$).
+template <typename I>
+inline
+mln_concrete(I)
+dilation_graph(const mln::Image<I>& input)
+{
+ return combine(dilation_vertex(input), dilation_edge(input));
+}
+
+/// Graph erosion (\f$epsilon \ovee Epsilon\f$).
+template <typename I>
+inline
+mln_concrete(I)
+erosion_graph(const mln::Image<I>& input)
+{
+ return combine(erosion_vertex(input), erosion_edge(input));
+}
+
+
+/*-------------------------.
+| Additional adjunctions. |
+`-------------------------*/
+
+template <typename I>
+inline
+mln_concrete(I)
+alpha1(const mln::Image<I>& input)
+{
+ mln_concrete(I) vertices;
+ mln::initialize(vertices, input);
+ mln::data::fill(vertices, true);
+ return combine(vertices, input);
+}
+
+template <typename I>
+inline
+mln_concrete(I)
+beta1(const mln::Image<I>& input)
+{
+ return combine(dilation_e2v(input), input);
+}
+
+template <typename I>
+inline
+mln_concrete(I)
+alpha2(const mln::Image<I>& input)
+{
+ return combine(input, erosion_v2e(input));
+}
+
+template <typename I>
+inline
+mln_concrete(I)
+beta2(const mln::Image<I>& input)
+{
+ mln_concrete(I) edges;
+ mln::initialize(edges, input);
+ mln::data::fill(edges, false);
+ return combine(input, edges);
+}
+
+template <typename I>
+inline
+mln_concrete(I)
+alpha3(const mln::Image<I>& input)
+{
+ return combine(erosion_e2v(input), erosion_v2e(erosion_e2v(input)));
+}
+
+template <typename I>
+inline
+mln_concrete(I)
+beta3(const mln::Image<I>& input)
+{
+ return combine(dilation_e2v(dilation_v2e(input)), dilation_v2e(input));
+}
+
+
+/*------------------------.
+| Openings and closings. |
+`------------------------*/
+
+/// Vertex opening (\f$\gamma_1\f$).
+template <typename I>
+inline
+mln_concrete(I)
+opening_vertex(const mln::Image<I>& input)
+{
+ return dilation_vertex(erosion_vertex(input));
+}
+
+/// Vertex closing (\f$\phi_1\f$).
+template <typename I>
+inline
+mln_concrete(I)
+closing_vertex(const mln::Image<I>& input)
+{
+ return erosion_vertex(dilation_vertex(input));
+}
+
+
+/// Edge opening (\f$\Gamma_1\f$).
+template <typename I>
+inline
+mln_concrete(I)
+opening_edge(const mln::Image<I>& input)
+{
+ return dilation_edge(erosion_edge(input));
+}
+
+/// Edge closing (\f$\Phi_1\f$).
+template <typename I>
+inline
+mln_concrete(I)
+closing_edge(const mln::Image<I>& input)
+{
+ return erosion_edge(dilation_edge(input));
+}
+
+
+/// Graph opening (\f${\gamma \ovee \Gamma}_1\f$).
+template <typename I>
+inline
+mln_concrete(I)
+opening_graph(const mln::Image<I>& input)
+{
+ return combine(opening_vertex(input), opening_edge(input));
+}
+
+/// Graph closing (\f${\phi \ovee \Phi}_1\f$).
+template <typename I>
+inline
+mln_concrete(I)
+closing_graph(const mln::Image<I>& input)
+{
+ return combine(closing_vertex(input), closing_edge(input));
+}
+
+
+/*----------------------------------.
+| Half-openings and half-closings. |
+`----------------------------------*/
+
+/// Vertex half-opening (\f$\gamma_{1/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+half_opening_vertex(const mln::Image<I>& input)
+{
+ return dilation_e2v(erosion_v2e(input));
+}
+
+/// Vertex half-closing (\f$\phi_{1/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+half_closing_vertex(const mln::Image<I>& input)
+{
+ return erosion_e2v(dilation_v2e(input));
+}
+
+
+/// Edge half-opening (\f$\Gamma_{1/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+half_opening_edge(const mln::Image<I>& input)
+{
+ return dilation_v2e(erosion_e2v(input));
+}
+
+/// Edge half-closing (\f$\Phi_{1/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+half_closing_edge(const mln::Image<I>& input)
+{
+ return erosion_v2e(dilation_e2v(input));
+}
+
+
+/// Graph half-opening (\f${\gamma \ovee \Gamma}_{1/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+half_opening_graph(const mln::Image<I>& input)
+{
+ return combine(half_opening_vertex(input), half_opening_edge(input));
+}
+
+/// Graph half-closing (\f${\phi \ovee \Phi}_{1/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+half_closing_graph(const mln::Image<I>& input)
+{
+ return combine(half_closing_vertex(input), half_closing_edge(input));
+}
+
+
+/*-------------------------------------------------------.
+| Parameterized openings and closings (granulometries). |
+`-------------------------------------------------------*/
+
+/// Opening (\f${\gamma \ovee \Gamma}_{\lambda/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+opening(const mln::Image<I>& input, unsigned lambda)
+{
+ unsigned i = lambda / 2;
+ unsigned j = lambda % 2;
+ mln_concrete(I) output = mln::duplicate(input);
+ for (unsigned m = 0; m < i; ++m)
+ output = erosion_graph(output);
+ for (unsigned m = 0; m < j; ++m)
+ output = half_opening_graph(output);
+ for (unsigned m = 0; m < i; ++m)
+ output = dilation_graph(output);
+ return output;
+}
+
+/// Opening (\f${\phi \ovee \Phi}_{\lambda/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+closing(const mln::Image<I>& input, unsigned lambda)
+{
+ unsigned i = lambda / 2;
+ unsigned j = lambda % 2;
+ mln_concrete(I) output = mln::duplicate(input);
+ for (unsigned m = 0; m < i; ++m)
+ output = dilation_graph(output);
+ for (unsigned m = 0; m < j; ++m)
+ output = half_closing_graph(output);
+ for (unsigned m = 0; m < i; ++m)
+ output = erosion_graph(output);
+ return output;
+}
+
+/*-------------------------------.
+| Alternate Sequential Filters. |
+`-------------------------------*/
+
+/// Alternate Sequential Filter (ASF) (\f${ASF}_{\lambda/2}\f$).
+template <typename I>
+inline
+mln_concrete(I)
+asf(const mln::Image<I>& input, unsigned lambda)
+{
+ mln_concrete(I) output = mln::duplicate(input);
+ for (unsigned m = 0; m < lambda; ++m)
+ output = half_opening_graph(half_closing_graph(output));
+ return output;
+}
+
+#endif // ! APPS_GRAPH_MORPHO_MORPHO_HH
--
1.6.4.2
1
0
[PATCH 4/6] Alias for binary 1-complex-based images in the dicrete plane.
by Roland Levillain 10 Sep '09
by Roland Levillain 10 Sep '09
10 Sep '09
* mln/core/alias/complex_image.hh (mln::bin_1complex_image2d):
New typedef.
---
milena/ChangeLog | 7 +++++++
milena/mln/core/alias/complex_image.hh | 7 +++++++
2 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 0451a79..65dfce9 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,12 @@
2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+ Alias for binary 1-complex-based images in the dicrete plane.
+
+ * mln/core/alias/complex_image.hh (mln::bin_1complex_image2d):
+ New typedef.
+
+2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+
Implement the remaining morphological operators on graphs.
* apps/graph-morpho/complex1d.cc
diff --git a/milena/mln/core/alias/complex_image.hh b/milena/mln/core/alias/complex_image.hh
index 57b67ae..89a8241 100644
--- a/milena/mln/core/alias/complex_image.hh
+++ b/milena/mln/core/alias/complex_image.hh
@@ -45,6 +45,13 @@ namespace mln
| 2-d plane 1-complex aliases. |
`------------------------------*/
+ /// \brief Type alias for a binary image based on a
+ /// 1-complex, where 0-faces are located at discrete (integer)
+ /// 2-dimensional points.
+ typedef
+ mln::complex_image<1, mln::discrete_plane_1complex_geometry, bool>
+ bin_1complex_image2d;
+
/// \brief Type alias for an 8-bit gray-level image based on a
/// 1-complex, where 0-faces are located at discrete (integer)
/// 2-dimensional points.
--
1.6.4.2
1
0
[PATCH 3/6] Implement the remaining morphological operators on graphs.
by Roland Levillain 10 Sep '09
by Roland Levillain 10 Sep '09
10 Sep '09
* apps/graph-morpho/complex1d.cc
(alpha1, beta1, alpha2, beta2, alpha3, beta3)
(opening_vertex, closing_vertex)
(opening_edge, closing_edge)
(opening_graph, closing_graph)
(half_opening_vertex, half_closing_vertex)
(half_opening_edge, half_closing_edge)
(half_opening_graph, half_closing_graph)
(opening, closing, asf):
New functions.
Exercise some of them...
(main): ...here.
* apps/graph-morpho/y.pbm,
* apps/graph-morpho/z.pbm:
New images.
* apps/graph-morpho/Makefile.am (EXTRA_DIST): Add y.pbm and z.pbm.
---
milena/ChangeLog | 21 +++
milena/apps/graph-morpho/Makefile.am | 2 +-
milena/apps/graph-morpho/complex1d.cc | 286 +++++++++++++++++++++++++++++++++
milena/apps/graph-morpho/y.pbm | 22 +++
milena/apps/graph-morpho/z.pbm | 22 +++
5 files changed, 352 insertions(+), 1 deletions(-)
create mode 100644 milena/apps/graph-morpho/y.pbm
create mode 100644 milena/apps/graph-morpho/z.pbm
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 3f74480..0451a79 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,26 @@
2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+ Implement the remaining morphological operators on graphs.
+
+ * apps/graph-morpho/complex1d.cc
+ (alpha1, beta1, alpha2, beta2, alpha3, beta3)
+ (opening_vertex, closing_vertex)
+ (opening_edge, closing_edge)
+ (opening_graph, closing_graph)
+ (half_opening_vertex, half_closing_vertex)
+ (half_opening_edge, half_closing_edge)
+ (half_opening_graph, half_closing_graph)
+ (opening, closing, asf):
+ New functions.
+ Exercise some of them...
+ (main): ...here.
+ * apps/graph-morpho/y.pbm,
+ * apps/graph-morpho/z.pbm:
+ New images.
+ * apps/graph-morpho/Makefile.am (EXTRA_DIST): Add y.pbm and z.pbm.
+
+2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+
Simplify graph-based image I/O in apps/graph-morpho.
* apps/graph-morpho/complex1d.cc (make_regular_complex1d_image):
diff --git a/milena/apps/graph-morpho/Makefile.am b/milena/apps/graph-morpho/Makefile.am
index 0d7f9e7..faa0fd4 100644
--- a/milena/apps/graph-morpho/Makefile.am
+++ b/milena/apps/graph-morpho/Makefile.am
@@ -25,4 +25,4 @@ complex1d_SOURCES = complex1d.cc
TESTS = complex1d
-EXTRA_DIST = x.pbm
+EXTRA_DIST = x.pbm y.pbm z.pbm
diff --git a/milena/apps/graph-morpho/complex1d.cc b/milena/apps/graph-morpho/complex1d.cc
index 6e98310..e220fca 100644
--- a/milena/apps/graph-morpho/complex1d.cc
+++ b/milena/apps/graph-morpho/complex1d.cc
@@ -42,6 +42,8 @@
#include <mln/core/site_set/p_set.hh>
#include <mln/util/site_pair.hh>
+#include <mln/core/routine/duplicate.hh>
+
#include <mln/math/abs.hh>
#include <mln/io/pbm/load.hh>
@@ -248,10 +250,15 @@ println(const complex_image<dim, geom_t, T>& ima, const box2d& support)
}
}
+
/*------------------------------------.
| Morphological operators on graphs. |
`------------------------------------*/
+// ------------------------ //
+// Dilations and erosions. //
+// ------------------------ //
+
/* FIXME: By constraining the domain of the input and passing the
neighborhood, one should be able to use a truly generic dilation
(resp. erosion), or even use Milena's standard morpho::dilation
@@ -265,6 +272,17 @@ dilation_e2v(const Image<I>& input_)
const I& input = exact(input_);
mln_concrete(I) output;
initialize(output, input);
+ /* FIXME: It'd be better to write something like this:
+
+ mln_piter(...) v(output | vertices);
+
+ We can actually write this, but `vertices' has to be a predicate
+ on sites (p2b function), which is not efficient, since both
+ vertices and edges will be browsed.
+
+ It would be very nice if `vertices' could be an actual site set,
+ so that `output | vertices' creates a morpher smart enough to
+ browse /only/ vertices. */
p_n_faces_fwd_piter<dim, geom_t> v(input.domain(), 0);
mln_niter_(v2e_t) e(v2e, v);
for_all(v)
@@ -423,6 +441,224 @@ erosion_graph(const Image<I>& input)
}
+// ------------------------ //
+// Additional adjunctions. //
+// ------------------------ //
+
+template <typename I>
+mln_concrete(I)
+alpha1(const Image<I>& input)
+{
+ mln_concrete(I) vertices;
+ initialize(vertices, input);
+ data::fill(vertices, true);
+ return combine(vertices, input);
+}
+
+template <typename I>
+mln_concrete(I)
+beta1(const Image<I>& input)
+{
+ return combine(dilation_e2v(input), input);
+}
+
+template <typename I>
+mln_concrete(I)
+alpha2(const Image<I>& input)
+{
+ return combine(input, erosion_v2e(input));
+}
+
+template <typename I>
+mln_concrete(I)
+beta2(const Image<I>& input)
+{
+ mln_concrete(I) edges;
+ initialize(edges, input);
+ data::fill(edges, false);
+ return combine(input, edges);
+}
+
+template <typename I>
+mln_concrete(I)
+alpha3(const Image<I>& input)
+{
+ return combine(erosion_e2v(input), erosion_v2e(erosion_e2v(input)));
+}
+
+template <typename I>
+mln_concrete(I)
+beta3(const Image<I>& input)
+{
+ return combine(dilation_e2v(dilation_v2e(input)), dilation_v2e(input));
+}
+
+
+// ----------------------- //
+// Openings and closings. //
+// ----------------------- //
+
+/// Vertex opening (\f$\gamma_1\f$).
+template <typename I>
+mln_concrete(I)
+opening_vertex(const Image<I>& input)
+{
+ return dilation_vertex(erosion_vertex(input));
+}
+
+/// Vertex closing (\f$\phi_1\f$).
+template <typename I>
+mln_concrete(I)
+closing_vertex(const Image<I>& input)
+{
+ return erosion_vertex(dilation_vertex(input));
+}
+
+
+/// Edge opening (\f$\Gamma_1\f$).
+template <typename I>
+mln_concrete(I)
+opening_edge(const Image<I>& input)
+{
+ return dilation_edge(erosion_edge(input));
+}
+
+/// Edge closing (\f$\Phi_1\f$).
+template <typename I>
+mln_concrete(I)
+closing_edge(const Image<I>& input)
+{
+ return erosion_edge(dilation_edge(input));
+}
+
+
+/// Graph opening (\f${\gamma \ovee \Gamma}_1\f$).
+template <typename I>
+mln_concrete(I)
+opening_graph(const Image<I>& input)
+{
+ return combine(opening_vertex(input), opening_edge(input));
+}
+
+/// Graph closing (\f${\phi \ovee \Phi}_1\f$).
+template <typename I>
+mln_concrete(I)
+closing_graph(const Image<I>& input)
+{
+ return combine(closing_vertex(input), closing_edge(input));
+}
+
+
+// --------------------------------- //
+// Half-openings and half-closings. //
+// --------------------------------- //
+
+/// Vertex half-opening (\f$\gamma_{1/2}\f$).
+template <typename I>
+mln_concrete(I)
+half_opening_vertex(const Image<I>& input)
+{
+ return dilation_e2v(erosion_v2e(input));
+}
+
+/// Vertex half-closing (\f$\phi_{1/2}\f$).
+template <typename I>
+mln_concrete(I)
+half_closing_vertex(const Image<I>& input)
+{
+ return erosion_e2v(dilation_v2e(input));
+}
+
+
+/// Edge half-opening (\f$\Gamma_{1/2}\f$).
+template <typename I>
+mln_concrete(I)
+half_opening_edge(const Image<I>& input)
+{
+ return dilation_v2e(erosion_e2v(input));
+}
+
+/// Edge half-closing (\f$\Phi_{1/2}\f$).
+template <typename I>
+mln_concrete(I)
+half_closing_edge(const Image<I>& input)
+{
+ return erosion_v2e(dilation_e2v(input));
+}
+
+
+/// Graph half-opening (\f${\gamma \ovee \Gamma}_{1/2}\f$).
+template <typename I>
+mln_concrete(I)
+half_opening_graph(const Image<I>& input)
+{
+ return combine(half_opening_vertex(input), half_opening_edge(input));
+}
+
+/// Graph half-closing (\f${\phi \ovee \Phi}_{1/2}\f$).
+template <typename I>
+mln_concrete(I)
+half_closing_graph(const Image<I>& input)
+{
+ return combine(half_closing_vertex(input), half_closing_edge(input));
+}
+
+
+// ------------------------------------------------------ //
+// Parameterized openings and closings (granulometries). //
+// ------------------------------------------------------ //
+
+/// Opening (\f${\gamma \ovee \Gamma}_{\lambda/2}\f$).
+template <typename I>
+mln_concrete(I)
+opening(const Image<I>& input, unsigned lambda)
+{
+ unsigned i = lambda / 2;
+ unsigned j = lambda % 2;
+ mln_concrete(I) output = duplicate(input);
+ for (unsigned m = 0; m < i; ++m)
+ output = erosion_graph(output);
+ for (unsigned m = 0; m < j; ++m)
+ output = half_opening_graph(output);
+ for (unsigned m = 0; m < i; ++m)
+ output = dilation_graph(output);
+ return output;
+}
+
+/// Opening (\f${\phi \ovee \Phi}_{\lambda/2}\f$).
+template <typename I>
+mln_concrete(I)
+closing(const Image<I>& input, unsigned lambda)
+{
+ unsigned i = lambda / 2;
+ unsigned j = lambda % 2;
+ mln_concrete(I) output = duplicate(input);
+ for (unsigned m = 0; m < i; ++m)
+ output = dilation_graph(output);
+ for (unsigned m = 0; m < j; ++m)
+ output = half_closing_graph(output);
+ for (unsigned m = 0; m < i; ++m)
+ output = erosion_graph(output);
+ return output;
+}
+
+// ----------------------------- //
+// Alternate Sequential Filter. //
+// ----------------------------- //
+
+/// Alternate Sequential Filter (ASF) (\f${ASF}_{\lambda/2}\f$).
+template <typename I>
+mln_concrete(I)
+asf(const Image<I>& input, unsigned lambda)
+{
+ mln_concrete(I) output = duplicate(input);
+ for (unsigned m = 0; m < lambda; ++m)
+ output = half_opening_graph(half_closing_graph(output));
+ return output;
+}
+
+
+
/*-----------------------------------.
| Applying morphological operators. |
`-----------------------------------*/
@@ -470,4 +706,54 @@ int main()
ima_t ero_ima = erosion_graph(x);
std::cout << "ero_ima:" << std::endl;
println(ero_ima, x_box);
+
+
+ ima_t alpha3_ima = alpha3(x);
+ std::cout << "alpha3_ima:" << std::endl;
+ println(alpha3_ima, x_box);
+
+ ima_t beta3_ima = beta3(x);
+ std::cout << "beta3_ima:" << std::endl;
+ println(beta3_ima, x_box);
+
+ // --------- //
+ // Filters. //
+ // --------- //
+
+ image2d<bool> y_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/y.pbm");
+ ima_t y = make_regular_complex1d_image(y_pbm);
+ box2d y_box(y_pbm.nrows() / 2 + 1, y_pbm.ncols() / 2 + 1);
+ std::cout << "y:" << std::endl;
+ println(y, y_box);
+
+ ima_t ope_ima = opening_graph(y);
+ std::cout << "ope_ima:" << std::endl;
+ println(ope_ima, y_box);
+
+ ima_t half_ope_ima = half_opening_graph(y);
+ std::cout << "half_ope_ima:" << std::endl;
+ println(half_ope_ima, y_box);
+
+ ima_t beta3_o_alpha3_ima = beta3(alpha3(y));
+ std::cout << "beta3_o_alpha3_ima:" << std::endl;
+ println(beta3_o_alpha3_ima, y_box);
+
+
+ image2d<bool> z_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/z.pbm");
+ ima_t z = make_regular_complex1d_image(z_pbm);
+ box2d z_box(z_pbm.nrows() / 2 + 1, z_pbm.ncols() / 2 + 1);
+ std::cout << "z:" << std::endl;
+ println(z, z_box);
+
+ ima_t clo_ima = closing_graph(z);
+ std::cout << "clo_ima:" << std::endl;
+ println(clo_ima, z_box);
+
+ ima_t half_clo_ima = half_closing_graph(z);
+ std::cout << "half_clo_ima:" << std::endl;
+ println(half_clo_ima, z_box);
+
+ ima_t alpha3_o_beta3_ima = alpha3(beta3(z));
+ std::cout << "alpha3_o_beta3_ima:" << std::endl;
+ println(alpha3_o_beta3_ima, z_box);
}
diff --git a/milena/apps/graph-morpho/y.pbm b/milena/apps/graph-morpho/y.pbm
new file mode 100644
index 0000000..6e14dde
--- /dev/null
+++ b/milena/apps/graph-morpho/y.pbm
@@ -0,0 +1,22 @@
+P1
+# y.pbm
+15 19
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 0 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 0 1 1 1 1 1 1 1 1 1 1
+1 1 0 0 0 0 0 0 0 1 1 1 1 1 1
+1 1 1 1 0 1 1 1 0 1 1 1 1 1 1
+1 1 1 1 0 1 1 1 0 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 0 1 1 1 1 1 1
+1 1 1 1 0 1 1 1 0 0 0 1 1 1 1
+1 1 1 1 0 1 1 1 0 1 0 1 1 1 1
+1 1 1 1 0 1 0 0 0 0 0 0 0 1 1
+1 1 1 1 0 1 1 1 0 1 0 1 1 1 1
+1 1 0 0 0 1 1 1 0 1 0 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 0 1 0 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 0 1 1 1 1 1 0 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
diff --git a/milena/apps/graph-morpho/z.pbm b/milena/apps/graph-morpho/z.pbm
new file mode 100644
index 0000000..1eb2ee2
--- /dev/null
+++ b/milena/apps/graph-morpho/z.pbm
@@ -0,0 +1,22 @@
+P1
+# z.pbm
+15 19
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 0 0 0 0 0 1 1 1 1
+1 1 1 1 1 1 0 1 1 1 0 1 1 1 1
+1 1 1 1 1 1 0 1 1 1 0 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
+1 1 0 0 0 1 0 1 0 0 0 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 0 1 1 1 1
+1 1 1 1 1 1 0 1 1 1 0 1 1 1 1
+1 1 1 1 1 1 0 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 0 1 1 1 0 1 1 1 1
+1 1 1 1 1 1 0 1 1 1 0 1 1 1 1
+1 1 0 1 1 1 0 0 0 0 0 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 0 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
--
1.6.4.2
1
0
---
ChangeLog | 4 ++++
configure.ac | 4 ++++
2 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index e2991df..f7fa700 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+
+ * configure.ac: Configure milena/apps/data.hh.
+
2009-09-08 Roland Levillain <roland(a)lrde.epita.fr>
* configure.ac: Configure milena/apps/graph-morpho/Makefile.
diff --git a/configure.ac b/configure.ac
index c7a2487..efbbb27 100644
--- a/configure.ac
+++ b/configure.ac
@@ -390,6 +390,10 @@ dnl>>
## Applications. ##
## -------------- ##
+# Ask for the creation of a milena/apps/data.hh, used to access to
+# data (images) from apps.
+AC_CONFIG_FILES([milena/apps/data.hh])
+
AC_ARG_ENABLE([apps],
[AS_HELP_STRING([--enable-apps],
[enable application])])
--
1.6.4.2
1
0
10 Sep '09
* apps/graph-morpho/complex1d.cc (make_regular_complex1d_image):
New function.
Use it...
(main): ...here, to simplify the construction of the input image,
by reading it from...
* apps/graph-morpho/x.pbm: ...this (new) image.
* apps/data.hh.in: New.
* apps/graph-morpho/Makefile.am (AM_CPPFLAGS):
Add -I$(top_builddir)/milena.
(bin_PROGRAMS): Rename as...
(noinst_PROGRAMS): ...this.
(EXTRA_DIST): New.
Add x.pbm.
---
milena/ChangeLog | 18 ++++
milena/apps/data.hh.in | 41 ++++++++
milena/apps/graph-morpho/Makefile.am | 6 +-
milena/apps/graph-morpho/complex1d.cc | 162 ++++++++++++++++----------------
milena/apps/graph-morpho/x.pbm | 20 ++++
5 files changed, 164 insertions(+), 83 deletions(-)
create mode 100644 milena/apps/data.hh.in
create mode 100644 milena/apps/graph-morpho/x.pbm
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 700906c..3f74480 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,21 @@
+2009-09-10 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Simplify graph-based image I/O in apps/graph-morpho.
+
+ * apps/graph-morpho/complex1d.cc (make_regular_complex1d_image):
+ New function.
+ Use it...
+ (main): ...here, to simplify the construction of the input image,
+ by reading it from...
+ * apps/graph-morpho/x.pbm: ...this (new) image.
+ * apps/data.hh.in: New.
+ * apps/graph-morpho/Makefile.am (AM_CPPFLAGS):
+ Add -I$(top_builddir)/milena.
+ (bin_PROGRAMS): Rename as...
+ (noinst_PROGRAMS): ...this.
+ (EXTRA_DIST): New.
+ Add x.pbm.
+
2009-09-10 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Fix luminance value computation for RGB to HSL.
diff --git a/milena/apps/data.hh.in b/milena/apps/data.hh.in
new file mode 100644
index 0000000..8adb35f
--- /dev/null
+++ b/milena/apps/data.hh.in
@@ -0,0 +1,41 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (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 APPS_DATA_HH
+# define APPS_DATA_HH
+
+# include <string>
+
+/* Macros are evil, but they save us an extra compilation unit here
+ (as well as additional burden in Makefiles, too.). */
+
+/// The absolute path to the img directory of Milena.
+# define MLN_IMG_DIR "@abs_top_srcdir@/milena/img"
+
+/// The absolute path to the apps directory of Milena.
+# define MLN_APPS_DIR "@abs_top_srcdir@/milena/apps/"
+
+#endif // ! APPS_DATA_HH
diff --git a/milena/apps/graph-morpho/Makefile.am b/milena/apps/graph-morpho/Makefile.am
index 590e756..0d7f9e7 100644
--- a/milena/apps/graph-morpho/Makefile.am
+++ b/milena/apps/graph-morpho/Makefile.am
@@ -15,12 +15,14 @@
# along with Olena. If not, see <http://www.gnu.org/licenses/>.
# Find Milena headers.
-AM_CPPFLAGS = -I$(top_srcdir)/milena
+AM_CPPFLAGS = -I$(top_srcdir)/milena -I$(top_builddir)/milena
# Produce fast code.
APPS_CXXFLAGS = @APPS_CXXFLAGS@
AM_CXXFLAGS = $(APPS_CXXFLAGS)
-bin_PROGRAMS = complex1d
+noinst_PROGRAMS = complex1d
complex1d_SOURCES = complex1d.cc
TESTS = complex1d
+
+EXTRA_DIST = x.pbm
diff --git a/milena/apps/graph-morpho/complex1d.cc b/milena/apps/graph-morpho/complex1d.cc
index 93eab21..6e98310 100644
--- a/milena/apps/graph-morpho/complex1d.cc
+++ b/milena/apps/graph-morpho/complex1d.cc
@@ -42,6 +42,11 @@
#include <mln/core/site_set/p_set.hh>
#include <mln/util/site_pair.hh>
+#include <mln/math/abs.hh>
+
+#include <mln/io/pbm/load.hh>
+
+#include "apps/data.hh"
using namespace mln;
@@ -120,6 +125,54 @@ build_regular_complex1d_image(const box2d& support)
return ima;
}
+template <typename I>
+ima_t
+make_regular_complex1d_image(const Image<I>& input_)
+{
+ const I& input = exact(input_);
+ const box2d& input_box = input.domain();
+ // The input image must have an odd number of rows and columns.
+ mln_precondition(input_box.nrows() % 2 == 1);
+ mln_precondition(input_box.ncols() % 2 == 1);
+
+ // The domain of the graph image is twice as small, since we
+ // consider only vertices (edges are set ``between'' vertices).
+ box2d output_box(input_box.nrows() / 2 + 1,
+ input_box.ncols() / 2 + 1);
+ ima_t output = build_regular_complex1d_image(output_box);
+
+ // Add values on vertices.
+ p_n_faces_fwd_piter<dim, geom_t> v(output.domain(), 0);
+ for_all(v)
+ {
+ mln_site_(geom_t) s(v);
+ // Site S is point2d multi-site and should be a singleton (since V
+ // iterates on vertices).
+ mln_invariant(s.size() == 1);
+ point2d p = s.front();
+ point2d q(p.row() * 2, p.col() * 2);
+ output(v) = input(q);
+ }
+
+ // Add values on edges.
+ p_n_faces_fwd_piter<dim, geom_t> e(output.domain(), 1);
+ for_all(e)
+ {
+ mln_site_(geom_t) s(e);
+ // Site S is point2d multi-site and should be a pair (since E
+ // iterates on vertices).
+ mln_invariant(s.size() == 2);
+ point2d p1 = s[0];
+ point2d p2 = s[1];
+ mln_invariant(math::abs(p1.row() - p2.row()) == 1
+ || math::abs(p1.col() - p2.col()) == 1);
+ point2d q (p1.row() + p2.row(), p1.col() + p2.col());
+ output(e) = input(q);
+ }
+
+ return output;
+}
+
template <typename T>
void
@@ -370,104 +423,51 @@ erosion_graph(const Image<I>& input)
}
+/*-----------------------------------.
+| Applying morphological operators. |
+`-----------------------------------*/
int main()
{
- /*--------------.
- | Input image. |
- `--------------*/
-
/* Build a ``regular'' graph image. Of course, it would have been
better, simpler and faster to use a cubical 1-complex here, but
- they are not yet available. */
- box2d b(9, 6);
- ima_t ima = build_regular_complex1d_image(b);
-
- /* Set the values so that IMA corresponds to the graph X of the ISMM
- 2009 paper from Jean Cousty et al. */
-
- // The set of vertices of the graph.
- p_set<point2d> vertices;
- vertices.insert(point2d(1, 2));
- vertices.insert(point2d(2, 1));
- vertices.insert(point2d(2, 2));
- vertices.insert(point2d(3, 4));
- vertices.insert(point2d(5, 2));
- vertices.insert(point2d(5, 3));
- vertices.insert(point2d(5, 4));
- vertices.insert(point2d(6, 1));
- vertices.insert(point2d(6, 2));
- vertices.insert(point2d(6, 3));
- vertices.insert(point2d(6, 4));
- vertices.insert(point2d(7, 2));
- vertices.insert(point2d(7, 3));
- // Add vertices.
- p_n_faces_fwd_piter<dim, geom_t> v(ima.domain(), 0);
- for_all(v)
- {
- mln_site_(geom_t) s(v);
- // Site S is point2d multi-site and should be a singleton (since V
- // iterates on vertices).
- mln_invariant(s.size() == 1);
- point2d p = s.front();
- ima(v) = vertices.has(p);
- }
-
- // The set of edges of the graph.
- typedef util::site_pair<point2d> point2d_pair;
- p_set< util::site_pair<point2d> > edges;
- edges.insert(point2d_pair(point2d(2, 1), point2d(2, 2)));
- edges.insert(point2d_pair(point2d(5, 3), point2d(5, 4)));
- edges.insert(point2d_pair(point2d(5, 2), point2d(6, 2)));
- edges.insert(point2d_pair(point2d(5, 3), point2d(6, 3)));
- edges.insert(point2d_pair(point2d(6, 1), point2d(6, 2)));
- edges.insert(point2d_pair(point2d(6, 2), point2d(6, 3)));
- edges.insert(point2d_pair(point2d(6, 3), point2d(6, 4)));
- edges.insert(point2d_pair(point2d(6, 2), point2d(7, 2)));
- edges.insert(point2d_pair(point2d(6, 3), point2d(7, 3)));
- edges.insert(point2d_pair(point2d(7, 2), point2d(7, 3)));
- // Add edges.
- p_n_faces_fwd_piter<dim, geom_t> e(ima.domain(), 1);
- for_all(e)
- {
- mln_site_(geom_t) s(e);
- // Site S is point2d multi-site and should be a pair (since E
- // iterates on vertices).
- mln_invariant(s.size() == 2);
- point2d p1 = s[0];
- point2d p2 = s[1];
- ima(e) =
- edges.has(point2d_pair(p1, p2)) || edges.has(point2d_pair(p2, p1));
- }
- std::cout << "ima:" << std::endl;
- println(ima, b);
+ they are not yet available (as of 2009-09-10). */
- /*-----------------------------------.
- | Applying morphological operators. |
- `-----------------------------------*/
+ // ------------------------ //
+ // Dilations and erosions. //
+ // ------------------------ //
- ima_t dil_e2v_ima = dilation_e2v(ima);
+ /* Set the values so that X corresponds to the graph X of the ISMM
+ 2009 paper from Jean Cousty et al. */
+ image2d<bool> x_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/x.pbm");
+ ima_t x = make_regular_complex1d_image(x_pbm);
+ box2d x_box(x_pbm.nrows() / 2 + 1, x_pbm.ncols() / 2 + 1);
+ std::cout << "x:" << std::endl;
+ println(x, x_box);
+
+ ima_t dil_e2v_ima = dilation_e2v(x);
std::cout << "dil_e2v_ima:" << std::endl;
- println(dil_e2v_ima, b);
+ println(dil_e2v_ima, x_box);
- ima_t ero_v2e_ima = erosion_v2e(ima);
+ ima_t ero_v2e_ima = erosion_v2e(x);
std::cout << "ero_v2e_ima:" << std::endl;
- println(ero_v2e_ima, b);
+ println(ero_v2e_ima, x_box);
+
- ima_t ero_e2v_ima = erosion_e2v(ima);
+ ima_t ero_e2v_ima = erosion_e2v(x);
std::cout << "ero_e2v_ima:" << std::endl;
- println(ero_e2v_ima, b);
+ println(ero_e2v_ima, x_box);
- ima_t dil_v2e_ima = dilation_v2e(ima);
+ ima_t dil_v2e_ima = dilation_v2e(x);
std::cout << "dil_v2e_ima:" << std::endl;
- println(dil_v2e_ima, b);
+ println(dil_v2e_ima, x_box);
- ima_t dil_ima = dilation_graph(ima);
+ ima_t dil_ima = dilation_graph(x);
std::cout << "dil_ima:" << std::endl;
- println(dil_ima, b);
+ println(dil_ima, x_box);
- ima_t ero_ima = erosion_graph(ima);
+ ima_t ero_ima = erosion_graph(x);
std::cout << "ero_ima:" << std::endl;
- println(ero_ima, b);
+ println(ero_ima, x_box);
}
diff --git a/milena/apps/graph-morpho/x.pbm b/milena/apps/graph-morpho/x.pbm
new file mode 100644
index 0000000..5bbea77
--- /dev/null
+++ b/milena/apps/graph-morpho/x.pbm
@@ -0,0 +1,20 @@
+P1
+# x.pbm
+11 17
+1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 0 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1
+1 1 0 0 0 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 0 1 1
+1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 0 1 0 0 0 1 1
+1 1 1 1 0 1 0 1 1 1 1
+1 1 0 0 0 0 0 0 0 1 1
+1 1 1 1 0 1 0 1 1 1 1
+1 1 1 1 0 0 0 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1
--
1.6.4.2
1
0