Add bozorth3 from NBIS; implement verify for image devices
uru4000 works splendiferously (YAY!) aes4000 is going to need some work though :(
This commit is contained in:
parent
41b25f28a4
commit
6b8d17ef26
14 changed files with 3260 additions and 27 deletions
6
README
6
README
|
@ -6,6 +6,12 @@ VERSION INCLUDES GPL CODE FROM LIBTHINKFINGER, therefore distribution is
|
||||||
subject to both the terms of the LGPL (see COPYING) *and* the GPL
|
subject to both the terms of the LGPL (see COPYING) *and* the GPL
|
||||||
(see COPYING.GPL).
|
(see COPYING.GPL).
|
||||||
|
|
||||||
|
libfprint includes code from NIST's NBIS software distribution:
|
||||||
|
http://fingerprint.nist.gov/NBIS/index.html
|
||||||
|
We include bozorth3 from the US export controlled distribution. We have
|
||||||
|
determined that it is fine to ship bozorth3 in an open source project,
|
||||||
|
see http://reactivated.net/fprint/US_export_control
|
||||||
|
|
||||||
At release time, I will contact libthinkfinger authors and see if they will
|
At release time, I will contact libthinkfinger authors and see if they will
|
||||||
be happy to relicense. I expect they will.
|
be happy to relicense. I expect they will.
|
||||||
|
|
||||||
|
|
2
THANKS
2
THANKS
|
@ -2,3 +2,5 @@ Tony Vroon - hardware donations
|
||||||
Gerrie Mansur from Security Database BV (http://www.securitydatabase.net/) - hardware donations
|
Gerrie Mansur from Security Database BV (http://www.securitydatabase.net/) - hardware donations
|
||||||
Joaquin Custodio - hardware donations
|
Joaquin Custodio - hardware donations
|
||||||
TimeTrex (http://www.timetrex.com/) - hardware donations
|
TimeTrex (http://www.timetrex.com/) - hardware donations
|
||||||
|
Craig Watson (NIST)
|
||||||
|
James Vasile (SFLC)
|
||||||
|
|
5
TODO
5
TODO
|
@ -13,6 +13,11 @@ ID Mouse driver
|
||||||
Support for 2nd generation MS devices
|
Support for 2nd generation MS devices
|
||||||
Support for 2nd generation UPEK devices
|
Support for 2nd generation UPEK devices
|
||||||
|
|
||||||
|
IMAGING
|
||||||
|
=======
|
||||||
|
aes4000 doesn't work very well, maybe due to small minutia count?
|
||||||
|
PPMM parameter to get_minutiae seems to have no effect
|
||||||
|
|
||||||
MISC
|
MISC
|
||||||
====
|
====
|
||||||
upekts/thinkfinger relicensing (GPL --> LGPL)
|
upekts/thinkfinger relicensing (GPL --> LGPL)
|
||||||
|
|
|
@ -7,6 +7,12 @@ AES4000_SRC = drivers/aes4000.c
|
||||||
DRIVER_SRC = $(UPEKTS_SRC) $(URU4000_SRC) $(AES4000_SRC)
|
DRIVER_SRC = $(UPEKTS_SRC) $(URU4000_SRC) $(AES4000_SRC)
|
||||||
|
|
||||||
NBIS_SRC = \
|
NBIS_SRC = \
|
||||||
|
nbis/bozorth3/bozorth3.c \
|
||||||
|
nbis/bozorth3/bz_alloc.c \
|
||||||
|
nbis/bozorth3/bz_drvrs.c \
|
||||||
|
nbis/bozorth3/bz_gbls.c \
|
||||||
|
nbis/bozorth3/bz_io.c \
|
||||||
|
nbis/bozorth3/bz_sort.c \
|
||||||
nbis/mindtct/binar.c \
|
nbis/mindtct/binar.c \
|
||||||
nbis/mindtct/block.c \
|
nbis/mindtct/block.c \
|
||||||
nbis/mindtct/chaincod.c \
|
nbis/mindtct/chaincod.c \
|
||||||
|
|
|
@ -180,6 +180,8 @@ struct fp_img *fpi_img_resize(struct fp_img *img, size_t newsize);
|
||||||
gboolean fpi_img_is_sane(struct fp_img *img);
|
gboolean fpi_img_is_sane(struct fp_img *img);
|
||||||
int fpi_img_detect_minutiae(struct fp_img_dev *imgdev, struct fp_img *img,
|
int fpi_img_detect_minutiae(struct fp_img_dev *imgdev, struct fp_img *img,
|
||||||
struct fp_print_data **ret);
|
struct fp_print_data **ret);
|
||||||
|
int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
|
||||||
|
struct fp_print_data *new_print);
|
||||||
|
|
||||||
#define bswap16(x) (((x & 0xff) << 8) | (x >> 8))
|
#define bswap16(x) (((x & 0xff) << 8) | (x >> 8))
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
|
|
@ -175,24 +175,6 @@ API_EXPORTED void fp_img_standardize(struct fp_img *img)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sort_x_y(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
struct minutiae_struct *af = (struct minutiae_struct *) a;
|
|
||||||
struct minutiae_struct *bf = (struct minutiae_struct *) b;
|
|
||||||
|
|
||||||
if (af->col[0] < bf->col[0])
|
|
||||||
return -1;
|
|
||||||
if (af->col[0] > bf->col[0])
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (af->col[1] < bf->col[1])
|
|
||||||
return -1;
|
|
||||||
if (af->col[1] > bf->col[1])
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Based on write_minutiae_XYTQ and bz_load */
|
/* Based on write_minutiae_XYTQ and bz_load */
|
||||||
static void minutiae_to_xyt(MINUTIAE *minutiae, int bwidth,
|
static void minutiae_to_xyt(MINUTIAE *minutiae, int bwidth,
|
||||||
int bheight, unsigned char *buf)
|
int bheight, unsigned char *buf)
|
||||||
|
@ -277,3 +259,21 @@ int fpi_img_detect_minutiae(struct fp_img_dev *imgdev, struct fp_img *img,
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
|
||||||
|
struct fp_print_data *new_print)
|
||||||
|
{
|
||||||
|
struct xyt_struct *gstruct = (struct xyt_struct *) enrolled_print->buffer;
|
||||||
|
struct xyt_struct *pstruct = (struct xyt_struct *) new_print->buffer;
|
||||||
|
GTimer *timer;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
timer = g_timer_new();
|
||||||
|
r = bozorth_main(pstruct, gstruct);
|
||||||
|
g_timer_stop(timer);
|
||||||
|
fp_dbg("bozorth processing took %f seconds, score=%d",
|
||||||
|
g_timer_elapsed(timer, NULL), r);
|
||||||
|
g_timer_destroy(timer);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ API_EXPORTED int fp_imgdev_capture(struct fp_img_dev *imgdev,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_ACCEPTABLE_MINUTIAE 5
|
#define MIN_ACCEPTABLE_MINUTIAE 10
|
||||||
|
|
||||||
int img_dev_enroll(struct fp_dev *dev, gboolean initial, int stage,
|
int img_dev_enroll(struct fp_dev *dev, gboolean initial, int stage,
|
||||||
struct fp_print_data **ret)
|
struct fp_print_data **ret)
|
||||||
|
@ -170,11 +170,43 @@ int img_dev_enroll(struct fp_dev *dev, gboolean initial, int stage,
|
||||||
return FP_ENROLL_COMPLETE;
|
return FP_ENROLL_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int img_dev_verify(struct fp_dev *dev,
|
||||||
|
struct fp_print_data *enrolled_print)
|
||||||
|
{
|
||||||
|
struct fp_img_dev *imgdev = dev->priv;
|
||||||
|
struct fp_img *img;
|
||||||
|
struct fp_print_data *print;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = fp_imgdev_capture(imgdev, 0, &img);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
fp_img_standardize(img);
|
||||||
|
r = fpi_img_detect_minutiae(imgdev, img, &print);
|
||||||
|
fp_img_free(img);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r < MIN_ACCEPTABLE_MINUTIAE) {
|
||||||
|
fp_dbg("not enough minutiae, %d/%d", r, MIN_ACCEPTABLE_MINUTIAE);
|
||||||
|
fp_print_data_free(print);
|
||||||
|
return FP_VERIFY_RETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fpi_img_compare_print_data(enrolled_print, print);
|
||||||
|
fp_print_data_free(print);
|
||||||
|
if (r >= 40)
|
||||||
|
return FP_VERIFY_MATCH;
|
||||||
|
else
|
||||||
|
return FP_VERIFY_NO_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
void fpi_img_driver_setup(struct fp_img_driver *idriver)
|
void fpi_img_driver_setup(struct fp_img_driver *idriver)
|
||||||
{
|
{
|
||||||
idriver->driver.type = DRIVER_IMAGING;
|
idriver->driver.type = DRIVER_IMAGING;
|
||||||
idriver->driver.init = img_dev_init;
|
idriver->driver.init = img_dev_init;
|
||||||
idriver->driver.exit = img_dev_exit;
|
idriver->driver.exit = img_dev_exit;
|
||||||
idriver->driver.enroll = img_dev_enroll;
|
idriver->driver.enroll = img_dev_enroll;
|
||||||
|
idriver->driver.verify = img_dev_verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1785
libfprint/nbis/bozorth3/bozorth3.c
Normal file
1785
libfprint/nbis/bozorth3/bozorth3.c
Normal file
File diff suppressed because it is too large
Load diff
119
libfprint/nbis/bozorth3/bz_alloc.c
Normal file
119
libfprint/nbis/bozorth3/bz_alloc.c
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
This file is part of the Export Control subset of the United States NIST
|
||||||
|
Biometric Image Software (NBIS) distribution:
|
||||||
|
http://fingerprint.nist.gov/NBIS/index.html
|
||||||
|
|
||||||
|
It is our understanding that this falls within ECCN 3D980, which covers
|
||||||
|
software associated with the development, production or use of certain
|
||||||
|
equipment controlled in accordance with U.S. concerns about crime control
|
||||||
|
practices in specific countries.
|
||||||
|
|
||||||
|
Therefore, this file should not be exported, or made available on fileservers,
|
||||||
|
except as allowed by U.S. export control laws.
|
||||||
|
|
||||||
|
Do not remove this notice.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* NOTE: Despite the above notice (which I have not removed), this file is
|
||||||
|
* being legally distributed within libfprint; the U.S. Export Administration
|
||||||
|
* Regulations do not place export restrictions upon distribution of
|
||||||
|
* "publicly available technology and software", as stated in EAR section
|
||||||
|
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
|
||||||
|
* the definition in section 734.7(a)(1).
|
||||||
|
*
|
||||||
|
* For further information, see http://reactivated.net/fprint/US_export_control
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
License:
|
||||||
|
This software was developed at the National Institute of Standards and
|
||||||
|
Technology (NIST) by employees of the Federal Government in the course
|
||||||
|
of their official duties. Pursuant to title 17 Section 105 of the
|
||||||
|
United States Code, this software is not subject to copyright protection
|
||||||
|
and is in the public domain. NIST assumes no responsibility whatsoever for
|
||||||
|
its use by other parties, and makes no guarantees, expressed or implied,
|
||||||
|
about its quality, reliability, or any other characteristic.
|
||||||
|
|
||||||
|
Disclaimer:
|
||||||
|
This software was developed to promote biometric standards and biometric
|
||||||
|
technology testing for the Federal Government in accordance with the USA
|
||||||
|
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
|
||||||
|
Specific hardware and software products identified in this software were used
|
||||||
|
in order to perform the software development. In no case does such
|
||||||
|
identification imply recommendation or endorsement by the National Institute
|
||||||
|
of Standards and Technology, nor does it imply that the products and equipment
|
||||||
|
identified are necessarily the best available for the purpose.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
LIBRARY: FING - NIST Fingerprint Systems Utilities
|
||||||
|
|
||||||
|
FILE: BZ_ALLOC.C
|
||||||
|
ALGORITHM: Allan S. Bozorth (FBI)
|
||||||
|
MODIFICATIONS: Michael D. Garris (NIST)
|
||||||
|
Stan Janet (NIST)
|
||||||
|
DATE: 09/21/2004
|
||||||
|
|
||||||
|
Contains routines responsible for supporting the
|
||||||
|
Bozorth3 fingerprint matching algorithm.
|
||||||
|
|
||||||
|
***********************************************************************
|
||||||
|
|
||||||
|
ROUTINES:
|
||||||
|
#cat: malloc_or_exit - allocates a buffer of bytes from the heap of
|
||||||
|
#cat: specified length exiting directly upon system error
|
||||||
|
#cat: malloc_or_return_error - allocates a buffer of bytes from the heap
|
||||||
|
#cat: of specified length returning an error code upon system error
|
||||||
|
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <bozorth.h>
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
char * malloc_or_exit( int nbytes, const char * what )
|
||||||
|
{
|
||||||
|
char * p;
|
||||||
|
|
||||||
|
/* These are now externally defined in bozorth.h */
|
||||||
|
/* extern FILE * stderr; */
|
||||||
|
/* extern char * get_progname( void ); */
|
||||||
|
|
||||||
|
|
||||||
|
p = malloc( (size_t) nbytes );
|
||||||
|
if ( p == CNULL ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: malloc() of %d bytes for %s failed: %s\n",
|
||||||
|
get_progname(),
|
||||||
|
nbytes,
|
||||||
|
what,
|
||||||
|
strerror( errno )
|
||||||
|
);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* returns CNULL on error */
|
||||||
|
char * malloc_or_return_error( int nbytes, const char * what )
|
||||||
|
{
|
||||||
|
char * p;
|
||||||
|
|
||||||
|
p = malloc( (size_t) nbytes );
|
||||||
|
if ( p == CNULL ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: malloc() of %d bytes for %s failed: %s\n",
|
||||||
|
get_progname(),
|
||||||
|
nbytes,
|
||||||
|
what,
|
||||||
|
strerror( errno )
|
||||||
|
);
|
||||||
|
return(CNULL);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
223
libfprint/nbis/bozorth3/bz_drvrs.c
Normal file
223
libfprint/nbis/bozorth3/bz_drvrs.c
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
This file is part of the Export Control subset of the United States NIST
|
||||||
|
Biometric Image Software (NBIS) distribution:
|
||||||
|
http://fingerprint.nist.gov/NBIS/index.html
|
||||||
|
|
||||||
|
It is our understanding that this falls within ECCN 3D980, which covers
|
||||||
|
software associated with the development, production or use of certain
|
||||||
|
equipment controlled in accordance with U.S. concerns about crime control
|
||||||
|
practices in specific countries.
|
||||||
|
|
||||||
|
Therefore, this file should not be exported, or made available on fileservers,
|
||||||
|
except as allowed by U.S. export control laws.
|
||||||
|
|
||||||
|
Do not remove this notice.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* NOTE: Despite the above notice (which I have not removed), this file is
|
||||||
|
* being legally distributed within libfprint; the U.S. Export Administration
|
||||||
|
* Regulations do not place export restrictions upon distribution of
|
||||||
|
* "publicly available technology and software", as stated in EAR section
|
||||||
|
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
|
||||||
|
* the definition in section 734.7(a)(1).
|
||||||
|
*
|
||||||
|
* For further information, see http://reactivated.net/fprint/US_export_control
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
License:
|
||||||
|
This software was developed at the National Institute of Standards and
|
||||||
|
Technology (NIST) by employees of the Federal Government in the course
|
||||||
|
of their official duties. Pursuant to title 17 Section 105 of the
|
||||||
|
United States Code, this software is not subject to copyright protection
|
||||||
|
and is in the public domain. NIST assumes no responsibility whatsoever for
|
||||||
|
its use by other parties, and makes no guarantees, expressed or implied,
|
||||||
|
about its quality, reliability, or any other characteristic.
|
||||||
|
|
||||||
|
Disclaimer:
|
||||||
|
This software was developed to promote biometric standards and biometric
|
||||||
|
technology testing for the Federal Government in accordance with the USA
|
||||||
|
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
|
||||||
|
Specific hardware and software products identified in this software were used
|
||||||
|
in order to perform the software development. In no case does such
|
||||||
|
identification imply recommendation or endorsement by the National Institute
|
||||||
|
of Standards and Technology, nor does it imply that the products and equipment
|
||||||
|
identified are necessarily the best available for the purpose.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
LIBRARY: FING - NIST Fingerprint Systems Utilities
|
||||||
|
|
||||||
|
FILE: BZ_DRVRS.C
|
||||||
|
ALGORITHM: Allan S. Bozorth (FBI)
|
||||||
|
MODIFICATIONS: Michael D. Garris (NIST)
|
||||||
|
Stan Janet (NIST)
|
||||||
|
DATE: 09/21/2004
|
||||||
|
|
||||||
|
Contains driver routines responsible for kicking off matches
|
||||||
|
using the Bozorth3 fingerprint matching algorithm.
|
||||||
|
|
||||||
|
***********************************************************************
|
||||||
|
|
||||||
|
ROUTINES:
|
||||||
|
#cat: bozorth_probe_init - creates the pairwise minutia comparison
|
||||||
|
#cat: table for the probe fingerprint
|
||||||
|
#cat: bozorth_gallery_init - creates the pairwise minutia comparison
|
||||||
|
#cat: table for the gallery fingerprint
|
||||||
|
#cat: bozorth_to_gallery - supports the matching scenario where the
|
||||||
|
#cat: same probe fingerprint is matches repeatedly
|
||||||
|
#cat: to multiple gallery fingerprints as in
|
||||||
|
#cat: identification mode
|
||||||
|
#cat: bozorth_main - supports the matching scenario where a
|
||||||
|
#cat: single probe fingerprint is to be matched
|
||||||
|
#cat: to a single gallery fingerprint as in
|
||||||
|
#cat: verificaiton mode
|
||||||
|
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <bozorth.h>
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
int bozorth_probe_init( struct xyt_struct * pstruct )
|
||||||
|
{
|
||||||
|
int sim; /* number of pointwise comparisons for Subject's record*/
|
||||||
|
int msim; /* Pruned length of Subject's comparison pointer list */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Take Subject's points and compute pointwise comparison statistics table and sorted row-pointer list. */
|
||||||
|
/* This builds a "Web" of relative edge statistics between points. */
|
||||||
|
bz_comp(
|
||||||
|
pstruct->nrows,
|
||||||
|
pstruct->xcol,
|
||||||
|
pstruct->ycol,
|
||||||
|
pstruct->thetacol,
|
||||||
|
&sim,
|
||||||
|
scols,
|
||||||
|
scolpt );
|
||||||
|
|
||||||
|
msim = sim; /* Init search to end of Subject's pointwise comparison table (last edge in Web) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bz_find( &msim, scolpt );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( msim < FDD ) /* Makes sure there are a reasonable number of edges (at least 500, if possible) to analyze in the Web */
|
||||||
|
msim = ( sim > FDD ) ? FDD : sim;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return msim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
int bozorth_gallery_init( struct xyt_struct * gstruct )
|
||||||
|
{
|
||||||
|
int fim; /* number of pointwise comparisons for On-File record*/
|
||||||
|
int mfim; /* Pruned length of On-File Record's pointer list */
|
||||||
|
|
||||||
|
|
||||||
|
/* Take On-File Record's points and compute pointwise comparison statistics table and sorted row-pointer list. */
|
||||||
|
/* This builds a "Web" of relative edge statistics between points. */
|
||||||
|
bz_comp(
|
||||||
|
gstruct->nrows,
|
||||||
|
gstruct->xcol,
|
||||||
|
gstruct->ycol,
|
||||||
|
gstruct->thetacol,
|
||||||
|
&fim,
|
||||||
|
fcols,
|
||||||
|
fcolpt );
|
||||||
|
|
||||||
|
mfim = fim; /* Init search to end of On-File Record's pointwise comparison table (last edge in Web) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bz_find( &mfim, fcolpt );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( mfim < FDD ) /* Makes sure there are a reasonable number of edges (at least 500, if possible) to analyze in the Web */
|
||||||
|
mfim = ( fim > FDD ) ? FDD : fim;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return mfim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
int bozorth_to_gallery(
|
||||||
|
int probe_len,
|
||||||
|
struct xyt_struct * pstruct,
|
||||||
|
struct xyt_struct * gstruct
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int np;
|
||||||
|
int gallery_len;
|
||||||
|
|
||||||
|
gallery_len = bozorth_gallery_init( gstruct );
|
||||||
|
np = bz_match( probe_len, gallery_len );
|
||||||
|
return bz_match_score( np, pstruct, gstruct );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
int bozorth_main(
|
||||||
|
struct xyt_struct * pstruct,
|
||||||
|
struct xyt_struct * gstruct
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ms;
|
||||||
|
int np;
|
||||||
|
int probe_len;
|
||||||
|
int gallery_len;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "PROBE_INIT() called\n" );
|
||||||
|
#endif
|
||||||
|
probe_len = bozorth_probe_init( pstruct );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "GALLERY_INIT() called\n" );
|
||||||
|
#endif
|
||||||
|
gallery_len = bozorth_gallery_init( gstruct );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "BZ_MATCH() called\n" );
|
||||||
|
#endif
|
||||||
|
np = bz_match( probe_len, gallery_len );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "BZ_MATCH() returned %d edge pairs\n", np );
|
||||||
|
printf( "COMPUTE() called\n" );
|
||||||
|
#endif
|
||||||
|
ms = bz_match_score( np, pstruct, gstruct );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "COMPUTE() returned %d\n", ms );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return ms;
|
||||||
|
}
|
113
libfprint/nbis/bozorth3/bz_gbls.c
Normal file
113
libfprint/nbis/bozorth3/bz_gbls.c
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
This file is part of the Export Control subset of the United States NIST
|
||||||
|
Biometric Image Software (NBIS) distribution:
|
||||||
|
http://fingerprint.nist.gov/NBIS/index.html
|
||||||
|
|
||||||
|
It is our understanding that this falls within ECCN 3D980, which covers
|
||||||
|
software associated with the development, production or use of certain
|
||||||
|
equipment controlled in accordance with U.S. concerns about crime control
|
||||||
|
practices in specific countries.
|
||||||
|
|
||||||
|
Therefore, this file should not be exported, or made available on fileservers,
|
||||||
|
except as allowed by U.S. export control laws.
|
||||||
|
|
||||||
|
Do not remove this notice.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* NOTE: Despite the above notice (which I have not removed), this file is
|
||||||
|
* being legally distributed within libfprint; the U.S. Export Administration
|
||||||
|
* Regulations do not place export restrictions upon distribution of
|
||||||
|
* "publicly available technology and software", as stated in EAR section
|
||||||
|
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
|
||||||
|
* the definition in section 734.7(a)(1).
|
||||||
|
*
|
||||||
|
* For further information, see http://reactivated.net/fprint/US_export_control
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
License:
|
||||||
|
This software was developed at the National Institute of Standards and
|
||||||
|
Technology (NIST) by employees of the Federal Government in the course
|
||||||
|
of their official duties. Pursuant to title 17 Section 105 of the
|
||||||
|
United States Code, this software is not subject to copyright protection
|
||||||
|
and is in the public domain. NIST assumes no responsibility whatsoever for
|
||||||
|
its use by other parties, and makes no guarantees, expressed or implied,
|
||||||
|
about its quality, reliability, or any other characteristic.
|
||||||
|
|
||||||
|
Disclaimer:
|
||||||
|
This software was developed to promote biometric standards and biometric
|
||||||
|
technology testing for the Federal Government in accordance with the USA
|
||||||
|
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
|
||||||
|
Specific hardware and software products identified in this software were used
|
||||||
|
in order to perform the software development. In no case does such
|
||||||
|
identification imply recommendation or endorsement by the National Institute
|
||||||
|
of Standards and Technology, nor does it imply that the products and equipment
|
||||||
|
identified are necessarily the best available for the purpose.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
LIBRARY: FING - NIST Fingerprint Systems Utilities
|
||||||
|
|
||||||
|
FILE: BZ_GBLS.C
|
||||||
|
ALGORITHM: Allan S. Bozorth (FBI)
|
||||||
|
MODIFICATIONS: Michael D. Garris (NIST)
|
||||||
|
Stan Janet (NIST)
|
||||||
|
DATE: 09/21/2004
|
||||||
|
|
||||||
|
Contains global variables responsible for supporting the
|
||||||
|
Bozorth3 fingerprint matching "core" algorithm.
|
||||||
|
|
||||||
|
***********************************************************************
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include <bozorth.h>
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* General supporting global variables */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
int colp[ COLP_SIZE_1 ][ COLP_SIZE_2 ]; /* Output from match(), this is a sorted table of compatible edge pairs containing: */
|
||||||
|
/* DeltaThetaKJs, Subject's K, J, then On-File's {K,J} or {J,K} depending */
|
||||||
|
/* Sorted first on Subject's point index K, */
|
||||||
|
/* then On-File's K or J point index (depending), */
|
||||||
|
/* lastly on Subject's J point index */
|
||||||
|
int scols[ SCOLS_SIZE_1 ][ COLS_SIZE_2 ]; /* Subject's pointwise comparison table containing: */
|
||||||
|
/* Distance,min(BetaK,BetaJ),max(BetaK,BbetaJ), K,J,ThetaKJ */
|
||||||
|
int fcols[ FCOLS_SIZE_1 ][ COLS_SIZE_2 ]; /* On-File Record's pointwise comparison table with: */
|
||||||
|
/* Distance,min(BetaK,BetaJ),max(BetaK,BbetaJ),K,J, ThetaKJ */
|
||||||
|
int * scolpt[ SCOLPT_SIZE ]; /* Subject's list of pointers to pointwise comparison rows, sorted on: */
|
||||||
|
/* Distance, min(BetaK,BetaJ), then max(BetaK,BetaJ) */
|
||||||
|
int * fcolpt[ FCOLPT_SIZE ]; /* On-File Record's list of pointers to pointwise comparison rows sorted on: */
|
||||||
|
/* Distance, min(BetaK,BetaJ), then max(BetaK,BetaJ) */
|
||||||
|
int sc[ SC_SIZE ]; /* Flags all compatible edges in the Subject's Web */
|
||||||
|
|
||||||
|
int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Globals used significantly by sift() */
|
||||||
|
/**************************************************************************/
|
||||||
|
int rq[ RQ_SIZE ] = {};
|
||||||
|
int tq[ TQ_SIZE ] = {};
|
||||||
|
int zz[ ZZ_SIZE ] = {};
|
||||||
|
|
||||||
|
int rx[ RX_SIZE ] = {};
|
||||||
|
int mm[ MM_SIZE ] = {};
|
||||||
|
int nn[ NN_SIZE ] = {};
|
||||||
|
|
||||||
|
int qq[ QQ_SIZE ] = {};
|
||||||
|
|
||||||
|
int rk[ RK_SIZE ] = {};
|
||||||
|
|
||||||
|
int cp[ CP_SIZE ] = {};
|
||||||
|
int rp[ RP_SIZE ] = {};
|
||||||
|
|
||||||
|
int rf[RF_SIZE_1][RF_SIZE_2] = {};
|
||||||
|
int cf[CF_SIZE_1][CF_SIZE_2] = {};
|
||||||
|
|
||||||
|
int y[20000] = {};
|
||||||
|
|
632
libfprint/nbis/bozorth3/bz_io.c
Normal file
632
libfprint/nbis/bozorth3/bz_io.c
Normal file
|
@ -0,0 +1,632 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
This file is part of the Export Control subset of the United States NIST
|
||||||
|
Biometric Image Software (NBIS) distribution:
|
||||||
|
http://fingerprint.nist.gov/NBIS/index.html
|
||||||
|
|
||||||
|
It is our understanding that this falls within ECCN 3D980, which covers
|
||||||
|
software associated with the development, production or use of certain
|
||||||
|
equipment controlled in accordance with U.S. concerns about crime control
|
||||||
|
practices in specific countries.
|
||||||
|
|
||||||
|
Therefore, this file should not be exported, or made available on fileservers,
|
||||||
|
except as allowed by U.S. export control laws.
|
||||||
|
|
||||||
|
Do not remove this notice.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* NOTE: Despite the above notice (which I have not removed), this file is
|
||||||
|
* being legally distributed within libfprint; the U.S. Export Administration
|
||||||
|
* Regulations do not place export restrictions upon distribution of
|
||||||
|
* "publicly available technology and software", as stated in EAR section
|
||||||
|
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
|
||||||
|
* the definition in section 734.7(a)(1).
|
||||||
|
*
|
||||||
|
* For further information, see http://reactivated.net/fprint/US_export_control
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
License:
|
||||||
|
This software was developed at the National Institute of Standards and
|
||||||
|
Technology (NIST) by employees of the Federal Government in the course
|
||||||
|
of their official duties. Pursuant to title 17 Section 105 of the
|
||||||
|
United States Code, this software is not subject to copyright protection
|
||||||
|
and is in the public domain. NIST assumes no responsibility whatsoever for
|
||||||
|
its use by other parties, and makes no guarantees, expressed or implied,
|
||||||
|
about its quality, reliability, or any other characteristic.
|
||||||
|
|
||||||
|
Disclaimer:
|
||||||
|
This software was developed to promote biometric standards and biometric
|
||||||
|
technology testing for the Federal Government in accordance with the USA
|
||||||
|
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
|
||||||
|
Specific hardware and software products identified in this software were used
|
||||||
|
in order to perform the software development. In no case does such
|
||||||
|
identification imply recommendation or endorsement by the National Institute
|
||||||
|
of Standards and Technology, nor does it imply that the products and equipment
|
||||||
|
identified are necessarily the best available for the purpose.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
LIBRARY: FING - NIST Fingerprint Systems Utilities
|
||||||
|
|
||||||
|
FILE: BZ_IO.C
|
||||||
|
ALGORITHM: Allan S. Bozorth (FBI)
|
||||||
|
MODIFICATIONS: Michael D. Garris (NIST)
|
||||||
|
Stan Janet (NIST)
|
||||||
|
DATE: 09/21/2004
|
||||||
|
|
||||||
|
Contains routines responsible for supporting command line
|
||||||
|
processing, file and data input to, and output from the
|
||||||
|
Bozorth3 fingerprint matching algorithm.
|
||||||
|
|
||||||
|
***********************************************************************
|
||||||
|
|
||||||
|
ROUTINES:
|
||||||
|
#cat: parse_line_range - parses strings of the form #-# into the upper
|
||||||
|
#cat: and lower bounds of a range corresponding to lines in
|
||||||
|
#cat: an input file list
|
||||||
|
#cat: set_progname - stores the program name for the current invocation
|
||||||
|
#cat: set_probe_filename - stores the name of the current probe file
|
||||||
|
#cat: being processed
|
||||||
|
#cat: set_gallery_filename - stores the name of the current gallery file
|
||||||
|
#cat: being processed
|
||||||
|
#cat: get_progname - retrieves the program name for the current invocation
|
||||||
|
#cat: get_probe_filename - retrieves the name of the current probe file
|
||||||
|
#cat: being processed
|
||||||
|
#cat: get_gallery_filename - retrieves the name of the current gallery
|
||||||
|
#cat: file being processed
|
||||||
|
#cat: get_next_file - gets the next probe (or gallery) filename to be
|
||||||
|
#cat: processed, either from the command line or from a
|
||||||
|
#cat: file list
|
||||||
|
#cat: get_score_filename - returns the filename to which the output line
|
||||||
|
#cat: should be written
|
||||||
|
#cat: get_score_line - formats output lines based on command line options
|
||||||
|
#cat: specified
|
||||||
|
#cat: bz_load - loads the contents of the specified XYT file into
|
||||||
|
#cat: structured memory
|
||||||
|
#cat: fd_readable - when multiple bozorth processes are being run
|
||||||
|
#cat: concurrently and one of the processes determines a
|
||||||
|
#cat: has been found, the other processes poll a file
|
||||||
|
#cat: descriptor using this function to see if they
|
||||||
|
#cat: should exit as well
|
||||||
|
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <bozorth.h>
|
||||||
|
|
||||||
|
static const int verbose_load = 0;
|
||||||
|
static const int verbose_main = 0;
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
int parse_line_range( const char * sb, int * begin, int * end )
|
||||||
|
{
|
||||||
|
int ib, ie;
|
||||||
|
char * se;
|
||||||
|
|
||||||
|
|
||||||
|
if ( ! isdigit(*sb) )
|
||||||
|
return -1;
|
||||||
|
ib = atoi( sb );
|
||||||
|
|
||||||
|
se = strchr( sb, '-' );
|
||||||
|
if ( se != (char *) NULL ) {
|
||||||
|
se++;
|
||||||
|
if ( ! isdigit(*se) )
|
||||||
|
return -2;
|
||||||
|
ie = atoi( se );
|
||||||
|
} else {
|
||||||
|
ie = ib;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ib <= 0 ) {
|
||||||
|
if ( ie <= 0 ) {
|
||||||
|
return -3;
|
||||||
|
} else {
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ie <= 0 ) {
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ib > ie )
|
||||||
|
return -6;
|
||||||
|
|
||||||
|
*begin = ib;
|
||||||
|
*end = ie;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
|
/* Used by the following set* and get* routines */
|
||||||
|
static char program_buffer[ 1024 ];
|
||||||
|
static char * pfile;
|
||||||
|
static char * gfile;
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
void set_progname( int use_pid, char * basename, pid_t pid )
|
||||||
|
{
|
||||||
|
if ( use_pid )
|
||||||
|
sprintf( program_buffer, "%s pid %ld", basename, (long) pid );
|
||||||
|
else
|
||||||
|
sprintf( program_buffer, "%s", basename );
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
void set_probe_filename( char * filename )
|
||||||
|
{
|
||||||
|
pfile = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
void set_gallery_filename( char * filename )
|
||||||
|
{
|
||||||
|
gfile = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
char * get_progname( void )
|
||||||
|
{
|
||||||
|
return program_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
char * get_probe_filename( void )
|
||||||
|
{
|
||||||
|
return pfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
char * get_gallery_filename( void )
|
||||||
|
{
|
||||||
|
return gfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
char * get_next_file(
|
||||||
|
char * fixed_file,
|
||||||
|
FILE * list_fp,
|
||||||
|
FILE * mates_fp,
|
||||||
|
int * done_now,
|
||||||
|
int * done_afterwards,
|
||||||
|
char * line,
|
||||||
|
int argc,
|
||||||
|
char ** argv,
|
||||||
|
int * optind,
|
||||||
|
|
||||||
|
int * lineno,
|
||||||
|
int begin,
|
||||||
|
int end
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char * p;
|
||||||
|
FILE * fp;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( fixed_file != (char *) NULL ) {
|
||||||
|
if ( verbose_main )
|
||||||
|
fprintf( stderr, "returning fixed filename: %s\n", fixed_file );
|
||||||
|
return fixed_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fp = list_fp;
|
||||||
|
if ( fp == (FILE *) NULL )
|
||||||
|
fp = mates_fp;
|
||||||
|
if ( fp != (FILE *) NULL ) {
|
||||||
|
while (1) {
|
||||||
|
if ( fgets( line, MAX_LINE_LENGTH, fp ) == (char *) NULL ) {
|
||||||
|
*done_now = 1;
|
||||||
|
if ( verbose_main )
|
||||||
|
fprintf( stderr, "returning NULL -- reached EOF\n" );
|
||||||
|
return (char *) NULL;
|
||||||
|
}
|
||||||
|
++*lineno;
|
||||||
|
|
||||||
|
if ( begin <= 0 ) /* no line number range was specified */
|
||||||
|
break;
|
||||||
|
if ( *lineno > end ) {
|
||||||
|
*done_now = 1;
|
||||||
|
if ( verbose_main )
|
||||||
|
fprintf( stderr, "returning NULL -- current line (%d) > end line (%d)\n",
|
||||||
|
*lineno, end );
|
||||||
|
return (char *) NULL;
|
||||||
|
}
|
||||||
|
if ( *lineno >= begin ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Otherwise ( *lineno < begin ) so read another line */
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strchr( line, '\n' );
|
||||||
|
if ( p == (char *) NULL ) {
|
||||||
|
*done_now = 1;
|
||||||
|
if ( verbose_main )
|
||||||
|
fprintf( stderr, "returning NULL -- missing newline character\n" );
|
||||||
|
return (char *) NULL;
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
p = line;
|
||||||
|
if ( verbose_main )
|
||||||
|
fprintf( stderr, "returning filename from next line: %s\n", p );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p = argv[*optind];
|
||||||
|
++*optind;
|
||||||
|
if ( *optind >= argc )
|
||||||
|
*done_afterwards = 1;
|
||||||
|
if ( verbose_main )
|
||||||
|
fprintf( stderr, "returning next argv: %s [done_afterwards=%d]\n", p, *done_afterwards );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* returns CNULL on error */
|
||||||
|
char * get_score_filename( const char * outdir, const char * listfile )
|
||||||
|
{
|
||||||
|
const char * basename;
|
||||||
|
int baselen;
|
||||||
|
int dirlen;
|
||||||
|
int extlen;
|
||||||
|
char * outfile;
|
||||||
|
|
||||||
|
/* These are now exteranlly defined in bozorth.h */
|
||||||
|
/* extern FILE * stderr; */
|
||||||
|
/* extern char * get_progname( void ); */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
basename = strrchr( listfile, '/' );
|
||||||
|
if ( basename == CNULL ) {
|
||||||
|
basename = listfile;
|
||||||
|
} else {
|
||||||
|
++basename;
|
||||||
|
}
|
||||||
|
baselen = strlen( basename );
|
||||||
|
if ( baselen == 0 ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: couldn't find basename of %s\n", get_progname(), listfile );
|
||||||
|
return(CNULL);
|
||||||
|
}
|
||||||
|
dirlen = strlen( outdir );
|
||||||
|
if ( dirlen == 0 ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: illegal output directory %s\n", get_progname(), outdir );
|
||||||
|
return(CNULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
extlen = strlen( SCOREFILE_EXTENSION );
|
||||||
|
outfile = malloc_or_return_error( dirlen + baselen + extlen + 2, "output filename" );
|
||||||
|
if ( outfile == CNULL)
|
||||||
|
return(CNULL);
|
||||||
|
|
||||||
|
sprintf( outfile, "%s/%s%s", outdir, basename, SCOREFILE_EXTENSION );
|
||||||
|
|
||||||
|
return outfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
char * get_score_line(
|
||||||
|
const char * probe_file,
|
||||||
|
const char * gallery_file,
|
||||||
|
int n,
|
||||||
|
int static_flag,
|
||||||
|
const char * fmt
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int nchars;
|
||||||
|
char * bufptr;
|
||||||
|
static char linebuf[1024];
|
||||||
|
|
||||||
|
nchars = 0;
|
||||||
|
bufptr = &linebuf[0];
|
||||||
|
while ( *fmt ) {
|
||||||
|
if ( nchars++ > 0 )
|
||||||
|
*bufptr++ = ' ';
|
||||||
|
switch ( *fmt++ ) {
|
||||||
|
case 's':
|
||||||
|
sprintf( bufptr, "%d", n );
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
sprintf( bufptr, "%s", probe_file );
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
sprintf( bufptr, "%s", gallery_file );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (char *) NULL;
|
||||||
|
}
|
||||||
|
bufptr = strchr( bufptr, '\0' );
|
||||||
|
}
|
||||||
|
*bufptr++ = '\n';
|
||||||
|
*bufptr = '\0';
|
||||||
|
|
||||||
|
return static_flag ? &linebuf[0] : strdup( linebuf );
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
Load a 3-4 column (X,Y,T[,Q]) set of minutiae from the specified file.
|
||||||
|
Row 3's value is an angle which is normalized to the interval (-180,180].
|
||||||
|
A maximum of MAX_BOZORTH_MINUTIAE minutiae can be returned -- fewer if
|
||||||
|
"DEFAULT_BOZORTH_MINUTIAE" is smaller. If the file contains more minutiae than are
|
||||||
|
to be returned, the highest-quality minutiae are returned.
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
struct xyt_struct * bz_load( const char * xyt_file )
|
||||||
|
{
|
||||||
|
int nminutiae;
|
||||||
|
int j;
|
||||||
|
int m;
|
||||||
|
int nargs_expected;
|
||||||
|
FILE * fp;
|
||||||
|
struct xyt_struct * s;
|
||||||
|
int * xptr;
|
||||||
|
int * yptr;
|
||||||
|
int * tptr;
|
||||||
|
int * qptr;
|
||||||
|
struct minutiae_struct c[MAX_FILE_MINUTIAE];
|
||||||
|
int xvals_lng[MAX_FILE_MINUTIAE], /* Temporary lists to store all the minutaie from a file */
|
||||||
|
yvals_lng[MAX_FILE_MINUTIAE],
|
||||||
|
tvals_lng[MAX_FILE_MINUTIAE],
|
||||||
|
qvals_lng[MAX_FILE_MINUTIAE];
|
||||||
|
int order[MAX_FILE_MINUTIAE]; /* The ranked order, after sort, for each index */
|
||||||
|
int xvals[MAX_BOZORTH_MINUTIAE], /* Temporary lists to hold input coordinates */
|
||||||
|
yvals[MAX_BOZORTH_MINUTIAE],
|
||||||
|
tvals[MAX_BOZORTH_MINUTIAE],
|
||||||
|
qvals[MAX_BOZORTH_MINUTIAE];
|
||||||
|
char xyt_line[ MAX_LINE_LENGTH ];
|
||||||
|
|
||||||
|
/* This is now externally defined in bozorth.h */
|
||||||
|
/* extern FILE * stderr; */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define C1 0
|
||||||
|
#define C2 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fp = fopen( xyt_file, "r" );
|
||||||
|
if ( fp == (FILE *) NULL ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: fopen() of minutiae file \"%s\" failed: %s\n",
|
||||||
|
get_progname(), xyt_file, strerror(errno) );
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nminutiae = 0;
|
||||||
|
nargs_expected = 0;
|
||||||
|
while ( fgets( xyt_line, sizeof xyt_line, fp ) != CNULL ) {
|
||||||
|
|
||||||
|
m = sscanf( xyt_line, "%d %d %d %d",
|
||||||
|
&xvals_lng[nminutiae],
|
||||||
|
&yvals_lng[nminutiae],
|
||||||
|
&tvals_lng[nminutiae],
|
||||||
|
&qvals_lng[nminutiae] );
|
||||||
|
if ( nminutiae == 0 ) {
|
||||||
|
if ( m != 3 && m != 4 ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: sscanf() failed on line %u in minutiae file \"%s\"\n",
|
||||||
|
get_progname(), nminutiae+1, xyt_file );
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
nargs_expected = m;
|
||||||
|
} else {
|
||||||
|
if ( m != nargs_expected ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: inconsistent argument count on line %u of minutiae file \"%s\"\n",
|
||||||
|
get_progname(), nminutiae+1, xyt_file );
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( m == 3 )
|
||||||
|
qvals_lng[nminutiae] = 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( tvals_lng[nminutiae] > 180 )
|
||||||
|
tvals_lng[nminutiae] -= 360;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if ( C1 ) {
|
||||||
|
c[nminutiae].col[0] = xvals_lng[nminutiae];
|
||||||
|
c[nminutiae].col[1] = yvals_lng[nminutiae];
|
||||||
|
c[nminutiae].col[2] = tvals_lng[nminutiae];
|
||||||
|
c[nminutiae].col[3] = qvals_lng[nminutiae];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
++nminutiae;
|
||||||
|
if ( nminutiae == MAX_FILE_MINUTIAE )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fclose(fp) != 0 ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: fclose() of minutiae file \"%s\" failed: %s\n",
|
||||||
|
get_progname(), xyt_file, strerror(errno) );
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( nminutiae > DEFAULT_BOZORTH_MINUTIAE ) {
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, "%s: WARNING: bz_load(): trimming minutiae to the %d of highest quality\n",
|
||||||
|
get_progname(), DEFAULT_BOZORTH_MINUTIAE );
|
||||||
|
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, "Before quality sort:\n" );
|
||||||
|
if ( sort_order_decreasing( qvals_lng, nminutiae, order )) {
|
||||||
|
fprintf( stderr, "%s: ERROR: sort failed and returned on error\n", get_progname());
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( j = 0; j < nminutiae; j++ ) {
|
||||||
|
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, " %3d: %3d %3d %3d ---> order = %3d\n",
|
||||||
|
j, xvals_lng[j], yvals_lng[j], qvals_lng[j], order[j] );
|
||||||
|
|
||||||
|
if ( j == 0 )
|
||||||
|
continue;
|
||||||
|
if ( qvals_lng[order[j]] > qvals_lng[order[j-1]] ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: sort failed: j=%d; qvals_lng[%d] > qvals_lng[%d]\n",
|
||||||
|
get_progname(), j, order[j], order[j-1] );
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, "\nAfter quality sort:\n" );
|
||||||
|
for ( j = 0; j < DEFAULT_BOZORTH_MINUTIAE; j++ ) {
|
||||||
|
xvals[j] = xvals_lng[order[j]];
|
||||||
|
yvals[j] = yvals_lng[order[j]];
|
||||||
|
tvals[j] = tvals_lng[order[j]];
|
||||||
|
qvals[j] = qvals_lng[order[j]];
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, " %3d: %3d %3d %3d\n", j, xvals[j], yvals[j], qvals[j] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( C1 ) {
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, "\nAfter qsort():\n" );
|
||||||
|
qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_quality_decreasing );
|
||||||
|
for ( j = 0; j < nminutiae; j++ ) {
|
||||||
|
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, "Q %3d: %3d %3d %3d\n",
|
||||||
|
j, c[j].col[0], c[j].col[1], c[j].col[3] );
|
||||||
|
|
||||||
|
if ( j > 0 && c[j].col[3] > c[j-1].col[3] ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[3] > c[%d].col[3]\n",
|
||||||
|
get_progname(), j, j-1 );
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, "\n" );
|
||||||
|
|
||||||
|
xptr = xvals;
|
||||||
|
yptr = yvals;
|
||||||
|
tptr = tvals;
|
||||||
|
qptr = qvals;
|
||||||
|
|
||||||
|
nminutiae = DEFAULT_BOZORTH_MINUTIAE;
|
||||||
|
} else{
|
||||||
|
xptr = xvals_lng;
|
||||||
|
yptr = yvals_lng;
|
||||||
|
tptr = tvals_lng;
|
||||||
|
qptr = qvals_lng;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for ( j=0; j < nminutiae; j++ ) {
|
||||||
|
c[j].col[0] = xptr[j];
|
||||||
|
c[j].col[1] = yptr[j];
|
||||||
|
c[j].col[2] = tptr[j];
|
||||||
|
c[j].col[3] = qptr[j];
|
||||||
|
}
|
||||||
|
qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_x_y );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( verbose_load ) {
|
||||||
|
fprintf( stderr, "\nSorted on increasing x, then increasing y\n" );
|
||||||
|
for ( j = 0; j < nminutiae; j++ ) {
|
||||||
|
fprintf( stderr, "%d : %3d, %3d, %3d, %3d\n", j, c[j].col[0], c[j].col[1], c[j].col[2], c[j].col[3] );
|
||||||
|
if ( j > 0 ) {
|
||||||
|
if ( c[j].col[0] < c[j-1].col[0] ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d > c[%d].col[0]=%d\n",
|
||||||
|
get_progname(),
|
||||||
|
j, c[j].col[0], j-1, c[j-1].col[0]
|
||||||
|
);
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
if ( c[j].col[0] == c[j-1].col[0] && c[j].col[1] < c[j-1].col[1] ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d == c[%d].col[0]=%d; c[%d].col[0]=%d == c[%d].col[0]=%d\n",
|
||||||
|
get_progname(),
|
||||||
|
j, c[j].col[0], j-1, c[j-1].col[0],
|
||||||
|
j, c[j].col[1], j-1, c[j-1].col[1]
|
||||||
|
);
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
s = (struct xyt_struct *) malloc( sizeof( struct xyt_struct ) );
|
||||||
|
if ( s == XYT_NULL ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: malloc() failure while loading minutiae file \"%s\" failed: %s\n",
|
||||||
|
get_progname(),
|
||||||
|
xyt_file,
|
||||||
|
strerror(errno)
|
||||||
|
);
|
||||||
|
return XYT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for ( j = 0; j < nminutiae; j++ ) {
|
||||||
|
s->xcol[j] = c[j].col[0];
|
||||||
|
s->ycol[j] = c[j].col[1];
|
||||||
|
s->thetacol[j] = c[j].col[2];
|
||||||
|
}
|
||||||
|
s->nrows = nminutiae;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( verbose_load )
|
||||||
|
fprintf( stderr, "Loaded %s\n", xyt_file );
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
#ifdef PARALLEL_SEARCH
|
||||||
|
int fd_readable( int fd )
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
fd_set rfds;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
|
||||||
|
FD_ZERO( &rfds );
|
||||||
|
FD_SET( fd, &rfds );
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
retval = select( fd+1, &rfds, NULL, NULL, &tv );
|
||||||
|
|
||||||
|
if ( retval < 0 ) {
|
||||||
|
perror( "select() failed" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( FD_ISSET( fd, &rfds ) ) {
|
||||||
|
/*fprintf( stderr, "data is available now.\n" );*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fprintf( stderr, "no data is available\n" ); */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
315
libfprint/nbis/bozorth3/bz_sort.c
Normal file
315
libfprint/nbis/bozorth3/bz_sort.c
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
This file is part of the Export Control subset of the United States NIST
|
||||||
|
Biometric Image Software (NBIS) distribution:
|
||||||
|
http://fingerprint.nist.gov/NBIS/index.html
|
||||||
|
|
||||||
|
It is our understanding that this falls within ECCN 3D980, which covers
|
||||||
|
software associated with the development, production or use of certain
|
||||||
|
equipment controlled in accordance with U.S. concerns about crime control
|
||||||
|
practices in specific countries.
|
||||||
|
|
||||||
|
Therefore, this file should not be exported, or made available on fileservers,
|
||||||
|
except as allowed by U.S. export control laws.
|
||||||
|
|
||||||
|
Do not remove this notice.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* NOTE: Despite the above notice (which I have not removed), this file is
|
||||||
|
* being legally distributed within libfprint; the U.S. Export Administration
|
||||||
|
* Regulations do not place export restrictions upon distribution of
|
||||||
|
* "publicly available technology and software", as stated in EAR section
|
||||||
|
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
|
||||||
|
* the definition in section 734.7(a)(1).
|
||||||
|
*
|
||||||
|
* For further information, see http://reactivated.net/fprint/US_export_control
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
License:
|
||||||
|
This software was developed at the National Institute of Standards and
|
||||||
|
Technology (NIST) by employees of the Federal Government in the course
|
||||||
|
of their official duties. Pursuant to title 17 Section 105 of the
|
||||||
|
United States Code, this software is not subject to copyright protection
|
||||||
|
and is in the public domain. NIST assumes no responsibility whatsoever for
|
||||||
|
its use by other parties, and makes no guarantees, expressed or implied,
|
||||||
|
about its quality, reliability, or any other characteristic.
|
||||||
|
|
||||||
|
Disclaimer:
|
||||||
|
This software was developed to promote biometric standards and biometric
|
||||||
|
technology testing for the Federal Government in accordance with the USA
|
||||||
|
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
|
||||||
|
Specific hardware and software products identified in this software were used
|
||||||
|
in order to perform the software development. In no case does such
|
||||||
|
identification imply recommendation or endorsement by the National Institute
|
||||||
|
of Standards and Technology, nor does it imply that the products and equipment
|
||||||
|
identified are necessarily the best available for the purpose.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
LIBRARY: FING - NIST Fingerprint Systems Utilities
|
||||||
|
|
||||||
|
FILE: BZ_SORT.C
|
||||||
|
ALGORITHM: Allan S. Bozorth (FBI)
|
||||||
|
MODIFICATIONS: Michael D. Garris (NIST)
|
||||||
|
Stan Janet (NIST)
|
||||||
|
DATE: 09/21/2004
|
||||||
|
|
||||||
|
Contains sorting routines responsible for supporting the
|
||||||
|
Bozorth3 fingerprint matching algorithm.
|
||||||
|
|
||||||
|
***********************************************************************
|
||||||
|
|
||||||
|
ROUTINES:
|
||||||
|
#cat: sort_quality_decreasing - comparison function passed to stdlib
|
||||||
|
#cat: qsort() used to sort minutia qualities
|
||||||
|
#cat: sort_x_y - comparison function passed to stdlib qsort() used
|
||||||
|
#cat: to sort minutia coordinates increasing first on x
|
||||||
|
#cat: then on y
|
||||||
|
#cat: sort_order_decreasing - calls a custom quicksort that sorts
|
||||||
|
#cat: a list of integers in decreasing order
|
||||||
|
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <bozorth.h>
|
||||||
|
|
||||||
|
/* These are now externally defined in bozorth.h */
|
||||||
|
/* extern char * get_progname( void ); */
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
int sort_quality_decreasing( const void * a, const void * b )
|
||||||
|
{
|
||||||
|
struct minutiae_struct * af;
|
||||||
|
struct minutiae_struct * bf;
|
||||||
|
|
||||||
|
af = (struct minutiae_struct *) a;
|
||||||
|
bf = (struct minutiae_struct *) b;
|
||||||
|
|
||||||
|
if ( af->col[3] > bf->col[3] )
|
||||||
|
return -1;
|
||||||
|
if ( af->col[3] < bf->col[3] )
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
int sort_x_y( const void * a, const void * b )
|
||||||
|
{
|
||||||
|
struct minutiae_struct * af;
|
||||||
|
struct minutiae_struct * bf;
|
||||||
|
|
||||||
|
af = (struct minutiae_struct *) a;
|
||||||
|
bf = (struct minutiae_struct *) b;
|
||||||
|
|
||||||
|
if ( af->col[0] < bf->col[0] )
|
||||||
|
return -1;
|
||||||
|
if ( af->col[0] > bf->col[0] )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ( af->col[1] < bf->col[1] )
|
||||||
|
return -1;
|
||||||
|
if ( af->col[1] > bf->col[1] )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************
|
||||||
|
qsort_decreasing() - quicksort an array of integers in decreasing
|
||||||
|
order [based on multisort.c, by Michael Garris
|
||||||
|
and Ted Zwiesler, 1986]
|
||||||
|
********************************************************/
|
||||||
|
/* Used by custom quicksort code below */
|
||||||
|
static int stack[BZ_STACKSIZE];
|
||||||
|
static int * stack_pointer = stack;
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* return values: 0 == successful, 1 == error */
|
||||||
|
static int popstack( int *popval )
|
||||||
|
{
|
||||||
|
if ( --stack_pointer < stack ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: popstack(): stack underflow\n", get_progname() );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*popval = *stack_pointer;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* return values: 0 == successful, 1 == error */
|
||||||
|
static int pushstack( int position )
|
||||||
|
{
|
||||||
|
*stack_pointer++ = position;
|
||||||
|
if ( stack_pointer > ( stack + BZ_STACKSIZE ) ) {
|
||||||
|
fprintf( stderr, "%s: ERROR: pushstack(): stack overflow\n", get_progname() );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/*******************************************************************
|
||||||
|
select_pivot()
|
||||||
|
selects a pivot from a list being sorted using the Singleton Method.
|
||||||
|
*******************************************************************/
|
||||||
|
static int select_pivot( struct cell v[], int left, int right )
|
||||||
|
{
|
||||||
|
int midpoint;
|
||||||
|
|
||||||
|
|
||||||
|
midpoint = ( left + right ) / 2;
|
||||||
|
if ( v[left].index <= v[midpoint].index ) {
|
||||||
|
if ( v[midpoint].index <= v[right].index ) {
|
||||||
|
return midpoint;
|
||||||
|
} else {
|
||||||
|
if ( v[right].index > v[left].index ) {
|
||||||
|
return right;
|
||||||
|
} else {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( v[left].index < v[right].index ) {
|
||||||
|
return left;
|
||||||
|
} else {
|
||||||
|
if ( v[right].index < v[midpoint].index ) {
|
||||||
|
return midpoint;
|
||||||
|
} else {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/********************************************************
|
||||||
|
partition_dec()
|
||||||
|
Inputs a pivot element making comparisons and swaps with other elements in a list,
|
||||||
|
until pivot resides at its correct position in the list.
|
||||||
|
********************************************************/
|
||||||
|
static void partition_dec( struct cell v[], int *llen, int *rlen, int *ll, int *lr, int *rl, int *rr, int p, int l, int r )
|
||||||
|
{
|
||||||
|
#define iswap(a,b) { int itmp = (a); a = (b); b = itmp; }
|
||||||
|
|
||||||
|
*ll = l;
|
||||||
|
*rr = r;
|
||||||
|
while ( 1 ) {
|
||||||
|
if ( l < p ) {
|
||||||
|
if ( v[l].index < v[p].index ) {
|
||||||
|
iswap( v[l].index, v[p].index )
|
||||||
|
iswap( v[l].item, v[p].item )
|
||||||
|
p = l;
|
||||||
|
} else {
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( r > p ) {
|
||||||
|
if ( v[r].index > v[p].index ) {
|
||||||
|
iswap( v[r].index, v[p].index )
|
||||||
|
iswap( v[r].item, v[p].item )
|
||||||
|
p = r;
|
||||||
|
l++;
|
||||||
|
} else {
|
||||||
|
r--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*lr = p - 1;
|
||||||
|
*rl = p + 1;
|
||||||
|
*llen = *lr - *ll + 1;
|
||||||
|
*rlen = *rr - *rl + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/********************************************************
|
||||||
|
qsort_decreasing()
|
||||||
|
This procedure inputs a pointer to an index_struct, the subscript of an index array to be
|
||||||
|
sorted, a left subscript pointing to where the sort is to begin in the index array, and a right
|
||||||
|
subscript where to end. This module invokes a decreasing quick-sort sorting the index array from l to r.
|
||||||
|
********************************************************/
|
||||||
|
/* return values: 0 == successful, 1 == error */
|
||||||
|
static int qsort_decreasing( struct cell v[], int left, int right )
|
||||||
|
{
|
||||||
|
int pivot;
|
||||||
|
int llen, rlen;
|
||||||
|
int lleft, lright, rleft, rright;
|
||||||
|
|
||||||
|
|
||||||
|
if ( pushstack( left ))
|
||||||
|
return 1;
|
||||||
|
if ( pushstack( right ))
|
||||||
|
return 2;
|
||||||
|
while ( stack_pointer != stack ) {
|
||||||
|
if (popstack(&right))
|
||||||
|
return 3;
|
||||||
|
if (popstack(&left ))
|
||||||
|
return 4;
|
||||||
|
if ( right - left > 0 ) {
|
||||||
|
pivot = select_pivot( v, left, right );
|
||||||
|
partition_dec( v, &llen, &rlen, &lleft, &lright, &rleft, &rright, pivot, left, right );
|
||||||
|
if ( llen > rlen ) {
|
||||||
|
if ( pushstack( lleft ))
|
||||||
|
return 5;
|
||||||
|
if ( pushstack( lright ))
|
||||||
|
return 6;
|
||||||
|
if ( pushstack( rleft ))
|
||||||
|
return 7;
|
||||||
|
if ( pushstack( rright ))
|
||||||
|
return 8;
|
||||||
|
} else{
|
||||||
|
if ( pushstack( rleft ))
|
||||||
|
return 9;
|
||||||
|
if ( pushstack( rright ))
|
||||||
|
return 10;
|
||||||
|
if ( pushstack( lleft ))
|
||||||
|
return 11;
|
||||||
|
if ( pushstack( lright ))
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* return values: 0 == successful, 1 == error */
|
||||||
|
int sort_order_decreasing(
|
||||||
|
int values[], /* INPUT: the unsorted values themselves */
|
||||||
|
int num, /* INPUT: the number of values */
|
||||||
|
int order[] /* OUTPUT: the order for each of the values if sorted */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct cell * cells;
|
||||||
|
|
||||||
|
|
||||||
|
cells = (struct cell *) malloc( num * sizeof(struct cell) );
|
||||||
|
if ( cells == (struct cell *) NULL ){
|
||||||
|
fprintf( stderr, "%s: ERROR: malloc(): struct cell\n", get_progname() );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < num; i++ ) {
|
||||||
|
cells[i].index = values[i];
|
||||||
|
cells[i].item = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( qsort_decreasing( cells, 0, num-1 ) < 0)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
for( i = 0; i < num; i++ ) {
|
||||||
|
order[i] = cells[i].item;
|
||||||
|
}
|
||||||
|
|
||||||
|
free( (void *) cells );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -186,15 +186,7 @@ struct xyt_struct {
|
||||||
/* In: SRC/BIN/BOZORTH3/BOZORTH3.C */
|
/* In: SRC/BIN/BOZORTH3/BOZORTH3.C */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* Globals supporting command line options */
|
/* Globals supporting command line options */
|
||||||
extern int m1_xyt;
|
|
||||||
extern int max_minutiae;
|
|
||||||
extern int min_computable_minutiae;
|
|
||||||
extern int verbose_main;
|
|
||||||
extern int verbose_load;
|
|
||||||
extern int verbose_bozorth;
|
|
||||||
extern int verbose_threshold;
|
extern int verbose_threshold;
|
||||||
/* Global supporting error reporting */
|
|
||||||
extern FILE *errorfp;
|
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* In: BZ_GBLS.C */
|
/* In: BZ_GBLS.C */
|
||||||
|
@ -258,6 +250,7 @@ extern struct xyt_struct *bz_load(const char *);
|
||||||
extern int fd_readable(int);
|
extern int fd_readable(int);
|
||||||
/* In: BZ_SORT.C */
|
/* In: BZ_SORT.C */
|
||||||
extern int sort_quality_decreasing(const void *, const void *);
|
extern int sort_quality_decreasing(const void *, const void *);
|
||||||
|
extern int sort_x_y(const void *, const void *);
|
||||||
extern int sort_order_decreasing(int [], int, int []);
|
extern int sort_order_decreasing(int [], int, int []);
|
||||||
|
|
||||||
#endif /* !_BOZORTH_H */
|
#endif /* !_BOZORTH_H */
|
||||||
|
|
Loading…
Reference in a new issue