Commit f3724b00 authored by Martin Horauer's avatar Martin Horauer
Browse files

restructured files and Makefiles, polished Readme.adoc

parent 50ad73df
CC=gcc
CFLAGS=-O2 -I include
SHARED=-fPIC -shared
LIBNAME=libfvs.s.o.1
FVSCFILES=export.c floatfield.c image.c imageenhance.c imagemanip.c img_base.c import.c matching.c minutia.c
FVSOBJECTS=$(FVSCFILES:.c=.o)
FVSHFILES=include/export.h include/floatfield.h include/fvs.h include/fvstypes.h include/image.h include/imagemanip.h include/img_base.h include/import.h include/matching.h include/minutia.h
CC = gcc
CFLAGS = -O2 -I include
SHARED = -fPIC -shared
LIBNAME = libfvs.s.o.1
SRCPATH = source
INCPATH = include
FVSCFILES = $(wildcard $(SRCPATH)/*.c)
FVSOBJS = $(FVSCFILES:.c=.o)
FVSHFILES = $(wildcard $(INCPATH)/*.h)
all: fvs_lib
fvs_lib: $(FVSCFILES) $(FVSOBJECTS)
$(CC) $(CFLAGS) $(SHARED) $(FVSOBJECTS) -o $(LIBNAME) -lc -lm -O `pkg-config --cflags --libs MagickCore`
fvs_lib: $(FVSCFILES) $(FVSOBJS)
$(info FVSOBJS="$(FVSOBJS)")
$(CC) $(CFLAGS) $(SHARED) $(FVSOBJS) -o $(LIBNAME) -lc -lm -O `pkg-config --cflags --libs MagickCore`
install:
echo "put me somewhere"
%.o: %.c
$(CC) -fPIC $(CFLAGS) -O `pkg-config --cflags MagickCore` -c $<
$(CC) -fPIC $(CFLAGS) -O `pkg-config --cflags MagickCore` -c $< -o $@
clean:
rm -f *.o
rm -f $(SRCPATH)/*.o
rm -f $(LIBNAME)
= Fingerprint Verification Library
The fingerprint verification software is made up by the following files.
[options="nowrap"]
----
src/import.c ............ functions to import bitmaps
src/export.c ............ functions to export bitmaps
src/image.c .............. base image functions and container classes
src/floatfield.c ........ floating point structures and functions
src/minutia.c ........... fingerprint minutia functions
src/img_base.c .......... fundamental fingerprint functions (binarization, invert, logical operations, etc.
src/imagemanip.c ........ image manipulation functions (angle, frequency, masks, thinning, etc.)
src/imageenhance.c ...... functions and algorithms to enhance image quality
src/matching.c .......... functions to compare two minutiae
include/*.h ............. header files
----
== Pre-Requisitis
The library relies on https://www.imagemagick.org/script/index.php[Imagemagick]
to handle all the low-level image manipulation funcionality.
Fedora Installation
[source=bash]
----
sudo dnf install ImageMagick-devel
----
Installation instructions for Windows, Mac OSX, other Linux distros see
https://www.imagemagick.org/script/download.php[here].
To build and make use of the `Makefile` standard C gcc compiler as well
as `pkg-config` is mandatory. In case `pkg-config` is not available use the
following option to build the library:
....
-I/usr/include/ImageMagick-6 -fopenmp -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16
....
TIP: In case you are using `clang` you will also need the usage of openMP, see
https://stackoverflow.com/questions/33357029/using-openmp-with-clang[using openMP with clang].
= Build
Simply use `make` to build a shared library.
= Howto extract fingerprint minutiae
Requires: mask & fingerprint image
The steps to extract fingerprint minutiae is made up of the following steps. The
recommended values are for the used fingerprint sensor and a regular use.
. import an image
. filter the image (soften mean) - recommended filter kernel size: 3
. normalize pixels - recommended filter kernel size 9
. add a canvas - generates a mask of fixed size to remove unusable image margins - recommended margin size 6
. calculate the _ridge_ direction - recommended parameters: 5 and 4
. logical AND of image and mask
. calculate a FFT of the image
. filter the image using a _Gabor_ filter - recommended parameter: 4.0
. create a b&w image
. thinning - reduce the ridge size to one pixel
. extended thinning
. extract of minutiae
== Task
Implement the above steps in a file `fvs_main.c`. To build, test and run the
final application you will need to link against the shared library.
....
gcc -Wall -Wextra --pedantic -lfvs fvs_main.c -o fvs
./fvs img/*.bmp
....
/*!
* \mainpage fvs_main
* \brief An application that extracts minutiae out of fingerprint bitmap
* files.
*
* (1) import an image
* (2) filter the image (soften mean)
* -> recommended filter kernel size: 3
* (3) normalize pixels
* -> recommended filter kernel size 9
* (4) add a canvas - generates a mask of fixed size to remove
* unusable image margins
* -> recommended margin size 6
* (5) calculate the _ridge_ direction
* -> recommended parameters: 5 and 4
* (6) logical AND of image and mask
* (7) calculate a FFT of the image
* (8) filter the image using a _Gabor_ filter
* -> recommended parameter: 4.0
* (9) create a b&w image
* (10) thinning - reduce the ridge size to one pixel
* (11) extended thinning
* (12) extract of minutiae
*/
int main(int argc, char *argv[])
{
// (1)
// ...
// (12)
// ...
return 0;
}
/*########################################################################
The contents of this file are subject to the Mozilla Public License
Version 1.0(the "License"); You may NOT use this file except in
compliance with the License. You may obtain a copy of the License at
http:// www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
The Initial Developer of the Original Code is Shivang Patel.
Copyright(C) 2002. All Rights Reserved.
Authors: Shivang Patel
Jaap de Haan(jdh)
Matthias Wenzl (mw)
Changes: jdh -> Added support for ImageMagick that enables
to export files to more than 40 formats.
mw -> Removed deprecated.
########################################################################*/
#include "import.h"
#include <stdio.h>
#include <string.h>
#include <magick/api.h>
/* imports a fingeprint image from a file */
FvsError_t FvsImageExport(const FvsImage_t image, const FvsString_t filename)
{
ExceptionInfo exception;
Image* magicimage;
ImageInfo* magicinfo;
FvsError_t ret = FvsOK;
FvsByte_t* buffer;
FvsInt_t pitch;
FvsInt_t height;
FvsInt_t width;
FvsInt_t i;
/* get buffer, size and pitch from the input image */
buffer = ImageGetBuffer(image);
pitch = ImageGetPitch(image);
height = ImageGetHeight(image);
width = ImageGetWidth(image);
/* Init Magick environment */
MagickCoreGenesis(".",MagickFalse);
//InitializeMagick(".");
GetExceptionInfo(&exception);
/* Create an empty imageinfo */
magicinfo = CloneImageInfo((ImageInfo*)NULL);
magicinfo->depth = 8;
/* create image */
magicimage = ConstituteImage(width, height, "I", CharPixel, buffer, &exception);
if (exception.severity!=UndefinedException)
CatchException(&exception);
if (magicimage!=(Image*)NULL)
{
/* copy the data */
for (i=0; i<height; i++)
{
ImportImagePixels(magicimage, 0, i, width, 1, "I", CharPixel,
buffer+i*pitch);
}
/* save the image to file */
(void)strcpy(magicimage->filename, filename);
magicimage->colorspace = GRAYColorspace;
magicimage->depth = 8;
WriteImage(magicinfo, magicimage);
/* dump info for debugging purposes */
/* DescribeImage(magicimage, stdout, 0); */
DestroyImage(magicimage);
}
else
ret = FvsFailure;
/* do cleanup */
DestroyImageInfo(magicinfo);
DestroyExceptionInfo(&exception);
MagickCoreTerminus();
//DestroyMagick();
return ret;
}
#if 0
/* The WAND interface is pretty buggy... use the old API */
/* exports a fingeprint image to a file */
FvsError_t FvsImageExport(const FvsImage_t image, const FvsString_t filename)
{
MagickWand* wand;
FvsByte_t* buffer;
FvsByte_t* out;
FvsInt_t pitch;
FvsInt_t height;
FvsInt_t width;
FvsError_t ret = FvsOK;
FvsInt_t i;
/* Init Magick */
wand = NewMagickWand();
if (wand!=NULL)
{
/* extract parameters */
buffer = ImageGetBuffer(image);
width = ImageGetWidth(image);
height = ImageGetHeight(image);
pitch = ImageGetPitch(image);
/* allocate a new buffer for the pixel data */
out = (FvsByte_t*)malloc(width*height);
if (out!=NULL)
{
for (i=0; i<height; i++)
memcpy(out+i*width, buffer+i*pitch, width);
/* out now contains the picture data in a contiguous buffer */
MagickSetSize(wand, width, height);
MagickSetImagePixels(wand, 0, 0, width, height, "I", CharPixel, out);
/* write data */
MagickWriteImage(wand, filename);
free(out);
}
else
ret = FvsMemory;
/* do cleanup */
DestroyMagickWand(wand);
}
else
ret = FvsMemory;
return ret;
}
#endif
/*########################################################################
*
* Copyright(C) 2002-2007. All Rights Reserved.
*
* Authors: Shivang Patel
* Jaap de Haan(jdh)
*
* Changes: jdh -> Added support for ImageMagick that enables
* to export files to more than 40 formats.
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2, or (at your option) any later
* version.
*
* This is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License with
* the fvs source package as the
* file COPYING. If not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
########################################################################*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "floatfield.h"
/*!
A fingerprint floating point field structure.
*/
typedef struct iFvsFloatField_t
{
FvsFloat_t *pimg; /* floating point field array */
FvsInt_t w; /* width of field */
FvsInt_t h; /* height of field */
FvsInt_t pitch; /* pitch */
} iFvsFloatField_t;
FvsFloatField_t FloatFieldCreate()
{
iFvsFloatField_t* p = NULL;
p = (FvsFloatField_t)malloc(sizeof(iFvsFloatField_t));
if (p!=NULL)
{
p->h = 0;
p->w = 0;
p->pitch = 0;
p->pimg = NULL;
}
return (FvsFloatField_t)p;
}
void FloatFieldDestroy(FvsFloatField_t field)
{
iFvsFloatField_t* p = NULL;
if (field==NULL)
return;
p = field;
(void)FloatFieldSetSize(field, 0, 0);
free(p);
}
FvsError_t FloatFieldSetSize(FvsFloatField_t img, const FvsInt_t width, const FvsInt_t height)
{
iFvsFloatField_t* field = (iFvsFloatField_t*)img;
FvsError_t nRet = FvsOK;
FvsInt_t newsize = (FvsInt_t)(width*height*sizeof(FvsFloat_t));
/* special case for zero size */
if (newsize==0)
{
if (field->pimg!=NULL)
{
free(field->pimg);
field->pimg = NULL;
field->w = 0;
field->h = 0;
field->pitch = 0;
}
return FvsOK;
}
if ((FvsInt_t)(field->h*field->w*sizeof(FvsFloat_t)) != newsize)
{
free(field->pimg);
field->w = 0;
field->h = 0;
field->pitch = 0;
/* This allocates the amount of memory need for the field structure */
field->pimg = (FvsFloat_t*)malloc((size_t)newsize);
}
if (field->pimg == NULL)
nRet = FvsMemory;
else
{
field->h = height;
field->w = width;
field->pitch = width;
}
return nRet;
}
FvsError_t FloatFieldCopy(FvsFloatField_t destination, const FvsFloatField_t source)
{
iFvsFloatField_t* dest = (iFvsFloatField_t*)destination;
iFvsFloatField_t* src = (iFvsFloatField_t*)source;
FvsError_t nRet = FvsOK;
nRet = FloatFieldSetSize(dest, src->w, src->h);
if (nRet==FvsOK)
memcpy(dest->pimg, src->pimg, src->h*src->w*sizeof(FvsFloat_t));
return nRet;
}
FvsError_t FloatFieldClear(FvsFloatField_t img)
{
return FloatFieldFlood(img, 0.0);
}
FvsError_t FloatFieldFlood(FvsFloatField_t img, const FvsFloat_t value)
{
iFvsFloatField_t* field = (iFvsFloatField_t*)img;
FvsError_t nRet = FvsOK;
FvsInt_t i;
if (field->pimg!=NULL)
{
for (i=0; i<field->h*field->w; i++)
field->pimg[i] = value;
}
return nRet;
}
/* set a pixel value in the picture */
void FloatFieldSetValue(FvsFloatField_t img, const FvsInt_t x, const FvsInt_t y, const FvsFloat_t val)
{
iFvsFloatField_t* field = (iFvsFloatField_t*)img;
int address = y * field->w + x;
field->pimg[address] = val;
}
/* This function returns the pixel for the x and y value */
FvsFloat_t FloatFieldGetValue(FvsFloatField_t img, const FvsInt_t x, const FvsInt_t y)
{
iFvsFloatField_t* field = (iFvsFloatField_t*)img;
/* position in array */
int address = y * field->pitch + x;
return field->pimg[address];
}
/* returns a pointer to the field buffer */
FvsFloat_t* FloatFieldGetBuffer(FvsFloatField_t img)
{
iFvsFloatField_t* field = (iFvsFloatField_t*)img;
return field->pimg;
}
/* retrieve width and height */
FvsInt_t FloatFieldGetWidth(const FvsFloatField_t img)
{
iFvsFloatField_t* field = (iFvsFloatField_t*)img;
return field->w;
}
FvsInt_t FloatFieldGetHeight(const FvsFloatField_t img)
{
iFvsFloatField_t* field = (iFvsFloatField_t*)img;
return field->h;
}
/* get the pitch pixel(x,y) pos is at x + y * pitch */
FvsInt_t FloatFieldGetPitch(const FvsFloatField_t img)
{
iFvsFloatField_t* field = (iFvsFloatField_t*)img;
return field->pitch;
}
/*########################################################################
*
* Copyright(C) 2002-2007. All Rights Reserved.
*
* Authors: Shivang Patel
* Jaap de Haan(jdh)
*
* Changes: jdh -> Added support for ImageMagick that enables
* to export files to more than 40 formats.
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2, or (at your option) any later
* version.
*
* This is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License with
* the fvs source package as the
* file COPYING. If not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
########################################################################*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "image.h"
/*!
A fingerprint image structure, a fingerprint image is a 256 gray level
image. This should be enough to do accurate processing. This image
class defines a common format for all algorithms running in this
suite. Images may be imported from different sources such as files,
network data, databases,...
*/
typedef struct iFvsImage_t
{
FvsByte_t *pimg; /* 8 bit image array */
FvsInt_t w; /* width of image */
FvsInt_t h; /* height of image */
FvsInt_t pitch; /* pitch */
FvsImageFlag_t flags; /* flags */
FvsInt_t dpi; /* dots per inch */
} iFvsImage_t;
FvsImage_t ImageCreate()
{
iFvsImage_t* p = NULL;
p = (FvsImage_t)malloc(sizeof(iFvsImage_t));
if (p!=NULL)
{
p->h = 0;
p->w = 0;
p->pitch = 0;
p->pimg = NULL;
p->flags = FvsImageGray; /* default flag */
}
return (FvsImage_t)p;
}
void ImageDestroy(FvsImage_t image)
{
iFvsImage_t* p = NULL;
if (image==NULL)
return;
(void)ImageSetSize(image, 0, 0);
p = image;
free(p);
}
FvsError_t ImageSetFlag(FvsImage_t img, const FvsImageFlag_t flag)
{
iFvsImage_t* image = (iFvsImage_t*)img;
image->flags = flag;
return FvsOK;
}
FvsError_t ImageSetDPI(FvsImage_t img, const FvsInt_t dpi)
{
iFvsImage_t* image = (iFvsImage_t*)img;
image->dpi = dpi;
return FvsOK;
}
FvsInt_t ImageGetDPI(const FvsImage_t img)
{
iFvsImage_t* image = (iFvsImage_t*)img;
return image->dpi;
}
FvsImageFlag_t ImageGetFlag(const FvsImage_t img)
{
iFvsImage_t* image = (iFvsImage_t*)img;
return image->flags;
}
FvsError_t ImageSetSize(FvsImage_t img, const FvsInt_t width, const FvsInt_t height)
{
iFvsImage_t* image = (iFvsImage_t*)img;
FvsError_t nRet = FvsOK;
FvsInt_t newsize = width*height;
/* special case for zero size */
if (newsize==0)
{
if (image->pimg!=NULL)
{
free(image->pimg);
image->pimg = NULL;
image->w = 0;
image->h = 0;
image->pitch = 0;
}
return FvsOK;
}