1.3. ML Classes - Overview

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.

1.3.1. Classes for Module Development

This chapter gives a survey of the most important ML components, classes and interfaces.

1.3.1.1. Module Overview

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.

1.3.1.2. Field Overview

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.

1.3.1.3. FieldContainer Overview

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.

1.3.1.4. Image Classes Overview

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.

1.3.2. Administrative Classes

1.3.2.1. The Host Overview

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.

1.3.2.2. The MLMemoryManager and Memory Handling

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.

1.3.2.3. Memory Overview

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.

1.3.2.4. The Runtime Type System

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.

1.3.2.5. Debugging Overview and Error Handling Support

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.

1.3.3. Image Classes

1.3.3.1.  ImageProperties Overview

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.

1.3.3.2.  MedicalImageProperties Overview

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.

1.3.3.3.  PagedImage Overview

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.

1.3.3.4.  SubImage and TSubImage Overview

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.

1.3.3.5.  VirtualVolume

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.

1.3.3.6.  BitImage

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.

1.3.3.7.  MemoryImage

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.

1.3.4. Helper Classes

1.3.4.1.  ImageVector

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.

1.3.4.2.  SubImageBox

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 .

1.3.5. APIs and Classes for Interfaces and Voxel Type Extensions

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.

1.3.6. Component Groups

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.

1.3.7. The ML Module Database

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.

When using the ML in combination with MeVisLab, a large number of non-image processing modules can also be used for module networks and applications:

  • 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.