The ML does not only implement base classes for image processing, but also covers areas such as linear algebra basics, error handling, debug functionality, a runtime type system, runtime types for voxels, observable parameter classes, containers for fields and much more.
The following sections will give a short overview of most of these classes and will explain their purpose.
This chapter gives a survey of the most important ML components, classes and interfaces.
The class
ml::Module
is the base class
from which all image processing modules need to be derived to
implement new algorithms for image processing. It provides a number
of virtual methods which can be overloaded to implement and control
image processing, and to handle/add/change algorithm and processing
parameters. See Chapter 3, Deriving Your Own Module from Module for more
information.
The
ml::Field
class encapsulates
a data type such as an integer, a vector, a matrix, a string or even
an image or a complex data structure. Currently, about 60 field
types are available in the ML. A field is useful for various
purposes: It can be observed for changes (listener pattern), its state can
be saved/restored by handling its value as a string, and it can be
connected with fields of other modules for data transfers. Modules
use these features for creating a reflective, self-descriptive and persistent
parameter interface. See Section 2.1.2, “
Field
” for more information on fields.
The
ml::FieldContainer
class manages a list of fields. A module is derived from the field container,
so all modules manage their fields themselves. See Section 2.1.3, “
FieldContainer
” for more information.
The ML does not process images as a whole but breaks them down
into smaller fractions of identical extents, the so-called
pages (see Section 2.3.4, “
PagedImage
”). Pages
can be easily buffered, cached and processed in parallel without
spending too much memory or time. The ML cache stores pages that
have a chance to be reused. For algorithms that cannot easily be
implemented on a page basis, the ML provides specialized classes
that also use internal paging, if possible. See Section 2.3.7, “
VirtualVolume
”, Section 2.3.6, “
BitImage
”), Section 2.3.8, “
MemoryImage
” and Section 1.3.3, “Image Classes”
for details.
The
ml::Host
is the core class of the ML.
It manages the entire image processing workflow including on-demand,
page-based image processing, caching and parallelization as well as
calling module functionalities for image processing. It also
provides functions such as checking and updating module graphs,
calculating (sub-) images with getTile()
commands and caching intermediate results by using the
MLMemoryManager
(see Section 1.3.2.2, “The MLMemoryManager
and Memory Handling”). It checks and processes a set of ML
modules that have been derived from the class
Module
(see Chapter 3, Deriving Your Own Module from Module) and are connected forming a directed
acyclic graph.
The
MLMemoryManager
is
dedicated to managing a certain buffer memory (the Page Cache) where pages that have been
generated by an image processing module are stored for later reuse.
If a given cache limit is exceeded, the memory manager
frees memory blocks using a least-recently-used caching strategy until
the cache limit is no longer exceeded.
The MLMemoryManager provides strong and weak smart pointers to
keep reference to managed memory blocks and is not limited to the use of ML pages,
can be used by other application libraries as well and allows to make libraries
cache-aware.
Memory blocks that are locked by a smart pointer will not be removed,
so it is possible that the cache size exceeds the
limit temporarily.
Since the ML is dedicated to efficiently processing images that are too large for being stored in memory, the ML controls memory handling globally in order to allow for a safe and efficient memory usage.
The ML class Memory
currently provides
functions for memory allocation, reallocation, freeing, etc. It
contains only basic functionality. In future versions, it will use
automatic strategies to (re-) organize and/or clean up the memory
(and the ML cache) to reduce or prevent out-of-memory errors.
Allocation errors can be handled by the ML or by users in different
ways. See Section 1.3.2.3, “Memory
Overview” for more
information.
The Runtime Type provides an interface where all important
classes and modules can register themselves (see Section 2.2.4, “The Runtime Type System” for more information). It stores
class names, types, source library, parent classes, etc. It also provides
a factory that permits the creation of instances of any
registered (non-abstract) class from a class name string.
It is crucial for applications such
as MeVisLab that need to handle
databases and networks of modules not yet known when the application
is compiled. These concepts are realized by the classes
Runtime
, RuntimeDict
and RuntimeType
as well as by a set of macros
that implement runtime module interface functionality.
The ML supports debugging and error handling (see Chapter 5, Debugging and Error Handling for more information).
Debug output can be controlled in the ML, i.e., it can be enabled/disabled for the entire ML or activated for individual classes.
Errors can be handled on different levels. In general,
programmers should check for errors and handle them by using
dedicated error handling macros and never by
using statements such as assert
,
abort
or exit
, because the
application cannot manage or log these statements. The way how the
ML behaves on errors can be configured globally. The ML could
generate an e-mail and terminate, or display a pop-up window and try
to continue. The behavior on errors should always be configured
globally for the ML.
The classes ErrorOutput
and
ErrorOutputInfos
are used for error handling
and ML output redirecting. They contain a set of static functions to
print debug information, warnings, errors and fatal errors. There is
a registration mechanism where the application can register itself
to be notified when an error, a warning or some debug information is
to be printed or handled.
The
ml::ImageProperties
class describes the basic image properties 6D image
extent, voxel data type, and minimum and maximum voxel values.
See Section 2.3.1, “
ImageProperties
” or
mlImageProperties.h
in project
ML
for more information.
The
ml::MedicalImageProperties
class is derived from
ImageProperties
. It contains additional
information specialized for medical data sets, like voxel size,
image orientation and position, a reference to the image's DICOM
information and descriptions of color channels, time points and the
user dimension. See Section 2.3.2, “
MedicalImageProperties
”
or
mlMedicalImageProperties.h
in project
ML
for more information.
Since images are usually not
processed as a whole by the ML, it is necessary to break them down
into smaller fractions of identical extents, the so-called
pages. The
ml::PagedImage
class is derived from the class
MedicalImageProperties
(see Section 2.3.2, “
MedicalImageProperties
” and thus inherits all properties
that describe an image. It is dedicated to managing paged images in
the ML and also to representing image outputs of ML modules. See
Section 2.3.4, “
PagedImage
” or
mlPagedImage.h
in
project ML
for more information.
This class represents image, subimage and page buffers, hence
knowledge about this class is crucial for programming most image
processing algorithms. It manages chunks of voxel data, copies
or fills them and offers fast data access methods with offset/stride
usage.
ml::TSubImage
is the typed version of
ml::SubImage
which permits typed data access. See Section 2.3.5, “SubImage
/TSubImage
”, or
mlSubImage.h
in project
ML
.
For many algorithms, the implementation of a page-based
approach might be difficult. A typical example is a filling
algorithm that needs random access to the input image, even if only
one voxel of the output image is required. Such algorithms can be
implemented efficiently by using the
ml::VirtualVolume
and
ml::TVirtualVolume
classes (see Section 2.3.7, “
VirtualVolume
”) without breaking the page-based approach
of the ML. A VirtualVolume
class
requests/calculates the image data when needed and rejects it if not
needed anymore. Thus large images can randomly be accessed without
the need to keep them completely in memory.
The
ml::BitImage
class (see Section 2.3.6, “
BitImage
”) supports the memory-efficient creating,
copying, filling, addressing of packed 6D binary images, and
interactions with the class SubImage
and
VirtualVolume
(see Section 2.3.5, “SubImage
/TSubImage
”
and Section 2.3.7, “
VirtualVolume
”.) This is often useful for
algorithms that need to mark or tag all voxels of a page or an
image, or for those algorithms that simply need to handle large
binary images.
Algorithms that need access to an entire non-paged
memory-mapped image may use the MemoryImage
approach (see Section 2.3.8, “
MemoryImage
”) for image processing.
This approach breaks the paging principle and should only be used if
it cannot be avoided and if it is safe to load the whole image into
memory. The memory image is integrated as a special member of the
class PagedImage
(see Section 2.3.4, “
PagedImage
”) and can thus be used in parallel or instead
of a paged image.
The class
ml::ImageVector
manages a 6D point or
vector with integer components and is used for voxel positions,
image extents, page extents and boxes. The typical (integer) vector
arithmetic is available as well as are methods for minimum and
maximum component determination, lexicographical comparisons, stride
operations and component multiplication for voxel addressing, etc.
See Section 2.4.1, “ImageVector
, ImageVector” for more information.
The class
ml::SubImageBox
manages a
rectangular 6D box specified by two integer
ImageVectors
that represent its corners. It
permits intersections, calculation of voxel volumes, etc. (see Section 2.4.2, “
SubImageBox
”). Like the class
ImageVector
(see Section 2.4.1, “ImageVector
, ImageVector”), it is
available in 16, 32 and 64 bit template specializations. The default
version SubImageBox
also uses 64 bit integer
addressing. An analogous class that uses 6D double (Vector6) vectors is
available as SubImageBoxd
in the file
mlSubImageBoxd.h
.
An easy way to use the ML is to link the C-API (see Section 6.3, “mlAPI.h”) of the ML. It provides a set of functions to create/delete modules, set their parameters (fields), to connect them and to request images from their outputs. The C-API allows non-C++ applications to make use of the ML. This interface is more stable than the C++ interface which may be modified more frequently and is not guaranteed to be binany compatible between ML versions.
The ML supports a set of scalar data types for image voxels (signed/unsigned 8, 16, 32, 64 bit integer types and float, double) as well as extended data types (see Chapter 7, Registered Voxel Data Types, Section 7.5.5, “Implementing a New Voxel Data Type by Deriving from MLTypeInfos”) that permit the usage of composite data types added by the user or by the ML itself. It is not necessary to recompile the ML to make use of these types, but modules might need to be adapted depending on how they were written.
ML classes can roughly be divided into three groups -
Core Classes, Helper or
User Classes and Aggregated Projects and Classes. Note that these classes are not necessarily in
the same directory or project. Also note that some of these classes
are not directly located in the project ML. Basic functionality is
typically located in the project MLUtilities
(see
Section 2.6.2, “
MLUtilities
”, vector and matrix arithmetics are located
in the project MLLinearAlgebra
(see Section 2.6.1, “MLLinearAlgebra
(Vector2, ..., Vector10, Vector16, Matrix2, , ..., Matrix6, quaternion, ImageVector)” and classes related to image processing
are located in the project ML
.
Core classes that provide the basic functionality for image processing and module handling:
Module
the base class for image processing
modules,
Field
,
FieldContainer
and
FieldSensor
for module parameters,
Host
,
MLMemoryManager
for image data and image flow
management,
ImageProperties
and
MedicalImageProperties
for image properties,
ImagePropertyExtension
that can be appended to medical image
properties,
PagedImage
and
MemoryImage
for image handling,
ErrorOutput
(from project Section 2.6.2, “
MLUtilities
”) for
error handling and logging,
InputConnector
, OutputConnector
for module input/output image connections.
Helper or user classes and projects simplifying the implementation of some algorithms:
Runtime
,
RuntimeDict
and
RuntimeType
(from project Section 2.6.2, “
MLUtilities
”) for
object factories and class management,
ImageVector
and
SubImageBox
for position and region management,
Linear algebra
classes like Vector2
, Vector3
,
Vector4
, Vector6
,
Matrix3
, Matrix4
(from
project MLLinearAlgebra
),
MLTypeInfos
for
registered and user-defined data types (see Chapter 7, Registered Voxel Data Types),
Rotation
, Disc
, SubImageBoxd
, Line
, Plane
parameters for modules,
DateTime,TimeCounter
, Notify
(from project Section 2.6.2, “
MLUtilities
”) for
high precision time measurement, and
Aggregated projects and classes that are not necessarily part of the ML but that are essential for advanced image processing:
BitImage
for flag and mask images,
MLBase
for point, function, marker, and vector lists,
etc. that can be passed between modules,
MLDataCompressor
for data compressor classes,
MLDiagnosis
with support for module tests and
inspection,
MLImageFormat
for ML specific file IO,
VirtualVolume
for random access to (large) paged
images,
and many more.
Many modules that use the ML are already available to developers:
Image file IO and DICOM support,
Arithmetic (Add, Subtraction, Inversion, And, Or, Xor, Sqrt, Sqr, Log, Exp, etc.),
Base
objects for marker, vector,
point or general object lists,
FlowControl (ImageIteratorStart/End, Switch, Bypass, etc.),
Geometry (image resizing, subimages, resampling, concatenation, MPR, etc.),
Distance and projection transformations (Radon, DistanceTransform, etc.),
Segmentation (medical imaging: LiveWire, vessels, tumors, region growing, thresholding, fuzzy),
Registration and image matching,
Drawing (RasterFunctions, Draw2D, Draw3D, LiveWire, etc.),
Statistical (GlobalStat, CalcVolume),
Morphology (Rank, Min, Max, Median, Gauss, Average, Statistical, Laplace, Edge detectors, CloseGap, Surround, etc.),
Transfer functions (Look up tables),
Object (list) handlers,
Color (model) management (color converters and tables),
Diagnostic modules for controlling ML core functions and for error and debug handling,
Texture analysis filters,
Logfile, tester and inspector modules,
and many more.
Viewers (2D, 3D, Shadow, Slab, Slice Viewer, Volume Rendering, etc.),
Vessel visualization,
2D/3D object list and marker managers and visualizers,
Transfer functions (Look up tables, LUT),
Diagram visualization (draws 2D coordinates, markers, points, lines, etc.),
Contour Segmentation Objects (CSO) for contour drawing, manipulation and conversion,
Winged Edge Mesh library (WEM) for iso surface management and surface shaded display,
Interactions (View2DExtensions, Manipulators, Draggers, MarkerEditor, etc.), and
a set of (helper) macros (e.g., convenience viewers, frequently used module groups, converters between scalars, vectors, matrices, etc.).
The following scientific packages (each of them offering hundreds of algorithms) are available:
Open Inventor
™: A
set of modules (nodes) for 3D rendering with cameras,
transformations, 3D viewers, textures, 2D and 3D text,
manipulators, shape objects, etc.
The Insight Segmentation and Registration Toolkit
™: Algorithms for
advanced image processing, registration, and image
analysis.
The Visualization Toolkit
™: Algorithms for advanced
visualization, rendering, and image processing.
© 2024 MeVis Medical Solutions AG