Section for Image Analysis
Department of Mathematical Modelling
Technical University of Denmark (DTU)
The DTU Image Viewer and Analyser DIVA is an application for viewing images and performing basic image analysis. The DIVA also serves as a platform for developing new and more advanced image analysis applications. The DIVA is based on a C++ template image class originally formulated by Microsoft and handles a wide variety of different image file formats and pixel types.
The DIVA has been developed by the Section for Image Analysis, Department of Mathematical Modelling (IMM), Technical University of Denmark .
DIVA as a platform
By using the DIVA as a platform for a new image analysis application you automatically get all the DIVA functionality included in the new application. To use the DIVA as a platform it is necessary to have a version of MS Visual C++ 6.0. The following sections describe how to use the DIVA as a platform in practice.
Installation of Microsoft Vision Software Developers Kit (VisSDK)
To install VisSDK v1.1 (or higher versions), which is necessary for using the DIVA as a platform, download the sources code from http://www.research.microsoft.com/research/vision. Unzip the VisSDK files and compile the VisSDK as follows:
Installation of Intel Image Processing Library (IPL)
To instal Intel Image Processing Library v2.1 (or higher versions), which is necessary for using the DIVA as a platform, download the library from http://developer.intel.com/vtune/perflibst/ipl/index.htm. Run the setup and do as follows:
For further information about the IPL installation refer to the IPL documentation.Select the Options item on the Tools menu in MS Visual C++. Go to the directories tab. Add the "inc" directory of the IPL library to your include file path:
C:\Program Files\Intel\plsuite\include
Add the IPL "lib\msvc" directory to your library file path in MS Visual C++:
C:\Program Files\Intel\plsuite\lib\msvc
Add the bin directory of the IPL (i.e. c:\Program Files\Intel\plsuite\bin) to your system path. On Windows NT, you can do this by adding it to the PATH variable on the Environment tab of the System control panel. On Windows 95, you’ll need to add the directory to the PATH variable in your autoexec.bat file.
Installation of Image Magic
The installation of Image Magick package v.4.2.1 (or higher versions) is optional for using the DIVA, but if you want to be able to open and save a wide variety of image formats you need it. To install the Image Magick package follow the instructions:
Installation of CLAPACK
The installation of CLAPACK is optional for using the DIVA, but if you want to be able to use more advanced matrix functions you need it. Refer to the Matrix Functions under VisMatrix project in the VisSDK documentation to see the actual matrix functions. To install the CLAPACK follow the instructions (Step 1 and 2 can be avoided if you have access to the BLAS, CLAPACK, F77 and I77 Lib files):
Installation of the DIVA
To install the DIVA download the DIVA source here and unzip the files. When the file is unzipped you should have the following directories:
To create a DIVA application use "File | New | Projects" and select the DIVA AppWizard. Before building the application update the following project settings for All Configurations (release and debug):
The organization of the DIVA classes
The organization of the DIVA classes follows a clear separation of the image analysis and the interface parts. This means that all code performing any analysis of the image is inserted in the image classes. This separation is chosen to ensure a high degree of reusability, portability and clarity of the code. The image classes used in the DIVA are all derived from the VisSDK CVisImageBase and CVisImage<TPixel> classes, where TPixel is a template argument, which corresponds the actual pixel type. For information about CVisImageBase and CVisImage<TPixel> read the VisSDK documentation. The actual hierarchy of the DIVA image classes is shown in Figure 1. From the CVisImage<TPixel> image class a number of classes are derived, which have different functionality. This is done to make it easy to use other peoples code, because each person more or less have their own set of classes. This mean that whenever the owner of for example the CDImageBasic<TPixel> class adds new functions to the class, the users of the class can change the old version with the new version without changing any of their own code. Another prerequisite to make the exchange of code possible is that the CVisImageBase and CVisImage<TPixel> are kept untouched. This also insures the easy incorporation of future releases of the VisSDK. The disadvantaged by not changing the base class is that it's impossible to make virtual base function, which requires the introduction of a wrapper class to avoid the use of switch structures. But this is a trade off.
Finally the image class CDImageApp<TPixel> is created
by inheriting from the existing image classes. The CDImageApp<TPixel>
is actually the image class, which is used in the DIVA. A number of classes
with new functionality have already been implemented in the DIVA
images classes.
Figure 1. Class hierarchy for the image classes in the DIVA.
The CVisImage<TPixel> and the derived classes are only able to handle single images. To represent a sequence of images two sequence classes CVisSequenceBase and CVisSequence<TPixel> is formulated under VisSDK. The sequence classes are basically a queue of images. Unfortunately the VisSDK CVisSequence<TPixel> class derived from the CVisSequenceBase class is only able of handling CVisImage images. DIVA uses a sequence class CDVisSequence<TPixel>, which is equivalent to the CVisSequence<TPixel> class , except it is able to handle CDImageApp<TPixel> images.
Beside the image and sequence classes the traditional
View, Doc etc. classes for multi document Windows applications are used
in the interface part of the DIVA. To actual interface the sequence/image
classes with the View/doc class is introduced two wrapper classes CDIVAWrapBase
and CDIVAWrap<TPixel>, which is "wrapped around" the sequence/image
classes, i.e. the sequence class is a member of the wrapper class. The
wrapper classes is introduced to make it possible to create virtual functions,
which manipulate the image. This was not possible before, if the CVisImageBase
class should be kept untouched. The introduction of the wrapper classes
makes it possible to avoid switch structures (with one exception), which
make the code much more structured, flexible and shorter .
In the actual implementation four wrapper classes exists: CDIVAWrapBase,
CDIVAWrap<TPixel>, CDIVAWrapGray<TPixel> and CDIVAWrapRGBA<TPixel>,
see figure 2. The separation between Gray and RGBA is introduced
to avoid the problems, which occurs when a function is not defined for
both formats.
Figure 2. Class hierarchy for the wrapper classes in the DIVA. CDIVAWrapBase is the abstract base class. CDIVAWrap contains the implementation of function, which are defined for all pixel formats. CDIVAWrapGray and CDIVAWrapRGBA contains the implementation of functions for Gray and RGBA images, which are not identical for both formats, respectively.
The procedure for adding a new function to the DIVA is naturally separated in the image analysis and the interface part. Basically the image analysis part is a question of adding a function to the relevant image class and the interface part is a question of adding a function to the wrapper and the view classes. As an example we are going to add a function, which takes exp to every pixel, to DIVA.
To make it easy to use other people's functions and visa versa, it is a fundamental request that the principles for organization of the DIVA code is respected.
Image analysis
First we are going to create the exp function in the image class CDImageMyClasse<TPixel>, see figure 1. The algorithm is very simple, see below. It loops over all the pixels in the active area ( the same as Region Of Interest ROI) and take exp to each pixel given by the function Pixel(x,y). Remember that the image coordinate system starts in the upper left corner of the image. Exp is only defined for gray scale images and not for RGB and YUV images. This example shows the big advantage of template image classes, because you only need to program one function for all gray scale images. Note how the history is updated in the end of the function.
"CDImageMyClass.h"
// image functions
void Exp();
"CDImageMyClass.inl"
template <class TPixel>
void CDImageMyClass<TPixel>::Exp()
{
for (int y = Top();y < Bottom(); y++)
{
for (int
x = Left();x < Right(); x++)
{
Pixel(x,y) = exp(Pixel(x,y));
}
}
// update history
AddToHistory("DIVA: Exp of each pixel
(Exp)");
}
Note, that it is faster to access pixel information by the use of pointers than the function Pixel(x,y), see the VisSDK documentation for further information.
Interface
The first step is to create the necessary functions in the wrapper classes. A pure virtual Exp() function is inserted in the base wrapper class, see below. The next step is to insert a Exp() function in the CDIVAWrapGray and CDIVAWrapRGBA classes. For the gray scale images corresponding to CDIVAWrapGray is the Exp() function, which was created above, applied to the current active image by the Image().Exp() function call, where Image() returns a reference to the current active image of the type CDImageApp<TPixel>. Unfortunately, the exp function is undefined for RGBA pixels, so the Exp() function in CDIVAWrapRGBA<TPixel> throws an error.
"DIVAWrapBase.h"
class CDIVAWrapBase
{
...
virtual void Exp() = 0;
...
}
"DIVAWrap.h"
template<class TPixel>
class CDIVAWrapGray : public CDIVAWrap
{
...
virtual void Exp() {Image().Exp();}
...
}
template<class TPixel>
class CDIVAWrapRGBA : public CDIVAWrap
{
...
virtual void Exp() { throw CVisError("This function
dos not support the pixel format RGB",eviserrorPixFmt,"Exp()","DIVAWrap.h",
__LINE__); }
...
}
The next step is to create an actual Windows interface
to Exp(). First open the resource editor for the menus and create a Tools
menu and add a pop-up Submenu Math Functions and then the Exp command,
see Figure 3. The next step is to create the function that handles the
Exp command. To do this open the class wizard (ctrl w) and add a new function.
To add the function chose the same setting as in the Object IDs and Messages
boxes in Figure 4, and select "Add Function".
Figure 3. Create a Tools | Math Functions menu and add the Exp command.
Figure 4. Class Wizard settings to create a function that handles the Exp command.
A empty function is now added in the header (.h) and code (.cpp) file. To edit the function select "Edit Code" in the class wizard. The last step is now to add the code that actually performs the exp on the image, see the listing of the needed code below. To call the Exp function a pointer to the actual document is acquired by GetDocument and a call to the Exp function in the wrapper class is performed by pDoc->m_pwrapbase->Exp(). The last step is then to update the display by a call to Invalidate(). Note, the try and catch structure, which catch errors that are thrown by the Exp function in CDIVAWrapRGBA if the image is an RGBA image.
"CDIVA2View.h"
void OnToolsMathfunctionsExp();
"CDIVA2View.cpp"
void CDIVA2View::OnToolsMathfunctionsExp()
{
try
{
CDIVA2Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// perform exp (using
the wrapper class)
pDoc->m_pwrapbase->Exp();
// update display
Invalidate();
}
catch(CVisError error)
{
ShowError(error);
}
}
Copyright, 1999
Section for Image Analysis
Department of Mathematical
Modelling
Technical University of
Denmark
DK-2800 Lyngby
Author: Rune Fisker
Last updated: June 29 1999.