VIP

VIP (Visual Information Processing) is an image processing software library that has been developed by the Robotics and Vision Research Group in The Department of Computer Science at The University of Western Australia. VIP is not intended to be a `product' like Khoros. The aim of VIP is to provide a convenient facility for building experimental vision software very quickly. The system consists of two parts:

The VIP library of image processing functions has been designed to enable users to create their own image processing programs very quickly and simply using a toolkit of standardized library functions. The library includes functions in the following categories:

The VIP image data structure supports a wide variety of image types ranging from a basic 8 bit grey level representation through to complex valued and colour images. New image types can be easily added without `breaking' the existing software. An additional feature of the VIP image data structure that distinguishes it from other image structures is its provision for comprehensive camera calibration data and lens distortion parameters. The VIP system provides support for reconstruction of 3D information from images via structured light and stereo. The VIP System is designed to run under Unix on DEC Alpha, Sun Sparc Machines and PC's running LINUX, a subset of VIP is also available to run under DOS.

The VIP IMAGE Structure

Central to any image processing system is the image data structure used. The VIP IMAGE structure supports a wide variety of image types ranging from a basic 8 bit grey level representation through to complex valued and colour images. This is achieved by using a union structure to point to the actual image data. This union structure consists of pointers to all the different types of image data elements that are supported. As pointers to all data types are the same size any number of new pointers to new data types can be added to the image pointer union without affecting the existing system. Thus new image types can be added easily without `breaking' the system. When accessing image data, simply choosing the appropriate element from the image pointer union will result in the correct pointer arithmetic occurring. An additional feature of the VIP image data structure that distinguishes it from other image structures is its provision for comprehensive camera calibration data and lens distortion parameters. The VIP system provides support for reconstruction of 3D information from images via structured light and stereo. To aid portability the data structures have been designed to have all elements aligned with word boundaries so that the different packing characteristics of different machines would not be an issue. It is assumed that binary files are stored in big-endian format (byte reversed order), this is the natural format produced by Sun SPARC machines. VIP libraries compiled for little-endian machines (DEC Alpha and PC's) will perform byte-reversal of image data when reading so that it can be interpreted correctly, and then when writing data out, will also perform byte-reversal to ensure consistency of binary data files. Unfortunately this does, of course, involve some loss of efficiency. The image types currently available under VIP are: BYTETYPE An unsigned 8 bit grey level image with values ranging from 0 to 255. SHORTTYPE Signed 16 bit grey level image. LONGTYPE Signed 32 bit grey level image. FLOATTYPE 32 bit floating point valued image. DOUBLETYPE 64 bit floating point valued image. COMPLEXTYPE Complex valued image, real and imaginary components each represented by a 32 bit floating point value. RGBTYPE Colour image represented by red, green and blue components, each component represented by an 8 bit unsigned values. HSITYPE Colour image represented by hue, saturation and intensity components, each component represented by an 8 bit unsigned values. Where appropriate (and where it makes sense) the VIP image processing libraries will in most cases allow different image types to be used and/or mixed in a seamless manner.

Conventions

VIP function names start with capitals, multiple words within a function name are separated by underscores and each word starts with a capital, eg. Allocate_Image. VIP data types and VIP global variables are in capitals. All error messages are reported via VIP_Error_Msg (in vipio.c). The success or otherwise of the execution of a function is indicated by the return of either `OK' (1) or `ERROR' (0). Functions that return addresses return NULL on failure. In general VIP functions should check to see if an input image is valid (non-NULL pointer and correct ID code). If an input image is not valid the function will report the error and exit returning a NULL image pointer. Thus if an error occurs early in a sequence of function calls in a program one will simply cascade harmlessly through the other function calls before terminating. The idea here being to avoid having to embed large numbers of error trapping calls in one's code, thus making it much easier to read. Accordingly it is good practice to initialise all image pointers to NULL. If any image pointer is passed to a function, and that pointer has never had any image data assigned to it, the receiving function can detect this as its value will be NULL. Also, the function Free_Image does not attempt to free memory if it is passed a NULL pointer. This is important if one is to cascade safely through a sequence of function calls if an error occurs as described above. Any image processing function should not destroy or overwrite its input image(s). The result should be placed in a new image, with the address of the new image usually being returned by the function. Generally, each image processing function contains a series of CASE statements, indexed by the image type, containing code to process the different types of images available under VIP. For example a thresholding function could operate on BYTETYPE, SHORTTYPE, FLOATTYPE and other images using this mechanism. There is no requirement that functions cater for all image types, and in many cases they will only support BYTETYPE images. Each function will test for validity of the image type and return an error message if it does not support the particular image input type. It is assumed that as people find functions that do not support an image type that they need they will add the appropriate code to these functions (and update the documentation!).

Error Reporting

A flexible system exists for the reporting of errors. Different types of programs have different needs for error reporting. Command line programs simply want messages printed on the screen, windows based programs want messages to be displayed in alert boxes and any long running program may want errors to be recorded in a log file. All of these needs can be accommodated in the VIP system. All error messages are reported via the function VIP_Error_Msg (in vipio.c). This function allows error messages to be directed to up to three different locations depending on the needs of the user. The three different (globally accessible) locations are: VIP_STD_ERR The default value of this is stderr, but it can be assigned to any file pointer. VIP_LOG_FILE A file pointer, default value is NULL. VIP_MESSAGE A character array. Error messages are always copied into this array. This string can then be displayed in an alert box in any windows based program.

Writing Programs and Functions that call VIP Libraries

Writing programs and functions that use VIP library functions is relatively straightforward. Indeed the aim of VIP has been to make the construction of image processing functions and programs as quick and simple as possible. Programs, even image processing ones, generally spend far more time being written and debugged than they do actually running. A convention that has been adopted in VIP is that all image processing functions do not destroy or overwrite their input image(s). Memory for a new image is always allocated and the result placed there. The address of the new image is usually returned by the function. While this can have some penalty in speed and certainly in memory usage it results in programs having a simple and consistant structure. Adopting this convention simplifies cases where one wants to mix images of different types. Also, in many cases one does not want the type of the output image to be the same as that of the input image, for example, the square of a BYTETYPE image will produce values outside of the range 0-255, it makes sense to return an integer or floating point valued image. Similarily when convolving an image with a first or second derivative mask the results will contain negative values and again one would want to return a signed integer or floating point valued image. To minimize the time spent tracking down bugs VIP incorporates some error checking. One of the most common problems is that illegal memory access where one mistakenly tries to access locations outside the image bounds. VIP images incorporate memory sentinel values at the start and the end of the image data. A function, Image_OK, can be called by users to check the validity of image data at any time. This function checks that the image pointer is not NULL, checks that it has the appropriate idcode for an image and checks that the memory sentinel values have not been corrupted (indicating one has written data beyond the bounds of the image). This function is called by all VIP functions prior to any processing of images to ensure errors of this sort are trapped as soon as possible.

A Sample Function

The following function performs a homomorphic filtering operation on an image. This is an image enhancing process that attempts to reduce the effects of low frequency lighting variations across an image, yet at the same time accentuating high frequency intensity variations to highlight the detail (see Gonzalez and Woods {\em ``Digital Image Processing''} p. 213 for more detail). The steps involved in this process are:

You should note the following:

/*- Homomorphic ------------------------------------------------
Function to perform homomorphic filtering on an image. An image
enhancing process that attempts to reduce the effects of low frequency
lighting variations across an image, yet at the same time accentuating
high frequency intensity variations to highlight the detail.
Reference: Gonzalez and Woods "Digital Image Processing" page 213.
Peter Kovesi  January 1994
input: image    - input image.
       LowGain  - gain factor for low frequencies (suggest 0.5).
       HighGain - gain factor for high frequencies (suggest 2.0).
       CutOff   - frequency at which transition from LowGain to
                  HighGain occurs (suggest 0.4).
       order    - order of Butterworth type filter (suggest 1)
       lHistogramCut - percentage of low end of histogram to
                       truncate (suggest 1).
       uHistogramCut - percentage of high end of histogram to
                       truncate (suggest 5).
Function returns filtered image.
------------------------------------------------------------------*/
IMAGE  *Homomorphic(IMAGE * image, double LowGain, double HighGain,
            double CutOff, int order, int lHistogramCut, int uHistogramCut)
{
    IMAGE  *t1 = NULL, *t2 = NULL, *t3 = NULL, *t4 = NULL, *t5 = NULL,
           *t6 = NULL, *t7 = NULL;
    IMAGE  *outimage = NULL, *filter = NULL;
    int     r, c;
    t1 = Log_Image(image);
    t2 = FFT_Image(t1, 0);
    Free_Image(t1);
    filter = Make_Homomorphic_Filter(t2->rows, t2->cols, CutOff, LowGain,
	HighGain, order);
    t3 = Multiply_Image(t2, filter);
    Free_Image(t2);
    Free_Image(filter);
    t4 = IFFT_Image(t3, 0);
    Free_Image(t3);
    if(!t4) {
      VIP_Error_Msg("Homomorphic: An error occurred during a function call");
      return(NULL);
    }
/* Extract real part of image */
    t5 = Allocate_Image(0, 0, t4->rows, t4->cols, FLOATTYPE);
    for (r = 0; r < t4->rows; r++)
        for (c = 0; c < t4->cols; c++)
            t5->i.f[r][c] = t4->i.cx[r][c].r;
    Free_Image(t4);
    t6 = Exp_Image(t5);
    Free_Image(t5);
/* Remove outlying values of image by truncating top and lower ends of
the image histogram by HistogramCut percent */
    t7 = Truncate_Image_Histogram(t6, lHistogramCut, uHistogramCut);
    Free_Image(t6);
    outimage = Float2Byte_Image_X(t7);
    Free_Image(t7);
    if(!outimage)
      VIP_Error_Msg(``Homomorphic: An error occurred during a function call'');
    return (outimage);
}