| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /******************************************************************************* | ||
| 2 | |||
| 3 | License: | ||
| 4 | This software and/or related materials was developed at the National Institute | ||
| 5 | of Standards and Technology (NIST) by employees of the Federal Government | ||
| 6 | in the course of their official duties. Pursuant to title 17 Section 105 | ||
| 7 | of the United States Code, this software is not subject to copyright | ||
| 8 | protection and is in the public domain. | ||
| 9 | |||
| 10 | This software and/or related materials have been determined to be not subject | ||
| 11 | to the EAR (see Part 734.3 of the EAR for exact details) because it is | ||
| 12 | a publicly available technology and software, and is freely distributed | ||
| 13 | to any interested party with no licensing requirements. Therefore, it is | ||
| 14 | permissible to distribute this software as a free download from the internet. | ||
| 15 | |||
| 16 | Disclaimer: | ||
| 17 | This software and/or related materials was developed to promote biometric | ||
| 18 | standards and biometric technology testing for the Federal Government | ||
| 19 | in accordance with the USA PATRIOT Act and the Enhanced Border Security | ||
| 20 | and Visa Entry Reform Act. Specific hardware and software products identified | ||
| 21 | in this software were used in order to perform the software development. | ||
| 22 | In no case does such identification imply recommendation or endorsement | ||
| 23 | by the National Institute of Standards and Technology, nor does it imply that | ||
| 24 | the products and equipment identified are necessarily the best available | ||
| 25 | for the purpose. | ||
| 26 | |||
| 27 | This software and/or related materials are provided "AS-IS" without warranty | ||
| 28 | of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY, | ||
| 29 | NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY | ||
| 30 | or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the | ||
| 31 | licensed product, however used. In no event shall NIST be liable for any | ||
| 32 | damages and/or costs, including but not limited to incidental or consequential | ||
| 33 | damages of any kind, including economic damage or injury to property and lost | ||
| 34 | profits, regardless of whether NIST shall be advised, have reason to know, | ||
| 35 | or in fact shall know of the possibility. | ||
| 36 | |||
| 37 | By using this software, you agree to bear all risk relating to quality, | ||
| 38 | use and performance of the software and/or related materials. You agree | ||
| 39 | to hold the Government harmless from any claim arising from your use | ||
| 40 | of the software. | ||
| 41 | |||
| 42 | *******************************************************************************/ | ||
| 43 | |||
| 44 | |||
| 45 | /*********************************************************************** | ||
| 46 | LIBRARY: LFS - NIST Latent Fingerprint System | ||
| 47 | |||
| 48 | FILE: QUALITY.C | ||
| 49 | AUTHOR: Michael D. Garris | ||
| 50 | DATE: 09/25/2000 | ||
| 51 | UPDATED: 03/16/2005 by MDG | ||
| 52 | |||
| 53 | Contains routines responsible for assessing minutia quality | ||
| 54 | and assigning different reliability measures. These routines | ||
| 55 | are primarily to support the rejection of bad minutiae. | ||
| 56 | |||
| 57 | *********************************************************************** | ||
| 58 | ROUTINES: | ||
| 59 | gen_quality_map() | ||
| 60 | combined_minutia_quality() | ||
| 61 | grayscale_reliability() | ||
| 62 | get_neighborhood_stats() | ||
| 63 | reliability_fr_quality_map() | ||
| 64 | |||
| 65 | ***********************************************************************/ | ||
| 66 | |||
| 67 | #include <stdio.h> | ||
| 68 | #include <math.h> | ||
| 69 | #include <lfs.h> | ||
| 70 | |||
| 71 | /*********************************************************************** | ||
| 72 | ************************************************************************ | ||
| 73 | #cat: gen_quality_map - Takes a direction map, low contrast map, low ridge | ||
| 74 | #cat: flow map, and high curvature map, and combines them | ||
| 75 | #cat: into a single map containing 5 levels of decreasing | ||
| 76 | #cat: quality. This is done through a set of heuristics. | ||
| 77 | |||
| 78 | Code originally written by Austin Hicklin for FBI ATU | ||
| 79 | Modified by Michael D. Garris (NIST) Sept. 1, 2000 | ||
| 80 | |||
| 81 | Set quality of 0(unusable)..4(good) (I call these grades A..F) | ||
| 82 | 0/F: low contrast OR no direction | ||
| 83 | 1/D: low flow OR high curve | ||
| 84 | (with low contrast OR no direction neighbor) | ||
| 85 | (or within NEIGHBOR_DELTA of edge) | ||
| 86 | 2/C: low flow OR high curve | ||
| 87 | (or good quality with low contrast/no direction neighbor) | ||
| 88 | 3/B: good quality with low flow / high curve neighbor | ||
| 89 | 4/A: good quality (none of the above) | ||
| 90 | |||
| 91 | Generally, the features in A/B quality are useful, the C/D quality | ||
| 92 | ones are not. | ||
| 93 | |||
| 94 | Input: | ||
| 95 | direction_map - map with blocks assigned dominant ridge flow direction | ||
| 96 | low_contrast_map - map with blocks flagged as low contrast | ||
| 97 | low_flow_map - map with blocks flagged as low ridge flow | ||
| 98 | high_curve_map - map with blocks flagged as high curvature | ||
| 99 | map_w - width (in blocks) of the maps | ||
| 100 | map_h - height (in blocks) of the maps | ||
| 101 | Output: | ||
| 102 | oqmap - points to new quality map | ||
| 103 | Return Code: | ||
| 104 | Zero - successful completion | ||
| 105 | Negative - system error | ||
| 106 | ************************************************************************/ | ||
| 107 | 48 | int gen_quality_map(int **oqmap, int *direction_map, int *low_contrast_map, | |
| 108 | int *low_flow_map, int *high_curve_map, | ||
| 109 | const int map_w, const int map_h) | ||
| 110 | { | ||
| 111 | |||
| 112 | 48 | int *QualMap; | |
| 113 | 48 | int thisX, thisY; | |
| 114 | 48 | int compX, compY; | |
| 115 | 48 | int arrayPos, arrayPos2; | |
| 116 | 48 | int QualOffset; | |
| 117 | |||
| 118 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 48 times.
|
48 | ASSERT_SIZE_MUL(map_w, map_h); |
| 119 |
1/2✓ Branch 0 (4→5) taken 48 times.
✗ Branch 1 (4→7) not taken.
|
48 | ASSERT_SIZE_MUL(map_w * map_h, sizeof(int)); |
| 120 | |||
| 121 | 48 | QualMap = (int *)g_malloc(map_w * map_h * sizeof(int)); | |
| 122 | |||
| 123 | /* Foreach row of blocks in maps ... */ | ||
| 124 |
2/2✓ Branch 0 (35→36) taken 1673 times.
✓ Branch 1 (35→37) taken 48 times.
|
1769 | for(thisY=0; thisY<map_h; thisY++){ |
| 125 | /* Foreach block in current row ... */ | ||
| 126 |
2/2✓ Branch 0 (33→8) taken 50730 times.
✓ Branch 1 (33→34) taken 1673 times.
|
52403 | for(thisX=0; thisX<map_w; thisX++) { |
| 127 | /* Compute block index. */ | ||
| 128 | 50730 | arrayPos=(thisY*map_w)+thisX; | |
| 129 | /* If current block has low contrast or INVALID direction ... */ | ||
| 130 |
4/4✓ Branch 0 (8→9) taken 46139 times.
✓ Branch 1 (8→10) taken 4591 times.
✓ Branch 2 (9→10) taken 7169 times.
✓ Branch 3 (9→11) taken 38970 times.
|
50730 | if(low_contrast_map[arrayPos] || direction_map[arrayPos]<0) |
| 131 | /* Set block's quality to 0/F. */ | ||
| 132 | 11760 | QualMap[arrayPos]=0; | |
| 133 | else{ | ||
| 134 | /* Set baseline quality before looking at neighbors */ | ||
| 135 | /* (will subtract QualOffset below) */ | ||
| 136 | /* If current block has low flow or high curvature ... */ | ||
| 137 |
4/4✓ Branch 0 (11→12) taken 24012 times.
✓ Branch 1 (11→13) taken 14958 times.
✓ Branch 2 (12→13) taken 811 times.
✓ Branch 3 (12→14) taken 23201 times.
|
38970 | if(low_flow_map[arrayPos] || high_curve_map[arrayPos]) |
| 138 | /* Set block's quality initially to 3/B. */ | ||
| 139 | 15769 | QualMap[arrayPos] = 3; /* offset will be -1..-2 */ | |
| 140 | /* Otherwise, block is NOT low flow AND NOT high curvature... */ | ||
| 141 | else | ||
| 142 | /* Set block's quality to 4/A. */ | ||
| 143 | 23201 | QualMap[arrayPos]=4; /* offset will be 0..-2 */ | |
| 144 | |||
| 145 | /* If block within NEIGHBOR_DELTA of edge ... */ | ||
| 146 |
6/6✓ Branch 0 (15→16) taken 37764 times.
✓ Branch 1 (15→19) taken 1206 times.
✓ Branch 2 (16→17) taken 36581 times.
✓ Branch 3 (16→19) taken 1183 times.
✓ Branch 4 (17→18) taken 35350 times.
✓ Branch 5 (17→19) taken 1231 times.
|
38970 | if(thisY < NEIGHBOR_DELTA || thisY > map_h - 1 - NEIGHBOR_DELTA || |
| 147 |
2/2✓ Branch 0 (18→19) taken 1086 times.
✓ Branch 1 (18→20) taken 34264 times.
|
35350 | thisX < NEIGHBOR_DELTA || thisX > map_w - 1 - NEIGHBOR_DELTA) |
| 148 | /* Set block's quality to 1/E. */ | ||
| 149 | 4706 | QualMap[arrayPos]=1; | |
| 150 | /* Otherwise, test neighboring blocks ... */ | ||
| 151 | else{ | ||
| 152 | /* Initialize quality adjustment to 0. */ | ||
| 153 | 34264 | QualOffset=0; | |
| 154 | /* Foreach row in neighborhood ... */ | ||
| 155 | 34264 | for(compY=thisY-NEIGHBOR_DELTA; | |
| 156 |
2/2✓ Branch 0 (30→21) taken 171320 times.
✓ Branch 1 (30→31) taken 34264 times.
|
205584 | compY<=thisY+NEIGHBOR_DELTA;compY++){ |
| 157 | /* Foreach block in neighborhood */ | ||
| 158 | /* (including current block)... */ | ||
| 159 | 171320 | for(compX=thisX-NEIGHBOR_DELTA; | |
| 160 |
2/2✓ Branch 0 (28→22) taken 800842 times.
✓ Branch 1 (28→29) taken 147621 times.
|
948463 | compX<=thisX+NEIGHBOR_DELTA;compX++) { |
| 161 | /* Compute neighboring block's index. */ | ||
| 162 | 800842 | arrayPos2 = (compY*map_w)+compX; | |
| 163 | /* If neighbor block (which might be itself) has */ | ||
| 164 | /* low contrast or INVALID direction .. */ | ||
| 165 |
2/2✓ Branch 0 (22→23) taken 797757 times.
✓ Branch 1 (22→29) taken 3085 times.
|
800842 | if(low_contrast_map[arrayPos2] || |
| 166 |
2/2✓ Branch 0 (23→24) taken 777143 times.
✓ Branch 1 (23→29) taken 20614 times.
|
797757 | direction_map[arrayPos2]<0) { |
| 167 | /* Set quality adjustment to -2. */ | ||
| 168 | QualOffset=-2; | ||
| 169 | /* Done with neighborhood row. */ | ||
| 170 | break; | ||
| 171 | } | ||
| 172 | /* Otherwise, if neighbor block (which might be */ | ||
| 173 | /* itself) has low flow or high curvature ... */ | ||
| 174 |
2/2✓ Branch 0 (24→25) taken 474406 times.
✓ Branch 1 (24→26) taken 302737 times.
|
777143 | else if(low_flow_map[arrayPos2] || |
| 175 |
2/2✓ Branch 0 (25→26) taken 16534 times.
✓ Branch 1 (25→27) taken 457872 times.
|
474406 | high_curve_map[arrayPos2]) { |
| 176 | /* Set quality to -1 if not already -2. */ | ||
| 177 | 319271 | QualOffset=min(QualOffset,-1); | |
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | /* Decrement minutia quality by neighborhood adjustment. */ | ||
| 182 | 34264 | QualMap[arrayPos]+=QualOffset; | |
| 183 | } | ||
| 184 | } | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | /* Set output pointer. */ | ||
| 189 | 48 | *oqmap = QualMap; | |
| 190 | /* Return normally. */ | ||
| 191 | 48 | return(0); | |
| 192 | } | ||
| 193 | |||
| 194 | /*********************************************************************** | ||
| 195 | ************************************************************************ | ||
| 196 | #cat: combined_minutia_quality - Combines quality measures derived from | ||
| 197 | #cat: the quality map and neighboring pixel statistics to | ||
| 198 | #cat: infer a reliability measure on the scale [0...1]. | ||
| 199 | |||
| 200 | Input: | ||
| 201 | minutiae - structure contining the detected minutia | ||
| 202 | quality_map - map with blocks assigned 1 of 5 quality levels | ||
| 203 | map_w - width (in blocks) of the map | ||
| 204 | map_h - height (in blocks) of the map | ||
| 205 | blocksize - size (in pixels) of each block in the map | ||
| 206 | idata - 8-bit grayscale fingerprint image | ||
| 207 | iw - width (in pixels) of the image | ||
| 208 | ih - height (in pixels) of the image | ||
| 209 | id - depth (in pixels) of the image | ||
| 210 | ppmm - scan resolution of the image in pixels/mm | ||
| 211 | Output: | ||
| 212 | minutiae - updated reliability members | ||
| 213 | Return Code: | ||
| 214 | Zero - successful completion | ||
| 215 | Negative - system error | ||
| 216 | ************************************************************************/ | ||
| 217 | 48 | int combined_minutia_quality(MINUTIAE *minutiae, | |
| 218 | int *quality_map, const int mw, const int mh, const int blocksize, | ||
| 219 | unsigned char *idata, const int iw, const int ih, const int id, | ||
| 220 | const double ppmm) | ||
| 221 | { | ||
| 222 | 48 | int ret, i, index, radius_pix; | |
| 223 | 48 | int *pquality_map, qmap_value; | |
| 224 | 48 | MINUTIA *minutia; | |
| 225 | 48 | double gs_reliability, reliability; | |
| 226 | |||
| 227 | /* If image is not 8-bit grayscale ... */ | ||
| 228 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→7) taken 48 times.
|
48 | if(id != 8){ |
| 229 | ✗ | fprintf(stderr, "ERROR : combined_miutia_quality : "); | |
| 230 | ✗ | fprintf(stderr, "image must pixel depth = %d must be 8 ", id); | |
| 231 | ✗ | fprintf(stderr, "to compute reliability\n"); | |
| 232 | ✗ | return(-2); | |
| 233 | } | ||
| 234 | |||
| 235 | /* Compute pixel radius of neighborhood based on image's scan resolution. */ | ||
| 236 |
1/2✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→9) taken 48 times.
|
48 | radius_pix = sround(RADIUS_MM * ppmm); |
| 237 | |||
| 238 | /* Expand block map values to pixel map. */ | ||
| 239 |
1/2✓ Branch 0 (11→24) taken 48 times.
✗ Branch 1 (11→27) not taken.
|
48 | if((ret = pixelize_map(&pquality_map, iw, ih, |
| 240 | quality_map, mw, mh, blocksize))){ | ||
| 241 | return(ret); | ||
| 242 | } | ||
| 243 | |||
| 244 | /* Foreach minutiae detected ... */ | ||
| 245 |
2/2✓ Branch 0 (24→12) taken 3495 times.
✓ Branch 1 (24→25) taken 48 times.
|
3543 | for(i = 0; i < minutiae->num; i++){ |
| 246 | /* Assign minutia pointer. */ | ||
| 247 | 3495 | minutia = minutiae->list[i]; | |
| 248 | |||
| 249 | /* Compute reliability from stdev and mean of pixel neighborhood. */ | ||
| 250 | 3495 | gs_reliability = grayscale_reliability(minutia, | |
| 251 | idata, iw, ih, radius_pix); | ||
| 252 | |||
| 253 | /* Lookup quality map value. */ | ||
| 254 | /* Compute minutia pixel index. */ | ||
| 255 | 3495 | index = (minutia->y * iw) + minutia->x; | |
| 256 | /* Switch on pixel's quality value ... */ | ||
| 257 | 3495 | qmap_value = pquality_map[index]; | |
| 258 | |||
| 259 | /* Combine grayscale reliability and quality map value. */ | ||
| 260 |
5/6✓ Branch 0 (13→14) taken 359 times.
✓ Branch 1 (13→15) taken 938 times.
✓ Branch 2 (13→16) taken 1599 times.
✓ Branch 3 (13→17) taken 596 times.
✗ Branch 4 (13→18) not taken.
✓ Branch 5 (13→23) taken 3 times.
|
3495 | switch(qmap_value){ |
| 261 | /* Quality A : [50..99]% */ | ||
| 262 | 359 | case 4 : | |
| 263 | 359 | reliability = 0.50 + (0.49 * gs_reliability); | |
| 264 | 359 | break; | |
| 265 | /* Quality B : [25..49]% */ | ||
| 266 | 938 | case 3 : | |
| 267 | 938 | reliability = 0.25 + (0.24 * gs_reliability); | |
| 268 | 938 | break; | |
| 269 | /* Quality C : [10..24]% */ | ||
| 270 | 1599 | case 2 : | |
| 271 | 1599 | reliability = 0.10 + (0.14 * gs_reliability); | |
| 272 | 1599 | break; | |
| 273 | /* Quality D : [5..9]% */ | ||
| 274 | 596 | case 1 : | |
| 275 | 596 | reliability = 0.05 + (0.04 * gs_reliability); | |
| 276 | 596 | break; | |
| 277 | /* Quality E : 1% */ | ||
| 278 | case 0 : | ||
| 279 | reliability = 0.01; | ||
| 280 | break; | ||
| 281 | /* Error if quality value not in range [0..4]. */ | ||
| 282 | ✗ | default: | |
| 283 | ✗ | fprintf(stderr, "ERROR : combined_miutia_quality : "); | |
| 284 | ✗ | fprintf(stderr, "unexpected quality map value %d ", qmap_value); | |
| 285 | ✗ | fprintf(stderr, "not in range [0..4]\n"); | |
| 286 | ✗ | g_free(pquality_map); | |
| 287 | ✗ | return(-3); | |
| 288 | } | ||
| 289 | 3495 | minutia->reliability = reliability; | |
| 290 | } | ||
| 291 | |||
| 292 | /* NEW 05-08-2002 */ | ||
| 293 | 48 | g_free(pquality_map); | |
| 294 | |||
| 295 | /* Return normally. */ | ||
| 296 | 48 | return(0); | |
| 297 | } | ||
| 298 | |||
| 299 | |||
| 300 | /*********************************************************************** | ||
| 301 | ************************************************************************ | ||
| 302 | #cat: grayscale_reliability - Given a minutia point, computes a reliability | ||
| 303 | #cat: measure from the stdev and mean of its pixel neighborhood. | ||
| 304 | |||
| 305 | Code originally written by Austin Hicklin for FBI ATU | ||
| 306 | Modified by Michael D. Garris (NIST) Sept. 25, 2000 | ||
| 307 | |||
| 308 | GrayScaleReliability - reasonable reliability heuristic, returns | ||
| 309 | 0.0 .. 1.0 based on stdev and Mean of a localized histogram where | ||
| 310 | "ideal" stdev is >=64; "ideal" Mean is 127. In a 1 ridge radius | ||
| 311 | (11 pixels), if the bytevalue (shade of gray) in the image has a | ||
| 312 | stdev of >= 64 & a mean of 127, returns 1.0 (well defined | ||
| 313 | light & dark areas in equal proportions). | ||
| 314 | |||
| 315 | Input: | ||
| 316 | minutia - structure containing detected minutia | ||
| 317 | idata - 8-bit grayscale fingerprint image | ||
| 318 | iw - width (in pixels) of the image | ||
| 319 | ih - height (in pixels) of the image | ||
| 320 | radius_pix - pixel radius of surrounding neighborhood | ||
| 321 | Return Value: | ||
| 322 | reliability - computed reliability measure | ||
| 323 | ************************************************************************/ | ||
| 324 | 3495 | double grayscale_reliability(MINUTIA *minutia, unsigned char *idata, | |
| 325 | const int iw, const int ih, const int radius_pix) | ||
| 326 | { | ||
| 327 | 3495 | double mean, stdev; | |
| 328 | 3495 | double reliability; | |
| 329 | |||
| 330 | 3495 | get_neighborhood_stats(&mean, &stdev, minutia, idata, iw, ih, radius_pix); | |
| 331 | |||
| 332 |
4/6✓ Branch 0 (3→4) taken 3495 times.
✗ Branch 1 (3→5) not taken.
✓ Branch 2 (5→6) taken 3474 times.
✓ Branch 3 (5→8) taken 21 times.
✓ Branch 4 (6→7) taken 3474 times.
✗ Branch 5 (6→8) not taken.
|
3495 | reliability = min((stdev>IDEALSTDEV ? 1.0 : stdev/(double)IDEALSTDEV), |
| 333 | (1.0-(fabs(mean-IDEALMEAN)/(double)IDEALMEAN))); | ||
| 334 | |||
| 335 | 3495 | return(reliability); | |
| 336 | } | ||
| 337 | |||
| 338 | |||
| 339 | /*********************************************************************** | ||
| 340 | ************************************************************************ | ||
| 341 | #cat: get_neighborhood_stats - Given a minutia point, computes the mean | ||
| 342 | #cat: and stdev of the 8-bit grayscale pixels values in a | ||
| 343 | #cat: surrounding neighborhood with specified radius. | ||
| 344 | |||
| 345 | Code originally written by Austin Hicklin for FBI ATU | ||
| 346 | Modified by Michael D. Garris (NIST) Sept. 25, 2000 | ||
| 347 | |||
| 348 | Input: | ||
| 349 | minutia - structure containing detected minutia | ||
| 350 | idata - 8-bit grayscale fingerprint image | ||
| 351 | iw - width (in pixels) of the image | ||
| 352 | ih - height (in pixels) of the image | ||
| 353 | radius_pix - pixel radius of surrounding neighborhood | ||
| 354 | Output: | ||
| 355 | mean - mean of neighboring pixels | ||
| 356 | stdev - standard deviation of neighboring pixels | ||
| 357 | ************************************************************************/ | ||
| 358 | 3495 | void get_neighborhood_stats(double *mean, double *stdev, MINUTIA *minutia, | |
| 359 | unsigned char *idata, const int iw, const int ih, | ||
| 360 | const int radius_pix) | ||
| 361 | { | ||
| 362 | 3495 | int i, x, y, rows, cols; | |
| 363 | 3495 | int n = 0, sumX = 0, sumXX = 0; | |
| 364 | 3495 | int histogram[256]; | |
| 365 | |||
| 366 | /* Zero out histogram. */ | ||
| 367 | 3495 | memset(histogram, 0, 256 * sizeof(int)); | |
| 368 | |||
| 369 | /* Set minutia's coordinate variables. */ | ||
| 370 | 3495 | x = minutia->x; | |
| 371 | 3495 | y = minutia->y; | |
| 372 | |||
| 373 | |||
| 374 | /* If minutiae point is within sampleboxsize distance of image border, */ | ||
| 375 | /* a value of 0 reliability is returned. */ | ||
| 376 |
3/6✓ Branch 0 (2→3) taken 3495 times.
✗ Branch 1 (2→6) not taken.
✓ Branch 2 (3→4) taken 3495 times.
✗ Branch 3 (3→6) not taken.
✓ Branch 4 (4→5) taken 3495 times.
✗ Branch 5 (4→6) not taken.
|
3495 | if ((x < radius_pix) || (x > iw-radius_pix-1) || |
| 377 |
1/2✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→7) taken 3495 times.
|
3495 | (y < radius_pix) || (y > ih-radius_pix-1)) { |
| 378 | ✗ | *mean = 0.0; | |
| 379 | ✗ | *stdev = 0.0; | |
| 380 | ✗ | return; | |
| 381 | |||
| 382 | } | ||
| 383 | |||
| 384 | /* Foreach row in neighborhood ... */ | ||
| 385 | 3495 | for(rows = y - radius_pix; | |
| 386 |
2/2✓ Branch 0 (12→8) taken 3495 times.
✓ Branch 1 (12→16) taken 3495 times.
|
6990 | rows <= y + radius_pix; |
| 387 | 3495 | rows++){ | |
| 388 | /* Foreach column in neighborhood ... */ | ||
| 389 | 3495 | for(cols = x - radius_pix; | |
| 390 |
2/2✓ Branch 0 (10→9) taken 3495 times.
✓ Branch 1 (10→11) taken 3495 times.
|
6990 | cols <= x + radius_pix; |
| 391 | 3495 | cols++){ | |
| 392 | /* Bump neighbor's pixel value bin in histogram. */ | ||
| 393 | 3495 | histogram[*(idata+(rows * iw)+cols)]++; | |
| 394 | } | ||
| 395 | } | ||
| 396 | |||
| 397 | /* Foreach grayscale pixel bin ... */ | ||
| 398 |
2/2✓ Branch 0 (16→13) taken 894720 times.
✓ Branch 1 (16→17) taken 3495 times.
|
898215 | for(i = 0; i < 256; i++){ |
| 399 |
2/2✓ Branch 0 (13→14) taken 3495 times.
✓ Branch 1 (13→15) taken 891225 times.
|
894720 | if(histogram[i]){ |
| 400 | /* Accumulate Sum(X[i]) */ | ||
| 401 | 3495 | sumX += (i * histogram[i]); | |
| 402 | /* Accumulate Sum(X[i]^2) */ | ||
| 403 | 3495 | sumXX += (i * i * histogram[i]); | |
| 404 | /* Accumulate N samples */ | ||
| 405 | 3495 | n += histogram[i]; | |
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | /* Mean = Sum(X[i])/N */ | ||
| 410 | 3495 | *mean = sumX/(double)n; | |
| 411 | /* Stdev = sqrt((Sum(X[i]^2)/N) - Mean^2) */ | ||
| 412 | 3495 | *stdev = sqrt((sumXX/(double)n) - ((*mean)*(*mean))); | |
| 413 | } | ||
| 414 | |||
| 415 | /*********************************************************************** | ||
| 416 | ************************************************************************ | ||
| 417 | #cat: reliability_fr_quality_map - Takes a set of minutiae and assigns | ||
| 418 | #cat: each one a reliability measure based on 1 of 5 possible | ||
| 419 | #cat: quality levels from its location in a quality map. | ||
| 420 | |||
| 421 | Input: | ||
| 422 | minutiae - structure contining the detected minutia | ||
| 423 | quality_map - map with blocks assigned 1 of 5 quality levels | ||
| 424 | map_w - width (in blocks) of the map | ||
| 425 | map_h - height (in blocks) of the map | ||
| 426 | blocksize - size (in pixels) of each block in the map | ||
| 427 | Output: | ||
| 428 | minutiae - updated reliability members | ||
| 429 | Return Code: | ||
| 430 | Zero - successful completion | ||
| 431 | Negative - system error | ||
| 432 | ************************************************************************/ | ||
| 433 |