From 297236b51a537d56b0a1e425d3e8582403f5ecb2 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Wed, 3 Jun 2020 18:26:40 -0700 Subject: [PATCH] nbis: re-add step to remove perimeter points This step helps to drop false minutiae for short sensors and it was accidentally dropped during NBIS update. Re-add this step and add a patch to update script to ensure that it's not dropped during next update. Fixes: 9fb789dc787d ("nbis: Update to NBIS 5.0.0") --- libfprint/nbis/include/lfs.h | 8 + libfprint/nbis/mindtct/globals.c | 4 + libfprint/nbis/mindtct/remove.c | 158 +++++++++++++++ libfprint/nbis/remove-perimeter-pts.patch | 231 ++++++++++++++++++++++ libfprint/nbis/update-from-nbis.sh | 5 +- 5 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 libfprint/nbis/remove-perimeter-pts.patch diff --git a/libfprint/nbis/include/lfs.h b/libfprint/nbis/include/lfs.h index f4f38d7..8b12e73 100644 --- a/libfprint/nbis/include/lfs.h +++ b/libfprint/nbis/include/lfs.h @@ -260,6 +260,8 @@ typedef struct g_lfsparms{ int pores_steps_bwd; double pores_min_dist2; double pores_max_ratio; + int remove_perimeter_pts; + int min_pp_distance; /* Ridge Counting Controls */ int max_nbrs; @@ -609,6 +611,9 @@ typedef struct g_lfsparms{ /* contour points to be considered a pore. */ #define PORES_MAX_RATIO 2.25 +/* Points which are closer than this distance to scan perimeter will be removed */ +#define PERIMETER_PTS_DISTANCE 10 + /***** RIDGE COUNTING CONSTANTS *****/ @@ -1123,6 +1128,9 @@ extern int remove_or_adjust_side_minutiae(MINUTIAE *, unsigned char *, extern int remove_or_adjust_side_minutiae_V2(MINUTIAE *, unsigned char *, const int, const int, int *, const int, const int, const LFSPARMS *); +extern int remove_perimeter_pts(MINUTIAE *minutiae, + unsigned char *bdata, const int iw, const int ih, + const LFSPARMS *lfsparms); /* results.c */ extern int write_text_results(char *, const int, const int, const int, diff --git a/libfprint/nbis/mindtct/globals.c b/libfprint/nbis/mindtct/globals.c index da10c15..79bc583 100644 --- a/libfprint/nbis/mindtct/globals.c +++ b/libfprint/nbis/mindtct/globals.c @@ -150,6 +150,8 @@ LFSPARMS g_lfsparms = { PORES_STEPS_BWD, PORES_MIN_DIST2, PORES_MAX_RATIO, + FALSE, /* not removing perimeter points by default */ + PERIMETER_PTS_DISTANCE, /* Ridge Counting Controls */ MAX_NBRS, @@ -234,6 +236,8 @@ LFSPARMS g_lfsparms_V2 = { PORES_STEPS_BWD, PORES_MIN_DIST2, PORES_MAX_RATIO, + FALSE, /* not removing perimeter points by default */ + PERIMETER_PTS_DISTANCE, /* Ridge Counting Controls */ MAX_NBRS, diff --git a/libfprint/nbis/mindtct/remove.c b/libfprint/nbis/mindtct/remove.c index af5ab7d..7311f1c 100644 --- a/libfprint/nbis/mindtct/remove.c +++ b/libfprint/nbis/mindtct/remove.c @@ -195,6 +195,11 @@ int remove_false_minutia_V2(MINUTIAE *minutiae, return(ret); } + /* 11. Remove minutiae on image edge */ + if((ret = remove_perimeter_pts(minutiae, bdata, iw, ih, lfsparms))) { + return (ret); + } + return(0); } @@ -1329,6 +1334,159 @@ int remove_pointing_invblock_V2(MINUTIAE *minutiae, return(0); } +static void mark_minutiae_in_range(MINUTIAE *minutiae, int *to_remove, int x, int y, + const LFSPARMS *lfsparms) +{ + int i, dist; + for (i = 0; i < minutiae->num; i++) { + if (to_remove[i]) + continue; + dist = (int)sqrt((x - minutiae->list[i]->x) * (x - minutiae->list[i]->x) + + (y - minutiae->list[i]->y) * (y - minutiae->list[i]->y)); + if (dist < lfsparms->min_pp_distance) { + to_remove[i] = 1; + } + } +} + +/************************************************************************* +************************************************************************** +#cat: remove_perimeter_pts - Takes a list of true and false minutiae and +#cat: attempts to detect and remove those false minutiae that +#cat: belong to image edge + + Input: + minutiae - list of true and false minutiae + bdata - binary image data (0==while & 1==black) + iw - width (in pixels) of image + ih - height (in pixels) of image + lfsparms - parameters and thresholds for controlling LFS + Output: + minutiae - list of pruned minutiae + Return Code: + Zero - successful completion + Negative - system error +**************************************************************************/ +int remove_perimeter_pts(MINUTIAE *minutiae, + unsigned char *bdata, const int iw, const int ih, + const LFSPARMS *lfsparms) +{ + int i, j, ret, *to_remove; + int *left, *left_up, *left_down; + int *right, *right_up, *right_down; + int removed = 0; + int left_min, right_max; + + if (!lfsparms->remove_perimeter_pts) + return(0); + + to_remove = calloc(minutiae->num, sizeof(int)); + left = calloc(ih, sizeof(int)); + left_up = calloc(ih, sizeof(int)); + left_down = calloc(ih, sizeof(int)); + right = calloc(ih, sizeof(int)); + right_up = calloc(ih, sizeof(int)); + right_down = calloc(ih, sizeof(int)); + + /* Pass downwards */ + left_min = iw - 1; + right_max = 0; + for (i = 0; i < ih; i++) { + for (j = 0; j < left_min; j++) { + if ((bdata[i * iw + j] != 0)) { + left_min = j; + break; + } + } + if (left_min == (iw - 1)) + left_down[i] = -1; + else + left_down[i] = left_min; + for (j = iw - 1; j >= right_max; j--) { + if ((bdata[i * iw + j] != 0)) { + right_max = j; + break; + } + } + if (right_max == 0) + right_down[i] = -1; + else + right_down[i] = right_max; + } + + /* Pass upwards */ + left_min = iw - 1; + right_max = 0; + for (i = ih - 1; i >= 0; i--) { + for (j = 0; j < left_min; j++) { + if ((bdata[i * iw + j] != 0)) { + left_min = j; + break; + } + } + if (left_min == (iw - 1)) + left_up[i] = -1; + else + left_up[i] = left_min; + for (j = iw - 1; j >= right_max; j--) { + if ((bdata[i * iw + j] != 0)) { + right_max = j; + break; + } + } + if (right_max == 0) + right_up[i] = -1; + else + right_up[i] = right_max; + } + + /* Merge */ + left_min = left_down[ih - 1]; + right_max = right_down[ih - 1]; + for (i = 0; i < ih; i++) { + if (left_down[i] != left_min) + left[i] = left_down[i]; + else + left[i] = left_up[i]; + + if (right_down[i] != right_max) + right[i] = right_down[i]; + else + right[i] = right_up[i]; + } + free(left_up); + free(left_down); + free(right_up); + free(right_down); + + /* Mark minitiae close to the edge */ + for (i = 0; i < ih; i++) { + if (left[i] != -1) + mark_minutiae_in_range(minutiae, to_remove, left[i], i, lfsparms); + if (right[i] != -1) + mark_minutiae_in_range(minutiae, to_remove, right[i], i, lfsparms); + } + + free(left); + free(right); + + for (i = minutiae->num - 1; i >= 0; i--) { + /* If the current minutia index is flagged for removal ... */ + if (to_remove[i]){ + removed ++; + /* Remove the minutia from the minutiae list. */ + if((ret = remove_minutia(i, minutiae))){ + free(to_remove); + return(ret); + } + } + } + + free(to_remove); + + return (0); +} + /************************************************************************* ************************************************************************** #cat: remove_overlaps - Takes a list of true and false minutiae and diff --git a/libfprint/nbis/remove-perimeter-pts.patch b/libfprint/nbis/remove-perimeter-pts.patch new file mode 100644 index 0000000..714f93b --- /dev/null +++ b/libfprint/nbis/remove-perimeter-pts.patch @@ -0,0 +1,231 @@ +diff --git nbis/include/lfs.h nbis/include/lfs.h +index f4f38d7..8b12e73 100644 +--- nbis/include/lfs.h ++++ nbis/include/lfs.h +@@ -260,6 +260,8 @@ typedef struct g_lfsparms{ + int pores_steps_bwd; + double pores_min_dist2; + double pores_max_ratio; ++ int remove_perimeter_pts; ++ int min_pp_distance; + + /* Ridge Counting Controls */ + int max_nbrs; +@@ -609,6 +611,9 @@ typedef struct g_lfsparms{ + /* contour points to be considered a pore. */ + #define PORES_MAX_RATIO 2.25 + ++/* Points which are closer than this distance to scan perimeter will be removed */ ++#define PERIMETER_PTS_DISTANCE 10 ++ + + /***** RIDGE COUNTING CONSTANTS *****/ + +@@ -1123,6 +1128,9 @@ extern int remove_or_adjust_side_minutiae(MINUTIAE *, unsigned char *, + extern int remove_or_adjust_side_minutiae_V2(MINUTIAE *, + unsigned char *, const int, const int, + int *, const int, const int, const LFSPARMS *); ++extern int remove_perimeter_pts(MINUTIAE *minutiae, ++ unsigned char *bdata, const int iw, const int ih, ++ const LFSPARMS *lfsparms); + + /* results.c */ + extern int write_text_results(char *, const int, const int, const int, +diff --git nbis/mindtct/globals.c nbis/mindtct/globals.c +index da10c15..79bc583 100644 +--- nbis/mindtct/globals.c ++++ nbis/mindtct/globals.c +@@ -150,6 +150,8 @@ LFSPARMS g_lfsparms = { + PORES_STEPS_BWD, + PORES_MIN_DIST2, + PORES_MAX_RATIO, ++ FALSE, /* not removing perimeter points by default */ ++ PERIMETER_PTS_DISTANCE, + + /* Ridge Counting Controls */ + MAX_NBRS, +@@ -234,6 +236,8 @@ LFSPARMS g_lfsparms_V2 = { + PORES_STEPS_BWD, + PORES_MIN_DIST2, + PORES_MAX_RATIO, ++ FALSE, /* not removing perimeter points by default */ ++ PERIMETER_PTS_DISTANCE, + + /* Ridge Counting Controls */ + MAX_NBRS, +diff --git nbis/mindtct/remove.c nbis/mindtct/remove.c +index af5ab7d..7311f1c 100644 +--- nbis/mindtct/remove.c ++++ nbis/mindtct/remove.c +@@ -195,6 +195,11 @@ int remove_false_minutia_V2(MINUTIAE *minutiae, + return(ret); + } + ++ /* 11. Remove minutiae on image edge */ ++ if((ret = remove_perimeter_pts(minutiae, bdata, iw, ih, lfsparms))) { ++ return (ret); ++ } ++ + return(0); + } + +@@ -1329,6 +1334,159 @@ int remove_pointing_invblock_V2(MINUTIAE *minutiae, + return(0); + } + ++static void mark_minutiae_in_range(MINUTIAE *minutiae, int *to_remove, int x, int y, ++ const LFSPARMS *lfsparms) ++{ ++ int i, dist; ++ for (i = 0; i < minutiae->num; i++) { ++ if (to_remove[i]) ++ continue; ++ dist = (int)sqrt((x - minutiae->list[i]->x) * (x - minutiae->list[i]->x) + ++ (y - minutiae->list[i]->y) * (y - minutiae->list[i]->y)); ++ if (dist < lfsparms->min_pp_distance) { ++ to_remove[i] = 1; ++ } ++ } ++} ++ ++/************************************************************************* ++************************************************************************** ++#cat: remove_perimeter_pts - Takes a list of true and false minutiae and ++#cat: attempts to detect and remove those false minutiae that ++#cat: belong to image edge ++ ++ Input: ++ minutiae - list of true and false minutiae ++ bdata - binary image data (0==while & 1==black) ++ iw - width (in pixels) of image ++ ih - height (in pixels) of image ++ lfsparms - parameters and thresholds for controlling LFS ++ Output: ++ minutiae - list of pruned minutiae ++ Return Code: ++ Zero - successful completion ++ Negative - system error ++**************************************************************************/ ++int remove_perimeter_pts(MINUTIAE *minutiae, ++ unsigned char *bdata, const int iw, const int ih, ++ const LFSPARMS *lfsparms) ++{ ++ int i, j, ret, *to_remove; ++ int *left, *left_up, *left_down; ++ int *right, *right_up, *right_down; ++ int removed = 0; ++ int left_min, right_max; ++ ++ if (!lfsparms->remove_perimeter_pts) ++ return(0); ++ ++ to_remove = calloc(minutiae->num, sizeof(int)); ++ left = calloc(ih, sizeof(int)); ++ left_up = calloc(ih, sizeof(int)); ++ left_down = calloc(ih, sizeof(int)); ++ right = calloc(ih, sizeof(int)); ++ right_up = calloc(ih, sizeof(int)); ++ right_down = calloc(ih, sizeof(int)); ++ ++ /* Pass downwards */ ++ left_min = iw - 1; ++ right_max = 0; ++ for (i = 0; i < ih; i++) { ++ for (j = 0; j < left_min; j++) { ++ if ((bdata[i * iw + j] != 0)) { ++ left_min = j; ++ break; ++ } ++ } ++ if (left_min == (iw - 1)) ++ left_down[i] = -1; ++ else ++ left_down[i] = left_min; ++ for (j = iw - 1; j >= right_max; j--) { ++ if ((bdata[i * iw + j] != 0)) { ++ right_max = j; ++ break; ++ } ++ } ++ if (right_max == 0) ++ right_down[i] = -1; ++ else ++ right_down[i] = right_max; ++ } ++ ++ /* Pass upwards */ ++ left_min = iw - 1; ++ right_max = 0; ++ for (i = ih - 1; i >= 0; i--) { ++ for (j = 0; j < left_min; j++) { ++ if ((bdata[i * iw + j] != 0)) { ++ left_min = j; ++ break; ++ } ++ } ++ if (left_min == (iw - 1)) ++ left_up[i] = -1; ++ else ++ left_up[i] = left_min; ++ for (j = iw - 1; j >= right_max; j--) { ++ if ((bdata[i * iw + j] != 0)) { ++ right_max = j; ++ break; ++ } ++ } ++ if (right_max == 0) ++ right_up[i] = -1; ++ else ++ right_up[i] = right_max; ++ } ++ ++ /* Merge */ ++ left_min = left_down[ih - 1]; ++ right_max = right_down[ih - 1]; ++ for (i = 0; i < ih; i++) { ++ if (left_down[i] != left_min) ++ left[i] = left_down[i]; ++ else ++ left[i] = left_up[i]; ++ ++ if (right_down[i] != right_max) ++ right[i] = right_down[i]; ++ else ++ right[i] = right_up[i]; ++ } ++ free(left_up); ++ free(left_down); ++ free(right_up); ++ free(right_down); ++ ++ /* Mark minitiae close to the edge */ ++ for (i = 0; i < ih; i++) { ++ if (left[i] != -1) ++ mark_minutiae_in_range(minutiae, to_remove, left[i], i, lfsparms); ++ if (right[i] != -1) ++ mark_minutiae_in_range(minutiae, to_remove, right[i], i, lfsparms); ++ } ++ ++ free(left); ++ free(right); ++ ++ for (i = minutiae->num - 1; i >= 0; i--) { ++ /* If the current minutia index is flagged for removal ... */ ++ if (to_remove[i]){ ++ removed ++; ++ /* Remove the minutia from the minutiae list. */ ++ if((ret = remove_minutia(i, minutiae))){ ++ free(to_remove); ++ return(ret); ++ } ++ } ++ } ++ ++ free(to_remove); ++ ++ return (0); ++} ++ + /************************************************************************* + ************************************************************************** + #cat: remove_overlaps - Takes a list of true and false minutiae and diff --git a/libfprint/nbis/update-from-nbis.sh b/libfprint/nbis/update-from-nbis.sh index d9400a2..f7ec0ee 100755 --- a/libfprint/nbis/update-from-nbis.sh +++ b/libfprint/nbis/update-from-nbis.sh @@ -194,4 +194,7 @@ spatch --sp-file remove-global-y.cocci bozorth3/* include/bozorth.h --in-place patch -p0 < glib-mem-warning.patch # Also fix some scan-build warnings, mostly by adding assertions -patch -p0 < fix-scan-build-reports.patch \ No newline at end of file +patch -p0 < fix-scan-build-reports.patch + +# Add pass to remove perimeter points +patch -p0 < remove-perimeter-pts.patch