DTU Image Viewer and Analyser DIVA

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.

DIVA is partly based on the  Microsoft Vision Software Developers Kit (VisSDK), Intel Image Processing Library (IPL) and Image Magic.


Installation
The installation is separated in three parts:

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:

For further information about the VisSDK installation refer to the VisSDK documentation.

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:

  • 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.
  • For further information about the IPL installation refer to the IPL documentation.

    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:

    For further information about the Image Magick  installation refer to the VisSDK and Image Magick documentation. Be aware that sometimes there are problems by building and linking Image Magick under Windows 95, see the VisSDK documentation.

    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):

    For further information about the CLAPACK  installation refer to the CLAPACK and LAPACK documentation.

    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 install the DIVA follow the instructions bellow: Creating a new DIVA application

    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):

    and add the following matrix CPP-files to the source files (chose "source files" under the" file view tab" and right click on the mouse and chose "Add files to folder". You may need to chose "Automatic use of precompiled headers" under "Projects | Settings | C/C++ | Precompiled headers" to actaully be able to compiled the files. Before building the application make sure the following settings are correct It should now be possible to build and run your DIVA application without any warnings or errors.

    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.


     










    Adding a new function

    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.