**Name**

**ml_extract** Extract morpho_lines of image

**Command Synopsis**

**ml_extract** [-L *level*] [-l *levels*] [-o *ml_opt*] [-d *c_out*] [-m] *image_in* *mimage*

-Llevel: for the value `level' compute morpho_lines (float)

-llevels: for each value in `levels' compute morpho_lines (Fsignal)

-oml_opt: select the content of the morpho_lines (min-max value)

-dc_out: draw the output mimage using ll_draw

-m : optimize memory occupation during extraction

image_in: original image

mimage: mimage with morpho_lines of image_in

**Function Summary**

void ml_extract (level , levels , opt , c_out , m_flag , image_org , m_image )

float *level ;

Fsignal levels ;

int *opt ;

Cimage c_out ;

char *m_flag ;

Fimage image_org ;

Mimage m_image ;

**Description**

Let us denote the data of the `fsignal` *levels* (**-l** option) by
*v*_{0}, *v*_{1},..., *v*_{N}, e.g. *levels->size*= *N* + 1.

For the **-L** option we have *N* = 0.

Moreover we recall that a `morpho_line` is the boundary of the set

The module **ml_extract** computes
the `morpho_lines` of *image_in*
where the *minvalue* and *maxvalue* are defined
through the choice of option **-o**.

The different possibilities for *ml_opt* are:

- 0
- Here
*minvalue*=*v*_{i}and*maxvalue*=+ , this gives the boundary of level sets

such that*v*_{i}*g*(*i*,*j*). This is the default. - 1
- With this option
*minvalue*=- and*maxvalue*=*v*_{i}, which gives the boundary of level sets such that*g*(*i*,*j*)*v*_{i}. - 2
- This option allows to compute isolines, thus
*minvalue*=*maxvalue*=*v*_{i}. - 3
- Computes general
`morpho_lines`with*minvalue*=*v*_{i}and*maxvalue*=*v*_{i+1}. - 4
- Computes (more) general
`morpho_lines`with*minvalue*=*v*_{2i}and*maxvalue*=*v*_{2i+1}.

For

Finally, for

Exactly one option out of **-L** and **-l** has to be chosen.

For **-L** only *ml_opt* 0, 1 and 2 are available.

For *ml_opt*=3
one must have *levels->size* 2 , if *ml_opt*=4 ,
*levels->size* has to be even.

Option **-d** allows to obtain a b/w `cimage` *c_out*
of the `morpho_lines`. This option uses **ml_draw**.
*image_in* is of format `fimage` and *m_image* of format
`mimage`.

Notice that only *m_image->nrow* ,
*m_image->ncol* and *m_image->first_ml* are set by the
module **ml_extract**.

The **-m** flag allows to optimize memory occupation during
the decomposition. This is interesting if you use **ml_extract**
as UNIX command. Using this flag in an internal call
of the module **ml_extract()** and trying to delete
points separately in the sequel of your program will corrupt
the data structure.

The `morpho_line` list *m_image->first_ml* is ordered like
the data of *levels*, thus first all the `morpho_lines`
associated to *v*_{0} (and perhaps *v*_{1}) are listed, then those
associated to the next slice (see above how *i* is incremented,
following the value of *ml_opt*) until up to the
last values of *levels->values*.

Thus the order of the data in *levels* induces the order
of the slices (e.g. the `morpho_lines`) in *m_image*.
This is of importance if the `mimage` is to be reconstructed
(see **ml_decompose** and **ml_reconstruct**).

Notice that we consider only 4-neighbourhood adjacancies to determine
which pixels are inside the set.

For each `morpho_line` the **ml_extract** module will set
a *minvalue* and a *maxvalue*, an open curve flag,
a list of integer point coordinates and a list
of the corresponding point types.

Notice that in a `morpho_line` a point never appears twice,
thus for a closed line the first point and last point
in the list are different.

In a `morpho_line` the points are listed such that
the set is always left of the line.

Be aware that **ml_extract** might create a very (!) large
data structure, depending on *N* and *NC***NL*.

Let us now give more details about the point coordinates of a
`morpho_line`. The figureII below
can be taken as illustration.
We have represented a `morpho_set` *MS* with dashed squares
in an 5×6 image (a pixel=a square),
notice that in this example *MS* is connected
(but not *MS*^{c}).

The boundary between pixels is given by the list of their vertices,
drawn as black dots. The pixel coordinates being integer, (*i*, *j*), the
vertices will have float coordinates
(*i*±0.5, *j*±0.5),
but as `morpho_lines` are supposed to have integer coordinates
we will adopt the following: each vertex will be represented
by the integer coordinates obtained through a
(+ 0.5, + 0.5)
translation (see **ml_fml** and **fml_ml**).

Thus let (*k*, *l* ) be the coordinates of a `morpho_line` point,
then the vertex it represents has float coordinates
(*k* - 0.5, *l* - 0.5), where
*k* {0,..., *NC*} and
*l* {0,..., *NL*}.

In the example the pixel
(3, 2) *MS*, has a boundary
defined by the float vertices (2.5, 1.5), (3.5, 1.5),
(3.5, 2.5) and (2.5, 2.5). This `morpho_line`
will be saved as (3, 2), (4, 2), (4, 3) and (3, 3).
An open `morpho_line` starts/stops at points
having one coordinate either equal to 0, to *NC* or to *NL*.

These conventions are very important, they allow the
**ml_reconstruct** module to work correctly.

Notice that a morpho_line might be sometimes self-intersecting!

Indeed look at the following ``picture'' *g*:

0 | 0 | 0 |

0 | 1 | 0 |

1 | 0 | 0 |

If we look for the sets
{(*i*, *j*) / 1 *g*(*i*, *j*)}, we will
find two 4-connected sets (the two 1 pixels),
there remains one region which is actually 8-connected.
Now if we look for
{(*i*, *j*) / *g*(*i*, *j*) 0},
there is only one 4-connected set, having one boundary which
self-intersects !

Thus if your application needs true Jordan curves
you should shrink the morpho_lines around the morpho_set.

**See Also**

**Version 8.1**

Last Modification date : Thu Nov 29 20:23:56 2001

**Author**

Georges Koepfler