From 9fb789dc787dbaa7caa0bc7dd2b9a1baa1f9a750 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 24 Aug 2018 19:48:53 +0200 Subject: [PATCH] nbis: Update to NBIS 5.0.0 This updates NBIS to its latest 5.0.0 version, dated 04/03/2015, from a 1.x version, dated 2007. Original sources are available at: https://www.nist.gov/itl/iad/image-group/products-and-services/image-group-open-source-server-nigos#Releases And full change log at: https://www.nist.gov/sites/default/files/documents/2016/12/14/changelog.txt --- libfprint/meson.build | 4 + libfprint/nbis/bozorth3/bozorth3.c | 114 +-- libfprint/nbis/bozorth3/bz_alloc.c | 119 +-- libfprint/nbis/bozorth3/bz_drvrs.c | 126 +-- libfprint/nbis/bozorth3/bz_gbls.c | 130 +-- libfprint/nbis/bozorth3/bz_io.c | 552 +---------- libfprint/nbis/bozorth3/bz_sort.c | 255 +---- libfprint/nbis/include/bozorth.h | 69 +- libfprint/nbis/include/bz_array.h | 54 +- libfprint/nbis/include/defs.h | 55 +- libfprint/nbis/include/lfs.h | 249 ++++- libfprint/nbis/include/log.h | 59 +- libfprint/nbis/include/morph.h | 55 +- libfprint/nbis/include/mytime.h | 106 ++ libfprint/nbis/include/sunrast.h | 55 +- libfprint/nbis/mindtct/binar.c | 135 ++- libfprint/nbis/mindtct/block.c | 60 +- libfprint/nbis/mindtct/chaincod.c | 211 ++++ libfprint/nbis/mindtct/contour.c | 516 +++++----- libfprint/nbis/mindtct/detect.c | 241 +++-- libfprint/nbis/mindtct/dft.c | 366 +++---- libfprint/nbis/mindtct/free.c | 56 +- libfprint/nbis/mindtct/getmin.c | 175 ++++ libfprint/nbis/mindtct/globals.c | 61 +- libfprint/nbis/mindtct/imgutil.c | 68 +- libfprint/nbis/mindtct/init.c | 84 +- libfprint/nbis/mindtct/line.c | 56 +- libfprint/nbis/mindtct/link.c | 254 +++++ libfprint/nbis/mindtct/log.c | 62 +- libfprint/nbis/mindtct/loop.c | 743 +++++--------- libfprint/nbis/mindtct/maps.c | 310 ++---- libfprint/nbis/mindtct/matchpat.c | 71 +- libfprint/nbis/mindtct/minutia.c | 1460 ++-------------------------- libfprint/nbis/mindtct/morph.c | 79 +- libfprint/nbis/mindtct/quality.c | 306 +++--- libfprint/nbis/mindtct/remove.c | 531 +++++----- libfprint/nbis/mindtct/ridges.c | 886 ++++++++--------- libfprint/nbis/mindtct/shape.c | 92 +- libfprint/nbis/mindtct/sort.c | 87 +- libfprint/nbis/mindtct/util.c | 81 +- libfprint/nbis/mindtct/xytreps.c | 136 +++ 41 files changed, 4165 insertions(+), 4964 deletions(-) create mode 100644 libfprint/nbis/include/mytime.h create mode 100644 libfprint/nbis/mindtct/chaincod.c create mode 100644 libfprint/nbis/mindtct/getmin.c create mode 100644 libfprint/nbis/mindtct/link.c create mode 100644 libfprint/nbis/mindtct/xytreps.c diff --git a/libfprint/meson.build b/libfprint/meson.build index 8689c9f..fea424f 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -30,14 +30,17 @@ nbis_sources = [ 'nbis/bozorth3/bz_sort.c', 'nbis/mindtct/binar.c', 'nbis/mindtct/block.c', + 'nbis/mindtct/chaincod.c', 'nbis/mindtct/contour.c', 'nbis/mindtct/detect.c', 'nbis/mindtct/dft.c', 'nbis/mindtct/free.c', + 'nbis/mindtct/getmin.c', 'nbis/mindtct/globals.c', 'nbis/mindtct/imgutil.c', 'nbis/mindtct/init.c', 'nbis/mindtct/line.c', + 'nbis/mindtct/link.c', 'nbis/mindtct/log.c', 'nbis/mindtct/loop.c', 'nbis/mindtct/maps.c', @@ -50,6 +53,7 @@ nbis_sources = [ 'nbis/mindtct/shape.c', 'nbis/mindtct/sort.c', 'nbis/mindtct/util.c', + 'nbis/mindtct/xytreps.c', ] aeslib = false diff --git a/libfprint/nbis/bozorth3/bozorth3.c b/libfprint/nbis/bozorth3/bozorth3.c index 54514e7..7724aea 100644 --- a/libfprint/nbis/bozorth3/bozorth3.c +++ b/libfprint/nbis/bozorth3/bozorth3.c @@ -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: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -89,9 +81,6 @@ identified are necessarily the best available for the purpose. #include #include -static const int verbose_bozorth = 0; -static const int m1_xyt = 0; - /***********************************************************************/ void bz_comp( int npoints, /* INPUT: # of points */ @@ -160,7 +149,7 @@ for ( k = 0; k < npoints - 1; k++ ) { else { double dz; - if ( m1_xyt ) + if ( 0 ) dz = ( 180.0F / PI_SINGLE ) * atanf( (float) -dy / (float) dx ); else 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 ) { #ifndef NOVERBOSE - if ( verbose_bozorth ) + if ( 0 ) printf( "bz_comp(): breaking loop to avoid table overflow\n" ); #endif goto COMP_END; @@ -392,7 +381,7 @@ static int * rtp[ ROT_SIZE_1 ]; /* extern int * scolpt[ SCOLPT_SIZE ]; INPUT */ /* extern int * fcolpt[ FCOLPT_SIZE ]; INPUT */ /* extern int colp[ COLP_SIZE_1 ][ COLP_SIZE_2 ]; OUTPUT */ -/* extern int verbose_bozorth; */ +/* extern int 0; */ /* extern FILE * stderr; */ /* extern char * get_progname( void ); */ /* extern char * get_probe_filename( void ); */ @@ -401,6 +390,7 @@ static int * rtp[ ROT_SIZE_1 ]; + st = 1; edge_pair_index = 0; rotptr = &rot[0][0]; @@ -570,7 +560,7 @@ for ( k = 1; k < probe_ptrlist_len; k++ ) { if ( edge_pair_index == 19999 ) { #ifndef NOVERBOSE - if ( verbose_bozorth ) + if ( 0 ) 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() ); #endif @@ -652,13 +642,13 @@ int avv[ AVV_SIZE_1 ][ AVV_SIZE_2 ]; if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { #ifndef NOVERBOSE 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", get_progname(), pstruct->nrows, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, get_probe_filename(), get_gallery_filename() ); } 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", get_progname(), pstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, @@ -672,7 +662,7 @@ if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { #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", get_progname(), gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, @@ -765,7 +755,7 @@ for ( k = 0; k < np - 1; k++ ) { } #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] ); #endif @@ -1167,7 +1157,7 @@ for ( k = 0; k < np - 1; k++ ) { if ( ll ) { - if ( m1_xyt ) + if ( 0 ) fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -jj / (float) ll ); else fi = ( 180.0F / PI_SINGLE ) * atanf( (float) jj / (float) ll ); @@ -1187,7 +1177,7 @@ for ( k = 0; k < np - 1; k++ ) { jj += 360; } else { - if ( m1_xyt ) { + if ( 0 ) { if ( jj > 0 ) jj = -90; else @@ -1204,7 +1194,7 @@ for ( k = 0; k < np - 1; k++ ) { if ( kk ) { - if ( m1_xyt ) + if ( 0 ) fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -j / (float) kk ); else fi = ( 180.0F / PI_SINGLE ) * atanf( (float) j / (float) kk ); @@ -1224,7 +1214,7 @@ for ( k = 0; k < np - 1; k++ ) { j += 360; } else { - if ( m1_xyt ) { + if ( 0 ) { if ( j > 0 ) j = -90; else @@ -1611,7 +1601,7 @@ if ( n ) { notfound = 1; #ifndef NOVERBOSE - if ( verbose_bozorth ) { + if ( 0 ) { int * llptr = lptr; printf( "bz_sift(): n: looking for l=%d in [", l ); for ( i = 0; i < lim; i++ ) { @@ -1657,7 +1647,7 @@ if ( t ) { notfound = 1; #ifndef NOVERBOSE - if ( verbose_bozorth ) { + if ( 0 ) { int * llptr = lptr; printf( "bz_sift(): t: looking for kz=%d in [", kz ); for ( i = 0; i < lim; i++ ) { diff --git a/libfprint/nbis/bozorth3/bz_alloc.c b/libfprint/nbis/bozorth3/bz_alloc.c index 5118282..e4ac991 100644 --- a/libfprint/nbis/bozorth3/bz_alloc.c +++ b/libfprint/nbis/bozorth3/bz_alloc.c @@ -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: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -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 */ -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; -} diff --git a/libfprint/nbis/bozorth3/bz_drvrs.c b/libfprint/nbis/bozorth3/bz_drvrs.c index 03f7171..8904f0f 100644 --- a/libfprint/nbis/bozorth3/bz_drvrs.c +++ b/libfprint/nbis/bozorth3/bz_drvrs.c @@ -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: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -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; -} diff --git a/libfprint/nbis/bozorth3/bz_gbls.c b/libfprint/nbis/bozorth3/bz_gbls.c index 0ecd081..dd828dc 100644 --- a/libfprint/nbis/bozorth3/bz_gbls.c +++ b/libfprint/nbis/bozorth3/bz_gbls.c @@ -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: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -91,23 +83,45 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ]; /**************************************************************************/ /* Globals used significantly by sift() */ /**************************************************************************/ -int rq[ RQ_SIZE ] = {}; -int tq[ TQ_SIZE ] = {}; -int zz[ ZZ_SIZE ] = {}; +#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 rx[ RX_SIZE ]; + int mm[ MM_SIZE ]; + int nn[ NN_SIZE ]; -int qq[ QQ_SIZE ] = {}; + int qq[ QQ_SIZE ]; -int rk[ RK_SIZE ] = {}; + int rk[ RK_SIZE ]; -int cp[ CP_SIZE ] = {}; -int rp[ RP_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 rf[RF_SIZE_1][RF_SIZE_2]; + int cf[CF_SIZE_1][CF_SIZE_2]; -int y[20000] = {}; + int y[20000]; +#else + 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] = {}; +#endif diff --git a/libfprint/nbis/bozorth3/bz_io.c b/libfprint/nbis/bozorth3/bz_io.c index e5dc3bb..5d2f863 100644 --- a/libfprint/nbis/bozorth3/bz_io.c +++ b/libfprint/nbis/bozorth3/bz_io.c @@ -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: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -57,6 +49,9 @@ identified are necessarily the best available for the purpose. MODIFICATIONS: Michael D. Garris (NIST) Stan Janet (NIST) 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 processing, file and data input to, and output from the @@ -100,50 +95,7 @@ identified are necessarily the best available for the purpose. #include #include -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; /***********************************************************************/ -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 ) @@ -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 */ -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]. 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 @@ -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; */ - - - -#define C1 0 -#define C2 1 - - - -fp = fopen( xyt_file, "r" ); -if ( fp == (FILE *) NULL ) { - fprintf( stderr, "%s: ERROR: fopen() of minutiae file \"%s\" failed: %s\n", - get_progname(), xyt_file, strerror(errno) ); - return XYT_NULL; -} - -nminutiae = 0; -nargs_expected = 0; -while ( fgets( xyt_line, sizeof xyt_line, fp ) != CNULL ) { - - m = sscanf( xyt_line, "%d %d %d %d", - &xvals_lng[nminutiae], - &yvals_lng[nminutiae], - &tvals_lng[nminutiae], - &qvals_lng[nminutiae] ); - if ( nminutiae == 0 ) { - if ( m != 3 && m != 4 ) { - fprintf( stderr, "%s: ERROR: sscanf() failed on line %u in minutiae file \"%s\"\n", - get_progname(), nminutiae+1, xyt_file ); - return XYT_NULL; - } - nargs_expected = m; - } else { - if ( m != nargs_expected ) { - fprintf( stderr, "%s: ERROR: inconsistent argument count on line %u of minutiae file \"%s\"\n", - get_progname(), nminutiae+1, xyt_file ); - return XYT_NULL; - } - } - if ( m == 3 ) - qvals_lng[nminutiae] = 1; - - - - if ( tvals_lng[nminutiae] > 180 ) - tvals_lng[nminutiae] -= 360; - - /* - if ( C1 ) { - c[nminutiae].col[0] = xvals_lng[nminutiae]; - c[nminutiae].col[1] = yvals_lng[nminutiae]; - c[nminutiae].col[2] = tvals_lng[nminutiae]; - c[nminutiae].col[3] = qvals_lng[nminutiae]; - } - */ - - ++nminutiae; - if ( nminutiae == MAX_FILE_MINUTIAE ) - break; -} - -if ( fclose(fp) != 0 ) { - fprintf( stderr, "%s: ERROR: fclose() of minutiae file \"%s\" failed: %s\n", - get_progname(), xyt_file, strerror(errno) ); - return XYT_NULL; -} - - - - -if ( nminutiae > DEFAULT_BOZORTH_MINUTIAE ) { - if ( verbose_load ) - fprintf( stderr, "%s: WARNING: bz_load(): trimming minutiae to the %d of highest quality\n", - get_progname(), DEFAULT_BOZORTH_MINUTIAE ); - - if ( verbose_load ) - fprintf( stderr, "Before quality sort:\n" ); - if ( sort_order_decreasing( qvals_lng, nminutiae, order )) { - fprintf( stderr, "%s: ERROR: sort failed and returned on error\n", get_progname()); - return XYT_NULL; - } - - for ( j = 0; j < nminutiae; j++ ) { - - if ( verbose_load ) - fprintf( stderr, " %3d: %3d %3d %3d ---> order = %3d\n", - j, xvals_lng[j], yvals_lng[j], qvals_lng[j], order[j] ); - - if ( j == 0 ) - continue; - if ( qvals_lng[order[j]] > qvals_lng[order[j-1]] ) { - fprintf( stderr, "%s: ERROR: sort failed: j=%d; qvals_lng[%d] > qvals_lng[%d]\n", - get_progname(), j, order[j], order[j-1] ); - return XYT_NULL; - } - } - - - if ( verbose_load ) - fprintf( stderr, "\nAfter quality sort:\n" ); - for ( j = 0; j < DEFAULT_BOZORTH_MINUTIAE; j++ ) { - xvals[j] = xvals_lng[order[j]]; - yvals[j] = yvals_lng[order[j]]; - tvals[j] = tvals_lng[order[j]]; - qvals[j] = qvals_lng[order[j]]; - if ( verbose_load ) - fprintf( stderr, " %3d: %3d %3d %3d\n", j, xvals[j], yvals[j], qvals[j] ); - } - - - if ( C1 ) { - if ( verbose_load ) - fprintf( stderr, "\nAfter qsort():\n" ); - qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_quality_decreasing ); - for ( j = 0; j < nminutiae; j++ ) { - - if ( verbose_load ) - fprintf( stderr, "Q %3d: %3d %3d %3d\n", - j, c[j].col[0], c[j].col[1], c[j].col[3] ); - - if ( j > 0 && c[j].col[3] > c[j-1].col[3] ) { - fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[3] > c[%d].col[3]\n", - get_progname(), j, j-1 ); - return XYT_NULL; - } - } - } - - if ( verbose_load ) - fprintf( stderr, "\n" ); - - xptr = xvals; - yptr = yvals; - tptr = tvals; - qptr = qvals; - - nminutiae = DEFAULT_BOZORTH_MINUTIAE; -} else{ - xptr = xvals_lng; - yptr = yvals_lng; - tptr = tvals_lng; - qptr = qvals_lng; -} - - - -for ( j=0; j < nminutiae; j++ ) { - c[j].col[0] = xptr[j]; - c[j].col[1] = yptr[j]; - c[j].col[2] = tptr[j]; - c[j].col[3] = qptr[j]; -} -qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_x_y ); - - - - -if ( verbose_load ) { - fprintf( stderr, "\nSorted on increasing x, then increasing y\n" ); - for ( j = 0; j < nminutiae; j++ ) { - fprintf( stderr, "%d : %3d, %3d, %3d, %3d\n", j, c[j].col[0], c[j].col[1], c[j].col[2], c[j].col[3] ); - if ( j > 0 ) { - if ( c[j].col[0] < c[j-1].col[0] ) { - fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d > c[%d].col[0]=%d\n", - get_progname(), - j, c[j].col[0], j-1, c[j-1].col[0] - ); - return XYT_NULL; - } - if ( c[j].col[0] == c[j-1].col[0] && c[j].col[1] < c[j-1].col[1] ) { - fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d == c[%d].col[0]=%d; c[%d].col[0]=%d == c[%d].col[0]=%d\n", - get_progname(), - j, c[j].col[0], j-1, c[j-1].col[0], - j, c[j].col[1], j-1, c[j-1].col[1] - ); - return XYT_NULL; - } - } - } -} - - - -s = (struct xyt_struct *) malloc( sizeof( struct xyt_struct ) ); -if ( s == XYT_NULL ) { - fprintf( stderr, "%s: ERROR: malloc() failure while loading minutiae file \"%s\" failed: %s\n", - get_progname(), - xyt_file, - strerror(errno) - ); - return XYT_NULL; -} - - - -for ( j = 0; j < nminutiae; j++ ) { - s->xcol[j] = c[j].col[0]; - s->ycol[j] = c[j].col[1]; - s->thetacol[j] = c[j].col[2]; -} -s->nrows = nminutiae; - - - - -if ( verbose_load ) - fprintf( stderr, "Loaded %s\n", xyt_file ); - -return s; -} +/************************************************************************ +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 +to be returned, the highest-quality minutiae are returned. +*************************************************************************/ /***********************************************************************/ #ifdef PARALLEL_SEARCH @@ -617,13 +171,13 @@ tv.tv_usec = 0; retval = select( fd+1, &rfds, NULL, NULL, &tv ); if ( retval < 0 ) { - perror( "select() failed" ); - return 0; + perror( "select() failed" ); + return 0; } if ( FD_ISSET( fd, &rfds ) ) { - /*fprintf( stderr, "data is available now.\n" );*/ - return 1; + /*fprintf( stderr, "data is available now.\n" );*/ + return 1; } /* fprintf( stderr, "no data is available\n" ); */ diff --git a/libfprint/nbis/bozorth3/bz_sort.c b/libfprint/nbis/bozorth3/bz_sort.c index 01371e5..b51a82e 100644 --- a/libfprint/nbis/bozorth3/bz_sort.c +++ b/libfprint/nbis/bozorth3/bz_sort.c @@ -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: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -78,23 +70,10 @@ identified are necessarily the best available for the purpose. #include /* These are now externally defined in bozorth.h */ +/* extern FILE * stderr; */ /* 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 ) @@ -124,67 +103,18 @@ qsort_decreasing() - quicksort an array of integers in decreasing and Ted Zwiesler, 1986] ********************************************************/ /* Used by custom quicksort code below */ -static int stack[BZ_STACKSIZE]; -static int * stack_pointer = stack; /***********************************************************************/ /* return values: 0 == successful, 1 == error */ -static int popstack( int *popval ) -{ -if ( --stack_pointer < stack ) { - fprintf( stderr, "%s: ERROR: popstack(): stack underflow\n", get_progname() ); - return 1; -} - -*popval = *stack_pointer; -return 0; -} /***********************************************************************/ /* return values: 0 == successful, 1 == error */ -static int pushstack( int position ) -{ -*stack_pointer++ = position; -if ( stack_pointer > ( stack + BZ_STACKSIZE ) ) { - fprintf( stderr, "%s: ERROR: pushstack(): stack overflow\n", get_progname() ); - return 1; -} -return 0; -} /***********************************************************************/ /******************************************************************* select_pivot() selects a pivot from a list being sorted using the Singleton Method. *******************************************************************/ -static int select_pivot( struct cell v[], int left, int right ) -{ -int midpoint; - - -midpoint = ( left + right ) / 2; -if ( v[left].index <= v[midpoint].index ) { - if ( v[midpoint].index <= v[right].index ) { - return midpoint; - } else { - if ( v[right].index > v[left].index ) { - return right; - } else { - return left; - } - } -} else { - if ( v[left].index < v[right].index ) { - return left; - } else { - if ( v[right].index < v[midpoint].index ) { - return midpoint; - } else { - return right; - } - } -} -} /***********************************************************************/ /******************************************************** @@ -192,41 +122,6 @@ partition_dec() Inputs a pivot element making comparisons and swaps with other elements in a list, until pivot resides at its correct position in the list. ********************************************************/ -static void partition_dec( struct cell v[], int *llen, int *rlen, int *ll, int *lr, int *rl, int *rr, int p, int l, int r ) -{ -#define iswap(a,b) { int itmp = (a); a = (b); b = itmp; } - -*ll = l; -*rr = r; -while ( 1 ) { - if ( l < p ) { - if ( v[l].index < v[p].index ) { - iswap( v[l].index, v[p].index ) - iswap( v[l].item, v[p].item ) - p = l; - } else { - l++; - } - } else { - if ( r > p ) { - if ( v[r].index > v[p].index ) { - iswap( v[r].index, v[p].index ) - iswap( v[r].item, v[p].item ) - p = r; - l++; - } else { - r--; - } - } else { - *lr = p - 1; - *rl = p + 1; - *llen = *lr - *ll + 1; - *rlen = *rr - *rl + 1; - break; - } - } -} -} /***********************************************************************/ /******************************************************** @@ -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. ********************************************************/ /* return values: 0 == successful, 1 == error */ -static int qsort_decreasing( struct cell v[], int left, int right ) -{ -int pivot; -int llen, rlen; -int lleft, lright, rleft, rright; - - -if ( pushstack( left )) - return 1; -if ( pushstack( right )) - return 2; -while ( stack_pointer != stack ) { - if (popstack(&right)) - return 3; - if (popstack(&left )) - return 4; - if ( right - left > 0 ) { - pivot = select_pivot( v, left, right ); - partition_dec( v, &llen, &rlen, &lleft, &lright, &rleft, &rright, pivot, left, right ); - if ( llen > rlen ) { - if ( pushstack( lleft )) - return 5; - if ( pushstack( lright )) - return 6; - if ( pushstack( rleft )) - return 7; - if ( pushstack( rright )) - return 8; - } else{ - if ( pushstack( rleft )) - return 9; - if ( pushstack( rright )) - return 10; - if ( pushstack( lleft )) - return 11; - if ( pushstack( lright )) - return 12; - } - } -} -return 0; -} /***********************************************************************/ /* return values: 0 == successful, 1 == error */ -int sort_order_decreasing( - int values[], /* INPUT: the unsorted values themselves */ - int num, /* INPUT: the number of values */ - int order[] /* OUTPUT: the order for each of the values if sorted */ - ) -{ -int i; -struct cell * cells; - - -cells = (struct cell *) malloc( num * sizeof(struct cell) ); -if ( cells == (struct cell *) NULL ){ - fprintf( stderr, "%s: ERROR: malloc(): struct cell\n", get_progname() ); - return 1; -} - -for( i = 0; i < num; i++ ) { - cells[i].index = values[i]; - cells[i].item = i; -} - -if ( qsort_decreasing( cells, 0, num-1 ) < 0) - return 2; - -for( i = 0; i < num; i++ ) { - order[i] = cells[i].item; -} - -free( (void *) cells ); - -return 0; -} diff --git a/libfprint/nbis/include/bozorth.h b/libfprint/nbis/include/bozorth.h index dbac409..08ec4b1 100644 --- a/libfprint/nbis/include/bozorth.h +++ b/libfprint/nbis/include/bozorth.h @@ -1,23 +1,43 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -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() */ @@ -174,7 +194,17 @@ struct xyt_struct { 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 XYTQ_NULL ( (struct xytq_struct *) NULL ) /* bz_load() */ /**************************************************************************/ @@ -187,6 +217,8 @@ struct xyt_struct { /**************************************************************************/ /* Globals supporting command line options */ extern int verbose_threshold; +/* Global supporting error reporting */ +extern FILE *stderr; /**************************************************************************/ /* 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_line(const char *, const char *, int, int, 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); /* In: BZ_SORT.C */ extern int sort_quality_decreasing(const void *, const void *); diff --git a/libfprint/nbis/include/bz_array.h b/libfprint/nbis/include/bz_array.h index 19b7da0..296f674 100644 --- a/libfprint/nbis/include/bz_array.h +++ b/libfprint/nbis/include/bz_array.h @@ -1,23 +1,43 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ diff --git a/libfprint/nbis/include/defs.h b/libfprint/nbis/include/defs.h index 1e982d0..f2953d3 100644 --- a/libfprint/nbis/include/defs.h +++ b/libfprint/nbis/include/defs.h @@ -1,23 +1,43 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -53,7 +73,6 @@ identified are necessarily the best available for the purpose. #define min(a, b) ((a) < (b) ? (a) : (b)) #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 xor(a, b) (!(a && b) && (a || b)) #define align_to_16(_v_) ((((_v_)+15)>>4)<<4) #define align_to_32(_v_) ((((_v_)+31)>>5)<<5) #ifndef CHUNKS diff --git a/libfprint/nbis/include/lfs.h b/libfprint/nbis/include/lfs.h index 9ff01b2..ae7aee5 100644 --- a/libfprint/nbis/include/lfs.h +++ b/libfprint/nbis/include/lfs.h @@ -1,23 +1,43 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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. *******************************************************************************/ @@ -33,6 +53,9 @@ identified are necessarily the best available for the purpose. Comments added to guide changes to blocksize or number of detected directions. 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 @@ -160,7 +183,7 @@ typedef struct shape{ /* Parameters used by LFS for setting thresholds and */ /* defining testing criterion. */ -typedef struct lfsparms{ +typedef struct g_lfsparms{ /* Image Controls */ int pad_value; int join_line_radius; @@ -236,8 +259,6 @@ typedef struct lfsparms{ int pores_steps_bwd; double pores_min_dist2; double pores_max_ratio; - int remove_perimeter_pts; - int min_pp_distance; /* Ridge Counting Controls */ int max_nbrs; @@ -382,7 +403,7 @@ typedef struct lfsparms{ /* Thresholds and factors used by HO39. Renamed */ /* here to give more meaning. */ /* HO39 Name=Value */ -/* Minimum DFT power allowable in any one direction. */ +/* Minimum DFT power allowable in any one direction. */ #define POWMAX_MIN 100000.0 /* thrhf=1e5f */ /* Minimum normalized power allowable in any one */ @@ -587,9 +608,6 @@ typedef struct lfsparms{ /* contour points to be considered a pore. */ #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 *****/ @@ -689,15 +707,24 @@ typedef struct lfsparms{ /*************************************************************************/ /* 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 *, unsigned char *, const int, const int, int *, const int, const int, 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 *, unsigned char *, const int, const int, const int *, const int, const int, 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 */ 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); 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 */ -int allocate_contour(int **ocontour_x, int **ocontour_y, - int **ocontour_ex, int **ocontour_ey, const int ncontour); +extern int allocate_contour(int **, int **, int **, int **, const int); extern void free_contour(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, @@ -726,6 +756,11 @@ extern int trace_contour(int **, int **, int **, int **, int *, extern int search_contour(const int, const int, const int, const int, const int, const int, 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 *, const 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); /* detect.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 *); +extern int lfs_detect_minutiae( MINUTIAE **, + int **, int **, int *, int *, + unsigned char **, int *, int *, + unsigned char *, const int, const int, + 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 */ extern int dft_dir_powers(double **, unsigned char *, const int, const int, const int, const DFTWAVES *, 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 **, 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 */ extern void free_dir2rad(DIR2RAD *); @@ -753,6 +799,13 @@ extern void free_dftwaves(DFTWAVES *); extern void free_rotgrids(ROTGRIDS *); 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 */ extern void bits_6to8(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 */ extern int init_dir2rad(DIR2RAD **, 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 init_rotgrids(ROTGRIDS **, 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_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 */ extern int line_points(int **, int **, 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 */ 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, unsigned char *, const int, const int, 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, 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 */ 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 *); extern int gen_high_curve_map(int **, int *, const int, const int, 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, unsigned char *, const int, const int, 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 void smooth_imap(int *, const int, const int, const DIR2RAD *, 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, 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 */ extern int alloc_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 *, unsigned char *, 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 *); extern int get_low_curvature_direction(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 */ 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, const int, unsigned char *, const int, const int, 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 */ extern int remove_false_minutia(MINUTIAE *, @@ -990,15 +1089,93 @@ extern int remove_false_minutia_V2(MINUTIAE *, unsigned char *, const int, const int, int *, int *, int *, const int, const int, 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 */ extern int count_minutiae_ridges(MINUTIAE *, unsigned char *, const int, const int, 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 */ +extern int alloc_shape(SHAPE **, const int, const int, const int, const int); 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 void sort_row_on_x(ROW *); /* sort.c */ 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); 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 */ /*************************************************************************/ diff --git a/libfprint/nbis/include/log.h b/libfprint/nbis/include/log.h index a9cd603..4fd7e75 100644 --- a/libfprint/nbis/include/log.h +++ b/libfprint/nbis/include/log.h @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 _LOG_H #define _LOG_H @@ -36,10 +57,6 @@ identified are necessarily the best available for the purpose. #define LOG_FILE "log.txt" #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 close_logfile(void); diff --git a/libfprint/nbis/include/morph.h b/libfprint/nbis/include/morph.h index 782d331..944bd2a 100644 --- a/libfprint/nbis/include/morph.h +++ b/libfprint/nbis/include/morph.h @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 __MORPH_H__ #define __MORPH_H__ diff --git a/libfprint/nbis/include/mytime.h b/libfprint/nbis/include/mytime.h new file mode 100644 index 0000000..e052a25 --- /dev/null +++ b/libfprint/nbis/include/mytime.h @@ -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 +#endif + +#ifdef __MSYS__ +#include +#else +#include +#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 + diff --git a/libfprint/nbis/include/sunrast.h b/libfprint/nbis/include/sunrast.h index 3d7deea..61c035f 100644 --- a/libfprint/nbis/include/sunrast.h +++ b/libfprint/nbis/include/sunrast.h @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 _SUNRAST_H #define _SUNRAST_H diff --git a/libfprint/nbis/mindtct/binar.c b/libfprint/nbis/mindtct/binar.c index 916d56e..fb2be22 100644 --- a/libfprint/nbis/mindtct/binar.c +++ b/libfprint/nbis/mindtct/binar.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -36,16 +57,44 @@ identified are necessarily the best available for the purpose. *********************************************************************** ROUTINES: + binarize() binarize_V2() + binarize_image() binarize_image_V2() dirbinarize() + isobinarize() ***********************************************************************/ #include -#include #include +/************************************************************************* +************************************************************************** +#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 @@ -101,6 +150,32 @@ int binarize_V2(unsigned char **odata, int *ow, int *oh, 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 @@ -247,3 +322,27 @@ int dirbinarize(const unsigned char *pptr, const int idir, 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 +**************************************************************************/ diff --git a/libfprint/nbis/mindtct/block.c b/libfprint/nbis/mindtct/block.c index be0b3f9..761f332 100644 --- a/libfprint/nbis/mindtct/block.c +++ b/libfprint/nbis/mindtct/block.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -44,8 +65,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include -#include #include /************************************************************************* @@ -86,7 +105,7 @@ int block_offsets(int **optr, int *ow, int *oh, int *blkoffs, bx, by, bw, bh, bi, bsize; int blkrow_start, blkrow_size, offset; int lastbw, lastbh; - int pad2, pw; + int pad2, pw, ph; /* Test if unpadded image is smaller than a single block */ if((iw < blocksize) || (ih < blocksize)){ @@ -99,6 +118,7 @@ int block_offsets(int **optr, int *ow, int *oh, /* Compute padded width and height of image */ pad2 = pad<<1; pw = iw + pad2; + ph = ih + pad2; /* Compute the number of columns and rows of blocks in the image. */ /* Take the ceiling to account for "leftovers" at the right and */ diff --git a/libfprint/nbis/mindtct/chaincod.c b/libfprint/nbis/mindtct/chaincod.c new file mode 100644 index 0000000..dd5d779 --- /dev/null +++ b/libfprint/nbis/mindtct/chaincod.c @@ -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 +#include + +/************************************************************************* +************************************************************************** +#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); +} diff --git a/libfprint/nbis/mindtct/contour.c b/libfprint/nbis/mindtct/contour.c index 92e77f5..689ffaf 100644 --- a/libfprint/nbis/mindtct/contour.c +++ b/libfprint/nbis/mindtct/contour.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -50,7 +71,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include #include /************************************************************************* @@ -591,236 +611,6 @@ int get_centered_contour(int **ocontour_x, int **ocontour_y, 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 @@ -1046,6 +836,236 @@ int search_contour(const int x_search, const int y_search, 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 diff --git a/libfprint/nbis/mindtct/detect.c b/libfprint/nbis/mindtct/detect.c index deadf29..10ed85c 100644 --- a/libfprint/nbis/mindtct/detect.c +++ b/libfprint/nbis/mindtct/detect.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -35,16 +56,46 @@ identified are necessarily the best available for the purpose. *********************************************************************** ROUTINES: + lfs_detect_minutiae() lfs_detect_minutiae_V2() - get_minutiae() ***********************************************************************/ #include -#include #include +#include #include +/************************************************************************* +#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: 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 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 *omw, int *omh, unsigned char **obdata, int *obw, int *obh, @@ -99,6 +150,8 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, int ret, maxpad; MINUTIAE *minutiae; + set_timer(total_timer); + /******************/ /* INITIALIZATION */ /******************/ @@ -181,6 +234,7 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, /******************/ /* MAPS */ /******************/ + set_timer(imap_timer); /* Generate block maps from the input image. */ 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"); + time_accum(imap_timer, imap_time); + /******************/ /* BINARIZARION */ /******************/ + set_timer(bin_timer); /* Initialize lookup table for pixel offsets to rotated grids */ /* used for directional binarization. */ @@ -254,9 +311,12 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, print2log("\nBINARIZATION DONE\n"); + time_accum(bin_timer, bin_time); + /******************/ /* DETECTION */ /******************/ + set_timer(minutia_timer); /* Convert 8-bit grayscale binary image [0,255] to */ /* 8-bit binary image [0,1]. */ @@ -281,6 +341,10 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, return(ret); } + time_accum(minutia_timer, minutia_time); + + set_timer(rm_minutia_timer); + if((ret = remove_false_minutia_V2(minutiae, bdata, iw, ih, direction_map, low_flow_map, high_curve_map, mw, mh, lfsparms))){ @@ -297,9 +361,13 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, print2log("\nMINUTIA DETECTION DONE\n"); + time_accum(rm_minutia_timer, rm_minutia_time); + /******************/ /* RIDGE COUNTS */ /******************/ + set_timer(ridge_count_timer); + if((ret = count_minutiae_ridges(minutiae, bdata, iw, ih, lfsparms))){ /* Free memory allocated to this point. */ free(pdata); @@ -314,6 +382,8 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, print2log("\nNEIGHBOR RIDGE COUNT DONE\n"); + time_accum(ridge_count_timer, ridge_count_time); + /******************/ /* WRAP-UP */ /******************/ @@ -337,6 +407,28 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, *obh = bh; *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((ret = close_logfile())) return(ret); @@ -344,112 +436,3 @@ static int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, 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); -} diff --git a/libfprint/nbis/mindtct/dft.c b/libfprint/nbis/mindtct/dft.c index af13653..0cc490a 100644 --- a/libfprint/nbis/mindtct/dft.c +++ b/libfprint/nbis/mindtct/dft.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -44,87 +65,8 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include #include -/************************************************************************* -************************************************************************** -#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. @@ -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: 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. +#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: - 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 + 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: - 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 + rowsums - the resulting vector of pixel row sums **************************************************************************/ -static void get_max_norm(double *powmax, int *powmax_dir, - double *pownorm, const double *power_vector, const int ndirs) +void sum_rot_block_rows(int *rowsums, const unsigned char *blkptr, + const int *grid_offsets, const int blocksize) { - int dir; - double max_v, powsum; - int max_i; - double powmean; + int ix, iy, gi; - /* Find max power value and store corresponding direction */ - max_v = power_vector[0]; - max_i = 0; + /* Initialize rotation offset index. */ + gi = 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; + /* 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++; } } - - *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. +#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: - 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) + 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: - 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 + power - the computed DFT power for the given wave form at the + given orientation within the image block **************************************************************************/ -static int sort_dft_waves(int *wis, const double *powmaxs, const double *pownorms, - const int nstats) +void dft_power(double *power, const int *rowsums, + const DFTWAVE *wave, const int wavelen) { int i; - double *pownorms2; + double cospart, sinpart; - /* 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); + /* 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]); } - 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); + /* Power is the sum of the squared cos and sin components */ + *power = (cospart * cospart) + (sinpart * sinpart); } /************************************************************************* @@ -356,3 +273,106 @@ int dft_power_stats(int *wis, double *powmaxs, int *powmax_dirs, 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); +} + diff --git a/libfprint/nbis/mindtct/free.c b/libfprint/nbis/mindtct/free.c index fd7612e..adaeeb9 100644 --- a/libfprint/nbis/mindtct/free.c +++ b/libfprint/nbis/mindtct/free.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -40,7 +61,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include #include /************************************************************************* diff --git a/libfprint/nbis/mindtct/getmin.c b/libfprint/nbis/mindtct/getmin.c new file mode 100644 index 0000000..08a087d --- /dev/null +++ b/libfprint/nbis/mindtct/getmin.c @@ -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 +#include + +/************************************************************************* +************************************************************************** +#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); +} diff --git a/libfprint/nbis/mindtct/globals.c b/libfprint/nbis/mindtct/globals.c index e17c7dc..da10c15 100644 --- a/libfprint/nbis/mindtct/globals.c +++ b/libfprint/nbis/mindtct/globals.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -40,7 +61,7 @@ identified are necessarily the best available for the purpose. /*************************************************************************/ #ifdef LOG_REPORT -FILE *g_logfp; +FILE *logfp; #endif /* Constants (C) for defining 4 DFT frequencies, where */ @@ -129,8 +150,6 @@ LFSPARMS g_lfsparms = { PORES_STEPS_BWD, PORES_MIN_DIST2, PORES_MAX_RATIO, - FALSE, /* not removing perimeter points by default */ - PERIMETER_PTS_DISTANCE, /* Ridge Counting Controls */ MAX_NBRS, @@ -215,8 +234,6 @@ LFSPARMS g_lfsparms_V2 = { PORES_STEPS_BWD, PORES_MIN_DIST2, PORES_MAX_RATIO, - FALSE, /* not removing perimeter points by default */ - PERIMETER_PTS_DISTANCE, /* Ridge Counting Controls */ MAX_NBRS, diff --git a/libfprint/nbis/mindtct/imgutil.c b/libfprint/nbis/mindtct/imgutil.c index c4fa868..50cf766 100644 --- a/libfprint/nbis/mindtct/imgutil.c +++ b/libfprint/nbis/mindtct/imgutil.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -45,7 +66,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include #include #include @@ -65,18 +85,6 @@ identified are necessarily the best available for the purpose. Output: 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; - } -} /************************************************************************* ************************************************************************** diff --git a/libfprint/nbis/mindtct/init.c b/libfprint/nbis/mindtct/init.c index 50dc0d7..a718279 100644 --- a/libfprint/nbis/mindtct/init.c +++ b/libfprint/nbis/mindtct/init.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -37,6 +58,7 @@ identified are necessarily the best available for the purpose. ROUTINES: init_dir2rad() init_dftwaves() + get_max_padding() get_max_padding_V2() init_rotgrids() alloc_dir_powers() @@ -44,7 +66,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include #include /************************************************************************* @@ -242,6 +263,33 @@ int init_dftwaves(DFTWAVES **optr, const double *dft_coefs, 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 diff --git a/libfprint/nbis/mindtct/line.c b/libfprint/nbis/mindtct/line.c index 5d9a8ed..07edf18 100644 --- a/libfprint/nbis/mindtct/line.c +++ b/libfprint/nbis/mindtct/line.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -38,7 +59,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include #include /************************************************************************* diff --git a/libfprint/nbis/mindtct/link.c b/libfprint/nbis/mindtct/link.c new file mode 100644 index 0000000..22e568a --- /dev/null +++ b/libfprint/nbis/mindtct/link.c @@ -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 +#include +#include + +/************************************************************************* +************************************************************************** +#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 +**************************************************************************/ + diff --git a/libfprint/nbis/mindtct/log.c b/libfprint/nbis/mindtct/log.c index d3aafbf..b1dcaad 100644 --- a/libfprint/nbis/mindtct/log.c +++ b/libfprint/nbis/mindtct/log.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -42,17 +63,12 @@ identified are necessarily the best available for the purpose. /* If logging is on, declare global file pointer and supporting */ /* global variable for logging intermediate results. */ -FILE *logfp; -int avrdir; -float dir_strength; -int nvalid; /***************************************************************************/ /***************************************************************************/ int open_logfile() { #ifdef LOG_REPORT - if((logfp = fopen(LOG_FILE, "wb")) == NULL){ fprintf(stderr, "ERROR : open_logfile : fopen : %s\n", LOG_FILE); return(-1); } @@ -69,7 +85,6 @@ void print2log(char *fmt, ...) va_list ap; va_start(ap, fmt); - vfprintf(logfp, fmt, ap); va_end(ap); #endif } @@ -79,7 +94,6 @@ void print2log(char *fmt, ...) int close_logfile() { #ifdef LOG_REPORT - if(fclose(logfp)){ fprintf(stderr, "ERROR : close_logfile : fclose : %s\n", LOG_FILE); return(-1); } diff --git a/libfprint/nbis/mindtct/loop.c b/libfprint/nbis/mindtct/loop.c index 3792b88..847c43f 100644 --- a/libfprint/nbis/mindtct/loop.c +++ b/libfprint/nbis/mindtct/loop.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -36,8 +57,6 @@ identified are necessarily the best available for the purpose. *********************************************************************** ROUTINES: - chain_code_loop() - is_chain_clockwise() get_loop_list() on_loop() on_island_lake() @@ -48,161 +67,13 @@ identified are necessarily the best available for the purpose. get_loop_aspect() fill_loop() fill_partial_row() + flood_loop() + flood_fill4() ***********************************************************************/ #include -#include #include -/************************************************************************* -************************************************************************** -#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 @@ -228,78 +99,6 @@ static int is_chain_clockwise(const int *chain, const int nchain, Zero - successful completion 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); -} /************************************************************************* ************************************************************************** @@ -558,7 +357,7 @@ int on_hook(const MINUTIA *minutia1, const MINUTIA *minutia2, /* If trace had an error in following the contour ... */ if(ret != 0) return(ret); - + /* Otherwise, the trace successfully followed the contour, but did */ /* not encounter the 2nd minutia point within the specified number */ @@ -648,107 +447,6 @@ int is_loop_clockwise(const int *contour_x, const int *contour_y, 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 @@ -776,131 +474,6 @@ static void get_loop_aspect(int *omin_fr, int *omin_to, double *omin_dist, Zero - loop processed successfully 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); -} /************************************************************************* ************************************************************************** @@ -936,6 +509,7 @@ int process_loop_V2(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, int *plow_flow_map, const LFSPARMS *lfsparms) { + int halfway; int idir, type, appearing; double min_dist, max_dist; int min_fr, max_fr, min_to, max_to; @@ -955,6 +529,9 @@ int process_loop_V2(MINUTIAE *minutiae, /* Get pixel value of feature's interior. */ feature_pix = *(bdata + (contour_y[0] * iw) + contour_x[0]); + /* Compute half the perimeter of the loop. */ + halfway = ncontour>>1; + /* Get the aspect dimensions of the loop in units of */ /* squared distance. */ get_loop_aspect(&min_fr, &min_to, &min_dist, @@ -1087,39 +664,103 @@ int process_loop_V2(MINUTIAE *minutiae, /************************************************************************* ************************************************************************** -#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. +#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: - 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 + 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: - 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, - const int y, unsigned char *bdata, const int iw, const int ih) +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 x; - unsigned char *bptr; + int halfway, limit; + 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. */ - bptr = bdata+(y*iw)+frx; + /* Compute half the perimeter of the loop. */ + halfway = ncontour>>1; - /* 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++; + /* 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; } /************************************************************************* @@ -1253,3 +894,119 @@ int fill_loop(const int *contour_x, const int *contour_y, 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. */ +} diff --git a/libfprint/nbis/mindtct/maps.c b/libfprint/nbis/mindtct/maps.c index 43929a4..5cd031b 100644 --- a/libfprint/nbis/mindtct/maps.c +++ b/libfprint/nbis/mindtct/maps.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -46,6 +67,7 @@ identified are necessarily the best available for the purpose. pixelize_map() smooth_direction_map() gen_high_curve_map() + gen_imap() gen_initial_imap() primary_dir_test() secondary_fork_test() @@ -58,6 +80,7 @@ identified are necessarily the best available for the purpose. average_8nbr_dir() num_valid_8nbrs() smooth_imap() + gen_nmap() vorticity() accum_nbr_vorticity() curvature() @@ -65,8 +88,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include -#include #include #include #include @@ -307,10 +328,6 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, xmaxlimit = pw - 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 ... */ for(bi = 0; bi < bsize; bi++){ /* Adjust block offset from pointing to block origin to pointing */ @@ -393,9 +410,9 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, { int _w; fprintf(logfp, " Power\n"); 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", - _w, wis[_w]+1, + _w, wis[_w]+1, powmaxs[wis[_w]], powmax_dirs[wis[_w]], pownorms[wis[_w]], powers[0][powmax_dirs[wis[_w]]]); } @@ -647,7 +664,7 @@ int morph_TF_map(int *tfmap, const int mw, const int mh, unsigned char *cimage, *mimage, *cptr; int *mptr; int i; - + /* Convert TRUE/FALSE map into a binary byte image. */ cimage = (unsigned char *)malloc(mw*mh); @@ -925,13 +942,37 @@ int gen_high_curve_map(int **ohcmap, int *direction_map, } /* bx */ } /* by */ - /* Assign High Curvature Map to output pointer. */ + /* Assign High Curvature Map to output pointer. */ *ohcmap = high_curve_map; /* Return normally. */ 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. @@ -959,126 +1000,6 @@ int gen_high_curve_map(int **ohcmap, int *direction_map, Zero - successful completion 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 powmax_dirs - directions associated with each of the N-1 maximum powers 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 Return Code: 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)){ #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, " Selected Wave = %d\n", wis[w]+1); 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 powmax_dirs - directions associated with each of the N-1 maximum powers 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 Return Code: 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: 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; - for(my = 0; my < mh; my++){ - for(mx = 0; mx < mw; mx++){ - /* Compute average direction from neighbors, returning the */ - /* number of valid neighbors used in the computation, and */ - /* the "strength" of the average direction. */ - average_8nbr_dir(&avrdir, &dir_strength, &nvalid, - imap, mx, my, mw, mh, dir2rad); - - /* If average direction strength is strong enough */ - /* (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++; - } - } -} + Input: + imap - associated input vector of IMAP directions + mw - the width (in blocks) of the IMAP + mh - the height (in blocks) of the IMAP + lfsparms - parameters and thresholds for controlling LFS + Output: + optr - points to the created NMAP + Return Code: + Zero - successful completion + Negative - system error +**************************************************************************/ /************************************************************************* ************************************************************************** diff --git a/libfprint/nbis/mindtct/matchpat.c b/libfprint/nbis/mindtct/matchpat.c index 04bb27b..290d00c 100644 --- a/libfprint/nbis/mindtct/matchpat.c +++ b/libfprint/nbis/mindtct/matchpat.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -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. Input: p1 - first pixel value of pair p2 - second pixel value of pair Output: - possible - list of matching feature_patterns[] indices + possible - list of matching g_feature_patterns[] indices nposs - number of matches Return Code: 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. Input: p1 - first 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 Output: - possible - list of matching feature_patterns[] indices + possible - list of matching g_feature_patterns[] indices nposs - number of matches Return Code: 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. Input: p1 - first 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 Output: - possible - list of matching feature_patterns[] indices + possible - list of matching g_feature_patterns[] indices nposs - number of matches Return Code: nposs - number of matches diff --git a/libfprint/nbis/mindtct/minutia.c b/libfprint/nbis/mindtct/minutia.c index 497336b..ca0d551 100644 --- a/libfprint/nbis/mindtct/minutia.c +++ b/libfprint/nbis/mindtct/minutia.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -37,6 +58,7 @@ identified are necessarily the best available for the purpose. ROUTINES: alloc_minutiae() realloc_minutiae() + detect_minutiae() detect_minutiae_V2() update_minutiae() update_minutiae_V2() @@ -73,30 +95,26 @@ identified are necessarily the best available for the purpose. adjust_high_curvature_minutia() adjust_high_curvature_minutia_V2() get_low_curvature_direction() - lfs2nist_minutia_XYT() ***********************************************************************/ #include -#include #include - - /************************************************************************* ************************************************************************** #cat: alloc_minutiae - Allocates and initializes a minutia list based on the #cat: specified maximum number of minutiae to be detected. Input: - max_minutiae - number of minutia to be allocated in list + DEFAULT_BOZORTH_MINUTIAE - number of minutia to be allocated in list Output: ominutiae - points to the allocated minutiae list Return Code: Zero - successful completion Negative - system error **************************************************************************/ -int alloc_minutiae(MINUTIAE **ominutiae, const int max_minutiae) +int alloc_minutiae(MINUTIAE **ominutiae, const int DEFAULT_BOZORTH_MINUTIAE) { MINUTIAE *minutiae; @@ -105,13 +123,13 @@ int alloc_minutiae(MINUTIAE **ominutiae, const int max_minutiae) fprintf(stderr, "ERROR : alloc_minutiae : malloc : minutiae\n"); exit(-430); } - minutiae->list = (MINUTIA **)malloc(max_minutiae * sizeof(MINUTIA *)); + minutiae->list = (MINUTIA **)malloc(DEFAULT_BOZORTH_MINUTIAE * sizeof(MINUTIA *)); if(minutiae->list == (MINUTIA **)NULL){ fprintf(stderr, "ERROR : alloc_minutiae : malloc : minutiae->list\n"); exit(-431); } - minutiae->alloc = max_minutiae; + minutiae->alloc = DEFAULT_BOZORTH_MINUTIAE; minutiae->num = 0; *ominutiae = minutiae; @@ -126,7 +144,7 @@ int alloc_minutiae(MINUTIAE **ominutiae, const int max_minutiae) Input: minutiae - previously allocated list of minutiae points - max_minutiae - number of minutia to be allocated in list + DEFAULT_BOZORTH_MINUTIAE - number of minutia to be allocated in list Output: minutiae - extended list of minutiae points Return Code: @@ -146,6 +164,29 @@ int realloc_minutiae(MINUTIAE *minutiae, const int incr_minutiae) return(0); } +/************************************************************************* +************************************************************************** +#cat: detect_minutiae - Takes a binary image and its associated IMAP and +#cat: NMAP matrices and scans each image block for potential +#cat: minutia points. + + Input: + bdata - binary image data (0==while & 1==black) + iw - width (in pixels) of image + ih - height (in pixels) of image + imap - matrix of ridge flow directions + nmap - IMAP augmented with blocks of HIGH-CURVATURE and + blocks which have no neighboring valid directions. + mw - width (in blocks) of IMAP and NMAP matrices. + mh - height (in blocks) of IMAP and NMAP matrices. + lfsparms - parameters and thresholds for controlling LFS + Output: + minutiae - points to a list of detected minutia structures + Return Code: + Zero - successful completion + Negative - system error +**************************************************************************/ + /************************************************************************* ************************************************************************** #cat: detect_minutiae_V2 - Takes a binary image and its associated @@ -666,40 +707,6 @@ int rm_dup_minutiae(MINUTIAE *minutiae) Output: fpout - open file pointer **************************************************************************/ -void dump_minutiae(FILE *fpout, const MINUTIAE *minutiae) -{ - int i, j; - - fprintf(fpout, "\n%d Minutiae Detected\n\n", minutiae->num); - - for(i = 0; i < minutiae->num; i++){ - /* Precision of reliablity added one decimal position */ - /* on 09-13-04 */ - fprintf(fpout, "%4d : %4d, %4d : %2d : %6.3f :", i, - minutiae->list[i]->x, minutiae->list[i]->y, - minutiae->list[i]->direction, minutiae->list[i]->reliability); - if(minutiae->list[i]->type == RIDGE_ENDING) - fprintf(fpout, "RIG : "); - else - fprintf(fpout, "BIF : "); - - if(minutiae->list[i]->appearing) - fprintf(fpout, "APP : "); - else - fprintf(fpout, "DIS : "); - - fprintf(fpout, "%2d ", minutiae->list[i]->feature_id); - - for(j = 0; j < minutiae->list[i]->num_nbrs; j++){ - fprintf(fpout, ": %4d,%4d; %2d ", - minutiae->list[minutiae->list[i]->nbrs[j]]->x, - minutiae->list[minutiae->list[i]->nbrs[j]]->y, - minutiae->list[i]->ridge_counts[j]); - } - - fprintf(fpout, "\n"); - } -} /************************************************************************* ************************************************************************** @@ -712,20 +719,6 @@ void dump_minutiae(FILE *fpout, const MINUTIAE *minutiae) Output: fpout - open file pointer **************************************************************************/ -void dump_minutiae_pts(FILE *fpout, const MINUTIAE *minutiae) -{ - int i; - - /* First line in the output file contians the number of minutia */ - /* points to be written to the file. */ - fprintf(fpout, "%d\n", minutiae->num); - - /* Foreach minutia in list... */ - for(i = 0; i < minutiae->num; i++){ - /* Write the minutia's coordinate point to the file pointer. */ - fprintf(fpout, "%4d %4d\n", minutiae->list[i]->x, minutiae->list[i]->y); - } -} /************************************************************************* @@ -741,32 +734,6 @@ void dump_minutiae_pts(FILE *fpout, const MINUTIAE *minutiae) Output: fpout - open file pointer **************************************************************************/ -void dump_reliable_minutiae_pts(FILE *fpout, const MINUTIAE *minutiae, - const double reliability) -{ - int i, count; - - /* First count the number of qualifying minutiae so that the */ - /* MFS header may be written. */ - count = 0; - /* Foreach minutia in list... */ - for(i = 0; i < minutiae->num; i++){ - if(minutiae->list[i]->reliability == reliability) - count++; - } - - /* First line in the output file contians the number of minutia */ - /* points to be written to the file. */ - fprintf(fpout, "%d\n", count); - - /* Foreach minutia in list... */ - for(i = 0; i < minutiae->num; i++){ - if(minutiae->list[i]->reliability == reliability) - /* Write the minutia's coordinate point to the file pointer. */ - fprintf(fpout, "%4d %4d\n", - minutiae->list[i]->x, minutiae->list[i]->y); - } -} /************************************************************************* ************************************************************************** @@ -782,7 +749,7 @@ void dump_reliable_minutiae_pts(FILE *fpout, const MINUTIAE *minutiae, reliability - floating point measure of minutia's reliability type - type of the minutia (ridge-ending or bifurcation) appearing - designates the minutia as appearing or disappearing - feature_id - index of minutia's matching feature_patterns[] + feature_id - index of minutia's matching g_feature_patterns[] Output: ominutia - ponter to an allocated and initialized minutia structure Return Code: @@ -927,119 +894,6 @@ int remove_minutia(const int index, MINUTIAE *minutiae) Zero - successful completion Negative - system error **************************************************************************/ -int join_minutia(const MINUTIA *minutia1, const MINUTIA *minutia2, - unsigned char *bdata, const int iw, const int ih, - const int with_boundary, const int line_radius) -{ - int dx_gte_dy, delta_x, delta_y; - int *x_list, *y_list, num; - int minutia_pix, boundary_pix; - int i, j, ret; - int x1, y1, x2, y2; - - /* Compute X and Y deltas between minutia points. */ - delta_x = abs(minutia1->x - minutia2->x); - delta_y = abs(minutia1->y - minutia2->y); - - /* Set flag based on |DX| >= |DY|. */ - /* If flag is true then add additional pixel width to the join line */ - /* by adding pixels neighboring top and bottom. */ - /* If flag is false then add additional pixel width to the join line */ - /* by adding pixels neighboring left and right. */ - if(delta_x >= delta_y) - dx_gte_dy = 1; - else - dx_gte_dy = 0; - - /* Compute points along line segment between the two minutia points. */ - if((ret = line_points(&x_list, &y_list, &num, - minutia1->x, minutia1->y, minutia2->x, minutia2->y))) - /* If error with line routine, return error code. */ - return(ret); - - /* Determine pixel color of minutia and boundary. */ - if(minutia1->type == RIDGE_ENDING){ - /* To connect 2 ridge-endings, draw black. */ - minutia_pix = 1; - boundary_pix = 0; - } - else{ - /* To connect 2 bifurcations, draw white. */ - minutia_pix = 0; - boundary_pix = 1; - } - - /* Foreach point on line connecting the minutiae points ... */ - for(i = 1; i < num-1; i++){ - /* Draw minutia pixel at current point on line. */ - *(bdata+(y_list[i]*iw)+x_list[i]) = minutia_pix; - - /* Initialize starting corrdinates for adding width to the */ - /* join line to the current point on the line. */ - x1 = x_list[i]; - y1 = y_list[i]; - x2 = x1; - y2 = y1; - /* Foreach pixel of added radial width ... */ - for(j = 0; j < line_radius; j++){ - - /* If |DX|>=|DY|, we want to add width to line by writing */ - /* to pixels neighboring above and below. */ - /* x1 -= (0=(1-1)); y1 -= 1 ==> ABOVE */ - /* x2 += (0=(1-1)); y2 += 1 ==> BELOW */ - /* If |DX|<|DY|, we want to add width to line by writing */ - /* to pixels neighboring left and right. */ - /* x1 -= (1=(1-0)); y1 -= 0 ==> LEFT */ - /* x2 += (1=(1-0)); y2 += 0 ==> RIGHT */ - - /* Advance 1st point along width dimension. */ - x1 -= (1 - dx_gte_dy); - y1 -= dx_gte_dy; - /* If pixel 1st point is within image boundaries ... */ - if((x1 >= 0) && (x1 < iw) && - (y1 >= 0) && (y1 < ih)) - /* Write the pixel ABOVE or LEFT. */ - *(bdata+(y1*iw)+x1) = minutia_pix; - - /* Advance 2nd point along width dimension. */ - x2 += (1 - dx_gte_dy); - y2 += dx_gte_dy; - /* If pixel 2nd point is within image boundaries ... */ - if((x2 >= 0) && (x2 < iw) && - /* Write the pixel BELOW or RIGHT. */ - (y2 >= 0) && (y2 < ih)) - *(bdata+(y2*iw)+x2) = minutia_pix; - } - - /* If boundary flag is set ... draw the boundary pixels.*/ - if(with_boundary){ - /* Advance 1st point along width dimension. */ - x1 -= (1 - dx_gte_dy); - y1 -= dx_gte_dy; - /* If pixel 1st point is within image boundaries ... */ - if((x1 >= 0) && (x1 < iw) && - (y1 >= 0) && (y1 < ih)) - /* Write the pixel ABOVE or LEFT of opposite color. */ - *(bdata+(y1*iw)+x1) = boundary_pix; - - /* Advance 2nd point along width dimension. */ - x2 += (1 - dx_gte_dy); - y2 += dx_gte_dy; - /* If pixel 2nd point is within image boundaries ... */ - if((x2 >= 0) && (x2 < iw) && - (y2 >= 0) && (y2 < ih)) - /* Write the pixel BELOW or RIGHT of opposite color. */ - *(bdata+(y2*iw)+x2) = boundary_pix; - } - } - - /* Deallocate points along connecting line. */ - free(x_list); - free(y_list); - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -1178,61 +1032,6 @@ int choose_scan_direction(const int imapval, const int ndirs) Zero - successful completion Negative - system error **************************************************************************/ -int scan4minutiae(MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - const int *imap, const int *nmap, - const int blk_x, const int blk_y, const int mw, const int mh, - const int scan_x, const int scan_y, - const int scan_w, const int scan_h, const int scan_dir, - const LFSPARMS *lfsparms) -{ - int blk_i, ret; - - /* Compute block index from block coordinates. */ - blk_i = (blk_y*mw) + blk_x; - - /* Conduct primary scan for minutiae horizontally. */ - if(scan_dir == SCAN_HORIZONTAL){ - - if((ret = scan4minutiae_horizontally(minutiae, bdata, iw, ih, - imap[blk_i], nmap[blk_i], - scan_x, scan_y, scan_w, scan_h, lfsparms))){ - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - } - - /* Rescan block vertically. */ - if((ret = rescan4minutiae_vertically(minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))){ - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - } - } - - /* Otherwise, conduct primary scan for minutiae vertically. */ - else{ - if((ret = scan4minutiae_vertically(minutiae, bdata, iw, ih, - imap[blk_i], nmap[blk_i], - scan_x, scan_y, scan_w, scan_h, lfsparms))){ - /* Return resulting code. */ - return(ret); - } - - /* Rescan block horizontally. */ - if((ret = rescan4minutiae_horizontally(minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))){ - /* Return resulting code. */ - return(ret); - } - } - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -1262,116 +1061,6 @@ int scan4minutiae(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int scan4minutiae_horizontally(MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - const int imapval, const int nmapval, - const int scan_x, const int scan_y, - const int scan_w, const int scan_h, - const LFSPARMS *lfsparms) -{ - int sx, sy, ex, ey, cx, cy, x2; - unsigned char *p1ptr, *p2ptr; - int possible[NFEATURES], nposs; - int ret; - - /* NOTE!!! Minutia that "straddle" region boundaries may be missed! */ - - /* If possible, overlap left and right of current scan region */ - /* by 2 pixel columns to help catch some minutia that straddle the */ - /* the scan region boundaries. */ - sx = max(0, scan_x-2); - ex = min(iw, scan_x+scan_w+2); - - /* If possible, overlap the scan region below by 1 pixel row. */ - sy = scan_y; - ey = min(ih, scan_y+scan_h+1); - - /* For now, we will not adjust for IMAP edge, as the binary image */ - /* was properly padded at its edges so as not to cause anomallies. */ - - /* Start at first row in region. */ - cy = sy; - /* While second scan row not outside the bottom of the scan region... */ - while(cy+1 < ey){ - /* Start at beginning of new scan row in region. */ - cx = sx; - /* While not at end of region's current scan row. */ - while(cx < ex){ - /* Get pixel pair from current x position in current and next */ - /* scan rows. */ - p1ptr = bdata+(cy*iw)+cx; - p2ptr = bdata+((cy+1)*iw)+cx; - /* If scan pixel pair matches first pixel pair of */ - /* 1 or more features... */ - if(match_1st_pair(*p1ptr, *p2ptr, possible, &nposs)){ - /* Bump forward to next scan pixel pair. */ - cx++; - p1ptr++; - p2ptr++; - /* If not at end of region's current scan row... */ - if(cx < ex){ - /* If scan pixel pair matches second pixel pair of */ - /* 1 or more features... */ - if(match_2nd_pair(*p1ptr, *p2ptr, possible, &nposs)){ - /* Store current x location. */ - x2 = cx; - /* Skip repeated pixel pairs. */ - skip_repeated_horizontal_pair(&cx, ex, &p1ptr, &p2ptr, - iw, ih); - /* If not at end of region's current scan row... */ - if(cx < ex){ - /* If scan pixel pair matches third pixel pair of */ - /* a single feature... */ - if(match_3rd_pair(*p1ptr, *p2ptr, possible, &nposs)){ - /* Process detected minutia point. */ - if((ret = process_horizontal_scan_minutia(minutiae, - cx, cy, x2, possible[0], - bdata, iw, ih, - imapval, nmapval, lfsparms))){ - /* Return code may be: */ - /* 1. ret< 0 (implying system error) */ - /* 2. ret==IGNORE (ignore current feature) */ - if(ret < 0) - return(ret); - /* Otherwise, IGNORE and continue. */ - } - } - - /* Set up to resume scan. */ - /* Test to see if 3rd pair can slide into 2nd pair. */ - /* The values of the 2nd pair MUST be different. */ - /* If 3rd pair values are different ... */ - if(*p1ptr != *p2ptr){ - /* Set next first pair to last of repeated */ - /* 2nd pairs, ie. back up one pair. */ - cx--; - } - - /* Otherwise, 3rd pair can't be a 2nd pair, so */ - /* keep pointing to 3rd pair so that it is used */ - /* in the next first pair test. */ - - } /* Else, at end of current scan row. */ - } - - /* Otherwise, 2nd pair failed, so keep pointing to it */ - /* so that it is used in the next first pair test. */ - - } /* Else, at end of current scan row. */ - } - /* Otherwise, 1st pair failed... */ - else{ - /* Bump forward to next pixel pair. */ - cx++; - } - } /* While not at end of current scan row. */ - /* Bump forward to next scan row. */ - cy++; - } /* While not out of scan rows. */ - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -1497,7 +1186,7 @@ int scan4minutiae_horizontally_V2(MINUTIAE *minutiae, /************************************************************************* ************************************************************************** -#cat: scan4minutiae_vertically - Scans a specified region of binary image data +#cat: scan4minutiae_vertically - Scans a specified region of binary image data #cat: vertically, detecting potential minutiae points. #cat: Minutia detected via the vetical scan process are #cat: by nature horizontally oriented (orthogonal to the scan). @@ -1523,116 +1212,6 @@ int scan4minutiae_horizontally_V2(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int scan4minutiae_vertically(MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - const int imapval, const int nmapval, - const int scan_x, const int scan_y, - const int scan_w, const int scan_h, - const LFSPARMS *lfsparms) -{ - int sx, sy, ex, ey, cx, cy, y2; - unsigned char *p1ptr, *p2ptr; - int possible[NFEATURES], nposs; - int ret; - - /* NOTE!!! Minutia that "straddle" region boundaries may be missed! */ - - /* If possible, overlap scan region to the right by 1 pixel column. */ - sx = scan_x; - ex = min(iw, scan_x+scan_w+1); - - /* If possible, overlap top and bottom of current scan region */ - /* by 2 pixel rows to help catch some minutia that straddle the */ - /* the scan region boundaries. */ - sy = max(0, scan_y-2); - ey = min(ih, scan_y+scan_h+2); - - /* For now, we will not adjust for IMAP edge, as the binary image */ - /* was properly padded at its edges so as not to cause anomalies. */ - - /* Start at first column in region. */ - cx = sx; - /* While second scan column not outside the right of the region ... */ - while(cx+1 < ex){ - /* Start at beginning of new scan column in region. */ - cy = sy; - /* While not at end of region's current scan column. */ - while(cy < ey){ - /* Get pixel pair from current y position in current and next */ - /* scan columns. */ - p1ptr = bdata+(cy*iw)+cx; - p2ptr = p1ptr+1; - /* If scan pixel pair matches first pixel pair of */ - /* 1 or more features... */ - if(match_1st_pair(*p1ptr, *p2ptr, possible, &nposs)){ - /* Bump forward to next scan pixel pair. */ - cy++; - p1ptr+=iw; - p2ptr+=iw; - /* If not at end of region's current scan column... */ - if(cy < ey){ - /* If scan pixel pair matches second pixel pair of */ - /* 1 or more features... */ - if(match_2nd_pair(*p1ptr, *p2ptr, possible, &nposs)){ - /* Store current y location. */ - y2 = cy; - /* Skip repeated pixel pairs. */ - skip_repeated_vertical_pair(&cy, ey, &p1ptr, &p2ptr, - iw, ih); - /* If not at end of region's current scan column... */ - if(cy < ey){ - /* If scan pixel pair matches third pixel pair of */ - /* a single feature... */ - if(match_3rd_pair(*p1ptr, *p2ptr, possible, &nposs)){ - /* Process detected minutia point. */ - if((ret = process_vertical_scan_minutia(minutiae, - cx, cy, y2, possible[0], - bdata, iw, ih, - imapval, nmapval, lfsparms))){ - /* Return code may be: */ - /* 1. ret< 0 (implying system error) */ - /* 2. ret==IGNORE (ignore current feature) */ - if(ret < 0) - return(ret); - /* Otherwise, IGNORE and continue. */ - } - } - - /* Set up to resume scan. */ - /* Test to see if 3rd pair can slide into 2nd pair. */ - /* The values of the 2nd pair MUST be different. */ - /* If 3rd pair values are different ... */ - if(*p1ptr != *p2ptr){ - /* Set next first pair to last of repeated */ - /* 2nd pairs, ie. back up one pair. */ - cy--; - } - - /* Otherwise, 3rd pair can't be a 2nd pair, so */ - /* keep pointing to 3rd pair so that it is used */ - /* in the next first pair test. */ - - } /* Else, at end of current scan row. */ - } - - /* Otherwise, 2nd pair failed, so keep pointing to it */ - /* so that it is used in the next first pair test. */ - - } /* Else, at end of current scan column. */ - } - /* Otherwise, 1st pair failed... */ - else{ - /* Bump forward to next pixel pair. */ - cy++; - } - } /* While not at end of current scan column. */ - /* Bump forward to next scan column. */ - cx++; - } /* While not out of scan columns. */ - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -1785,62 +1364,6 @@ int scan4minutiae_vertically_V2(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int rescan4minutiae_horizontally(MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - const int *imap, const int *nmap, - const int blk_x, const int blk_y, - const int mw, const int mh, - const int scan_x, const int scan_y, - const int scan_w, const int scan_h, - const LFSPARMS *lfsparms) -{ - int blk_i, ret; - - /* Compute block index from block coordinates. */ - blk_i = (blk_y*mw)+blk_x; - - /* If high-curve block... */ - if(nmap[blk_i] == HIGH_CURVATURE){ - /* Rescan entire block in orthogonal direction. */ - if((ret = scan4minutiae_horizontally(minutiae, bdata, iw, ih, - imap[blk_i], nmap[blk_i], - scan_x, scan_y, scan_w, scan_h, lfsparms))) - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - } - /* Otherwise, block is low-curvature. */ - else{ - /* 1. Rescan horizontally to the North. */ - if((ret = rescan_partial_horizontally(NORTH, minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))) - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - - /* 2. Rescan horizontally to the East. */ - if((ret = rescan_partial_horizontally(EAST, minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))) - return(ret); - - /* 3. Rescan horizontally to the South. */ - if((ret = rescan_partial_horizontally(SOUTH, minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))) - return(ret); - - /* 4. Rescan horizontally to the West. */ - if((ret = rescan_partial_horizontally(WEST, minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))) - return(ret); - } /* End low-curvature rescan. */ - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -1871,62 +1394,6 @@ int rescan4minutiae_horizontally(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int rescan4minutiae_vertically(MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - const int *imap, const int *nmap, - const int blk_x, const int blk_y, - const int mw, const int mh, - const int scan_x, const int scan_y, - const int scan_w, const int scan_h, - const LFSPARMS *lfsparms) -{ - int blk_i, ret; - - /* Compute block index from block coordinates. */ - blk_i = (blk_y*mw)+blk_x; - - /* If high-curve block... */ - if(nmap[blk_i] == HIGH_CURVATURE){ - /* Rescan entire block in orthogonal direction. */ - if((ret = scan4minutiae_vertically(minutiae, bdata, iw, ih, - imap[blk_i], nmap[blk_i], - scan_x, scan_y, scan_w, scan_h, lfsparms))) - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - } - /* Otherwise, block is low-curvature. */ - else{ - /* 1. Rescan vertically to the North. */ - if((ret = rescan_partial_vertically(NORTH, minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))) - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - - /* 2. Rescan vertically to the East. */ - if((ret = rescan_partial_vertically(EAST, minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))) - return(ret); - - /* 3. Rescan vertically to the South. */ - if((ret = rescan_partial_vertically(SOUTH, minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))) - return(ret); - - /* 4. Rescan vertically to the West. */ - if((ret = rescan_partial_vertically(WEST, minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, lfsparms))) - return(ret); - } /* End low-curvature rescan. */ - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -1957,70 +1424,6 @@ int rescan4minutiae_vertically(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int rescan_partial_horizontally(const int nbr_dir, MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - const int *imap, const int *nmap, - const int blk_x, const int blk_y, - const int mw, const int mh, - const int scan_x, const int scan_y, - const int scan_w, const int scan_h, - const LFSPARMS *lfsparms) -{ - int nblk_i, blk_i; - int rescan_dir; - int rescan_x, rescan_y, rescan_w, rescan_h; - int ret; - - /* Neighbor will either be NORTH, SOUTH, EAST, OR WEST. */ - ret = get_nbr_block_index(&nblk_i, nbr_dir, blk_x, blk_y, mw, mh); - /* Will return: */ - /* 1. Neighbor index found == FOUND */ - /* 2. Neighbor not found == NOT_FOUND */ - /* 3. System error < 0 */ - - /* If system error ... */ - if(ret < 0) - /* Return the error code. */ - return(ret); - - /* If neighbor not found ... */ - if(ret == NOT_FOUND) - /* Nothing to do, so return normally. */ - return(0); - - /* Otherwise, neighboring block found ... */ - - /* If neighbor block is VALID... */ - if(imap[nblk_i] != INVALID_DIR){ - - /* Compute block index from current (not neighbor) block coordinates. */ - blk_i = (blk_y*mw)+blk_x; - - /* Select feature scan direction based on neighbor IMAP. */ - rescan_dir = choose_scan_direction(imap[nblk_i], - lfsparms->num_directions); - /* If new scan direction is HORIZONTAL... */ - if(rescan_dir == SCAN_HORIZONTAL){ - /* Adjust scan_x, scan_y, scan_w, scan_h for rescan. */ - if((ret = adjust_horizontal_rescan(nbr_dir, &rescan_x, &rescan_y, - &rescan_w, &rescan_h, - scan_x, scan_y, scan_w, scan_h, lfsparms->blocksize))) - /* Return system error code. */ - return(ret); - /* Rescan specified region in block vertically. */ - /* Pass IMAP direction for the block, NOT its neighbor. */ - if((ret = scan4minutiae_horizontally(minutiae, bdata, iw, ih, - imap[blk_i], nmap[blk_i], - rescan_x, rescan_y, rescan_w, rescan_h, lfsparms))) - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - } /* Otherwise, block has already been scanned vertically. */ - } /* Otherwise, neighbor has INVALID IMAP, so ignore rescan. */ - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -2051,70 +1454,6 @@ int rescan_partial_horizontally(const int nbr_dir, MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int rescan_partial_vertically(const int nbr_dir, MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - const int *imap, const int *nmap, - const int blk_x, const int blk_y, - const int mw, const int mh, - const int scan_x, const int scan_y, - const int scan_w, const int scan_h, - const LFSPARMS *lfsparms) -{ - int nblk_i, blk_i; - int rescan_dir; - int rescan_x, rescan_y, rescan_w, rescan_h; - int ret; - - /* Neighbor will either be NORTH, SOUTH, EAST, OR WEST. */ - ret = get_nbr_block_index(&nblk_i, nbr_dir, blk_x, blk_y, mw, mh); - /* Will return: */ - /* 1. Neighbor index found == FOUND */ - /* 2. Neighbor not found == NOT_FOUND */ - /* 3. System error < 0 */ - - /* If system error ... */ - if(ret < 0) - /* Return the error code. */ - return(ret); - - /* If neighbor not found ... */ - if(ret == NOT_FOUND) - /* Nothing to do, so return normally. */ - return(0); - - /* Otherwise, neighboring block found ... */ - - /* If neighbor block is VALID... */ - if(imap[nblk_i] != INVALID_DIR){ - - /* Compute block index from current (not neighbor) block coordinates. */ - blk_i = (blk_y*mw)+blk_x; - - /* Select feature scan direction based on neighbor IMAP. */ - rescan_dir = choose_scan_direction(imap[nblk_i], - lfsparms->num_directions); - /* If new scan direction is VERTICAL... */ - if(rescan_dir == SCAN_VERTICAL){ - /* Adjust scan_x, scan_y, scan_w, scan_h for rescan. */ - if((ret = adjust_vertical_rescan(nbr_dir, &rescan_x, &rescan_y, - &rescan_w, &rescan_h, - scan_x, scan_y, scan_w, scan_h, lfsparms->blocksize))) - /* Return system error code. */ - return(ret); - /* Rescan specified region in block vertically. */ - /* Pass IMAP direction for the block, NOT its neighbor. */ - if((ret = scan4minutiae_vertically(minutiae, bdata, iw, ih, - imap[blk_i], nmap[blk_i], - rescan_x, rescan_y, rescan_w, rescan_h, lfsparms))) - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - } /* Otherwise, block has already been scanned horizontally. */ - } /* Otherwise, neighbor has INVALID IMAP, so ignore rescan. */ - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -2134,56 +1473,6 @@ int rescan_partial_vertically(const int nbr_dir, MINUTIAE *minutiae, FOUND - neighbor index exists and returned Negative - system error **************************************************************************/ -int get_nbr_block_index(int *oblk_i, const int nbr_dir, - const int blk_x, const int blk_y, const int mw, const int mh) -{ - int nx, ny, ni; - - switch(nbr_dir){ - case NORTH: - /* If neighbor doesn't exist above... */ - if((ny = blk_y-1) < 0) - /* Done, so return normally. */ - return(NOT_FOUND); - /* Get neighbor's block index. */ - ni = (ny*mw)+blk_x; - break; - case EAST: - /* If neighbor doesn't exist to the right... */ - if((nx = blk_x+1) >= mw) - /* Done, so return normally. */ - return(NOT_FOUND); - /* Get neighbor's block index. */ - ni = (blk_y*mw)+nx; - break; - case SOUTH: - /* If neighbor doesn't exist below... */ - if((ny = blk_y+1) >= mh) - /* Return normally. */ - return(NOT_FOUND); - /* Get neighbor's block index. */ - ni = (ny*mw)+blk_x; - break; - case WEST: - /* If neighbor doesn't exist to the left... */ - if((nx = blk_x-1) < 0) - /* Return normally. */ - return(NOT_FOUND); - /* Get neighbor's block index. */ - ni = (blk_y*mw)+nx; - break; - default: - fprintf(stderr, - "ERROR : get_nbr_block_index : illegal neighbor direction\n"); - return(-200); - } - - /* Assign output pointer. */ - *oblk_i = ni; - - /* Return neighbor FOUND. */ - return(FOUND); -} /************************************************************************* ************************************************************************** @@ -2206,126 +1495,6 @@ int get_nbr_block_index(int *oblk_i, const int nbr_dir, Zero - successful completion Negative - system error **************************************************************************/ -int adjust_horizontal_rescan(const int nbr_dir, int *rescan_x, int *rescan_y, - int *rescan_w, int *rescan_h, const int scan_x, const int scan_y, - const int scan_w, const int scan_h, const int blocksize) -{ - int half_blocksize, qtr_blocksize; - - /* Compute half of blocksize. */ - half_blocksize = blocksize>>1; - /* Compute quarter of blocksize. */ - qtr_blocksize = blocksize>>2; - - /* Neighbor will either be NORTH, SOUTH, EAST, OR WEST. */ - switch(nbr_dir){ - case NORTH: - /* - ************************* - * RESCAN NORTH * - * AREA * - ************************* - | | - | | - | | - | | - | | - | | - ------------------------- - */ - /* Rescan origin stays the same. */ - *rescan_x = scan_x; - *rescan_y = scan_y; - /* Rescan width stays the same. */ - *rescan_w = scan_w; - /* Rescan height is reduced to "qtr_blocksize" */ - /* if scan_h is larger. */ - *rescan_h = min(qtr_blocksize, scan_h); - break; - case EAST: - /* - ------------************* - | * * - | * * - | * E R * - | * A E * - | * S S * - | * T C * - | * A * - | * N * - | * * - | * * - ------------************* - */ - /* Rescan x-orign is set to half_blocksize from right edge of */ - /* block if scan width is larger. */ - *rescan_x = max(scan_x+scan_w-half_blocksize, scan_x); - /* Rescan y-origin stays the same. */ - *rescan_y = scan_y; - /* Rescan width is reduced to "half_blocksize" */ - /* if scan width is larger. */ - *rescan_w = min(half_blocksize, scan_w); - /* Rescan height stays the same. */ - *rescan_h = scan_h; - break; - case SOUTH: - /* - ------------------------- - | | - | | - | | - | | - | | - | | - ************************* - * RESCAN SOUTH * - * AREA * - ************************* - */ - /* Rescan x-origin stays the same. */ - *rescan_x = scan_x; - /* Rescan y-orign is set to qtr_blocksize from bottom edge of */ - /* block if scan height is larger. */ - *rescan_y = max(scan_y+scan_h-qtr_blocksize, scan_y); - /* Rescan width stays the same. */ - *rescan_w = scan_w; - /* Rescan height is reduced to "qtr_blocksize" */ - /* if scan height is larger. */ - *rescan_h = min(qtr_blocksize, scan_h); - break; - case WEST: - /* - *************------------ - * * | - * * | - * W R * | - * E E * | - * S S * | - * T C * | - * A * | - * N * | - * * | - * * | - *************------------ - */ - /* Rescan origin stays the same. */ - *rescan_x = scan_x; - *rescan_y = scan_y; - /* Rescan width is reduced to "half_blocksize" */ - /* if scan width is larger. */ - *rescan_w = min(half_blocksize, scan_w); - /* Rescan height stays the same. */ - *rescan_h = scan_h; - break; - default: - fprintf(stderr, - "ERROR : adjust_horizontal_rescan : illegal neighbor direction\n"); - return(-210); - } - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -2348,128 +1517,6 @@ int adjust_horizontal_rescan(const int nbr_dir, int *rescan_x, int *rescan_y, Zero - successful completion Negative - system error **************************************************************************/ -int adjust_vertical_rescan(const int nbr_dir, int *rescan_x, int *rescan_y, - int *rescan_w, int *rescan_h, const int scan_x, const int scan_y, - const int scan_w, const int scan_h, const int blocksize) -{ - int half_blocksize, qtr_blocksize; - - /* Compute half of blocksize. */ - half_blocksize = blocksize>>1; - /* Compute quarter of blocksize. */ - qtr_blocksize = blocksize>>2; - - /* Neighbor will either be NORTH, SOUTH, EAST, OR WEST. */ - switch(nbr_dir){ - case NORTH: - /* - ************************* - * * - * RESCAN NORTH * - * AREA * - * * - ************************* - | | - | | - | | - | | - | | - ------------------------- - */ - /* Rescan origin stays the same. */ - *rescan_x = scan_x; - *rescan_y = scan_y; - /* Rescan width stays the same. */ - *rescan_w = scan_w; - /* Rescan height is reduced to "half_blocksize" */ - /* if scan_h is larger. */ - *rescan_h = min(half_blocksize, scan_h); - break; - case EAST: - /* - ------------------******* - | * * - | * * - | * E R * - | * A E * - | * S S * - | * T C * - | * A * - | * N * - | * * - | * * - ------------------******* - */ - /* Rescan x-orign is set to qtr_blocksize from right edge of */ - /* block if scan width is larger. */ - *rescan_x = max(scan_x+scan_w-qtr_blocksize, scan_x); - /* Rescan y-origin stays the same. */ - *rescan_y = scan_y; - /* Rescan width is reduced to "qtr_blocksize" */ - /* if scan width is larger. */ - *rescan_w = min(qtr_blocksize, scan_w); - /* Rescan height stays the same. */ - *rescan_h = scan_h; - break; - case SOUTH: - /* - ------------------------- - | | - | | - | | - | | - | | - ************************* - * * - * RESCAN SOUTH * - * AREA * - * * - ************************* - */ - /* Rescan x-origin stays the same. */ - *rescan_x = scan_x; - /* Rescan y-orign is set to half_blocksize from bottom edge of */ - /* block if scan height is larger. */ - *rescan_y = max(scan_y+scan_h-half_blocksize, scan_y); - /* Rescan width stays the same. */ - *rescan_w = scan_w; - /* Rescan height is reduced to "half_blocksize" */ - /* if scan height is larger. */ - *rescan_h = min(half_blocksize, scan_h); - break; - case WEST: - /* - *******------------------ - * * | - * * | - * W R * | - * E E * | - * S S * | - * T C * | - * A * | - * N * | - * * | - * * | - *******------------------ - */ - /* Rescan origin stays the same. */ - *rescan_x = scan_x; - *rescan_y = scan_y; - /* Rescan width is reduced to "qtr_blocksize" */ - /* if scan width is larger. */ - *rescan_w = min(qtr_blocksize, scan_w); - /* Rescan height stays the same. */ - *rescan_h = scan_h; - break; - default: - fprintf(stderr, - "ERROR : adjust_vertical_rescan : illegal neighbor direction\n"); - return(-220); - } - - /* Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -2484,7 +1531,7 @@ int adjust_vertical_rescan(const int nbr_dir, int *rescan_x, int *rescan_y, cx - x-pixel coord where 3rd pattern pair of mintuia was detected cy - y-pixel coord where 3rd pattern pair of mintuia was detected y2 - y-pixel coord where 2nd pattern pair of mintuia was detected - feature_id - type of minutia (ex. index into feature_patterns[] list) + feature_id - type of minutia (ex. index into g_feature_patterns[] list) bdata - binary image data (0==while & 1==black) iw - width (in pixels) of image ih - height (in pixels) of image @@ -2498,81 +1545,6 @@ int adjust_vertical_rescan(const int nbr_dir, int *rescan_x, int *rescan_y, IGNORE - minutia is to be ignored Negative - system error **************************************************************************/ -int process_horizontal_scan_minutia(MINUTIAE *minutiae, - const int cx, const int cy, - const int x2, const int feature_id, - unsigned char *bdata, const int iw, const int ih, - const int imapval, const int nmapval, - const LFSPARMS *lfsparms) -{ - MINUTIA *minutia; - int x_loc, y_loc; - int x_edge, y_edge; - int idir, ret; - - /* Set x location of minutia point to be half way between */ - /* first position of second feature pair and position of */ - /* third feature pair. */ - x_loc = (cx + x2)>>1; - - /* Set same x location to neighboring edge pixel. */ - x_edge = x_loc; - - /* Feature location should always point to either ending */ - /* of ridge or (for bifurcations) ending of valley. */ - /* So, if detected feature is APPEARING... */ - if(g_feature_patterns[feature_id].appearing){ - /* Set y location to second scan row. */ - y_loc = cy+1; - /* Set y location of neighboring edge pixel to the first scan row. */ - y_edge = cy; - } - /* Otherwise, feature is DISAPPEARING... */ - else{ - /* Set y location to first scan row. */ - y_loc = cy; - /* Set y location of neighboring edge pixel to the second scan row. */ - y_edge = cy+1; - } - - /* If current minutia is in a high-curvature block... */ - if(nmapval == HIGH_CURVATURE){ - /* Adjust location and direction locally. */ - if((ret = adjust_high_curvature_minutia(&idir, &x_loc, &y_loc, - &x_edge, &y_edge, x_loc, y_loc, x_edge, y_edge, - bdata, iw, ih, minutiae, lfsparms))){ - /* Could be a system error or IGNORE minutia. */ - return(ret); - } - /* Otherwise, we have our high-curvature minutia attributes. */ - } - /* Otherwise, minutia is in fairly low-curvature block... */ - else{ - /* Get minutia direction based on current IMAP value. */ - idir = get_low_curvature_direction(SCAN_HORIZONTAL, - g_feature_patterns[feature_id].appearing, - imapval, lfsparms->num_directions); - } - - /* Create a minutia object based on derived attributes. */ - if((ret = create_minutia(&minutia, x_loc, y_loc, x_edge, y_edge, idir, - DEFAULT_RELIABILITY, - g_feature_patterns[feature_id].type, - g_feature_patterns[feature_id].appearing, feature_id))) - /* Return system error. */ - 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); - - /* Otherwise, return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -2587,7 +1559,7 @@ int process_horizontal_scan_minutia(MINUTIAE *minutiae, cx - x-pixel coord where 3rd pattern pair of mintuia was detected cy - y-pixel coord where 3rd pattern pair of mintuia was detected y2 - y-pixel coord where 2nd pattern pair of mintuia was detected - feature_id - type of minutia (ex. index into feature_patterns[] list) + feature_id - type of minutia (ex. index into g_feature_patterns[] list) bdata - binary image data (0==while & 1==black) iw - width (in pixels) of image ih - height (in pixels) of image @@ -2626,7 +1598,7 @@ int process_horizontal_scan_minutia_V2(MINUTIAE *minutiae, /* Feature location should always point to either ending */ /* of ridge or (for bifurcations) ending of valley. */ - /* So, if detected feature is APPEARING... */ + /* So, if detected feature is APPEARING... */ if(g_feature_patterns[feature_id].appearing){ /* Set y location to second scan row. */ y_loc = cy+1; @@ -2711,7 +1683,7 @@ int process_horizontal_scan_minutia_V2(MINUTIAE *minutiae, cx - x-pixel coord where 3rd pattern pair of mintuia was detected cy - y-pixel coord where 3rd pattern pair of mintuia was detected x2 - x-pixel coord where 2nd pattern pair of mintuia was detected - feature_id - type of minutia (ex. index into feature_patterns[] list) + feature_id - type of minutia (ex. index into g_feature_patterns[] list) bdata - binary image data (0==while & 1==black) iw - width (in pixels) of image ih - height (in pixels) of image @@ -2725,80 +1697,6 @@ int process_horizontal_scan_minutia_V2(MINUTIAE *minutiae, IGNORE - minutia is to be ignored Negative - system error **************************************************************************/ -int process_vertical_scan_minutia(MINUTIAE *minutiae, - const int cx, const int cy, - const int y2, const int feature_id, - unsigned char *bdata, const int iw, const int ih, - const int imapval, const int nmapval, - const LFSPARMS *lfsparms) -{ - MINUTIA *minutia; - int x_loc, y_loc; - int x_edge, y_edge; - int idir, ret; - - /* Feature location should always point to either ending */ - /* of ridge or (for bifurcations) ending of valley. */ - /* So, if detected feature is APPEARING... */ - if(g_feature_patterns[feature_id].appearing){ - /* Set x location to second scan column. */ - x_loc = cx+1; - /* Set x location of neighboring edge pixel to the first scan column. */ - x_edge = cx; - } - /* Otherwise, feature is DISAPPEARING... */ - else{ - /* Set x location to first scan column. */ - x_loc = cx; - /* Set x location of neighboring edge pixel to the second scan column. */ - x_edge = cx+1; - } - - /* Set y location of minutia point to be half way between */ - /* first position of second feature pair and position of */ - /* third feature pair. */ - y_loc = (cy + y2)>>1; - /* Set same y location to neighboring edge pixel. */ - y_edge = y_loc; - - /* If current minutia is in a high-curvature block... */ - if(nmapval == HIGH_CURVATURE){ - /* Adjust location and direction locally. */ - if((ret = adjust_high_curvature_minutia(&idir, &x_loc, &y_loc, - &x_edge, &y_edge, x_loc, y_loc, x_edge, y_edge, - bdata, iw, ih, minutiae, lfsparms))){ - /* Could be a system error or IGNORE minutia. */ - return(ret); - } - /* Otherwise, we have our high-curvature minutia attributes. */ - } - /* Otherwise, minutia is in fairly low-curvature block... */ - else{ - /* Get minutia direction based on current IMAP value. */ - idir = get_low_curvature_direction(SCAN_VERTICAL, - g_feature_patterns[feature_id].appearing, - imapval, lfsparms->num_directions); - } - - /* Create a minutia object based on derived attributes. */ - if((ret = create_minutia(&minutia, x_loc, y_loc, x_edge, y_edge, idir, - DEFAULT_RELIABILITY, - g_feature_patterns[feature_id].type, - g_feature_patterns[feature_id].appearing, feature_id))) - /* Return system error. */ - 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); - - /* Otherwise, return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -2813,7 +1711,7 @@ int process_vertical_scan_minutia(MINUTIAE *minutiae, cx - x-pixel coord where 3rd pattern pair of mintuia was detected cy - y-pixel coord where 3rd pattern pair of mintuia was detected x2 - x-pixel coord where 2nd pattern pair of mintuia was detected - feature_id - type of minutia (ex. index into feature_patterns[] list) + feature_id - type of minutia (ex. index into g_feature_patterns[] list) bdata - binary image data (0==while & 1==black) iw - width (in pixels) of image ih - height (in pixels) of image @@ -2844,7 +1742,7 @@ int process_vertical_scan_minutia_V2(MINUTIAE *minutiae, /* Feature location should always point to either ending */ /* of ridge or (for bifurcations) ending of valley. */ - /* So, if detected feature is APPEARING... */ + /* So, if detected feature is APPEARING... */ if(g_feature_patterns[feature_id].appearing){ /* Set x location to second scan column. */ x_loc = cx+1; @@ -2884,7 +1782,7 @@ int process_vertical_scan_minutia_V2(MINUTIAE *minutiae, /* Could be a system error or IGNORE minutia. */ return(ret); } - /* Otherwise, we have our high-curvature minutia attributes. */ + /* Otherwise, we have our high-curvature minutia attributes. */ } /* Otherwise, minutia is in fairly low-curvature block... */ else{ @@ -2959,167 +1857,6 @@ int process_vertical_scan_minutia_V2(MINUTIAE *minutiae, IGNORE - minutia point is to be ignored Negative - system error **************************************************************************/ -int adjust_high_curvature_minutia(int *oidir, int *ox_loc, int *oy_loc, - int *ox_edge, int *oy_edge, - const int x_loc, const int y_loc, - const int x_edge, const int y_edge, - unsigned char *bdata, const int iw, const int ih, - MINUTIAE *minutiae, const LFSPARMS *lfsparms) -{ - int ret; - int *contour_x, *contour_y, *contour_ex, *contour_ey, ncontour; - int min_i; - double min_theta; - int feature_pix; - int mid_x, mid_y, mid_pix; - int idir; - int half_contour, angle_edge; - - /* Set variable from parameter structure. */ - half_contour = lfsparms->high_curve_half_contour; - - /* Set edge length for computing contour's angle of curvature */ - /* to one quarter of desired pixel length of entire contour. */ - /* Ex. If half_contour==14, then contour length==29=(2X14)+1 */ - /* and angle_edge==7=(14/2). */ - angle_edge = half_contour>>1; - - /* Get the pixel value of current feature. */ - feature_pix = *(bdata + (y_loc * iw) + x_loc); - - /* Extract feature's contour. */ - if((ret = get_high_curvature_contour(&contour_x, &contour_y, - &contour_ex, &contour_ey, &ncontour, half_contour, - x_loc, y_loc, x_edge, y_edge, bdata, iw, ih))){ - /* Returns with: */ - /* 1. Successful or empty contour == 0 */ - /* If contour is empty, then contour lists are not allocated. */ - /* 2. Contour forms loop == LOOP_FOUND */ - /* 3. Sysetm error < 0 */ - - /* If the contour forms a loop... */ - if(ret == LOOP_FOUND){ - - /* If the order of the contour is clockwise, then the loops's */ - /* contour pixels are outside the corresponding edge pixels. We */ - /* definitely do NOT want to fill based on the feature pixel in */ - /* this case, because it is OUTSIDE the loop. For now we will */ - /* ignore the loop and the minutia that triggered its tracing. */ - /* It is likely that other minutia on the loop will be */ - /* detected that create a contour on the "inside" of the loop. */ - /* There is another issue here that could be addressed ... */ - /* It seems that many/multiple minutia are often detected within */ - /* the same loop, which currently requires retracing the loop, */ - /* locating minutia on opposite ends of the major axis of the */ - /* loop, and then determining that the minutia have already been */ - /* entered into the minutiae list upon processing the very first */ - /* minutia detected in the loop. There is a lot of redundant */ - /* work being done here! */ - /* Is_loop_clockwise takes a default value to be returned if the */ - /* routine is unable to determine the direction of the contour. */ - /* In this case, we want to IGNORE the loop if we can't tell its */ - /* direction so that we do not inappropriately fill the loop, so */ - /* we are passing the default value TRUE. */ - if((ret = is_loop_clockwise(contour_x, contour_y, ncontour, TRUE))){ - /* Deallocate contour lists. */ - free_contour(contour_x, contour_y, contour_ex, contour_ey); - /* If we had a system error... */ - if(ret < 0) - /* Return the error code. */ - return(ret); - /* Otherwise, loop is clockwise, so return IGNORE. */ - return(IGNORE); - } - - /* Otherwise, process the clockwise-ordered contour of the loop */ - /* as it may contain minutia. If no minutia found, then it is */ - /* filled in. */ - ret = process_loop(minutiae, contour_x, contour_y, - contour_ex, contour_ey, ncontour, - bdata, iw, ih, lfsparms); - /* Returns with: */ - /* 1. Successful processing of loop == 0 */ - /* 2. System error < 0 */ - - /* Deallocate contour lists. */ - free_contour(contour_x, contour_y, contour_ex, contour_ey); - - /* If loop processed successfully ... */ - if(ret == 0) - /* Then either a minutia pair was extracted or the loop was */ - /* filled. Either way we want to IGNORE the minutia that */ - /* started the whole loop processing in the beginning. */ - return(IGNORE); - - /* Otherwise, there was a system error. */ - /* Return the resulting code. */ - return(ret); - } - - /* Otherwise not a loop, so get_high_curvature_contour incurred */ - /* a system error. Return the error code. */ - return(ret); - } - - /* If contour is empty ... then contour lists were not allocated, so */ - /* simply return IGNORE. The contour comes back empty when there */ - /* were not a sufficient number of points found on the contour. */ - if(ncontour == 0) - return(IGNORE); - - /* Otherwise, there are contour points to process. */ - - /* Given the contour, determine the point of highest curvature */ - /* (ie. forming the minimum angle between contour walls). */ - if((ret = min_contour_theta(&min_i, &min_theta, angle_edge, - contour_x, contour_y, ncontour))){ - /* Deallocate contour lists. */ - free_contour(contour_x, contour_y, contour_ex, contour_ey); - /* Returns IGNORE or system error. Either way */ - /* free the contour and return the code. */ - return(ret); - } - - /* If the minimum theta found along the contour is too large... */ - if(min_theta >= lfsparms->max_high_curve_theta){ - /* Deallocate contour lists. */ - free_contour(contour_x, contour_y, contour_ex, contour_ey); - /* Reject the high-curvature minutia, and return IGNORE. */ - return(IGNORE); - } - - /* Test to see if interior of curvature is OK. Compute midpoint */ - /* between left and right points symmetrically distant (angle_edge */ - /* pixels) from the contour's point of minimum theta. */ - mid_x = (contour_x[min_i-angle_edge] + contour_x[min_i+angle_edge])>>1; - mid_y = (contour_y[min_i-angle_edge] + contour_y[min_i+angle_edge])>>1; - mid_pix = *(bdata + (mid_y * iw) + mid_x); - /* If the interior pixel value is not the same as the feature's... */ - if(mid_pix != feature_pix){ - /* Deallocate contour lists. */ - free_contour(contour_x, contour_y, contour_ex, contour_ey); - /* Reject the high-curvature minutia and return IGNORE. */ - return(IGNORE); - } - - /* Compute new direction based on line connecting adjusted feature */ - /* location and the midpoint in the feature's interior. */ - idir = line2direction(contour_x[min_i], contour_y[min_i], - mid_x, mid_y, lfsparms->num_directions); - - /* Set minutia location to minimum theta position on the contour. */ - *oidir = idir; - *ox_loc = contour_x[min_i]; - *oy_loc = contour_y[min_i]; - *ox_edge = contour_ex[min_i]; - *oy_edge = contour_ey[min_i]; - - /* Deallocate contour buffers. */ - free_contour(contour_x, contour_y, contour_ex, contour_ey); - - /*Return normally. */ - return(0); -} /************************************************************************* ************************************************************************** @@ -3464,48 +2201,3 @@ int get_low_curvature_direction(const int scan_dir, const int appearing, return(idir); } -/************************************************************************* -************************************************************************** -#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 - Return Code: - Zero - successful completion - Negative - system error -**************************************************************************/ -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; -} - diff --git a/libfprint/nbis/mindtct/morph.c b/libfprint/nbis/mindtct/morph.c index d4ec85f..41978f1 100644 --- a/libfprint/nbis/mindtct/morph.c +++ b/libfprint/nbis/mindtct/morph.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -69,13 +90,13 @@ void erode_charimage_2(unsigned char *inp, unsigned char *out, { int row, col; unsigned char *itr = inp, *otr = out; - + memcpy(out, inp, iw*ih); - + /* for true pixels. kill pixel if there is at least one false neighbor */ for ( row = 0 ; row < ih ; row++ ) for ( col = 0 ; col < iw ; col++ ) - { + { if (*itr) /* erode only operates on true pixels */ { /* more efficient with C's left to right evaluation of */ @@ -87,7 +108,7 @@ void erode_charimage_2(unsigned char *inp, unsigned char *out, *otr = 0; } itr++ ; otr++; - } + } } /************************************************************************* @@ -109,13 +130,13 @@ void dilate_charimage_2(unsigned char *inp, unsigned char *out, { int row, col; unsigned char *itr = inp, *otr = out; - + memcpy(out, inp, iw*ih); - + /* for all pixels. set pixel if there is at least one true neighbor */ for ( row = 0 ; row < ih ; row++ ) for ( col = 0 ; col < iw ; col++ ) - { + { if (!*itr) /* pixel is already true, neighbors irrelevant */ { /* more efficient with C's left to right evaluation of */ @@ -127,7 +148,7 @@ void dilate_charimage_2(unsigned char *inp, unsigned char *out, *otr = 1; } itr++ ; otr++; - } + } } /************************************************************************* @@ -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 */ return failcode; /* use plane geometry and return code. */ - else + 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 */ return failcode; /* use plane geometry and return code. */ - else + 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 */ return failcode; /* use plane geometry and return code. */ - else + 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 */ return failcode; /* use plane geometry and return code. */ - else + return *(ptr- 1); } diff --git a/libfprint/nbis/mindtct/quality.c b/libfprint/nbis/mindtct/quality.c index 5dcabc2..db2bc5c 100644 --- a/libfprint/nbis/mindtct/quality.c +++ b/libfprint/nbis/mindtct/quality.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -39,12 +60,11 @@ identified are necessarily the best available for the purpose. combined_minutia_quality() grayscale_reliability() get_neighborhood_stats() + reliability_fr_quality_map() ***********************************************************************/ #include -#include -#include #include #include @@ -172,120 +192,6 @@ int gen_quality_map(int **oqmap, int *direction_map, int *low_contrast_map, 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 @@ -391,3 +297,137 @@ int combined_minutia_quality(MINUTIAE *minutiae, 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 +************************************************************************/ diff --git a/libfprint/nbis/mindtct/remove.c b/libfprint/nbis/mindtct/remove.c index 6863ecf..faa6607 100644 --- a/libfprint/nbis/mindtct/remove.c +++ b/libfprint/nbis/mindtct/remove.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -35,15 +56,21 @@ identified are necessarily the best available for the purpose. *********************************************************************** ROUTINES: + remove_false_minutia() remove_false_minutia_V2() remove_holes() remove_hooks() + remove_hooks_islands_overlaps() remove_islands_and_lakes() remove_malformations() - remove_near_invblock_V2() + remove_near_invblocks() + remove_near_invblocks_V2() + remove_pointing_invblock() remove_pointing_invblock_V2() remove_overlaps() + remove_pores() remove_pores_V2() + remove_or_adjust_side_minutiae() remove_or_adjust_side_minutiae_V2() ***********************************************************************/ @@ -52,6 +79,125 @@ identified are necessarily the best available for the purpose. #include #include +/************************************************************************* +************************************************************************** +#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. @@ -68,7 +214,7 @@ identified are necessarily the best available for the purpose. Zero - successful completion Negative - system error **************************************************************************/ -static int remove_holes(MINUTIAE *minutiae, +int remove_holes(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -139,7 +285,7 @@ static int remove_holes(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -static int remove_hooks(MINUTIAE *minutiae, +int remove_hooks(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -341,6 +487,29 @@ static int remove_hooks(MINUTIAE *minutiae, 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 @@ -362,7 +531,7 @@ static int remove_hooks(MINUTIAE *minutiae, Zero - successful completion 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, const LFSPARMS *lfsparms) { @@ -616,7 +785,7 @@ static int remove_islands_and_lakes(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -static int remove_malformations(MINUTIAE *minutiae, +int remove_malformations(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, int *low_flow_map, const int mw, const int mh, const LFSPARMS *lfsparms) @@ -647,7 +816,7 @@ static int remove_malformations(MINUTIAE *minutiae, /* Return error code. */ return(ret); } - + /* If trace was not possible OR loop found OR */ /* contour is incomplete ... */ if((ret == IGNORE) || @@ -803,6 +972,26 @@ static int remove_malformations(MINUTIAE *minutiae, 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 @@ -821,7 +1010,7 @@ static int remove_malformations(MINUTIAE *minutiae, Zero - successful completion 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) { int i, ret; @@ -1032,6 +1221,26 @@ static int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map, 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 @@ -1050,7 +1259,7 @@ static int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map, Zero - successful completion 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, const LFSPARMS *lfsparms) { @@ -1140,7 +1349,7 @@ static int remove_pointing_invblock_V2(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -static int remove_overlaps(MINUTIAE *minutiae, +int remove_overlaps(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -1350,32 +1559,20 @@ static int remove_overlaps(MINUTIAE *minutiae, 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: attempts to detect and remove those false minutiae that -#cat: belong to image edge +#cat: remove_pores - Attempts to detect and remove minutia points located on +#cat: pore-shaped valleys. 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 @@ -1383,125 +1580,6 @@ static void mark_minutiae_in_range(MINUTIAE *minutiae, int *to_remove, int x, in Zero - successful completion 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 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, int *direction_map, int *low_flow_map, int *high_curve_map, const int mw, const int mh, @@ -1777,7 +1855,7 @@ static int remove_pores_V2(MINUTIAE *minutiae, /* counter-clockwise scan and step along a */ /* specified number of steps (ex. 8). */ ret = trace_contour(&contour_x, &contour_y, - &contour_ex, &contour_ey, &ncontour, + &contour_ex, &contour_ey, &ncontour, lfsparms->pores_steps_bwd, qx, qy, qx, qy, qex, qey, SCAN_COUNTER_CLOCKWISE, bdata, iw, ih); @@ -1896,6 +1974,26 @@ static int remove_pores_V2(MINUTIAE *minutiae, 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 @@ -1918,7 +2016,7 @@ static int remove_pores_V2(MINUTIAE *minutiae, Zero - successful completion 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, int *direction_map, const int mw, const int mh, const LFSPARMS *lfsparms) @@ -2164,104 +2262,3 @@ static int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, 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); -} - diff --git a/libfprint/nbis/mindtct/ridges.c b/libfprint/nbis/mindtct/ridges.c index 9fb110f..b5b7f2c 100644 --- a/libfprint/nbis/mindtct/ridges.c +++ b/libfprint/nbis/mindtct/ridges.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -52,156 +73,135 @@ identified are necessarily the best available for the purpose. /************************************************************************* ************************************************************************** -#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. +#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: - 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 + 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: - 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 + minutiae - list of minutiae augmented with neighbors and ridge counts Return Code: - Zero - successful completion - Negative - system error + Zero - successful completion + Negative - system error **************************************************************************/ -static 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 count_minutiae_ridges(MINUTIAE *minutiae, + unsigned char *bdata, const int iw, const int ih, + const LFSPARMS *lfsparms) { + int ret; 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); + 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); } - /* 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); + /* Remove any duplicate minutia points from the list. */ + if((ret = rm_dup_minutiae(minutiae))){ + return(ret); } - /* 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--; + /* 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); + } } - /* 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: 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. +#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: - 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 + 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: - 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 + minutiae - minutia augmented with neighbors and ridge counts Return Code: - Zero - successful completion - Negative - system error + Zero - successful completion + Negative - system error **************************************************************************/ -static 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) +int count_minutia_ridges(const int first, MINUTIAE *minutiae, + unsigned char *bdata, const int iw, const int ih, + const LFSPARMS *lfsparms) { - double dist2; - MINUTIA *minutia1, *minutia2; - int pos, last_nbr; + int i, ret, *nbr_list, *nbr_nridges, nnbrs; - /* Compute position of maximum last neighbor stored. */ - last_nbr = max_nbrs - 1; + /* 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); + } - /* Assigne temporary minutia pointers. */ - minutia1 = minutiae->list[first]; - minutia2 = minutiae->list[second]; + print2log("NBRS FOUND: %d,%d = %d\n", minutiae->list[first]->x, + minutiae->list[first]->y, nnbrs); - /* 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. */ + /* If no neighors found ... */ + if(nnbrs == 0){ + /* Then no list returned and no ridges to count. */ 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 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) { int ret, second, last_nbr; @@ -312,6 +312,160 @@ static int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs, 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 @@ -331,7 +485,7 @@ static int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs, Zero - successful completion 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) { double *join_thetas, theta; @@ -369,7 +523,164 @@ static int sort_neighbors(int *nbr_list, const int nnbrs, const int first, free(join_thetas); /* Return normally. */ - 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); } /************************************************************************* @@ -395,7 +706,7 @@ static int sort_neighbors(int *nbr_list, const int nnbrs, const int first, TRUE - pixel pair transition 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, 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 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, unsigned char *bdata, const int iw, const int ih, const int max_ridge_steps) @@ -482,7 +793,7 @@ static int validate_ridge_crossing(const int ridge_start, const int ridge_end, /* position is on the white (of a black to white transition) and */ /* the ridge start is on the black (of a black to white trans), */ /* so the edge trace needs to look for the what pixel (not the */ - /* black one) of the ridge start transition. */ + /* black one) of the ridge start transition. */ ret = trace_contour(&contour_x, &contour_y, &contour_ex, &contour_ey, &ncontour, max_ridge_steps, @@ -535,298 +846,7 @@ static int validate_ridge_crossing(const int ridge_start, const int ridge_end, /* Otherwise, second trace returned IGNORE or ridge start found. */ } /* Otherwise, first trace returned IGNORE or ridge start found. */ - + /* If we get here, then we failed to validate a ridge crossing. */ 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); -} - diff --git a/libfprint/nbis/mindtct/shape.c b/libfprint/nbis/mindtct/shape.c index 4e8ea8f..f189a99 100644 --- a/libfprint/nbis/mindtct/shape.c +++ b/libfprint/nbis/mindtct/shape.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -36,12 +57,12 @@ identified are necessarily the best available for the purpose. ROUTINES: alloc_shape() free_shape() + dump_shape() shape_from_contour() sort_row_on_x() ***********************************************************************/ #include -#include #include /************************************************************************* @@ -60,7 +81,7 @@ identified are necessarily the best available for the purpose. Zero - Shape successfully allocated and initialized 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) { 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: right on X. +#cat: dump_shape - Takes an initialized shape structure and dumps its contents +#cat: as formatted text to the specified open file pointer. Input: - row - row structure to be sorted + shape - shape structure to be dumped 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); } +/************************************************************************* +************************************************************************** +#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); +} + diff --git a/libfprint/nbis/mindtct/sort.c b/libfprint/nbis/mindtct/sort.c index 3a0f47c..9080ce0 100644 --- a/libfprint/nbis/mindtct/sort.c +++ b/libfprint/nbis/mindtct/sort.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -43,7 +64,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include #include /************************************************************************* @@ -104,29 +124,6 @@ int sort_indices_int_inc(int **optr, int *ranks, const int num) Zero - successful completion 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); -} /************************************************************************* ************************************************************************** @@ -176,7 +173,7 @@ void bubble_sort_int_inc_2(int *ranks, int *items, const int len) } /* Decrement the ending index. */ n--; - } + } } /************************************************************************* @@ -228,7 +225,7 @@ void bubble_sort_double_inc_2(double *ranks, int *items, const int len) } /* Decrement the ending index. */ n--; - } + } } /*************************************************************************** @@ -271,7 +268,7 @@ void bubble_sort_double_dec_2(double *ranks, int *items, const int len) } } n--; - } + } } /************************************************************************* @@ -315,6 +312,6 @@ void bubble_sort_int_inc(int *ranks, const int len) } /* Decrement the ending index. */ n--; - } + } } diff --git a/libfprint/nbis/mindtct/util.c b/libfprint/nbis/mindtct/util.c index a4e98da..1662e62 100644 --- a/libfprint/nbis/mindtct/util.c +++ b/libfprint/nbis/mindtct/util.c @@ -1,26 +1,47 @@ /******************************************************************************* -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. +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. -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. +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 @@ -47,7 +68,6 @@ identified are necessarily the best available for the purpose. ***********************************************************************/ #include -#include #include /************************************************************************* @@ -142,7 +162,7 @@ int minmaxs(int **ominmax_val, int **ominmax_type, int **ominmax_i, int i, diff, state, start, loc; int *minmax_val, *minmax_type, *minmax_i, minmax_alloc, minmax_num; - + /* Determine maximum length for allocation of buffers. */ /* If there are fewer than 3 items ... */ if(num < 3){ @@ -427,27 +447,6 @@ int in_int_list(const int item, const int *list, const int len) Zero - successful completion 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); -} /************************************************************************* ************************************************************************** @@ -561,7 +560,7 @@ int line2direction(const int fx, const int fy, /* Make sure on range [0..(ndirsX2)]. */ idir %= full_ndirs; - /* Return the integer direction. */ + /* Return the integer direction. */ return(idir); } diff --git a/libfprint/nbis/mindtct/xytreps.c b/libfprint/nbis/mindtct/xytreps.c new file mode 100644 index 0000000..7310f98 --- /dev/null +++ b/libfprint/nbis/mindtct/xytreps.c @@ -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 +#include + +/************************************************************************* +************************************************************************** +#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 +**************************************************************************/ +