Commit 7107e0f0 authored by Michaël Roynard's avatar Michaël Roynard
Browse files

Merge branch 'development/doc-erosion' into 'dev'

Documentation

Closes #9

See merge request !9
parents e3d7915e c652d093
add_custom_target(doc
COMMAND doxygen ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile
COMMAND sphinx-build -b html ${CMAKE_CURRENT_SOURCE_DIR}/source ${CMAKE_CURRENT_BINARY_DIR}/build
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_subdirectory(source/snipsets)
add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/doxyxml/index.xml
COMMAND doxygen Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(source/snipsets)
add_custom_target(build-doxyxml
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/doxyxml/index.xml)
add_custom_target(doc
COMMAND sphinx-build -b html ${CMAKE_CURRENT_SOURCE_DIR}/source ${CMAKE_CURRENT_BINARY_DIR}/build
DEPENDS build-images
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/doxyxml/index.xml")
@import url("css/theme.css");
.breatheparameterlist p {
display: inline;
}
/* .breatheparameterlist p { */
/* display: inline; */
/* } */
.rst-content dl:not(.docutils) dt {
display: block;
background: none;
margin-top: 0;
margin-bottom: 0;
}
.rst-content dl:not(.docutils) dt:last-child {
margin-bottom: 6px;
.rst-content dl:not(.docutils) dt em:not(.property) {
color: black;
}
.rst-content dl:not(.docutils) dl dt {
display: block;
margin-top: 0;
margin-bottom: 0;
}
/* .rst-content dl:not(.docutils) dt:last-child { */
/* margin-bottom: 6px; */
/* } */
/* .rst-content dl:not(.docutils) dl dt { */
/* display: block; */
/* margin-top: 0; */
/* margin-bottom: 0; */
/* } */
Mathematical Morphology Module
==============================
.. doxygengroup:: morpho
Structural Morphological Operation
**********************************
.. toctree::
:maxdepth: 1
morpho/erosion
morpho/dilation
morpho/opening
morpho/closing
morpho/hit_or_miss
morpho/opening_by_reconstruction
morpho/closing_by_reconstruction
Closing
=======
#. .. cpp:function:: \
template <class InputImage, class StructuringElement> \
concrete_t<InputImage> closing(const InputImage& ima, const StructuringElement& se)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement, class Compare> \
concrete_t<InputImage> closing(const InputImage& ima, const StructuringElement& se, Compare cmp)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement, class OutputImage, class Compare> \
void closing(const InputImage& ima, const StructuringElement& se, Compare cmp, OutputImage& output)
Closing by a structuring element.
Given a structuring element 𝐵, the closing :math:`\gamma(f)` of the input
image 𝑓 is defined as:
.. math::
\gamma(f) = \varepsilon_\mathcal{B}(\delta_\mathcal{B}(f))
* (2,3) If a optional \p cmp function is provided, the algorithm will internally do
an unqualified call to ``inf(x, y,cmp)``.The default is the product-order so
that it works for vectorial type as well.
* (3) If the optional ``output`` image is provided, it must be wide enough to store
the results (the function does not perform any resizing).
:param ima: Input image 𝑓
:param se: Structuring element 𝐵
:param cmp (optional): Comparison function
:param output (optional): Output image
:return:
* (1,2) An image whose type is deduced from the input image
* (3\) Nothing (the output image is passed as an argument)
:exception: N/A
Notes
-----
Complexity
----------
Example 1 : Closing by a square on a gray-level image
------------------------------------------------------
.. code-block:: cpp
#include <mln/morpho/structural/closing.hpp>
#include <mln/core/wind2d.hpp>
// Define a square SE of size 21x21
auto input = ...;
auto rect = mln::make_rectangle2d(21,21);
auto output = mln::morpho::structural::closing(input, rect);
.. image:: /images/lena_gray.jpg
:width: 49%
.. image:: /images/morpho_closing_1.png
:width: 49%
Closing by reconstruction
=========================
.. cpp:function:: \
template <class InputImage1, class InputImage2, class Neighborhood> \
concrete_t<InputImage1> closing_by_reconstruction(const InputImage1& f, const InputImage2& markers, const Neighborhood& nbh)
.. cpp:function:: \
template <class InputImage1, class InputImage2, class Neighborhood, class Compare> \
concrete_t<InputImage1> closing_by_reconstruction(const InputImage1& f, const InputImage2& markers, const Neighborhood& nbh, Compare cmp)
Perform the reconstruction of the image ``markers`` over the constrain
image ``f``. Contrary to :ref:`opening-by-reconstruction`, the *background* is
reconstructed instead of the *foreground*.
:param f: Input image 𝑓
:param markers: Marker image (must have the same value type of 𝑓)
:param nbh: Fundamental structuring element.
:param cmp (optional): Comparaison function defining a strict weak ordering of values.
:return: An image whose type is deduced from the input image
:precondition: :math:`markers > f`
:exception: N/A
Notes
-----
Complexity
----------
Dilation
========
#. .. cpp:function:: \
template <class InputImage, class StructuringElement> \
concrete_t<InputImage> dilate(const InputImage& ima, const StructuringElement& se)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement, class Compare> \
concrete_t<InputImage> dilate(const InputImage& ima, const StructuringElement& se, Compare cmp)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement, class OutputImage, class Compare> \
void dilate(const InputImage& ima, const StructuringElement& se, OutputImage& output, Compare cmp)
Dilation by a structuring element.
Given a structuring element 𝐵, the dilation :math:`\delta(f)` of the input
image 𝑓 is defined as:
.. math::
\delta(f)(x) = \bigvee \{ \, f(y), y \in B_x \, \}
* (2,3) If a optional \p cmp function is provided, the algorithm will internally do
an unqualified call to ``inf(x, y,cmp)``.The default is the product-order so
that it works for vectorial type as well.
* (3) If the optional ``output`` image is provided, it must be wide enough to store
the results (the function does not perform any resizing).
:param ima: Input image 𝑓
:param se: Structuring element 𝐵
:param cmp (optional): Comparison function
:param output (optional): Output image
:return:
* (1,2) An image whose type is deduced from the input image
* (3\) Nothing (the output image is passed as an argument)
:exception: N/A
Notes
-----
Complexity
----------
Example 1 : Dilation by a square on a gray-level image
------------------------------------------------------
.. code-block:: cpp
#include <mln/morpho/structural/dilate.hpp>
#include <mln/core/wind2d.hpp>
// Define a square SE of size 21x21
auto input = ...;
auto rect = mln::make_rectangle2d(21,21);
auto output = mln::morpho::structural::dilate(input, rect);
.. image:: /images/lena_gray.jpg
:width: 49%
.. image:: /images/morpho_dilation_1.png
:width: 49%
Erosion
=======
#. .. cpp:function:: \
template <class InputImage, class StructuringElement> \
concrete_t<InputImage> erode(const InputImage& ima, const StructuringElement& se)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement, class Compare> \
concrete_t<InputImage> erode(const InputImage& ima, const StructuringElement& se, Compare cmp)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement, class OutputImage, class Compare> \
void erode(const InputImage& ima, const StructuringElement& se, OutputImage& output, Compare cmp)
Erosion by a structuring element.
Given a structuring element 𝐵, the erosion :math:`\varepsilon(f)` of the input
image 𝑓 is defined as:
.. math::
\varepsilon(f)(x) = \bigwedge \{ \, f(y), y \in B_x \, \}
* (2,3) If a optional \p cmp function is provided, the algorithm will internally do
an unqualified call to ``inf(x, y,cmp)``.The default is the product-order so
that it works for vectorial type as well.
* (3) If the optional ``output`` image is provided, it must be wide enough to store
the results (the function does not perform any resizing).
:param ima: Input image 𝑓
:param se: Structuring element 𝐵
:param cmp (optional): Comparison function
:param output (optional): Output image
:return:
* (1,2) An image whose type is deduced from the input image
* (3\) Nothing (the output image is passed as an argument)
:exception: N/A
Notes
-----
Complexity
----------
Example 1 : Erosion by a square on a gray-level image
------------------------------------------------------
.. code-block:: cpp
#include <mln/morpho/structural/erode.hpp>
#include <mln/core/wind2d.hpp>
// Define a square SE of size 21x21
auto input = ...;
auto rect = mln::make_rectangle2d(21,21);
auto output = mln::morpho::structural::erode(input, rect);
.. image:: /images/lena_gray.jpg
:width: 49%
.. image:: /images/morpho_erosion_1.png
:width: 49%
Hit or Miss
===========
#. .. cpp:function:: \
template <class InputImage, class StructuringElement1, class StructuringElement2> \
concrete_t<InputImage> hit_or_miss(const InputImage& ima, const StructuringElement1& se_hit, const StructuringElement1& se_miss)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement1, class StructuringElement2, class OutputImage> \
void hit_or_miss(const InputImage& ima, const StructuringElement1& se_hit, const StructuringElement1& se_miss, OutputImage& output)
The hit-or-miss transform is non-linerar filter used to detect pattern in
images. It is defined as:
.. math::
UHTM_\mathcal{B}(f)(x) =
\begin{cases}
\varepsilon_{B_{fg}}(x) - \delta_{B_{bg}}(x) & \mathrm{if} \varepsilon_{B_{fg}}(x) > \delta_{B_{bg}}(x)\newline
0 & otherwise
\end{cases}
where :math:`$ \mathcal{B} = (B_{fg}, B_{bg})` is the composite
structuring element composed by the two disjoint foreground and background
SEs.
* (2\) If the optional ``output`` image is provided, it must be wide enough to store
the results (the function does not perform any resizing).
:param ima: Input image 𝑓
:param se_hit: Structuring element for the foreground :math:`B_{fg}`
:param se_miss: Structuring element for the foreground :math:`B_{bg}`
:param output (optional): Output image
:return:
* (1\) An image whose type is deduced from the input image
* (2\) Nothing (the output image is passed as an argument)
:exception: N/A
Notes
-----
Complexity
----------
Example 1 : Staff lines selection
---------------------------------
Hit or miss transform to detect horizontal 1px-thick line, with pattern::
x x x
o o o
x x x
.. literalinclude:: /snipsets/staff_lines.cpp
:lines: 29-36
:language: cpp
.. image:: /images/staff_lines.png
:width: 49%
.. image:: /images/morpho_hitormiss_1.png
:width: 49%
Hit or miss transform to detect horizontal 2px-thick line, with pattern::
x x x
o o o
o o o
x x x
.. literalinclude:: /snipsets/staff_lines.cpp
:lines: 29-36
:language: cpp
.. image:: /images/staff_lines.png
:width: 49%
.. image:: /images/morpho_hitormiss_2.png
:width: 49%
Logical or between the two previous images:
.. literalinclude:: /snipsets/staff_lines.cpp
:lines: 57
:language: cpp
.. image:: /images/staff_lines.png
:width: 49%
.. image:: /images/staff_lines_markers.png
:width: 49%
Opening
=======
#. .. cpp:function:: \
template <class InputImage, class StructuringElement> \
concrete_t<InputImage> opening(const InputImage& ima, const StructuringElement& se)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement, class Compare> \
concrete_t<InputImage> opening(const InputImage& ima, const StructuringElement& se, Compare cmp)
#. .. cpp:function:: \
template <class InputImage, class StructuringElement, class OutputImage, class Compare> \
void opening(const InputImage& ima, const StructuringElement& se, Compare cmp, OutputImage& output)
Opening by a structuring element.
Given a structuring element 𝐵, the opening :math:`\gamma(f)` of the input
image 𝑓 is defined as:
.. math::
\gamma(f) = \delta_\mathcal{B}(\varepsilon_\mathcal{B}(f))
* (2,3) If a optional \p cmp function is provided, the algorithm will internally do
an unqualified call to ``inf(x, y,cmp)``.The default is the product-order so
that it works for vectorial type as well.
* (3) If the optional ``output`` image is provided, it must be wide enough to store
the results (the function does not perform any resizing).
:param ima: Input image 𝑓
:param se: Structuring element 𝐵
:param cmp (optional): Comparison function
:param output (optional): Output image
:return:
* (1,2) An image whose type is deduced from the input image
* (3\) Nothing (the output image is passed as an argument)
:exception: N/A
Notes
-----
Complexity
----------
Example 1 : Opening by a square on a gray-level image
------------------------------------------------------
.. code-block:: cpp
#include <mln/morpho/structural/opening.hpp>
#include <mln/core/wind2d.hpp>
// Define a square SE of size 21x21
auto input = ...;
auto rect = mln::make_rectangle2d(21,21);
auto output = mln::morpho::structural::opening(input, rect);
.. image:: /images/lena_gray.jpg
:width: 49%
.. image:: /images/morpho_opening_1.png
:width: 49%
.. _opening-by-reconstruction:
Opening by reconstruction
=========================
.. cpp:function:: \
template <class InputImage1, class InputImage2, class Neighborhood> \
concrete_t<InputImage1> opening_by_reconstruction(const InputImage1& f, const InputImage2& markers, const Neighborhood& nbh)
Perform the reconstruction of the image ``markers`` under the constrain
image ``f``. The markers designate the parts of the image we want to
retain. In binary, it is equivalent to perform the *conditional*
dilation of the ``markers`` :math:`X`, by a structuring element 𝑩, using
the *reference* 𝑓 until reaching stability.
.. math::
\delta^{n+1}_{f,\mathcal{B}}(X) = \delta_\mathcal{B}(\delta^{n}_{f,\mathcal{B}}(X)) \cap f
:param f: Input image 𝑓
:param markers: Marker image (must have the same value type of 𝑓)
:param nbh: Fundamental structiring element.
:return: An image whose type is deduced from the input image
:precondition: :math:`markers < f`
:exception: N/A
Notes
-----
Complexity
----------
Example 1 : Staff lines reconstruction
--------------------------------------
.. image:: /images/staff_lines.png
:width: 49%
.. image:: /images/staff_lines_markers.png
:width: 49%
The markers have been obtained with the :cpp:func:`hit_or_miss`.
* Reconstruction of the objects touching staff lines; with the foundamental SE
(4-connection). All objects that do not touch the staff lines are removed.
.. literalinclude:: /snipsets/staff_lines.cpp
:lines: 60
:language: cpp
.. image:: /images/staff_lines.png
:width: 49%
.. image:: /images/morpho_reconstruction_1.png
:width: 49%
* Reconstruction of the lines only; with an horizontal SE `x-o-x`.
.. literalinclude:: /snipsets/staff_lines.cpp
:lines: 63
:language: cpp
.. image:: /images/staff_lines.png
:width: 49%
.. image:: /images/morpho_reconstruction_2.png
:width: 49%
##################################
## Gererate All Example Images ###
set(DOCUMENTATION_IMAGE_DIR ${PROJECT_SOURCE_DIR}/doc/source/images)
set(PYLENE_IMAGE_DIR ${PROJECT_SOURCE_DIR}/img)
set(DOCUMENTATION_IMAGES "")
function(add_image EXECUTABLE INPUT OUTPUT)
set(OUTPUT ${DOCUMENTATION_IMAGE_DIR}/${OUTPUT})
list(APPEND DOCUMENTATION_IMAGES ${OUTPUT})
set(DOCUMENTATION_IMAGES ${DOCUMENTATION_IMAGES} PARENT_SCOPE)
add_custom_command(OUTPUT ${OUTPUT}
COMMAND ${EXECUTABLE} ${INPUT} ${OUTPUT} ${ARGN}
COMMAND_EXPAND_LISTS
WORKING_DIRECTORY ${DOCUMENTATION_IMAGE_DIR})
endfunction()
add_image("erosion-cli;erosion;square;21" ${PYLENE_IMAGE_DIR}/lena.pgm morpho_erosion_1.png)
add_image("erosion-cli;dilation;square;21" ${PYLENE_IMAGE_DIR}/lena.pgm morpho_dilation_1.png)
add_image("erosion-cli;opening;square;21" ${PYLENE_IMAGE_DIR}/lena.pgm morpho_opening_1.png)
add_image("erosion-cli;closing;square;21" ${PYLENE_IMAGE_DIR}/lena.pgm morpho_closing_1.png)
add_image("staff_lines" ${DOCUMENTATION_IMAGE_DIR}/staff_lines.pbm
morpho_hitormiss_1.png morpho_hitormiss_2.png staff_lines_markers.png morpho_reconstruction_1.png morpho_reconstruction_2.png)
add_custom_target(build-images
DEPENDS "${DOCUMENTATION_IMAGES}")
link_libraries(${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE} ${FreeImage_LIBRARY})
add_executable(erosion-cli erosion-cli.cpp)
add_executable(staff_lines staff_lines.cpp)
add_executable(component_tree_1 component_tree_1.cpp)
target_link_libraries(component_tree_1 ${FreeImage_LIBRARIES})
......@@ -10,7 +10,6 @@
#include <mln/morpho/component_tree/accumulate.hpp>
#include <mln/morpho/component_tree/filtering.hpp>
#include <mln/morpho/component_tree/reconstruction.hpp>
#include <mln/morpho/tos/ctos.hpp>
int
main()
......
#include <mln/core/image/image2d.hpp>
#include <mln/core/win2d.hpp>
#include <mln/morpho/structural/erode.hpp>
#include <mln/morpho/structural/dilate.hpp>