Merge branch 'wip/hadess/update-nbis-5-0-0' into 'master'

Update to NBIS 5.0.0

See merge request libfprint/libfprint!12
This commit is contained in:
Bastien Nocera 2018-08-28 09:35:46 +00:00
commit 9ccbda4a40
48 changed files with 4489 additions and 4978 deletions

View file

@ -566,12 +566,6 @@ fpi_dev_get_verify_data(struct fp_dev *dev)
return dev->verify_data; return dev->verify_data;
} }
enum fp_dev_state
fpi_dev_get_dev_state(struct fp_dev *dev)
{
return dev->state;
}
/** /**
* fp_driver_get_name: * fp_driver_get_name:
* @drv: the driver * @drv: the driver

View file

@ -216,6 +216,10 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
/* Deactivate device */ /* Deactivate device */
static void dev_deactivate(struct fp_img_dev *dev) static void dev_deactivate(struct fp_img_dev *dev)
{ {
vfs301_dev_t *vdev;
vdev = fpi_imgdev_get_user_data(dev);
vfs301_proto_deinit(fpi_imgdev_get_usb_dev(dev), vdev);
fpi_imgdev_deactivate_complete(dev); fpi_imgdev_deactivate_complete(dev);
} }

View file

@ -84,7 +84,6 @@ void fpi_dev_set_user_data (struct fp_dev *dev, void *user_data);
int fpi_dev_get_nr_enroll_stages(struct fp_dev *dev); int fpi_dev_get_nr_enroll_stages(struct fp_dev *dev);
void fpi_dev_set_nr_enroll_stages(struct fp_dev *dev, int nr_enroll_stages); void fpi_dev_set_nr_enroll_stages(struct fp_dev *dev, int nr_enroll_stages);
struct fp_print_data *fpi_dev_get_verify_data(struct fp_dev *dev); struct fp_print_data *fpi_dev_get_verify_data(struct fp_dev *dev);
enum fp_dev_state fpi_dev_get_dev_state(struct fp_dev *dev);
enum fp_imgdev_state { enum fp_imgdev_state {
IMGDEV_STATE_INACTIVE, IMGDEV_STATE_INACTIVE,

View file

@ -304,9 +304,6 @@ static int fpi_img_detect_minutiae(struct fp_img *img)
return -EINVAL; return -EINVAL;
} }
/* Remove perimeter points from partial image */
g_lfsparms_V2.remove_perimeter_pts = img->flags & FP_IMG_PARTIAL ? TRUE : FALSE;
/* 25.4 mm per inch */ /* 25.4 mm per inch */
timer = g_timer_new(); timer = g_timer_new();
r = get_minutiae(&minutiae, &quality_map, &direction_map, r = get_minutiae(&minutiae, &quality_map, &direction_map,

View file

@ -30,14 +30,17 @@ nbis_sources = [
'nbis/bozorth3/bz_sort.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/contour.c', 'nbis/mindtct/contour.c',
'nbis/mindtct/detect.c', 'nbis/mindtct/detect.c',
'nbis/mindtct/dft.c', 'nbis/mindtct/dft.c',
'nbis/mindtct/free.c', 'nbis/mindtct/free.c',
'nbis/mindtct/getmin.c',
'nbis/mindtct/globals.c', 'nbis/mindtct/globals.c',
'nbis/mindtct/imgutil.c', 'nbis/mindtct/imgutil.c',
'nbis/mindtct/init.c', 'nbis/mindtct/init.c',
'nbis/mindtct/line.c', 'nbis/mindtct/line.c',
'nbis/mindtct/link.c',
'nbis/mindtct/log.c', 'nbis/mindtct/log.c',
'nbis/mindtct/loop.c', 'nbis/mindtct/loop.c',
'nbis/mindtct/maps.c', 'nbis/mindtct/maps.c',
@ -50,6 +53,7 @@ nbis_sources = [
'nbis/mindtct/shape.c', 'nbis/mindtct/shape.c',
'nbis/mindtct/sort.c', 'nbis/mindtct/sort.c',
'nbis/mindtct/util.c', 'nbis/mindtct/util.c',
'nbis/mindtct/xytreps.c',
] ]
aeslib = false aeslib = false

View file

@ -1,51 +1,43 @@
/******************************************************************************
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 https://fprint.freedesktop.org/us-export-control.html
*/
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -89,9 +81,6 @@ identified are necessarily the best available for the purpose.
#include <stdio.h> #include <stdio.h>
#include <bozorth.h> #include <bozorth.h>
static const int verbose_bozorth = 0;
static const int m1_xyt = 0;
/***********************************************************************/ /***********************************************************************/
void bz_comp( void bz_comp(
int npoints, /* INPUT: # of points */ int npoints, /* INPUT: # of points */
@ -160,7 +149,7 @@ for ( k = 0; k < npoints - 1; k++ ) {
else { else {
double dz; double dz;
if ( m1_xyt ) if ( 0 )
dz = ( 180.0F / PI_SINGLE ) * atanf( (float) -dy / (float) dx ); dz = ( 180.0F / PI_SINGLE ) * atanf( (float) -dy / (float) dx );
else else
dz = ( 180.0F / PI_SINGLE ) * atanf( (float) dy / (float) dx ); dz = ( 180.0F / PI_SINGLE ) * atanf( (float) dy / (float) dx );
@ -261,7 +250,7 @@ for ( k = 0; k < npoints - 1; k++ ) {
if ( table_index == 19999 ) { if ( table_index == 19999 ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) if ( 0 )
printf( "bz_comp(): breaking loop to avoid table overflow\n" ); printf( "bz_comp(): breaking loop to avoid table overflow\n" );
#endif #endif
goto COMP_END; goto COMP_END;
@ -392,7 +381,7 @@ static int * rtp[ ROT_SIZE_1 ];
/* extern int * scolpt[ SCOLPT_SIZE ]; INPUT */ /* extern int * scolpt[ SCOLPT_SIZE ]; INPUT */
/* extern int * fcolpt[ FCOLPT_SIZE ]; INPUT */ /* extern int * fcolpt[ FCOLPT_SIZE ]; INPUT */
/* extern int colp[ COLP_SIZE_1 ][ COLP_SIZE_2 ]; OUTPUT */ /* extern int colp[ COLP_SIZE_1 ][ COLP_SIZE_2 ]; OUTPUT */
/* extern int verbose_bozorth; */ /* extern int 0; */
/* extern FILE * stderr; */ /* extern FILE * stderr; */
/* extern char * get_progname( void ); */ /* extern char * get_progname( void ); */
/* extern char * get_probe_filename( void ); */ /* extern char * get_probe_filename( void ); */
@ -401,6 +390,7 @@ static int * rtp[ ROT_SIZE_1 ];
st = 1; st = 1;
edge_pair_index = 0; edge_pair_index = 0;
rotptr = &rot[0][0]; rotptr = &rot[0][0];
@ -570,7 +560,7 @@ for ( k = 1; k < probe_ptrlist_len; k++ ) {
if ( edge_pair_index == 19999 ) { if ( edge_pair_index == 19999 ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) if ( 0 )
fprintf( stderr, "%s: bz_match(): WARNING: list is full, breaking loop early [p=%s; g=%s]\n", fprintf( stderr, "%s: bz_match(): WARNING: list is full, breaking loop early [p=%s; g=%s]\n",
get_progname(), get_probe_filename(), get_gallery_filename() ); get_progname(), get_probe_filename(), get_gallery_filename() );
#endif #endif
@ -652,13 +642,13 @@ int avv[ AVV_SIZE_1 ][ AVV_SIZE_2 ];
if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
if ( verbose_bozorth ) if ( 0 )
fprintf( stderr, "%s: bz_match_score(): both probe and gallery file have too few minutiae (%d,%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n", fprintf( stderr, "%s: bz_match_score(): both probe and gallery file have too few minutiae (%d,%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n",
get_progname(), get_progname(),
pstruct->nrows, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, pstruct->nrows, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
get_probe_filename(), get_gallery_filename() ); get_probe_filename(), get_gallery_filename() );
} else { } else {
if ( verbose_bozorth ) if ( 0 )
fprintf( stderr, "%s: bz_match_score(): probe file has too few minutiae (%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n", fprintf( stderr, "%s: bz_match_score(): probe file has too few minutiae (%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n",
get_progname(), get_progname(),
pstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, pstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
@ -672,7 +662,7 @@ if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) if ( 0 )
fprintf( stderr, "%s: bz_match_score(): gallery file has too few minutiae (%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n", fprintf( stderr, "%s: bz_match_score(): gallery file has too few minutiae (%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n",
get_progname(), get_progname(),
gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
@ -765,7 +755,7 @@ for ( k = 0; k < np - 1; k++ ) {
} }
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) if ( 0 )
printf( "x1 %d %d %d %d %d %d\n", kx, colp[kx][0], colp[kx][1], colp[kx][2], colp[kx][3], colp[kx][4] ); printf( "x1 %d %d %d %d %d %d\n", kx, colp[kx][0], colp[kx][1], colp[kx][2], colp[kx][3], colp[kx][4] );
#endif #endif
@ -1167,7 +1157,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( ll ) { if ( ll ) {
if ( m1_xyt ) if ( 0 )
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -jj / (float) ll ); fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -jj / (float) ll );
else else
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) jj / (float) ll ); fi = ( 180.0F / PI_SINGLE ) * atanf( (float) jj / (float) ll );
@ -1187,7 +1177,7 @@ for ( k = 0; k < np - 1; k++ ) {
jj += 360; jj += 360;
} else { } else {
if ( m1_xyt ) { if ( 0 ) {
if ( jj > 0 ) if ( jj > 0 )
jj = -90; jj = -90;
else else
@ -1204,7 +1194,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( kk ) { if ( kk ) {
if ( m1_xyt ) if ( 0 )
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -j / (float) kk ); fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -j / (float) kk );
else else
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) j / (float) kk ); fi = ( 180.0F / PI_SINGLE ) * atanf( (float) j / (float) kk );
@ -1224,7 +1214,7 @@ for ( k = 0; k < np - 1; k++ ) {
j += 360; j += 360;
} else { } else {
if ( m1_xyt ) { if ( 0 ) {
if ( j > 0 ) if ( j > 0 )
j = -90; j = -90;
else else
@ -1611,7 +1601,7 @@ if ( n ) {
notfound = 1; notfound = 1;
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) { if ( 0 ) {
int * llptr = lptr; int * llptr = lptr;
printf( "bz_sift(): n: looking for l=%d in [", l ); printf( "bz_sift(): n: looking for l=%d in [", l );
for ( i = 0; i < lim; i++ ) { for ( i = 0; i < lim; i++ ) {
@ -1657,7 +1647,7 @@ if ( t ) {
notfound = 1; notfound = 1;
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) { if ( 0 ) {
int * llptr = lptr; int * llptr = lptr;
printf( "bz_sift(): t: looking for kz=%d in [", kz ); printf( "bz_sift(): t: looking for kz=%d in [", kz );
for ( i = 0; i < lim; i++ ) { for ( i = 0; i < lim; i++ ) {

View file

@ -1,51 +1,43 @@
/******************************************************************************
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 https://fprint.freedesktop.org/us-export-control.html
*/
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -77,43 +69,6 @@ identified are necessarily the best available for the purpose.
/***********************************************************************/ /***********************************************************************/
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 */ /* 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;
}

View file

@ -1,51 +1,43 @@
/******************************************************************************
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 https://fprint.freedesktop.org/us-export-control.html
*/
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -177,47 +169,3 @@ 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;
}

View file

@ -1,51 +1,43 @@
/******************************************************************************
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 https://fprint.freedesktop.org/us-export-control.html
*/
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -91,6 +83,27 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
/**************************************************************************/ /**************************************************************************/
/* Globals used significantly by sift() */ /* Globals used significantly by sift() */
/**************************************************************************/ /**************************************************************************/
#ifdef TARGET_OS
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];
#else
int rq[ RQ_SIZE ] = {}; int rq[ RQ_SIZE ] = {};
int tq[ TQ_SIZE ] = {}; int tq[ TQ_SIZE ] = {};
int zz[ ZZ_SIZE ] = {}; int zz[ ZZ_SIZE ] = {};
@ -110,4 +123,5 @@ int rf[RF_SIZE_1][RF_SIZE_2] = {};
int cf[CF_SIZE_1][CF_SIZE_2] = {}; int cf[CF_SIZE_1][CF_SIZE_2] = {};
int y[20000] = {}; int y[20000] = {};
#endif

View file

@ -1,51 +1,43 @@
/******************************************************************************
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 https://fprint.freedesktop.org/us-export-control.html
*/
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -57,6 +49,9 @@ identified are necessarily the best available for the purpose.
MODIFICATIONS: Michael D. Garris (NIST) MODIFICATIONS: Michael D. Garris (NIST)
Stan Janet (NIST) Stan Janet (NIST)
DATE: 09/21/2004 DATE: 09/21/2004
UPDATED: 01/11/2012 by Kenneth Ko
UPDATED: 03/08/2012 by Kenneth Ko
UPDATED: 07/10/2014 by Kenneth Ko
Contains routines responsible for supporting command line Contains routines responsible for supporting command line
processing, file and data input to, and output from the processing, file and data input to, and output from the
@ -100,50 +95,7 @@ identified are necessarily the best available for the purpose.
#include <sys/time.h> #include <sys/time.h>
#include <bozorth.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;
}
/***********************************************************************/ /***********************************************************************/
@ -153,25 +105,10 @@ static char * pfile;
static char * gfile; 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 ) char * get_progname( void )
@ -192,171 +129,15 @@ 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 */ /* 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. Load a 3-4 column (X,Y,T[,Q]) set of minutiae from the specified file
and return a XYT sturcture.
Row 3's value is an angle which is normalized to the interval (-180,180]. 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 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 "DEFAULT_BOZORTH_MINUTIAE" is smaller. If the file contains more minutiae than are
@ -364,241 +145,14 @@ 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; */ Load a XYTQ structure and return a XYT struct.
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
#define C1 0 to be returned, the highest-quality minutiae are returned.
#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 #ifdef PARALLEL_SEARCH

View file

@ -1,51 +1,43 @@
/******************************************************************************
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 https://fprint.freedesktop.org/us-export-control.html
*/
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -78,23 +70,10 @@ identified are necessarily the best available for the purpose.
#include <bozorth.h> #include <bozorth.h>
/* These are now externally defined in bozorth.h */ /* These are now externally defined in bozorth.h */
/* extern FILE * stderr; */
/* extern char * get_progname( void ); */ /* 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 ) int sort_x_y( const void * a, const void * b )
@ -124,67 +103,18 @@ qsort_decreasing() - quicksort an array of integers in decreasing
and Ted Zwiesler, 1986] and Ted Zwiesler, 1986]
********************************************************/ ********************************************************/
/* Used by custom quicksort code below */ /* Used by custom quicksort code below */
static int stack[BZ_STACKSIZE];
static int * stack_pointer = stack;
/***********************************************************************/ /***********************************************************************/
/* return values: 0 == successful, 1 == error */ /* 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 */ /* 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() select_pivot()
selects a pivot from a list being sorted using the Singleton Method. 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;
}
}
}
}
/***********************************************************************/ /***********************************************************************/
/******************************************************** /********************************************************
@ -192,41 +122,6 @@ partition_dec()
Inputs a pivot element making comparisons and swaps with other elements in a list, Inputs a pivot element making comparisons and swaps with other elements in a list,
until pivot resides at its correct position in the 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;
}
}
}
}
/***********************************************************************/ /***********************************************************************/
/******************************************************** /********************************************************
@ -236,80 +131,6 @@ sorted, a left subscript pointing to where the sort is to begin in the index ar
subscript where to end. This module invokes a decreasing quick-sort sorting the index array from l to r. 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 */ /* 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 */ /* 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;
}

View file

@ -1,23 +1,43 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -163,7 +183,7 @@ struct cell {
}; };
/**************************************************************************/ /**************************************************************************/
/* In BZ_IO : Supports the loading and manipulation of XYT data */ /* In BZ_IO : Supports the loading and manipulation of XYT and XYTQ data */
/**************************************************************************/ /**************************************************************************/
#define MAX_FILE_MINUTIAE 1000 /* bz_load() */ #define MAX_FILE_MINUTIAE 1000 /* bz_load() */
@ -174,7 +194,17 @@ struct xyt_struct {
int thetacol[ MAX_BOZORTH_MINUTIAE ]; int thetacol[ MAX_BOZORTH_MINUTIAE ];
}; };
struct xytq_struct {
int nrows;
int xcol[ MAX_FILE_MINUTIAE ];
int ycol[ MAX_FILE_MINUTIAE ];
int thetacol[ MAX_FILE_MINUTIAE ];
int qualitycol[ MAX_FILE_MINUTIAE ];
};
#define XYT_NULL ( (struct xyt_struct *) NULL ) /* bz_load() */ #define XYT_NULL ( (struct xyt_struct *) NULL ) /* bz_load() */
#define XYTQ_NULL ( (struct xytq_struct *) NULL ) /* bz_load() */
/**************************************************************************/ /**************************************************************************/
@ -187,6 +217,8 @@ struct xyt_struct {
/**************************************************************************/ /**************************************************************************/
/* Globals supporting command line options */ /* Globals supporting command line options */
extern int verbose_threshold; extern int verbose_threshold;
/* Global supporting error reporting */
extern FILE *stderr;
/**************************************************************************/ /**************************************************************************/
/* In: BZ_GBLS.C */ /* In: BZ_GBLS.C */
@ -247,6 +279,7 @@ extern char *get_next_file(char *, FILE *, FILE *, int *, int *, char *,
extern char *get_score_filename(const char *, const char *); extern char *get_score_filename(const char *, const char *);
extern char *get_score_line(const char *, const char *, int, int, const char *); extern char *get_score_line(const char *, const char *, int, int, const char *);
extern struct xyt_struct *bz_load(const char *); extern struct xyt_struct *bz_load(const char *);
extern struct xyt_struct *bz_prune(struct xytq_struct *, int);
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 *);

View file

@ -1,23 +1,43 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/

View file

@ -1,23 +1,43 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -53,7 +73,6 @@ identified are necessarily the best available for the purpose.
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
#define sround(x) ((int) (((x)<0) ? (x)-0.5 : (x)+0.5)) #define sround(x) ((int) (((x)<0) ? (x)-0.5 : (x)+0.5))
#define sround_uint(x) ((unsigned int) (((x)<0) ? (x)-0.5 : (x)+0.5)) #define sround_uint(x) ((unsigned int) (((x)<0) ? (x)-0.5 : (x)+0.5))
#define xor(a, b) (!(a && b) && (a || b))
#define align_to_16(_v_) ((((_v_)+15)>>4)<<4) #define align_to_16(_v_) ((((_v_)+15)>>4)<<4)
#define align_to_32(_v_) ((((_v_)+31)>>5)<<5) #define align_to_32(_v_) ((((_v_)+31)>>5)<<5)
#ifndef CHUNKS #ifndef CHUNKS

View file

@ -1,23 +1,43 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
@ -33,6 +53,9 @@ identified are necessarily the best available for the purpose.
Comments added to guide changes to blocksize Comments added to guide changes to blocksize
or number of detected directions. or number of detected directions.
UPDATED: 03/11/2005 by MDG UPDATED: 03/11/2005 by MDG
UPDATED: 01/31/2008 by Kenneth Ko
UPDATED: 09/04/2008 by Kenneth Ko
UPDATED: 01/11/2012 by Kenneth Ko
FILE: LFS.H FILE: LFS.H
@ -160,7 +183,7 @@ typedef struct shape{
/* Parameters used by LFS for setting thresholds and */ /* Parameters used by LFS for setting thresholds and */
/* defining testing criterion. */ /* defining testing criterion. */
typedef struct lfsparms{ typedef struct g_lfsparms{
/* Image Controls */ /* Image Controls */
int pad_value; int pad_value;
int join_line_radius; int join_line_radius;
@ -236,8 +259,6 @@ typedef struct lfsparms{
int pores_steps_bwd; int pores_steps_bwd;
double pores_min_dist2; double pores_min_dist2;
double pores_max_ratio; double pores_max_ratio;
int remove_perimeter_pts;
int min_pp_distance;
/* Ridge Counting Controls */ /* Ridge Counting Controls */
int max_nbrs; int max_nbrs;
@ -587,9 +608,6 @@ typedef struct lfsparms{
/* contour points to be considered a pore. */ /* contour points to be considered a pore. */
#define PORES_MAX_RATIO 2.25 #define PORES_MAX_RATIO 2.25
/* Points which are closer than this distance to scan perimeter will be removed */
#define PERIMETER_PTS_DISTANCE 10
/***** RIDGE COUNTING CONSTANTS *****/ /***** RIDGE COUNTING CONSTANTS *****/
@ -689,15 +707,24 @@ typedef struct lfsparms{
/*************************************************************************/ /*************************************************************************/
/* binar.c */ /* binar.c */
extern int binarize(unsigned char **, int *, int *,
unsigned char *, const int, const int,
int *, const int, const int,
const ROTGRIDS *, const LFSPARMS *);
extern int binarize_V2(unsigned char **, int *, int *, extern int binarize_V2(unsigned char **, int *, int *,
unsigned char *, const int, const int, unsigned char *, const int, const int,
int *, const int, const int, int *, const int, const int,
const ROTGRIDS *, const LFSPARMS *); const ROTGRIDS *, const LFSPARMS *);
extern int binarize_image(unsigned char **, int *, int *,
unsigned char *, const int, const int,
const int *, const int, const int, const int,
const ROTGRIDS *, const int);
extern int binarize_image_V2(unsigned char **, int *, int *, extern int binarize_image_V2(unsigned char **, int *, int *,
unsigned char *, const int, const int, unsigned char *, const int, const int,
const int *, const int, const int, const int *, const int, const int,
const int, const ROTGRIDS *); const int, const ROTGRIDS *);
extern int dirbinarize(const unsigned char *, const int, const ROTGRIDS *); extern int dirbinarize(const unsigned char *, const int, const ROTGRIDS *);
extern int isobinarize(unsigned char *, const int, const int, const int);
/* block.c */ /* block.c */
extern int block_offsets(int **, int *, int *, const int, const int, extern int block_offsets(int **, int *, int *, const int, const int,
@ -709,9 +736,12 @@ extern int find_valid_block(int *, int *, int *, int *, int *,
const int, const int); const int, const int);
extern void set_margin_blocks(int *, const int, const int, const int); extern void set_margin_blocks(int *, const int, const int, const int);
/* chaincod.c */
extern int chain_code_loop(int **, int *, const int *, const int *, const int);
extern int is_chain_clockwise(const int *, const int, const int);
/* contour.c */ /* contour.c */
int allocate_contour(int **ocontour_x, int **ocontour_y, extern int allocate_contour(int **, int **, int **, int **, const int);
int **ocontour_ex, int **ocontour_ey, const int ncontour);
extern void free_contour(int *, int *, int *, int *); extern void free_contour(int *, int *, int *, int *);
extern int get_high_curvature_contour(int **, int **, int **, int **, int *, extern int get_high_curvature_contour(int **, int **, int **, int **, int *,
const int, const int, const int, const int, const int, const int, const int, const int, const int, const int,
@ -726,6 +756,11 @@ extern int trace_contour(int **, int **, int **, int **, int *,
extern int search_contour(const int, const int, const int, extern int search_contour(const int, const int, const int,
const int, const int, const int, const int, const int, const int, const int, const int, const int, const int,
unsigned char *, const int, const int); unsigned char *, const int, const int);
extern int next_contour_pixel(int *, int *, int *, int *,
const int, const int, const int, const int, const int,
unsigned char *, const int, const int);
extern int start_scan_nbr(const int, const int, const int, const int);
extern int next_scan_nbr(const int, const int);
extern int min_contour_theta(int *, double *, const int, const int *, extern int min_contour_theta(int *, double *, const int, const int *,
const int *, const int); const int *, const int);
extern void contour_limits(int *, int *, int *, int *, const int *, extern void contour_limits(int *, int *, int *, int *, const int *,
@ -734,18 +769,29 @@ extern void fix_edge_pixel_pair(int *, int *, int *, int *,
unsigned char *, const int, const int); unsigned char *, const int, const int);
/* detect.c */ /* detect.c */
extern int get_minutiae(MINUTIAE **, int **, int **, int **, extern int lfs_detect_minutiae( MINUTIAE **,
int **, int **, int *, int *, int **, int **, int *, int *,
unsigned char **, int *, int *, int *, unsigned char **, int *, int *,
unsigned char *, const int, const int, unsigned char *, const int, const int,
const int, const double, const LFSPARMS *); const LFSPARMS *);
extern int lfs_detect_minutiae_V2(MINUTIAE **,
int **, int **, int **, int **, int *, int *,
unsigned char **, int *, int *,
unsigned char *, const int, const int,
const LFSPARMS *);
/* dft.c */ /* dft.c */
extern int dft_dir_powers(double **, unsigned char *, const int, extern int dft_dir_powers(double **, unsigned char *, const int,
const int, const int, const DFTWAVES *, const int, const int, const DFTWAVES *,
const ROTGRIDS *); const ROTGRIDS *);
extern void sum_rot_block_rows(int *, const unsigned char *, const int *,
const int);
extern void dft_power(double *, const int *, const DFTWAVE *, const int);
extern int dft_power_stats(int *, double *, int *, double *, double **, extern int dft_power_stats(int *, double *, int *, double *, double **,
const int, const int, const int); const int, const int, const int);
extern void get_max_norm(double *, int *, double *, const double *, const int);
extern int sort_dft_waves(int *, const double *, const double *, const int);
/* free.c */ /* free.c */
extern void free_dir2rad(DIR2RAD *); extern void free_dir2rad(DIR2RAD *);
@ -753,6 +799,13 @@ extern void free_dftwaves(DFTWAVES *);
extern void free_rotgrids(ROTGRIDS *); extern void free_rotgrids(ROTGRIDS *);
extern void free_dir_powers(double **, const int); extern void free_dir_powers(double **, const int);
/* getmin.c */
extern int get_minutiae(MINUTIAE **, int **, int **, int **,
int **, int **, int *, int *,
unsigned char **, int *, int *, int *,
unsigned char *, const int, const int,
const int, const double, const LFSPARMS *);
/* imgutil.c */ /* imgutil.c */
extern void bits_6to8(unsigned char *, const int, const int); extern void bits_6to8(unsigned char *, const int, const int);
extern void bits_8to6(unsigned char *, const int, const int); extern void bits_8to6(unsigned char *, const int, const int);
@ -771,15 +824,41 @@ extern int search_in_direction(int *, int *, int *, int *, const int,
/* init.c */ /* init.c */
extern int init_dir2rad(DIR2RAD **, const int); extern int init_dir2rad(DIR2RAD **, const int);
extern int init_dftwaves(DFTWAVES **, const double *, const int, const int); extern int init_dftwaves(DFTWAVES **, const double *, const int, const int);
extern int get_max_padding(const int, const int, const int, const int);
extern int get_max_padding_V2(const int, const int, const int, const int); extern int get_max_padding_V2(const int, const int, const int, const int);
extern int init_rotgrids(ROTGRIDS **, const int, const int, const int, extern int init_rotgrids(ROTGRIDS **, const int, const int, const int,
const double, const int, const int, const int, const int); const double, const int, const int, const int, const int);
extern int alloc_dir_powers(double ***, const int, const int); extern int alloc_dir_powers(double ***, const int, const int);
extern int alloc_power_stats(int **, double **, int **, double **, const int); extern int alloc_power_stats(int **, double **, int **, double **, const int);
/* isempty.c */
extern int is_image_empty(int *, const int, const int);
extern int is_qmap_empty(int *, const int, const int);
/* line.c */ /* line.c */
extern int line_points(int **, int **, int *, extern int line_points(int **, int **, int *,
const int, const int, const int, const int); const int, const int, const int, const int);
extern int bresenham_line_points(int **, int **, int *,
const int, const int, const int, const int);
/* link.c */
extern int link_minutiae(MINUTIAE *, unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int create_link_table(int **, int **, int **, int *, int *, int *,
const int, const int, const MINUTIAE *, const int *,
int *, const int, const int, unsigned char *,
const int, const int, const LFSPARMS *);
extern int update_link_table(int *, int *, int *, int *, int *, int *,
const int, int *, int *, int *, int *,
const int, const int, const int);
extern int order_link_table(int *, int *, int *, const int, const int,
const int, const int, const MINUTIAE *, const int);
extern int process_link_table(const int *, const int *, const int *,
const int, const int, const int, const int, MINUTIAE *,
int *, unsigned char *, const int, const int,
const LFSPARMS *);
extern double link_score(const double, const double, const LFSPARMS *);
/* loop.c */ /* loop.c */
extern int get_loop_list(int **, MINUTIAE *, const int, unsigned char *, extern int get_loop_list(int **, MINUTIAE *, const int, unsigned char *,
@ -799,8 +878,16 @@ extern int process_loop_V2(MINUTIAE *, const int *, const int *,
const int *, const int *, const int, const int *, const int *, const int,
unsigned char *, const int, const int, unsigned char *, const int, const int,
int *, const LFSPARMS *); int *, const LFSPARMS *);
extern void get_loop_aspect(int *, int *, double *, int *, int *, double *,
const int *, const int *, const int);
extern int fill_loop(const int *, const int *, const int, extern int fill_loop(const int *, const int *, const int,
unsigned char *, const int, const int); unsigned char *, const int, const int);
extern void fill_partial_row(const int, const int, const int, const int,
unsigned char *, const int, const int);
extern void flood_loop(const int *, const int *, const int,
unsigned char *, const int, const int);
extern void flood_fill4(const int, const int, const int,
unsigned char *, const int, const int);
/* maps.c */ /* maps.c */
extern int gen_image_maps(int **, int **, int **, int **, int *, int *, extern int gen_image_maps(int **, int **, int **, int **, int *, int *,
@ -820,6 +907,10 @@ extern void smooth_direction_map(int *, int *, const int, const int,
const DIR2RAD *, const LFSPARMS *); const DIR2RAD *, const LFSPARMS *);
extern int gen_high_curve_map(int **, int *, const int, const int, extern int gen_high_curve_map(int **, int *, const int, const int,
const LFSPARMS *); const LFSPARMS *);
extern int gen_imap(int **, int *, int *,
unsigned char *, const int, const int,
const DIR2RAD *, const DFTWAVES *, const ROTGRIDS *,
const LFSPARMS *);
extern int gen_initial_imap(int **, int *, const int, const int, extern int gen_initial_imap(int **, int *, const int, const int,
unsigned char *, const int, const int, unsigned char *, const int, const int,
const DFTWAVES *, const ROTGRIDS *, const LFSPARMS *); const DFTWAVES *, const ROTGRIDS *, const LFSPARMS *);
@ -850,6 +941,7 @@ extern void average_8nbr_dir(int *, double *, int *, int *, const int,
extern int num_valid_8nbrs(int *, const int, const int, const int, const int); extern int num_valid_8nbrs(int *, const int, const int, const int, const int);
extern void smooth_imap(int *, const int, const int, const DIR2RAD *, extern void smooth_imap(int *, const int, const int, const DIR2RAD *,
const LFSPARMS *); const LFSPARMS *);
extern int gen_nmap(int **, int *, const int, const int, const LFSPARMS *);
extern int vorticity(int *, const int, const int, const int, const int, extern int vorticity(int *, const int, const int, const int, const int,
const int); const int);
extern void accum_nbr_vorticity(int *, const int, const int, const int); extern void accum_nbr_vorticity(int *, const int, const int, const int);
@ -868,6 +960,9 @@ extern void skip_repeated_vertical_pair(int *, const int,
/* minutia.c */ /* minutia.c */
extern int alloc_minutiae(MINUTIAE **, const int); extern int alloc_minutiae(MINUTIAE **, const int);
extern int realloc_minutiae(MINUTIAE *, const int); extern int realloc_minutiae(MINUTIAE *, const int);
extern int detect_minutiae(MINUTIAE *, unsigned char *, const int, const int,
const int *, const int *, const int, const int,
const LFSPARMS *);
extern int detect_minutiae_V2(MINUTIAE *, extern int detect_minutiae_V2(MINUTIAE *,
unsigned char *, const int, const int, unsigned char *, const int, const int,
int *, int *, int *, const int, const int, int *, int *, int *, const int, const int,
@ -972,8 +1067,6 @@ extern int adjust_high_curvature_minutia_V2(int *, int *, int *,
int *, MINUTIAE *, const LFSPARMS *); int *, MINUTIAE *, const LFSPARMS *);
extern int get_low_curvature_direction(const int, const int, const int, extern int get_low_curvature_direction(const int, const int, const int,
const int); const int);
void lfs2nist_minutia_XYT(int *ox, int *oy, int *ot,
const MINUTIA *minutia, const int iw, const int ih);
/* quality.c */ /* quality.c */
extern int gen_quality_map(int **, int *, int *, int *, int *, extern int gen_quality_map(int **, int *, int *, int *, int *,
@ -981,6 +1074,12 @@ extern int gen_quality_map(int **, int *, int *, int *, int *,
extern int combined_minutia_quality(MINUTIAE *, int *, const int, const int, extern int combined_minutia_quality(MINUTIAE *, int *, const int, const int,
const int, unsigned char *, const int, const int, const int, unsigned char *, const int, const int,
const int, const double); const int, const double);
double grayscale_reliability(MINUTIA *, unsigned char *,
const int, const int, const int);
extern void get_neighborhood_stats(double *, double *, MINUTIA *,
unsigned char *, const int, const int, const int);
extern int reliability_fr_quality_map(MINUTIAE *, int *, const int,
const int, const int, const int, const int);
/* remove.c */ /* remove.c */
extern int remove_false_minutia(MINUTIAE *, extern int remove_false_minutia(MINUTIAE *,
@ -990,15 +1089,93 @@ extern int remove_false_minutia_V2(MINUTIAE *,
unsigned char *, const int, const int, unsigned char *, const int, const int,
int *, int *, int *, const int, const int, int *, int *, int *, const int, const int,
const LFSPARMS *); const LFSPARMS *);
extern int remove_holes(MINUTIAE *, unsigned char *, const int, const int,
const LFSPARMS *);
extern int remove_hooks(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_hooks_islands_lakes_overlaps(MINUTIAE *, unsigned char *,
const int, const int, const LFSPARMS *);
extern int remove_islands_and_lakes(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_malformations(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int remove_near_invblock(MINUTIAE *, int *, const int, const int,
const LFSPARMS *);
extern int remove_near_invblock_V2(MINUTIAE *, int *,
const int, const int, const LFSPARMS *);
extern int remove_pointing_invblock(MINUTIAE *, int *, const int, const int,
const LFSPARMS *);
extern int remove_pointing_invblock_V2(MINUTIAE *,
int *, const int, const int, const LFSPARMS *);
extern int remove_overlaps(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_pores(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int remove_pores_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, int *, int *, const int, const int,
const LFSPARMS *);
extern int remove_or_adjust_side_minutiae(MINUTIAE *, unsigned char *,
const int, const int, const LFSPARMS *);
extern int remove_or_adjust_side_minutiae_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
/* results.c */
extern int write_text_results(char *, const int, const int, const int,
const MINUTIAE *, int *, int *, int *, int *, int *,
const int, const int);
extern int write_minutiae_XYTQ(char *ofile, const int,
const MINUTIAE *, const int, const int);
extern void dump_map(FILE *, int *, const int, const int);
extern int drawimap(int *, const int, const int, unsigned char *,
const int, const int, const ROTGRIDS *, const int);
extern void drawimap2(int *, const int *, const int, const int,
unsigned char *, const int, const int,
const double, const int, const int);
extern void drawblocks(const int *, const int, const int,
unsigned char *, const int, const int, const int );
extern int drawrotgrid(const ROTGRIDS *, const int, unsigned char *,
const int, const int, const int, const int);
extern void dump_link_table(FILE *, const int *, const int *, const int *,
const int, const int, const int, const MINUTIAE *);
extern int draw_direction_map(char *, int *,
int *, const int, const int, const int,
unsigned char *, const int, const int, const int);
extern int draw_TF_map(char *, int *,
int *, const int, const int, const int,
unsigned char *, const int, const int, const int);
/* ridges.c */ /* ridges.c */
extern int count_minutiae_ridges(MINUTIAE *, extern int count_minutiae_ridges(MINUTIAE *,
unsigned char *, const int, const int, unsigned char *, const int, const int,
const LFSPARMS *); const LFSPARMS *);
extern int count_minutia_ridges(const int, MINUTIAE *,
unsigned char *, const int, const int,
const LFSPARMS *);
extern int find_neighbors(int **, int *, const int, const int, MINUTIAE *);
extern int update_nbr_dists(int *, double *, int *, const int,
const int, const int, MINUTIAE *);
extern int insert_neighbor(const int, const int, const double,
int *, double *, int *, const int);
extern int sort_neighbors(int *, const int, const int, MINUTIAE *);
extern int ridge_count(const int, const int, MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int find_transition(int *, const int, const int,
const int *, const int *, const int,
unsigned char *, const int, const int);
extern int validate_ridge_crossing(const int, const int,
const int *, const int *, const int,
unsigned char *, const int, const int, const int);
/* shape.c */ /* shape.c */
extern int alloc_shape(SHAPE **, const int, const int, const int, const int);
extern void free_shape(SHAPE *); extern void free_shape(SHAPE *);
extern void dump_shape(FILE *, const SHAPE *);
extern int shape_from_contour(SHAPE **, const int *, const int *, const int); extern int shape_from_contour(SHAPE **, const int *, const int *, const int);
extern void sort_row_on_x(ROW *);
/* sort.c */ /* sort.c */
extern int sort_indices_int_inc(int **, int *, const int); extern int sort_indices_int_inc(int **, int *, const int);
@ -1023,6 +1200,12 @@ extern int line2direction(const int, const int, const int, const int,
const int); const int);
extern int closest_dir_dist(const int, const int, const int); extern int closest_dir_dist(const int, const int, const int);
/* xytreps.c */
extern void lfs2nist_minutia_XYT(int *, int *, int *,
const MINUTIA *, const int, const int);
extern void lfs2m1_minutia_XYT(int *, int *, int *, const MINUTIA *);
extern void lfs2nist_format(MINUTIAE *, int, int);
/*************************************************************************/ /*************************************************************************/
/* EXTERNAL GLOBAL VARIABLE DEFINITIONS */ /* EXTERNAL GLOBAL VARIABLE DEFINITIONS */
/*************************************************************************/ /*************************************************************************/

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
#ifndef _LOG_H #ifndef _LOG_H
#define _LOG_H #define _LOG_H
@ -36,10 +57,6 @@ identified are necessarily the best available for the purpose.
#define LOG_FILE "log.txt" #define LOG_FILE "log.txt"
#endif #endif
extern FILE *g_logfp;
extern int g_avrdir;
extern float g_dir_strength;
extern int g_nvalid;
extern int open_logfile(void); extern int open_logfile(void);
extern int close_logfile(void); extern int close_logfile(void);

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
#ifndef __MORPH_H__ #ifndef __MORPH_H__
#define __MORPH_H__ #define __MORPH_H__

View file

@ -0,0 +1,106 @@
/*******************************************************************************
License:
This software and/or related materials 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.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials 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.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
#ifndef _MYTIME_H
#define _MYTIME_H
/* this file needed to support timer and ticks */
/* UPDATED: 03/16/2005 by MDG */
#ifdef TIMER
#include <sys/types.h>
#endif
#ifdef __MSYS__
#include <sys/time.h>
#else
#include <sys/times.h>
#endif
#ifdef TIMER
#define set_timer(_timer_); \
{ \
_timer_ = ticks();
#else
#define set_timer(_timer_);
#endif
#ifdef TIMER
#define time_accum(_timer_, _var_); \
_var_ += (ticks() - _timer_)/(float)ticksPerSec(); \
}
#else
#define time_accum(_timer_, _var_);
#endif
#ifdef TIMER
#define print_time(_fp_, _fmt_, _var_); \
fprintf(_fp_, _fmt_, _var_);
#else
#define print_time(_fp_, _fmt_, _var_);
#endif
extern clock_t ticks(void);
extern int ticksPerSec(void);
extern clock_t total_timer;
extern float total_time;
extern clock_t imap_timer;
extern float imap_time;
extern clock_t bin_timer;
extern float bin_time;
extern clock_t minutia_timer;
extern float minutia_time;
extern clock_t rm_minutia_timer;
extern float rm_minutia_time;
extern clock_t ridge_count_timer;
extern float ridge_count_time;
#endif

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
#ifndef _SUNRAST_H #ifndef _SUNRAST_H
#define _SUNRAST_H #define _SUNRAST_H

View file

@ -0,0 +1,58 @@
--- include/lfs.h 2018-08-24 15:31:54.535579623 +0200
+++ include/lfs.h.orig 2018-08-24 15:31:48.781587933 +0200
@@ -66,7 +43,7 @@ of the software.
#include <math.h>
#include <stdio.h>
-#include <an2k.h> /* Needed by to_type9.c */
+#include <fp_internal.h>
/*************************************************************************/
/* OUTPUT FILE EXTENSIONS */
@@ -154,26 +131,8 @@ typedef struct rotgrids{
#define DISAPPEARING 0
#define APPEARING 1
-typedef struct minutia{
- int x;
- int y;
- int ex;
- int ey;
- int direction;
- double reliability;
- int type;
- int appearing;
- int feature_id;
- int *nbrs;
- int *ridge_counts;
- int num_nbrs;
-} MINUTIA;
-
-typedef struct minutiae{
- int alloc;
- int num;
- MINUTIA **list;
-} MINUTIAE;
+typedef struct fp_minutia MINUTIA;
+typedef struct fp_minutiae MINUTIAE;
typedef struct feature_pattern{
int type;
@@ -1185,17 +1185,6 @@ extern void bubble_sort_double_inc_2(double *, int *, const int);
extern void bubble_sort_double_dec_2(double *, int *, const int);
extern void bubble_sort_int_inc(int *, const int);
-/* to_type9.c */
-extern int minutiae2type_9(RECORD **, const int, MINUTIAE *, const int,
- const int, const double);
-extern int mintiae2field_12(FIELD **, MINUTIAE *, const int, const int,
- const double);
-
-/* update.c */
-extern int update_ANSI_NIST_lfs_results(ANSI_NIST *, MINUTIAE *,
- unsigned char *, const int, const int,
- const int, const double, const int, const int);
-
/* util.c */
extern int maxv(const int *, const int);
extern int minv(const int *, const int);

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -36,16 +57,44 @@ identified are necessarily the best available for the purpose.
*********************************************************************** ***********************************************************************
ROUTINES: ROUTINES:
binarize()
binarize_V2() binarize_V2()
binarize_image()
binarize_image_V2() binarize_image_V2()
dirbinarize() dirbinarize()
isobinarize()
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/*************************************************************************
**************************************************************************
#cat: binarize - Takes a padded grayscale input image and its associated ridge
#cat: direction flow NMAP and produces a binarized version of the
#cat: image. It then fills horizontal and vertical "holes" in the
#cat: binary image results.
Input:
pdata - padded input grayscale image
pw - padded width (in pixels) of input image
ph - padded height (in pixels) of input image
nmap - 2-D vector of IMAP directions and other codes
mw - width (in blocks) of the NMAP
mh - height (in blocks) of the NMAP
dirbingrids - set of rotated grid offsets used for directional
binarization
lfsparms - parameters and thresholds for controlling LFS
Output:
optr - points to created (unpadded) binary image
ow - width of binary image
oh - height of binary image
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: binarize_V2 - Takes a padded grayscale input image and its associated #cat: binarize_V2 - Takes a padded grayscale input image and its associated
@ -101,6 +150,32 @@ int binarize_V2(unsigned char **odata, int *ow, int *oh,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: binarize_image - Takes a grayscale input image and its associated
#cat: NMAP and generates a binarized version of the image.
Input:
pdata - padded input grayscale image
pw - padded width (in pixels) of input image
ph - padded height (in pixels) of input image
nmap - 2-D vector of IMAP directions and other codes
mw - width (in blocks) of the NMAP
mh - height (in blocks) of the NMAP
imap_blocksize - dimension (in pixels) of each NMAP block
dirbingrids - set of rotated grid offsets used for directional
binarization
isobin_grid_dim - dimension (in pixels) of grid used for isotropic
binarization
Output:
optr - points to binary image results
ow - points to binary image width
oh - points to binary image height
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: binarize_image_V2 - Takes a grayscale input image and its associated #cat: binarize_image_V2 - Takes a grayscale input image and its associated
@ -247,3 +322,27 @@ int dirbinarize(const unsigned char *pptr, const int idir,
return(WHITE_PIXEL); return(WHITE_PIXEL);
} }
/*************************************************************************
**************************************************************************
#cat: isobinarize - Determines the binary value of a grayscale pixel based
#cat: on comparing the grayscale value with a surrounding
#cat: neighborhood grid of pixels. If the current pixel (treated
#cat: as an average) is less than the sum of the pixels in
#cat: the neighborhood, then the binary value is set to BLACK,
#cat: otherwise it is set to WHITE. This binarization technique
#cat: is used when there is no VALID IMAP direction for the
#cat: block in which the current pixel resides.
CAUTION: The image to which the input pixel points must be appropriately
padded to account for the radius of the neighborhood. Otherwise,
this routine may access "unkown" memory.
Input:
pptr - pointer to curent grayscale pixel
pw - padded width (in pixels) of the grayscale image
ph - padded height (in pixels) of the grayscale image
isobin_grid_dim - dimension (in pixels) of the neighborhood
Return Code:
BLACK_PIXEL - pixel intensity for BLACK
WHITE_PIXEL - pixel intensity of WHITE
**************************************************************************/

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -44,8 +65,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lfs.h> #include <lfs.h>
/************************************************************************* /*************************************************************************
@ -96,7 +115,7 @@ int block_offsets(int **optr, int *ow, int *oh,
return(-80); return(-80);
} }
/* Compute padded width and height of image */ /* Compute padded width of image */
pad2 = pad<<1; pad2 = pad<<1;
pw = iw + pad2; pw = iw + pad2;

View file

@ -0,0 +1,211 @@
/*******************************************************************************
License:
This software and/or related materials 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.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials 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.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
FILE: CHAINCODE.C
AUTHOR: Michael D. Garris
DATE: 05/11/1999
Contains routines responsible for generating and manipulating
chain codes as part of the NIST Latent Fingerprint System (LFS).
***********************************************************************
ROUTINES:
chain_code_loop()
is_chain_clockwise()
***********************************************************************/
#include <stdio.h>
#include <lfs.h>
/*************************************************************************
**************************************************************************
#cat: chain_code_loop - Converts a feature's contour points into an
#cat: 8-connected chain code vector. This encoding represents
#cat: the direction taken between each adjacent point in the
#cat: contour. Chain codes may be used for many purposes, such
#cat: as computing the perimeter or area of an object, and they
#cat: may be used in object detection and recognition.
Input:
contour_x - x-coord list for feature's contour points
contour_y - y-coord list for feature's contour points
ncontour - number of points in contour
Output:
ochain - resulting vector of chain codes
onchain - number of codes in chain
(same as number of points in contour)
Return Code:
Zero - chain code successful derived
Negative - system error
**************************************************************************/
int chain_code_loop(int **ochain, int *onchain,
const int *contour_x, const int *contour_y, const int ncontour)
{
int *chain;
int i, j, dx, dy;
/* If we don't have at least 3 points in the contour ... */
if(ncontour <= 3){
/* Then we don't have a loop, so set chain length to 0 */
/* and return without any allocations. */
*onchain = 0;
return(0);
}
/* Allocate chain code vector. It will be the same length as the */
/* number of points in the contour. There will be one chain code */
/* between each point on the contour including a code between the */
/* last to the first point on the contour (completing the loop). */
chain = (int *)malloc(ncontour * sizeof(int));
/* If the allocation fails ... */
if(chain == (int *)NULL){
fprintf(stderr, "ERROR : chain_code_loop : malloc : chain\n");
return(-170);
}
/* For each neighboring point in the list (with "i" pointing to the */
/* previous neighbor and "j" pointing to the next neighbor... */
for(i = 0, j=1; i < ncontour-1; i++, j++){
/* Compute delta in X between neighbors. */
dx = contour_x[j] - contour_x[i];
/* Compute delta in Y between neighbors. */
dy = contour_y[j] - contour_y[i];
/* Derive chain code index from neighbor deltas. */
/* The deltas are on the range [-1..1], so to use them as indices */
/* into the code list, they must first be incremented by one. */
chain[i] = *(g_chaincodes_nbr8+((dy+1)*NBR8_DIM)+dx+1);
}
/* Now derive chain code between last and first points in the */
/* contour list. */
dx = contour_x[0] - contour_x[i];
dy = contour_y[0] - contour_y[i];
chain[i] = *(g_chaincodes_nbr8+((dy+1)*NBR8_DIM)+dx+1);
/* Store results to the output pointers. */
*ochain = chain;
*onchain = ncontour;
/* Return normally. */
return(0);
}
/*************************************************************************
**************************************************************************
#cat: is_chain_clockwise - Takes an 8-connected chain code vector and
#cat: determines if the codes are ordered clockwise or
#cat: counter-clockwise.
#cat: The routine also requires a default return value be
#cat: specified in the case the the routine is not able to
#cat: definitively determine the chains direction. This allows
#cat: the default response to be application-specific.
Input:
chain - chain code vector
nchain - number of codes in chain
default_ret - default return code (used when we can't tell the order)
Return Code:
TRUE - chain determined to be ordered clockwise
FALSE - chain determined to be ordered counter-clockwise
Default - could not determine the order of the chain
**************************************************************************/
int is_chain_clockwise(const int *chain, const int nchain,
const int default_ret)
{
int i, j, d, sum;
/* Initialize turn-accumulator to 0. */
sum = 0;
/* Foreach neighboring code in chain, compute the difference in */
/* direction and accumulate. Left-hand turns increment, whereas */
/* right-hand decrement. */
for(i = 0, j =1; i < nchain-1; i++, j++){
/* Compute delta in neighbor direction. */
d = chain[j] - chain[i];
/* Make the delta the "inner" distance. */
/* If delta >= 4, for example if chain_i==2 and chain_j==7 (which */
/* means the contour went from a step up to step down-to-the-right) */
/* then 5=(7-2) which is >=4, so -3=(5-8) which means that the */
/* change in direction is a righ-hand turn of 3 units). */
if(d >= 4)
d -= 8;
/* If delta <= -4, for example if chain_i==7 and chain_j==2 (which */
/* means the contour went from a step down-to-the-right to step up) */
/* then -5=(2-7) which is <=-4, so 3=(-5+8) which means that the */
/* change in direction is a left-hand turn of 3 units). */
else if (d <= -4)
d += 8;
/* The delta direction is then accumulated. */
sum += d;
}
/* Now we need to add in the final delta direction between the last */
/* and first codes in the chain. */
d = chain[0] - chain[i];
if(d >= 4)
d -= 8;
else if (d <= -4)
d += 8;
sum += d;
/* If the final turn_accumulator == 0, then we CAN'T TELL the */
/* direction of the chain code, so return the default return value. */
if(sum == 0)
return(default_ret);
/* Otherwise, if the final turn-accumulator is positive ... */
else if(sum > 0)
/* Then we had a greater amount of left-hand turns than right-hand */
/* turns, so the chain is in COUNTER-CLOCKWISE order, so return FALSE. */
return(FALSE);
/* Otherwise, the final turn-accumulator is negative ... */
else
/* So we had a greater amount of right-hand turns than left-hand */
/* turns, so the chain is in CLOCKWISE order, so return TRUE. */
return(TRUE);
}

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -50,7 +71,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/************************************************************************* /*************************************************************************
@ -591,236 +611,6 @@ int get_centered_contour(int **ocontour_x, int **ocontour_y,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: start_scan_nbr - Takes a two pixel coordinates that are either
#cat: aligned north-to-south or east-to-west, and returns the
#cat: position the second pixel is in realtionship to the first.
#cat: The positions returned are based on 8-connectedness.
#cat: NOTE, this routine does NOT account for diagonal positions.
Input:
x_prev - x-coord of first point
y_prev - y-coord of first point
x_next - x-coord of second point
y_next - y-coord of second point
Return Code:
NORTH - second pixel above first
SOUTH - second pixel below first
EAST - second pixel right of first
WEST - second pixel left of first
**************************************************************************/
static int start_scan_nbr(const int x_prev, const int y_prev,
const int x_next, const int y_next)
{
if((x_prev==x_next) && (y_next > y_prev))
return(SOUTH);
else if ((x_prev==x_next) && (y_next < y_prev))
return(NORTH);
else if ((x_next > x_prev) && (y_prev==y_next))
return(EAST);
else if ((x_next < x_prev) && (y_prev==y_next))
return(WEST);
/* Added by MDG on 03-16-05 */
/* Should never reach here. Added to remove compiler warning. */
return(INVALID_DIR); /* -1 */
}
/*************************************************************************
**************************************************************************
#cat: next_scan_nbr - Advances the given 8-connected neighbor index
#cat: on location in the specifiec direction (clockwise or
#cat: counter-clockwise).
Input:
nbr_i - current 8-connected neighbor index
scan_clock - direction in which the neighbor index is to be advanced
Return Code:
Next neighbor - 8-connected index of next neighbor
**************************************************************************/
static int next_scan_nbr(const int nbr_i, const int scan_clock)
{
int new_i;
/* If scanning neighbors clockwise ... */
if(scan_clock == SCAN_CLOCKWISE)
/* Advance one neighbor clockwise. */
new_i = (nbr_i+1)%8;
/* Otherwise, scanning neighbors counter-clockwise ... */
else
/* Advance one neighbor counter-clockwise. */
/* There are 8 pixels in the neighborhood, so to */
/* decrement with wrapping from 0 around to 7, add */
/* the nieghbor index by 7 and mod with 8. */
new_i = (nbr_i+7)%8;
/* Return the new neighbor index. */
return(new_i);
}
/*************************************************************************
**************************************************************************
#cat: next_contour_pixel - Takes a pixel coordinate of a point determined
#cat: to be on the interior edge of a feature (ridge or valley-
#cat: ending), and attempts to locate a neighboring pixel on the
#cat: feature's contour. Neighbors of the current feature pixel
#cat: are searched in a specified direction (clockwise or counter-
#cat: clockwise) and the first pair of adjacent/neigboring pixels
#cat: found with the first pixel having the color of the feature
#cat: and the second the opposite color are returned as the next
#cat: point on the contour. One exception happens when the new
#cat: point is on an "exposed" corner.
Input:
cur_x_loc - x-pixel coord of current point on feature's
interior contour
cur_y_loc - y-pixel coord of current point on feature's
interior contour
cur_x_edge - x-pixel coord of corresponding edge pixel
(exterior to feature)
cur_y_edge - y-pixel coord of corresponding edge pixel
(exterior to feature)
scan_clock - direction in which neighboring pixels are to be scanned
for the next contour pixel
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
Output:
next_x_loc - x-pixel coord of next point on feature's interior contour
next_y_loc - y-pixel coord of next point on feature's interior contour
next_x_edge - x-pixel coord of corresponding edge (exterior to feature)
next_y_edge - y-pixel coord of corresponding edge (exterior to feature)
Return Code:
TRUE - next contour point found and returned
FALSE - next contour point NOT found
**************************************************************************/
/*************************************************************************/
static int next_contour_pixel(int *next_x_loc, int *next_y_loc,
int *next_x_edge, int *next_y_edge,
const int cur_x_loc, const int cur_y_loc,
const int cur_x_edge, const int cur_y_edge,
const int scan_clock,
unsigned char *bdata, const int iw, const int ih)
{
int feature_pix, edge_pix;
int prev_nbr_pix, prev_nbr_x, prev_nbr_y;
int cur_nbr_pix, cur_nbr_x, cur_nbr_y;
int ni, nx, ny, npix;
int nbr_i, i;
/* Get the feature's pixel value. */
feature_pix = *(bdata + (cur_y_loc * iw) + cur_x_loc);
/* Get the feature's edge pixel value. */
edge_pix = *(bdata + (cur_y_edge * iw) + cur_x_edge);
/* Get the nieghbor position of the feature's edge pixel in relationship */
/* to the feature's actual position. */
/* REMEBER: The feature's position is always interior and on a ridge */
/* ending (black pixel) or (for bifurcations) on a valley ending (white */
/* pixel). The feature's edge pixel is an adjacent pixel to the feature */
/* pixel that is exterior to the ridge or valley ending and opposite in */
/* pixel value. */
nbr_i = start_scan_nbr(cur_x_loc, cur_y_loc, cur_x_edge, cur_y_edge);
/* Set current neighbor scan pixel to the feature's edge pixel. */
cur_nbr_x = cur_x_edge;
cur_nbr_y = cur_y_edge;
cur_nbr_pix = edge_pix;
/* Foreach pixel neighboring the feature pixel ... */
for(i = 0; i < 8; i++){
/* Set current neighbor scan pixel to previous scan pixel. */
prev_nbr_x = cur_nbr_x;
prev_nbr_y = cur_nbr_y;
prev_nbr_pix = cur_nbr_pix;
/* Bump pixel neighbor index clockwise or counter-clockwise. */
nbr_i = next_scan_nbr(nbr_i, scan_clock);
/* Set current scan pixel to the new neighbor. */
/* REMEMBER: the neighbors are being scanned around the original */
/* feature point. */
cur_nbr_x = cur_x_loc + g_nbr8_dx[nbr_i];
cur_nbr_y = cur_y_loc + g_nbr8_dy[nbr_i];
/* If new neighbor is not within image boundaries... */
if((cur_nbr_x < 0) || (cur_nbr_x >= iw) ||
(cur_nbr_y < 0) || (cur_nbr_y >= ih))
/* Return (FALSE==>Failure) if neighbor out of bounds. */
return(FALSE);
/* Get the new neighbor's pixel value. */
cur_nbr_pix = *(bdata + (cur_nbr_y * iw) + cur_nbr_x);
/* If the new neighbor's pixel value is the same as the feature's */
/* pixel value AND the previous neighbor's pixel value is the same */
/* as the features's edge, then we have "likely" found our next */
/* contour pixel. */
if((cur_nbr_pix == feature_pix) && (prev_nbr_pix == edge_pix)){
/* Check to see if current neighbor is on the corner of the */
/* neighborhood, and if so, test to see if it is "exposed". */
/* The neighborhood corners have odd neighbor indicies. */
if(nbr_i % 2){
/* To do this, look ahead one more neighbor pixel. */
ni = next_scan_nbr(nbr_i, scan_clock);
nx = cur_x_loc + g_nbr8_dx[ni];
ny = cur_y_loc + g_nbr8_dy[ni];
/* If new neighbor is not within image boundaries... */
if((nx < 0) || (nx >= iw) ||
(ny < 0) || (ny >= ih))
/* Return (FALSE==>Failure) if neighbor out of bounds. */
return(FALSE);
npix = *(bdata + (ny * iw) + nx);
/* If the next neighbor's value is also the same as the */
/* feature's pixel, then corner is NOT exposed... */
if(npix == feature_pix){
/* Assign the current neighbor pair to the output pointers. */
*next_x_loc = cur_nbr_x;
*next_y_loc = cur_nbr_y;
*next_x_edge = prev_nbr_x;
*next_y_edge = prev_nbr_y;
/* Return TRUE==>Success. */
return(TRUE);
}
/* Otherwise, corner pixel is "exposed" so skip it. */
else{
/* Skip current corner neighbor by resetting it to the */
/* next neighbor, which upon the iteration will immediately */
/* become the previous neighbor. */
cur_nbr_x = nx;
cur_nbr_y = ny;
cur_nbr_pix = npix;
/* Advance neighbor index. */
nbr_i = ni;
/* Advance neighbor count. */
i++;
}
}
/* Otherwise, current neighbor is not a corner ... */
else{
/* Assign the current neighbor pair to the output pointers. */
*next_x_loc = cur_nbr_x;
*next_y_loc = cur_nbr_y;
*next_x_edge = prev_nbr_x;
*next_y_edge = prev_nbr_y;
/* Return TRUE==>Success. */
return(TRUE);
}
}
}
/* If we get here, then we did not find the next contour pixel */
/* within the 8 neighbors of the current feature pixel so */
/* return (FALSE==>Failure). */
/* NOTE: This must mean we found a single isolated pixel. */
/* Perhaps this should be filled? */
return(FALSE);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: trace_contour - Takes the pixel coordinate of a detected minutia #cat: trace_contour - Takes the pixel coordinate of a detected minutia
@ -1046,6 +836,236 @@ int search_contour(const int x_search, const int y_search,
return(NOT_FOUND); return(NOT_FOUND);
} }
/*************************************************************************
**************************************************************************
#cat: next_contour_pixel - Takes a pixel coordinate of a point determined
#cat: to be on the interior edge of a feature (ridge or valley-
#cat: ending), and attempts to locate a neighboring pixel on the
#cat: feature's contour. Neighbors of the current feature pixel
#cat: are searched in a specified direction (clockwise or counter-
#cat: clockwise) and the first pair of adjacent/neigboring pixels
#cat: found with the first pixel having the color of the feature
#cat: and the second the opposite color are returned as the next
#cat: point on the contour. One exception happens when the new
#cat: point is on an "exposed" corner.
Input:
cur_x_loc - x-pixel coord of current point on feature's
interior contour
cur_y_loc - y-pixel coord of current point on feature's
interior contour
cur_x_edge - x-pixel coord of corresponding edge pixel
(exterior to feature)
cur_y_edge - y-pixel coord of corresponding edge pixel
(exterior to feature)
scan_clock - direction in which neighboring pixels are to be scanned
for the next contour pixel
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
Output:
next_x_loc - x-pixel coord of next point on feature's interior contour
next_y_loc - y-pixel coord of next point on feature's interior contour
next_x_edge - x-pixel coord of corresponding edge (exterior to feature)
next_y_edge - y-pixel coord of corresponding edge (exterior to feature)
Return Code:
TRUE - next contour point found and returned
FALSE - next contour point NOT found
**************************************************************************/
/*************************************************************************/
int next_contour_pixel(int *next_x_loc, int *next_y_loc,
int *next_x_edge, int *next_y_edge,
const int cur_x_loc, const int cur_y_loc,
const int cur_x_edge, const int cur_y_edge,
const int scan_clock,
unsigned char *bdata, const int iw, const int ih)
{
int feature_pix, edge_pix;
int prev_nbr_pix, prev_nbr_x, prev_nbr_y;
int cur_nbr_pix, cur_nbr_x, cur_nbr_y;
int ni, nx, ny, npix;
int nbr_i, i;
/* Get the feature's pixel value. */
feature_pix = *(bdata + (cur_y_loc * iw) + cur_x_loc);
/* Get the feature's edge pixel value. */
edge_pix = *(bdata + (cur_y_edge * iw) + cur_x_edge);
/* Get the nieghbor position of the feature's edge pixel in relationship */
/* to the feature's actual position. */
/* REMEBER: The feature's position is always interior and on a ridge */
/* ending (black pixel) or (for bifurcations) on a valley ending (white */
/* pixel). The feature's edge pixel is an adjacent pixel to the feature */
/* pixel that is exterior to the ridge or valley ending and opposite in */
/* pixel value. */
nbr_i = start_scan_nbr(cur_x_loc, cur_y_loc, cur_x_edge, cur_y_edge);
/* Set current neighbor scan pixel to the feature's edge pixel. */
cur_nbr_x = cur_x_edge;
cur_nbr_y = cur_y_edge;
cur_nbr_pix = edge_pix;
/* Foreach pixel neighboring the feature pixel ... */
for(i = 0; i < 8; i++){
/* Set current neighbor scan pixel to previous scan pixel. */
prev_nbr_x = cur_nbr_x;
prev_nbr_y = cur_nbr_y;
prev_nbr_pix = cur_nbr_pix;
/* Bump pixel neighbor index clockwise or counter-clockwise. */
nbr_i = next_scan_nbr(nbr_i, scan_clock);
/* Set current scan pixel to the new neighbor. */
/* REMEMBER: the neighbors are being scanned around the original */
/* feature point. */
cur_nbr_x = cur_x_loc + g_nbr8_dx[nbr_i];
cur_nbr_y = cur_y_loc + g_nbr8_dy[nbr_i];
/* If new neighbor is not within image boundaries... */
if((cur_nbr_x < 0) || (cur_nbr_x >= iw) ||
(cur_nbr_y < 0) || (cur_nbr_y >= ih))
/* Return (FALSE==>Failure) if neighbor out of bounds. */
return(FALSE);
/* Get the new neighbor's pixel value. */
cur_nbr_pix = *(bdata + (cur_nbr_y * iw) + cur_nbr_x);
/* If the new neighbor's pixel value is the same as the feature's */
/* pixel value AND the previous neighbor's pixel value is the same */
/* as the features's edge, then we have "likely" found our next */
/* contour pixel. */
if((cur_nbr_pix == feature_pix) && (prev_nbr_pix == edge_pix)){
/* Check to see if current neighbor is on the corner of the */
/* neighborhood, and if so, test to see if it is "exposed". */
/* The neighborhood corners have odd neighbor indicies. */
if(nbr_i % 2){
/* To do this, look ahead one more neighbor pixel. */
ni = next_scan_nbr(nbr_i, scan_clock);
nx = cur_x_loc + g_nbr8_dx[ni];
ny = cur_y_loc + g_nbr8_dy[ni];
/* If new neighbor is not within image boundaries... */
if((nx < 0) || (nx >= iw) ||
(ny < 0) || (ny >= ih))
/* Return (FALSE==>Failure) if neighbor out of bounds. */
return(FALSE);
npix = *(bdata + (ny * iw) + nx);
/* If the next neighbor's value is also the same as the */
/* feature's pixel, then corner is NOT exposed... */
if(npix == feature_pix){
/* Assign the current neighbor pair to the output pointers. */
*next_x_loc = cur_nbr_x;
*next_y_loc = cur_nbr_y;
*next_x_edge = prev_nbr_x;
*next_y_edge = prev_nbr_y;
/* Return TRUE==>Success. */
return(TRUE);
}
/* Otherwise, corner pixel is "exposed" so skip it. */
else{
/* Skip current corner neighbor by resetting it to the */
/* next neighbor, which upon the iteration will immediately */
/* become the previous neighbor. */
cur_nbr_x = nx;
cur_nbr_y = ny;
cur_nbr_pix = npix;
/* Advance neighbor index. */
nbr_i = ni;
/* Advance neighbor count. */
i++;
}
}
/* Otherwise, current neighbor is not a corner ... */
else{
/* Assign the current neighbor pair to the output pointers. */
*next_x_loc = cur_nbr_x;
*next_y_loc = cur_nbr_y;
*next_x_edge = prev_nbr_x;
*next_y_edge = prev_nbr_y;
/* Return TRUE==>Success. */
return(TRUE);
}
}
}
/* If we get here, then we did not find the next contour pixel */
/* within the 8 neighbors of the current feature pixel so */
/* return (FALSE==>Failure). */
/* NOTE: This must mean we found a single isolated pixel. */
/* Perhaps this should be filled? */
return(FALSE);
}
/*************************************************************************
**************************************************************************
#cat: start_scan_nbr - Takes a two pixel coordinates that are either
#cat: aligned north-to-south or east-to-west, and returns the
#cat: position the second pixel is in realtionship to the first.
#cat: The positions returned are based on 8-connectedness.
#cat: NOTE, this routine does NOT account for diagonal positions.
Input:
x_prev - x-coord of first point
y_prev - y-coord of first point
x_next - x-coord of second point
y_next - y-coord of second point
Return Code:
NORTH - second pixel above first
SOUTH - second pixel below first
EAST - second pixel right of first
WEST - second pixel left of first
**************************************************************************/
int start_scan_nbr(const int x_prev, const int y_prev,
const int x_next, const int y_next)
{
if((x_prev==x_next) && (y_next > y_prev))
return(SOUTH);
else if ((x_prev==x_next) && (y_next < y_prev))
return(NORTH);
else if ((x_next > x_prev) && (y_prev==y_next))
return(EAST);
else if ((x_next < x_prev) && (y_prev==y_next))
return(WEST);
/* Added by MDG on 03-16-05 */
/* Should never reach here. Added to remove compiler warning. */
return(INVALID_DIR); /* -1 */
}
/*************************************************************************
**************************************************************************
#cat: next_scan_nbr - Advances the given 8-connected neighbor index
#cat: on location in the specifiec direction (clockwise or
#cat: counter-clockwise).
Input:
nbr_i - current 8-connected neighbor index
scan_clock - direction in which the neighbor index is to be advanced
Return Code:
Next neighbor - 8-connected index of next neighbor
**************************************************************************/
int next_scan_nbr(const int nbr_i, const int scan_clock)
{
int new_i;
/* If scanning neighbors clockwise ... */
if(scan_clock == SCAN_CLOCKWISE)
/* Advance one neighbor clockwise. */
new_i = (nbr_i+1)%8;
/* Otherwise, scanning neighbors counter-clockwise ... */
else
/* Advance one neighbor counter-clockwise. */
/* There are 8 pixels in the neighborhood, so to */
/* decrement with wrapping from 0 around to 7, add */
/* the nieghbor index by 7 and mod with 8. */
new_i = (nbr_i+7)%8;
/* Return the new neighbor index. */
return(new_i);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: min_contour_theta - Takes a contour list and analyzes it locating the #cat: min_contour_theta - Takes a contour list and analyzes it locating the

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -35,16 +56,46 @@ identified are necessarily the best available for the purpose.
*********************************************************************** ***********************************************************************
ROUTINES: ROUTINES:
lfs_detect_minutiae()
lfs_detect_minutiae_V2() lfs_detect_minutiae_V2()
get_minutiae()
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <lfs.h> #include <lfs.h>
#include <mytime.h>
#include <log.h> #include <log.h>
/*************************************************************************
#cat: lfs_detect_minutiae - Takes a grayscale fingerprint image (of arbitrary
#cat: size), and returns a map of directional ridge flow in the image
#cat: (2 versions), a binarized image designating ridges from valleys,
#cat: and a list of minutiae (including position, type, direction,
#cat: neighbors, and ridge counts to neighbors).
Input:
idata - input 8-bit grayscale fingerprint image data
iw - width (in pixels) of the image
ih - height (in pixels) of the image
lfsparms - parameters and thresholds for controlling LFS
Output:
ominutiae - resulting list of minutiae
oimap - resulting IMAP
{invalid (-1) or valid ridge directions}
onmap - resulting NMAP
{invalid (-1), high-curvature (-2), blanked blocks {-3} or
valid ridge directions}
omw - width (in blocks) of image maps
omh - height (in blocks) of image maps
obdata - resulting binarized image
{0 = black pixel (ridge) and 255 = white pixel (valley)}
obw - width (in pixels) of the binary image
obh - height (in pixels) of the binary image
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/************************************************************************* /*************************************************************************
#cat: lfs_detect_minutiae_V2 - Takes a grayscale fingerprint image (of #cat: lfs_detect_minutiae_V2 - Takes a grayscale fingerprint image (of
#cat: arbitrary size), and returns a set of image block maps, #cat: arbitrary size), and returns a set of image block maps,
@ -81,7 +132,7 @@ identified are necessarily the best available for the purpose.
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
int **odmap, int **olcmap, int **olfmap, int **ohcmap, int **odmap, int **olcmap, int **olfmap, int **ohcmap,
int *omw, int *omh, int *omw, int *omh,
unsigned char **obdata, int *obw, int *obh, unsigned char **obdata, int *obw, int *obh,
@ -99,6 +150,8 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
int ret, maxpad; int ret, maxpad;
MINUTIAE *minutiae; MINUTIAE *minutiae;
set_timer(total_timer);
/******************/ /******************/
/* INITIALIZATION */ /* INITIALIZATION */
/******************/ /******************/
@ -181,6 +234,7 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
/******************/ /******************/
/* MAPS */ /* MAPS */
/******************/ /******************/
set_timer(imap_timer);
/* Generate block maps from the input image. */ /* Generate block maps from the input image. */
if((ret = gen_image_maps(&direction_map, &low_contrast_map, if((ret = gen_image_maps(&direction_map, &low_contrast_map,
@ -200,9 +254,12 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
print2log("\nMAPS DONE\n"); print2log("\nMAPS DONE\n");
time_accum(imap_timer, imap_time);
/******************/ /******************/
/* BINARIZARION */ /* BINARIZARION */
/******************/ /******************/
set_timer(bin_timer);
/* Initialize lookup table for pixel offsets to rotated grids */ /* Initialize lookup table for pixel offsets to rotated grids */
/* used for directional binarization. */ /* used for directional binarization. */
@ -254,9 +311,12 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
print2log("\nBINARIZATION DONE\n"); print2log("\nBINARIZATION DONE\n");
time_accum(bin_timer, bin_time);
/******************/ /******************/
/* DETECTION */ /* DETECTION */
/******************/ /******************/
set_timer(minutia_timer);
/* Convert 8-bit grayscale binary image [0,255] to */ /* Convert 8-bit grayscale binary image [0,255] to */
/* 8-bit binary image [0,1]. */ /* 8-bit binary image [0,1]. */
@ -281,6 +341,10 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
return(ret); return(ret);
} }
time_accum(minutia_timer, minutia_time);
set_timer(rm_minutia_timer);
if((ret = remove_false_minutia_V2(minutiae, bdata, iw, ih, if((ret = remove_false_minutia_V2(minutiae, bdata, iw, ih,
direction_map, low_flow_map, high_curve_map, mw, mh, direction_map, low_flow_map, high_curve_map, mw, mh,
lfsparms))){ lfsparms))){
@ -297,9 +361,13 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
print2log("\nMINUTIA DETECTION DONE\n"); print2log("\nMINUTIA DETECTION DONE\n");
time_accum(rm_minutia_timer, rm_minutia_time);
/******************/ /******************/
/* RIDGE COUNTS */ /* RIDGE COUNTS */
/******************/ /******************/
set_timer(ridge_count_timer);
if((ret = count_minutiae_ridges(minutiae, bdata, iw, ih, lfsparms))){ if((ret = count_minutiae_ridges(minutiae, bdata, iw, ih, lfsparms))){
/* Free memory allocated to this point. */ /* Free memory allocated to this point. */
free(pdata); free(pdata);
@ -314,6 +382,8 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
print2log("\nNEIGHBOR RIDGE COUNT DONE\n"); print2log("\nNEIGHBOR RIDGE COUNT DONE\n");
time_accum(ridge_count_timer, ridge_count_time);
/******************/ /******************/
/* WRAP-UP */ /* WRAP-UP */
/******************/ /******************/
@ -337,6 +407,28 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
*obh = bh; *obh = bh;
*ominutiae = minutiae; *ominutiae = minutiae;
time_accum(total_timer, total_time);
/******************/
/* PRINT TIMINGS */
/******************/
/* These Timings will print when TIMER is defined. */
/* print MAP generation timing statistics */
print_time(stderr, "TIMER: MAPS time = %f (secs)\n", imap_time);
/* print binarization timing statistics */
print_time(stderr, "TIMER: Binarization time = %f (secs)\n", bin_time);
/* print minutia detection timing statistics */
print_time(stderr, "TIMER: Minutia Detection time = %f (secs)\n",
minutia_time);
/* print minutia removal timing statistics */
print_time(stderr, "TIMER: Minutia Removal time = %f (secs)\n",
rm_minutia_time);
/* print neighbor ridge count timing statistics */
print_time(stderr, "TIMER: Neighbor Ridge Counting time = %f (secs)\n",
ridge_count_time);
/* print total timing statistics */
print_time(stderr, "TIMER: Total time = %f (secs)\n", total_time);
/* If LOG_REPORT defined, close log report file. */ /* If LOG_REPORT defined, close log report file. */
if((ret = close_logfile())) if((ret = close_logfile()))
return(ret); return(ret);
@ -344,112 +436,3 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: get_minutiae - Takes a grayscale fingerprint image, binarizes the input
#cat: image, and detects minutiae points using LFS Version 2.
#cat: The routine passes back the detected minutiae, the
#cat: binarized image, and a set of image quality maps.
Input:
idata - grayscale fingerprint image data
iw - width (in pixels) of the grayscale image
ih - height (in pixels) of the grayscale image
id - pixel depth (in bits) of the grayscale image
ppmm - the scan resolution (in pixels/mm) of the grayscale image
lfsparms - parameters and thresholds for controlling LFS
Output:
ominutiae - points to a structure containing the
detected minutiae
oquality_map - resulting integrated image quality map
odirection_map - resulting direction map
olow_contrast_map - resulting low contrast map
olow_flow_map - resulting low ridge flow map
ohigh_curve_map - resulting high curvature map
omap_w - width (in blocks) of image maps
omap_h - height (in blocks) of image maps
obdata - points to binarized image data
obw - width (in pixels) of binarized image
obh - height (in pixels) of binarized image
obd - pixel depth (in bits) of binarized image
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
int get_minutiae(MINUTIAE **ominutiae, int **oquality_map,
int **odirection_map, int **olow_contrast_map,
int **olow_flow_map, int **ohigh_curve_map,
int *omap_w, int *omap_h,
unsigned char **obdata, int *obw, int *obh, int *obd,
unsigned char *idata, const int iw, const int ih,
const int id, const double ppmm, const LFSPARMS *lfsparms)
{
int ret;
MINUTIAE *minutiae = NULL;
int *direction_map = NULL, *low_contrast_map = NULL, *low_flow_map = NULL;
int *high_curve_map = NULL, *quality_map = NULL;
int map_w = 0, map_h = 0;
unsigned char *bdata = NULL;
int bw = 0, bh = 0;
/* If input image is not 8-bit grayscale ... */
if(id != 8){
fprintf(stderr, "ERROR : get_minutiae : input image pixel ");
fprintf(stderr, "depth = %d != 8.\n", id);
return(-2);
}
/* Detect minutiae in grayscale fingerpeint image. */
if((ret = lfs_detect_minutiae_V2(&minutiae,
&direction_map, &low_contrast_map,
&low_flow_map, &high_curve_map,
&map_w, &map_h,
&bdata, &bw, &bh,
idata, iw, ih, lfsparms))){
return(ret);
}
/* Build integrated quality map. */
if((ret = gen_quality_map(&quality_map,
direction_map, low_contrast_map,
low_flow_map, high_curve_map, map_w, map_h))){
free_minutiae(minutiae);
free(direction_map);
free(low_contrast_map);
free(low_flow_map);
free(high_curve_map);
free(bdata);
return(ret);
}
/* Assign reliability from quality map. */
if((ret = combined_minutia_quality(minutiae, quality_map, map_w, map_h,
lfsparms->blocksize,
idata, iw, ih, id, ppmm))){
free_minutiae(minutiae);
free(direction_map);
free(low_contrast_map);
free(low_flow_map);
free(high_curve_map);
free(quality_map);
free(bdata);
return(ret);
}
/* Set output pointers. */
*ominutiae = minutiae;
*oquality_map = quality_map;
*odirection_map = direction_map;
*olow_contrast_map = low_contrast_map;
*olow_flow_map = low_flow_map;
*ohigh_curve_map = high_curve_map;
*omap_w = map_w;
*omap_h = map_h;
*obdata = bdata;
*obw = bw;
*obh = bh;
*obd = id;
/* Return normally. */
return(0);
}

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -44,87 +65,8 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/*************************************************************************
**************************************************************************
#cat: sum_rot_block_rows - Computes a vector or pixel row sums by sampling
#cat: the current image block at a given orientation. The
#cat: sampling is conducted using a precomputed set of rotated
#cat: pixel offsets (called a grid) relative to the orgin of
#cat: the image block.
Input:
blkptr - the pixel address of the origin of the current image block
grid_offsets - the rotated pixel offsets for a block-sized grid
rotated according to a specific orientation
blocksize - the width and height of the image block and thus the size
of the rotated grid
Output:
rowsums - the resulting vector of pixel row sums
**************************************************************************/
static void sum_rot_block_rows(int *rowsums, const unsigned char *blkptr,
const int *grid_offsets, const int blocksize)
{
int ix, iy, gi;
/* Initialize rotation offset index. */
gi = 0;
/* For each row in block ... */
for(iy = 0; iy < blocksize; iy++){
/* The sums are accumlated along the rotated rows of the grid, */
/* so initialize row sum to 0. */
rowsums[iy] = 0;
/* Foreach column in block ... */
for(ix = 0; ix < blocksize; ix++){
/* Accumulate pixel value at rotated grid position in image */
rowsums[iy] += *(blkptr + grid_offsets[gi]);
gi++;
}
}
}
/*************************************************************************
**************************************************************************
#cat: dft_power - Computes the DFT power by applying a specific wave form
#cat: frequency to a vector of pixel row sums computed from a
#cat: specific orientation of the block image
Input:
rowsums - accumulated rows of pixels from within a rotated grid
overlaying an input image block
wave - the wave form (cosine and sine components) at a specific
frequency
wavelen - the length of the wave form (must match the height of the
image block which is the length of the rowsum vector)
Output:
power - the computed DFT power for the given wave form at the
given orientation within the image block
**************************************************************************/
static void dft_power(double *power, const int *rowsums,
const DFTWAVE *wave, const int wavelen)
{
int i;
double cospart, sinpart;
/* Initialize accumulators */
cospart = 0.0;
sinpart = 0.0;
/* Accumulate cos and sin components of DFT. */
for(i = 0; i < wavelen; i++){
/* Multiply each rotated row sum by its */
/* corresponding cos or sin point in DFT wave. */
cospart += (rowsums[i] * wave->cos[i]);
sinpart += (rowsums[i] * wave->sin[i]);
}
/* Power is the sum of the squared cos and sin components */
*power = (cospart * cospart) + (sinpart * sinpart);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: dft_dir_powers - Conducts the DFT analysis on a block of image data. #cat: dft_dir_powers - Conducts the DFT analysis on a block of image data.
@ -199,105 +141,80 @@ int dft_dir_powers(double **powers, unsigned char *pdata,
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: get_max_norm - Analyses a DFT power vector for a specific wave form #cat: sum_rot_block_rows - Computes a vector or pixel row sums by sampling
#cat: applied at different orientations (directions) to the #cat: the current image block at a given orientation. The
#cat: current image block. The routine retuns the maximum #cat: sampling is conducted using a precomputed set of rotated
#cat: power value in the vector, the direction at which the #cat: pixel offsets (called a grid) relative to the orgin of
#cat: maximum occurs, and a normalized power value. The #cat: the image block.
#cat: normalized power is computed as the maximum power divided
#cat: by the average power across all the directions. These
#cat: simple statistics are fundamental to the selection of
#cat: a dominant direction flow for the image block.
Input: Input:
power_vector - the DFT power values derived form a specific wave form blkptr - the pixel address of the origin of the current image block
applied at different directions grid_offsets - the rotated pixel offsets for a block-sized grid
ndirs - the number of directions to which the wave form was applied rotated according to a specific orientation
blocksize - the width and height of the image block and thus the size
of the rotated grid
Output: Output:
powmax - the maximum power value in the DFT power vector rowsums - the resulting vector of pixel row sums
powmax_dir - the direciton at which the maximum power value occured
pownorm - the normalized power corresponding to the maximum power
**************************************************************************/ **************************************************************************/
static void get_max_norm(double *powmax, int *powmax_dir, void sum_rot_block_rows(int *rowsums, const unsigned char *blkptr,
double *pownorm, const double *power_vector, const int ndirs) const int *grid_offsets, const int blocksize)
{ {
int dir; int ix, iy, gi;
double max_v, powsum;
int max_i;
double powmean;
/* Find max power value and store corresponding direction */ /* Initialize rotation offset index. */
max_v = power_vector[0]; gi = 0;
max_i = 0;
/* Sum the total power in a block at a given direction */ /* For each row in block ... */
powsum = power_vector[0]; for(iy = 0; iy < blocksize; iy++){
/* The sums are accumlated along the rotated rows of the grid, */
/* For each direction ... */ /* so initialize row sum to 0. */
for(dir = 1; dir < ndirs; dir++){ rowsums[iy] = 0;
powsum += power_vector[dir]; /* Foreach column in block ... */
if(power_vector[dir] > max_v){ for(ix = 0; ix < blocksize; ix++){
max_v = power_vector[dir]; /* Accumulate pixel value at rotated grid position in image */
max_i = dir; rowsums[iy] += *(blkptr + grid_offsets[gi]);
gi++;
} }
} }
*powmax = max_v;
*powmax_dir = max_i;
/* Powmean is used as denominator for pownorm, so setting */
/* a non-zero minimum avoids possible division by zero. */
powmean = max(powsum, MIN_POWER_SUM)/(double)ndirs;
*pownorm = *powmax / powmean;
} }
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: sort_dft_waves - Creates a ranked list of DFT wave form statistics #cat: dft_power - Computes the DFT power by applying a specific wave form
#cat: by sorting on the normalized squared maximum power. #cat: frequency to a vector of pixel row sums computed from a
#cat: specific orientation of the block image
Input: Input:
powmaxs - maximum DFT power for each wave form used to derive rowsums - accumulated rows of pixels from within a rotated grid
statistics overlaying an input image block
pownorms - normalized maximum power corresponding to values in powmaxs wave - the wave form (cosine and sine components) at a specific
nstats - number of wave forms used to derive statistics (N Wave - 1) frequency
wavelen - the length of the wave form (must match the height of the
image block which is the length of the rowsum vector)
Output: Output:
wis - sorted list of indices corresponding to the ranked set of power - the computed DFT power for the given wave form at the
wave form statistics. These indices will be used as given orientation within the image block
indirect addresses when processing the power statistics
in descending order of "dominance"
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/ **************************************************************************/
static int sort_dft_waves(int *wis, const double *powmaxs, const double *pownorms, void dft_power(double *power, const int *rowsums,
const int nstats) const DFTWAVE *wave, const int wavelen)
{ {
int i; int i;
double *pownorms2; double cospart, sinpart;
/* Allocate normalized power^2 array */ /* Initialize accumulators */
pownorms2 = (double *)malloc(nstats * sizeof(double)); cospart = 0.0;
if(pownorms2 == (double *)NULL){ sinpart = 0.0;
fprintf(stderr, "ERROR : sort_dft_waves : malloc : pownorms2\n");
return(-100); /* Accumulate cos and sin components of DFT. */
for(i = 0; i < wavelen; i++){
/* Multiply each rotated row sum by its */
/* corresponding cos or sin point in DFT wave. */
cospart += (rowsums[i] * wave->cos[i]);
sinpart += (rowsums[i] * wave->sin[i]);
} }
for(i = 0; i < nstats; i++){ /* Power is the sum of the squared cos and sin components */
/* Wis will hold the sorted statistic indices when all is done. */ *power = (cospart * cospart) + (sinpart * sinpart);
wis[i] = i;
/* This is normalized squared max power. */
pownorms2[i] = powmaxs[i] * pownorms[i];
}
/* Sort the statistic indices on the normalized squared power. */
bubble_sort_double_dec_2(pownorms2, wis, nstats);
/* Deallocate the working memory. */
free(pownorms2);
return(0);
} }
/************************************************************************* /*************************************************************************
@ -356,3 +273,106 @@ int dft_power_stats(int *wis, double *powmaxs, int *powmax_dirs,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: get_max_norm - Analyses a DFT power vector for a specific wave form
#cat: applied at different orientations (directions) to the
#cat: current image block. The routine retuns the maximum
#cat: power value in the vector, the direction at which the
#cat: maximum occurs, and a normalized power value. The
#cat: normalized power is computed as the maximum power divided
#cat: by the average power across all the directions. These
#cat: simple statistics are fundamental to the selection of
#cat: a dominant direction flow for the image block.
Input:
power_vector - the DFT power values derived form a specific wave form
applied at different directions
ndirs - the number of directions to which the wave form was applied
Output:
powmax - the maximum power value in the DFT power vector
powmax_dir - the direciton at which the maximum power value occured
pownorm - the normalized power corresponding to the maximum power
**************************************************************************/
void get_max_norm(double *powmax, int *powmax_dir,
double *pownorm, const double *power_vector, const int ndirs)
{
int dir;
double max_v, powsum;
int max_i;
double powmean;
/* Find max power value and store corresponding direction */
max_v = power_vector[0];
max_i = 0;
/* Sum the total power in a block at a given direction */
powsum = power_vector[0];
/* For each direction ... */
for(dir = 1; dir < ndirs; dir++){
powsum += power_vector[dir];
if(power_vector[dir] > max_v){
max_v = power_vector[dir];
max_i = dir;
}
}
*powmax = max_v;
*powmax_dir = max_i;
/* Powmean is used as denominator for pownorm, so setting */
/* a non-zero minimum avoids possible division by zero. */
powmean = max(powsum, MIN_POWER_SUM)/(double)ndirs;
*pownorm = *powmax / powmean;
}
/*************************************************************************
**************************************************************************
#cat: sort_dft_waves - Creates a ranked list of DFT wave form statistics
#cat: by sorting on the normalized squared maximum power.
Input:
powmaxs - maximum DFT power for each wave form used to derive
statistics
pownorms - normalized maximum power corresponding to values in powmaxs
nstats - number of wave forms used to derive statistics (N Wave - 1)
Output:
wis - sorted list of indices corresponding to the ranked set of
wave form statistics. These indices will be used as
indirect addresses when processing the power statistics
in descending order of "dominance"
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
int sort_dft_waves(int *wis, const double *powmaxs, const double *pownorms,
const int nstats)
{
int i;
double *pownorms2;
/* Allocate normalized power^2 array */
pownorms2 = (double *)malloc(nstats * sizeof(double));
if(pownorms2 == (double *)NULL){
fprintf(stderr, "ERROR : sort_dft_waves : malloc : pownorms2\n");
return(-100);
}
for(i = 0; i < nstats; i++){
/* Wis will hold the sorted statistic indices when all is done. */
wis[i] = i;
/* This is normalized squared max power. */
pownorms2[i] = powmaxs[i] * pownorms[i];
}
/* Sort the statistic indices on the normalized squared power. */
bubble_sort_double_dec_2(pownorms2, wis, nstats);
/* Deallocate the working memory. */
free(pownorms2);
return(0);
}

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -40,7 +61,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/************************************************************************* /*************************************************************************

View file

@ -0,0 +1,175 @@
/*******************************************************************************
License:
This software and/or related materials 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.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials 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.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
FILE: GETMIN.C
AUTHOR: Michael D. Garris
DATE: 09/10/2004
UPDATED: 03/16/2005 by MDG
Takes an 8-bit grayscale fingerpinrt image and detects minutiae
as part of the NIST Latent Fingerprint System (LFS), returning
minutiae with final reliabilities and maps including a merged
quality map.
***********************************************************************
ROUTINES:
get_minutiae()
***********************************************************************/
#include <stdio.h>
#include <lfs.h>
/*************************************************************************
**************************************************************************
#cat: get_minutiae - Takes a grayscale fingerprint image, binarizes the input
#cat: image, and detects minutiae points using LFS Version 2.
#cat: The routine passes back the detected minutiae, the
#cat: binarized image, and a set of image quality maps.
Input:
idata - grayscale fingerprint image data
iw - width (in pixels) of the grayscale image
ih - height (in pixels) of the grayscale image
id - pixel depth (in bits) of the grayscale image
ppmm - the scan resolution (in pixels/mm) of the grayscale image
lfsparms - parameters and thresholds for controlling LFS
Output:
ominutiae - points to a structure containing the
detected minutiae
oquality_map - resulting integrated image quality map
odirection_map - resulting direction map
olow_contrast_map - resulting low contrast map
olow_flow_map - resulting low ridge flow map
ohigh_curve_map - resulting high curvature map
omap_w - width (in blocks) of image maps
omap_h - height (in blocks) of image maps
obdata - points to binarized image data
obw - width (in pixels) of binarized image
obh - height (in pixels) of binarized image
obd - pixel depth (in bits) of binarized image
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
int get_minutiae(MINUTIAE **ominutiae, int **oquality_map,
int **odirection_map, int **olow_contrast_map,
int **olow_flow_map, int **ohigh_curve_map,
int *omap_w, int *omap_h,
unsigned char **obdata, int *obw, int *obh, int *obd,
unsigned char *idata, const int iw, const int ih,
const int id, const double ppmm, const LFSPARMS *lfsparms)
{
int ret;
MINUTIAE *minutiae;
int *direction_map, *low_contrast_map, *low_flow_map;
int *high_curve_map, *quality_map;
int map_w, map_h;
unsigned char *bdata;
int bw, bh;
/* If input image is not 8-bit grayscale ... */
if(id != 8){
fprintf(stderr, "ERROR : get_minutiae : input image pixel ");
fprintf(stderr, "depth = %d != 8.\n", id);
return(-2);
}
/* Detect minutiae in grayscale fingerpeint image. */
if((ret = lfs_detect_minutiae_V2(&minutiae,
&direction_map, &low_contrast_map,
&low_flow_map, &high_curve_map,
&map_w, &map_h,
&bdata, &bw, &bh,
idata, iw, ih, lfsparms))){
return(ret);
}
/* Build integrated quality map. */
if((ret = gen_quality_map(&quality_map,
direction_map, low_contrast_map,
low_flow_map, high_curve_map, map_w, map_h))){
free_minutiae(minutiae);
free(direction_map);
free(low_contrast_map);
free(low_flow_map);
free(high_curve_map);
free(bdata);
return(ret);
}
/* Assign reliability from quality map. */
if((ret = combined_minutia_quality(minutiae, quality_map, map_w, map_h,
lfsparms->blocksize,
idata, iw, ih, id, ppmm))){
free_minutiae(minutiae);
free(direction_map);
free(low_contrast_map);
free(low_flow_map);
free(high_curve_map);
free(quality_map);
free(bdata);
return(ret);
}
/* Set output pointers. */
*ominutiae = minutiae;
*oquality_map = quality_map;
*odirection_map = direction_map;
*olow_contrast_map = low_contrast_map;
*olow_flow_map = low_flow_map;
*ohigh_curve_map = high_curve_map;
*omap_w = map_w;
*omap_h = map_h;
*obdata = bdata;
*obw = bw;
*obh = bh;
*obd = id;
/* Return normally. */
return(0);
}

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -40,7 +61,7 @@ identified are necessarily the best available for the purpose.
/*************************************************************************/ /*************************************************************************/
#ifdef LOG_REPORT #ifdef LOG_REPORT
FILE *g_logfp; FILE *logfp;
#endif #endif
/* Constants (C) for defining 4 DFT frequencies, where */ /* Constants (C) for defining 4 DFT frequencies, where */
@ -129,8 +150,6 @@ LFSPARMS g_lfsparms = {
PORES_STEPS_BWD, PORES_STEPS_BWD,
PORES_MIN_DIST2, PORES_MIN_DIST2,
PORES_MAX_RATIO, PORES_MAX_RATIO,
FALSE, /* not removing perimeter points by default */
PERIMETER_PTS_DISTANCE,
/* Ridge Counting Controls */ /* Ridge Counting Controls */
MAX_NBRS, MAX_NBRS,
@ -215,8 +234,6 @@ LFSPARMS g_lfsparms_V2 = {
PORES_STEPS_BWD, PORES_STEPS_BWD,
PORES_MIN_DIST2, PORES_MIN_DIST2,
PORES_MAX_RATIO, PORES_MAX_RATIO,
FALSE, /* not removing perimeter points by default */
PERIMETER_PTS_DISTANCE,
/* Ridge Counting Controls */ /* Ridge Counting Controls */
MAX_NBRS, MAX_NBRS,

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -45,7 +66,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <memory.h> #include <memory.h>
#include <lfs.h> #include <lfs.h>
@ -65,18 +85,6 @@ identified are necessarily the best available for the purpose.
Output: Output:
idata - contains the bit-shifted results idata - contains the bit-shifted results
**************************************************************************/ **************************************************************************/
void bits_6to8(unsigned char *idata, const int iw, const int ih)
{
int i, isize;
unsigned char *iptr;
isize = iw * ih;
iptr = idata;
for(i = 0; i < isize; i++){
/* Multiply every pixel value by 4 so that [0..64) -> [0..255) */
*iptr++ <<= 2;
}
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -37,6 +58,7 @@ identified are necessarily the best available for the purpose.
ROUTINES: ROUTINES:
init_dir2rad() init_dir2rad()
init_dftwaves() init_dftwaves()
get_max_padding()
get_max_padding_V2() get_max_padding_V2()
init_rotgrids() init_rotgrids()
alloc_dir_powers() alloc_dir_powers()
@ -44,7 +66,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/************************************************************************* /*************************************************************************
@ -242,6 +263,33 @@ int init_dftwaves(DFTWAVES **optr, const double *dft_coefs,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: get_max_padding - Deterines the maximum amount of image pixel padding
#cat: required by all LFS processes. Padding is currently
#cat: required by the rotated grids used in DFT analyses,
#cat: rotated grids used in directional binarization,
#cat: and in the grid used for isotropic binarization.
#cat: The NIST generalized code enables the parameters
#cat: governing these processes to be redefined, so a check
#cat: at runtime is required to determine which process
#cat: requires the most padding. By using the maximum as
#cat: the padding factor, all processes will run safely
#cat: with a single padding of the input image avoiding the
#cat: need to repad for further processes.
Input:
imap_blocksize - the size (in pixels) of each IMAP block in the image
dirbin_grid_w - the width (in pixels) of the rotated grids used in
directional binarization
dirbin_grid_h - the height (in pixels) of the rotated grids used in
directional binarization
isobin_grid_dim - the dimension (in pixels) of the square grid used in
isotropic binarization
Return Code:
Non-negative - the maximum padding required for all processes
**************************************************************************/
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: get_max_padding_V2 - Deterines the maximum amount of image pixel padding #cat: get_max_padding_V2 - Deterines the maximum amount of image pixel padding

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -38,7 +59,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/************************************************************************* /*************************************************************************

View file

@ -0,0 +1,254 @@
/*******************************************************************************
License:
This software and/or related materials 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.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials 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.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
FILE: LINK.C
AUTHOR: Michael D. Garris
DATE: 08/02/1999
UPDATED: 10/04/1999 Version 2 by MDG
UPDATED: 03/16/2005 by MDG
Contains routines responsible for linking compatible minutiae
together as part of the NIST Latent Fingerprint System (LFS).
***********************************************************************
ROUTINES:
link_minutiae()
create_link_table()
update_link_table()
order_link_table()
process_link_table()
link_score()
***********************************************************************/
#include <stdio.h>
#include <lfs.h>
#include <log.h>
/*************************************************************************
**************************************************************************
#cat: link_minutiae - Clusters minutiae that are sufficiently close to each
#cat: other and have compatible directions to be considered part
#cat: of the same ridge or valley and then links them together.
#cat: In linking two minutia, the respective minutia features
#cat: in the image are joined by drawing pixels and the points
#cat: are removed from the list.
Input:
minutiae - list of true and false minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
nmap - IMAP ridge flow matrix with invalid, high-curvature,
and no-valid-neighbor regions identified
mw - width in blocks of the NMAP
mh - height in blocks of the NMAP
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
bdata - edited binary image with breaks in ridges and valleys filled
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: create_link_table - Builds a 2D minutia link table where each cell in the
#cat: table represents a potential linking of 2 different
#cat: minutia points. Minutia IDs are stored on each axes
#cat: and scores representing the degree of compatibility
#cat: between 2 minutia are stored in each cell. Note that
#cat: the table is sparsely filled with scores.
Input:
tbldim - dimension of each axes of the link table
start - index position of starting minutia point in input list
minutiae - list of minutia
onloop - list of loop flags (on flag for each minutia point in list)
nmap - IMAP ridge flow matrix with invalid, high-curvature,
and no-valid-neighbor regions identified
mw - width in blocks of the NMAP
mh - height in blocks of the NMAP
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
lfsparms - parameters and thresholds for controlling LFS
Output:
olink_table - sparse 2D table containing scores of potentially
linked minutia pairs
ox_axis - minutia IDs registered along x-axis
oy_axis - minutia IDs registered along y-axis
onx_axis - number of minutia registered along x-axis
ony_axis - number of minutia registered along y-axis
on_entries - number of scores currently entered in the table
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: update_link_table - Takes the indices of 2 minutia and their link
#cat: compatibility score and updates the 2D link table.
#cat: The input minutia are registered to positions along
#cat: different axes, if they are not already in the table,
#cat: and a queue is maintained so that a cluster of
#cat: potentially linked points may be gathered.
Input:
link_table - sparse 2D table containing scores of potentially linked
minutia pairs
x_axis - minutia IDs registered along x-axis
y_axis - minutia IDs registered along y-axis
nx_axis - number of minutia registered along x-axis
ny_axis - number of minutia registered along y-axis
n_entries - number of scores currently entered in the table
tbldim - dimension of each axes of the link table
queue - list of clustered minutiae yet to be used to locate
other compatible minutiae
head - head of the queue
tail - tail of the queue
inqueue - flag for each minutia point in minutiae list to signify if
it has been clustered with the points in this current link
table
first - index position of first minutia of current link pair
second - index position of second minutia of current link pair
score - degree of link compatibility of current link pair
Output:
link_table - updated sparse 2D table containing scores of potentially
linked minutia pairs
x_axis - updated minutia IDs registered along x-axis
y_axis - updated minutia IDs registered along y-axis
nx_axis - updated number of minutia registered along x-axis
ny_axis - updated number of minutia registered along y-axis
n_entries - updated number of scores currently entered in the table
queue - updated list of clustered minutiae yet to be used to locate
other compatible minutiae
tail - updated tail of the queue
inqueue - updated list of flags, one for each minutia point in
minutiae list to signify if it has been clustered with
the points in this current link table
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: order_link_table - Puts the link table in sorted order based on x and
#cat: then y-axis entries. These minutia are sorted based
#cat: on their point of perpendicular intersection with a
#cat: line running from the origin at an angle equal to the
#cat: average direction of all entries in the link table.
Input:
link_table - sparse 2D table containing scores of potentially linked
minutia pairs
x_axis - minutia IDs registered along x-axis
y_axis - minutia IDs registered along y-axis
nx_axis - number of minutia registered along x-axis
ny_axis - number of minutia registered along y-axis
n_entries - number of scores currently entered in the table
tbldim - dimension of each axes of the link table
minutiae - list of minutia
ndirs - number of IMAP directions (in semicircle)
Output:
link_table - sorted sparse 2D table containing scores of potentially
linked minutia pairs
x_axis - sorted minutia IDs registered along x-axis
y_axis - sorted minutia IDs registered along y-axis
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: process_link_table - Processes the link table deciding which minutia
#cat: pairs in the table should be linked (ie. joined in
#cat: the image and removed from the minutiae list (and
#cat: from onloop).
Input:
link_table - sparse 2D table containing scores of potentially linked
minutia pairs
x_axis - minutia IDs registered along x-axis
y_axis - minutia IDs registered along y-axis
nx_axis - number of minutia registered along x-axis
ny_axis - number of minutia registered along y-axis
n_entries - number of scores currently entered in the table
tbldim - dimension of each axes of the link table
minutiae - list of minutia
onloop - list of flags signifying which minutia lie on small lakes
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
onloop - updated loop flags
bdata - edited image with minutia features joined
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: link_score - Takes 2 parameters, a 'join angle' and a 'join distance'
#cat: computed between 2 minutia and combines these to compute
#cat: a score representing the degree of link compatibility
#cat: between the 2 minutiae.
Input:
jointheta - angle measured between 2 minutiae
joindist - distance between 2 minutiae
lfsparms - parameters and thresholds for controlling LFS
Return Code:
Score - degree of link compatibility
**************************************************************************/

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -42,17 +63,12 @@ identified are necessarily the best available for the purpose.
/* If logging is on, declare global file pointer and supporting */ /* If logging is on, declare global file pointer and supporting */
/* global variable for logging intermediate results. */ /* global variable for logging intermediate results. */
FILE *logfp;
int avrdir;
float dir_strength;
int nvalid;
/***************************************************************************/ /***************************************************************************/
/***************************************************************************/ /***************************************************************************/
int open_logfile() int open_logfile()
{ {
#ifdef LOG_REPORT #ifdef LOG_REPORT
if((logfp = fopen(LOG_FILE, "wb")) == NULL){
fprintf(stderr, "ERROR : open_logfile : fopen : %s\n", LOG_FILE); fprintf(stderr, "ERROR : open_logfile : fopen : %s\n", LOG_FILE);
return(-1); return(-1);
} }
@ -69,7 +85,6 @@ void print2log(char *fmt, ...)
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
vfprintf(logfp, fmt, ap);
va_end(ap); va_end(ap);
#endif #endif
} }
@ -79,7 +94,6 @@ void print2log(char *fmt, ...)
int close_logfile() int close_logfile()
{ {
#ifdef LOG_REPORT #ifdef LOG_REPORT
if(fclose(logfp)){
fprintf(stderr, "ERROR : close_logfile : fclose : %s\n", LOG_FILE); fprintf(stderr, "ERROR : close_logfile : fclose : %s\n", LOG_FILE);
return(-1); return(-1);
} }

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -36,8 +57,6 @@ identified are necessarily the best available for the purpose.
*********************************************************************** ***********************************************************************
ROUTINES: ROUTINES:
chain_code_loop()
is_chain_clockwise()
get_loop_list() get_loop_list()
on_loop() on_loop()
on_island_lake() on_island_lake()
@ -48,161 +67,13 @@ identified are necessarily the best available for the purpose.
get_loop_aspect() get_loop_aspect()
fill_loop() fill_loop()
fill_partial_row() fill_partial_row()
flood_loop()
flood_fill4()
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/*************************************************************************
**************************************************************************
#cat: chain_code_loop - Converts a feature's contour points into an
#cat: 8-connected chain code vector. This encoding represents
#cat: the direction taken between each adjacent point in the
#cat: contour. Chain codes may be used for many purposes, such
#cat: as computing the perimeter or area of an object, and they
#cat: may be used in object detection and recognition.
Input:
contour_x - x-coord list for feature's contour points
contour_y - y-coord list for feature's contour points
ncontour - number of points in contour
Output:
ochain - resulting vector of chain codes
onchain - number of codes in chain
(same as number of points in contour)
Return Code:
Zero - chain code successful derived
Negative - system error
**************************************************************************/
static int chain_code_loop(int **ochain, int *onchain,
const int *contour_x, const int *contour_y, const int ncontour)
{
int *chain;
int i, j, dx, dy;
/* If we don't have at least 3 points in the contour ... */
if(ncontour <= 3){
/* Then we don't have a loop, so set chain length to 0 */
/* and return without any allocations. */
*onchain = 0;
return(0);
}
/* Allocate chain code vector. It will be the same length as the */
/* number of points in the contour. There will be one chain code */
/* between each point on the contour including a code between the */
/* last to the first point on the contour (completing the loop). */
chain = (int *)malloc(ncontour * sizeof(int));
/* If the allocation fails ... */
if(chain == (int *)NULL){
fprintf(stderr, "ERROR : chain_code_loop : malloc : chain\n");
return(-170);
}
/* For each neighboring point in the list (with "i" pointing to the */
/* previous neighbor and "j" pointing to the next neighbor... */
for(i = 0, j=1; i < ncontour-1; i++, j++){
/* Compute delta in X between neighbors. */
dx = contour_x[j] - contour_x[i];
/* Compute delta in Y between neighbors. */
dy = contour_y[j] - contour_y[i];
/* Derive chain code index from neighbor deltas. */
/* The deltas are on the range [-1..1], so to use them as indices */
/* into the code list, they must first be incremented by one. */
chain[i] = *(g_chaincodes_nbr8+((dy+1)*NBR8_DIM)+dx+1);
}
/* Now derive chain code between last and first points in the */
/* contour list. */
dx = contour_x[0] - contour_x[i];
dy = contour_y[0] - contour_y[i];
chain[i] = *(g_chaincodes_nbr8+((dy+1)*NBR8_DIM)+dx+1);
/* Store results to the output pointers. */
*ochain = chain;
*onchain = ncontour;
/* Return normally. */
return(0);
}
/*************************************************************************
**************************************************************************
#cat: is_chain_clockwise - Takes an 8-connected chain code vector and
#cat: determines if the codes are ordered clockwise or
#cat: counter-clockwise.
#cat: The routine also requires a default return value be
#cat: specified in the case the the routine is not able to
#cat: definitively determine the chains direction. This allows
#cat: the default response to be application-specific.
Input:
chain - chain code vector
nchain - number of codes in chain
default_ret - default return code (used when we can't tell the order)
Return Code:
TRUE - chain determined to be ordered clockwise
FALSE - chain determined to be ordered counter-clockwise
Default - could not determine the order of the chain
**************************************************************************/
static int is_chain_clockwise(const int *chain, const int nchain,
const int default_ret)
{
int i, j, d, sum;
/* Initialize turn-accumulator to 0. */
sum = 0;
/* Foreach neighboring code in chain, compute the difference in */
/* direction and accumulate. Left-hand turns increment, whereas */
/* right-hand decrement. */
for(i = 0, j =1; i < nchain-1; i++, j++){
/* Compute delta in neighbor direction. */
d = chain[j] - chain[i];
/* Make the delta the "inner" distance. */
/* If delta >= 4, for example if chain_i==2 and chain_j==7 (which */
/* means the contour went from a step up to step down-to-the-right) */
/* then 5=(7-2) which is >=4, so -3=(5-8) which means that the */
/* change in direction is a righ-hand turn of 3 units). */
if(d >= 4)
d -= 8;
/* If delta <= -4, for example if chain_i==7 and chain_j==2 (which */
/* means the contour went from a step down-to-the-right to step up) */
/* then -5=(2-7) which is <=-4, so 3=(-5+8) which means that the */
/* change in direction is a left-hand turn of 3 units). */
else if (d <= -4)
d += 8;
/* The delta direction is then accumulated. */
sum += d;
}
/* Now we need to add in the final delta direction between the last */
/* and first codes in the chain. */
d = chain[0] - chain[i];
if(d >= 4)
d -= 8;
else if (d <= -4)
d += 8;
sum += d;
/* If the final turn_accumulator == 0, then we CAN'T TELL the */
/* direction of the chain code, so return the default return value. */
if(sum == 0)
return(default_ret);
/* Otherwise, if the final turn-accumulator is positive ... */
else if(sum > 0)
/* Then we had a greater amount of left-hand turns than right-hand */
/* turns, so the chain is in COUNTER-CLOCKWISE order, so return FALSE. */
return(FALSE);
/* Otherwise, the final turn-accumulator is negative ... */
else
/* So we had a greater amount of right-hand turns than left-hand */
/* turns, so the chain is in CLOCKWISE order, so return TRUE. */
return(TRUE);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: get_loop_list - Takes a list of minutia points and determines which #cat: get_loop_list - Takes a list of minutia points and determines which
@ -228,78 +99,6 @@ static int is_chain_clockwise(const int *chain, const int nchain,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
int get_loop_list(int **oonloop, MINUTIAE *minutiae, const int loop_len,
unsigned char *bdata, const int iw, const int ih)
{
int i, ret;
int *onloop;
MINUTIA *minutia;
/* Allocate a list of onloop flags (one for each minutia in list). */
onloop = (int *)malloc(minutiae->num * sizeof(int));
if(onloop == (int *)NULL){
fprintf(stderr, "ERROR : get_loop_list : malloc : onloop\n");
return(-320);
}
i = 0;
/* Foreach minutia remaining in list ... */
while(i < minutiae->num){
/* Assign a temporary pointer. */
minutia = minutiae->list[i];
/* If current minutia is a bifurcation ... */
if(minutia->type == BIFURCATION){
/* Check to see if it is on a loop of specified length. */
ret = on_loop(minutia, loop_len, bdata, iw, ih);
/* If minutia is on a loop... */
if(ret == LOOP_FOUND){
/* Then set the onloop flag to TRUE. */
onloop[i] = TRUE;
/* Advance to next minutia in the list. */
i++;
}
/* If on loop test IGNORED ... */
else if (ret == IGNORE){
/* Remove the current minutia from the list. */
if((ret = remove_minutia(i, minutiae))){
/* Deallocate working memory. */
free(onloop);
/* Return error code. */
return(ret);
}
/* No need to advance because next minutia has "slid" */
/* into position pointed to by 'i'. */
}
/* If the minutia is NOT on a loop... */
else if (ret == FALSE){
/* Then set the onloop flag to FALSE. */
onloop[i] = FALSE;
/* Advance to next minutia in the list. */
i++;
}
/* Otherwise, an ERROR occurred while looking for loop. */
else{
/* Deallocate working memory. */
free(onloop);
/* Return error code. */
return(ret);
}
}
/* Otherwise, the current minutia is a ridge-ending... */
else{
/* Ridge-endings will never be on a loop, so set flag to FALSE. */
onloop[i] = FALSE;
/* Advance to next minutia in the list. */
i++;
}
}
/* Store flag list to output pointer. */
*oonloop = onloop;
/* Return normally. */
return(0);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
@ -648,107 +447,6 @@ int is_loop_clockwise(const int *contour_x, const int *contour_y,
return(ret); return(ret);
} }
/*************************************************************************
**************************************************************************
#cat: get_loop_aspect - Takes a contour list (determined to form a complete
#cat: loop) and measures the loop's aspect (the largest and smallest
#cat: distances across the loop) and returns the points on the
#cat: loop where these distances occur.
Input:
contour_x - x-coord list for loop's contour points
contour_y - y-coord list for loop's contour points
ncontour - number of points in contour
Output:
omin_fr - contour point index where minimum aspect occurs
omin_to - opposite contour point index where minimum aspect occurs
omin_dist - the minimum distance across the loop
omax_fr - contour point index where maximum aspect occurs
omax_to - contour point index where maximum aspect occurs
omax_dist - the maximum distance across the loop
**************************************************************************/
static void get_loop_aspect(int *omin_fr, int *omin_to, double *omin_dist,
int *omax_fr, int *omax_to, double *omax_dist,
const int *contour_x, const int *contour_y, const int ncontour)
{
int halfway, limit;
int i, j;
double dist;
double min_dist, max_dist;
int min_i, max_i, min_j, max_j;
/* Compute half the perimeter of the loop. */
halfway = ncontour>>1;
/* Take opposite points on the contour and walk half way */
/* around the loop. */
i = 0;
j = halfway;
/* Compute squared distance between opposite points on loop. */
dist = squared_distance(contour_x[i], contour_y[i],
contour_x[j], contour_y[j]);
/* Initialize running minimum and maximum distances along loop. */
min_dist = dist;
min_i = i;
min_j = j;
max_dist = dist;
max_i = i;
max_j = j;
/* Bump to next pair of opposite points. */
i++;
/* Make sure j wraps around end of list. */
j++;
j %= ncontour;
/* If the loop is of even length, then we only need to walk half */
/* way around as the other half will be exactly redundant. If */
/* the loop is of odd length, then the second half will not be */
/* be exactly redundant and the difference "may" be meaningful. */
/* If execution speed is an issue, then probably get away with */
/* walking only the fist half of the loop under ALL conditions. */
/* If loop has odd length ... */
if(ncontour % 2)
/* Walk the loop's entire perimeter. */
limit = ncontour;
/* Otherwise the loop has even length ... */
else
/* Only walk half the perimeter. */
limit = halfway;
/* While we have not reached our perimeter limit ... */
while(i < limit){
/* Compute squared distance between opposite points on loop. */
dist = squared_distance(contour_x[i], contour_y[i],
contour_x[j], contour_y[j]);
/* Check the running minimum and maximum distances. */
if(dist < min_dist){
min_dist = dist;
min_i = i;
min_j = j;
}
if(dist > max_dist){
max_dist = dist;
max_i = i;
max_j = j;
}
/* Bump to next pair of opposite points. */
i++;
/* Make sure j wraps around end of list. */
j++;
j %= ncontour;
}
/* Assign minimum and maximum distances to output pointers. */
*omin_fr = min_i;
*omin_to = min_j;
*omin_dist = min_dist;
*omax_fr = max_i;
*omax_to = max_j;
*omax_dist = max_dist;
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: process_loop - Takes a contour list that has been determined to form #cat: process_loop - Takes a contour list that has been determined to form
@ -776,131 +474,6 @@ static void get_loop_aspect(int *omin_fr, int *omin_to, double *omin_dist,
Zero - loop processed successfully Zero - loop processed successfully
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
int process_loop(MINUTIAE *minutiae,
const int *contour_x, const int *contour_y,
const int *contour_ex, const int *contour_ey, const int ncontour,
unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms)
{
int idir, type, appearing;
double min_dist, max_dist;
int min_fr, max_fr, min_to, max_to;
int mid_x, mid_y, mid_pix;
int feature_pix;
int ret;
MINUTIA *minutia;
/* If contour is empty, then just return. */
if(ncontour <= 0)
return(0);
/* If loop is large enough ... */
if(ncontour > lfsparms->min_loop_len){
/* Get pixel value of feature's interior. */
feature_pix = *(bdata + (contour_y[0] * iw) + contour_x[0]);
/* Get the aspect dimensions of the loop in units of */
/* squared distance. */
get_loop_aspect(&min_fr, &min_to, &min_dist,
&max_fr, &max_to, &max_dist,
contour_x, contour_y, ncontour);
/* If loop passes aspect ratio tests ... loop is sufficiently */
/* narrow or elongated ... */
if((min_dist < lfsparms->min_loop_aspect_dist) ||
((max_dist/min_dist) >= lfsparms->min_loop_aspect_ratio)){
/* Update minutiae list with opposite points of max distance */
/* on the loop. */
/* First, check if interior point has proper pixel value. */
mid_x = (contour_x[max_fr]+contour_x[max_to])>>1;
mid_y = (contour_y[max_fr]+contour_y[max_to])>>1;
mid_pix = *(bdata + (mid_y * iw) + mid_x);
/* If interior point is the same as the feature... */
if(mid_pix == feature_pix){
/* 1. Treat maximum distance point as a potential minutia. */
/* Compute direction from maximum loop point to its */
/* opposite point. */
idir = line2direction(contour_x[max_fr], contour_y[max_fr],
contour_x[max_to], contour_y[max_to],
lfsparms->num_directions);
/* Get type of minutia: BIFURCATION or RIDGE_ENDING. */
type = minutia_type(feature_pix);
/* Determine if minutia is appearing or disappearing. */
if((appearing = is_minutia_appearing(
contour_x[max_fr], contour_y[max_fr],
contour_ex[max_fr], contour_ey[max_fr])) < 0){
/* Return system error code. */
return(appearing);
}
/* Create new minutia object. */
if((ret = create_minutia(&minutia,
contour_x[max_fr], contour_y[max_fr],
contour_ex[max_fr], contour_ey[max_fr],
idir, DEFAULT_RELIABILITY,
type, appearing, LOOP_ID))){
/* Return system error code. */
return(ret);
}
/* Update the minutiae list with potential new minutia. */
ret = update_minutiae(minutiae, minutia, bdata, iw, ih, lfsparms);
/* If minuitia IGNORED and not added to the minutia list ... */
if(ret == IGNORE)
/* Deallocate the minutia. */
free_minutia(minutia);
/* 2. Treat point opposite of maximum distance point as */
/* a potential minutia. */
/* Flip the direction 180 degrees. Make sure new direction */
/* is on the range [0..(ndirsX2)]. */
idir += lfsparms->num_directions;
idir %= (lfsparms->num_directions<<1);
/* The type of minutia will stay the same. */
/* Determine if minutia is appearing or disappearing. */
if((appearing = is_minutia_appearing(
contour_x[max_to], contour_y[max_to],
contour_ex[max_to], contour_ey[max_to])) < 0){
/* Return system error code. */
return(appearing);
}
/* Create new minutia object. */
if((ret = create_minutia(&minutia,
contour_x[max_to], contour_y[max_to],
contour_ex[max_to], contour_ey[max_to],
idir, DEFAULT_RELIABILITY,
type, appearing, LOOP_ID))){
/* Return system error code. */
return(ret);
}
/* Update the minutiae list with potential new minutia. */
ret = update_minutiae(minutiae, minutia, bdata, iw, ih, lfsparms);
/* If minuitia IGNORED and not added to the minutia list ... */
if(ret == IGNORE)
/* Deallocate the minutia. */
free_minutia(minutia);
/* Done successfully processing this loop, so return normally. */
return(0);
} /* Otherwise, loop interior has problems. */
} /* Otherwise, loop is not the right shape for minutiae. */
} /* Otherwise, loop's perimeter is too small for minutiae. */
/* If we get here, we have a loop that is assumed to not contain */
/* minutiae, so remove the loop from the image. */
ret = fill_loop(contour_x, contour_y, ncontour, bdata, iw, ih);
/* Return either an error code from fill_loop or return normally. */
return(ret);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
@ -1087,39 +660,103 @@ int process_loop_V2(MINUTIAE *minutiae,
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: fill_partial_row - Fills a specified range of contiguous pixels on #cat: get_loop_aspect - Takes a contour list (determined to form a complete
#cat: a specified row of an 8-bit pixel image with a specified #cat: loop) and measures the loop's aspect (the largest and smallest
#cat: pixel value. NOTE, the pixel coordinates are assumed to #cat: distances across the loop) and returns the points on the
#cat: be within the image boundaries. #cat: loop where these distances occur.
Input: Input:
fill_pix - pixel value to fill with (should be on range [0..255] contour_x - x-coord list for loop's contour points
frx - x-pixel coord where fill should begin contour_y - y-coord list for loop's contour points
tox - x-pixel coord where fill should end (inclusive) ncontour - number of points in contour
y - y-pixel coord of current row being filled
bdata - 8-bit image data
iw - width (in pixels) of image
ih - height (in pixels) of image
Output: Output:
bdata - 8-bit image data with partial row filled. omin_fr - contour point index where minimum aspect occurs
omin_to - opposite contour point index where minimum aspect occurs
omin_dist - the minimum distance across the loop
omax_fr - contour point index where maximum aspect occurs
omax_to - contour point index where maximum aspect occurs
omax_dist - the maximum distance across the loop
**************************************************************************/ **************************************************************************/
static void fill_partial_row(const int fill_pix, const int frx, const int tox, void get_loop_aspect(int *omin_fr, int *omin_to, double *omin_dist,
const int y, unsigned char *bdata, const int iw, const int ih) int *omax_fr, int *omax_to, double *omax_dist,
const int *contour_x, const int *contour_y, const int ncontour)
{ {
int x; int halfway, limit;
unsigned char *bptr; int i, j;
double dist;
double min_dist, max_dist;
int min_i, max_i, min_j, max_j;
/* Set pixel pointer to starting x-coord on current row. */ /* Compute half the perimeter of the loop. */
bptr = bdata+(y*iw)+frx; halfway = ncontour>>1;
/* Foreach pixel between starting and ending x-coord on row */ /* Take opposite points on the contour and walk half way */
/* (including the end points) ... */ /* around the loop. */
for(x = frx; x <= tox; x++){ i = 0;
/* Set current pixel with fill pixel value. */ j = halfway;
*bptr = fill_pix; /* Compute squared distance between opposite points on loop. */
/* Bump to next pixel in the row. */ dist = squared_distance(contour_x[i], contour_y[i],
bptr++; contour_x[j], contour_y[j]);
/* Initialize running minimum and maximum distances along loop. */
min_dist = dist;
min_i = i;
min_j = j;
max_dist = dist;
max_i = i;
max_j = j;
/* Bump to next pair of opposite points. */
i++;
/* Make sure j wraps around end of list. */
j++;
j %= ncontour;
/* If the loop is of even length, then we only need to walk half */
/* way around as the other half will be exactly redundant. If */
/* the loop is of odd length, then the second half will not be */
/* be exactly redundant and the difference "may" be meaningful. */
/* If execution speed is an issue, then probably get away with */
/* walking only the fist half of the loop under ALL conditions. */
/* If loop has odd length ... */
if(ncontour % 2)
/* Walk the loop's entire perimeter. */
limit = ncontour;
/* Otherwise the loop has even length ... */
else
/* Only walk half the perimeter. */
limit = halfway;
/* While we have not reached our perimeter limit ... */
while(i < limit){
/* Compute squared distance between opposite points on loop. */
dist = squared_distance(contour_x[i], contour_y[i],
contour_x[j], contour_y[j]);
/* Check the running minimum and maximum distances. */
if(dist < min_dist){
min_dist = dist;
min_i = i;
min_j = j;
} }
if(dist > max_dist){
max_dist = dist;
max_i = i;
max_j = j;
}
/* Bump to next pair of opposite points. */
i++;
/* Make sure j wraps around end of list. */
j++;
j %= ncontour;
}
/* Assign minimum and maximum distances to output pointers. */
*omin_fr = min_i;
*omin_to = min_j;
*omin_dist = min_dist;
*omax_fr = max_i;
*omax_to = max_j;
*omax_dist = max_dist;
} }
/************************************************************************* /*************************************************************************
@ -1253,3 +890,119 @@ int fill_loop(const int *contour_x, const int *contour_y,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: fill_partial_row - Fills a specified range of contiguous pixels on
#cat: a specified row of an 8-bit pixel image with a specified
#cat: pixel value. NOTE, the pixel coordinates are assumed to
#cat: be within the image boundaries.
Input:
fill_pix - pixel value to fill with (should be on range [0..255]
frx - x-pixel coord where fill should begin
tox - x-pixel coord where fill should end (inclusive)
y - y-pixel coord of current row being filled
bdata - 8-bit image data
iw - width (in pixels) of image
ih - height (in pixels) of image
Output:
bdata - 8-bit image data with partial row filled.
**************************************************************************/
void fill_partial_row(const int fill_pix, const int frx, const int tox,
const int y, unsigned char *bdata, const int iw, const int ih)
{
int x;
unsigned char *bptr;
/* Set pixel pointer to starting x-coord on current row. */
bptr = bdata+(y*iw)+frx;
/* Foreach pixel between starting and ending x-coord on row */
/* (including the end points) ... */
for(x = frx; x <= tox; x++){
/* Set current pixel with fill pixel value. */
*bptr = fill_pix;
/* Bump to next pixel in the row. */
bptr++;
}
}
/*************************************************************************
**************************************************************************
#cat: flood_loop - Fills a given contour (determined to form a complete loop)
#cat: with a specified pixel value using a recursive flood-fill
#cat: technique.
#cat: NOTE, this fill approach will NOT always work with the
#cat: contours generated in this application because they
#cat: are NOT guaranteed to be ENTIRELY surrounded by 8-connected
#cat: pixels not equal to the fill pixel value. This is unfortunate
#cat: because the flood-fill is a simple algorithm that will handle
#cat: complex/concaved shapes.
Input:
contour_x - x-coord list for loop's contour points
contour_y - y-coord list for loop's contour points
ncontour - number of points in contour
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
Output:
bdata - binary image data with loop filled
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: flood_fill4 - Recursively floods a region of an 8-bit pixel image with a
#cat: specified pixel value given a starting (seed) point. The
#cat: recursion is based neighbors being 4-connected.
Input:
fill_pix - 8-bit pixel value to be filled with (on range [0..255]
x - starting x-pixel coord
y - starting y-pixel coord
bdata - 8-bit pixel image data
iw - width (in pixels) of image
ih - height (in pixels) of image
Output:
bdata - 8-bit pixel image data with region filled
**************************************************************************/
void flood_fill4(const int fill_pix, const int x, const int y,
unsigned char *bdata, const int iw, const int ih)
{
unsigned char *pptr;
int y_north, y_south, x_east, x_west;
/* Get address of current pixel. */
pptr = bdata + (y*iw) + x;
/* If pixel needs to be filled ... */
if(*pptr != fill_pix){
/* Fill the current pixel. */
*pptr = fill_pix;
/* Recursively invoke flood on the pixel's 4 neighbors. */
/* Test to make sure neighbors are within image boudaries */
/* before invoking each flood. */
y_north = y-1;
y_south = y+1;
x_west = x-1;
x_east = x+1;
/* Invoke North */
if(y_north >= 0)
flood_fill4(fill_pix, x, y_north, bdata, iw, ih);
/* Invoke East */
if(x_east < iw)
flood_fill4(fill_pix, x_east, y, bdata, iw, ih);
/* Invoke South */
if(y_south < ih)
flood_fill4(fill_pix, x, y_south, bdata, iw, ih);
/* Invoke West */
if(x_west >= 0)
flood_fill4(fill_pix, x_west, y, bdata, iw, ih);
}
/* Otherwise, there is nothing to be done. */
}

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -46,6 +67,7 @@ identified are necessarily the best available for the purpose.
pixelize_map() pixelize_map()
smooth_direction_map() smooth_direction_map()
gen_high_curve_map() gen_high_curve_map()
gen_imap()
gen_initial_imap() gen_initial_imap()
primary_dir_test() primary_dir_test()
secondary_fork_test() secondary_fork_test()
@ -58,6 +80,7 @@ identified are necessarily the best available for the purpose.
average_8nbr_dir() average_8nbr_dir()
num_valid_8nbrs() num_valid_8nbrs()
smooth_imap() smooth_imap()
gen_nmap()
vorticity() vorticity()
accum_nbr_vorticity() accum_nbr_vorticity()
curvature() curvature()
@ -65,8 +88,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lfs.h> #include <lfs.h>
#include <morph.h> #include <morph.h>
#include <log.h> #include <log.h>
@ -307,10 +328,6 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap,
xmaxlimit = pw - dftgrids->pad - lfsparms->windowsize - 1; xmaxlimit = pw - dftgrids->pad - lfsparms->windowsize - 1;
ymaxlimit = ph - dftgrids->pad - lfsparms->windowsize - 1; ymaxlimit = ph - dftgrids->pad - lfsparms->windowsize - 1;
/* max limits should not be negative */
xmaxlimit = MAX(xmaxlimit, 0);
ymaxlimit = MAX(ymaxlimit, 0);
/* Foreach block in image ... */ /* Foreach block in image ... */
for(bi = 0; bi < bsize; bi++){ for(bi = 0; bi < bsize; bi++){
/* Adjust block offset from pointing to block origin to pointing */ /* Adjust block offset from pointing to block origin to pointing */
@ -393,7 +410,7 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap,
{ int _w; { int _w;
fprintf(logfp, " Power\n"); fprintf(logfp, " Power\n");
for(_w = 0; _w < nstats; _w++){ for(_w = 0; _w < nstats; _w++){
/* Add 1 to wis[w] to create index to original dft_coefs[] */ /* Add 1 to wis[w] to create index to original g_dft_coefs[] */
fprintf(logfp, " wis[%d] %d %12.3f %2d %9.3f %12.3f\n", fprintf(logfp, " wis[%d] %d %12.3f %2d %9.3f %12.3f\n",
_w, wis[_w]+1, _w, wis[_w]+1,
powmaxs[wis[_w]], powmax_dirs[wis[_w]], pownorms[wis[_w]], powmaxs[wis[_w]], powmax_dirs[wis[_w]], pownorms[wis[_w]],
@ -932,6 +949,30 @@ int gen_high_curve_map(int **ohcmap, int *direction_map,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: gen_imap - Computes an IMAP, which is a 2D vector of integer directions,
#cat: where each direction represents the dominant ridge flow in
#cat: a block of the input grayscale image. This routine will
#cat: generate an IMAP for arbitrarily sized, non-square, images.
Input:
pdata - padded input image data (8 bits [0..256) grayscale)
pw - padded width (in pixels) of the input image
ph - padded height (in pixels) of the input image
dir2rad - lookup table for converting integer directions
dftwaves - structure containing the DFT wave forms
dftgrids - structure containing the rotated pixel grid offsets
lfsparms - parameters and thresholds for controlling LFS
Output:
optr - points to the created IMAP
ow - width (in blocks) of the IMAP
oh - height (in blocks) of the IMAP
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: gen_initial_imap - Creates an initial IMAP from the given input image. #cat: gen_initial_imap - Creates an initial IMAP from the given input image.
@ -959,126 +1000,6 @@ int gen_high_curve_map(int **ohcmap, int *direction_map,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
int gen_initial_imap(int **optr, int *blkoffs, const int mw, const int mh,
unsigned char *pdata, const int pw, const int ph,
const DFTWAVES *dftwaves, const ROTGRIDS *dftgrids,
const LFSPARMS *lfsparms)
{
int *imap;
int bi, bsize, blkdir;
int *wis, *powmax_dirs;
double **powers, *powmaxs, *pownorms;
int nstats;
int ret; /* return code */
print2log("INITIAL MAP\n");
/* Compute total number of blocks in IMAP */
bsize = mw * mh;
/* Allocate IMAP memory */
imap = (int *)malloc(bsize * sizeof(int));
if(imap == (int *)NULL){
fprintf(stderr, "ERROR : gen_initial_imap : malloc : imap\n");
return(-70);
}
/* Allocate DFT directional power vectors */
if((ret = alloc_dir_powers(&powers, dftwaves->nwaves, dftgrids->ngrids))){
/* Free memory allocated to this point. */
free(imap);
return(ret);
}
/* Allocate DFT power statistic arrays */
/* Compute length of statistics arrays. Statistics not needed */
/* for the first DFT wave, so the length is number of waves - 1. */
nstats = dftwaves->nwaves - 1;
if((ret = alloc_power_stats(&wis, &powmaxs, &powmax_dirs,
&pownorms, nstats))){
/* Free memory allocated to this point. */
free(imap);
free_dir_powers(powers, dftwaves->nwaves);
return(ret);
}
/* Initialize the imap to -1 */
memset(imap, INVALID_DIR, bsize * sizeof(int));
/* Foreach block in imap ... */
for(bi = 0; bi < bsize; bi++){
print2log(" BLOCK %2d (%2d, %2d)\n", bi, bi%mw, bi/mw);
/* Compute DFT powers */
if((ret = dft_dir_powers(powers, pdata, blkoffs[bi], pw, ph,
dftwaves, dftgrids))){
/* Free memory allocated to this point. */
free(imap);
free_dir_powers(powers, dftwaves->nwaves);
free(wis);
free(powmaxs);
free(powmax_dirs);
free(pownorms);
return(ret);
}
/* Compute DFT power statistics, skipping first applied DFT */
/* wave. This is dependent on how the primary and secondary */
/* direction tests work below. */
if((ret = dft_power_stats(wis, powmaxs, powmax_dirs, pownorms, powers,
1, dftwaves->nwaves, dftgrids->ngrids))){
/* Free memory allocated to this point. */
free(imap);
free_dir_powers(powers, dftwaves->nwaves);
free(wis);
free(powmaxs);
free(powmax_dirs);
free(pownorms);
return(ret);
}
#ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
{ int _w;
fprintf(logfp, " Power\n");
for(_w = 0; _w < nstats; _w++){
/* Add 1 to wis[w] to create index to original dft_coefs[] */
fprintf(logfp, " wis[%d] %d %12.3f %2d %9.3f %12.3f\n",
_w, wis[_w]+1,
powmaxs[wis[_w]], powmax_dirs[wis[_w]], pownorms[wis[_w]],
powers[0][powmax_dirs[wis[_w]]]);
}
}
#endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/* Conduct primary direction test */
blkdir = primary_dir_test(powers, wis, powmaxs, powmax_dirs,
pownorms, nstats, lfsparms);
if(blkdir != INVALID_DIR)
imap[bi] = blkdir;
else{
/* Conduct secondary (fork) direction test */
blkdir = secondary_fork_test(powers, wis, powmaxs, powmax_dirs,
pownorms, nstats, lfsparms);
if(blkdir != INVALID_DIR)
imap[bi] = blkdir;
}
/* Otherwise current block direction in IMAP remains INVALID */
} /* bi */
/* Deallocate working memory */
free_dir_powers(powers, dftwaves->nwaves);
free(wis);
free(powmaxs);
free(powmax_dirs);
free(pownorms);
*optr = imap;
return(0);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
@ -1093,7 +1014,7 @@ int gen_initial_imap(int **optr, int *blkoffs, const int mw, const int mh,
powmaxs - maximum power for each of the highest N-1 frequencies powmaxs - maximum power for each of the highest N-1 frequencies
powmax_dirs - directions associated with each of the N-1 maximum powers powmax_dirs - directions associated with each of the N-1 maximum powers
pownorms - normalized power for each of the highest N-1 frequencies pownorms - normalized power for each of the highest N-1 frequencies
nstats - N-1 wave frequencies (where N is the length of dft_coefs) nstats - N-1 wave frequencies (where N is the length of g_dft_coefs)
lfsparms - parameters and thresholds for controlling LFS lfsparms - parameters and thresholds for controlling LFS
Return Code: Return Code:
Zero or Positive - The selected IMAP integer direction Zero or Positive - The selected IMAP integer direction
@ -1120,7 +1041,7 @@ int primary_dir_test(double **powers, const int *wis,
(powers[0][powmax_dirs[wis[w]]] <= lfsparms->powmax_max)){ (powers[0][powmax_dirs[wis[w]]] <= lfsparms->powmax_max)){
#ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
/* Add 1 to wis[w] to create index to original dft_coefs[] */ /* Add 1 to wis[w] to create index to original g_dft_coefs[] */
fprintf(logfp, fprintf(logfp,
" Selected Wave = %d\n", wis[w]+1); " Selected Wave = %d\n", wis[w]+1);
fprintf(logfp, fprintf(logfp,
@ -1177,7 +1098,7 @@ int primary_dir_test(double **powers, const int *wis,
powmaxs - maximum power for each of the highest N-1 frequencies powmaxs - maximum power for each of the highest N-1 frequencies
powmax_dirs - directions associated with each of the N-1 maximum powers powmax_dirs - directions associated with each of the N-1 maximum powers
pownorms - normalized power for each of the highest N-1 frequencies pownorms - normalized power for each of the highest N-1 frequencies
nstats - N-1 wave frequencies (where N is the length of dft_coefs) nstats - N-1 wave frequencies (where N is the length of g_dft_coefs)
lfsparms - parameters and thresholds for controlling LFS lfsparms - parameters and thresholds for controlling LFS
Return Code: Return Code:
Zero or Positive - The selected IMAP integer direction Zero or Positive - The selected IMAP integer direction
@ -2022,76 +1943,29 @@ int num_valid_8nbrs(int *imap, const int mx, const int my,
Output: Output:
imap - vector of smoothed input values imap - vector of smoothed input values
**************************************************************************/ **************************************************************************/
void smooth_imap(int *imap, const int mw, const int mh,
const DIR2RAD *dir2rad, const LFSPARMS *lfsparms)
{
int mx, my;
int *iptr;
int avrdir, nvalid;
double dir_strength;
print2log("SMOOTH MAP\n"); /*************************************************************************
**************************************************************************
#cat: gen_nmap - Computes an NMAP from its associated 2D vector of integer
#cat: directions (IMAP). Each value in the NMAP either represents
#cat: a direction of dominant ridge flow in a block of the input
#cat: grayscale image, or it contains a codes describing why such
#cat: a direction was not procuded.
#cat: For example, blocks near areas of high-curvature (such as
#cat: with cores and deltas) will not produce reliable IMAP
#cat: directions.
iptr = imap; Input:
for(my = 0; my < mh; my++){ imap - associated input vector of IMAP directions
for(mx = 0; mx < mw; mx++){ mw - the width (in blocks) of the IMAP
/* Compute average direction from neighbors, returning the */ mh - the height (in blocks) of the IMAP
/* number of valid neighbors used in the computation, and */ lfsparms - parameters and thresholds for controlling LFS
/* the "strength" of the average direction. */ Output:
average_8nbr_dir(&avrdir, &dir_strength, &nvalid, optr - points to the created NMAP
imap, mx, my, mw, mh, dir2rad); Return Code:
Zero - successful completion
/* If average direction strength is strong enough */ Negative - system error
/* (Ex. thresh==0.2)... */ **************************************************************************/
if(dir_strength >= lfsparms->dir_strength_min){
/* If IMAP direction is valid ... */
if(*iptr != INVALID_DIR){
/* Conduct valid neighbor test (Ex. thresh==3)... */
if(nvalid >= lfsparms->rmv_valid_nbr_min){
#ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
fprintf(logfp, " BLOCK %2d (%2d, %2d)\n",
mx+(my*mw), mx, my);
fprintf(logfp, " Average NBR : %2d %6.3f %d\n",
avrdir, dir_strength, nvalid);
fprintf(logfp, " 1. Valid NBR (%d >= %d)\n",
nvalid, lfsparms->rmv_valid_nbr_min);
fprintf(logfp, " Valid Direction = %d\n", *iptr);
fprintf(logfp, " Smoothed Direction = %d\n", avrdir);
#endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/* Reassign valid IMAP direction with average direction. */
*iptr = avrdir;
}
}
/* Otherwise IMAP direction is invalid ... */
else{
/* Even if IMAP value is invalid, if number of valid */
/* neighbors is big enough (Ex. thresh==7)... */
if(nvalid >= lfsparms->smth_valid_nbr_min){
#ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
fprintf(logfp, " BLOCK %2d (%2d, %2d)\n",
mx+(my*mw), mx, my);
fprintf(logfp, " Average NBR : %2d %6.3f %d\n",
avrdir, dir_strength, nvalid);
fprintf(logfp, " 2. Invalid NBR (%d >= %d)\n",
nvalid, lfsparms->smth_valid_nbr_min);
fprintf(logfp, " Invalid Direction = %d\n", *iptr);
fprintf(logfp, " Smoothed Direction = %d\n", avrdir);
#endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/* Assign invalid IMAP direction with average direction. */
*iptr = avrdir;
}
}
}
/* Bump to next IMAP direction. */
iptr++;
}
}
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -46,14 +67,14 @@ identified are necessarily the best available for the purpose.
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: match_1st_pair - Determines which of the feature_patterns[] have their #cat: match_1st_pair - Determines which of the g_feature_patterns[] have their
#cat: first pixel pair match the specified pixel pair. #cat: first pixel pair match the specified pixel pair.
Input: Input:
p1 - first pixel value of pair p1 - first pixel value of pair
p2 - second pixel value of pair p2 - second pixel value of pair
Output: Output:
possible - list of matching feature_patterns[] indices possible - list of matching g_feature_patterns[] indices
nposs - number of matches nposs - number of matches
Return Code: Return Code:
nposs - number of matches nposs - number of matches
@ -84,16 +105,16 @@ int match_1st_pair(unsigned char p1, unsigned char p2,
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: match_2nd_pair - Determines which of the passed feature_patterns[] have #cat: match_2nd_pair - Determines which of the passed g_feature_patterns[] have
#cat: their second pixel pair match the specified pixel pair. #cat: their second pixel pair match the specified pixel pair.
Input: Input:
p1 - first pixel value of pair p1 - first pixel value of pair
p2 - second pixel value of pair p2 - second pixel value of pair
possible - list of potentially-matching feature_patterns[] indices possible - list of potentially-matching g_feature_patterns[] indices
nposs - number of potential matches nposs - number of potential matches
Output: Output:
possible - list of matching feature_patterns[] indices possible - list of matching g_feature_patterns[] indices
nposs - number of matches nposs - number of matches
Return Code: Return Code:
nposs - number of matches nposs - number of matches
@ -132,16 +153,16 @@ int match_2nd_pair(unsigned char p1, unsigned char p2,
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: match_3rd_pair - Determines which of the passed feature_patterns[] have #cat: match_3rd_pair - Determines which of the passed g_feature_patterns[] have
#cat: their third pixel pair match the specified pixel pair. #cat: their third pixel pair match the specified pixel pair.
Input: Input:
p1 - first pixel value of pair p1 - first pixel value of pair
p2 - second pixel value of pair p2 - second pixel value of pair
possible - list of potentially-matching feature_patterns[] indices possible - list of potentially-matching g_feature_patterns[] indices
nposs - number of potential matches nposs - number of potential matches
Output: Output:
possible - list of matching feature_patterns[] indices possible - list of matching g_feature_patterns[] indices
nposs - number of matches nposs - number of matches
Return Code: Return Code:
nposs - number of matches nposs - number of matches

File diff suppressed because it is too large Load diff

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -151,7 +172,7 @@ char get_south8_2(char *ptr, const int row, const int iw, const int ih,
{ {
if (row >= ih-1) /* catch case where image is undefined southwards */ if (row >= ih-1) /* catch case where image is undefined southwards */
return failcode; /* use plane geometry and return code. */ return failcode; /* use plane geometry and return code. */
else
return *(ptr+iw); return *(ptr+iw);
} }
@ -175,7 +196,7 @@ char get_north8_2(char *ptr, const int row, const int iw,
{ {
if (row < 1) /* catch case where image is undefined northwards */ if (row < 1) /* catch case where image is undefined northwards */
return failcode; /* use plane geometry and return code. */ return failcode; /* use plane geometry and return code. */
else
return *(ptr-iw); return *(ptr-iw);
} }
@ -199,7 +220,7 @@ char get_east8_2(char *ptr, const int col, const int iw,
{ {
if (col >= iw-1) /* catch case where image is undefined eastwards */ if (col >= iw-1) /* catch case where image is undefined eastwards */
return failcode; /* use plane geometry and return code. */ return failcode; /* use plane geometry and return code. */
else
return *(ptr+ 1); return *(ptr+ 1);
} }
@ -221,6 +242,6 @@ char get_west8_2(char *ptr, const int col, const int failcode)
{ {
if (col < 1) /* catch case where image is undefined westwards */ if (col < 1) /* catch case where image is undefined westwards */
return failcode; /* use plane geometry and return code. */ return failcode; /* use plane geometry and return code. */
else
return *(ptr- 1); return *(ptr- 1);
} }

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -39,12 +60,11 @@ identified are necessarily the best available for the purpose.
combined_minutia_quality() combined_minutia_quality()
grayscale_reliability() grayscale_reliability()
get_neighborhood_stats() get_neighborhood_stats()
reliability_fr_quality_map()
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> #include <math.h>
#include <lfs.h> #include <lfs.h>
@ -172,120 +192,6 @@ int gen_quality_map(int **oqmap, int *direction_map, int *low_contrast_map,
return(0); return(0);
} }
/***********************************************************************
************************************************************************
#cat: get_neighborhood_stats - Given a minutia point, computes the mean
#cat: and stdev of the 8-bit grayscale pixels values in a
#cat: surrounding neighborhood with specified radius.
Code originally written by Austin Hicklin for FBI ATU
Modified by Michael D. Garris (NIST) Sept. 25, 2000
Input:
minutia - structure containing detected minutia
idata - 8-bit grayscale fingerprint image
iw - width (in pixels) of the image
ih - height (in pixels) of the image
radius_pix - pixel radius of surrounding neighborhood
Output:
mean - mean of neighboring pixels
stdev - standard deviation of neighboring pixels
************************************************************************/
static void get_neighborhood_stats(double *mean, double *stdev, MINUTIA *minutia,
unsigned char *idata, const int iw, const int ih,
const int radius_pix)
{
int i, x, y, rows, cols;
int n = 0, sumX = 0, sumXX = 0;
int histogram[256];
/* Zero out histogram. */
memset(histogram, 0, 256 * sizeof(int));
/* Set minutia's coordinate variables. */
x = minutia->x;
y = minutia->y;
/* If minutiae point is within sampleboxsize distance of image border, */
/* a value of 0 reliability is returned. */
if ((x < radius_pix) || (x > iw-radius_pix-1) ||
(y < radius_pix) || (y > ih-radius_pix-1)) {
*mean = 0.0;
*stdev = 0.0;
return;
}
/* Foreach row in neighborhood ... */
for(rows = y - radius_pix;
rows <= y + radius_pix;
rows++){
/* Foreach column in neighborhood ... */
for(cols = x - radius_pix;
cols <= x + radius_pix;
cols++){
/* Bump neighbor's pixel value bin in histogram. */
histogram[*(idata+(rows * iw)+cols)]++;
}
}
/* Foreach grayscale pixel bin ... */
for(i = 0; i < 256; i++){
if(histogram[i]){
/* Accumulate Sum(X[i]) */
sumX += (i * histogram[i]);
/* Accumulate Sum(X[i]^2) */
sumXX += (i * i * histogram[i]);
/* Accumulate N samples */
n += histogram[i];
}
}
/* Mean = Sum(X[i])/N */
*mean = sumX/(double)n;
/* Stdev = sqrt((Sum(X[i]^2)/N) - Mean^2) */
*stdev = sqrt((sumXX/(double)n) - ((*mean)*(*mean)));
}
/***********************************************************************
************************************************************************
#cat: grayscale_reliability - Given a minutia point, computes a reliability
#cat: measure from the stdev and mean of its pixel neighborhood.
Code originally written by Austin Hicklin for FBI ATU
Modified by Michael D. Garris (NIST) Sept. 25, 2000
GrayScaleReliability - reasonable reliability heuristic, returns
0.0 .. 1.0 based on stdev and Mean of a localized histogram where
"ideal" stdev is >=64; "ideal" Mean is 127. In a 1 ridge radius
(11 pixels), if the bytevalue (shade of gray) in the image has a
stdev of >= 64 & a mean of 127, returns 1.0 (well defined
light & dark areas in equal proportions).
Input:
minutia - structure containing detected minutia
idata - 8-bit grayscale fingerprint image
iw - width (in pixels) of the image
ih - height (in pixels) of the image
radius_pix - pixel radius of surrounding neighborhood
Return Value:
reliability - computed reliability measure
************************************************************************/
static double grayscale_reliability(MINUTIA *minutia, unsigned char *idata,
const int iw, const int ih, const int radius_pix)
{
double mean, stdev;
double reliability;
get_neighborhood_stats(&mean, &stdev, minutia, idata, iw, ih, radius_pix);
reliability = min((stdev>IDEALSTDEV ? 1.0 : stdev/(double)IDEALSTDEV),
(1.0-(fabs(mean-IDEALMEAN)/(double)IDEALMEAN)));
return(reliability);
}
/*********************************************************************** /***********************************************************************
************************************************************************ ************************************************************************
#cat: combined_minutia_quality - Combines quality measures derived from #cat: combined_minutia_quality - Combines quality measures derived from
@ -391,3 +297,137 @@ int combined_minutia_quality(MINUTIAE *minutiae,
return(0); return(0);
} }
/***********************************************************************
************************************************************************
#cat: grayscale_reliability - Given a minutia point, computes a reliability
#cat: measure from the stdev and mean of its pixel neighborhood.
Code originally written by Austin Hicklin for FBI ATU
Modified by Michael D. Garris (NIST) Sept. 25, 2000
GrayScaleReliability - reasonable reliability heuristic, returns
0.0 .. 1.0 based on stdev and Mean of a localized histogram where
"ideal" stdev is >=64; "ideal" Mean is 127. In a 1 ridge radius
(11 pixels), if the bytevalue (shade of gray) in the image has a
stdev of >= 64 & a mean of 127, returns 1.0 (well defined
light & dark areas in equal proportions).
Input:
minutia - structure containing detected minutia
idata - 8-bit grayscale fingerprint image
iw - width (in pixels) of the image
ih - height (in pixels) of the image
radius_pix - pixel radius of surrounding neighborhood
Return Value:
reliability - computed reliability measure
************************************************************************/
double grayscale_reliability(MINUTIA *minutia, unsigned char *idata,
const int iw, const int ih, const int radius_pix)
{
double mean, stdev;
double reliability;
get_neighborhood_stats(&mean, &stdev, minutia, idata, iw, ih, radius_pix);
reliability = min((stdev>IDEALSTDEV ? 1.0 : stdev/(double)IDEALSTDEV),
(1.0-(fabs(mean-IDEALMEAN)/(double)IDEALMEAN)));
return(reliability);
}
/***********************************************************************
************************************************************************
#cat: get_neighborhood_stats - Given a minutia point, computes the mean
#cat: and stdev of the 8-bit grayscale pixels values in a
#cat: surrounding neighborhood with specified radius.
Code originally written by Austin Hicklin for FBI ATU
Modified by Michael D. Garris (NIST) Sept. 25, 2000
Input:
minutia - structure containing detected minutia
idata - 8-bit grayscale fingerprint image
iw - width (in pixels) of the image
ih - height (in pixels) of the image
radius_pix - pixel radius of surrounding neighborhood
Output:
mean - mean of neighboring pixels
stdev - standard deviation of neighboring pixels
************************************************************************/
void get_neighborhood_stats(double *mean, double *stdev, MINUTIA *minutia,
unsigned char *idata, const int iw, const int ih,
const int radius_pix)
{
int i, x, y, rows, cols;
int n = 0, sumX = 0, sumXX = 0;
int histogram[256];
/* Zero out histogram. */
memset(histogram, 0, 256 * sizeof(int));
/* Set minutia's coordinate variables. */
x = minutia->x;
y = minutia->y;
/* If minutiae point is within sampleboxsize distance of image border, */
/* a value of 0 reliability is returned. */
if ((x < radius_pix) || (x > iw-radius_pix-1) ||
(y < radius_pix) || (y > ih-radius_pix-1)) {
*mean = 0.0;
*stdev = 0.0;
return;
}
/* Foreach row in neighborhood ... */
for(rows = y - radius_pix;
rows <= y + radius_pix;
rows++){
/* Foreach column in neighborhood ... */
for(cols = x - radius_pix;
cols <= x + radius_pix;
cols++){
/* Bump neighbor's pixel value bin in histogram. */
histogram[*(idata+(rows * iw)+cols)]++;
}
}
/* Foreach grayscale pixel bin ... */
for(i = 0; i < 256; i++){
if(histogram[i]){
/* Accumulate Sum(X[i]) */
sumX += (i * histogram[i]);
/* Accumulate Sum(X[i]^2) */
sumXX += (i * i * histogram[i]);
/* Accumulate N samples */
n += histogram[i];
}
}
/* Mean = Sum(X[i])/N */
*mean = sumX/(double)n;
/* Stdev = sqrt((Sum(X[i]^2)/N) - Mean^2) */
*stdev = sqrt((sumXX/(double)n) - ((*mean)*(*mean)));
}
/***********************************************************************
************************************************************************
#cat: reliability_fr_quality_map - Takes a set of minutiae and assigns
#cat: each one a reliability measure based on 1 of 5 possible
#cat: quality levels from its location in a quality map.
Input:
minutiae - structure contining the detected minutia
quality_map - map with blocks assigned 1 of 5 quality levels
map_w - width (in blocks) of the map
map_h - height (in blocks) of the map
blocksize - size (in pixels) of each block in the map
Output:
minutiae - updated reliability members
Return Code:
Zero - successful completion
Negative - system error
************************************************************************/

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -35,15 +56,21 @@ identified are necessarily the best available for the purpose.
*********************************************************************** ***********************************************************************
ROUTINES: ROUTINES:
remove_false_minutia()
remove_false_minutia_V2() remove_false_minutia_V2()
remove_holes() remove_holes()
remove_hooks() remove_hooks()
remove_hooks_islands_overlaps()
remove_islands_and_lakes() remove_islands_and_lakes()
remove_malformations() remove_malformations()
remove_near_invblock_V2() remove_near_invblocks()
remove_near_invblocks_V2()
remove_pointing_invblock()
remove_pointing_invblock_V2() remove_pointing_invblock_V2()
remove_overlaps() remove_overlaps()
remove_pores()
remove_pores_V2() remove_pores_V2()
remove_or_adjust_side_minutiae()
remove_or_adjust_side_minutiae_V2() remove_or_adjust_side_minutiae_V2()
***********************************************************************/ ***********************************************************************/
@ -52,6 +79,125 @@ identified are necessarily the best available for the purpose.
#include <lfs.h> #include <lfs.h>
#include <log.h> #include <log.h>
/*************************************************************************
**************************************************************************
#cat: remove_false_minutia - Takes a list of true and false minutiae and
#cat: attempts to detect and remove the false minutiae based
#cat: on a series of tests.
Input:
minutiae - list of true and false minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
nmap - IMAP ridge flow matrix with invalid, high-curvature,
and no-valid-neighbor regions identified
mw - width in blocks of the NMAP
mh - height in blocks of the NMAP
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: remove_false_minutia_V2 - Takes a list of true and false minutiae and
#cat: attempts to detect and remove the false minutiae based
#cat: on a series of tests.
Input:
minutiae - list of true and false minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
direction_map - map of image blocks containing directional ridge flow
low_flow_map - map of image blocks flagged as LOW RIDGE FLOW
high_curve_map - map of image blocks flagged as HIGH CURVATURE
mw - width in blocks of the maps
mh - height in blocks of the maps
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
int remove_false_minutia_V2(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih,
int *direction_map, int *low_flow_map, int *high_curve_map,
const int mw, const int mh, const LFSPARMS *lfsparms)
{
int ret;
/* 1. Sort minutiae points top-to-bottom and left-to-right. */
if((ret = sort_minutiae_y_x(minutiae, iw, ih))){
return(ret);
}
/* 2. Remove minutiae on lakes (filled with white pixels) and */
/* islands (filled with black pixels), both defined by a pair of */
/* minutia points. */
if((ret = remove_islands_and_lakes(minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
/* 3. Remove minutiae on holes in the binary image defined by a */
/* single point. */
if((ret = remove_holes(minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
/* 4. Remove minutiae that point sufficiently close to a block with */
/* INVALID direction. */
if((ret = remove_pointing_invblock_V2(minutiae, direction_map, mw, mh,
lfsparms))){
return(ret);
}
/* 5. Remove minutiae that are sufficiently close to a block with */
/* INVALID direction. */
if((ret = remove_near_invblock_V2(minutiae, direction_map, mw, mh,
lfsparms))){
return(ret);
}
/* 6. Remove or adjust minutiae that reside on the side of a ridge */
/* or valley. */
if((ret = remove_or_adjust_side_minutiae_V2(minutiae, bdata, iw, ih,
direction_map, mw, mh, lfsparms))){
return(ret);
}
/* 7. Remove minutiae that form a hook on the side of a ridge or valley. */
if((ret = remove_hooks(minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
/* 8. Remove minutiae that are on opposite sides of an overlap. */
if((ret = remove_overlaps(minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
/* 9. Remove minutiae that are "irregularly" shaped. */
if((ret = remove_malformations(minutiae, bdata, iw, ih,
low_flow_map, mw, mh, lfsparms))){
return(ret);
}
/* 10. Remove minutiae that form long, narrow, loops in the */
/* "unreliable" regions in the binary image. */
if((ret = remove_pores_V2(minutiae, bdata, iw, ih,
direction_map, low_flow_map, high_curve_map,
mw, mh, lfsparms))){
return(ret);
}
return(0);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: remove_holes - Removes minutia points on small loops around valleys. #cat: remove_holes - Removes minutia points on small loops around valleys.
@ -68,7 +214,7 @@ identified are necessarily the best available for the purpose.
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_holes(MINUTIAE *minutiae, int remove_holes(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih, unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms) const LFSPARMS *lfsparms)
{ {
@ -139,7 +285,7 @@ static int remove_holes(MINUTIAE *minutiae,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_hooks(MINUTIAE *minutiae, int remove_hooks(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih, unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms) const LFSPARMS *lfsparms)
{ {
@ -341,6 +487,29 @@ static int remove_hooks(MINUTIAE *minutiae,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: remove_hooks_islands_lakes_overlaps - Removes minutia points on hooks,
#cat: islands, lakes, and overlaps and fills in small small
#cat: loops in the binary image and joins minutia features in
#cat: the image on opposite sides of an overlap. So, this
#cat: routine not only prunes minutia points but it edits the
#cat: binary input image as well.
Input:
minutiae - list of true and false minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
bdata - edited binary image with loops filled and overlaps removed
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: remove_islands_and_lakes - Takes a list of true and false minutiae and #cat: remove_islands_and_lakes - Takes a list of true and false minutiae and
@ -362,7 +531,7 @@ static int remove_hooks(MINUTIAE *minutiae,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_islands_and_lakes(MINUTIAE *minutiae, int remove_islands_and_lakes(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih, unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms) const LFSPARMS *lfsparms)
{ {
@ -616,7 +785,7 @@ static int remove_islands_and_lakes(MINUTIAE *minutiae,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_malformations(MINUTIAE *minutiae, int remove_malformations(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih, unsigned char *bdata, const int iw, const int ih,
int *low_flow_map, const int mw, const int mh, int *low_flow_map, const int mw, const int mh,
const LFSPARMS *lfsparms) const LFSPARMS *lfsparms)
@ -803,6 +972,26 @@ static int remove_malformations(MINUTIAE *minutiae,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: remove_near_invblocks - Removes minutia points from the given list
#cat: that are sufficiently close to a block with invalid
#cat: ridge flow or to the edge of the image.
Input:
minutiae - list of true and false minutiae
nmap - IMAP ridge flow matrix with invalid, high-curvature,
and no-valid-neighbor regions identified
mw - width in blocks of the NMAP
mh - height in blocks of the NMAP
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: remove_near_invblocks_V2 - Removes minutia points from the given list #cat: remove_near_invblocks_V2 - Removes minutia points from the given list
@ -821,7 +1010,7 @@ static int remove_malformations(MINUTIAE *minutiae,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map, int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map,
const int mw, const int mh, const LFSPARMS *lfsparms) const int mw, const int mh, const LFSPARMS *lfsparms)
{ {
int i, ret; int i, ret;
@ -1032,6 +1221,26 @@ static int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: remove_pointing_invblock - Removes minutia points that are relatively
#cat: close in the direction opposite the minutia to an NMAP
#cat: block with invalid ridge flow.
Input:
minutiae - list of true and false minutiae
nmap - IMAP ridge flow matrix with invalid, high-curvature,
and no-valid-neighbor regions identified
mw - width in blocks of the NMAP
mh - height in blocks of the NMAP
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: remove_pointing_invblock_V2 - Removes minutia points that are relatively #cat: remove_pointing_invblock_V2 - Removes minutia points that are relatively
@ -1050,7 +1259,7 @@ static int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_pointing_invblock_V2(MINUTIAE *minutiae, int remove_pointing_invblock_V2(MINUTIAE *minutiae,
int *direction_map, const int mw, const int mh, int *direction_map, const int mw, const int mh,
const LFSPARMS *lfsparms) const LFSPARMS *lfsparms)
{ {
@ -1140,7 +1349,7 @@ static int remove_pointing_invblock_V2(MINUTIAE *minutiae,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_overlaps(MINUTIAE *minutiae, int remove_overlaps(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih, unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms) const LFSPARMS *lfsparms)
{ {
@ -1350,32 +1559,20 @@ static int remove_overlaps(MINUTIAE *minutiae,
return(0); return(0);
} }
static void mark_minutiae_in_range(MINUTIAE *minutiae, int *to_remove, int x, int y,
const LFSPARMS *lfsparms)
{
int i, dist;
for (i = 0; i < minutiae->num; i++) {
if (to_remove[i])
continue;
dist = (int)sqrt((x - minutiae->list[i]->x) * (x - minutiae->list[i]->x) +
(y - minutiae->list[i]->y) * (y - minutiae->list[i]->y));
if (dist < lfsparms->min_pp_distance) {
to_remove[i] = 1;
}
}
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: remove_perimeter_pts - Takes a list of true and false minutiae and #cat: remove_pores - Attempts to detect and remove minutia points located on
#cat: attempts to detect and remove those false minutiae that #cat: pore-shaped valleys.
#cat: belong to image edge
Input: Input:
minutiae - list of true and false minutiae minutiae - list of true and false minutiae
bdata - binary image data (0==while & 1==black) bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image iw - width (in pixels) of image
ih - height (in pixels) of image ih - height (in pixels) of image
nmap - IMAP ridge flow matrix with invalid, high-curvature,
and no-valid-neighbor regions identified
mw - width in blocks of the NMAP
mh - height in blocks of the NMAP
lfsparms - parameters and thresholds for controlling LFS lfsparms - parameters and thresholds for controlling LFS
Output: Output:
minutiae - list of pruned minutiae minutiae - list of pruned minutiae
@ -1383,125 +1580,6 @@ static void mark_minutiae_in_range(MINUTIAE *minutiae, int *to_remove, int x, in
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_perimeter_pts(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms)
{
int i, j, ret, *to_remove;
int *left, *left_up, *left_down;
int *right, *right_up, *right_down;
int removed = 0;
int left_min, right_max;
if (!lfsparms->remove_perimeter_pts)
return(0);
to_remove = calloc(minutiae->num, sizeof(int));
left = calloc(ih, sizeof(int));
left_up = calloc(ih, sizeof(int));
left_down = calloc(ih, sizeof(int));
right = calloc(ih, sizeof(int));
right_up = calloc(ih, sizeof(int));
right_down = calloc(ih, sizeof(int));
/* Pass downwards */
left_min = iw - 1;
right_max = 0;
for (i = 0; i < ih; i++) {
for (j = 0; j < left_min; j++) {
if ((bdata[i * iw + j] != 0)) {
left_min = j;
break;
}
}
if (left_min == (iw - 1))
left_down[i] = -1;
else
left_down[i] = left_min;
for (j = iw - 1; j >= right_max; j--) {
if ((bdata[i * iw + j] != 0)) {
right_max = j;
break;
}
}
if (right_max == 0)
right_down[i] = -1;
else
right_down[i] = right_max;
}
/* Pass upwards */
left_min = iw - 1;
right_max = 0;
for (i = ih - 1; i >= 0; i--) {
for (j = 0; j < left_min; j++) {
if ((bdata[i * iw + j] != 0)) {
left_min = j;
break;
}
}
if (left_min == (iw - 1))
left_up[i] = -1;
else
left_up[i] = left_min;
for (j = iw - 1; j >= right_max; j--) {
if ((bdata[i * iw + j] != 0)) {
right_max = j;
break;
}
}
if (right_max == 0)
right_up[i] = -1;
else
right_up[i] = right_max;
}
/* Merge */
left_min = left_down[ih - 1];
right_max = right_down[ih - 1];
for (i = 0; i < ih; i++) {
if (left_down[i] != left_min)
left[i] = left_down[i];
else
left[i] = left_up[i];
if (right_down[i] != right_max)
right[i] = right_down[i];
else
right[i] = right_up[i];
}
free(left_up);
free(left_down);
free(right_up);
free(right_down);
/* Mark minitiae close to the edge */
for (i = 0; i < ih; i++) {
if (left[i] != -1)
mark_minutiae_in_range(minutiae, to_remove, left[i], i, lfsparms);
if (right[i] != -1)
mark_minutiae_in_range(minutiae, to_remove, right[i], i, lfsparms);
}
free(left);
free(right);
for (i = minutiae->num - 1; i >= 0; i--) {
/* If the current minutia index is flagged for removal ... */
if (to_remove[i]){
removed ++;
/* Remove the minutia from the minutiae list. */
if((ret = remove_minutia(i, minutiae))){
free(to_remove);
return(ret);
}
}
}
free(to_remove);
return (0);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
@ -1527,7 +1605,7 @@ static int remove_perimeter_pts(MINUTIAE *minutiae,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_pores_V2(MINUTIAE *minutiae, int remove_pores_V2(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih, unsigned char *bdata, const int iw, const int ih,
int *direction_map, int *low_flow_map, int *direction_map, int *low_flow_map,
int *high_curve_map, const int mw, const int mh, int *high_curve_map, const int mw, const int mh,
@ -1896,6 +1974,26 @@ static int remove_pores_V2(MINUTIAE *minutiae,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: remove_or_adjust_side_minutiae - Removes loops or minutia points that
#cat: are not on complete contours of specified length. If the
#cat: contour is complete, then the minutia is adjusted based
#cat: on a minmax analysis of the rotated y-coords of the contour.
Input:
minutiae - list of true and false minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: remove_or_adjust_side_minutiae_V2 - Removes loops or minutia points that #cat: remove_or_adjust_side_minutiae_V2 - Removes loops or minutia points that
@ -1918,7 +2016,7 @@ static int remove_pores_V2(MINUTIAE *minutiae,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih, unsigned char *bdata, const int iw, const int ih,
int *direction_map, const int mw, const int mh, int *direction_map, const int mw, const int mh,
const LFSPARMS *lfsparms) const LFSPARMS *lfsparms)
@ -2164,104 +2262,3 @@ static int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: remove_false_minutia_V2 - Takes a list of true and false minutiae and
#cat: attempts to detect and remove the false minutiae based
#cat: on a series of tests.
Input:
minutiae - list of true and false minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
direction_map - map of image blocks containing directional ridge flow
low_flow_map - map of image blocks flagged as LOW RIDGE FLOW
high_curve_map - map of image blocks flagged as HIGH CURVATURE
mw - width in blocks of the maps
mh - height in blocks of the maps
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of pruned minutiae
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
int remove_false_minutia_V2(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih,
int *direction_map, int *low_flow_map, int *high_curve_map,
const int mw, const int mh, const LFSPARMS *lfsparms)
{
int ret;
/* 1. Sort minutiae points top-to-bottom and left-to-right. */
if((ret = sort_minutiae_y_x(minutiae, iw, ih))){
return(ret);
}
/* 2. Remove minutiae on lakes (filled with white pixels) and */
/* islands (filled with black pixels), both defined by a pair of */
/* minutia points. */
if((ret = remove_islands_and_lakes(minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
/* 3. Remove minutiae on holes in the binary image defined by a */
/* single point. */
if((ret = remove_holes(minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
/* 4. Remove minutiae that point sufficiently close to a block with */
/* INVALID direction. */
if((ret = remove_pointing_invblock_V2(minutiae, direction_map, mw, mh,
lfsparms))){
return(ret);
}
/* 5. Remove minutiae that are sufficiently close to a block with */
/* INVALID direction. */
if((ret = remove_near_invblock_V2(minutiae, direction_map, mw, mh,
lfsparms))){
return(ret);
}
/* 6. Remove or adjust minutiae that reside on the side of a ridge */
/* or valley. */
if((ret = remove_or_adjust_side_minutiae_V2(minutiae, bdata, iw, ih,
direction_map, mw, mh, lfsparms))){
return(ret);
}
/* 7. Remove minutiae that form a hook on the side of a ridge or valley. */
if((ret = remove_hooks(minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
/* 8. Remove minutiae that are on opposite sides of an overlap. */
if((ret = remove_overlaps(minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
/* 9. Remove minutiae that are "irregularly" shaped. */
if((ret = remove_malformations(minutiae, bdata, iw, ih,
low_flow_map, mw, mh, lfsparms))){
return(ret);
}
/* 10. Remove minutiae that form long, narrow, loops in the */
/* "unreliable" regions in the binary image. */
if((ret = remove_pores_V2(minutiae, bdata, iw, ih,
direction_map, low_flow_map, high_curve_map,
mw, mh, lfsparms))){
return(ret);
}
/* 11. Remove minutiae on image edge */
if((ret = remove_perimeter_pts(minutiae, bdata, iw, ih, lfsparms))) {
return (ret);
}
return(0);
}

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -52,76 +73,51 @@ identified are necessarily the best available for the purpose.
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: insert_neighbor - Takes a minutia index and its squared distance to a #cat: count_minutiae_ridges - Takes a list of minutiae, and for each one,
#cat: primary minutia point, and inserts them in the specified #cat: determines its closest neighbors and counts the number
#cat: position of their respective lists, shifting previously #cat: of interveining ridges between the minutia point and
#cat: stored values down and off the lists as necessary. #cat: each of its neighbors.
Input: Input:
pos - postions where values are to be inserted in lists minutiae - list of minutiae
nbr_index - index of minutia being inserted bdata - binary image data (0==while & 1==black)
nbr_dist2 - squared distance of minutia to its primary point iw - width (in pixels) of image
nbr_list - current list of nearest neighbor minutia indices ih - height (in pixels) of image
nbr_sqr_dists - corresponding squared euclidean distance of each lfsparms - parameters and thresholds for controlling LFS
neighbor to the primary minutia point
nnbrs - number of neighbors currently in the list
max_nbrs - maximum number of closest neighbors to be returned
Output: Output:
nbr_list - updated list of nearest neighbor indices minutiae - list of minutiae augmented with neighbors and ridge counts
nbr_sqr_dists - updated list of nearest neighbor distances
nnbrs - number of neighbors in the update lists
Return Code: Return Code:
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int insert_neighbor(const int pos, const int nbr_index, const double nbr_dist2, int count_minutiae_ridges(MINUTIAE *minutiae,
int *nbr_list, double *nbr_sqr_dists, unsigned char *bdata, const int iw, const int ih,
int *nnbrs, const int max_nbrs) const LFSPARMS *lfsparms)
{ {
int ret;
int i; int i;
/* If the desired insertion position is beyond one passed the last */ print2log("\nFINDING NBRS AND COUNTING RIDGES:\n");
/* neighbor in the lists OR greater than equal to the maximum ... */
/* NOTE: pos is zero-oriented while nnbrs and max_nbrs are 1-oriented. */ /* Sort minutia points on x then y (column-oriented). */
if((pos > *nnbrs) || if((ret = sort_minutiae_x_y(minutiae, iw, ih))){
(pos >= max_nbrs)){ return(ret);
fprintf(stderr,
"ERROR : insert_neighbor : insertion point exceeds lists\n");
return(-480);
} }
/* If the neighbor lists are NOT full ... */ /* Remove any duplicate minutia points from the list. */
if(*nnbrs < max_nbrs){ if((ret = rm_dup_minutiae(minutiae))){
/* Then we have room to shift everything down to make room for new */ return(ret);
/* neighbor and increase the number of neighbors stored by 1. */
i = *nnbrs-1;
(*nnbrs)++;
}
/* Otherwise, the neighbors lists are full ... */
else if(*nnbrs == max_nbrs)
/* So, we must bump the last neighbor in the lists off to make */
/* room for the new neighbor (ignore last neighbor in lists). */
i = *nnbrs-2;
/* Otherwise, there is a list overflow error condition */
/* (shouldn't ever happen, but just in case) ... */
else{
fprintf(stderr,
"ERROR : insert_neighbor : overflow in neighbor lists\n");
return(-481);
} }
/* While we havn't reached the desired insertion point ... */ /* Foreach remaining sorted minutia in list ... */
while(i >= pos){ for(i = 0; i < minutiae->num-1; i++){
/* Shift the current neighbor down the list 1 positon. */ /* Located neighbors and count number of ridges in between. */
nbr_list[i+1] = nbr_list[i]; /* NOTE: neighbor and ridge count results are stored in */
nbr_sqr_dists[i+1] = nbr_sqr_dists[i]; /* minutiae->list[i]. */
i--; if((ret = count_minutia_ridges(i, minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
} }
/* We are now ready to put our new neighbor in the position where */
/* we shifted everything down from to make room. */
nbr_list[pos] = nbr_index;
nbr_sqr_dists[pos] = nbr_dist2;
/* Return normally. */ /* Return normally. */
return(0); return(0);
@ -129,79 +125,83 @@ static int insert_neighbor(const int pos, const int nbr_index, const double nbr_
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: update_nbr_dists - Takes the current list of neighbors along with a #cat: count_minutia_ridges - Takes a minutia, and determines its closest
#cat: primary minutia and a potential new neighbor, and #cat: neighbors and counts the number of interveining ridges
#cat: determines if the new neighbor is sufficiently close #cat: between the minutia point and each of its neighbors.
#cat: to be added to the list of nearest neighbors. If added,
#cat: it is placed in the list in its proper order based on
#cat: squared distance to the primary point.
Input: Input:
nbr_list - current list of nearest neighbor minutia indices minutia - input minutia
nbr_sqr_dists - corresponding squared euclidean distance of each bdata - binary image data (0==while & 1==black)
neighbor to the primary minutia point iw - width (in pixels) of image
nnbrs - number of neighbors currently in the list ih - height (in pixels) of image
max_nbrs - maximum number of closest neighbors to be returned lfsparms - parameters and thresholds for controlling LFS
first - index of the primary minutia point
second - index of the secondary (new neighbor) point
minutiae - list of minutiae
Output: Output:
nbr_list - updated list of nearest neighbor indices minutiae - minutia augmented with neighbors and ridge counts
nbr_sqr_dists - updated list of nearest neighbor distances
nnbrs - number of neighbors in the update lists
Return Code: Return Code:
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int update_nbr_dists(int *nbr_list, double *nbr_sqr_dists, int count_minutia_ridges(const int first, MINUTIAE *minutiae,
int *nnbrs, const int max_nbrs, unsigned char *bdata, const int iw, const int ih,
const int first, const int second, MINUTIAE *minutiae) const LFSPARMS *lfsparms)
{ {
double dist2; int i, ret, *nbr_list, *nbr_nridges, nnbrs;
MINUTIA *minutia1, *minutia2;
int pos, last_nbr;
/* Compute position of maximum last neighbor stored. */ /* Find up to the maximum number of qualifying neighbors. */
last_nbr = max_nbrs - 1; if((ret = find_neighbors(&nbr_list, &nnbrs, lfsparms->max_nbrs,
first, minutiae))){
/* Assigne temporary minutia pointers. */ free(nbr_list);
minutia1 = minutiae->list[first]; return(ret);
minutia2 = minutiae->list[second];
/* Compute squared euclidean distance between minutia pair. */
dist2 = squared_distance(minutia1->x, minutia1->y,
minutia2->x, minutia2->y);
/* If maximum number of neighbors not yet stored in lists OR */
/* if the squared distance to current secondary is less */
/* than the largest stored neighbor distance ... */
if((*nnbrs < max_nbrs) ||
(dist2 < nbr_sqr_dists[last_nbr])){
/* Find insertion point in neighbor lists. */
pos = find_incr_position_dbl(dist2, nbr_sqr_dists, *nnbrs);
/* If the position returned is >= maximum list length (this should */
/* never happen, but just in case) ... */
if(pos >= max_nbrs){
fprintf(stderr,
"ERROR : update_nbr_dists : illegal position for new neighbor\n");
return(-470);
} }
/* Insert the new neighbor into the neighbor lists at the */
/* specified location. */
if(insert_neighbor(pos, second, dist2,
nbr_list, nbr_sqr_dists, nnbrs, max_nbrs))
return(-471);
/* Otherwise, neighbor inserted successfully, so return normally. */ print2log("NBRS FOUND: %d,%d = %d\n", minutiae->list[first]->x,
minutiae->list[first]->y, nnbrs);
/* If no neighors found ... */
if(nnbrs == 0){
/* Then no list returned and no ridges to count. */
return(0); return(0);
} }
/* Otherwise, the new neighbor is not sufficiently close to be */
/* added or inserted into the neighbor lists, so ignore the neighbor */
/* and return normally. */
else
return(0);
/* Sort neighbors on delta dirs. */
if((ret = sort_neighbors(nbr_list, nnbrs, first, minutiae))){
free(nbr_list);
return(ret);
}
/* Count ridges between first and neighbors. */
/* List of ridge counts, one for each neighbor stored. */
nbr_nridges = (int *)malloc(nnbrs * sizeof(int));
if(nbr_nridges == (int *)NULL){
free(nbr_list);
fprintf(stderr, "ERROR : count_minutia_ridges : malloc : nbr_nridges\n");
return(-450);
}
/* Foreach neighbor found and sorted in list ... */
for(i = 0; i < nnbrs; i++){
/* Count the ridges between the primary minutia and the neighbor. */
ret = ridge_count(first, nbr_list[i], minutiae, bdata, iw, ih, lfsparms);
/* If system error ... */
if(ret < 0){
/* Deallocate working memories. */
free(nbr_list);
free(nbr_nridges);
/* Return error code. */
return(ret);
}
/* Otherwise, ridge count successful, so store ridge count to list. */
nbr_nridges[i] = ret;
}
/* Assign neighbor indices and ridge counts to primary minutia. */
minutiae->list[first]->nbrs = nbr_list;
minutiae->list[first]->ridge_counts = nbr_nridges;
minutiae->list[first]->num_nbrs = nnbrs;
/* Return normally. */
return(0);
} }
/************************************************************************* /*************************************************************************
@ -224,7 +224,7 @@ static int update_nbr_dists(int *nbr_list, double *nbr_sqr_dists,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs, int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs,
const int first, MINUTIAE *minutiae) const int first, MINUTIAE *minutiae)
{ {
int ret, second, last_nbr; int ret, second, last_nbr;
@ -312,6 +312,160 @@ static int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: update_nbr_dists - Takes the current list of neighbors along with a
#cat: primary minutia and a potential new neighbor, and
#cat: determines if the new neighbor is sufficiently close
#cat: to be added to the list of nearest neighbors. If added,
#cat: it is placed in the list in its proper order based on
#cat: squared distance to the primary point.
Input:
nbr_list - current list of nearest neighbor minutia indices
nbr_sqr_dists - corresponding squared euclidean distance of each
neighbor to the primary minutia point
nnbrs - number of neighbors currently in the list
max_nbrs - maximum number of closest neighbors to be returned
first - index of the primary minutia point
second - index of the secondary (new neighbor) point
minutiae - list of minutiae
Output:
nbr_list - updated list of nearest neighbor indices
nbr_sqr_dists - updated list of nearest neighbor distances
nnbrs - number of neighbors in the update lists
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
int update_nbr_dists(int *nbr_list, double *nbr_sqr_dists,
int *nnbrs, const int max_nbrs,
const int first, const int second, MINUTIAE *minutiae)
{
double dist2;
MINUTIA *minutia1, *minutia2;
int pos, last_nbr;
/* Compute position of maximum last neighbor stored. */
last_nbr = max_nbrs - 1;
/* Assigne temporary minutia pointers. */
minutia1 = minutiae->list[first];
minutia2 = minutiae->list[second];
/* Compute squared euclidean distance between minutia pair. */
dist2 = squared_distance(minutia1->x, minutia1->y,
minutia2->x, minutia2->y);
/* If maximum number of neighbors not yet stored in lists OR */
/* if the squared distance to current secondary is less */
/* than the largest stored neighbor distance ... */
if((*nnbrs < max_nbrs) ||
(dist2 < nbr_sqr_dists[last_nbr])){
/* Find insertion point in neighbor lists. */
pos = find_incr_position_dbl(dist2, nbr_sqr_dists, *nnbrs);
/* If the position returned is >= maximum list length (this should */
/* never happen, but just in case) ... */
if(pos >= max_nbrs){
fprintf(stderr,
"ERROR : update_nbr_dists : illegal position for new neighbor\n");
return(-470);
}
/* Insert the new neighbor into the neighbor lists at the */
/* specified location. */
if(insert_neighbor(pos, second, dist2,
nbr_list, nbr_sqr_dists, nnbrs, max_nbrs))
return(-471);
/* Otherwise, neighbor inserted successfully, so return normally. */
return(0);
}
/* Otherwise, the new neighbor is not sufficiently close to be */
/* added or inserted into the neighbor lists, so ignore the neighbor */
/* and return normally. */
else
return(0);
}
/*************************************************************************
**************************************************************************
#cat: insert_neighbor - Takes a minutia index and its squared distance to a
#cat: primary minutia point, and inserts them in the specified
#cat: position of their respective lists, shifting previously
#cat: stored values down and off the lists as necessary.
Input:
pos - postions where values are to be inserted in lists
nbr_index - index of minutia being inserted
nbr_dist2 - squared distance of minutia to its primary point
nbr_list - current list of nearest neighbor minutia indices
nbr_sqr_dists - corresponding squared euclidean distance of each
neighbor to the primary minutia point
nnbrs - number of neighbors currently in the list
max_nbrs - maximum number of closest neighbors to be returned
Output:
nbr_list - updated list of nearest neighbor indices
nbr_sqr_dists - updated list of nearest neighbor distances
nnbrs - number of neighbors in the update lists
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
int insert_neighbor(const int pos, const int nbr_index, const double nbr_dist2,
int *nbr_list, double *nbr_sqr_dists,
int *nnbrs, const int max_nbrs)
{
int i;
/* If the desired insertion position is beyond one passed the last */
/* neighbor in the lists OR greater than equal to the maximum ... */
/* NOTE: pos is zero-oriented while nnbrs and max_nbrs are 1-oriented. */
if((pos > *nnbrs) ||
(pos >= max_nbrs)){
fprintf(stderr,
"ERROR : insert_neighbor : insertion point exceeds lists\n");
return(-480);
}
/* If the neighbor lists are NOT full ... */
if(*nnbrs < max_nbrs){
/* Then we have room to shift everything down to make room for new */
/* neighbor and increase the number of neighbors stored by 1. */
i = *nnbrs-1;
(*nnbrs)++;
}
/* Otherwise, the neighbors lists are full ... */
else if(*nnbrs == max_nbrs)
/* So, we must bump the last neighbor in the lists off to make */
/* room for the new neighbor (ignore last neighbor in lists). */
i = *nnbrs-2;
/* Otherwise, there is a list overflow error condition */
/* (shouldn't ever happen, but just in case) ... */
else{
fprintf(stderr,
"ERROR : insert_neighbor : overflow in neighbor lists\n");
return(-481);
}
/* While we havn't reached the desired insertion point ... */
while(i >= pos){
/* Shift the current neighbor down the list 1 positon. */
nbr_list[i+1] = nbr_list[i];
nbr_sqr_dists[i+1] = nbr_sqr_dists[i];
i--;
}
/* We are now ready to put our new neighbor in the position where */
/* we shifted everything down from to make room. */
nbr_list[pos] = nbr_index;
nbr_sqr_dists[pos] = nbr_dist2;
/* Return normally. */
return(0);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: sort_neighbors - Takes a list of primary minutia and its neighboring #cat: sort_neighbors - Takes a list of primary minutia and its neighboring
@ -331,7 +485,7 @@ static int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs,
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int sort_neighbors(int *nbr_list, const int nnbrs, const int first, int sort_neighbors(int *nbr_list, const int nnbrs, const int first,
MINUTIAE *minutiae) MINUTIAE *minutiae)
{ {
double *join_thetas, theta; double *join_thetas, theta;
@ -372,6 +526,163 @@ static int sort_neighbors(int *nbr_list, const int nnbrs, const int first,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: ridge_count - Takes a pair of minutiae, and counts the number of
#cat: ridges crossed along the linear trajectory connecting
#cat: the 2 points in the image.
Input:
first - index of primary minutia
second - index of secondary (neighbor) minutia
minutiae - list of minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
lfsparms - parameters and thresholds for controlling LFS
Return Code:
Zero or Positive - number of ridges counted
Negative - system error
**************************************************************************/
int ridge_count(const int first, const int second, MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms)
{
MINUTIA *minutia1, *minutia2;
int i, ret, found;
int *xlist, *ylist, num;
int ridge_count, ridge_start, ridge_end;
int prevpix, curpix;
minutia1 = minutiae->list[first];
minutia2 = minutiae->list[second];
/* If the 2 mintuia have identical pixel coords ... */
if((minutia1->x == minutia2->x) &&
(minutia1->y == minutia2->y))
/* Then zero ridges between points. */
return(0);
/* Compute linear trajectory of contiguous pixels between first */
/* and second minutia points. */
if((ret = line_points(&xlist, &ylist, &num,
minutia1->x, minutia1->y, minutia2->x, minutia2->y))){
return(ret);
}
/* It there are no points on the line trajectory, then no ridges */
/* to count (this should not happen, but just in case) ... */
if(num == 0){
free(xlist);
free(ylist);
return(0);
}
/* Find first pixel opposite type along linear trajectory from */
/* first minutia. */
prevpix = *(bdata+(ylist[0]*iw)+xlist[0]);
i = 1;
found = FALSE;
while(i < num){
curpix = *(bdata+(ylist[i]*iw)+xlist[i]);
if(curpix != prevpix){
found = TRUE;
break;
}
i++;
}
/* If opposite pixel not found ... then no ridges to count */
if(!found){
free(xlist);
free(ylist);
return(0);
}
/* Ready to count ridges, so initialize counter to 0. */
ridge_count = 0;
print2log("RIDGE COUNT: %d,%d to %d,%d ", minutia1->x, minutia1->y,
minutia2->x, minutia2->y);
/* While not at the end of the trajectory ... */
while(i < num){
/* If 0-to-1 transition not found ... */
if(!find_transition(&i, 0, 1, xlist, ylist, num, bdata, iw, ih)){
/* Then we are done looking for ridges. */
free(xlist);
free(ylist);
print2log("\n");
/* Return number of ridges counted to this point. */
return(ridge_count);
}
/* Otherwise, we found a new ridge start transition, so store */
/* its location (the location of the 1 in 0-to-1 transition). */
ridge_start = i;
print2log(": RS %d,%d ", xlist[i], ylist[i]);
/* If 1-to-0 transition not found ... */
if(!find_transition(&i, 1, 0, xlist, ylist, num, bdata, iw, ih)){
/* Then we are done looking for ridges. */
free(xlist);
free(ylist);
print2log("\n");
/* Return number of ridges counted to this point. */
return(ridge_count);
}
/* Otherwise, we found a new ridge end transition, so store */
/* its location (the location of the 0 in 1-to-0 transition). */
ridge_end = i;
print2log("; RE %d,%d ", xlist[i], ylist[i]);
/* Conduct the validation, tracing the contour of the ridge */
/* from the ridge ending point a specified number of steps */
/* scanning for neighbors clockwise and counter-clockwise. */
/* If the ridge starting point is encounted during the trace */
/* then we can assume we do not have a valid ridge crossing */
/* and instead we are walking on and off the edge of the */
/* side of a ridge. */
ret = validate_ridge_crossing(ridge_start, ridge_end,
xlist, ylist, num, bdata, iw, ih,
lfsparms->max_ridge_steps);
/* If system error ... */
if(ret < 0){
free(xlist);
free(ylist);
/* Return the error code. */
return(ret);
}
print2log("; V%d ", ret);
/* If validation result is TRUE ... */
if(ret){
/* Then assume we have found a valid ridge crossing and bump */
/* the ridge counter. */
ridge_count++;
}
/* Otherwise, ignore the current ridge start and end transitions */
/* and go back and search for new ridge start. */
}
/* Deallocate working memories. */
free(xlist);
free(ylist);
print2log("\n");
/* Return the number of ridges counted. */
return(ridge_count);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: find_transition - Takes a pixel trajectory and a starting index, and #cat: find_transition - Takes a pixel trajectory and a starting index, and
@ -395,7 +706,7 @@ static int sort_neighbors(int *nbr_list, const int nnbrs, const int first,
TRUE - pixel pair transition found TRUE - pixel pair transition found
FALSE - pixel pair transition not found FALSE - pixel pair transition not found
**************************************************************************/ **************************************************************************/
static int find_transition(int *iptr, const int pix1, const int pix2, int find_transition(int *iptr, const int pix1, const int pix2,
const int *xlist, const int *ylist, const int num, const int *xlist, const int *ylist, const int num,
unsigned char *bdata, const int iw, const int ih) unsigned char *bdata, const int iw, const int ih)
{ {
@ -456,7 +767,7 @@ static int find_transition(int *iptr, const int pix1, const int pix2,
FALSE - ridge corssing INVALID FALSE - ridge corssing INVALID
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
static int validate_ridge_crossing(const int ridge_start, const int ridge_end, int validate_ridge_crossing(const int ridge_start, const int ridge_end,
const int *xlist, const int *ylist, const int num, const int *xlist, const int *ylist, const int num,
unsigned char *bdata, const int iw, const int ih, unsigned char *bdata, const int iw, const int ih,
const int max_ridge_steps) const int max_ridge_steps)
@ -539,294 +850,3 @@ static int validate_ridge_crossing(const int ridge_start, const int ridge_end,
/* If we get here, then we failed to validate a ridge crossing. */ /* If we get here, then we failed to validate a ridge crossing. */
return(FALSE); return(FALSE);
} }
/*************************************************************************
**************************************************************************
#cat: ridge_count - Takes a pair of minutiae, and counts the number of
#cat: ridges crossed along the linear trajectory connecting
#cat: the 2 points in the image.
Input:
first - index of primary minutia
second - index of secondary (neighbor) minutia
minutiae - list of minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
lfsparms - parameters and thresholds for controlling LFS
Return Code:
Zero or Positive - number of ridges counted
Negative - system error
**************************************************************************/
static int ridge_count(const int first, const int second, MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms)
{
MINUTIA *minutia1, *minutia2;
int i, ret, found;
int *xlist, *ylist, num;
int ridge_cnt, ridge_start, ridge_end;
int prevpix, curpix;
minutia1 = minutiae->list[first];
minutia2 = minutiae->list[second];
/* If the 2 mintuia have identical pixel coords ... */
if((minutia1->x == minutia2->x) &&
(minutia1->y == minutia2->y))
/* Then zero ridges between points. */
return(0);
/* Compute linear trajectory of contiguous pixels between first */
/* and second minutia points. */
if((ret = line_points(&xlist, &ylist, &num,
minutia1->x, minutia1->y, minutia2->x, minutia2->y))){
return(ret);
}
/* It there are no points on the line trajectory, then no ridges */
/* to count (this should not happen, but just in case) ... */
if(num == 0){
free(xlist);
free(ylist);
return(0);
}
/* Find first pixel opposite type along linear trajectory from */
/* first minutia. */
prevpix = *(bdata+(ylist[0]*iw)+xlist[0]);
i = 1;
found = FALSE;
while(i < num){
curpix = *(bdata+(ylist[i]*iw)+xlist[i]);
if(curpix != prevpix){
found = TRUE;
break;
}
i++;
}
/* If opposite pixel not found ... then no ridges to count */
if(!found){
free(xlist);
free(ylist);
return(0);
}
/* Ready to count ridges, so initialize counter to 0. */
ridge_cnt = 0;
print2log("RIDGE COUNT: %d,%d to %d,%d ", minutia1->x, minutia1->y,
minutia2->x, minutia2->y);
/* While not at the end of the trajectory ... */
while(i < num){
/* If 0-to-1 transition not found ... */
if(!find_transition(&i, 0, 1, xlist, ylist, num, bdata, iw, ih)){
/* Then we are done looking for ridges. */
free(xlist);
free(ylist);
print2log("\n");
/* Return number of ridges counted to this point. */
return(ridge_cnt);
}
/* Otherwise, we found a new ridge start transition, so store */
/* its location (the location of the 1 in 0-to-1 transition). */
ridge_start = i;
print2log(": RS %d,%d ", xlist[i], ylist[i]);
/* If 1-to-0 transition not found ... */
if(!find_transition(&i, 1, 0, xlist, ylist, num, bdata, iw, ih)){
/* Then we are done looking for ridges. */
free(xlist);
free(ylist);
print2log("\n");
/* Return number of ridges counted to this point. */
return(ridge_cnt);
}
/* Otherwise, we found a new ridge end transition, so store */
/* its location (the location of the 0 in 1-to-0 transition). */
ridge_end = i;
print2log("; RE %d,%d ", xlist[i], ylist[i]);
/* Conduct the validation, tracing the contour of the ridge */
/* from the ridge ending point a specified number of steps */
/* scanning for neighbors clockwise and counter-clockwise. */
/* If the ridge starting point is encounted during the trace */
/* then we can assume we do not have a valid ridge crossing */
/* and instead we are walking on and off the edge of the */
/* side of a ridge. */
ret = validate_ridge_crossing(ridge_start, ridge_end,
xlist, ylist, num, bdata, iw, ih,
lfsparms->max_ridge_steps);
/* If system error ... */
if(ret < 0){
free(xlist);
free(ylist);
/* Return the error code. */
return(ret);
}
print2log("; V%d ", ret);
/* If validation result is TRUE ... */
if(ret){
/* Then assume we have found a valid ridge crossing and bump */
/* the ridge counter. */
ridge_cnt++;
}
/* Otherwise, ignore the current ridge start and end transitions */
/* and go back and search for new ridge start. */
}
/* Deallocate working memories. */
free(xlist);
free(ylist);
print2log("\n");
/* Return the number of ridges counted. */
return(ridge_cnt);
}
/*************************************************************************
**************************************************************************
#cat: count_minutia_ridges - Takes a minutia, and determines its closest
#cat: neighbors and counts the number of interveining ridges
#cat: between the minutia point and each of its neighbors.
Input:
minutia - input minutia
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - minutia augmented with neighbors and ridge counts
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
static int count_minutia_ridges(const int first, MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms)
{
int i, ret, *nbr_list = NULL, *nbr_nridges, nnbrs;
/* Find up to the maximum number of qualifying neighbors. */
if((ret = find_neighbors(&nbr_list, &nnbrs, lfsparms->max_nbrs,
first, minutiae))){
free(nbr_list);
return(ret);
}
print2log("NBRS FOUND: %d,%d = %d\n", minutiae->list[first]->x,
minutiae->list[first]->y, nnbrs);
/* If no neighors found ... */
if(nnbrs == 0){
/* Then no list returned and no ridges to count. */
return(0);
}
/* Sort neighbors on delta dirs. */
if((ret = sort_neighbors(nbr_list, nnbrs, first, minutiae))){
free(nbr_list);
return(ret);
}
/* Count ridges between first and neighbors. */
/* List of ridge counts, one for each neighbor stored. */
nbr_nridges = (int *)malloc(nnbrs * sizeof(int));
if(nbr_nridges == (int *)NULL){
free(nbr_list);
fprintf(stderr, "ERROR : count_minutia_ridges : malloc : nbr_nridges\n");
return(-450);
}
/* Foreach neighbor found and sorted in list ... */
for(i = 0; i < nnbrs; i++){
/* Count the ridges between the primary minutia and the neighbor. */
ret = ridge_count(first, nbr_list[i], minutiae, bdata, iw, ih, lfsparms);
/* If system error ... */
if(ret < 0){
/* Deallocate working memories. */
free(nbr_list);
free(nbr_nridges);
/* Return error code. */
return(ret);
}
/* Otherwise, ridge count successful, so store ridge count to list. */
nbr_nridges[i] = ret;
}
/* Assign neighbor indices and ridge counts to primary minutia. */
minutiae->list[first]->nbrs = nbr_list;
minutiae->list[first]->ridge_counts = nbr_nridges;
minutiae->list[first]->num_nbrs = nnbrs;
/* Return normally. */
return(0);
}
/*************************************************************************
**************************************************************************
#cat: count_minutiae_ridges - Takes a list of minutiae, and for each one,
#cat: determines its closest neighbors and counts the number
#cat: of interveining ridges between the minutia point and
#cat: each of its neighbors.
Input:
minutiae - list of minutiae
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
lfsparms - parameters and thresholds for controlling LFS
Output:
minutiae - list of minutiae augmented with neighbors and ridge counts
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
int count_minutiae_ridges(MINUTIAE *minutiae,
unsigned char *bdata, const int iw, const int ih,
const LFSPARMS *lfsparms)
{
int ret;
int i;
print2log("\nFINDING NBRS AND COUNTING RIDGES:\n");
/* Sort minutia points on x then y (column-oriented). */
if((ret = sort_minutiae_x_y(minutiae, iw, ih))){
return(ret);
}
/* Remove any duplicate minutia points from the list. */
if((ret = rm_dup_minutiae(minutiae))){
return(ret);
}
/* Foreach remaining sorted minutia in list ... */
for(i = 0; i < minutiae->num-1; i++){
/* Located neighbors and count number of ridges in between. */
/* NOTE: neighbor and ridge count results are stored in */
/* minutiae->list[i]. */
if((ret = count_minutia_ridges(i, minutiae, bdata, iw, ih, lfsparms))){
return(ret);
}
}
/* Return normally. */
return(0);
}

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -36,12 +57,12 @@ identified are necessarily the best available for the purpose.
ROUTINES: ROUTINES:
alloc_shape() alloc_shape()
free_shape() free_shape()
dump_shape()
shape_from_contour() shape_from_contour()
sort_row_on_x() sort_row_on_x()
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/************************************************************************* /*************************************************************************
@ -60,7 +81,7 @@ identified are necessarily the best available for the purpose.
Zero - Shape successfully allocated and initialized Zero - Shape successfully allocated and initialized
Negative - System error Negative - System error
**************************************************************************/ **************************************************************************/
static int alloc_shape(SHAPE **oshape, const int xmin, const int ymin, int alloc_shape(SHAPE **oshape, const int xmin, const int ymin,
const int xmax, const int ymax) const int xmax, const int ymax)
{ {
SHAPE *shape; SHAPE *shape;
@ -180,21 +201,14 @@ void free_shape(SHAPE *shape)
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
#cat: sort_row_on_x - Takes a row structure and sorts its points left-to- #cat: dump_shape - Takes an initialized shape structure and dumps its contents
#cat: right on X. #cat: as formatted text to the specified open file pointer.
Input: Input:
row - row structure to be sorted shape - shape structure to be dumped
Output: Output:
row - row structure with points in sorted order fpout - open file pointer to be written to
**************************************************************************/ **************************************************************************/
static void sort_row_on_x(ROW *row)
{
/* Conduct a simple increasing bubble sort on the x-coords */
/* in the given row. A bubble sort is satisfactory as the */
/* number of points will be relatively small. */
bubble_sort_int_inc(row->xs, row->npts);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************
@ -270,3 +284,21 @@ int shape_from_contour(SHAPE **oshape, const int *contour_x,
return(0); return(0);
} }
/*************************************************************************
**************************************************************************
#cat: sort_row_on_x - Takes a row structure and sorts its points left-to-
#cat: right on X.
Input:
row - row structure to be sorted
Output:
row - row structure with points in sorted order
**************************************************************************/
void sort_row_on_x(ROW *row)
{
/* Conduct a simple increasing bubble sort on the x-coords */
/* in the given row. A bubble sort is satisfactory as the */
/* number of points will be relatively small. */
bubble_sort_int_inc(row->xs, row->npts);
}

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -43,7 +64,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/************************************************************************* /*************************************************************************
@ -104,29 +124,6 @@ int sort_indices_int_inc(int **optr, int *ranks, const int num)
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
int sort_indices_double_inc(int **optr, double *ranks, const int num)
{
int *order;
int i;
/* Allocate list of sequential indices. */
order = (int *)malloc(num * sizeof(int));
if(order == (int *)NULL){
fprintf(stderr, "ERROR : sort_indices_double_inc : malloc : order\n");
return(-400);
}
/* Initialize list of sequential indices. */
for(i = 0; i < num; i++)
order[i] = i;
/* Sort the indicies into rank order. */
bubble_sort_double_inc_2(ranks, order, num);
/* Set output pointer to the resulting order of sorted indices. */
*optr = order;
/* Return normally. */
return(0);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************

View file

@ -1,26 +1,47 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic. This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer: Disclaimer:
This software was developed to promote biometric standards and biometric This software and/or related materials was developed to promote biometric
technology testing for the Federal Government in accordance with the USA standards and biometric technology testing for the Federal Government
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. in accordance with the USA PATRIOT Act and the Enhanced Border Security
Specific hardware and software products identified in this software were used and Visa Entry Reform Act. Specific hardware and software products identified
in order to perform the software development. In no case does such in this software were used in order to perform the software development.
identification imply recommendation or endorsement by the National Institute In no case does such identification imply recommendation or endorsement
of Standards and Technology, nor does it imply that the products and equipment by the National Institute of Standards and Technology, nor does it imply that
identified are necessarily the best available for the purpose. the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/ *******************************************************************************/
/*********************************************************************** /***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System LIBRARY: LFS - NIST Latent Fingerprint System
@ -47,7 +68,6 @@ identified are necessarily the best available for the purpose.
***********************************************************************/ ***********************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <lfs.h> #include <lfs.h>
/************************************************************************* /*************************************************************************
@ -427,27 +447,6 @@ int in_int_list(const int item, const int *list, const int len)
Zero - successful completion Zero - successful completion
Negative - system error Negative - system error
**************************************************************************/ **************************************************************************/
int remove_from_int_list(const int index, int *list, const int num)
{
int fr, to;
/* Make sure the requested index is within range. */
if((index < 0) && (index >= num)){
fprintf(stderr, "ERROR : remove_from_int_list : index out of range\n");
return(-370);
}
/* Slide the remaining list of integers up over top of the */
/* position of the integer being removed. */
for(to = index, fr = index+1; fr < num; to++, fr++)
list[to] = list[fr];
/* NOTE: Decrementing the number of integers remaining in the list is */
/* the responsibility of the caller! */
/* Return normally. */
return(0);
}
/************************************************************************* /*************************************************************************
************************************************************************** **************************************************************************

View file

@ -0,0 +1,136 @@
/*******************************************************************************
License:
This software and/or related materials 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.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials 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.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
FILE: XYTREPS.C
AUTHOR: Michael D. Garris
DATE: 09/16/2004
UPDATED: 01/11/2012
Contains routines useful in converting minutiae in LFS "native"
representation into other representations, such as
M1 (ANSI INCITS 378-2004) & NIST internal representations.
***********************************************************************
ROUTINES:
lfs2nist_minutia_XTY()
lfs2m1_minutia_XTY()
lfs2nist_format()
***********************************************************************/
#include <lfs.h>
#include <defs.h>
/*************************************************************************
**************************************************************************
#cat: lfs2nist_minutia_XYT - Converts XYT minutiae attributes in LFS native
#cat: representation to NIST internal representation
Input:
minutia - LFS minutia structure containing attributes to be converted
Output:
ox - NIST internal based x-pixel coordinate
oy - NIST internal based y-pixel coordinate
ot - NIST internal based minutia direction/orientation
**************************************************************************/
void lfs2nist_minutia_XYT(int *ox, int *oy, int *ot,
const MINUTIA *minutia, const int iw, const int ih)
{
int x, y, t;
float degrees_per_unit;
/* XYT's according to NIST internal rep: */
/* 1. pixel coordinates with origin bottom-left */
/* 2. orientation in degrees on range [0..360] */
/* with 0 pointing east and increasing counter */
/* clockwise (same as M1) */
/* 3. direction pointing out and away from the */
/* ridge ending or bifurcation valley */
/* (opposite direction from M1) */
x = minutia->x;
y = ih - minutia->y;
degrees_per_unit = 180 / (float)NUM_DIRECTIONS;
t = (270 - sround(minutia->direction * degrees_per_unit)) % 360;
if(t < 0){
t += 360;
}
*ox = x;
*oy = y;
*ot = t;
}
/*************************************************************************
**************************************************************************
#cat: lfs2m1_minutia_XYT - Converts XYT minutiae attributes in LFS native
#cat: representation to M1 (ANSI INCITS 378-2004) representation
Input:
minutia - LFS minutia structure containing attributes to be converted
Output:
ox - M1 based x-pixel coordinate
oy - M1 based y-pixel coordinate
ot - M1 based minutia direction/orientation
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: lfs2nist_format - Takes a minutiae data structure and converts
#cat: the XYT minutiae attributes in LFS native
#cat: representation to NIST internal representation
Input:
iminutiae - minutiae data structure
iw - width (in pixels) of the grayscale image
ih - height (in pixels) of the grayscale image
Output:
iminutiae - overwrite each minutia element in the minutiae data
sturcture convernt to nist internal minutiae format
**************************************************************************/

View file

@ -0,0 +1,82 @@
#!/bin/lua
function read_all(file)
local f = io.open(file, "r")
if not f then return nil end
local t = f:read("*all")
f:close()
return t
end
function write_all(file, content)
local f = io.open(file, "w")
f:write(content)
f:close()
end
-- From http://lua-users.org/wiki/SplitJoin
function split_lines(str)
local t = {}
local function helper(line)
table.insert(t, line)
return ""
end
helper((str:gsub("(.-)\r?\n", helper)))
return t
end
function remove_func_content(func, content)
local lines = split_lines(content)
local res = {}
local in_func = false
local num_braces = 0
local found_func = false
for k, v in ipairs(lines) do
if in_func == true then
local orig_braces = num_braces
local _, count = string.gsub(v, "{", "")
num_braces = num_braces + count
_, count = string.gsub(v, "}", "")
num_braces = num_braces - count
if orig_braces ~= 0 and num_braces == 0 then
print (func .. ' finished line '.. k)
in_func = false
end
elseif (v:match(' '..func..'%(%a+') or
v:match(' '..func..' %(%a+') or
v:match(' '..func..'%( %a+') or
v:match(' '..func..'%($')) and
not v:match('= '..func..'%(%a+') then
print (func .. ' started line ' .. k)
found_func = true
in_func = true
else
table.insert(res, v)
end
end
if not found_func then
return nil
end
return table.concat(res, '\n')
end
function remove_func_file(func, file)
content = read_all(file)
content = remove_func_content(func, content)
if not content then
error('Could not find function '..func..'() in '..file)
else
write_all(file, content)
end
end
local func
for k, v in ipairs(arg) do
if k == 1 then
func = v
else
remove_func_file(func, v)
end
end

View file

@ -0,0 +1,181 @@
#!/bin/sh -e
help()
{
echo "Usage:"
echo " `basename $0` [NBIS directory]"
exit
}
replace_global()
{
if [ ! -f "$2" ] ; then
FILES=`find -name *.[ch]`
else
FILES=$2
fi
sed -i "s/$1/g_$1/" $FILES
}
rename_variable()
{
if [ ! -f "$3" ] ; then
FILES=`find -name *.[ch]`
else
FILES=$3
fi
sed -i "s/$1/$2/" $FILES
}
remove_function()
{
if [ ! -f "$2" ] ; then
FILES=`find -name *.[ch]`
else
FILES=$2
fi
./remove-function.lua $1 $FILES
}
if [ $# -ne 1 ] ; then echo "*** Wrong number of arguments ***" ; help ; fi
if [ ! -d $1 ] ; then echo "*** $1 not a directory ***" ; help ; fi
DIR="$1"
if [ ! -d $DIR/bozorth3 ] ; then echo "*** $DIR not an NBIS source directory ***" ; help ; fi
if [ ! -d $DIR/mindtct ] ; then echo "*** $DIR not an NBIS source directory ***" ; help ; fi
# Update files
for i in bozorth3/*.c ; do
cp -a $DIR/bozorth3/src/lib/bozorth3/`basename $i` bozorth3/
chmod 0644 bozorth3/`basename $i`
done
for i in mindtct/*.c chaincod.c getmin.c link.c xytreps.c; do
cp -a $DIR/mindtct/src/lib/mindtct/`basename $i` mindtct/
chmod 0644 mindtct/`basename $i`
done
for i in include/*.h mytime.h ; do
FILE=`basename $i`
ORIG=`find $DIR -name $FILE | grep -v misc/ | grep -v exports/`
cp -a -f $ORIG include/
chmod 0644 include/$FILE
done
# Replace global variables
replace_global dft_coefs include/lfs.h
replace_global dft_coefs mindtct/globals.c
replace_global dft_coefs mindtct/maps.c
replace_global dft_coefs mindtct/detect.c
# Also does lfsparms_V2
replace_global lfsparms include/lfs.h
replace_global lfsparms mindtct/globals.c
replace_global nbr8_dx
replace_global nbr8_dy
replace_global chaincodes_nbr8
replace_global feature_patterns
rename_variable errorfp stderr
# Remove command-line options globals
for i in m1_xyt max_minutiae min_computable_minutiae verbose_bozorth verbose_main verbose_load; do
sed -i "/$i/d" include/bozorth.h
done
rename_variable max_minutiae DEFAULT_BOZORTH_MINUTIAE
rename_variable m1_xyt 0
rename_variable min_computable_minutiae MIN_COMPUTABLE_BOZORTH_MINUTIAE
rename_variable verbose_bozorth 0
rename_variable verbose_main 0
rename_variable verbose_load 0
# Remove logging globals
for i in logfp avrdir dir_strength nvalid ; do
sed -i "/$i/d" mindtct/log.c
sed -i "/$i/d" include/log.h
done
# Remove an unused static variable
sed -i "/stack_pointer = stack/d" bozorth3/bz_sort.c
sed -i "/stack\[BZ_STACKSIZE\]/d" bozorth3/bz_sort.c
# +extern int verbose_load;
# extern int verbose_threshold;
# +/* Global supporting error reporting */
# +extern FILE *stderr;
# Remove unused functions
patch -p0 < lfs.h.patch
remove_function binarize mindtct/binar.c
remove_function binarize_image mindtct/binar.c
remove_function isobinarize mindtct/binar.c
remove_function lfs_detect_minutiae mindtct/detect.c
remove_function bits_6to8 mindtct/imgutil.c
remove_function bozorth_main bozorth3/bz_drvrs.c
remove_function bz_load bozorth3/bz_io.c
remove_function bz_prune bozorth3/bz_io.c
remove_function get_next_file bozorth3/bz_io.c
remove_function get_score_filename bozorth3/bz_io.c
remove_function get_score_line bozorth3/bz_io.c
remove_function parse_line_range bozorth3/bz_io.c
remove_function set_gallery_filename bozorth3/bz_io.c
remove_function set_probe_filename bozorth3/bz_io.c
remove_function set_progname bozorth3/bz_io.c
remove_function detect_minutiae mindtct/minutia.c
remove_function dump_minutiae_pts mindtct/minutia.c
remove_function dump_minutiae mindtct/minutia.c
remove_function dump_reliable_minutiae_pts mindtct/minutia.c
remove_function scan4minutiae mindtct/minutia.c
remove_function scan4minutiae_horizontally mindtct/minutia.c
remove_function scan4minutiae_vertically mindtct/minutia.c
remove_function rescan4minutiae_horizontally mindtct/minutia.c
remove_function rescan4minutiae_vertically mindtct/minutia.c
remove_function process_horizontal_scan_minutia mindtct/minutia.c
remove_function process_vertical_scan_minutia mindtct/minutia.c
remove_function get_nbr_block_index mindtct/minutia.c
remove_function join_minutia mindtct/minutia.c
remove_function rescan_partial_horizontally mindtct/minutia.c
remove_function rescan_partial_vertically mindtct/minutia.c
remove_function adjust_high_curvature_minutia mindtct/minutia.c
remove_function adjust_horizontal_rescan mindtct/minutia.c
remove_function adjust_vertical_rescan mindtct/minutia.c
remove_function dump_shape mindtct/shape.c
remove_function flood_loop mindtct/loop.c
remove_function get_loop_list mindtct/loop.c
remove_function process_loop mindtct/loop.c
remove_function gen_imap mindtct/maps.c
remove_function gen_nmap mindtct/maps.c
remove_function gen_initial_imap mindtct/maps.c
remove_function smooth_imap mindtct/maps.c
remove_function get_max_padding mindtct/init.c
remove_function lfs2m1_minutia_XYT mindtct/xytreps.c
remove_function lfs2nist_format mindtct/xytreps.c
remove_function malloc_or_exit bozorth3/bz_alloc.c
remove_function malloc_or_return_error bozorth3/bz_alloc.c
remove_function reliability_fr_quality_map mindtct/quality.c
remove_function remove_false_minutia mindtct/remove.c
remove_function remove_pores mindtct/remove.c
remove_function remove_pointing_invblock mindtct/remove.c
remove_function remove_hooks_islands_lakes_overlaps mindtct/remove.c
remove_function remove_near_invblock mindtct/remove.c
remove_function remove_or_adjust_side_minutiae mindtct/remove.c
remove_function sort_quality_decreasing bozorth3/bz_sort.c
remove_function sort_order_decreasing bozorth3/bz_sort.c
remove_function qsort_decreasing bozorth3/bz_sort.c
remove_function partition_dec bozorth3/bz_sort.c
remove_function popstack bozorth3/bz_sort.c
remove_function pushstack bozorth3/bz_sort.c
remove_function select_pivot bozorth3/bz_sort.c
remove_function sort_indices_double_inc mindtct/sort.c
remove_function link_minutiae mindtct/link.c
remove_function create_link_table mindtct/link.c
remove_function order_link_table mindtct/link.c
remove_function process_link_table mindtct/link.c
remove_function update_link_table mindtct/link.c
remove_function link_score mindtct/link.c
remove_function remove_from_int_list mindtct/util.c
# Remove trailing spaces
sed -i 's/[ \t]*$//' `find -name "*.[ch]"`
# Remove usebsd.h
sed -i '/usebsd.h/d' `find -name "*.[ch]"`