Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Olena
pylene
Commits
4bcc7c32
Commit
4bcc7c32
authored
Oct 15, 2021
by
Baptiste Esteban
Browse files
Avoiding copy when adding border + doc corrections
parent
f61d9c41
Pipeline
#30608
passed with stage
in 19 minutes and 35 seconds
Changes
3
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
doc/source/core/pad.rst
View file @
4bcc7c32
...
...
@@ -119,7 +119,7 @@ This file provides functions to pad a rectangular buffer or an image either:
:param input: The input ndimage (or ndimensional buffer).
:param output: The input ndimage (or ndimensional buffer).
:param mode: The padding policy
:param value: The value used to fill the array (used if mode is `PAD_CONSTANT`
:param value: The value used to fill the array (used if mode is `PAD_CONSTANT`
)
**Second version**
...
...
@@ -127,7 +127,7 @@ This file provides functions to pad a rectangular buffer or an image either:
:param out: The output ndimensional buffer.
:param roi: The roi of the output buffer
:param mode: The padding policy
:param value: The value used to fill the array (used if mode is `PAD_CONSTANT`
:param value: The value used to fill the array (used if mode is `PAD_CONSTANT`
)
...
...
@@ -143,7 +143,7 @@ This file provides functions to pad a rectangular buffer or an image either:
mln::image2d<uint8_t> input(iroi);
mln::image2d<uint8_t> out(oroi);
mln::copy_
and_
pad(input, out, mln::PAD_CONSTANT, 69);
mln::copy_pad(input, out, mln::PAD_CONSTANT, 69);
doc/source/morpho/multivariate_component_tree.rst
View file @
4bcc7c32
...
...
@@ -33,6 +33,7 @@ This example computes a grain filter, which removes all the node having an area
::
#include <mln/accu/accumulators/count.hpp>
#include <mln/core/extension/padding.hpp>
#include <mln/core/image/ndimage.hpp>
#include <mln/morpho/mtos.hpp>
#include <mln/io/imread.hpp>
...
...
@@ -40,11 +41,8 @@ This example computes a grain filter, which removes all the node having an area
// Function to reduce the nodemap to the original image domain
mln::image2d<int> reduce_nodemap(mln::image2d<int> n);
// Function to add a border
mln::image2d<mln::rgb8> add_border(mln::image2d<mln::rgb8> ima);
// Function to remove the border
mln::image2d<int> remove_border(mln::image2d<int> n);
// Function to get the median of the border values
mln::rgb8 get_median_on_border(mln::image2d<mln::rgb8> ima);
// Accumulator to compute the mean of the pixel values of each node, without taking into account the values of the holes
struct mean_node_accu : mln::Accumulator<mean_node_accu>
...
...
@@ -71,17 +69,21 @@ This example computes a grain filter, which removes all the node having an area
mln::image2d<mln::rgb8> ima;
mln::io::imread("lena.ppm", ima);
// Add a border
auto to_process = add_border(ima);
// Adding a border
const auto median = get_median_on_border(ima);
ima.inflate_domain(1);
constexpr int borders[2][2] = {{1, 1}, {1, 1}};
mln::pad(ima, mln::PAD_CONSTANT, borders, median);
// Compute the MToS
auto [t, nm] = mln::morpho::mtos(to_process, {
0, 0});
auto [t, nm] = mln::morpho::mtos(to_process, {
-1, -1}); // The rooting point is in the added border
// Reduce the nodemap
nm = reduce_nodemap(nm);
// Remove the border in the nodemap
nm = remove_border(nm);
// Remove the border
ima.inflate_domain(-1);
nm.inflate_domain(-1);
// Compute the area of each node of the tree
auto area = t.compute_attribute_on_points(nm, mln::accu::accumulators::count<int>());
...
...
doc/source/snippets/mtos_example.cpp
View file @
4bcc7c32
#include
<mln/accu/accumulators/count.hpp>
#include
<mln/accu/accumulators/max.hpp>
#include
<mln/core/algorithm/accumulate.hpp>
#include
<mln/core/colors.hpp>
#include
<mln/core/extension/padding.hpp>
#include
<mln/core/image/ndimage.hpp>
#include
<mln/core/image/view/channel.hpp>
#include
<mln/core/image/view/transform.hpp>
...
...
@@ -20,6 +23,7 @@ namespace
struct
mean_node_accu
:
mln
::
Accumulator
<
mean_node_accu
>
{
using
result_type
=
decltype
(
std
::
declval
<
mln
::
rgb8
>
()
+
std
::
declval
<
mln
::
rgb8
>
());
public:
void
take
(
const
mln
::
rgb8
&
v
)
{
...
...
@@ -32,21 +36,15 @@ namespace
result_type
to_result
()
const
{
return
m_count
>
1
?
static_cast
<
result_type
>
(
m_sum
/
m_count
)
:
m_sum
;
}
private:
result_type
m_sum
=
{
0
,
0
,
0
};
int
m_count
=
0
;
result_type
m_sum
=
{
0
,
0
,
0
};
int
m_count
=
0
;
};
/// \brief Add a border to the image with values set at the median value
mln
::
image2d
<
mln
::
rgb8
>
add_border
(
mln
::
image2d
<
mln
::
rgb8
>
ima
)
mln
::
rgb8
get_median_on_border
(
mln
::
image2d
<
mln
::
rgb8
>
ima
)
{
mln
::
image2d
<
mln
::
rgb8
>
res
(
ima
.
width
()
+
2
,
ima
.
height
()
+
2
);
std
::
vector
<
mln
::
rgb8
>
border
;
border
.
reserve
(
2
*
ima
.
width
()
+
2
*
ima
.
height
()
-
4
);
mln_foreach
(
auto
p
,
ima
.
domain
())
res
(
mln
::
point2d
{
1
,
1
}
+
p
)
=
ima
(
p
);
for
(
int
i
=
0
;
i
<
ima
.
width
();
i
++
)
{
border
.
push_back
(
ima
(
mln
::
point2d
{
i
,
0
}));
...
...
@@ -65,45 +63,18 @@ namespace
i
++
;
return
i
<
3
&&
a
[
i
]
<
b
[
i
];
});
mln
::
rgb8
med
=
border
[
border
.
size
()
/
2
];
for
(
int
i
=
0
;
i
<
res
.
width
();
i
++
)
{
res
(
mln
::
point2d
{
i
,
0
})
=
med
;
res
(
mln
::
point2d
{
i
,
res
.
height
()
-
1
})
=
med
;
}
for
(
int
i
=
1
;
i
<
res
.
height
()
-
1
;
i
++
)
{
res
(
mln
::
point2d
{
0
,
i
})
=
med
;
res
(
mln
::
point2d
{
res
.
width
()
-
1
,
i
})
=
med
;
}
return
res
;
}
mln
::
image2d
<
int
>
remove_border
(
mln
::
image2d
<
int
>
n
)
{
mln
::
image2d
<
int
>
res
(
n
.
width
()
-
2
,
n
.
height
()
-
2
);
mln_foreach
(
auto
p
,
res
.
domain
())
res
(
p
)
=
n
(
p
+
mln
::
point2d
{
1
,
1
});
return
res
;
}
/// \brief Compute the maximum value of an image
std
::
uint16_t
max
(
mln
::
image2d
<
std
::
uint16_t
>
ima
)
{
std
::
uint16_t
res
=
0
;
mln_foreach
(
auto
p
,
ima
.
domain
())
res
=
std
::
max
(
res
,
ima
(
p
));
return
res
;
return
border
[
border
.
size
()
/
2
];
}
/// \brief Reduce the size of a nodemap by a factor 2
mln
::
image2d
<
int
>
reduce_nodemap
(
mln
::
image2d
<
int
>
n
)
{
mln
::
image2d
<
int
>
res
((
n
.
width
()
+
3
)
/
4
,
(
n
.
height
()
+
3
)
/
4
);
// mln::image2d<int> res((n.width() + 3) / 4, (n.height() + 3) / 4);
const
mln
::
point2d
pmin
(
n
.
domain
().
tl
());
const
mln
::
point2d
pmax
(
n
.
domain
().
br
());
mln
::
image2d
<
int
>
res
(
mln
::
box2d
{{(
pmin
[
0
]
-
3
)
/
4
,
(
pmin
[
1
]
-
3
)
/
4
},
{(
pmax
[
0
]
+
3
)
/
4
,
(
pmax
[
1
]
+
3
)
/
4
}});
mln_foreach
(
auto
p
,
n
.
domain
())
mln_foreach
(
auto
p
,
n
.
domain
())
{
if
(
p
[
0
]
%
4
==
0
&&
p
[
1
]
%
4
==
0
)
{
...
...
@@ -119,13 +90,18 @@ int main(int argc, char* argv[])
{
if
(
argc
<
4
)
{
std
::
cerr
<<
"Invalid number of arguments
\n
Usage: "
<<
argv
[
0
]
<<
" input_filename depth_map_filename rec_filename
\n
"
;
std
::
cerr
<<
"Invalid number of arguments
\n
Usage: "
<<
argv
[
0
]
<<
" input_filename depth_map_filename rec_filename
\n
"
;
return
1
;
}
mln
::
image2d
<
mln
::
rgb8
>
ima
;
mln
::
io
::
imread
(
argv
[
1
],
ima
);
auto
to_process
=
add_border
(
ima
);
const
auto
med
=
get_median_on_border
(
ima
);
ima
.
inflate_domain
(
1
);
constexpr
int
borders
[
2
][
2
]
=
{{
1
,
1
},
{
1
,
1
}};
mln
::
pad
(
ima
,
mln
::
PAD_CONSTANT
,
borders
,
med
);
mln
::
morpho
::
component_tree
<>
trees
[
3
];
mln
::
image2d
<
int
>
nodemaps
[
3
];
...
...
@@ -133,28 +109,29 @@ int main(int argc, char* argv[])
for
(
int
c
=
0
;
c
<
3
;
c
++
)
{
std
::
tie
(
trees
[
c
],
nodemaps
[
c
])
=
mln
::
morpho
::
tos
(
mln
::
view
::
channel
(
to_process
,
c
),
{
0
,
0
});
std
::
tie
(
trees
[
c
],
nodemaps
[
c
])
=
mln
::
morpho
::
tos
(
mln
::
view
::
channel
(
ima
,
c
),
{
-
1
,
-
1
});
depths
[
c
]
=
trees
[
c
].
compute_depth
();
}
const
auto
[
gos
,
tree_to_graph
]
=
mln
::
morpho
::
details
::
compute_inclusion_graph
(
trees
,
nodemaps
,
depths
,
3
);
auto
depth_map
=
mln
::
morpho
::
details
::
compute_depth_map
(
gos
,
tree_to_graph
,
nodemaps
);
{
std
::
uint16_t
max_depth
=
m
ax
(
depth_map
);
std
::
uint16_t
max_depth
=
m
ln
::
accumulate
(
depth_map
,
mln
::
accu
::
accumulators
::
max
<
std
::
uint16_t
>
()
);
auto
normalized_depth
=
mln
::
view
::
transform
(
depth_map
,
[
&
max_depth
](
std
::
uint16_t
a
)
->
float
{
return
(
float
)
a
/
(
float
)
max_depth
;
});
auto
heat_depth
=
mln
::
view
::
transform
(
normalized_depth
,
heat_lut
);
mln
::
io
::
imsave
(
heat_depth
,
argv
[
2
]);
}
auto
[
t
,
nm
]
=
mln
::
morpho
::
details
::
satmaxtree
(
depth_map
,
{
0
,
0
});
nm
=
reduce_nodemap
(
nm
);
nm
=
remove_border
(
nm
);
auto
[
t
,
nm
]
=
mln
::
morpho
::
details
::
satmaxtree
(
depth_map
,
{
-
1
,
-
1
});
nm
=
reduce_nodemap
(
nm
);
ima
.
inflate_domain
(
-
1
);
nm
.
inflate_domain
(
-
1
);
auto
area
=
t
.
compute_attribute_on_points
(
nm
,
mln
::
accu
::
accumulators
::
count
<
int
>
());
t
.
filter
(
mln
::
morpho
::
CT_FILTER_DIRECT
,
nm
,
[
&
area
](
int
n
)
{
return
area
[
n
]
>=
100
;
});
auto
mean
=
t
.
compute_attribute_on_values
(
nm
,
ima
,
mean_node_accu
());
auto
rec
=
t
.
reconstruct_from
(
nm
,
ranges
::
make_span
(
mean
.
data
(),
mean
.
size
()));
auto
rec
=
t
.
reconstruct_from
(
nm
,
ranges
::
make_span
(
mean
.
data
(),
mean
.
size
()));
mln
::
io
::
imsave
(
mln
::
view
::
cast
<
mln
::
rgb8
>
(
rec
),
argv
[
3
]);
return
0
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment