MIN-Faculty
Department of Informatics
Scene analysis and visualization (SAV)

Digital image processing using Allegro Common Lisp and VIGRA = VIGRACL

Description of the interface

Allegro Common Lisp and Ansi Commmon Lisp make it quite easy to add so-called "Foreign-Code", that is program code that is not written with LISP itself. That is why we have chosen this interface (called Foreign-Funktion-Interface: FFI) for the VIGRACL. With the FFI you can add the algorithms of C-conform dynamic libraries (e.g. under Windows: DLLs, under MacOSX: dylibs) to your LISP program at runtime and use them right out-of-the-box. Obviously we connect Common Lisp to the VIGRA_C library as the VIGRA itself does not offer a dynamic C-library containing all algorithms. We also hide the low-level calls from the user in that way, that the user can only see the tiny LISP functions and does not have to care about conversion to pointers or memory allocation.

Datastructures

Another important question is the representation of an image inside the LISP environment. We have chosen lists of the built-in type array (of course the two-dimensional one), where the first dimension is of [0...width-1] and the second dimension is of [0...height-1]. Every array is of element type 'float' and denotes a specific image-band. These bands are ordered '(R G B) for colour images and '(G) for grayscale images.
The following table lists all functions, that are offered by the VIGRACL. Please note that the functions named '-band' wor band-wise (can be applied to arrays) whereas the other functions can directly be used for images.

vigracl_logo

vigracl.impex

vigracl.imgproc

vigracl.filters

vigracl.segmentation

vigracl.morphology

loadimage

saveimage

resizeimage-band

resizeimage

rotateimage-band

rotateimage

affinewarpimage-band

affinewarpimage

reflectimage-band

reflectimage

fouriertransform-band

fouriertransform

convolveimage-band

convolveimage

separableconvolveimage-band

separableconvolveimage

gsmooth-band

gsmooth

gaussiangradient-band

gaussiangradient

ggradient-band

ggradient

laplacianofgaussian-band

laplacianofgaussian

gsharpening-band

gsharpening

sharpening-band

sharpening

nonlineardiffusion-band

nonlineardiffusion

distancetransform-band

distancetransform

labelimage-band

labelimage

watersheds-band

watersheds

cannyedgeimage-band

cannyedgeimage

differenceofexponentialedgeimage-band

differenceofexponentialedgeimage

regionimagetocrackedgeimage-band

regionimagetocrackedgeimage

erodeimage-band

erodeimage

dilateimage-band

dilateimage

openingimage-band = (dilateimage-band (erodeimage-band band))

openingimage = (dilateimage (erodeimage img))

closingimage-band = (erodeimage-band (dilateimage-band band))

closingimage = (erodeimage (dilateimage img))

Beside these bound functions, there are some more funktions that will make functional digital image processing a lot easier:

vigracl.helpers

:array-map

array-map!

array-reduce

array-for-each-index

image-map

image-map!

image-reduce

image-for-each-index-array

Examples

Embedding the VIGRACL into Allegro Common Lisp (Common Lisp must know where th path of VIGRACL therefore):

CL-USER> (load "vigracl.cl")

Afterwards you may want to load an image (here: "blox.gif"):

CL-USER> (setq img (vigracl.impex:loadimage  "blox.gif"))

Since version 0.3.0 we can change into the VIGRACL-package and then call all the functions without the package-prefix:
From this point on, we assume that you use a version >= 0.3.0. If not, the package names have to be written in front of each function call again

CL-USER> (in-package :vigracl)
#<The VIGRACL package>
VIGRACL> (setq img (loadimage  "blox.gif"))

Smoothing the image with a Gaussian filter of sigma=3 save the result to img2:

VIGRACL> (setq img2 (gsmooth img 3))

Convert the smoothed image from image domain to frequency space using the FFT:

VIGRACL> (setq img3 (fouriertransform img2))

Applying the wassershed-transform to the gradient magnitude image (Gaussian Gradient filter, sigma=1) of a resized image (to: 500x500 pixel):

VIGRACL> (setq img4  (watersheds
                          (ggradient 
                              (resizeimage img 500 500 4)
                                  1.0)))

Implementing own image processing functions
Thresholding an image (if value of pixel >50 : 1, 0 else) and label the connected regions afterwards:

VIGRACL> (defun threshold-band (arr t)  
             (let* ((width  (array-dimension arr 0))
      		        (height (array-dimension arr 1))
                    (arr2   (make-array (array-dimensions arr)
                                  :element-type (array-element-type arr)
                                  :initial-element 0.0))
                     (foo     (do* ((j 1 (+ j 1)))
                                   ((= j (- (array-dimension arr 1) 1)))
                                   (do* ((i 1 (+ i 1)))
                                        ((= i (- (array-dimension arr 0) 1)))
                                           (if (> (aref arr i j) t)
                                               (setf (aref arr2 i j) 1.0)
                                               (setf (aref arr2 i j) 0.0))))))
                     arr2))
VIGRACL> (compile 'threshold)

VIGRACL> (setq img5  (labelimage
				(mapcar #'(lambda (arr) (threshold-band arr 50)) img)))

WARNING: If you write own functions, do not forget (compile 'function_name) ! Otherwise the execution of that algorithm may be terribly slow...

Using the new array helper functions (since Version 0.2.0), we can write the upper example like this:

VIGRACL> (defun threshold (arr t)  
                (image-map #'(lamba (x) (if (> x t) 1.0 0.0))
                           arr))
VIGRACL> (compile 'threshold)

Now you may see, how these helper functions support functional programming in digital image processing: They lead to shorter and more elegant programs!

Download & Installation

The current release (Version 0.5.0) can be downloaded here. It consists of the VIGRACL component (in folder vigracl) and of the necessary VIGRA_C files (in subfolder vigra_c) (see above for more informations).This release does not contain the VIGRA itself.

Changes to version 0.4.0:

  • Introduction of Colour-images
  • Definition of VIGRACL using Allegro's defsystem
  • Interface changed: Images are no longer defined as arrays, but as lists of arrays
  • New functions: The former array-based functions are renamed with the suffix '-band'. The new functions do now work on the new image representation (see above)
  • New functions convolveimage[-band] und separableconvolveimage[-band] zur Faltung von Bildern
  • New function gaussiangradient[-band] Computes the partial derivatives in x- and y-direction, unlike (cf. ggradient[-band]) computing the magnitude.
  • DThe examples now include colour image processing.

The old version (version 0.4.0) can be downloaded here. It consists of the VIGRACL component (in folder vigracl) and of the necessary VIGRA_C files (in subfolder vigra_c) (see above for more informations).This release does not conatain the VIGRA itself.

Changes to version 0.3.0:

  • Added new array helper functions: array-map!, array-reduce und array-for-each-index.
  • Interface changed: array-map und array-map! now have the signature (func arrays) instead of (arr func) allow to apply non-unary functions and more than one image as the standard-map for lists does.
  • Interface changed: array-map und array-map! now also work for more than one image, so array-combine was removed!
  • Interface changed: Renamed array-copy to copy-array.
  • Interface changed: The Fourier Transformation does no longer contain implicit rescaling of the image. The new signature is just (arr) instead of (arr new_width new_height)
  • New function: affinewarpimage with signature (arr affinematrix resize_mode) to perform an affine transformation of an image. AffineMatrix has to be a 3x3 array of type 'double-float.
  • New: Morphological functions erodeimage(arr), dilateimage(arr), openingimage(arr) und closingimage(arr) were introduced
  • New function: regionimagetocrackedgeimage(arr) was introduced
  • The example files ("examples.cl" und "fft_example.cl") have been adapted to work with the new functions and their signatures.

The old version (version 0.3.0) can still be downloaded here.

Changes to version 0.2.0:

  • Introduced common package environment
  • Made the example files ("examples.cl" und "fft_example.cl") caompatible to the new package environment.

The old version (version 0.2.0) can still be downloaded here.

Changes to version 0.1.0:

  • Fixed error in the Fast Fourier-Transform.
  • Added array helper functions:
    array-copy (copying of arrays)
    array-map (like map for lists but for arrays)
    array-combine (comination of two arrays)
  • Added second example file to demonstrate the use of the array helper functions and the FFT ("fft_example.cl")
  • Renamed main examples file from "example.cl" to "examples.cl".

The old version (version 0.1.0) can still be downloaded here. However, because of the errors in this version, you may not want to download this version!

Installation instructions for MacOS X:

Creating a dynamic library (vigra_c.dylib)
Just make the Makefile which is loacate at the subfolder "vigra_c". After successful make, there should be a file called "vigra_c.dylib" at the VIGRACL directory.

Installation instructions for Linux:

Creating a dynamic library (vigra_c.so)
There is currently no straightforward way for the compilation of a linux shared object. On the other hand, you should easily be able to make the necessary changes:

  1. Change the Makefile at folder "vigracl/vigra_c" to create a C-compatible (-fPIC e.g.) shared object file at folder vigracl.
  2. Change the vigracl.cl file to search for the vigra_c.so file if the platform is Linux. Therefore look at line 2-4 .

Installation instructions for Windows:

Creating a dynamic library (vigra_c.dll)
You'll find a Visual Studio Projectfile in the subfolder "vigra_c\win32-msvc2005". Please make sure to set the right paths to the VIGRA (Lib & Include!) in the projects options and then compile the projectto create the DLL file. After the compilation, you should find a file called "vigra_c.dll" inside the Release folder. Please copy this DLL into the "vigracl" folder.

Future Milestones:

  • Embedding of further VIGRA functions