diff --git a/.gitignore b/.gitignore index a026bd3..8a4f119 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ depcomp install-sh .deps .libs +compile diff --git a/libfprint/Makefile.am b/libfprint/Makefile.am index 800125f..c537b76 100644 --- a/libfprint/Makefile.am +++ b/libfprint/Makefile.am @@ -33,10 +33,8 @@ NBIS_SRC = \ nbis/mindtct/matchpat.c \ nbis/mindtct/minutia.c \ nbis/mindtct/morph.c \ - nbis/mindtct/mytime.c \ nbis/mindtct/quality.c \ nbis/mindtct/remove.c \ - nbis/mindtct/results.c \ nbis/mindtct/ridges.c \ nbis/mindtct/shape.c \ nbis/mindtct/sort.c \ diff --git a/libfprint/nbis/include/lfs.h b/libfprint/nbis/include/lfs.h index b37147e..f260c48 100644 --- a/libfprint/nbis/include/lfs.h +++ b/libfprint/nbis/include/lfs.h @@ -701,24 +701,15 @@ 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, @@ -763,12 +754,6 @@ extern void fix_edge_pixel_pair(int *, int *, int *, int *, unsigned char *, const int, const int); /* detect.c */ -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 *, @@ -779,13 +764,8 @@ extern int lfs_detect_minutiae_V2(MINUTIAE **, 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 *); @@ -818,7 +798,6 @@ 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); @@ -833,8 +812,6 @@ 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, @@ -872,16 +849,8 @@ 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 *, @@ -901,10 +870,6 @@ 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 *); @@ -935,7 +900,6 @@ 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); @@ -954,9 +918,6 @@ 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, @@ -1083,58 +1044,6 @@ 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 *); /* ridges.c */ extern int count_minutiae_ridges(MINUTIAE *, @@ -1159,11 +1068,8 @@ extern int validate_ridge_crossing(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); diff --git a/libfprint/nbis/include/mytime.h b/libfprint/nbis/include/mytime.h deleted file mode 100644 index 4abb1ac..0000000 --- a/libfprint/nbis/include/mytime.h +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. - -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. - -*******************************************************************************/ - -#ifndef _MYTIME_H -#define _MYTIME_H - -/* this file needed to support timer and ticks */ -/* UPDATED: 03/16/2005 by MDG */ - -#ifdef TIMER -#include -#include -#endif - -#ifdef TIMER -#define set_timer(_timer_); \ - { \ - _timer_ = (unsigned long)ticks(); -#else -#define set_timer(_timer_); -#endif - -#ifdef TIMER -#define time_accum(_timer_, _var_); \ - _var_ += ((unsigned long)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 unsigned long ticks(void); -extern int ticksPerSec(void); - -extern unsigned long total_timer; -extern float total_time; - -extern unsigned long imap_timer; -extern float imap_time; - -extern unsigned long bin_timer; -extern float bin_time; - -extern unsigned long minutia_timer; -extern float minutia_time; - -extern unsigned long rm_minutia_timer; -extern float rm_minutia_time; - -extern unsigned long ridge_count_timer; -extern float ridge_count_time; - -#endif - diff --git a/libfprint/nbis/mindtct/binar.c b/libfprint/nbis/mindtct/binar.c index 2c4355c..916d56e 100644 --- a/libfprint/nbis/mindtct/binar.c +++ b/libfprint/nbis/mindtct/binar.c @@ -36,12 +36,9 @@ identified are necessarily the best available for the purpose. *********************************************************************** ROUTINES: - binarize() binarize_V2() - binarize_image() binarize_image_V2() dirbinarize() - isobinarize() ***********************************************************************/ @@ -49,58 +46,6 @@ identified are necessarily the best available for the purpose. #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 -**************************************************************************/ -int binarize(unsigned char **optr, int *ow, int *oh, - unsigned char *pdata, const int pw, const int ph, - int *nmap, const int mw, const int mh, - const ROTGRIDS *dirbingrids, const LFSPARMS *lfsparms) -{ - unsigned char *bdata; - int i, bw, bh, ret; /* return code */ - - /* 1. Binarize the padded input image using NMAP information. */ - if((ret = binarize_image(&bdata, &bw, &bh, pdata, pw, ph, - nmap, mw, mh, lfsparms->blocksize, - dirbingrids, lfsparms->isobin_grid_dim))){ - return(ret); - } - - /* 2. Fill black and white holes in binary image. */ - /* LFS scans the binary image, filling holes, 3 times. */ - for(i = 0; i < lfsparms->num_fill_holes; i++) - fill_holes(bdata, bw, bh); - - /* Return binarized input image. */ - *optr = bdata; - *ow = bw; - *oh = bh; - return(0); -} - /************************************************************************* ************************************************************************** #cat: binarize_V2 - Takes a padded grayscale input image and its associated @@ -156,89 +101,6 @@ 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 -**************************************************************************/ -int binarize_image(unsigned char **optr, int *ow, int *oh, - unsigned char *pdata, const int pw, const int ph, - const int *nmap, const int mw, const int mh, - const int imap_blocksize, const ROTGRIDS *dirbingrids, - const int isobin_grid_dim) -{ - int ix, iy, bw, bh, bx, by, nmapval; - unsigned char *bdata, *bptr; - unsigned char *pptr, *spptr; - - /* Compute dimensions of "unpadded" binary image results. */ - bw = pw - (dirbingrids->pad<<1); - bh = ph - (dirbingrids->pad<<1); - - bdata = (unsigned char *)malloc(bw*bh*sizeof(unsigned char)); - if(bdata == (unsigned char *)NULL){ - fprintf(stderr, "ERROR : binarize_image : malloc : bdata\n"); - return(-110); - } - - bptr = bdata; - spptr = pdata + (dirbingrids->pad * pw) + dirbingrids->pad; - for(iy = 0; iy < bh; iy++){ - /* Set pixel pointer to start of next row in grid. */ - pptr = spptr; - for(ix = 0; ix < bw; ix++){ - /* Compute which block the current pixel is in. */ - bx = (int)(ix/imap_blocksize); - by = (int)(iy/imap_blocksize); - /* Get corresponding value in NMAP */ - nmapval = *(nmap + (by*mw) + bx); - /* If current block has no neighboring blocks with */ - /* VALID directions ... */ - if(nmapval == NO_VALID_NBRS) - /* Set binary pixel to white (255). */ - *bptr = WHITE_PIXEL; - /* Otherwise, if block's NMAP has a valid direction ... */ - else if(nmapval >= 0) - /* Use directional binarization based on NMAP direction. */ - *bptr = dirbinarize(pptr, nmapval, dirbingrids); - else - /* Otherwise, the block's NMAP is either INVALID or */ - /* HIGH-CURVATURE, so use isotropic binarization. */ - *bptr = isobinarize(pptr, pw, ph, isobin_grid_dim); - /* Bump input and output pixel pointers. */ - pptr++; - bptr++; - } - /* Bump pointer to the next row in padded input image. */ - spptr += pw; - } - - *optr = bdata; - *ow = bw; - *oh = bh; - return(0); -} - /************************************************************************* ************************************************************************** #cat: binarize_image_V2 - Takes a grayscale input image and its associated @@ -385,71 +247,3 @@ 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 -**************************************************************************/ -int isobinarize(unsigned char *pptr, const int pw, const int ph, - const int isobin_grid_dim) -{ - unsigned char *sptr, *cptr; - int px, py; - int radius; - int bsum; - double drad; - - /* Initialize grid pixel sum to zero. */ - bsum = 0; - /* Compute radius from current pixel based on isobin_grid_dim. */ - drad = (isobin_grid_dim - 1)/(double)2.0; - /* Need to truncate precision so that answers are consistent */ - /* on different computer architectures when rounding doubles. */ - drad = trunc_dbl_precision(drad, TRUNC_SCALE); - radius = sround(drad); - /* Set pointer to origin of grid centered on the current pixel. */ - sptr = pptr - (radius*pw) - radius; - - /* For each row in the grid ... */ - for(py = 0; py < isobin_grid_dim; py++){ - /* Set pixel pointer to start of next row in grid. */ - cptr = sptr; - /* For each column in the grid ... */ - for(px = 0; px < isobin_grid_dim; px++){ - /* Accumulate next pixel in the grid. */ - bsum += *cptr; - /* Bump pixel pointer. */ - cptr++; - } - /* Bump to the start of the next row in the grid. */ - sptr += pw; - } - - /* If current (center) pixel when treated as an average for the */ - /* entire grid is less than the total pixel sum of the grid ... */ - if((*pptr * isobin_grid_dim * isobin_grid_dim) < bsum) - /* Set the binary pixel to BLACK. */ - return(BLACK_PIXEL); - else - /* Otherwise, set the binary pixel to WHITE. */ - return(WHITE_PIXEL); -} diff --git a/libfprint/nbis/mindtct/detect.c b/libfprint/nbis/mindtct/detect.c index 3f56738..3b05d21 100644 --- a/libfprint/nbis/mindtct/detect.c +++ b/libfprint/nbis/mindtct/detect.c @@ -35,7 +35,6 @@ identified are necessarily the best available for the purpose. *********************************************************************** ROUTINES: - lfs_detect_minutiae() lfs_detect_minutiae_V2() ***********************************************************************/ @@ -43,330 +42,8 @@ identified are necessarily the best available for the purpose. #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 -**************************************************************************/ -int lfs_detect_minutiae(MINUTIAE **ominutiae, - int **oimap, int **onmap, int *omw, int *omh, - unsigned char **obdata, int *obw, int *obh, - unsigned char *idata, const int iw, const int ih, - const LFSPARMS *lfsparms) -{ - unsigned char *pdata, *bdata; - int pw, ph, bw, bh; - DIR2RAD *dir2rad; - DFTWAVES *dftwaves; - ROTGRIDS *dftgrids; - ROTGRIDS *dirbingrids; - int *imap, *nmap, mw, mh; - int ret, maxpad; - MINUTIAE *minutiae; - - set_timer(total_timer); - - /******************/ - /* INITIALIZATION */ - /******************/ - - /* If LOG_REPORT defined, open log report file. */ - if((ret = open_logfile())) - /* If system error, exit with error code. */ - return(ret); - - /* Determine the maximum amount of image padding required to support */ - /* LFS processes. */ - maxpad = get_max_padding(lfsparms->blocksize, - lfsparms->dirbin_grid_w, lfsparms->dirbin_grid_h, - lfsparms->isobin_grid_dim); - - /* Initialize lookup table for converting integer IMAP directions */ - /* to angles in radians. */ - if((ret = init_dir2rad(&dir2rad, lfsparms->num_directions))){ - /* Free memory allocated to this point. */ - return(ret); - } - - /* Initialize wave form lookup tables for DFT analyses. */ - /* used for direction binarization. */ - if((ret = init_dftwaves(&dftwaves, dft_coefs, lfsparms->num_dft_waves, - lfsparms->blocksize))){ - /* Free memory allocated to this point. */ - free_dir2rad(dir2rad); - return(ret); - } - - /* Initialize lookup table for pixel offsets to rotated grids */ - /* used for DFT analyses. */ - if((ret = init_rotgrids(&dftgrids, iw, ih, maxpad, - lfsparms->start_dir_angle, lfsparms->num_directions, - lfsparms->blocksize, lfsparms->blocksize, - RELATIVE2ORIGIN))){ - /* Free memory allocated to this point. */ - free_dir2rad(dir2rad); - free_dftwaves(dftwaves); - return(ret); - } - - /* Pad input image based on max padding. */ - if(maxpad > 0){ /* May not need to pad at all */ - if((ret = pad_uchar_image(&pdata, &pw, &ph, idata, iw, ih, - maxpad, lfsparms->pad_value))){ - /* Free memory allocated to this point. */ - free_dir2rad(dir2rad); - free_dftwaves(dftwaves); - free_rotgrids(dftgrids); - return(ret); - } - } - else{ - /* If padding is unnecessary, then copy the input image. */ - pdata = (unsigned char *)malloc(iw*ih); - if(pdata == (unsigned char *)NULL){ - /* Free memory allocated to this point. */ - free_dir2rad(dir2rad); - free_dftwaves(dftwaves); - free_rotgrids(dftgrids); - fprintf(stderr, "ERROR : lfs_detect_minutiae : malloc : pdata\n"); - return(-430); - } - memcpy(pdata, idata, iw*ih); - pw = iw; - ph = ih; - } - - /* Scale input image to 6 bits [0..63] */ - /* !!! Would like to remove this dependency eventualy !!! */ - /* But, the DFT computations will need to be changed, and */ - /* could not get this work upon first attempt. */ - bits_8to6(pdata, pw, ph); - - print2log("\nINITIALIZATION AND PADDING DONE\n"); - - /******************/ - /* IMAP */ - /******************/ - set_timer(imap_timer); - - /* Generate IMAP for the input image. */ - if((ret = gen_imap(&imap, &mw, &mh, pdata, pw, ph, dir2rad, - dftwaves, dftgrids, lfsparms))){ - /* Free memory allocated to this point. */ - free_dir2rad(dir2rad); - free_dftwaves(dftwaves); - free_rotgrids(dftgrids); - free(pdata); - return(ret); - } - - free_dir2rad(dir2rad); - free_dftwaves(dftwaves); - free_rotgrids(dftgrids); - - print2log("\nIMAP DONE\n"); - - /* Generate NMAP from the IMAP of the input image. */ - if((ret = gen_nmap(&nmap, imap, mw, mh, lfsparms))){ - /* Free memory allocated to this point. */ - free(pdata); - free(imap); - return(ret); - } - - print2log("\nNMAP 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. */ - if((ret = init_rotgrids(&dirbingrids, iw, ih, maxpad, - lfsparms->start_dir_angle, lfsparms->num_directions, - lfsparms->dirbin_grid_w, lfsparms->dirbin_grid_h, - RELATIVE2CENTER))){ - /* Free memory allocated to this point. */ - free(pdata); - free(imap); - free(nmap); - return(ret); - } - - /* Binarize input image based on NMAP information. */ - if((ret = binarize(&bdata, &bw, &bh, pdata, pw, ph, nmap, mw, mh, - dirbingrids, lfsparms))){ - /* Free memory allocated to this point. */ - free(pdata); - free(imap); - free(nmap); - free_rotgrids(dirbingrids); - return(ret); - } - free_rotgrids(dirbingrids); - - /* Check dimension of binary image. If they are different from */ - /* the input image, then ERROR. */ - if((iw != bw) || (ih != bh)){ - /* Free memory allocated to this point. */ - free(pdata); - free(imap); - free(nmap); - free(bdata); - fprintf(stderr, - "ERROR : lfs_detect_minutiae : binary image has bad dimensions : %d, %d\n", - bw, bh); - return(-431); - } - - 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]. */ - gray2bin(1, 1, 0, bdata, iw, ih); - - /* Allocate list of maximum number of minutia pointers. */ - if((ret = alloc_minutiae(&minutiae, MAX_MINUTIAE))){ - return(ret); - } - - /* Detect the minutiae in the binarized image. */ - if((ret = detect_minutiae(minutiae, bdata, iw, ih, imap, nmap, mw, mh, - lfsparms))){ - /* Free memory allocated to this point. */ - free(pdata); - free(imap); - free(nmap); - free(bdata); - return(ret); - } - - time_accum(minutia_timer, minutia_time); - - set_timer(rm_minutia_timer); - - if((ret = remove_false_minutia(minutiae, bdata, iw, ih, nmap, mw, mh, - lfsparms))){ - /* Free memory allocated to this point. */ - free(pdata); - free(imap); - free(nmap); - free(bdata); - free_minutiae(minutiae); - return(ret); - } - - 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); - free(imap); - free(nmap); - free(bdata); - free_minutiae(minutiae); - return(ret); - } - - - print2log("\nNEIGHBOR RIDGE COUNT DONE\n"); - - time_accum(ridge_count_timer, ridge_count_time); - - /******************/ - /* WRAP-UP */ - /******************/ - - /* Convert 8-bit binary image [0,1] to 8-bit */ - /* grayscale binary image [0,255]. */ - gray2bin(1, 255, 0, bdata, iw, ih); - - /* Deallocate working memory. */ - free(pdata); - - /* Assign results to output pointers. */ - *oimap = imap; - *onmap = nmap; - *omw = mw; - *omh = mh; - *obdata = bdata; - *obw = bw; - *obh = bh; - *ominutiae = minutiae; - - time_accum(total_timer, total_time); - - /******************/ - /* PRINT TIMINGS */ - /******************/ - /* These Timings will print when TIMER is defined. */ - /* print IMAP generation timing statistics */ - print_time(stderr, "TIMER: IMAP 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); - - return(0); -} - /************************************************************************* #cat: lfs_detect_minutiae_V2 - Takes a grayscale fingerprint image (of #cat: arbitrary size), and returns a set of image block maps, @@ -421,8 +98,6 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, int ret, maxpad; MINUTIAE *minutiae; - set_timer(total_timer); - /******************/ /* INITIALIZATION */ /******************/ @@ -505,7 +180,6 @@ 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, @@ -525,12 +199,9 @@ 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. */ @@ -582,12 +253,9 @@ 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]. */ @@ -612,10 +280,6 @@ 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))){ @@ -632,13 +296,9 @@ 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); @@ -653,8 +313,6 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, print2log("\nNEIGHBOR RIDGE COUNT DONE\n"); - time_accum(ridge_count_timer, ridge_count_time); - /******************/ /* WRAP-UP */ /******************/ @@ -678,28 +336,6 @@ 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); diff --git a/libfprint/nbis/mindtct/dft.c b/libfprint/nbis/mindtct/dft.c index 1159fa1..af13653 100644 --- a/libfprint/nbis/mindtct/dft.c +++ b/libfprint/nbis/mindtct/dft.c @@ -47,6 +47,84 @@ identified are necessarily the best available for the purpose. #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. @@ -121,80 +199,105 @@ int dft_dir_powers(double **powers, unsigned char *pdata, /************************************************************************* ************************************************************************** -#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. +#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: - 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 + 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: - rowsums - the resulting vector of pixel row sums + 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 sum_rot_block_rows(int *rowsums, const unsigned char *blkptr, - const int *grid_offsets, const int blocksize) +static void get_max_norm(double *powmax, int *powmax_dir, + double *pownorm, const double *power_vector, const int ndirs) { - int ix, iy, gi; + int dir; + double max_v, powsum; + int max_i; + double powmean; - /* Initialize rotation offset index. */ - gi = 0; + /* Find max power value and store corresponding direction */ + max_v = power_vector[0]; + max_i = 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++; + /* 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: 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 +#cat: sort_dft_waves - Creates a ranked list of DFT wave form statistics +#cat: by sorting on the normalized squared maximum power. 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) + 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: - power - the computed DFT power for the given wave form at the - given orientation within the image block + 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 **************************************************************************/ -void dft_power(double *power, const int *rowsums, - const DFTWAVE *wave, const int wavelen) +static int sort_dft_waves(int *wis, const double *powmaxs, const double *pownorms, + const int nstats) { int i; - double cospart, sinpart; + double *pownorms2; - /* 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]); + /* 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); } - /* Power is the sum of the squared cos and sin components */ - *power = (cospart * cospart) + (sinpart * sinpart); + 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); } /************************************************************************* @@ -253,106 +356,3 @@ 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/init.c b/libfprint/nbis/mindtct/init.c index 4414165..50dc0d7 100644 --- a/libfprint/nbis/mindtct/init.c +++ b/libfprint/nbis/mindtct/init.c @@ -37,7 +37,6 @@ 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() @@ -243,80 +242,6 @@ 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 -**************************************************************************/ -int get_max_padding(const int imap_blocksize, - const int dirbin_grid_w, const int dirbin_grid_h, - const int isobin_grid_dim) -{ - int dft_pad, dirbin_pad, isobin_pad, max_pad; - double diag; - double pad; - - /* Compute pad required for rotated blocks used in DFT analyses. */ - diag = sqrt((double)(2.0 * imap_blocksize * imap_blocksize)); - /* Compute pad as difference between the IMAP blocksize */ - /* and the diagonal distance of the block. */ - /* Assumption: all block origins reside in valid/allocated memory. */ - /* DFT grids are computed with pixel offsets RELATIVE2ORIGIN. */ - pad = (diag-imap_blocksize)/(double)2.0; - /* Need to truncate precision so that answers are consistent */ - /* on different computer architectures when rounding doubles. */ - pad = trunc_dbl_precision(pad, TRUNC_SCALE); - dft_pad = sround(pad); - - /* Compute pad required for rotated blocks used in directional */ - /* binarization. */ - diag = sqrt((double)((dirbin_grid_w*dirbin_grid_w)+ - (dirbin_grid_h*dirbin_grid_h))); - /* Assumption: all grid centers reside in valid/allocated memory. */ - /* dirbin grids are computed with pixel offsets RELATIVE2CENTER. */ - pad = (diag-1)/(double)2.0; - /* Need to truncate precision so that answers are consistent */ - /* on different computer architectures when rounding doubles. */ - pad = trunc_dbl_precision(pad, TRUNC_SCALE); - dirbin_pad = sround(pad); - - /* Compute pad required for grids used in isotropic binarization. */ - pad = (isobin_grid_dim - 1)/(double)2.0; - /* Need to truncate precision so that answers are consistent */ - /* on different computer architectures when rounding doubles. */ - pad = trunc_dbl_precision(pad, TRUNC_SCALE); - isobin_pad = sround((isobin_grid_dim - 1)/(double)2.0); - - max_pad = max(dft_pad, dirbin_pad); - max_pad = max(max_pad, isobin_pad); - - /* Return the maximum of the three required paddings. This padding will */ - /* be sufficiently large for all three purposes, so that padding of the */ - /* input image will only be required once. */ - return(max_pad); -} - /************************************************************************* ************************************************************************** #cat: get_max_padding_V2 - Deterines the maximum amount of image pixel padding diff --git a/libfprint/nbis/mindtct/loop.c b/libfprint/nbis/mindtct/loop.c index 1e84c46..9e15e95 100644 --- a/libfprint/nbis/mindtct/loop.c +++ b/libfprint/nbis/mindtct/loop.c @@ -46,8 +46,6 @@ identified are necessarily the best available for the purpose. get_loop_aspect() fill_loop() fill_partial_row() - flood_loop() - flood_fill4() ***********************************************************************/ #include @@ -499,6 +497,107 @@ 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 @@ -845,103 +944,39 @@ int process_loop_V2(MINUTIAE *minutiae, /************************************************************************* ************************************************************************** -#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. +#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: - 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 + 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: - 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 + bdata - 8-bit image data with partial row filled. **************************************************************************/ -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) +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) { - int halfway, limit; - int i, j; - double dist; - double min_dist, max_dist; - int min_i, max_i, min_j, max_j; + int x; + unsigned char *bptr; - /* Compute half the perimeter of the loop. */ - halfway = ncontour>>1; + /* Set pixel pointer to starting x-coord on current row. */ + bptr = bdata+(y*iw)+frx; - /* 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; + /* 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++; } - - /* 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; } /************************************************************************* @@ -1075,154 +1110,3 @@ 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 -**************************************************************************/ -void flood_loop(const int *contour_x, const int *contour_y, - const int ncontour, unsigned char *bdata, - const int iw, const int ih) -{ - int feature_pix, fill_pix; - int i; - - /* Get the pixel value of the minutia feauture. This is */ - /* the pixel value we wish to replace with the flood. */ - feature_pix = *(bdata + (contour_y[0] * iw) + contour_x[0]); - - /* Flip the feature pixel value to the value we want to */ - /* fill with and send this value to the flood routine. */ - fill_pix = !feature_pix; - - /* Flood-fill interior of contour using a 4-neighbor fill. */ - /* We are using a 4-neighbor fill because the contour was */ - /* collected using 8-neighbors, and the 4-neighbor fill */ - /* will NOT escape the 8-neighbor based contour. */ - /* The contour passed must be guarenteed to be complete for */ - /* the flood-fill to work properly. */ - /* We are initiating a flood-fill from each point on the */ - /* contour to make sure complex patterns get filled in. */ - /* The complex patterns we are concerned about are those */ - /* that "pinch" the interior of the feature off due to */ - /* skipping "exposed" corners along the contour. */ - /* Simple shapes will fill upon invoking the first contour */ - /* pixel, and the subsequent calls will immediately return */ - /* as their seed pixel will have already been flipped. */ - for(i = 0; i < ncontour; i++){ - /* Start the recursive flooding. */ - flood_fill4(fill_pix, contour_x[i], contour_y[i], - bdata, iw, ih); - } -} - -/************************************************************************* -************************************************************************** -#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 3050c5c..6f49e3c 100644 --- a/libfprint/nbis/mindtct/maps.c +++ b/libfprint/nbis/mindtct/maps.c @@ -46,7 +46,6 @@ 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() @@ -59,7 +58,6 @@ identified are necessarily the best available for the purpose. average_8nbr_dir() num_valid_8nbrs() smooth_imap() - gen_nmap() vorticity() accum_nbr_vorticity() curvature() @@ -930,75 +928,6 @@ int gen_high_curve_map(int **ohcmap, int *direction_map, 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 -**************************************************************************/ -int gen_imap(int **optr, int *ow, int *oh, - unsigned char *pdata, const int pw, const int ph, - const DIR2RAD *dir2rad, const DFTWAVES *dftwaves, - const ROTGRIDS *dftgrids, const LFSPARMS *lfsparms) -{ - int *imap, mw, mh, iw, ih; - int *blkoffs; - int ret; /* return code */ - - /* 1. Compute block offsets for the entire image, accounting for pad */ - /* Block_offsets() assumes square block (grid), so ERROR otherwise. */ - if(dftgrids->grid_w != dftgrids->grid_h){ - fprintf(stderr, "ERROR : gen_imap : DFT grids must be square\n"); - return(-60); - } - /* Compute unpadded image dimensions. */ - iw = pw - (dftgrids->pad<<1); - ih = ph - (dftgrids->pad<<1); - if((ret = block_offsets(&blkoffs, &mw, &mh, iw, ih, - dftgrids->pad, dftgrids->grid_w))){ - return(ret); - } - - /* 2. Generate initial imap */ - if((ret = gen_initial_imap(&imap, blkoffs, mw, mh, pdata, pw, ph, - dftwaves, dftgrids, lfsparms))){ - /* Free memory allocated to this point. */ - free(blkoffs); - return(ret); - } - - /* 3. Remove IMAP directions that are inconsistent with neighbors */ - remove_incon_dirs(imap, mw, mh, dir2rad, lfsparms); - - /* 4. Smooth imap values with their neighbors */ - smooth_imap(imap, mw, mh, dir2rad, lfsparms); - - /* Deallocate working memory. */ - free(blkoffs); - - *optr = imap; - *ow = mw; - *oh = mh; - return(0); -} - /************************************************************************* ************************************************************************** #cat: gen_initial_imap - Creates an initial IMAP from the given input image. @@ -2160,100 +2089,6 @@ void smooth_imap(int *imap, const int mw, const int mh, } } -/************************************************************************* -************************************************************************** -#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. - - 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 -**************************************************************************/ -int gen_nmap(int **optr, int *imap, const int mw, const int mh, - const LFSPARMS *lfsparms) -{ - int *nmap, mapsize; - int *nptr, *iptr; - int bx, by; - int nvalid, cmeasure, vmeasure; - - mapsize = mw*mh; - nmap = (int *)malloc(mapsize * sizeof(int)); - if(nmap == (int *)NULL){ - fprintf(stderr, "ERROR: gen_nmap : malloc : nmap\n"); - return(-120); - } - - nptr = nmap; - iptr = imap; - /* Foreach row in IMAP ... */ - for(by = 0; by < mh; by++){ - /* Foreach column in IMAP ... */ - for(bx = 0; bx < mw; bx++){ - /* Count number of valid neighbors around current block ... */ - nvalid = num_valid_8nbrs(imap, bx, by, mw, mh); - /* If block has no valid neighbors ... */ - if(nvalid == 0) - /* Set NMAP value to NO VALID NEIGHBORS */ - *nptr = NO_VALID_NBRS; - else{ - /* If current IMAP value is INVALID ... */ - if(*iptr == INVALID_DIR){ - /* If not enough VALID neighbors ... */ - if(nvalid < lfsparms->vort_valid_nbr_min){ - /* Set NMAP value to INVALID */ - *nptr = INVALID_DIR; - } - else{ - /* Otherwise measure vorticity of neighbors. */ - vmeasure = vorticity(imap, bx, by, mw, mh, - lfsparms->num_directions); - /* If vorticity too low ... */ - if(vmeasure < lfsparms->highcurv_vorticity_min) - *nptr = INVALID_DIR; - else - /* Otherwise high-curvature area (Ex. core or delta). */ - *nptr = HIGH_CURVATURE; - } - } - /* Otherwise VALID IMAP value ... */ - else{ - /* Measure curvature around the VALID IMAP block. */ - cmeasure = curvature(imap, bx, by, mw, mh, - lfsparms->num_directions); - /* If curvature is too high ... */ - if(cmeasure >= lfsparms->highcurv_curvature_min) - *nptr = HIGH_CURVATURE; - else - /* Otherwise acceptable amount of curature, so assign */ - /* VALID IMAP value to NMAP. */ - *nptr = *iptr; - } - } /* end else (nvalid > 0) */ - /* BUMP IMAP and NMAP pointers. */ - iptr++; - nptr++; - - } /* bx */ - } /* by */ - - *optr = nmap; - return(0); -} - /************************************************************************* ************************************************************************** #cat: vorticity - Measures the amount of cummulative curvature incurred diff --git a/libfprint/nbis/mindtct/minutia.c b/libfprint/nbis/mindtct/minutia.c index 29f505c..5193fc8 100644 --- a/libfprint/nbis/mindtct/minutia.c +++ b/libfprint/nbis/mindtct/minutia.c @@ -37,7 +37,6 @@ identified are necessarily the best available for the purpose. ROUTINES: alloc_minutiae() realloc_minutiae() - detect_minutiae() detect_minutiae_V2() update_minutiae() update_minutiae_V2() @@ -144,99 +143,6 @@ 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 -**************************************************************************/ -int detect_minutiae(MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - const int *imap, const int *nmap, const int mw, const int mh, - const LFSPARMS *lfsparms) -{ - int blk_i, blk_x, blk_y; - int scan_x, scan_y, scan_w, scan_h; - int scan_dir; - int ret; - - /* Start with first block in IMAP. */ - blk_i = 0; - - /* Start with first scan line in image. */ - scan_y = 0; - - /* Foreach row of blocks in IMAP... */ - for(blk_y = 0; blk_y < mh; blk_y++){ - /* Reset to beginning of new block row. */ - scan_x = 0; - /* Foreach block in current IMAP row... */ - for(blk_x = 0; blk_x < mw; blk_x++){ - - /* If IMAP is VALID ... */ - if(imap[blk_i] != INVALID_DIR){ - /* Choose the feature scan direction based on the block's */ - /* VALID IMAP direction. The scan direction will either */ - /* be HORIZONTAL or VERTICAL. */ - scan_dir = choose_scan_direction(imap[blk_i], - lfsparms->num_directions); - /* Set width of scan region. The image may not be an even */ - /* multiple of "blocksize" in width and height, so we must */ - /* account for this. */ - /* Bump right by "blocksize" pixels, but not beyond the */ - /* image boundary. */ - scan_w = min(scan_x+lfsparms->blocksize, iw); - /* Make the resulting width relative to the region's starting */ - /* x-pixel column. */ - scan_w -= scan_x; - /* Bump down by "blocksize" pixels, but not beyond the */ - /* image boundary. */ - scan_h = min(scan_y+lfsparms->blocksize, ih); - /* Make the resulting height relative to the region's starting */ - /* y-pixel row. */ - scan_h -= scan_y; - /* Scan the defined region for minutia features. */ - if((ret = scan4minutiae(minutiae, bdata, iw, ih, - imap, nmap, blk_x, blk_y, mw, mh, - scan_x, scan_y, scan_w, scan_h, scan_dir, - lfsparms))){ - /* Return code may be: */ - /* 1. ret<0 (implying system error) */ - return(ret); - } - - } /* Otherwise, IMAP is INVALID, so ignore the block. This seems */ - /* quite drastic! */ - - /* Advance to the next IMAP block in the row in the image. */ - scan_x += lfsparms->blocksize; - /* Advance to the next IMAP block in the row. */ - blk_i++; - } /* End foreach blk_x */ - /* Advance to the next IMAP row in the image. */ - scan_y += lfsparms->blocksize; - } /* End foreach blk_y */ - - /* Return normally. */ - return(0); -} - /************************************************************************* ************************************************************************** #cat: detect_minutiae_V2 - Takes a binary image and its associated diff --git a/libfprint/nbis/mindtct/mytime.c b/libfprint/nbis/mindtct/mytime.c deleted file mode 100644 index 296503a..0000000 --- a/libfprint/nbis/mindtct/mytime.c +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. - -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. - -*******************************************************************************/ - -/*********************************************************************** - LIBRARY: LFS - NIST Latent Fingerprint System - - FILE: MYTIME.C - AUTHOR: Michael D. Garris - DATE: 03/16/1999 - - Contains global variable definitions used to record timings by - the NIST Latent Fingerprint System (LFS). -***********************************************************************/ - -/* Total time: including all initializations */ -/* : excluding all I/O except for required HO39 input image */ -/* (This is done to contrast the fact that the NIST GENHO39 */ -/* eliminates the need for this extra read.) */ -unsigned long total_timer; -float total_time = 0.0; /* time accumulator */ - -/* IMAP generation time: excluding initialization */ -unsigned long imap_timer; -float imap_time = 0.0; /* time accumulator */ - -/* Binarization time: excluding initialization */ -unsigned long bin_timer; -float bin_time = 0.0; /* time accumulator */ - -/* Minutia Detection time */ -unsigned long minutia_timer; -float minutia_time = 0.0; /* time accumulator */ - -/* Minutia Removal time */ -unsigned long rm_minutia_timer; -float rm_minutia_time = 0.0; /* time accumulator */ - -/* Neighbor Ridge Counting time */ -unsigned long ridge_count_timer; -float ridge_count_time = 0.0; /* time accumulator */ diff --git a/libfprint/nbis/mindtct/remove.c b/libfprint/nbis/mindtct/remove.c index e3ddbef..592cb72 100644 --- a/libfprint/nbis/mindtct/remove.c +++ b/libfprint/nbis/mindtct/remove.c @@ -35,15 +35,14 @@ 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_hooks_islands_lakes_overlaps() remove_islands_and_lakes() remove_malformations() - remove_near_invblocks() - remove_near_invblocks_V2() + remove_near_invblock() + remove_near_invblock_V2() remove_pointing_invblock() remove_pointing_invblock_V2() remove_overlaps() @@ -58,169 +57,6 @@ 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 -**************************************************************************/ -int remove_false_minutia(MINUTIAE *minutiae, - unsigned char *bdata, const int iw, const int ih, - int *nmap, const int mw, const int mh, - const LFSPARMS *lfsparms) -{ - int ret; - - /* Sort minutiae points top-to-bottom and left-to-right. */ - if((ret = sort_minutiae_y_x(minutiae, iw, ih))){ - return(ret); - } - - if((ret = link_minutiae(minutiae, bdata, iw, ih, nmap, mw, mh, lfsparms))){ - return(ret); - } - - if((ret = remove_hooks_islands_lakes_overlaps(minutiae, bdata, iw, ih, - lfsparms))){ - return(ret); - } - - if((ret = remove_pointing_invblock(minutiae, nmap, mw, mh, lfsparms))){ - return(ret); - } - - if((ret = remove_holes(minutiae, bdata, iw, ih, lfsparms))){ - return(ret); - } - - if((ret = remove_or_adjust_side_minutiae(minutiae, - bdata, iw, ih, lfsparms))){ - return(ret); - } - - if((ret = remove_near_invblock(minutiae, nmap, mw, mh, lfsparms))){ - return(ret); - } - - if((ret = remove_pores(minutiae, bdata, iw, ih, nmap, mw, mh, lfsparms))){ - return(ret); - } - - 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); - } - - return(0); -} - /************************************************************************* ************************************************************************** #cat: remove_holes - Removes minutia points on small loops around valleys. @@ -237,7 +73,7 @@ int remove_false_minutia_V2(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_holes(MINUTIAE *minutiae, +static int remove_holes(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -308,7 +144,7 @@ int remove_holes(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_hooks(MINUTIAE *minutiae, +static int remove_hooks(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -532,7 +368,7 @@ int remove_hooks(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_hooks_islands_lakes_overlaps(MINUTIAE *minutiae, +static int remove_hooks_islands_lakes_overlaps(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -827,7 +663,7 @@ int remove_hooks_islands_lakes_overlaps(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_islands_and_lakes(MINUTIAE *minutiae, +static int remove_islands_and_lakes(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -1081,7 +917,7 @@ int remove_islands_and_lakes(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_malformations(MINUTIAE *minutiae, +static 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) @@ -1287,7 +1123,7 @@ int remove_malformations(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_near_invblock(MINUTIAE *minutiae, int *nmap, +static int remove_near_invblock(MINUTIAE *minutiae, int *nmap, const int mw, const int mh, const LFSPARMS *lfsparms) { int i, ret; @@ -1517,7 +1353,7 @@ int remove_near_invblock(MINUTIAE *minutiae, int *nmap, Zero - successful completion Negative - system error **************************************************************************/ -int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map, +static int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map, const int mw, const int mh, const LFSPARMS *lfsparms) { int i, ret; @@ -1747,7 +1583,7 @@ int remove_near_invblock_V2(MINUTIAE *minutiae, int *direction_map, Zero - successful completion Negative - system error **************************************************************************/ -int remove_pointing_invblock(MINUTIAE *minutiae, +static int remove_pointing_invblock(MINUTIAE *minutiae, int *nmap, const int mw, const int mh, const LFSPARMS *lfsparms) { @@ -1839,7 +1675,7 @@ int remove_pointing_invblock(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_pointing_invblock_V2(MINUTIAE *minutiae, +static int remove_pointing_invblock_V2(MINUTIAE *minutiae, int *direction_map, const int mw, const int mh, const LFSPARMS *lfsparms) { @@ -1929,7 +1765,7 @@ int remove_pointing_invblock_V2(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_overlaps(MINUTIAE *minutiae, +static int remove_overlaps(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -2160,7 +1996,7 @@ int remove_overlaps(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_pores(MINUTIAE *minutiae, +static int remove_pores(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, int *nmap, const int mw, const int mh, const LFSPARMS *lfsparms) @@ -2548,7 +2384,7 @@ int remove_pores(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_pores_V2(MINUTIAE *minutiae, +static 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, @@ -2936,7 +2772,7 @@ int remove_pores_V2(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_or_adjust_side_minutiae(MINUTIAE *minutiae, +static int remove_or_adjust_side_minutiae(MINUTIAE *minutiae, unsigned char *bdata, const int iw, const int ih, const LFSPARMS *lfsparms) { @@ -3156,7 +2992,7 @@ int remove_or_adjust_side_minutiae(MINUTIAE *minutiae, Zero - successful completion Negative - system error **************************************************************************/ -int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, +static 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) @@ -3402,3 +3238,99 @@ 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); + } + + return(0); +} + diff --git a/libfprint/nbis/mindtct/results.c b/libfprint/nbis/mindtct/results.c deleted file mode 100644 index 1f8f1db..0000000 --- a/libfprint/nbis/mindtct/results.c +++ /dev/null @@ -1,682 +0,0 @@ -/******************************************************************************* - -License: -This software was developed at the National Institute of Standards and -Technology (NIST) by employees of the Federal Government in the course -of their official duties. Pursuant to title 17 Section 105 of the -United States Code, this software is not subject to copyright protection -and is in the public domain. NIST assumes no responsibility whatsoever for -its use by other parties, and makes no guarantees, expressed or implied, -about its quality, reliability, or any other characteristic. - -Disclaimer: -This software was developed to promote biometric standards and biometric -technology testing for the Federal Government in accordance with the USA -PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. -Specific hardware and software products identified in this software were used -in order to perform the software development. In no case does such -identification imply recommendation or endorsement by the National Institute -of Standards and Technology, nor does it imply that the products and equipment -identified are necessarily the best available for the purpose. - -*******************************************************************************/ - -/*********************************************************************** - LIBRARY: LFS - NIST Latent Fingerprint System - - FILE: RESULTS.C - AUTHOR: Michael D. Garris - DATE: 03/16/1999 - UPDATED: 10/04/1999 Version 2 by MDG - 09/14/2004 - UPDATED: 03/16/2005 by MDG - - Contains routines useful in visualizing intermediate and final - results when exercising the NIST Latent Fingerprint System (LFS). - -*********************************************************************** - ROUTINES: - write_text_results() - write_minutiae_XYTQ() - dump_map() - drawmap() - drawmap2() - drawblocks() - drawrotgrid() - dump_link_table() - -***********************************************************************/ - -#include -#include -#include -#include -#include -#include - -/************************************************************************* -************************************************************************** -#cat: write_text_results - Takes LFS results including minutiae and image -#cat: maps and writes them to separate formatted text files. - - Input: - oroot - root pathname for output files - m1flag - if flag set, write (X,Y,T)'s out to "*.xyt" file according - to M1 (ANSI INCITS 378-2004) minutiae representation - - M1 Rep: - 1. pixel origin top left - 2. direction pointing up the ridge ending or - bifurcaiton valley - NIST Internal Rep: - 1. pixel origin bottom left - 2. direction pointing out and away from the - ridge ending or bifurcation valley - - iw - image pixel width - ih - image pixel height - minutiae - structure containing the detected minutiae - quality_map - integrated image quality map - direction_map - direction map - low_contrast_map - low contrast map - low_flow_map - low ridge flow map - high_curve_map - high curvature map - map_w - width (in blocks) of image maps - map_h - height (in blocks) of image maps - Return Code: - Zero - successful completion - Negative - system error -**************************************************************************/ -int write_text_results(char *oroot, const int m1flag, - const int iw, const int ih, - const MINUTIAE *minutiae, int *quality_map, - int *direction_map, int *low_contrast_map, - int *low_flow_map, int *high_curve_map, - const int map_w, const int map_h) -{ - FILE *fp; - int ret; - char ofile[MAXPATHLEN]; - - /* 1. Write Minutiae results to text file ".min". */ - /* XYT's written in LFS native representation: */ - /* 1. pixel coordinates with origin top-left */ - /* 2. 11.25 degrees quantized integer orientation */ - /* on range [0..31] */ - /* 3. minutiae reliability on range [0.0 .. 1.0] */ - /* with 0.0 lowest and 1.0 highest reliability */ - sprintf(ofile, "%s.%s", oroot, MIN_TXT_EXT); - if((fp = fopen(ofile, "wb")) == (FILE *)NULL){ - fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile); - return(-2); - } - /* Print out Image Dimensions Header */ - /* !!!! Image dimension header added 09-13-04 !!!! */ - fprintf(fp, "Image (w,h) %d %d\n", iw, ih); - /* Print text report from the structure containing detected minutiae. */ - dump_minutiae(fp, minutiae); - if(fclose(fp)){ - fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile); - return(-3); - } - - /* 2. Write just minutiae XYT's & Qualities to text */ - /* file ".xyt". */ - /* */ - /* A. If M1 flag set: */ - /* XYTQ's written according to M1 (ANSI INCITS */ - /* 378-2004) representation: */ - /* 1. pixel coordinates with origin top-left */ - /* 2. orientation in degrees on range [0..360] */ - /* with 0 pointing east and increasing counter */ - /* clockwise */ - /* 3. direction pointing up the ridge ending or */ - /* bifurcaiton valley */ - /* 4. minutiae qualities on integer range [0..100] */ - /* (non-standard) */ - /* */ - /* B. If M1 flag NOT set: */ - /* XYTQ's written 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) */ - /* 4. minutiae qualities on integer range [0..100] */ - /* (non-standard) */ - sprintf(ofile, "%s.%s", oroot, XYT_EXT); - if(m1flag){ - if((ret = write_minutiae_XYTQ(ofile, M1_XYT_REP, minutiae, iw, ih))){ - return(ret); - } - } - else{ - if((ret = write_minutiae_XYTQ(ofile, NIST_INTERNAL_XYT_REP, - minutiae, iw, ih))){ - return(ret); - } - } - - /* 3. Write Integrated Quality Map results to text file. */ - sprintf(ofile, "%s.%s", oroot, QUALITY_MAP_EXT); - if((fp = fopen(ofile, "wb")) == (FILE *)NULL){ - fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile); - return(-4); - } - /* Print a text report from the map. */ - dump_map(fp, quality_map, map_w, map_h); - if(fclose(fp)){ - fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile); - return(-5); - } - - /* 4. Write Direction Map results to text file. */ - sprintf(ofile, "%s.%s", oroot, DIRECTION_MAP_EXT); - if((fp = fopen(ofile, "wb")) == (FILE *)NULL){ - fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile); - return(-6); - } - /* Print a text report from the map. */ - dump_map(fp, direction_map, map_w, map_h); - if(fclose(fp)){ - fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile); - return(-7); - } - - /* 5. Write Low Contrast Map results to text file. */ - sprintf(ofile, "%s.%s", oroot, LOW_CONTRAST_MAP_EXT); - if((fp = fopen(ofile, "wb")) == (FILE *)NULL){ - fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile); - return(-8); - } - /* Print a text report from the map. */ - dump_map(fp, low_contrast_map, map_w, map_h); - if(fclose(fp)){ - fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile); - return(-9); - } - - /* 6. Write Low Flow Map results to text file. */ - sprintf(ofile, "%s.%s", oroot, LOW_FLOW_MAP_EXT); - if((fp = fopen(ofile, "wb")) == (FILE *)NULL){ - fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile); - return(-10); - } - /* Print a text report from the map. */ - dump_map(fp, low_flow_map, map_w, map_h); - if(fclose(fp)){ - fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile); - return(-11); - } - - /* 7. Write High Curvature Map results to text file. */ - sprintf(ofile, "%s.%s", oroot, HIGH_CURVE_MAP_EXT); - if((fp = fopen(ofile, "wb")) == (FILE *)NULL){ - fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile); - return(-12); - } - /* Print a text report from the map. */ - dump_map(fp, high_curve_map, map_w, map_h); - if(fclose(fp)){ - fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile); - return(-13); - } - - /* Return normally. */ - return(0); -} - -/************************************************************************* -************************************************************************** -#cat: write_minutiae_XYTQ - Write just minutiae XYT's & Qualities to text -#cat: file according to the specified mintuiae represenation - - Input: - ofile - output file name - reptype - specifies XYT output representation - minutiae - structure containing a list of LFS detected minutiae - iw - width (in pixels) of the input image - ih - height (in pixels) of the input image - Return Code: - Zero - successful completion - Negative - system error -**************************************************************************/ -int write_minutiae_XYTQ(char *ofile, const int reptype, - const MINUTIAE *minutiae, const int iw, const int ih) -{ - FILE *fp; - int i, ox, oy, ot, oq; - MINUTIA *minutia; - - /* A. If M1 flag set: */ - /* XYTQ's written according to M1 (ANSI INCITS */ - /* 378-2004) representation: */ - /* 1. pixel coordinates with origin top-left */ - /* 2. orientation in degrees on range [0..360] */ - /* with 0 pointing east and increasing counter */ - /* clockwise */ - /* 3. direction pointing up the ridge ending or */ - /* bifurcaiton valley */ - /* 4. minutiae qualities on integer range [0..100] */ - /* (non-standard) */ - /* */ - /* B. If M1 flag NOT set: */ - /* XYTQ's written 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) */ - /* 4. minutiae qualities on integer range [0..100] */ - /* (non-standard) */ - - if((fp = fopen(ofile, "wb")) == (FILE *)NULL){ - fprintf(stderr, "ERROR : write_minutiae_XYTQ : fopen : %s\n", ofile); - return(-2); - } - - for(i = 0; i < minutiae->num; i++){ - minutia = minutiae->list[i]; - - switch(reptype){ - case M1_XYT_REP: - lfs2m1_minutia_XYT(&ox, &oy, &ot, minutia); - break; - case NIST_INTERNAL_XYT_REP: - lfs2nist_minutia_XYT(&ox, &oy, &ot, minutia, iw, ih); - break; - default: - fprintf(stderr, "ERROR : write_minutiae_XYTQ : "); - fprintf(stderr, "Invalid XYT representation type = %d\n", reptype); - fclose(fp); - return(-4); - } - - oq = sround(minutia->reliability * 100.0); - - fprintf(fp, "%d %d %d %d\n", ox, oy, ot, oq); - } - - - if(fclose(fp)){ - fprintf(stderr, "ERROR : write_minutiae_XYTQ : fopen : %s\n", ofile); - return(-5); - } - - return(0); -} - -/************************************************************************* -************************************************************************** -#cat: dump_map - Prints a text report to the specified open file pointer -#cat: of the integer values in a 2D integer vector. - - Input: - fpout - open file pointer - map - vector of integer directions (-1 ==> invalid direction) - mw - width (number of blocks) of map vector - mh - height (number of blocks) of map vector -**************************************************************************/ -void dump_map(FILE *fpout, int *map, const int mw, const int mh) -{ - int mx, my; - int *iptr; - - /* Simply print the map matrix out to the specified file pointer. */ - iptr = map; - for(my = 0; my < mh; my++){ - for(mx = 0; mx < mw; mx++){ - fprintf(fpout, "%2d ", *iptr++); - } - fprintf(fpout, "\n"); - } -} - -/************************************************************************* -************************************************************************** -#cat: drawmap - Draws integer direction vectors over their respective blocks -#cat: of an input image. Note that the input image is modified -#cat: upon return form this routine. - - Input: - imap - computed vector of integer directions. (-1 ==> invalid) - mw - width (in blocks) of the map - mh - height (in blocks) of the map - idata - input image data to be annotated - iw - width (in pixels) of the input image - ih - height (in pixels) of the input image - rotgrids - structure containing the rotated pixel grid offsets - draw_pixel - pixel intensity to be used when drawing on the image - Output: - idata - input image contains the results of the annoatation - Return Code: - Zero - successful completion - Negative - system error -**************************************************************************/ -int drawmap(int *imap, const int mw, const int mh, - unsigned char *idata, const int iw, const int ih, - const ROTGRIDS *dftgrids, const int draw_pixel) -{ - int bi, *iptr; - double dy, dx, xincr, yincr; - int cbxy; - int i, xyoffset; - unsigned char *cptr, *lptr, *rptr, *eptr; - double theta, pi_incr; - int *blkoffs, bw, bh; - int ret; /* return code */ - - /* Compute block offsets into the input image. */ - /* Block_offsets() assumes square block (grid), so ERROR otherwise. */ - if(dftgrids->grid_w != dftgrids->grid_h){ - fprintf(stderr, "ERROR : drawmap : DFT grids must be square\n"); - return(-130); - } - if((ret = block_offsets(&blkoffs, &bw, &bh, iw, ih, - dftgrids->pad, dftgrids->grid_w))){ - return(ret); - } - - if((bw != mw) || (bh != mh)){ - /* Free memory allocated to this point. */ - free(blkoffs); - fprintf(stderr, - "ERROR : drawmap : block dimensions between map and image do not match\n"); - return(-131); - } - - cbxy = dftgrids->grid_w>>1; - pi_incr = M_PI/(double)dftgrids->ngrids; - - eptr = idata + (ih*iw); - iptr = imap; - /* Foreach block in image ... */ - for(bi = 0; bi < mw*mh; bi++){ - - /* If valid direction for block ... */ - if(*iptr != INVALID_DIR){ - - /* Get slope components of direction angle */ - theta = dftgrids->start_angle + (*iptr * pi_incr); - dx = cos(theta); - dy = sin(theta); - - /* Draw line rotated by the direction angle and centered */ - /* on the block. */ - /* Check if line is perfectly vertical ... */ - if(dx == 0){ - /* Draw vertical line starting at top of block shifted */ - /* over to horizontal center of the block. */ - lptr = idata + blkoffs[bi] + cbxy; - for(i = 0; i < dftgrids->grid_w; i++){ - if((lptr > idata) && (lptr < eptr)){ - *lptr = draw_pixel; - } - lptr += iw; - } - } - else{ - cptr = idata + blkoffs[bi] + (cbxy*iw) + cbxy; - - /* Draw center pixel */ - *cptr = draw_pixel; - - /* Draw left and right half of line */ - xincr = dx; - yincr = dy; - for(i = 0; i < cbxy; i++){ - xyoffset = (sround(yincr)*iw) + sround(xincr); - rptr = cptr + xyoffset; - if((rptr > idata) && (rptr < eptr)){ - *rptr = draw_pixel; - } - lptr = cptr - xyoffset; - if((lptr > idata) && (lptr < eptr)){ - *lptr = draw_pixel; - } - xincr += dx; - yincr += dy; - } - } - } - iptr++; - } - - /* Deallocate working memory */ - free(blkoffs); - - return(0); -} - -/************************************************************************* -************************************************************************** -#cat: drawmap2 - Draws integer direction vectors over their respective blocks -#cat: of an input image. Note that the input image is modified -#cat: upon return form this routine. In this version of the -#cat: routine, offsets to the origin of each block in the image -#cat: must be precomputed and passed in. - - Input: - imap - computed vector of integer directions. (-1 ==> invalid) - blkoffs - list of pixel offsets to the origin of each block in the - image from which the map was computed - mw - width (in blocks) of the map - mh - height (in blocks) of the map - pdata - input image data to be annotated - pw - width (in pixels) of the input image - ph - height (in pixels) of the input image - start_angle - the angle (in radians) that the direction 0 points in - ndirs - number of directions within a half circle - blocksize - the dimensions (in pixels) of each block - Output: - pdata - input image contains the results of the annoatation -**************************************************************************/ -void drawmap2(int *imap, const int *blkoffs, const int mw, const int mh, - unsigned char *pdata, const int pw, const int ph, - const double start_angle, const int ndirs, const int blocksize) -{ - int bi, *iptr; - double dy, dx, xincr, yincr; - int cbxy; - int i, xyoffset; - unsigned char *cptr, *lptr, *rptr, *eptr; - double theta, pi_incr; - - cbxy = blocksize>>1; - pi_incr = M_PI/(double)ndirs; - - eptr = pdata + (pw*ph); - iptr = imap; - /* Foreach block in image ... */ - for(bi = 0; bi < mw*mh; bi++){ - - /* If valid direction for block ... */ - if(*iptr != INVALID_DIR){ - - /* Get slope components of direction angle */ - theta = start_angle + (*iptr * pi_incr); - dx = cos((double)theta); - dy = sin((double)theta); - - /* Draw line rotated by the direction angle and centered */ - /* on the block. */ - /* Check if line is perfectly vertical ... */ - if(dx == 0){ - /* Draw vertical line starting at top of block shifted */ - /* over to horizontal center of the block. */ - lptr = pdata + blkoffs[bi] + cbxy; - for(i = 0; i < blocksize; i++){ - if((lptr > pdata) && (lptr < eptr)) - *lptr = 255; - lptr += pw; - } - } - else{ - cptr = pdata + blkoffs[bi] + (cbxy*pw) + cbxy; - - /* Draw center pixel */ - *cptr = 255; - - /* Draw left and right half of line */ - xincr = dx; - yincr = dy; - for(i = 0; i < cbxy; i++){ - xyoffset = (sround(yincr)*pw) + sround(xincr); - rptr = cptr + xyoffset; - if((rptr > pdata) && (rptr < eptr)) - *rptr = 255; - lptr = cptr - xyoffset; - if((lptr > pdata) && (lptr < eptr)) - *lptr = 255; - xincr += dx; - yincr += dy; - } - } - } - iptr++; - } -} - -/************************************************************************* -************************************************************************** -#cat: drawblocks - Annotates an input image with the location of each block's -#cat: origin. This routine is useful to see how blocks are -#cat: assigned to arbitrarily-sized images that are not an even -#cat: width or height of the block size. In these cases the last -#cat: column pair and row pair of blocks overlap each other. -#cat: Note that the input image is modified upon return form -#cat: this routine. - - Input: - blkoffs - offsets to the pixel origin of each block in the image - mw - number of blocks horizontally in the input image - mh - number of blocks vertically in the input image - pdata - input image data to be annotated that has pixel dimensions - compatible with the offsets in blkoffs - pw - width (in pixels) of the input image - ph - height (in pixels) of the input image - draw_pixel - pixel intensity to be used when drawing on the image - Output: - pdata - input image contains the results of the annoatation -**************************************************************************/ -void drawblocks(const int *blkoffs, const int mw, const int mh, - unsigned char *pdata, const int pw, const int ph, - const int draw_pixel) -{ - int bi; - unsigned char *bptr; - - for(bi = 0; bi < mw*mh; bi++){ - bptr = pdata + blkoffs[bi]; - *bptr = draw_pixel; - } -} - - -/************************************************************************* -************************************************************************** -#cat: drawrotgrid - Annotates an input image with a specified rotated grid. -#cat: This routine is useful to see the location and orientation -#cat: of a specific rotated grid within a specific block in the -#cat: image. Note that the input image is modified upon return -#cat: form this routine. - - Input: - rotgrids - structure containing the rotated pixel grid offsets - dir - integer direction of the rotated grid to be annontated - idata - input image data to be annotated. - blkoffset - the pixel offset from the origin of the input image to - the origin of the specific block to be annoted - iw - width (in pixels) of the input image - ih - height (in pixels) of the input image - draw_pixel - pixel intensity to be used when drawing on the image - Return Code: - Zero - successful completion - Negative - system error -**************************************************************************/ -int drawrotgrid(const ROTGRIDS *rotgrids, const int dir, - unsigned char *idata, const int blkoffset, - const int iw, const int ih, const int draw_pixel) -{ - int i, j, gi; - - /* Check if specified rotation direction is within range of */ - /* rotated grids. */ - if(dir >= rotgrids->ngrids){ - fprintf(stderr, - "ERROR : drawrotgrid : input direction exceeds range of rotated grids\n"); - return(-140); - } - - /* Intialize grid offset index */ - gi = 0; - /* Foreach row in rotated grid ... */ - for(i = 0; i < rotgrids->grid_h; i++){ - /* Foreach column in rotated grid ... */ - for(j = 0; j < rotgrids->grid_w; j++){ - /* Draw pixels from every other rotated row to represent direction */ - /* of line sums used in DFT processing. */ - if(i%2) - *(idata+blkoffset+rotgrids->grids[dir][gi]) = draw_pixel; - /* Bump grid offset index */ - gi++; - } - } - - return(0); -} - -/************************************************************************* -************************************************************************** -#cat: dump_link_table - takes a link table and vectors of minutia IDs -#cat: assigned to its axes and prints the table's contents out -#cat: as formatted text to the specified open file pointer. - - Input: - fpout - open file pointer - 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 - tbldim - dimension of each axes of the link table - minutiae - list of minutia points -**************************************************************************/ -void dump_link_table(FILE *fpout, const int *link_table, - const int *x_axis, const int *y_axis, - const int nx_axis, const int ny_axis, const int tbldim, - const MINUTIAE *minutiae) -{ - int i, tx, ty, sentry, entry; - - fprintf(fpout, "DUMP LINK TABLE:\n"); - - fprintf(fpout, "X-AXIS:\n"); - for(i = 0; i < nx_axis; i++){ - fprintf(fpout, "%d: %d,%d\n", i, minutiae->list[x_axis[i]]->x, - minutiae->list[x_axis[i]]->y); - } - - fprintf(fpout, "Y-AXIS:\n"); - for(i = 0; i < ny_axis; i++){ - fprintf(fpout, "%d: %d,%d\n", i, minutiae->list[y_axis[i]]->x, - minutiae->list[y_axis[i]]->y); - } - - fprintf(fpout, "TABLE:\n"); - sentry = 0; - for(ty = 0; ty < ny_axis; ty++){ - entry = sentry; - for(tx = 0; tx < nx_axis; tx++){ - fprintf(fpout, "%7d ", link_table[entry++]); - } - fprintf(fpout, "\n"); - sentry += tbldim; - } -} - diff --git a/libfprint/nbis/mindtct/shape.c b/libfprint/nbis/mindtct/shape.c index 23ba16c..4e8ea8f 100644 --- a/libfprint/nbis/mindtct/shape.c +++ b/libfprint/nbis/mindtct/shape.c @@ -36,7 +36,6 @@ identified are necessarily the best available for the purpose. ROUTINES: alloc_shape() free_shape() - dump_shape() shape_from_contour() sort_row_on_x() ***********************************************************************/ @@ -61,7 +60,7 @@ identified are necessarily the best available for the purpose. Zero - Shape successfully allocated and initialized Negative - System error **************************************************************************/ -int alloc_shape(SHAPE **oshape, const int xmin, const int ymin, +static int alloc_shape(SHAPE **oshape, const int xmin, const int ymin, const int xmax, const int ymax) { SHAPE *shape; @@ -181,33 +180,20 @@ void free_shape(SHAPE *shape) /************************************************************************* ************************************************************************** -#cat: dump_shape - Takes an initialized shape structure and dumps its contents -#cat: as formatted text to the specified open file pointer. +#cat: sort_row_on_x - Takes a row structure and sorts its points left-to- +#cat: right on X. Input: - shape - shape structure to be dumped + row - row structure to be sorted Output: - fpout - open file pointer to be written to + row - row structure with points in sorted order **************************************************************************/ -void dump_shape(FILE *fpout, const SHAPE *shape) +static void sort_row_on_x(ROW *row) { - int i, j; - - /* Print the shape's y-limits and number of scanlines. */ - fprintf(fpout, "shape: ymin=%d, ymax=%d, nrows=%d\n", - shape->ymin, shape->ymax, shape->nrows); - - /* Foreach row in the shape... */ - for(i = 0; i < shape->nrows; i++){ - /* Print the current row's y-coord and number of points on the row. */ - fprintf(fpout, "row %d : y=%d, npts=%d\n", i, shape->rows[i]->y, - shape->rows[i]->npts); - /* Print each successive point on the current row. */ - for(j = 0; j < shape->rows[i]->npts; j++){ - fprintf(fpout, "pt %d : %d %d\n", j, shape->rows[i]->xs[j], - shape->rows[i]->y); - } - } + /* 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); } /************************************************************************* @@ -284,21 +270,3 @@ 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); -} -