Summary


Introduction

This part of our site will deal with image processing. After a short introduction to common methods, we will present the program Qlisp. You will find concrete examples at the end of this chapter.

In image analysis, we distinguish two different theories: Mathematical morphology and signal processing.

We think that an advantage for industrial control is the non-linearity of morphological functions. Starting from the original image, you eliminate - with each transformation - useless information by keeping the features that you want to extract.

In other fields, however, like the visual improvement of images, the description of contours or compression, the methods of signal processing are incontestably better adapted.

The examples at the end of this section will show you typical applications for mathematical morphology and for signal processing. But initially, we would like to present you the tool that we use for image processing.

Top


Image analysis with Qlisp

The first version of Qlisp was programmed in 1991 on the image processing station Q570 of Cambridge Instruments: We combined the library of the Q570 with the Lisp interpreter. The PhD thesis "Morphologie Mathématique Appliquée au Contrôle Industriel de Pièces Coulées, T. Jochems, School of Mines, Paris" describes the design and the use of this version.

The fast growth of computers' power was the basis of a second version. The transformations carried out electronically on the Q570 were replaced by functions coded in C. Programmed on an Alpha station of DEC, Qlisp is used from now on for teaching artificial vision at the Engineering School IMERIR, Perpignan.

Since then, the system has been widening continuously and has the following features today:

Top


Industrial use

For industrial applications, the routines of image analysis are often used in a specific data-processing environment, which ensures the stability and the coherence of these applications. For this reason, we decided to split up Qlisp in two distinct parts:

The advantage of this approach is that you can initially develop and test applications with the Lisp interpreter. This decreases appreciably the length of this period. As a second step, you can export the resulting prototype to your industrial application.

Here is the list of C routines that you dispose of after having downloaded Qlisp.

Fichier

Fonctions

intern.cpp

extern void imainit();
extern int  newimage(int x,int y,int w,int h,int depth);
extern void freeimage(int id);
extern void binset(int id,int val);
extern void greyset(int id,int val);
extern void colset(int id,int val);
extern void convert(int ima_in,int ima_out);
extern void frames(int x,int y,int w,int h);
extern void iframe(int x,int y,int w,int h);
extern void mframe(int x,int y,int w,int h);

base.cpp

extern int  binrpix(int id,int x,int y);
extern int  greyrpix(int id,int x,int y);
extern int  colrpix(int id,int x,int y);
extern void binwpix(int id,int x,int y,int val);
extern void greywpix(int id,int x,int y,int val);
extern void colwpix(int id,int x,int y,int val);
extern void binwline(int id,int x1,int y1,int x2,int y2,int val);
extern void greywline(int id,int x1,int y1,int x2,int y2,int al);
extern void colwline(int id,int x1,int y1,int x2,int y2,int val);
extern void binbord(int binout,int val,int x,int y,int w,int h);
extern void greybord(int ginout,int val,int x,int y,int w,int h);
extern void colbord(int cinout,int val,int x,int y,int w,int h);
extern void bincopy(int bin,int bout);
extern void greycopy(int gin,int gout);
extern void colcopy(int gin,int gout);
extern void binshift(int bin,int bout,int dx,int dy);
extern void greyshift(int gin,int gout,int dx,int dy);
extern void colshift(int cin,int cout,int dx,int dy);
extern void binzoom(int bin,int bout,float zx,float zy);
extern void greyzoom(int gin,int gout,float zx,float zy);
extern void colzoom(int cin,int cout,float zx,float zy);
extern void greyzoombil(int gin,int gout,float zx,float zy);
extern void colzoombil(int cin,int cout,float zx,float zy);
extern void binrot90(int bin,int bout,int dir);
extern void greyrot90(int gin,int gout,int dir);
extern void colrot90(int cin,int cout,int dir);
extern void binrot(int bin,int bout,float angle);
extern void greyrot(int gin,int gout,float angle);
extern void colrot(int cin,int cout,float angle);
extern void greyrotbil(int gin,int gout,float angle);
extern void colrotbil(int cin,int cout,float angle);
extern void greyadd(int gin,int ginout,int type);
extern void greyaddl(int gin,int ginout,int type);
extern void greysub(int gin,int ginout,int type);
extern void greysubl(int gin,int ginout,int type);
extern void coladd(int cin,int cinout,int type);
extern void coladdl(int cin,int cinout,int type);
extern void colsub(int cin,int cinout,int type);
extern void colsubl(int cin,int cinout,int type);
extern void greymultl(int gin,int ginout,int fact,int type);
extern void greydiv(int gin,int ginout,int fact,int type);
extern void colmultl(int cin,int cinout,int fact,int type);
extern void coldiv(int cin,int cinout,int fact,int type);
extern void binsup(int bin,int binout);
extern void bininf(int bin,int binout);
extern void greysup(int gin,int ginout);
extern void greyinf(int gin,int ginout);
extern void colsup(int cin,int cinout);
extern void colinf(int cin,int cinout);
extern void greymask(int gin,int bin,int ginout,int type);
extern void colmask(int cin,int bin,int cinout,int type);
extern void greycombine(float c1,int gin,float c2,int ginout);
extern void colcombine(float c1,int cin,float c2,int cinout);

trans.cpp

extern void bingrey(int bin,int gout);
extern void greybin(int gin,int bout);
extern void thresh(int gin,int bout,int lo,int hi);
extern int  fpoint(int bin,int *x,int *y);
extern void bininvert(int binout);
extern void greyinvert(int ginout);
extern void colinvert(int cinout);
extern void bininfnbh(int bin,int tmp,int bout,int se);
extern void binsupnbh(int bin,int tmp,int bout,int se);
extern void greysupnbh(int gin,int gout,int se);
extern void greyinfnbh(int gin,int gout,int se);
extern void greylindilation(int gin,int gout,float angle,int size);
extern void greylinerosion(int gin,int gout,float angle,int size);
extern void anamorph(int ginout,uchar *lut);
extern void bitmap(int gin,int bout,int ds);
extern void distance(int inout,int outside);
extern void getsample(gin,...);
extern void median(int gin,int gout,int size);

queue.cpp

extern void qinit();
extern int  label(int gout,int gmask,uint gmax);
extern void binbuild(int ginout,int gmask);
extern void greybuild(int ginout,int gmask);
extern void watershed(int ginout,int mask);
extern void thinqueue();

measure.cpp

extern void greymeas(int id,int *min,int *max,double *mean);
extern int  binsum(int bin);
extern int  greysum(int gin);
extern void histogram(int gin,int *pi);
extern void f_fpoint(int label,int *buffer);
extern void f_mpoint(int label,int *buffer);
extern void f_rect(int label,int *buffer);
extern void f_area(int label,int *buffer);
extern void f_volume(int label,int ima,int *buffer);
extern void f_grey(int label,int ima,int *buffer);

signal.cpp

extern void convh(int gin,int gout,...);
extern void conv(int gin,int gout,...);
extern void rech(int gin,int gout,...);
extern void fcenter(int gout);
extern void butter(int gout,int d,int n);
extern void conveuler(int gin,int ain,int reel,int imag,float k);
extern void convbackeuler(int reel,int imag,int gout,int aout,float k);
extern void multdiv(int gin,int ain,int reel,int imag,int what,float k);
extern void ft(int gin,int ain,int gout,int aout,int dir,float fact);
extern void fft(int reel,int imag,int dir);
extern void real(int gin,int ain,int gout,int mode);
extern void imaginary(int gin,int ain,int gout,int mode);

io.cpp

extern void loadcamera(char *name);
extern void freecamera();
extern bool cameraok();
extern char*(*camerror)();
extern bool (*caminit)(char *args);
extern void (*camfree)(void);
extern bool (*camsnap)(int camera,char *options);
extern bool (*camreadheader)(int *x,int *y,int *w,int *h,...);
extern bool (*camreaddata)(uchar *data);
extern bool (*camlut) (uchar lut[256]);
extern void loadfilter(char *name);
extern void freefilter();
extern bool filterok();
extern char*(*filtererror)();
extern bool (*filterfopen)(char *name,bool write);
extern void (*filterfclose)();
extern bool (*filterreadheader)(int *x,int *y,int *w,int *h,...);
extern bool (*filterreaddata)(uchar* data);
extern bool (*filterwriteheader)(int x,int y,int w,int h,...);
extern bool (*filterwritedata)(uchar* data);

color.cpp

extern void colgrey(int col, int red, int green, int blue);
extern void greycol(int red, int green, int blue, int col);
extern void rgbihs(int rgb,int ihs);
extern void ihsrgb(int ihs,int rgb);
extern void intensity(int rgb,int grey);

Top


Suitability for teaching

We use Qlisp for teaching image analysis. Its hierarchical structure, explained in the next figure, is the main reason for its good suitability for education.

pyramid

In the lowest layer, the functions are coded in C because of the speed of this language. There is no pedagogical interest for beginners in image analysis to realize these functions, the time required being too long.

In the Lisp layer, the basic functions can be combined to obtain new, more complex and more powerful methods. This property of Qlisp is well adapted to mathematical morphology: An erosion of size n, for example, is calculated by applying n times an erosion of size 1 (decomposition of the structuring element); an opening is defined as an erosion followed by a dilation with the transposed structuring element. The following table shows the coding of three new transformations. The functional character of Lisp simplifies programming.

Function

Coding in Lisp

geodesic dilation

(defun gdsdilation(ima mask se size)
  (dotimes(i size ima)
    (setq ima (inf
      (dilation ima se 1)
      mask))))

morphological opening

(defun opening(ima se size)
  (dilation
    (erosion ima se size)
    (transpose se) size))

gradient

(defun gradient(ima &key (se se-c) (size 1))
  (sub
    (dilation ima se size)
    (erosion ima se size)))

The participants of the courses work on the Lisp layer and in this way put the theory into practice. In the current system, more than 100 transformations are defined in Lisp.

In the application layer, you can finally solve real and complex problems while using the basic library and the transformations coded in Lisp. In the following chapter, we will show three examples, which are also treated in our courses.

Top


Examples

In this chapter, we will illustrate the various approaches of image analysis with some examples. All results are calculated with the Qlisp system.

Line extraction

This example shows line detection on a metal sheet. It was studied at the ENSMP by A. Tuzikov for the Belgian company OCAS.

Image (1) shows a metal sheet (25x25 mm) on which black lines have been traced. The interest is the automatic detection of these lines after deforming the sheet by pressure. The data thus obtained is used to optimize the tool of deformation.

original

opening

binary image

1) original

2) opening

3) threshold

binary filtering

result

4) binary filter

5) result

The treatment starts with a noise filter (2). A "top hat" eliminates then the effect of heterogeneous lighting. A consecutive threshold produces image (3). A binary filtering of noise (4) and a "skeleton by influence zone" finish the treatment. The result is shown in image (5).

This example shows well the philosophy of morphological filtering: You remove more and more information (noise, gray-levels, size) by keeping only the desired features.

Top


Restoring a blurred image

This example shows an application of signal processing. Image (1) presents the original image captured by a camera, which has a defect in the video amplifier. Although we simulated this defect, it could be a real problem, see Apollo or Hubble...

original

impulse reponse

1) original

2) characteristics

fft

result

3) spectrum

4) result

We need a description of the defect. In our case, we acquire the image (2) with only one lit-up central point. This image thus represents the impulse response of the defective camera. We calculate then the spectrum (3) of image (1) and the spectrum of the impulse response. We finish by dividing these spectra and applying the inverse Fourier transformation. The result (4) is not fuzzy any more. Signal processing needs a lot of computing time: 85ms for this example.

Top


Recognition of filigrees

This example shows the recognition of filigrees. It was resolved in a school project by a group of 4 students at the Engineering School IMERIR.

original

first treatment

1) original

2) amplified contrast

sample

result

3) sample

4) result

Image (1) shows the filigrees acquired by a black-and-white camera. The first step consists in improving and stabilizing the contrast of this image. We use a "top hat" and "histogram imposing " and get the result (2). Here we will seek a sample (3), which shows a characteristic part of the filigree. This image was stored before in a database. The result (4) illustrates that the sample is detected 4 times in the original image. The recognition of the sample is carried out by an accelerated correlation between the images (2) and (3), the processing time is 25ms for the complete process.

Top


Testing Qlisp

Perhaps you would like to test yourself the image analysis transformations. You could download Qlisp and test at home the examples contained in this program. And you could try to treat your own images.

Presentation      Top      Download