MIN-Fakultät
Fachbereich Informatik
Szenenanalyse und Visualisierung (SAV)

Bildverarbeitung mit PLT Scheme und der VIGRA = VIGRAPLT

Aufbau der Schnittstelle

Da es mit PLT Scheme seit Version 4.0 leicht möglich ist, sogenannten "Foreign-Code", also Code der nicht mit Scheme selbst geschrieben wurde zu laden, wird diese Schnittstelle (das Foreign-Funktion-Interface: FFI) im Rahmen der VIGRAPLT ausgenutzt. Diese ermöglicht es, C-konforme Shared Libraries (unter Windows: DLLs, unter MacOSX: dylibs) dynamisch zur Laufzeit an Lisp zu binden, so dass die enthaltenen Funktionen benutzt werden können.
Da die VIGRA allerings nur für Import- bzw. Export von Bildern eine Shared Library anbietet, musste als erste Zwischenstufe ein C-Wrapper für die VIGRA-Funktionen geschrieben werden (VIGRA_C), die innerhalb der Scheme Umgebung zur Verfügung stehen sollen. An diese dynamische C-Biblitohek werden dann die entsprechenden Scheme Funktionen gebunden, die den Aufruf vor dem Benutzer verschatten.

Verwendete Datenstrukturen

Durch die Anbindung der Datenstrukturen an die C-Schnittstelle, sollte möglichst wenig Overhead entstehen. So sollte ein Bild auch nur ein Mal im Speicher vorhanden sein, und nicht etwa doppelt, um es an die C-Schnittstelle in einer geeigneten Form (kopiert) weiterzugeben. Daher werden in diesem Kapitel die neuen Datenstrukturen beschrieben, die mit der VigraPLT in Scheme eingeführt werden.

Repräsentation von Bildern

Die Repräsentation eines Bildes in dieser Erweiterung ist durch eine Liste von Bändern (Farbkanälen) gegeben. Jedes einzelne Band beruht wiederum intern auf einem "cvector" vom Typ "float", da dieser eine einfache Übergabe an die C-Schnittstelle bietet. Leider ist dieser aber nur eindimensional definiert, weshalb er in der Datei "vigraplt.carray.ss" zunächst auf n Dimensionen erweitert wurde.
Diese Erweiterung ist deshalb wichtig, weil wir ein Bild als zweidimensionalen Datentyp beschreiben möchten, der in der Lage ist, für jeden Pixel einen float (Gleitkommazahl) Wert zu speichern. Das n-dimensionale "carray" ist für den praktischen Umgang mit Bildern unwichtig, da es spezielle Funktionen für Bilder gibt, welche sich in der Datei "vigraplt.helpers.ss" finden.

Repräsentation von Matrizen

Die Repräsentation für Matrizen wird zunächst nur für eine einzige Funktion der VigraPLT benötigt, nämlich die affine Transformation eines Bildes. Dennoch ist diese Erweiterung ist deshalb wichtig, um genau diese Funktion benutzbar zu machen. Matrizen werden genauso wie Bilder repräsentiert, mit dem einzigen Unterschied, dass sie Gleitkommazahlen mit doppelter Genauigkeit als Wertebereich verwenden. Dies bietet sich an, um die Rechengenauigkeit zu erhöhen. Außerdem sind Matrizen meist deutlich "kleiner" als Bilder, weshalb dies für diesen Fall beim Speicherverbrauch in einem akzeptablem Rahmen bleibt. Die Funktionen orientieren sich ebenfalls an denen die für Bilder zur Verfügung stehen.

Die folgende Tabelle zeigt noch einmal übersichtlich alle Funktionsnamen, die diese Schnittstelle PLT Scheme über die VIGRA_C bereitstellt:

vigraplt_logo

vigraplt.impex

vigraplt.imgproc

vigraplt.filters

vigraplt.segmentation

vigraplt.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))

Außerdem gibt es noch in Scheme geschriebene Hilfsfunktionen, die den Umgang mit Bildern in der funktionalen Programmierung erleichtern sollen:

vigraplt.helpers

Image

Array

Matrix

Construction:make-image

Accessors: image-data, image-width, image-height, image-ref, image-set!

Conversion: copy-image,image->list, list->image

Functional support: image-map, image-map!, image-reduce, image-for-each-index

Construction:make-array

Accessors: array-data, array-width, array-height, array-ref, array-set!

Conversion: copy-array,array->list, list->array

Functional support: array-map, array-map!, array-reduce, array-for-each-index

Construction: make-matrix

Accessors: matrix-data, matrix-rows, matrix-cols, matrix-ref, matrix-set!

Conversion: copy-matrix,matrix->list, list->matrix

Functions: matrix-mult

Anwendungsbeispiele

Einbindung der VIGRAPLT in PLT Scheme (dafür muss die VIGRAPLT im "collects" Verzeichnis liegen):

> (require vigraplt/vigraplt)

Anschließend kann man zum Beispiel ein beliebiges Bild laden (hier: "blox.gif"):

> (define img (loadimage  (build-path vigraplt-path "blox.gif")))

Das Bild mit einem Gaussfilter mit sigma=3 glätten und das geglättete Bild in img2 ablegen:

> (define img2 (gsmooth img 3.0))

Das geglättete Bild in den diskretisierten Frequenzraum überführen:

> (define img3 (fouriertransform img2))

Mit den Bild-Hilfsfunktionen lässt sich z.B. leicht ein Schwellenwert-Algorithmus schreiben:

> (define (threshold image t)  
         (image-map (lambda (x) (if (> x t)  1.0  0.0))
                    image))

Auch ein Bild anhand einer Bildmaske auszuschneiden ist schnell mit den Bild-Hilfsfunktionen zu erreichen:

> (define (mask_image image mask)  
         (image-map (lambda (value mask) (if (> mask 0.0)  value  0.0))
                    image
                    mask))

Download & Installation

Aktuelle Version 0.5.0

Das aktuelle Paket (Version 0.5.0) kann hier heruntergeladen werden. Es beinhaltet im Ordner vigraplt die VIGRAPLT Anbindung und im Unterordner vigra_c die nötigen VIGRA_C Dateien (siehe oben).Dieses Paket beinhaltet nicht die VIGRA! Diese muss bereits auf dem System installiert sein.
Außerdem ist noch das Referenzhandbuch für Version 0.5.0 als PDF verfügbar (OpenOffice Document-Format, HMTL-Format, Alle Formate und Beispiele als ZIP). Es beinhaltet eine ausführliche Beschreibung der Verfahren und weitere Beispiele (Hello Image-Beispiel, Filter-Beispiel, Segmentierungs-Beispiel).

Installationshinweise für MacOS X:

Erstellen der dynamischen Bibliothek (libvigra_c.dylib)
Dazu muss das Makefile im Unterordner vigra_c ausgeführt werden. Nach erfolgreichem Aufruf von "make" und anschließend "make install" sollten zwei Dateien "libvigra_c.dylib" "libvigra_c.so" im VIGRAPLT-Verzeichnis befinden. Anschließend muss noch das vigraplt Verszeichnis in das PLT Scheme "collects" Verzeichnis gelinkt werden, damit das oben angegebene "require" in PLT Scheme funktioniert.

Installationshinweise für Linux:

Erstellen der dynamischen Bibliothek (libvigra_c.so)

  1. Das Makefile im Ordner "vigraplt/vigra_c" so anpassen, dass der Pfad zur VIGRA korrekt gesetzt ist.
  2. make linux
  3. make install
  4. Anschließend muss noch das vigraplt Verszeichnis in das PLT Scheme "collects" Verzeichnis gelinkt werden, damit das oben angegebene "require" in PLT Scheme funktioniert.

Installationshinweise für Windows:

Entweder die vorkompilierte Version hier herunterladen und die enthaltene "vigraimpex.dll" in das Windows System-Verzeichnis kopieren (z.B. Windows\System32) oder

Erstellen der dynamischen Bibliothek (vigra_c.dll)
Dazu befindet sich im Unterordner "vigra_c\win32-msvc2005" ein Visual Studio Projekt. Hier müssen eventuell noch die Pfade, die zur VIGRA führen, angepasst werden. Danach kann man mit "Projekt erstellen" die DLL erzeugen. Nach erfolgreichem Aufruf sollte sich eine Datei namens "vigra_c.dll" im Release-Verzeichnis befinden. Diese muss nun noch ins "vigraplt" Verzeichnis kopiert werden. Anschließend muss noch das vigraplt Verszeichnis in das PLT Scheme "collects" Verzeichnis gelinkt werden, damit das oben angegebene "require" in PLT Scheme funktioniert.

Ältere Versionen

Bekannte Bugs der VIGRAPLT:

Leider hat sich einer kleiner Bug in die VIGRAPLT eingeschlichen, der mit der nächsten Version behoben werden wird. Bis dahin kann man den Bug selbst fixen, indem man in der Datei "vigraplt.helpers.ss" die Funktion list->image wie folgt ändert:

50:    ; list -> image conversion 
51:    (define (list->image lst)
52:      (list->carray lst _float))

Der gleiche Bug betrifft auch die Matrix zu Listen Konvertierungsfunktionen in derselben Datei:

156:    ; list -> matrix conversion 
157:    (define (list->matrix lst)
158:      (list->carray lst _double))

Außerdem führt die labelimage-Funktion eine Komponentennummerierung auf Grund der 8er-Zusammenhangskomponenten durch, und benutzt somit nicht wie im Handbuch beschrieben den 4er-Zusammenhang!

Das ältere Paket (Version 0.1.0) kann hier heruntergeladen werden. Es beinhaltet im Ordner vigraplt die VIGRAPLT Anbindung und im Unterordner vigra_c die nötigen VIGRA_C Dateien (siehe oben).
Außerdem ist noch das Referenzhandbuch für Version 0.1.0 verfügbar. Es beinhaltet eine ausführliche Beschreibung der Verfahren und weitere Beispiele.Dieses Paket beinhaltet nicht die VIGRA! Diese muss bereits auf dem System installiert sein.

Installationshinweise für MacOS X:

Erstellen der dynamischen Bibliothek (vigra_c.dylib)
Dazu muss das Makefile im Unterordner vigra_c ausgeführt werden. Nach erfolgreichem Aufruf sollte sich eine Datei namens "vigra_c.dylib" im VIGRAPLT-Verzeichnis befinden. Anschließend muss noch das vigraplt Verszeichnis in das PLT Scheme "collects" Verzeichnis gelinkt werden, damit das oben angegebene "require" in PLT Scheme funktioniert.

Installationshinweise für Linux:

Erstellen der dynamischen Bibliothek (vigra_c.so)
Das Erstellen einer Linux-Bibliothek wird zur Zeit noch nicht direkt unterstützt, es sollte jedoch kein Problem sein die Anpassungen zu tun, die dafür nötig sind:

  1. Das Makefile im Ordner "vigraplt/vigra_c" so anpassen, dass ein C-kompatibles shared object file im Ordner vigraplt erzeugt wird.
  2. Die vigraplt.cl Datei musss nun nur noch so angepasst werden, dass sie auch nach dieser Datei sucht, falls das Betriebssystem ein Linux ist. Dies müsste in Zeile 2-4 ergänzt werden.
  3. Anschließend muss noch das vigraplt Verszeichnis in das PLT Scheme "collects" Verzeichnis gelinkt werden, damit das oben angegebene "require" in PLT Scheme funktioniert.

Installationshinweise für Windows:

Entweder die vorkompilierte Version hier herunterladen oder

Erstellen der dynamischen Bibliothek (vigra_c.dll)
Dazu befindet sich im Unterordner "vigra_c\win32-msvc2005" ein Visual Studio Projekt. Hier müssen eventuell noch die Pfade, die zur VIGRA führen, angepasst werden. Danach kann man mit "Projekt erstellen" die DLL erzeugen. Nach erfolgreichem Aufruf sollte sich eine Datei namens "vigra_c.dll" im Release-Verzeichnis befinden. Diese muss nun noch ins "vigraplt" Verzeichnis kopiert werden. Anschließend muss noch das vigraplt Verszeichnis in das PLT Scheme "collects" Verzeichnis gelinkt werden, damit das oben angegebene "require" in PLT Scheme funktioniert.

Weitere Meilensteine:

  • Einbindung weiterer VIGRA-Funktionen