| 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: MAPS.C | ||
| 49 | AUTHOR: Michael D. Garris | ||
| 50 | DATE: 03/16/1999 | ||
| 51 | UPDATED: 10/04/1999 Version 2 by MDG | ||
| 52 | UPDATED: 10/26/1999 by MDG | ||
| 53 | To permit margin blocks to be flagged in | ||
| 54 | low contrast and low flow maps. | ||
| 55 | UPDATED: 03/16/2005 by MDG | ||
| 56 | |||
| 57 | Contains routines responsible for computing various block-based | ||
| 58 | maps (including directional ridge flow maps) from an arbitrarily- | ||
| 59 | sized image as part of the NIST Latent Fingerprint System (LFS). | ||
| 60 | |||
| 61 | *********************************************************************** | ||
| 62 | ROUTINES: | ||
| 63 | gen_image_maps() | ||
| 64 | gen_initial_maps() | ||
| 65 | interpolate_direction_map() | ||
| 66 | morph_TF_map() | ||
| 67 | pixelize_map() | ||
| 68 | smooth_direction_map() | ||
| 69 | gen_high_curve_map() | ||
| 70 | gen_imap() | ||
| 71 | gen_initial_imap() | ||
| 72 | primary_dir_test() | ||
| 73 | secondary_fork_test() | ||
| 74 | remove_incon_dirs() | ||
| 75 | test_top_edge() | ||
| 76 | test_right_edge() | ||
| 77 | test_bottom_edge() | ||
| 78 | test_left_edge() | ||
| 79 | remove_dir() | ||
| 80 | average_8nbr_dir() | ||
| 81 | num_valid_8nbrs() | ||
| 82 | smooth_imap() | ||
| 83 | gen_nmap() | ||
| 84 | vorticity() | ||
| 85 | accum_nbr_vorticity() | ||
| 86 | curvature() | ||
| 87 | |||
| 88 | ***********************************************************************/ | ||
| 89 | |||
| 90 | #include <stdio.h> | ||
| 91 | #include <lfs.h> | ||
| 92 | #include <morph.h> | ||
| 93 | #include <log.h> | ||
| 94 | |||
| 95 | /************************************************************************* | ||
| 96 | ************************************************************************** | ||
| 97 | #cat: gen_image_maps - Computes a set of image maps based on Version 2 | ||
| 98 | #cat: of the NIST LFS System. The first map is a Direction Map | ||
| 99 | #cat: which is a 2D vector of integer directions, where each | ||
| 100 | #cat: direction represents the dominant ridge flow in a block of | ||
| 101 | #cat: the input grayscale image. The Low Contrast Map flags | ||
| 102 | #cat: blocks with insufficient contrast. The Low Flow Map flags | ||
| 103 | #cat: blocks with insufficient ridge flow. The High Curve Map | ||
| 104 | #cat: flags blocks containing high curvature. This routine will | ||
| 105 | #cat: generate maps for an arbitrarily sized, non-square, image. | ||
| 106 | |||
| 107 | Input: | ||
| 108 | pdata - padded input image data (8 bits [0..256) grayscale) | ||
| 109 | pw - padded width (in pixels) of the input image | ||
| 110 | ph - padded height (in pixels) of the input image | ||
| 111 | dir2rad - lookup table for converting integer directions | ||
| 112 | dftwaves - structure containing the DFT wave forms | ||
| 113 | dftgrids - structure containing the rotated pixel grid offsets | ||
| 114 | lfsparms - parameters and thresholds for controlling LFS | ||
| 115 | Output: | ||
| 116 | odmap - points to the created Direction Map | ||
| 117 | olcmap - points to the created Low Contrast Map | ||
| 118 | olfmap - points to the Low Ridge Flow Map | ||
| 119 | ohcmap - points to the High Curvature Map | ||
| 120 | omw - width (in blocks) of the maps | ||
| 121 | omh - height (in blocks) of the maps | ||
| 122 | Return Code: | ||
| 123 | Zero - successful completion | ||
| 124 | Negative - system error | ||
| 125 | **************************************************************************/ | ||
| 126 | 48 | int gen_image_maps(int **odmap, int **olcmap, int **olfmap, int **ohcmap, | |
| 127 | int *omw, int *omh, | ||
| 128 | unsigned char *pdata, const int pw, const int ph, | ||
| 129 | const DIR2RAD *dir2rad, const DFTWAVES *dftwaves, | ||
| 130 | const ROTGRIDS *dftgrids, const LFSPARMS *lfsparms) | ||
| 131 | { | ||
| 132 | 48 | int *direction_map, *low_contrast_map, *low_flow_map, *high_curve_map; | |
| 133 | 48 | int mw, mh, iw, ih; | |
| 134 | 48 | int *blkoffs; | |
| 135 | 48 | int ret; /* return code */ | |
| 136 | |||
| 137 | /* 1. Compute block offsets for the entire image, accounting for pad */ | ||
| 138 | /* Block_offsets() assumes square block (grid), so ERROR otherwise. */ | ||
| 139 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 48 times.
|
48 | if(dftgrids->grid_w != dftgrids->grid_h){ |
| 140 | ✗ | fprintf(stderr, | |
| 141 | "ERROR : gen_image_maps : DFT grids must be square\n"); | ||
| 142 | ✗ | return(-540); | |
| 143 | } | ||
| 144 | /* Compute unpadded image dimensions. */ | ||
| 145 | 48 | iw = pw - (dftgrids->pad<<1); | |
| 146 | 48 | ih = ph - (dftgrids->pad<<1); | |
| 147 |
1/2✓ Branch 0 (6→7) taken 48 times.
✗ Branch 1 (6→36) not taken.
|
48 | if((ret = block_offsets(&blkoffs, &mw, &mh, iw, ih, |
| 148 | dftgrids->pad, lfsparms->blocksize))){ | ||
| 149 | return(ret); | ||
| 150 | } | ||
| 151 | |||
| 152 | /* 2. Generate initial Direction Map and Low Contrast Map*/ | ||
| 153 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→11) taken 48 times.
|
48 | if((ret = gen_initial_maps(&direction_map, &low_contrast_map, |
| 154 | &low_flow_map, blkoffs, mw, mh, | ||
| 155 | pdata, pw, ph, dftwaves, dftgrids, lfsparms))){ | ||
| 156 | /* Free memory allocated to this point. */ | ||
| 157 | ✗ | g_free(blkoffs); | |
| 158 | ✗ | return(ret); | |
| 159 | } | ||
| 160 | |||
| 161 |
1/2✗ Branch 0 (12→13) not taken.
✓ Branch 1 (12→17) taken 48 times.
|
48 | if((ret = morph_TF_map(low_flow_map, mw, mh, lfsparms))){ |
| 162 | ✗ | g_free(direction_map); | |
| 163 | ✗ | g_free(low_contrast_map); | |
| 164 | ✗ | g_free(low_flow_map); | |
| 165 | ✗ | return(ret); | |
| 166 | } | ||
| 167 | |||
| 168 | /* 3. Remove directions that are inconsistent with neighbors */ | ||
| 169 | 48 | remove_incon_dirs(direction_map, mw, mh, dir2rad, lfsparms); | |
| 170 | |||
| 171 | |||
| 172 | /* 4. Smooth Direction Map values with their neighbors */ | ||
| 173 | 48 | smooth_direction_map(direction_map, low_contrast_map, mw, mh, | |
| 174 | dir2rad, lfsparms); | ||
| 175 | |||
| 176 | /* 5. Interpolate INVALID direction blocks with their valid neighbors. */ | ||
| 177 |
1/2✗ Branch 0 (20→21) not taken.
✓ Branch 1 (20→25) taken 48 times.
|
48 | if((ret = interpolate_direction_map(direction_map, low_contrast_map, |
| 178 | mw, mh, lfsparms))){ | ||
| 179 | ✗ | g_free(direction_map); | |
| 180 | ✗ | g_free(low_contrast_map); | |
| 181 | ✗ | g_free(low_flow_map); | |
| 182 | ✗ | return(ret); | |
| 183 | } | ||
| 184 | |||
| 185 | /* May be able to skip steps 6 and/or 7 if computation time */ | ||
| 186 | /* is a critical factor. */ | ||
| 187 | |||
| 188 | /* 6. Remove directions that are inconsistent with neighbors */ | ||
| 189 | 48 | remove_incon_dirs(direction_map, mw, mh, dir2rad, lfsparms); | |
| 190 | |||
| 191 | /* 7. Smooth Direction Map values with their neighbors. */ | ||
| 192 | 48 | smooth_direction_map(direction_map, low_contrast_map, mw, mh, | |
| 193 | dir2rad, lfsparms); | ||
| 194 | |||
| 195 | /* 8. Set the Direction Map values in the image margin to INVALID. */ | ||
| 196 | 48 | set_margin_blocks(direction_map, mw, mh, INVALID_DIR); | |
| 197 | |||
| 198 | /* 9. Generate High Curvature Map from interpolated Direction Map. */ | ||
| 199 |
1/2✗ Branch 0 (29→30) not taken.
✓ Branch 1 (29→34) taken 48 times.
|
48 | if((ret = gen_high_curve_map(&high_curve_map, direction_map, mw, mh, |
| 200 | lfsparms))){ | ||
| 201 | ✗ | g_free(direction_map); | |
| 202 | ✗ | g_free(low_contrast_map); | |
| 203 | ✗ | g_free(low_flow_map); | |
| 204 | ✗ | return(ret); | |
| 205 | } | ||
| 206 | |||
| 207 | /* Deallocate working memory. */ | ||
| 208 | 48 | g_free(blkoffs); | |
| 209 | |||
| 210 | 48 | *odmap = direction_map; | |
| 211 | 48 | *olcmap = low_contrast_map; | |
| 212 | 48 | *olfmap = low_flow_map; | |
| 213 | 48 | *ohcmap = high_curve_map; | |
| 214 | 48 | *omw = mw; | |
| 215 | 48 | *omh = mh; | |
| 216 | 48 | return(0); | |
| 217 | } | ||
| 218 | |||
| 219 | /************************************************************************* | ||
| 220 | ************************************************************************** | ||
| 221 | #cat: gen_initial_maps - Creates an initial Direction Map from the given | ||
| 222 | #cat: input image. It very important that the image be properly | ||
| 223 | #cat: padded so that rotated grids along the boundary of the image | ||
| 224 | #cat: do not access unkown memory. The rotated grids are used by a | ||
| 225 | #cat: DFT-based analysis to determine the integer directions | ||
| 226 | #cat: in the map. Typically this initial vector of directions will | ||
| 227 | #cat: subsequently have weak or inconsistent directions removed | ||
| 228 | #cat: followed by a smoothing process. The resulting Direction | ||
| 229 | #cat: Map contains valid directions >= 0 and INVALID values = -1. | ||
| 230 | #cat: This routine also computes and returns 2 other image maps. | ||
| 231 | #cat: The Low Contrast Map flags blocks in the image with | ||
| 232 | #cat: insufficient contrast. Blocks with low contrast have a | ||
| 233 | #cat: corresponding direction of INVALID in the Direction Map. | ||
| 234 | #cat: The Low Flow Map flags blocks in which the DFT analyses | ||
| 235 | #cat: could not determine a significant ridge flow. Blocks with | ||
| 236 | #cat: low ridge flow also have a corresponding direction of | ||
| 237 | #cat: INVALID in the Direction Map. | ||
| 238 | |||
| 239 | Input: | ||
| 240 | blkoffs - offsets to the pixel origin of each block in the padded image | ||
| 241 | mw - number of blocks horizontally in the padded input image | ||
| 242 | mh - number of blocks vertically in the padded input image | ||
| 243 | pdata - padded input image data (8 bits [0..256) grayscale) | ||
| 244 | pw - width (in pixels) of the padded input image | ||
| 245 | ph - height (in pixels) of the padded input image | ||
| 246 | dftwaves - structure containing the DFT wave forms | ||
| 247 | dftgrids - structure containing the rotated pixel grid offsets | ||
| 248 | lfsparms - parameters and thresholds for controlling LFS | ||
| 249 | Output: | ||
| 250 | odmap - points to the newly created Direction Map | ||
| 251 | olcmap - points to the newly created Low Contrast Map | ||
| 252 | Return Code: | ||
| 253 | Zero - successful completion | ||
| 254 | Negative - system error | ||
| 255 | **************************************************************************/ | ||
| 256 | 48 | int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, | |
| 257 | int *blkoffs, const int mw, const int mh, | ||
| 258 | unsigned char *pdata, const int pw, const int ph, | ||
| 259 | const DFTWAVES *dftwaves, const ROTGRIDS *dftgrids, | ||
| 260 | const LFSPARMS *lfsparms) | ||
| 261 | { | ||
| 262 | 48 | int *direction_map, *low_contrast_map, *low_flow_map; | |
| 263 | 48 | int bi, bsize, blkdir; | |
| 264 | 48 | int *wis, *powmax_dirs; | |
| 265 | 48 | double **powers, *powmaxs, *pownorms; | |
| 266 | 48 | int nstats; | |
| 267 | 48 | int ret; /* return code */ | |
| 268 | 48 | int dft_offset; | |
| 269 | 48 | int xminlimit, xmaxlimit, yminlimit, ymaxlimit; | |
| 270 | 48 | int win_x, win_y, low_contrast_offset; | |
| 271 | |||
| 272 | 48 | print2log("INITIAL MAP\n"); | |
| 273 | |||
| 274 | /* Compute total number of blocks in map */ | ||
| 275 |
2/4✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 48 times.
✓ Branch 2 (5→6) taken 48 times.
✗ Branch 3 (5→11) not taken.
|
48 | ASSERT_INT_MUL(mw, mh); |
| 276 | 48 | bsize = mw * mh; | |
| 277 | |||
| 278 | /* Allocate Direction Map memory */ | ||
| 279 | 48 | direction_map = (int *)g_malloc(bsize * sizeof(int)); | |
| 280 | /* Initialize the Direction Map to INVALID (-1). */ | ||
| 281 | 48 | memset(direction_map, INVALID_DIR, bsize * sizeof(int)); | |
| 282 | |||
| 283 | /* Allocate Low Contrast Map memory */ | ||
| 284 | 48 | low_contrast_map = (int *)g_malloc(bsize * sizeof(int)); | |
| 285 | /* Initialize the Low Contrast Map to FALSE (0). */ | ||
| 286 | 48 | memset(low_contrast_map, 0, bsize * sizeof(int)); | |
| 287 | |||
| 288 | /* Allocate Low Ridge Flow Map memory */ | ||
| 289 | 48 | low_flow_map = (int *)g_malloc(bsize * sizeof(int)); | |
| 290 | /* Initialize the Low Flow Map to FALSE (0). */ | ||
| 291 | 48 | memset(low_flow_map, 0, bsize * sizeof(int)); | |
| 292 | |||
| 293 | /* Allocate DFT directional power vectors */ | ||
| 294 |
1/2✗ Branch 0 (10→12) not taken.
✓ Branch 1 (10→16) taken 48 times.
|
48 | if((ret = alloc_dir_powers(&powers, dftwaves->nwaves, dftgrids->ngrids))){ |
| 295 | /* Free memory allocated to this point. */ | ||
| 296 | ✗ | g_free(direction_map); | |
| 297 | ✗ | g_free(low_contrast_map); | |
| 298 | ✗ | g_free(low_flow_map); | |
| 299 | ✗ | return(ret); | |
| 300 | } | ||
| 301 | |||
| 302 | /* Allocate DFT power statistic arrays */ | ||
| 303 | /* Compute length of statistics arrays. Statistics not needed */ | ||
| 304 | /* for the first DFT wave, so the length is number of waves - 1. */ | ||
| 305 | 48 | nstats = dftwaves->nwaves - 1; | |
| 306 |
1/2✗ Branch 0 (17→18) not taken.
✓ Branch 1 (17→23) taken 48 times.
|
48 | if((ret = alloc_power_stats(&wis, &powmaxs, &powmax_dirs, |
| 307 | &pownorms, nstats))){ | ||
| 308 | /* Free memory allocated to this point. */ | ||
| 309 | ✗ | g_free(direction_map); | |
| 310 | ✗ | g_free(low_contrast_map); | |
| 311 | ✗ | g_free(low_flow_map); | |
| 312 | ✗ | free_dir_powers(powers, dftwaves->nwaves); | |
| 313 | ✗ | return(ret); | |
| 314 | } | ||
| 315 | |||
| 316 | /* Compute special window origin limits for determining low contrast. */ | ||
| 317 | /* These pixel limits avoid analyzing the padded borders of the image. */ | ||
| 318 | 48 | xminlimit = dftgrids->pad; | |
| 319 | 48 | yminlimit = dftgrids->pad; | |
| 320 | 48 | xmaxlimit = pw - dftgrids->pad - lfsparms->windowsize - 1; | |
| 321 | 48 | ymaxlimit = ph - dftgrids->pad - lfsparms->windowsize - 1; | |
| 322 | |||
| 323 | /* Foreach block in image ... */ | ||
| 324 |
2/2✓ Branch 0 (70→24) taken 50730 times.
✓ Branch 1 (70→71) taken 48 times.
|
50778 | for(bi = 0; bi < bsize; bi++){ |
| 325 | /* Adjust block offset from pointing to block origin to pointing */ | ||
| 326 | /* to surrounding window origin. */ | ||
| 327 | 50730 | dft_offset = blkoffs[bi] - (lfsparms->windowoffset * pw) - | |
| 328 | lfsparms->windowoffset; | ||
| 329 | |||
| 330 | /* Compute pixel coords of window origin. */ | ||
| 331 | 50730 | win_x = dft_offset % pw; | |
| 332 | 50730 | win_y = (int)(dft_offset / pw); | |
| 333 | |||
| 334 | /* Make sure the current window does not access padded image pixels */ | ||
| 335 | /* for analyzing low contrast. */ | ||
| 336 | 50730 | win_x = max(xminlimit, win_x); | |
| 337 | 50730 | win_x = min(xmaxlimit, win_x); | |
| 338 | 50730 | win_y = max(yminlimit, win_y); | |
| 339 | 50730 | win_y = min(ymaxlimit, win_y); | |
| 340 | 50730 | low_contrast_offset = (win_y * pw) + win_x; | |
| 341 | |||
| 342 | 50730 | print2log(" BLOCK %2d (%2d, %2d) ", bi, bi%mw, bi/mw); | |
| 343 | |||
| 344 | /* If block is low contrast ... */ | ||
| 345 |
2/2✓ Branch 0 (26→27) taken 4591 times.
✓ Branch 1 (26→39) taken 46139 times.
|
50730 | if((ret = low_contrast_block(low_contrast_offset, lfsparms->windowsize, |
| 346 | pdata, pw, ph, lfsparms))){ | ||
| 347 | /* If system error ... */ | ||
| 348 |
1/2✗ Branch 0 (27→28) not taken.
✓ Branch 1 (27→37) taken 4591 times.
|
4591 | if(ret < 0){ |
| 349 | ✗ | g_free(direction_map); | |
| 350 | ✗ | g_free(low_contrast_map); | |
| 351 | ✗ | g_free(low_flow_map); | |
| 352 | ✗ | free_dir_powers(powers, dftwaves->nwaves); | |
| 353 | ✗ | g_free(wis); | |
| 354 | ✗ | g_free(powmaxs); | |
| 355 | ✗ | g_free(powmax_dirs); | |
| 356 | ✗ | g_free(pownorms); | |
| 357 | ✗ | return(ret); | |
| 358 | } | ||
| 359 | |||
| 360 | /* Otherwise, block is low contrast ... */ | ||
| 361 | 4591 | print2log("LOW CONTRAST\n"); | |
| 362 | 4591 | low_contrast_map[bi] = TRUE; | |
| 363 | /* Direction Map's block is already set to INVALID. */ | ||
| 364 | } | ||
| 365 | /* Otherwise, sufficient contrast for DFT processing ... */ | ||
| 366 | else { | ||
| 367 | 46139 | print2log("\n"); | |
| 368 | |||
| 369 | /* Compute DFT powers */ | ||
| 370 |
1/2✗ Branch 0 (41→42) not taken.
✓ Branch 1 (41→51) taken 46139 times.
|
46139 | if((ret = dft_dir_powers(powers, pdata, low_contrast_offset, pw, ph, |
| 371 | dftwaves, dftgrids))){ | ||
| 372 | /* Free memory allocated to this point. */ | ||
| 373 | ✗ | g_free(direction_map); | |
| 374 | ✗ | g_free(low_contrast_map); | |
| 375 | ✗ | g_free(low_flow_map); | |
| 376 | ✗ | free_dir_powers(powers, dftwaves->nwaves); | |
| 377 | ✗ | g_free(wis); | |
| 378 | ✗ | g_free(powmaxs); | |
| 379 | ✗ | g_free(powmax_dirs); | |
| 380 | ✗ | g_free(pownorms); | |
| 381 | ✗ | return(ret); | |
| 382 | } | ||
| 383 | |||
| 384 | /* Compute DFT power statistics, skipping first applied DFT */ | ||
| 385 | /* wave. This is dependent on how the primary and secondary */ | ||
| 386 | /* direction tests work below. */ | ||
| 387 |
1/2✗ Branch 0 (52→53) not taken.
✓ Branch 1 (52→62) taken 46139 times.
|
46139 | if((ret = dft_power_stats(wis, powmaxs, powmax_dirs, pownorms, powers, |
| 388 | 1, dftwaves->nwaves, dftgrids->ngrids))){ | ||
| 389 | /* Free memory allocated to this point. */ | ||
| 390 | ✗ | g_free(direction_map); | |
| 391 | ✗ | g_free(low_contrast_map); | |
| 392 | ✗ | g_free(low_flow_map); | |
| 393 | ✗ | free_dir_powers(powers, dftwaves->nwaves); | |
| 394 | ✗ | g_free(wis); | |
| 395 | ✗ | g_free(powmaxs); | |
| 396 | ✗ | g_free(powmax_dirs); | |
| 397 | ✗ | g_free(pownorms); | |
| 398 | ✗ | return(ret); | |
| 399 | } | ||
| 400 | |||
| 401 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 402 | { int _w; | ||
| 403 | fprintf(logfp, " Power\n"); | ||
| 404 | for(_w = 0; _w < nstats; _w++){ | ||
| 405 | /* Add 1 to wis[w] to create index to original g_dft_coefs[] */ | ||
| 406 | fprintf(logfp, " wis[%d] %d %12.3f %2d %9.3f %12.3f\n", | ||
| 407 | _w, wis[_w]+1, | ||
| 408 | powmaxs[wis[_w]], powmax_dirs[wis[_w]], pownorms[wis[_w]], | ||
| 409 | powers[0][powmax_dirs[wis[_w]]]); | ||
| 410 | } | ||
| 411 | } | ||
| 412 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 413 | |||
| 414 | /* Conduct primary direction test */ | ||
| 415 | 46139 | blkdir = primary_dir_test(powers, wis, powmaxs, powmax_dirs, | |
| 416 | pownorms, nstats, lfsparms); | ||
| 417 | |||
| 418 |
2/2✓ Branch 0 (63→64) taken 35558 times.
✓ Branch 1 (63→65) taken 10581 times.
|
46139 | if(blkdir != INVALID_DIR) |
| 419 | 35558 | direction_map[bi] = blkdir; | |
| 420 | else{ | ||
| 421 | /* Conduct secondary (fork) direction test */ | ||
| 422 | 10581 | blkdir = secondary_fork_test(powers, wis, powmaxs, powmax_dirs, | |
| 423 | pownorms, nstats, lfsparms); | ||
| 424 |
2/2✓ Branch 0 (66→67) taken 473 times.
✓ Branch 1 (66→68) taken 10108 times.
|
10581 | if(blkdir != INVALID_DIR) |
| 425 | 473 | direction_map[bi] = blkdir; | |
| 426 | /* Otherwise current direction in Direction Map remains INVALID */ | ||
| 427 | else | ||
| 428 | /* Flag the block as having LOW RIDGE FLOW. */ | ||
| 429 | 10108 | low_flow_map[bi] = TRUE; | |
| 430 | } | ||
| 431 | |||
| 432 | } /* End DFT */ | ||
| 433 | } /* bi */ | ||
| 434 | |||
| 435 | /* Deallocate working memory */ | ||
| 436 | 48 | free_dir_powers(powers, dftwaves->nwaves); | |
| 437 | 48 | g_free(wis); | |
| 438 | 48 | g_free(powmaxs); | |
| 439 | 48 | g_free(powmax_dirs); | |
| 440 | 48 | g_free(pownorms); | |
| 441 | |||
| 442 | 48 | *odmap = direction_map; | |
| 443 | 48 | *olcmap = low_contrast_map; | |
| 444 | 48 | *olfmap = low_flow_map; | |
| 445 | 48 | return(0); | |
| 446 | } | ||
| 447 | |||
| 448 | /************************************************************************* | ||
| 449 | ************************************************************************** | ||
| 450 | #cat: interpolate_direction_map - Take a Direction Map and Low Contrast | ||
| 451 | #cat: Map and attempts to fill in INVALID directions in the | ||
| 452 | #cat: Direction Map based on a blocks valid neighbors. The | ||
| 453 | #cat: valid neighboring directions are combined in a weighted | ||
| 454 | #cat: average inversely proportional to their distance from | ||
| 455 | #cat: the block being interpolated. Low Contrast blocks are | ||
| 456 | #cat: used to prempt the search for a valid neighbor in a | ||
| 457 | #cat: specific direction, which keeps the process from | ||
| 458 | #cat: interpolating directions for blocks in the background and | ||
| 459 | #cat: and perimeter of the fingerprint in the image. | ||
| 460 | |||
| 461 | Input: | ||
| 462 | direction_map - map of blocks containing directional ridge flow | ||
| 463 | low_contrast_map - map of blocks flagged as LOW CONTRAST | ||
| 464 | mw - number of blocks horizontally in the maps | ||
| 465 | mh - number of blocks vertically in the maps | ||
| 466 | lfsparms - parameters and thresholds for controlling LFS | ||
| 467 | Output: | ||
| 468 | direction_map - contains the newly interpolated results | ||
| 469 | Return Code: | ||
| 470 | Zero - successful completion | ||
| 471 | Negative - system error | ||
| 472 | **************************************************************************/ | ||
| 473 | 48 | int interpolate_direction_map(int *direction_map, int *low_contrast_map, | |
| 474 | const int mw, const int mh, const LFSPARMS *lfsparms) | ||
| 475 | { | ||
| 476 | 48 | int x, y, new_dir; | |
| 477 | 48 | int n_dir, e_dir, s_dir, w_dir; | |
| 478 | 48 | int n_dist = 0, e_dist = 0, s_dist = 0, w_dist = 0, total_dist; | |
| 479 | 48 | int n_found, e_found, s_found, w_found, total_found; | |
| 480 | 48 | int n_delta = 0, e_delta = 0, s_delta = 0, w_delta = 0, total_delta; | |
| 481 | 48 | int nbr_x, nbr_y; | |
| 482 | 48 | int *omap, *dptr, *cptr, *optr; | |
| 483 | 48 | double avr_dir; | |
| 484 | |||
| 485 | 48 | print2log("INTERPOLATE DIRECTION MAP\n"); | |
| 486 | |||
| 487 | /* Allocate output (interpolated) Direction Map. */ | ||
| 488 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 48 times.
|
48 | ASSERT_SIZE_MUL(mw, mh); |
| 489 |
1/2✓ Branch 0 (5→6) taken 48 times.
✗ Branch 1 (5→8) not taken.
|
48 | ASSERT_SIZE_MUL(mw * mh, sizeof(int)); |
| 490 | 48 | omap = (int *)g_malloc(mw * mh * sizeof(int)); | |
| 491 | |||
| 492 | /* Set pointers to the first block in the maps. */ | ||
| 493 | 48 | dptr = direction_map; | |
| 494 | 48 | cptr = low_contrast_map; | |
| 495 | 48 | optr = omap; | |
| 496 | |||
| 497 | /* Foreach block in the maps ... */ | ||
| 498 |
2/2✓ Branch 0 (53→54) taken 1673 times.
✓ Branch 1 (53→55) taken 48 times.
|
1769 | for(y = 0; y < mh; y++){ |
| 499 |
2/2✓ Branch 0 (51→9) taken 50730 times.
✓ Branch 1 (51→52) taken 1673 times.
|
52403 | for(x = 0; x < mw; x++){ |
| 500 | |||
| 501 | /* If image block is NOT LOW CONTRAST and has INVALID direction ... */ | ||
| 502 |
4/4✓ Branch 0 (9→10) taken 46139 times.
✓ Branch 1 (9→49) taken 4591 times.
✓ Branch 2 (10→11) taken 12738 times.
✓ Branch 3 (10→49) taken 33401 times.
|
50730 | if((!*cptr) && (*dptr == INVALID_DIR)){ |
| 503 | |||
| 504 | /* Set neighbor accumulators to 0. */ | ||
| 505 | 12738 | total_found = 0; | |
| 506 | 12738 | total_dist = 0; | |
| 507 | |||
| 508 | /* Find north neighbor. */ | ||
| 509 |
2/2✓ Branch 0 (12→13) taken 7763 times.
✓ Branch 1 (12→14) taken 4975 times.
|
12738 | if((n_found = find_valid_block(&n_dir, &nbr_x, &nbr_y, |
| 510 | direction_map, low_contrast_map, | ||
| 511 | x, y, mw, mh, 0, -1)) == FOUND){ | ||
| 512 | /* Compute north distance. */ | ||
| 513 | 7763 | n_dist = y - nbr_y; | |
| 514 | /* Accumulate neighbor distance. */ | ||
| 515 | 7763 | total_dist += n_dist; | |
| 516 | /* Bump number of neighbors found. */ | ||
| 517 | 7763 | total_found++; | |
| 518 | } | ||
| 519 | |||
| 520 | /* Find east neighbor. */ | ||
| 521 |
2/2✓ Branch 0 (15→16) taken 8641 times.
✓ Branch 1 (15→17) taken 4097 times.
|
12738 | if((e_found = find_valid_block(&e_dir, &nbr_x, &nbr_y, |
| 522 | direction_map, low_contrast_map, | ||
| 523 | x, y, mw, mh, 1, 0)) == FOUND){ | ||
| 524 | /* Compute east distance. */ | ||
| 525 | 8641 | e_dist = nbr_x - x; | |
| 526 | /* Accumulate neighbor distance. */ | ||
| 527 | 8641 | total_dist += e_dist; | |
| 528 | /* Bump number of neighbors found. */ | ||
| 529 | 8641 | total_found++; | |
| 530 | } | ||
| 531 | |||
| 532 | /* Find south neighbor. */ | ||
| 533 |
2/2✓ Branch 0 (18→19) taken 9466 times.
✓ Branch 1 (18→20) taken 3272 times.
|
12738 | if((s_found = find_valid_block(&s_dir, &nbr_x, &nbr_y, |
| 534 | direction_map, low_contrast_map, | ||
| 535 | x, y, mw, mh, 0, 1)) == FOUND){ | ||
| 536 | /* Compute south distance. */ | ||
| 537 | 9466 | s_dist = nbr_y - y; | |
| 538 | /* Accumulate neighbor distance. */ | ||
| 539 | 9466 | total_dist += s_dist; | |
| 540 | /* Bump number of neighbors found. */ | ||
| 541 | 9466 | total_found++; | |
| 542 | } | ||
| 543 | |||
| 544 | /* Find west neighbor. */ | ||
| 545 |
2/2✓ Branch 0 (21→22) taken 9448 times.
✓ Branch 1 (21→23) taken 3290 times.
|
12738 | if((w_found = find_valid_block(&w_dir, &nbr_x, &nbr_y, |
| 546 | direction_map, low_contrast_map, | ||
| 547 | x, y, mw, mh, -1, 0)) == FOUND){ | ||
| 548 | /* Compute west distance. */ | ||
| 549 | 9448 | w_dist = x - nbr_x; | |
| 550 | /* Accumulate neighbor distance. */ | ||
| 551 | 9448 | total_dist += w_dist; | |
| 552 | /* Bump number of neighbors found. */ | ||
| 553 | 9448 | total_found++; | |
| 554 | } | ||
| 555 | |||
| 556 | /* If a sufficient number of neighbors found (Ex. 2) ... */ | ||
| 557 |
2/2✓ Branch 0 (23→24) taken 10891 times.
✓ Branch 1 (23→48) taken 1847 times.
|
12738 | if(total_found >= lfsparms->min_interpolate_nbrs){ |
| 558 | |||
| 559 | /* Accumulate weighted sum of neighboring directions */ | ||
| 560 | /* inversely related to the distance from current block. */ | ||
| 561 | 10891 | total_delta = 0.0; | |
| 562 | /* If neighbor found to the north ... */ | ||
| 563 |
2/2✓ Branch 0 (24→25) taken 7373 times.
✓ Branch 1 (24→26) taken 3518 times.
|
10891 | if(n_found){ |
| 564 | 7373 | n_delta = total_dist - n_dist; | |
| 565 | 7373 | total_delta += n_delta; | |
| 566 | } | ||
| 567 | /* If neighbor found to the east ... */ | ||
| 568 |
2/2✓ Branch 0 (26→27) taken 8280 times.
✓ Branch 1 (26→28) taken 2611 times.
|
10891 | if(e_found){ |
| 569 | 8280 | e_delta = total_dist - e_dist; | |
| 570 | 8280 | total_delta += e_delta; | |
| 571 | } | ||
| 572 | /* If neighbor found to the south ... */ | ||
| 573 |
2/2✓ Branch 0 (28→29) taken 9188 times.
✓ Branch 1 (28→30) taken 1703 times.
|
10891 | if(s_found){ |
| 574 | 9188 | s_delta = total_dist - s_dist; | |
| 575 | 9188 | total_delta += s_delta; | |
| 576 | } | ||
| 577 | /* If neighbor found to the west ... */ | ||
| 578 |
2/2✓ Branch 0 (30→31) taken 8941 times.
✓ Branch 1 (30→32) taken 1950 times.
|
10891 | if(w_found){ |
| 579 | 8941 | w_delta = total_dist - w_dist; | |
| 580 | 8941 | total_delta += w_delta; | |
| 581 | } | ||
| 582 | |||
| 583 | 10891 | avr_dir = 0.0; | |
| 584 | |||
| 585 |
2/2✓ Branch 0 (32→33) taken 7373 times.
✓ Branch 1 (32→34) taken 3518 times.
|
10891 | if(n_found){ |
| 586 | 7373 | avr_dir += (n_dir*(n_delta/(double)total_delta)); | |
| 587 | } | ||
| 588 |
2/2✓ Branch 0 (34→35) taken 8280 times.
✓ Branch 1 (34→36) taken 2611 times.
|
10891 | if(e_found){ |
| 589 | 8280 | avr_dir += (e_dir*(e_delta/(double)total_delta)); | |
| 590 | } | ||
| 591 |
2/2✓ Branch 0 (36→37) taken 9188 times.
✓ Branch 1 (36→38) taken 1703 times.
|
10891 | if(s_found){ |
| 592 | 9188 | avr_dir += (s_dir*(s_delta/(double)total_delta)); | |
| 593 | } | ||
| 594 |
2/2✓ Branch 0 (38→39) taken 8941 times.
✓ Branch 1 (38→40) taken 1950 times.
|
10891 | if(w_found){ |
| 595 | 8941 | avr_dir += (w_dir*(w_delta/(double)total_delta)); | |
| 596 | } | ||
| 597 | |||
| 598 | /* Need to truncate precision so that answers are consistent */ | ||
| 599 | /* on different computer architectures when rounding doubles. */ | ||
| 600 |
1/2✗ Branch 0 (40→41) not taken.
✓ Branch 1 (40→42) taken 10891 times.
|
10891 | avr_dir = trunc_dbl_precision(avr_dir, TRUNC_SCALE); |
| 601 | |||
| 602 | /* Assign interpolated direction to output Direction Map. */ | ||
| 603 |
1/2✗ Branch 0 (43→44) not taken.
✓ Branch 1 (43→45) taken 10891 times.
|
10891 | new_dir = sround(avr_dir); |
| 604 | |||
| 605 | 10891 | print2log(" Block %d,%d INTERP numnbs=%d newdir=%d\n", | |
| 606 | x, y, total_found, new_dir); | ||
| 607 | |||
| 608 | 10891 | *optr = new_dir; | |
| 609 | } | ||
| 610 | else{ | ||
| 611 | /* Otherwise, the direction remains INVALID. */ | ||
| 612 | 1847 | *optr = *dptr; | |
| 613 | } | ||
| 614 | } | ||
| 615 | else{ | ||
| 616 | /* Otherwise, assign the current direction to the output block. */ | ||
| 617 | 37992 | *optr = *dptr; | |
| 618 | } | ||
| 619 | |||
| 620 | /* Bump to the next block in the maps ... */ | ||
| 621 | 50730 | dptr++; | |
| 622 | 50730 | cptr++; | |
| 623 | 50730 | optr++; | |
| 624 | } | ||
| 625 | } | ||
| 626 | |||
| 627 | /* Copy the interpolated directions into the input map. */ | ||
| 628 | 48 | memcpy(direction_map, omap, mw*mh*sizeof(int)); | |
| 629 | /* Deallocate the working memory. */ | ||
| 630 | 48 | g_free(omap); | |
| 631 | |||
| 632 | /* Return normally. */ | ||
| 633 | 48 | return(0); | |
| 634 | } | ||
| 635 | |||
| 636 | /************************************************************************* | ||
| 637 | ************************************************************************** | ||
| 638 | #cat: morph_tf_map - Takes a 2D vector of TRUE and FALSE values integers | ||
| 639 | #cat: and dialates and erodes the map in an attempt to fill | ||
| 640 | #cat: in voids in the map. | ||
| 641 | |||
| 642 | Input: | ||
| 643 | tfmap - vector of integer block values | ||
| 644 | mw - width (in blocks) of the map | ||
| 645 | mh - height (in blocks) of the map | ||
| 646 | lfsparms - parameters and thresholds for controlling LFS | ||
| 647 | Output: | ||
| 648 | tfmap - resulting morphed map | ||
| 649 | **************************************************************************/ | ||
| 650 | 48 | int morph_TF_map(int *tfmap, const int mw, const int mh, | |
| 651 | const LFSPARMS *lfsparms) | ||
| 652 | { | ||
| 653 | 48 | unsigned char *cimage, *mimage, *cptr; | |
| 654 | 48 | int *mptr; | |
| 655 | 48 | int i; | |
| 656 | |||
| 657 |
2/4✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 48 times.
✓ Branch 2 (4→5) taken 48 times.
✗ Branch 3 (4→8) not taken.
|
48 | ASSERT_INT_MUL(mw, mh); |
| 658 | |||
| 659 | /* Convert TRUE/FALSE map into a binary byte image. */ | ||
| 660 | 48 | cimage = (unsigned char *)g_malloc(mw * mh); | |
| 661 | |||
| 662 | 48 | mimage = (unsigned char *)g_malloc(mw * mh); | |
| 663 | |||
| 664 | 48 | cptr = cimage; | |
| 665 | 48 | mptr = tfmap; | |
| 666 |
2/2✓ Branch 0 (10→9) taken 50730 times.
✓ Branch 1 (10→11) taken 48 times.
|
50826 | for(i = 0; i < mw*mh; i++){ |
| 667 | 50730 | *cptr++ = *mptr++; | |
| 668 | } | ||
| 669 | |||
| 670 | 48 | dilate_charimage_2(cimage, mimage, mw, mh); | |
| 671 | 48 | dilate_charimage_2(mimage, cimage, mw, mh); | |
| 672 | 48 | erode_charimage_2(cimage, mimage, mw, mh); | |
| 673 | 48 | erode_charimage_2(mimage, cimage, mw, mh); | |
| 674 | |||
| 675 | 48 | cptr = cimage; | |
| 676 | 48 | mptr = tfmap; | |
| 677 |
2/2✓ Branch 0 (17→16) taken 50730 times.
✓ Branch 1 (17→18) taken 48 times.
|
50826 | for(i = 0; i < mw*mh; i++){ |
| 678 | 50730 | *mptr++ = *cptr++; | |
| 679 | } | ||
| 680 | |||
| 681 | 48 | g_free(cimage); | |
| 682 | 48 | g_free(mimage); | |
| 683 | |||
| 684 | 48 | return(0); | |
| 685 | } | ||
| 686 | |||
| 687 | /************************************************************************* | ||
| 688 | ************************************************************************** | ||
| 689 | #cat: pixelize_map - Takes a block image map and assigns each pixel in the | ||
| 690 | #cat: image its corresponding block value. This allows block | ||
| 691 | #cat: values in maps to be directly accessed via pixel addresses. | ||
| 692 | |||
| 693 | Input: | ||
| 694 | iw - the width (in pixels) of the corresponding image | ||
| 695 | ih - the height (in pixels) of the corresponding image | ||
| 696 | imap - input block image map | ||
| 697 | mw - the width (in blocks) of the map | ||
| 698 | mh - the height (in blocks) of the map | ||
| 699 | blocksize - the dimension (in pixels) of each block | ||
| 700 | Output: | ||
| 701 | omap - points to the resulting pixelized map | ||
| 702 | Return Code: | ||
| 703 | Zero - successful completion | ||
| 704 | Negative - system error | ||
| 705 | **************************************************************************/ | ||
| 706 | 192 | int pixelize_map(int **omap, const int iw, const int ih, | |
| 707 | int *imap, const int mw, const int mh, const int blocksize) | ||
| 708 | { | ||
| 709 | 192 | int *pmap; | |
| 710 | 192 | int ret, x, y; | |
| 711 | 192 | int *blkoffs, bw, bh, bi; | |
| 712 | 192 | int *spptr, *pptr; | |
| 713 | |||
| 714 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 192 times.
|
192 | ASSERT_SIZE_MUL(iw, ih); |
| 715 |
1/2✓ Branch 0 (4→5) taken 192 times.
✗ Branch 1 (4→8) not taken.
|
192 | ASSERT_SIZE_MUL(iw * ih, sizeof(int)); |
| 716 | |||
| 717 | 192 | pmap = (int *)g_malloc(iw * ih * sizeof(int)); | |
| 718 | |||
| 719 |
1/2✗ Branch 0 (7→9) not taken.
✓ Branch 1 (7→11) taken 192 times.
|
192 | if((ret = block_offsets(&blkoffs, &bw, &bh, iw, ih, 0, blocksize))){ |
| 720 | ✗ | g_free(pmap); | |
| 721 | ✗ | return(ret); | |
| 722 | } | ||
| 723 | |||
| 724 |
2/4✓ Branch 0 (11→12) taken 192 times.
✗ Branch 1 (11→13) not taken.
✗ Branch 2 (12→13) not taken.
✓ Branch 3 (12→23) taken 192 times.
|
192 | if((bw != mw) || (bh != mh)){ |
| 725 | ✗ | g_free(blkoffs); | |
| 726 | ✗ | g_free(pmap); | |
| 727 | ✗ | fprintf(stderr, | |
| 728 | "ERROR : pixelize_map : block dimensions do not match\n"); | ||
| 729 | ✗ | return(-591); | |
| 730 | } | ||
| 731 | |||
| 732 |
2/2✓ Branch 0 (23→17) taken 202920 times.
✓ Branch 1 (23→24) taken 192 times.
|
203112 | for(bi = 0; bi < mw*mh; bi++){ |
| 733 | 202920 | spptr = pmap + blkoffs[bi]; | |
| 734 |
2/2✓ Branch 0 (21→19) taken 1623360 times.
✓ Branch 1 (21→22) taken 202920 times.
|
1826280 | for(y = 0; y < blocksize; y++){ |
| 735 | pptr = spptr; | ||
| 736 |
2/2✓ Branch 0 (19→18) taken 12986880 times.
✓ Branch 1 (19→20) taken 1623360 times.
|
14610240 | for(x = 0; x < blocksize; x++){ |
| 737 | 12986880 | *pptr++ = imap[bi]; | |
| 738 | } | ||
| 739 | 1623360 | spptr += iw; | |
| 740 | } | ||
| 741 | } | ||
| 742 | |||
| 743 | /* Deallocate working memory. */ | ||
| 744 | 192 | g_free(blkoffs); | |
| 745 | /* Assign pixelized map to output pointer. */ | ||
| 746 | 192 | *omap = pmap; | |
| 747 | |||
| 748 | /* Return normally. */ | ||
| 749 | 192 | return(0); | |
| 750 | } | ||
| 751 | |||
| 752 | /************************************************************************* | ||
| 753 | ************************************************************************** | ||
| 754 | #cat: smooth_direction_map - Takes a vector of integer directions and smooths | ||
| 755 | #cat: them by analyzing the direction of adjacent neighbors. | ||
| 756 | |||
| 757 | Input: | ||
| 758 | direction_map - vector of integer block values | ||
| 759 | mw - width (in blocks) of the map | ||
| 760 | mh - height (in blocks) of the map | ||
| 761 | dir2rad - lookup table for converting integer directions | ||
| 762 | lfsparms - parameters and thresholds for controlling LFS | ||
| 763 | Output: | ||
| 764 | imap - vector of smoothed input values | ||
| 765 | **************************************************************************/ | ||
| 766 | 96 | void smooth_direction_map(int *direction_map, int *low_contrast_map, | |
| 767 | const int mw, const int mh, | ||
| 768 | const DIR2RAD *dir2rad, const LFSPARMS *lfsparms) | ||
| 769 | { | ||
| 770 | 96 | int mx, my; | |
| 771 | 96 | int *dptr, *cptr; | |
| 772 | 96 | int avrdir, nvalid; | |
| 773 | 96 | double dir_strength; | |
| 774 | |||
| 775 | 96 | print2log("SMOOTH DIRECTION MAP\n"); | |
| 776 | |||
| 777 | /* Assign pointers to beginning of both maps. */ | ||
| 778 | 96 | dptr = direction_map; | |
| 779 | 96 | cptr = low_contrast_map; | |
| 780 | |||
| 781 | /* Foreach block in maps ... */ | ||
| 782 |
2/2✓ Branch 0 (15→16) taken 3346 times.
✓ Branch 1 (15→17) taken 96 times.
|
3538 | for(my = 0; my < mh; my++){ |
| 783 |
2/2✓ Branch 0 (13→4) taken 101460 times.
✓ Branch 1 (13→14) taken 3346 times.
|
104806 | for(mx = 0; mx < mw; mx++){ |
| 784 | /* If the current block does NOT have LOW CONTRAST ... */ | ||
| 785 |
2/2✓ Branch 0 (4→5) taken 92278 times.
✓ Branch 1 (4→12) taken 9182 times.
|
101460 | if(!*cptr){ |
| 786 | |||
| 787 | /* Compute average direction from neighbors, returning the */ | ||
| 788 | /* number of valid neighbors used in the computation, and */ | ||
| 789 | /* the "strength" of the average direction. */ | ||
| 790 | 92278 | average_8nbr_dir(&avrdir, &dir_strength, &nvalid, | |
| 791 | direction_map, mx, my, mw, mh, dir2rad); | ||
| 792 | |||
| 793 | /* If average direction strength is strong enough */ | ||
| 794 | /* (Ex. thresh==0.2)... */ | ||
| 795 |
2/2✓ Branch 0 (6→7) taken 83572 times.
✓ Branch 1 (6→12) taken 8706 times.
|
92278 | if(dir_strength >= lfsparms->dir_strength_min){ |
| 796 | /* If Direction Map direction is valid ... */ | ||
| 797 |
2/2✓ Branch 0 (7→8) taken 74131 times.
✓ Branch 1 (7→10) taken 9441 times.
|
83572 | if(*dptr != INVALID_DIR){ |
| 798 | /* Conduct valid neighbor test (Ex. thresh==3)... */ | ||
| 799 |
1/2✓ Branch 0 (8→9) taken 74131 times.
✗ Branch 1 (8→12) not taken.
|
74131 | if(nvalid >= lfsparms->rmv_valid_nbr_min){ |
| 800 | |||
| 801 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 802 | fprintf(logfp, " BLOCK %2d (%2d, %2d)\n", | ||
| 803 | mx+(my*mw), mx, my); | ||
| 804 | fprintf(logfp, " Average NBR : %2d %6.3f %d\n", | ||
| 805 | avrdir, dir_strength, nvalid); | ||
| 806 | fprintf(logfp, " 1. Valid NBR (%d >= %d)\n", | ||
| 807 | nvalid, lfsparms->rmv_valid_nbr_min); | ||
| 808 | fprintf(logfp, " Valid Direction = %d\n", *dptr); | ||
| 809 | fprintf(logfp, " Smoothed Direction = %d\n", avrdir); | ||
| 810 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 811 | |||
| 812 | /* Reassign valid direction with average direction. */ | ||
| 813 | 74131 | *dptr = avrdir; | |
| 814 | } | ||
| 815 | } | ||
| 816 | /* Otherwise direction is invalid ... */ | ||
| 817 | else{ | ||
| 818 | /* Even if DIRECTION_MAP value is invalid, if number of */ | ||
| 819 | /* valid neighbors is big enough (Ex. thresh==7)... */ | ||
| 820 |
2/2✓ Branch 0 (10→11) taken 1309 times.
✓ Branch 1 (10→12) taken 8132 times.
|
9441 | if(nvalid >= lfsparms->smth_valid_nbr_min){ |
| 821 | |||
| 822 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 823 | fprintf(logfp, " BLOCK %2d (%2d, %2d)\n", | ||
| 824 | mx+(my*mw), mx, my); | ||
| 825 | fprintf(logfp, " Average NBR : %2d %6.3f %d\n", | ||
| 826 | avrdir, dir_strength, nvalid); | ||
| 827 | fprintf(logfp, " 2. Invalid NBR (%d >= %d)\n", | ||
| 828 | nvalid, lfsparms->smth_valid_nbr_min); | ||
| 829 | fprintf(logfp, " Invalid Direction = %d\n", *dptr); | ||
| 830 | fprintf(logfp, " Smoothed Direction = %d\n", avrdir); | ||
| 831 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 832 | |||
| 833 | /* Assign invalid direction with average direction. */ | ||
| 834 | 1309 | *dptr = avrdir; | |
| 835 | } | ||
| 836 | } | ||
| 837 | } | ||
| 838 | } | ||
| 839 | /* Otherwise, block has LOW CONTRAST, so keep INVALID direction. */ | ||
| 840 | |||
| 841 | /* Bump to next block in maps. */ | ||
| 842 | 101460 | dptr++; | |
| 843 | 101460 | cptr++; | |
| 844 | } | ||
| 845 | } | ||
| 846 | 96 | } | |
| 847 | |||
| 848 | /************************************************************************* | ||
| 849 | ************************************************************************** | ||
| 850 | #cat: gen_high_curve_map - Takes a Direction Map and generates a new map | ||
| 851 | #cat: that flags blocks with HIGH CURVATURE. | ||
| 852 | |||
| 853 | Input: | ||
| 854 | direction_map - map of blocks containing directional ridge flow | ||
| 855 | mw - the width (in blocks) of the map | ||
| 856 | mh - the height (in blocks) of the map | ||
| 857 | lfsparms - parameters and thresholds for controlling LFS | ||
| 858 | Output: | ||
| 859 | ohcmap - points to the created High Curvature Map | ||
| 860 | Return Code: | ||
| 861 | Zero - successful completion | ||
| 862 | Negative - system error | ||
| 863 | **************************************************************************/ | ||
| 864 | 48 | int gen_high_curve_map(int **ohcmap, int *direction_map, | |
| 865 | const int mw, const int mh, const LFSPARMS *lfsparms) | ||
| 866 | { | ||
| 867 | 48 | int *high_curve_map, mapsize; | |
| 868 | 48 | int *hptr, *dptr; | |
| 869 | 48 | int bx, by; | |
| 870 | 48 | int nvalid, cmeasure, vmeasure; | |
| 871 | |||
| 872 |
2/4✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 48 times.
✓ Branch 2 (4→5) taken 48 times.
✗ Branch 3 (4→6) not taken.
|
48 | ASSERT_INT_MUL(mw, mh); |
| 873 | 48 | mapsize = mw*mh; | |
| 874 | |||
| 875 | /* Allocate High Curvature Map. */ | ||
| 876 |
1/2✓ Branch 0 (5→7) taken 48 times.
✗ Branch 1 (5→9) not taken.
|
48 | ASSERT_SIZE_MUL(mapsize, sizeof(int)); |
| 877 | 48 | high_curve_map = (int *)g_malloc(mapsize * sizeof(int)); | |
| 878 | /* Initialize High Curvature Map to FALSE (0). */ | ||
| 879 | 48 | memset(high_curve_map, 0, mapsize*sizeof(int)); | |
| 880 | |||
| 881 | 48 | hptr = high_curve_map; | |
| 882 | 48 | dptr = direction_map; | |
| 883 | |||
| 884 | /* Foreach row in maps ... */ | ||
| 885 |
2/2✓ Branch 0 (23→24) taken 1673 times.
✓ Branch 1 (23→25) taken 48 times.
|
1721 | for(by = 0; by < mh; by++){ |
| 886 | /* Foreach column in maps ... */ | ||
| 887 |
2/2✓ Branch 0 (21→10) taken 50730 times.
✓ Branch 1 (21→22) taken 1673 times.
|
52403 | for(bx = 0; bx < mw; bx++){ |
| 888 | |||
| 889 | /* Count number of valid neighbors around current block ... */ | ||
| 890 | 50730 | nvalid = num_valid_8nbrs(direction_map, bx, by, mw, mh); | |
| 891 | |||
| 892 | /* If valid neighbors exist ... */ | ||
| 893 |
2/2✓ Branch 0 (11→12) taken 45618 times.
✓ Branch 1 (11→20) taken 5112 times.
|
50730 | if(nvalid > 0){ |
| 894 | /* If current block's direction is INVALID ... */ | ||
| 895 |
2/2✓ Branch 0 (12→13) taken 6667 times.
✓ Branch 1 (12→17) taken 38951 times.
|
45618 | if(*dptr == INVALID_DIR){ |
| 896 | /* If a sufficient number of VALID neighbors exists ... */ | ||
| 897 |
2/2✓ Branch 0 (13→14) taken 16 times.
✓ Branch 1 (13→20) taken 6651 times.
|
6667 | if(nvalid >= lfsparms->vort_valid_nbr_min){ |
| 898 | /* Measure vorticity of neighbors. */ | ||
| 899 | 16 | vmeasure = vorticity(direction_map, bx, by, mw, mh, | |
| 900 | lfsparms->num_directions); | ||
| 901 | /* If vorticity is sufficiently high ... */ | ||
| 902 |
1/2✗ Branch 0 (15→16) not taken.
✓ Branch 1 (15→20) taken 16 times.
|
16 | if(vmeasure >= lfsparms->highcurv_vorticity_min) |
| 903 | /* Flag block as HIGH CURVATURE. */ | ||
| 904 | ✗ | *hptr = TRUE; | |
| 905 | } | ||
| 906 | } | ||
| 907 | /* Otherwise block has valid direction ... */ | ||
| 908 | else{ | ||
| 909 | /* Measure curvature around the valid block. */ | ||
| 910 | 38951 | cmeasure = curvature(direction_map, bx, by, mw, mh, | |
| 911 | lfsparms->num_directions); | ||
| 912 | /* If curvature is sufficiently high ... */ | ||
| 913 |
2/2✓ Branch 0 (18→19) taken 1866 times.
✓ Branch 1 (18→20) taken 37085 times.
|
38951 | if(cmeasure >= lfsparms->highcurv_curvature_min) |
| 914 | 1866 | *hptr = TRUE; | |
| 915 | } | ||
| 916 | } /* Else (nvalid <= 0) */ | ||
| 917 | |||
| 918 | /* Bump pointers to next block in maps. */ | ||
| 919 | 50730 | dptr++; | |
| 920 | 50730 | hptr++; | |
| 921 | |||
| 922 | } /* bx */ | ||
| 923 | } /* by */ | ||
| 924 | |||
| 925 | /* Assign High Curvature Map to output pointer. */ | ||
| 926 | 48 | *ohcmap = high_curve_map; | |
| 927 | |||
| 928 | /* Return normally. */ | ||
| 929 | 48 | return(0); | |
| 930 | } | ||
| 931 | |||
| 932 | /************************************************************************* | ||
| 933 | ************************************************************************** | ||
| 934 | #cat: gen_imap - Computes an IMAP, which is a 2D vector of integer directions, | ||
| 935 | #cat: where each direction represents the dominant ridge flow in | ||
| 936 | #cat: a block of the input grayscale image. This routine will | ||
| 937 | #cat: generate an IMAP for arbitrarily sized, non-square, images. | ||
| 938 | |||
| 939 | Input: | ||
| 940 | pdata - padded input image data (8 bits [0..256) grayscale) | ||
| 941 | pw - padded width (in pixels) of the input image | ||
| 942 | ph - padded height (in pixels) of the input image | ||
| 943 | dir2rad - lookup table for converting integer directions | ||
| 944 | dftwaves - structure containing the DFT wave forms | ||
| 945 | dftgrids - structure containing the rotated pixel grid offsets | ||
| 946 | lfsparms - parameters and thresholds for controlling LFS | ||
| 947 | Output: | ||
| 948 | optr - points to the created IMAP | ||
| 949 | ow - width (in blocks) of the IMAP | ||
| 950 | oh - height (in blocks) of the IMAP | ||
| 951 | Return Code: | ||
| 952 | Zero - successful completion | ||
| 953 | Negative - system error | ||
| 954 | **************************************************************************/ | ||
| 955 | |||
| 956 | /************************************************************************* | ||
| 957 | ************************************************************************** | ||
| 958 | #cat: gen_initial_imap - Creates an initial IMAP from the given input image. | ||
| 959 | #cat: It very important that the image be properly padded so | ||
| 960 | #cat: that rotated grids along the boudary of the image do not | ||
| 961 | #cat: access unkown memory. The rotated grids are used by a | ||
| 962 | #cat: DFT-based analysis to determine the integer directions | ||
| 963 | #cat: in the IMAP. Typically this initial vector of directions will | ||
| 964 | #cat: subsequently have weak or inconsistent directions removed | ||
| 965 | #cat: followed by a smoothing process. | ||
| 966 | |||
| 967 | Input: | ||
| 968 | blkoffs - offsets to the pixel origin of each block in the padded image | ||
| 969 | mw - number of blocks horizontally in the padded input image | ||
| 970 | mh - number of blocks vertically in the padded input image | ||
| 971 | pdata - padded input image data (8 bits [0..256) grayscale) | ||
| 972 | pw - width (in pixels) of the padded input image | ||
| 973 | ph - height (in pixels) of the padded input image | ||
| 974 | dftwaves - structure containing the DFT wave forms | ||
| 975 | dftgrids - structure containing the rotated pixel grid offsets | ||
| 976 | lfsparms - parameters and thresholds for controlling LFS | ||
| 977 | Output: | ||
| 978 | optr - points to the newly created IMAP | ||
| 979 | Return Code: | ||
| 980 | Zero - successful completion | ||
| 981 | Negative - system error | ||
| 982 | **************************************************************************/ | ||
| 983 | |||
| 984 | /************************************************************************* | ||
| 985 | ************************************************************************** | ||
| 986 | #cat: primary_dir_test - Applies the primary set of criteria for selecting | ||
| 987 | #cat: an IMAP integer direction from a set of DFT results | ||
| 988 | #cat: computed from a block of image data | ||
| 989 | |||
| 990 | Input: | ||
| 991 | powers - DFT power computed from each (N) wave frequencies at each | ||
| 992 | rotation direction in the current image block | ||
| 993 | wis - sorted order of the highest N-1 frequency power statistics | ||
| 994 | powmaxs - maximum power for each of the highest N-1 frequencies | ||
| 995 | powmax_dirs - directions associated with each of the N-1 maximum powers | ||
| 996 | pownorms - normalized power for each of the highest N-1 frequencies | ||
| 997 | nstats - N-1 wave frequencies (where N is the length of g_dft_coefs) | ||
| 998 | lfsparms - parameters and thresholds for controlling LFS | ||
| 999 | Return Code: | ||
| 1000 | Zero or Positive - The selected IMAP integer direction | ||
| 1001 | INVALID_DIR - IMAP Integer direction could not be determined | ||
| 1002 | **************************************************************************/ | ||
| 1003 | 46139 | int primary_dir_test(double **powers, const int *wis, | |
| 1004 | const double *powmaxs, const int *powmax_dirs, | ||
| 1005 | const double *pownorms, const int nstats, | ||
| 1006 | const LFSPARMS *lfsparms) | ||
| 1007 | { | ||
| 1008 | 46139 | int w; | |
| 1009 | |||
| 1010 | 46139 | print2log(" Primary\n"); | |
| 1011 | |||
| 1012 | /* Look at max power statistics in decreasing order ... */ | ||
| 1013 |
2/2✓ Branch 0 (8→4) taken 70845 times.
✓ Branch 1 (8→9) taken 10581 times.
|
127565 | for(w = 0; w < nstats; w++){ |
| 1014 | /* 1. Test magnitude of current max power (Ex. Thresh==100000) */ | ||
| 1015 |
2/2✓ Branch 0 (4→5) taken 64207 times.
✓ Branch 1 (4→7) taken 6638 times.
|
70845 | if((powmaxs[wis[w]] > lfsparms->powmax_min) && |
| 1016 | /* 2. Test magnitude of normalized max power (Ex. Thresh==3.8) */ | ||
| 1017 |
2/2✓ Branch 0 (5→6) taken 36391 times.
✓ Branch 1 (5→7) taken 27816 times.
|
64207 | (pownorms[wis[w]] > lfsparms->pownorm_min) && |
| 1018 | /* 3. Test magnitude of power of lowest DFT frequency at current */ | ||
| 1019 | /* max power direction and make sure it is not too big. */ | ||
| 1020 | /* (Ex. Thresh==50000000) */ | ||
| 1021 |
2/2✓ Branch 0 (6→7) taken 833 times.
✓ Branch 1 (6→9) taken 35558 times.
|
36391 | (powers[0][powmax_dirs[wis[w]]] <= lfsparms->powmax_max)){ |
| 1022 | |||
| 1023 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 1024 | /* Add 1 to wis[w] to create index to original g_dft_coefs[] */ | ||
| 1025 | fprintf(logfp, | ||
| 1026 | " Selected Wave = %d\n", wis[w]+1); | ||
| 1027 | fprintf(logfp, | ||
| 1028 | " 1. Power Magnitude (%12.3f > %12.3f)\n", | ||
| 1029 | powmaxs[wis[w]], lfsparms->powmax_min); | ||
| 1030 | fprintf(logfp, | ||
| 1031 | " 2. Norm Power Magnitude (%9.3f > %9.3f)\n", | ||
| 1032 | pownorms[wis[w]], lfsparms->pownorm_min); | ||
| 1033 | fprintf(logfp, | ||
| 1034 | " 3. Low Freq Wave Magnitude (%12.3f <= %12.3f)\n", | ||
| 1035 | powers[0][powmax_dirs[wis[w]]], lfsparms->powmax_max); | ||
| 1036 | fprintf(logfp, | ||
| 1037 | " PASSED\n"); | ||
| 1038 | fprintf(logfp, | ||
| 1039 | " Selected Direction = %d\n", | ||
| 1040 | powmax_dirs[wis[w]]); | ||
| 1041 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 1042 | |||
| 1043 | /* If ALL 3 criteria met, return current max power direction. */ | ||
| 1044 | return(powmax_dirs[wis[w]]); | ||
| 1045 | |||
| 1046 | } | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | /* Otherwise test failed. */ | ||
| 1050 | |||
| 1051 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 1052 | fprintf(logfp, " 1. Power Magnitude ( > %12.3f)\n", | ||
| 1053 | lfsparms->powmax_min); | ||
| 1054 | fprintf(logfp, " 2. Norm Power Magnitude ( > %9.3f)\n", | ||
| 1055 | lfsparms->pownorm_min); | ||
| 1056 | fprintf(logfp, " 3. Low Freq Wave Magnitude ( <= %12.3f)\n", | ||
| 1057 | lfsparms->powmax_max); | ||
| 1058 | fprintf(logfp, " FAILED\n"); | ||
| 1059 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 1060 | |||
| 1061 | return(INVALID_DIR); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | /************************************************************************* | ||
| 1065 | ************************************************************************** | ||
| 1066 | #cat: secondary_fork_test - Applies a secondary set of criteria for selecting | ||
| 1067 | #cat: an IMAP integer direction from a set of DFT results | ||
| 1068 | #cat: computed from a block of image data. This test | ||
| 1069 | #cat: analyzes the strongest power statistics associated | ||
| 1070 | #cat: with a given frequency and direction and analyses | ||
| 1071 | #cat: small changes in direction to the left and right to | ||
| 1072 | #cat: determine if the block contains a "fork". | ||
| 1073 | |||
| 1074 | Input: | ||
| 1075 | powers - DFT power computed from each (N) wave frequencies at each | ||
| 1076 | rotation direction in the current image block | ||
| 1077 | wis - sorted order of the highest N-1 frequency power statistics | ||
| 1078 | powmaxs - maximum power for each of the highest N-1 frequencies | ||
| 1079 | powmax_dirs - directions associated with each of the N-1 maximum powers | ||
| 1080 | pownorms - normalized power for each of the highest N-1 frequencies | ||
| 1081 | nstats - N-1 wave frequencies (where N is the length of g_dft_coefs) | ||
| 1082 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1083 | Return Code: | ||
| 1084 | Zero or Positive - The selected IMAP integer direction | ||
| 1085 | INVALID_DIR - IMAP Integer direction could not be determined | ||
| 1086 | **************************************************************************/ | ||
| 1087 | 10581 | int secondary_fork_test(double **powers, const int *wis, | |
| 1088 | const double *powmaxs, const int *powmax_dirs, | ||
| 1089 | const double *pownorms, const int nstats, | ||
| 1090 | const LFSPARMS *lfsparms) | ||
| 1091 | { | ||
| 1092 | 10581 | int ldir, rdir; | |
| 1093 | 10581 | double fork_pownorm_min, fork_pow_thresh; | |
| 1094 | |||
| 1095 | #ifdef LOG_REPORT | ||
| 1096 | { int firstpart = 0; /* Flag to determine if passed 1st part ... */ | ||
| 1097 | fprintf(logfp, " Secondary\n"); | ||
| 1098 | #endif | ||
| 1099 | |||
| 1100 | /* Relax the normalized power threshold under fork conditions. */ | ||
| 1101 | 10581 | fork_pownorm_min = lfsparms->fork_pct_pownorm * lfsparms->pownorm_min; | |
| 1102 | |||
| 1103 | /* 1. Test magnitude of largest max power (Ex. Thresh==100000) */ | ||
| 1104 |
2/2✓ Branch 0 (2→3) taken 9500 times.
✓ Branch 1 (2→4) taken 1081 times.
|
10581 | if((powmaxs[wis[0]] > lfsparms->powmax_min) && |
| 1105 | /* 2. Test magnitude of corresponding normalized power */ | ||
| 1106 | /* (Ex. Thresh==2.85) */ | ||
| 1107 |
2/2✓ Branch 0 (3→4) taken 3919 times.
✓ Branch 1 (3→5) taken 5581 times.
|
9500 | (pownorms[wis[0]] >= fork_pownorm_min) && |
| 1108 | /* 3. Test magnitude of power of lowest DFT frequency at largest */ | ||
| 1109 | /* max power direction and make sure it is not too big. */ | ||
| 1110 | /* (Ex. Thresh==50000000) */ | ||
| 1111 |
2/2✓ Branch 0 (5→4) taken 376 times.
✓ Branch 1 (5→6) taken 5205 times.
|
5581 | (powers[0][powmax_dirs[wis[0]]] <= lfsparms->powmax_max)){ |
| 1112 | |||
| 1113 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 1114 | /* First part passed ... */ | ||
| 1115 | firstpart = 1; | ||
| 1116 | fprintf(logfp, | ||
| 1117 | " Selected Wave = %d\n", wis[0]+1); | ||
| 1118 | fprintf(logfp, | ||
| 1119 | " 1. Power Magnitude (%12.3f > %12.3f)\n", | ||
| 1120 | powmaxs[wis[0]], lfsparms->powmax_min); | ||
| 1121 | fprintf(logfp, | ||
| 1122 | " 2. Norm Power Magnitude (%9.3f >= %9.3f)\n", | ||
| 1123 | pownorms[wis[0]], fork_pownorm_min); | ||
| 1124 | fprintf(logfp, | ||
| 1125 | " 3. Low Freq Wave Magnitude (%12.3f <= %12.3f)\n", | ||
| 1126 | powers[0][powmax_dirs[wis[0]]], lfsparms->powmax_max); | ||
| 1127 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 1128 | |||
| 1129 | /* Add FORK_INTERVALs to current direction modulo NDIRS */ | ||
| 1130 | 5205 | rdir = (powmax_dirs[wis[0]] + lfsparms->fork_interval) % | |
| 1131 | 5205 | lfsparms->num_directions; | |
| 1132 | |||
| 1133 | /* Subtract FORK_INTERVALs from direction modulo NDIRS */ | ||
| 1134 | /* For example, FORK_INTERVAL==2 & NDIRS==16, then */ | ||
| 1135 | /* ldir = (dir - (16-2)) % 16 */ | ||
| 1136 | /* which keeps result in proper modulo range. */ | ||
| 1137 | 5205 | ldir = (powmax_dirs[wis[0]] + lfsparms->num_directions - | |
| 1138 | lfsparms->fork_interval) % lfsparms->num_directions; | ||
| 1139 | |||
| 1140 | 5205 | print2log(" Left = %d, Current = %d, Right = %d\n", | |
| 1141 | ldir, powmax_dirs[wis[0]], rdir); | ||
| 1142 | |||
| 1143 | /* Set forked angle threshold to be a % of the max directional */ | ||
| 1144 | /* power. (Ex. thresh==0.7*powmax) */ | ||
| 1145 | 5205 | fork_pow_thresh = powmaxs[wis[0]] * lfsparms->fork_pct_powmax; | |
| 1146 | |||
| 1147 | /* Look up and test the computed power for the left and right */ | ||
| 1148 | /* fork directions.s */ | ||
| 1149 | /* The power stats (and thus wis) are on the range [0..nwaves-1) */ | ||
| 1150 | /* as the statistics for the first DFT wave are not included. */ | ||
| 1151 | /* The original power vectors exist for ALL DFT waves, therefore */ | ||
| 1152 | /* wis indices must be added by 1 before addressing the original */ | ||
| 1153 | /* powers vector. */ | ||
| 1154 | /* LFS permits one and only one of the fork angles to exceed */ | ||
| 1155 | /* the relative power threshold. */ | ||
| 1156 |
2/2✓ Branch 0 (7→8) taken 290 times.
✓ Branch 1 (7→9) taken 4915 times.
|
5205 | if(((powers[wis[0]+1][ldir] <= fork_pow_thresh) || |
| 1157 |
4/4✓ Branch 0 (8→4) taken 1 times.
✓ Branch 1 (8→9) taken 289 times.
✓ Branch 2 (9→10) taken 4915 times.
✓ Branch 3 (9→11) taken 289 times.
|
5205 | (powers[wis[0]+1][rdir] <= fork_pow_thresh)) && |
| 1158 | 4915 | ((powers[wis[0]+1][ldir] > fork_pow_thresh) || | |
| 1159 |
2/2✓ Branch 0 (10→4) taken 4731 times.
✓ Branch 1 (10→11) taken 184 times.
|
4915 | (powers[wis[0]+1][rdir] > fork_pow_thresh))){ |
| 1160 | |||
| 1161 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 1162 | fprintf(logfp, | ||
| 1163 | " 4. Left Power Magnitude (%12.3f > %12.3f)\n", | ||
| 1164 | powers[wis[0]+1][ldir], fork_pow_thresh); | ||
| 1165 | fprintf(logfp, | ||
| 1166 | " 5. Right Power Magnitude (%12.3f > %12.3f)\n", | ||
| 1167 | powers[wis[0]+1][rdir], fork_pow_thresh); | ||
| 1168 | fprintf(logfp, " PASSED\n"); | ||
| 1169 | fprintf(logfp, | ||
| 1170 | " Selected Direction = %d\n", powmax_dirs[wis[0]]); | ||
| 1171 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 1172 | |||
| 1173 | /* If ALL the above criteria hold, then return the direction */ | ||
| 1174 | /* of the largest max power. */ | ||
| 1175 | 473 | return(powmax_dirs[wis[0]]); | |
| 1176 | } | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | /* Otherwise test failed. */ | ||
| 1180 | |||
| 1181 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 1182 | if(!firstpart){ | ||
| 1183 | fprintf(logfp, | ||
| 1184 | " 1. Power Magnitude ( > %12.3f)\n", | ||
| 1185 | lfsparms->powmax_min); | ||
| 1186 | fprintf(logfp, | ||
| 1187 | " 2. Norm Power Magnitude ( > %9.3f)\n", | ||
| 1188 | fork_pownorm_min); | ||
| 1189 | fprintf(logfp, | ||
| 1190 | " 3. Low Freq Wave Magnitude ( <= %12.3f)\n", | ||
| 1191 | lfsparms->powmax_max); | ||
| 1192 | } | ||
| 1193 | else{ | ||
| 1194 | fprintf(logfp, " 4. Left Power Magnitude (%12.3f > %12.3f)\n", | ||
| 1195 | powers[wis[0]+1][ldir], fork_pow_thresh); | ||
| 1196 | fprintf(logfp, " 5. Right Power Magnitude (%12.3f > %12.3f)\n", | ||
| 1197 | powers[wis[0]+1][rdir], fork_pow_thresh); | ||
| 1198 | } | ||
| 1199 | fprintf(logfp, " FAILED\n"); | ||
| 1200 | } /* Close scope of firstpart */ | ||
| 1201 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 1202 | |||
| 1203 | return(INVALID_DIR); | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | /************************************************************************* | ||
| 1207 | ************************************************************************** | ||
| 1208 | #cat: remove_incon_dirs - Takes a vector of integer directions and removes | ||
| 1209 | #cat: individual directions that are too weak or inconsistent. | ||
| 1210 | #cat: Directions are tested from the center of the IMAP working | ||
| 1211 | #cat: outward in concentric squares, and the process resets to | ||
| 1212 | #cat: the center and continues until no changes take place during | ||
| 1213 | #cat: a complete pass. | ||
| 1214 | |||
| 1215 | Input: | ||
| 1216 | imap - vector of IMAP integer directions | ||
| 1217 | mw - width (in blocks) of the IMAP | ||
| 1218 | mh - height (in blocks) of the IMAP | ||
| 1219 | dir2rad - lookup table for converting integer directions | ||
| 1220 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1221 | Output: | ||
| 1222 | imap - vector of pruned input values | ||
| 1223 | **************************************************************************/ | ||
| 1224 | 96 | void remove_incon_dirs(int *imap, const int mw, const int mh, | |
| 1225 | const DIR2RAD *dir2rad, const LFSPARMS *lfsparms) | ||
| 1226 | { | ||
| 1227 | 96 | int cx, cy; | |
| 1228 | 96 | int *iptr; | |
| 1229 | 96 | int nremoved; | |
| 1230 | 96 | int lbox, rbox, tbox, bbox; | |
| 1231 | |||
| 1232 | #ifdef LOG_REPORT | ||
| 1233 | { int numpass = 0; | ||
| 1234 | fprintf(logfp, "REMOVE MAP\n"); | ||
| 1235 | #endif | ||
| 1236 | |||
| 1237 | /* Compute center coords of IMAP */ | ||
| 1238 | 96 | cx = mw>>1; | |
| 1239 | 96 | cy = mh>>1; | |
| 1240 | |||
| 1241 | /* Do pass, while directions have been removed in a pass ... */ | ||
| 1242 | 328 | do{ | |
| 1243 | |||
| 1244 | #ifdef LOG_REPORT | ||
| 1245 | /* Count number of complete passes through IMAP */ | ||
| 1246 | ++numpass; | ||
| 1247 | fprintf(logfp, " PASS = %d\n", numpass); | ||
| 1248 | #endif | ||
| 1249 | |||
| 1250 | /* Reinitialize number of removed directions to 0 */ | ||
| 1251 | 328 | nremoved = 0; | |
| 1252 | |||
| 1253 | /* Start at center */ | ||
| 1254 | 328 | iptr = imap + (cy * mw) + cx; | |
| 1255 | /* If valid IMAP direction and test for removal is true ... */ | ||
| 1256 |
4/4✓ Branch 0 (3→4) taken 196 times.
✓ Branch 1 (3→5) taken 132 times.
✓ Branch 2 (6→4) taken 127 times.
✓ Branch 3 (6→7) taken 5 times.
|
460 | if((*iptr != INVALID_DIR)&& |
| 1257 | 132 | (remove_dir(imap, cx, cy, mw, mh, dir2rad, lfsparms))){ | |
| 1258 | |||
| 1259 | /* Set to INVALID */ | ||
| 1260 | 5 | *iptr = INVALID_DIR; | |
| 1261 | /* Bump number of removed IMAP directions */ | ||
| 1262 | 5 | nremoved++; | |
| 1263 | } | ||
| 1264 | |||
| 1265 | /* Initialize side indices of concentric boxes */ | ||
| 1266 | 328 | lbox = cx-1; | |
| 1267 | 328 | tbox = cy-1; | |
| 1268 | 328 | rbox = cx+1; | |
| 1269 | 328 | bbox = cy+1; | |
| 1270 | |||
| 1271 | /* Grow concentric boxes, until ALL edges of imap are exceeded */ | ||
| 1272 |
4/4✓ Branch 0 (22→9) taken 5195 times.
✓ Branch 1 (22→23) taken 1271 times.
✓ Branch 2 (23→9) taken 943 times.
✓ Branch 3 (23→24) taken 328 times.
|
6466 | while((lbox >= 0) || (rbox < mw) || (tbox >= 0) || (bbox < mh)){ |
| 1273 | |||
| 1274 | /* test top edge of box */ | ||
| 1275 |
2/2✓ Branch 0 (9→10) taken 5718 times.
✓ Branch 1 (9→12) taken 420 times.
|
6138 | if(tbox >= 0) |
| 1276 | 5718 | nremoved += test_top_edge(lbox, tbox, rbox, bbox, imap, mw, mh, | |
| 1277 | dir2rad, lfsparms); | ||
| 1278 | |||
| 1279 | /* test right edge of box */ | ||
| 1280 |
2/2✓ Branch 0 (12→13) taken 4899 times.
✓ Branch 1 (12→15) taken 1239 times.
|
6138 | if(rbox < mw) |
| 1281 | 4899 | nremoved += test_right_edge(lbox, tbox, rbox, bbox, imap, mw, mh, | |
| 1282 | dir2rad, lfsparms); | ||
| 1283 | |||
| 1284 | /* test bottom edge of box */ | ||
| 1285 |
2/2✓ Branch 0 (15→16) taken 5443 times.
✓ Branch 1 (15→18) taken 695 times.
|
6138 | if(bbox < mh) |
| 1286 | 5443 | nremoved += test_bottom_edge(lbox, tbox, rbox, bbox, imap, mw, mh, | |
| 1287 | dir2rad, lfsparms); | ||
| 1288 | |||
| 1289 | /* test left edge of box */ | ||
| 1290 |
2/2✓ Branch 0 (18→19) taken 5195 times.
✓ Branch 1 (18→21) taken 943 times.
|
6138 | if(lbox >=0) |
| 1291 | 5195 | nremoved += test_left_edge(lbox, tbox, rbox, bbox, imap, mw, mh, | |
| 1292 | dir2rad, lfsparms); | ||
| 1293 | |||
| 1294 | /* Resize current box */ | ||
| 1295 | 6138 | lbox--; | |
| 1296 | 6138 | tbox--; | |
| 1297 | 6138 | rbox++; | |
| 1298 | 6138 | bbox++; | |
| 1299 | } | ||
| 1300 |
2/2✓ Branch 0 (24→25) taken 232 times.
✓ Branch 1 (24→26) taken 96 times.
|
328 | }while(nremoved); |
| 1301 | |||
| 1302 | #ifdef LOG_REPORT | ||
| 1303 | } /* Close scope of numpass */ | ||
| 1304 | #endif | ||
| 1305 | |||
| 1306 | 96 | } | |
| 1307 | |||
| 1308 | /************************************************************************* | ||
| 1309 | ************************************************************************** | ||
| 1310 | #cat: test_top_edge - Walks the top edge of a concentric square in the IMAP, | ||
| 1311 | #cat: testing directions along the way to see if they should | ||
| 1312 | #cat: be removed due to being too weak or inconsistent with | ||
| 1313 | #cat: respect to their adjacent neighbors. | ||
| 1314 | |||
| 1315 | Input: | ||
| 1316 | lbox - left edge of current concentric square | ||
| 1317 | tbox - top edge of current concentric square | ||
| 1318 | rbox - right edge of current concentric square | ||
| 1319 | bbox - bottom edge of current concentric square | ||
| 1320 | imap - vector of IMAP integer directions | ||
| 1321 | mw - width (in blocks) of the IMAP | ||
| 1322 | mh - height (in blocks) of the IMAP | ||
| 1323 | dir2rad - lookup table for converting integer directions | ||
| 1324 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1325 | Return Code: | ||
| 1326 | Positive - direction should be removed from IMAP | ||
| 1327 | Zero - direction should NOT be remove from IMAP | ||
| 1328 | **************************************************************************/ | ||
| 1329 | 5718 | int test_top_edge(const int lbox, const int tbox, const int rbox, | |
| 1330 | const int bbox, int *imap, const int mw, const int mh, | ||
| 1331 | const DIR2RAD *dir2rad, const LFSPARMS *lfsparms) | ||
| 1332 | { | ||
| 1333 | 5718 | int bx, by, sx, ex; | |
| 1334 | 5718 | int *iptr, *sptr, *eptr; | |
| 1335 | 5718 | int nremoved; | |
| 1336 | |||
| 1337 | /* Initialize number of directions removed on edge to 0 */ | ||
| 1338 | 5718 | nremoved = 0; | |
| 1339 | |||
| 1340 | /* Set start pointer to top-leftmost point of box, or set it to */ | ||
| 1341 | /* the leftmost point in the IMAP row (0), whichever is larger. */ | ||
| 1342 | 5718 | sx = max(lbox, 0); | |
| 1343 | 5718 | sptr = imap + (tbox*mw) + sx; | |
| 1344 | |||
| 1345 | /* Set end pointer to either 1 point short of the top-rightmost */ | ||
| 1346 | /* point of box, or set it to the rightmost point in the IMAP */ | ||
| 1347 | /* row (lastx=mw-1), whichever is smaller. */ | ||
| 1348 |
2/2✓ Branch 0 (2→3) taken 4730 times.
✓ Branch 1 (2→4) taken 988 times.
|
5718 | ex = min(rbox-1, mw-1); |
| 1349 | 5718 | eptr = imap + (tbox*mw) + ex; | |
| 1350 | |||
| 1351 | /* For each point on box's edge ... */ | ||
| 1352 | 5718 | for(iptr = sptr, bx = sx, by = tbox; | |
| 1353 |
2/2✓ Branch 0 (12→6) taken 97987 times.
✓ Branch 1 (12→13) taken 5718 times.
|
103705 | iptr <= eptr; |
| 1354 | 97987 | iptr++, bx++){ | |
| 1355 | /* If valid IMAP direction and test for removal is true ... */ | ||
| 1356 |
4/4✓ Branch 0 (6→7) taken 34527 times.
✓ Branch 1 (6→8) taken 63460 times.
✓ Branch 2 (9→7) taken 62080 times.
✓ Branch 3 (9→10) taken 1380 times.
|
161447 | if((*iptr != INVALID_DIR)&& |
| 1357 | 63460 | (remove_dir(imap, bx, by, mw, mh, dir2rad, lfsparms))){ | |
| 1358 | /* Set to INVALID */ | ||
| 1359 | 1380 | *iptr = INVALID_DIR; | |
| 1360 | /* Bump number of removed IMAP directions */ | ||
| 1361 | 1380 | nremoved++; | |
| 1362 | } | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | /* Return the number of directions removed on edge */ | ||
| 1366 | 5718 | return(nremoved); | |
| 1367 | } | ||
| 1368 | |||
| 1369 | /************************************************************************* | ||
| 1370 | ************************************************************************** | ||
| 1371 | #cat: test_right_edge - Walks the right edge of a concentric square in the | ||
| 1372 | #cat: IMAP, testing directions along the way to see if they | ||
| 1373 | #cat: should be removed due to being too weak or inconsistent | ||
| 1374 | #cat: with respect to their adjacent neighbors. | ||
| 1375 | |||
| 1376 | Input: | ||
| 1377 | lbox - left edge of current concentric square | ||
| 1378 | tbox - top edge of current concentric square | ||
| 1379 | rbox - right edge of current concentric square | ||
| 1380 | bbox - bottom edge of current concentric square | ||
| 1381 | imap - vector of IMAP integer directions | ||
| 1382 | mw - width (in blocks) of the IMAP | ||
| 1383 | mh - height (in blocks) of the IMAP | ||
| 1384 | dir2rad - lookup table for converting integer directions | ||
| 1385 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1386 | Return Code: | ||
| 1387 | Positive - direction should be removed from IMAP | ||
| 1388 | Zero - direction should NOT be remove from IMAP | ||
| 1389 | **************************************************************************/ | ||
| 1390 | 4899 | int test_right_edge(const int lbox, const int tbox, const int rbox, | |
| 1391 | const int bbox, int *imap, const int mw, const int mh, | ||
| 1392 | const DIR2RAD *dir2rad, const LFSPARMS *lfsparms) | ||
| 1393 | { | ||
| 1394 | 4899 | int bx, by, sy, ey; | |
| 1395 | 4899 | int *iptr, *sptr, *eptr; | |
| 1396 | 4899 | int nremoved; | |
| 1397 | |||
| 1398 | /* Initialize number of directions removed on edge to 0 */ | ||
| 1399 | 4899 | nremoved = 0; | |
| 1400 | |||
| 1401 | /* Set start pointer to top-rightmost point of box, or set it to */ | ||
| 1402 | /* the topmost point in IMAP column (0), whichever is larger. */ | ||
| 1403 | 4899 | sy = max(tbox, 0); | |
| 1404 | 4899 | sptr = imap + (sy*mw) + rbox; | |
| 1405 | |||
| 1406 | /* Set end pointer to either 1 point short of the bottom- */ | ||
| 1407 | /* rightmost point of box, or set it to the bottommost point */ | ||
| 1408 | /* in the IMAP column (lasty=mh-1), whichever is smaller. */ | ||
| 1409 |
2/2✓ Branch 0 (2→3) taken 4508 times.
✓ Branch 1 (2→4) taken 391 times.
|
4899 | ey = min(bbox-1,mh-1); |
| 1410 | 4899 | eptr = imap + (ey*mw) + rbox; | |
| 1411 | |||
| 1412 | /* For each point on box's edge ... */ | ||
| 1413 | 4899 | for(iptr = sptr, bx = rbox, by = sy; | |
| 1414 |
2/2✓ Branch 0 (12→6) taken 79343 times.
✓ Branch 1 (12→13) taken 4899 times.
|
84242 | iptr <= eptr; |
| 1415 | 79343 | iptr+=mw, by++){ | |
| 1416 | /* If valid IMAP direction and test for removal is true ... */ | ||
| 1417 |
4/4✓ Branch 0 (6→7) taken 25784 times.
✓ Branch 1 (6→8) taken 53559 times.
✓ Branch 2 (9→7) taken 52622 times.
✓ Branch 3 (9→10) taken 937 times.
|
132902 | if((*iptr != INVALID_DIR)&& |
| 1418 | 53559 | (remove_dir(imap, bx, by, mw, mh, dir2rad, lfsparms))){ | |
| 1419 | /* Set to INVALID */ | ||
| 1420 | 937 | *iptr = INVALID_DIR; | |
| 1421 | /* Bump number of removed IMAP directions */ | ||
| 1422 | 937 | nremoved++; | |
| 1423 | } | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | /* Return the number of directions removed on edge */ | ||
| 1427 | 4899 | return(nremoved); | |
| 1428 | } | ||
| 1429 | |||
| 1430 | /************************************************************************* | ||
| 1431 | ************************************************************************** | ||
| 1432 | #cat: test_bottom_edge - Walks the bottom edge of a concentric square in the | ||
| 1433 | #cat: IMAP, testing directions along the way to see if they | ||
| 1434 | #cat: should be removed due to being too weak or inconsistent | ||
| 1435 | #cat: with respect to their adjacent neighbors. | ||
| 1436 | Input: | ||
| 1437 | lbox - left edge of current concentric square | ||
| 1438 | tbox - top edge of current concentric square | ||
| 1439 | rbox - right edge of current concentric square | ||
| 1440 | bbox - bottom edge of current concentric square | ||
| 1441 | imap - vector of IMAP integer directions | ||
| 1442 | mw - width (in blocks) of the IMAP | ||
| 1443 | mh - height (in blocks) of the IMAP | ||
| 1444 | dir2rad - lookup table for converting integer directions | ||
| 1445 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1446 | Return Code: | ||
| 1447 | Positive - direction should be removed from IMAP | ||
| 1448 | Zero - direction should NOT be remove from IMAP | ||
| 1449 | **************************************************************************/ | ||
| 1450 | 5443 | int test_bottom_edge(const int lbox, const int tbox, const int rbox, | |
| 1451 | const int bbox, int *imap, const int mw, const int mh, | ||
| 1452 | const DIR2RAD *dir2rad, const LFSPARMS *lfsparms) | ||
| 1453 | { | ||
| 1454 | 5443 | int bx, by, sx, ex; | |
| 1455 | 5443 | int *iptr, *sptr, *eptr; | |
| 1456 | 5443 | int nremoved; | |
| 1457 | |||
| 1458 | /* Initialize number of directions removed on edge to 0 */ | ||
| 1459 | 5443 | nremoved = 0; | |
| 1460 | |||
| 1461 | /* Set start pointer to bottom-rightmost point of box, or set it to the */ | ||
| 1462 | /* rightmost point in the IMAP ROW (lastx=mw-1), whichever is smaller. */ | ||
| 1463 | 5443 | sx = min(rbox, mw-1); | |
| 1464 | 5443 | sptr = imap + (bbox*mw) + sx; | |
| 1465 | |||
| 1466 | /* Set end pointer to either 1 point short of the bottom- */ | ||
| 1467 | /* lefttmost point of box, or set it to the leftmost point */ | ||
| 1468 | /* in the IMAP row (x=0), whichever is larger. */ | ||
| 1469 | 5443 | ex = max(lbox-1, 0); | |
| 1470 | 5443 | eptr = imap + (bbox*mw) + ex; | |
| 1471 | |||
| 1472 | /* For each point on box's edge ... */ | ||
| 1473 | 5443 | for(iptr = sptr, bx = sx, by = bbox; | |
| 1474 |
2/2✓ Branch 0 (9→3) taken 98932 times.
✓ Branch 1 (9→10) taken 5443 times.
|
104375 | iptr >= eptr; |
| 1475 | 98932 | iptr--, bx--){ | |
| 1476 | /* If valid IMAP direction and test for removal is true ... */ | ||
| 1477 |
4/4✓ Branch 0 (3→4) taken 26222 times.
✓ Branch 1 (3→5) taken 72710 times.
✓ Branch 2 (6→4) taken 71958 times.
✓ Branch 3 (6→7) taken 752 times.
|
171642 | if((*iptr != INVALID_DIR)&& |
| 1478 | 72710 | (remove_dir(imap, bx, by, mw, mh, dir2rad, lfsparms))){ | |
| 1479 | /* Set to INVALID */ | ||
| 1480 | 752 | *iptr = INVALID_DIR; | |
| 1481 | /* Bump number of removed IMAP directions */ | ||
| 1482 | 752 | nremoved++; | |
| 1483 | } | ||
| 1484 | } | ||
| 1485 | |||
| 1486 | /* Return the number of directions removed on edge */ | ||
| 1487 | 5443 | return(nremoved); | |
| 1488 | } | ||
| 1489 | |||
| 1490 | /************************************************************************* | ||
| 1491 | ************************************************************************** | ||
| 1492 | #cat: test_left_edge - Walks the left edge of a concentric square in the IMAP, | ||
| 1493 | #cat: testing directions along the way to see if they should | ||
| 1494 | #cat: be removed due to being too weak or inconsistent with | ||
| 1495 | #cat: respect to their adjacent neighbors. | ||
| 1496 | |||
| 1497 | Input: | ||
| 1498 | lbox - left edge of current concentric square | ||
| 1499 | tbox - top edge of current concentric square | ||
| 1500 | rbox - right edge of current concentric square | ||
| 1501 | bbox - bottom edge of current concentric square | ||
| 1502 | imap - vector of IMAP integer directions | ||
| 1503 | mw - width (in blocks) of the IMAP | ||
| 1504 | mh - height (in blocks) of the IMAP | ||
| 1505 | dir2rad - lookup table for converting integer directions | ||
| 1506 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1507 | Return Code: | ||
| 1508 | Positive - direction should be removed from IMAP | ||
| 1509 | Zero - direction should NOT be remove from IMAP | ||
| 1510 | **************************************************************************/ | ||
| 1511 | 5195 | int test_left_edge(const int lbox, const int tbox, const int rbox, | |
| 1512 | const int bbox, int *imap, const int mw, const int mh, | ||
| 1513 | const DIR2RAD *dir2rad, const LFSPARMS *lfsparms) | ||
| 1514 | { | ||
| 1515 | 5195 | int bx, by, sy, ey; | |
| 1516 | 5195 | int *iptr, *sptr, *eptr; | |
| 1517 | 5195 | int nremoved; | |
| 1518 | |||
| 1519 | /* Initialize number of directions removed on edge to 0 */ | ||
| 1520 | 5195 | nremoved = 0; | |
| 1521 | |||
| 1522 | /* Set start pointer to bottom-leftmost point of box, or set it to */ | ||
| 1523 | /* the bottommost point in IMAP column (lasty=mh-1), whichever */ | ||
| 1524 | /* is smaller. */ | ||
| 1525 | 5195 | sy = min(bbox, mh-1); | |
| 1526 | 5195 | sptr = imap + (sy*mw) + lbox; | |
| 1527 | |||
| 1528 | /* Set end pointer to either 1 point short of the top-leftmost */ | ||
| 1529 | /* point of box, or set it to the topmost point in the IMAP */ | ||
| 1530 | /* column (y=0), whichever is larger. */ | ||
| 1531 | 5195 | ey = max(tbox-1, 0); | |
| 1532 | 5195 | eptr = imap + (ey*mw) + lbox; | |
| 1533 | |||
| 1534 | /* For each point on box's edge ... */ | ||
| 1535 | 5195 | for(iptr = sptr, bx = lbox, by = sy; | |
| 1536 |
2/2✓ Branch 0 (9→3) taken 97241 times.
✓ Branch 1 (9→10) taken 5195 times.
|
102436 | iptr >= eptr; |
| 1537 | 97241 | iptr-=mw, by--){ | |
| 1538 | /* If valid IMAP direction and test for removal is true ... */ | ||
| 1539 |
4/4✓ Branch 0 (3→4) taken 26919 times.
✓ Branch 1 (3→5) taken 70322 times.
✓ Branch 2 (6→4) taken 69174 times.
✓ Branch 3 (6→7) taken 1148 times.
|
167563 | if((*iptr != INVALID_DIR)&& |
| 1540 | 70322 | (remove_dir(imap, bx, by, mw, mh, dir2rad, lfsparms))){ | |
| 1541 | /* Set to INVALID */ | ||
| 1542 | 1148 | *iptr = INVALID_DIR; | |
| 1543 | /* Bump number of removed IMAP directions */ | ||
| 1544 | 1148 | nremoved++; | |
| 1545 | } | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | /* Return the number of directions removed on edge */ | ||
| 1549 | 5195 | return(nremoved); | |
| 1550 | } | ||
| 1551 | |||
| 1552 | /************************************************************************* | ||
| 1553 | ************************************************************************** | ||
| 1554 | #cat: remove_dir - Determines if an IMAP direction should be removed based | ||
| 1555 | #cat: on analyzing its adjacent neighbors | ||
| 1556 | |||
| 1557 | Input: | ||
| 1558 | imap - vector of IMAP integer directions | ||
| 1559 | mx - IMAP X-coord of the current direction being tested | ||
| 1560 | my - IMPA Y-coord of the current direction being tested | ||
| 1561 | mw - width (in blocks) of the IMAP | ||
| 1562 | mh - height (in blocks) of the IMAP | ||
| 1563 | dir2rad - lookup table for converting integer directions | ||
| 1564 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1565 | Return Code: | ||
| 1566 | Positive - direction should be removed from IMAP | ||
| 1567 | Zero - direction should NOT be remove from IMAP | ||
| 1568 | **************************************************************************/ | ||
| 1569 | 260183 | int remove_dir(int *imap, const int mx, const int my, | |
| 1570 | const int mw, const int mh, const DIR2RAD *dir2rad, | ||
| 1571 | const LFSPARMS *lfsparms) | ||
| 1572 | { | ||
| 1573 | 260183 | int avrdir, nvalid, dist; | |
| 1574 | 260183 | double dir_strength; | |
| 1575 | |||
| 1576 | /* Compute average direction from neighbors, returning the */ | ||
| 1577 | /* number of valid neighbors used in the computation, and */ | ||
| 1578 | /* the "strength" of the average direction. */ | ||
| 1579 | 260183 | average_8nbr_dir(&avrdir, &dir_strength, &nvalid, imap, mx, my, mw, mh, | |
| 1580 | dir2rad); | ||
| 1581 | |||
| 1582 | /* Conduct valid neighbor test (Ex. thresh==3) */ | ||
| 1583 |
2/2✓ Branch 0 (3→4) taken 258033 times.
✓ Branch 1 (3→7) taken 2150 times.
|
260183 | if(nvalid < lfsparms->rmv_valid_nbr_min){ |
| 1584 | |||
| 1585 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 1586 | fprintf(logfp, " BLOCK %2d (%2d, %2d)\n", | ||
| 1587 | mx+(my*mw), mx, my); | ||
| 1588 | fprintf(logfp, " Average NBR : %2d %6.3f %d\n", | ||
| 1589 | avrdir, dir_strength, nvalid); | ||
| 1590 | fprintf(logfp, " 1. Valid NBR (%d < %d)\n", | ||
| 1591 | nvalid, lfsparms->rmv_valid_nbr_min); | ||
| 1592 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 1593 | |||
| 1594 | return(1); | ||
| 1595 | } | ||
| 1596 | |||
| 1597 | /* If stregnth of average neighbor direction is large enough to */ | ||
| 1598 | /* put credence in ... (Ex. thresh==0.2) */ | ||
| 1599 |
2/2✓ Branch 0 (4→5) taken 248735 times.
✓ Branch 1 (4→7) taken 9298 times.
|
258033 | if(dir_strength >= lfsparms->dir_strength_min){ |
| 1600 | |||
| 1601 | /* Conduct direction distance test (Ex. thresh==3) */ | ||
| 1602 | /* Compute minimum absolute distance between current and */ | ||
| 1603 | /* average directions accounting for wrapping from 0 to NDIRS. */ | ||
| 1604 | 248735 | dist = abs(avrdir - *(imap+(my*mw)+mx)); | |
| 1605 | 248735 | dist = min(dist, dir2rad->ndirs-dist); | |
| 1606 |
2/2✓ Branch 0 (5→6) taken 2072 times.
✓ Branch 1 (5→7) taken 246663 times.
|
248735 | if(dist > lfsparms->dir_distance_max){ |
| 1607 | |||
| 1608 | #ifdef LOG_REPORT /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
| 1609 | fprintf(logfp, " BLOCK %2d (%2d, %2d)\n", | ||
| 1610 | mx+(my*mw), mx, my); | ||
| 1611 | fprintf(logfp, " Average NBR : %2d %6.3f %d\n", | ||
| 1612 | avrdir, dir_strength, nvalid); | ||
| 1613 | fprintf(logfp, " 1. Valid NBR (%d < %d)\n", | ||
| 1614 | nvalid, lfsparms->rmv_valid_nbr_min); | ||
| 1615 | fprintf(logfp, " 2. Direction Strength (%6.3f >= %6.3f)\n", | ||
| 1616 | dir_strength, lfsparms->dir_strength_min); | ||
| 1617 | fprintf(logfp, " Current Dir = %d, Average Dir = %d\n", | ||
| 1618 | *(imap+(my*mw)+mx), avrdir); | ||
| 1619 | fprintf(logfp, " 3. Direction Distance (%d > %d)\n", | ||
| 1620 | dist, lfsparms->dir_distance_max); | ||
| 1621 | #endif /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
| 1622 | |||
| 1623 | 2072 | return(2); | |
| 1624 | } | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | /* Otherwise, the strength of the average direciton is not strong enough */ | ||
| 1628 | /* to put credence in, so leave the current block's directon alone. */ | ||
| 1629 | |||
| 1630 | return(0); | ||
| 1631 | } | ||
| 1632 | |||
| 1633 | /************************************************************************* | ||
| 1634 | ************************************************************************** | ||
| 1635 | #cat: average_8nbr_dir - Given an IMAP direction, computes an average | ||
| 1636 | #cat: direction from its adjacent 8 neighbors returning | ||
| 1637 | #cat: the average direction, its strength, and the | ||
| 1638 | #cat: number of valid direction in the neighborhood. | ||
| 1639 | |||
| 1640 | Input: | ||
| 1641 | imap - vector of IMAP integer directions | ||
| 1642 | mx - IMAP X-coord of the current direction | ||
| 1643 | my - IMPA Y-coord of the current direction | ||
| 1644 | mw - width (in blocks) of the IMAP | ||
| 1645 | mh - height (in blocks) of the IMAP | ||
| 1646 | dir2rad - lookup table for converting integer directions | ||
| 1647 | Output: | ||
| 1648 | avrdir - the average direction computed from neighbors | ||
| 1649 | dir_strenght - the strength of the average direction | ||
| 1650 | nvalid - the number of valid directions used to compute the | ||
| 1651 | average | ||
| 1652 | **************************************************************************/ | ||
| 1653 | 352461 | void average_8nbr_dir(int *avrdir, double *dir_strength, int *nvalid, | |
| 1654 | int *imap, const int mx, const int my, | ||
| 1655 | const int mw, const int mh, | ||
| 1656 | const DIR2RAD *dir2rad) | ||
| 1657 | { | ||
| 1658 | 352461 | int *iptr; | |
| 1659 | 352461 | int e,w,n,s; | |
| 1660 | 352461 | double cospart, sinpart; | |
| 1661 | 352461 | double pi2, pi_factor, theta; | |
| 1662 | 352461 | double avr; | |
| 1663 | |||
| 1664 | /* Compute neighbor coordinates to current IMAP direction */ | ||
| 1665 | 352461 | e = mx+1; /* East */ | |
| 1666 | 352461 | w = mx-1; /* West */ | |
| 1667 | 352461 | n = my-1; /* North */ | |
| 1668 | 352461 | s = my+1; /* South */ | |
| 1669 | |||
| 1670 | /* Intialize accumulators */ | ||
| 1671 | 352461 | *nvalid = 0; | |
| 1672 | 352461 | cospart = 0.0; | |
| 1673 | 352461 | sinpart = 0.0; | |
| 1674 | |||
| 1675 | /* 1. Test NW */ | ||
| 1676 | /* If NW point within IMAP boudaries ... */ | ||
| 1677 |
2/2✓ Branch 0 (2→3) taken 332827 times.
✓ Branch 1 (2→5) taken 19634 times.
|
352461 | if((w >= 0) && (n >= 0)){ |
| 1678 | 332827 | iptr = imap + (n*mw) + w; | |
| 1679 | /* If valid direction ... */ | ||
| 1680 |
2/2✓ Branch 0 (3→4) taken 291383 times.
✓ Branch 1 (3→5) taken 41444 times.
|
332827 | if(*iptr != INVALID_DIR){ |
| 1681 | /* Accumulate cosine and sine components of the direction */ | ||
| 1682 | 291383 | cospart += dir2rad->cos[*iptr]; | |
| 1683 | 291383 | sinpart += dir2rad->sin[*iptr]; | |
| 1684 | /* Bump number of accumulated directions */ | ||
| 1685 | 291383 | (*nvalid)++; | |
| 1686 | } | ||
| 1687 | } | ||
| 1688 | |||
| 1689 | /* 2. Test N */ | ||
| 1690 | /* If N point within IMAP boudaries ... */ | ||
| 1691 |
2/2✓ Branch 0 (5→6) taken 343874 times.
✓ Branch 1 (5→8) taken 8587 times.
|
352461 | if(n >= 0){ |
| 1692 | 343874 | iptr = imap + (n*mw) + mx; | |
| 1693 | /* If valid direction ... */ | ||
| 1694 |
2/2✓ Branch 0 (6→7) taken 305668 times.
✓ Branch 1 (6→8) taken 38206 times.
|
343874 | if(*iptr != INVALID_DIR){ |
| 1695 | /* Accumulate cosine and sine components of the direction */ | ||
| 1696 | 305668 | cospart += dir2rad->cos[*iptr]; | |
| 1697 | 305668 | sinpart += dir2rad->sin[*iptr]; | |
| 1698 | /* Bump number of accumulated directions */ | ||
| 1699 | 305668 | (*nvalid)++; | |
| 1700 | } | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | /* 3. Test NE */ | ||
| 1704 | /* If NE point within IMAP boudaries ... */ | ||
| 1705 |
2/2✓ Branch 0 (8→9) taken 334128 times.
✓ Branch 1 (8→11) taken 18333 times.
|
352461 | if((e < mw) && (n >= 0)){ |
| 1706 | 334128 | iptr = imap + (n*mw) + e; | |
| 1707 | /* If valid direction ... */ | ||
| 1708 |
2/2✓ Branch 0 (9→10) taken 291706 times.
✓ Branch 1 (9→11) taken 42422 times.
|
334128 | if(*iptr != INVALID_DIR){ |
| 1709 | /* Accumulate cosine and sine components of the direction */ | ||
| 1710 | 291706 | cospart += dir2rad->cos[*iptr]; | |
| 1711 | 291706 | sinpart += dir2rad->sin[*iptr]; | |
| 1712 | /* Bump number of accumulated directions */ | ||
| 1713 | 291706 | (*nvalid)++; | |
| 1714 | } | ||
| 1715 | } | ||
| 1716 | |||
| 1717 | /* 4. Test E */ | ||
| 1718 | /* If E point within IMAP boudaries ... */ | ||
| 1719 |
2/2✓ Branch 0 (11→12) taken 342501 times.
✓ Branch 1 (11→14) taken 9960 times.
|
352461 | if(e < mw){ |
| 1720 | 342501 | iptr = imap + (my*mw) + e; | |
| 1721 | /* If valid direction ... */ | ||
| 1722 |
2/2✓ Branch 0 (12→13) taken 303000 times.
✓ Branch 1 (12→14) taken 39501 times.
|
342501 | if(*iptr != INVALID_DIR){ |
| 1723 | /* Accumulate cosine and sine components of the direction */ | ||
| 1724 | 303000 | cospart += dir2rad->cos[*iptr]; | |
| 1725 | 303000 | sinpart += dir2rad->sin[*iptr]; | |
| 1726 | /* Bump number of accumulated directions */ | ||
| 1727 | 303000 | (*nvalid)++; | |
| 1728 | } | ||
| 1729 | } | ||
| 1730 | |||
| 1731 | /* 5. Test SE */ | ||
| 1732 | /* If SE point within IMAP boudaries ... */ | ||
| 1733 |
2/2✓ Branch 0 (14→15) taken 331886 times.
✓ Branch 1 (14→17) taken 20575 times.
|
352461 | if((e < mw) && (s < mh)){ |
| 1734 | 331886 | iptr = imap + (s*mw) + e; | |
| 1735 | /* If valid direction ... */ | ||
| 1736 |
2/2✓ Branch 0 (15→16) taken 290021 times.
✓ Branch 1 (15→17) taken 41865 times.
|
331886 | if(*iptr != INVALID_DIR){ |
| 1737 | /* Accumulate cosine and sine components of the direction */ | ||
| 1738 | 290021 | cospart += dir2rad->cos[*iptr]; | |
| 1739 | 290021 | sinpart += dir2rad->sin[*iptr]; | |
| 1740 | /* Bump number of accumulated directions */ | ||
| 1741 | 290021 | (*nvalid)++; | |
| 1742 | } | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | /* 6. Test S */ | ||
| 1746 | /* If S point within IMAP boudaries ... */ | ||
| 1747 |
2/2✓ Branch 0 (17→18) taken 341524 times.
✓ Branch 1 (17→20) taken 10937 times.
|
352461 | if(s < mh){ |
| 1748 | 341524 | iptr = imap + (s*mw) + mx; | |
| 1749 | /* If valid direction ... */ | ||
| 1750 |
2/2✓ Branch 0 (18→19) taken 303870 times.
✓ Branch 1 (18→20) taken 37654 times.
|
341524 | if(*iptr != INVALID_DIR){ |
| 1751 | /* Accumulate cosine and sine components of the direction */ | ||
| 1752 | 303870 | cospart += dir2rad->cos[*iptr]; | |
| 1753 | 303870 | sinpart += dir2rad->sin[*iptr]; | |
| 1754 | /* Bump number of accumulated directions */ | ||
| 1755 | 303870 | (*nvalid)++; | |
| 1756 | } | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | /* 7. Test SW */ | ||
| 1760 | /* If SW point within IMAP boudaries ... */ | ||
| 1761 |
2/2✓ Branch 0 (20→21) taken 330415 times.
✓ Branch 1 (20→23) taken 22046 times.
|
352461 | if((w >= 0) && (s < mh)){ |
| 1762 | 330415 | iptr = imap + (s*mw) + w; | |
| 1763 | /* If valid direction ... */ | ||
| 1764 |
2/2✓ Branch 0 (21→22) taken 290298 times.
✓ Branch 1 (21→23) taken 40117 times.
|
330415 | if(*iptr != INVALID_DIR){ |
| 1765 | /* Accumulate cosine and sine components of the direction */ | ||
| 1766 | 290298 | cospart += dir2rad->cos[*iptr]; | |
| 1767 | 290298 | sinpart += dir2rad->sin[*iptr]; | |
| 1768 | /* Bump number of accumulated directions */ | ||
| 1769 | 290298 | (*nvalid)++; | |
| 1770 | } | ||
| 1771 | } | ||
| 1772 | |||
| 1773 | /* 8. Test W */ | ||
| 1774 | /* If W point within IMAP boudaries ... */ | ||
| 1775 |
2/2✓ Branch 0 (23→24) taken 341061 times.
✓ Branch 1 (23→26) taken 11400 times.
|
352461 | if(w >= 0){ |
| 1776 | 341061 | iptr = imap + (my*mw) + w; | |
| 1777 | /* If valid direction ... */ | ||
| 1778 |
2/2✓ Branch 0 (24→25) taken 304074 times.
✓ Branch 1 (24→26) taken 36987 times.
|
341061 | if(*iptr != INVALID_DIR){ |
| 1779 | /* Accumulate cosine and sine components of the direction */ | ||
| 1780 | 304074 | cospart += dir2rad->cos[*iptr]; | |
| 1781 | 304074 | sinpart += dir2rad->sin[*iptr]; | |
| 1782 | /* Bump number of accumulated directions */ | ||
| 1783 | 304074 | (*nvalid)++; | |
| 1784 | } | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | /* If there were no neighbors found with valid direction ... */ | ||
| 1788 |
2/2✓ Branch 0 (26→27) taken 6620 times.
✓ Branch 1 (26→28) taken 345841 times.
|
352461 | if(*nvalid == 0){ |
| 1789 | /* Return INVALID direction. */ | ||
| 1790 | 6620 | *dir_strength = 0; | |
| 1791 | 6620 | *avrdir = INVALID_DIR; | |
| 1792 | 6620 | return; | |
| 1793 | } | ||
| 1794 | |||
| 1795 | /* Compute averages of accumulated cosine and sine direction components */ | ||
| 1796 | 345841 | cospart /= (double)(*nvalid); | |
| 1797 | 345841 | sinpart /= (double)(*nvalid); | |
| 1798 | |||
| 1799 | /* Compute directional strength as hypotenuse (without sqrt) of average */ | ||
| 1800 | /* cosine and sine direction components. Believe this value will be on */ | ||
| 1801 | /* the range of [0 .. 1]. */ | ||
| 1802 | 345841 | *dir_strength = (cospart * cospart) + (sinpart * sinpart); | |
| 1803 | /* Need to truncate precision so that answers are consistent */ | ||
| 1804 | /* on different computer architectures when comparing doubles. */ | ||
| 1805 | 345841 | *dir_strength = trunc_dbl_precision(*dir_strength, TRUNC_SCALE); | |
| 1806 | |||
| 1807 | /* If the direction strength is not sufficiently high ... */ | ||
| 1808 |
2/2✓ Branch 0 (28→29) taken 11731 times.
✓ Branch 1 (28→30) taken 334110 times.
|
345841 | if(*dir_strength < DIR_STRENGTH_MIN){ |
| 1809 | /* Return INVALID direction. */ | ||
| 1810 | 11731 | *dir_strength = 0; | |
| 1811 | 11731 | *avrdir = INVALID_DIR; | |
| 1812 | 11731 | return; | |
| 1813 | } | ||
| 1814 | |||
| 1815 | /* Compute angle (in radians) from Arctan of avarage */ | ||
| 1816 | /* cosine and sine direction components. I think this order */ | ||
| 1817 | /* is necessary because 0 direction is vertical and positive */ | ||
| 1818 | /* direction is clockwise. */ | ||
| 1819 | 334110 | theta = atan2(sinpart, cospart); | |
| 1820 | |||
| 1821 | /* Atan2 returns theta on range [-PI..PI]. Adjust theta so that */ | ||
| 1822 | /* it is on the range [0..2PI]. */ | ||
| 1823 | 334110 | pi2 = 2*M_PI; | |
| 1824 | 334110 | theta += pi2; | |
| 1825 | 334110 | theta = fmod(theta, pi2); | |
| 1826 | |||
| 1827 | /* Pi_factor sets the period of the trig functions to NDIRS units in x. */ | ||
| 1828 | /* For example, if NDIRS==16, then pi_factor = 2(PI/16) = .3926... */ | ||
| 1829 | /* Dividing theta (in radians) by this factor ((1/pi_factor)==2.546...) */ | ||
| 1830 | /* will produce directions on the range [0..NDIRS]. */ | ||
| 1831 | 334110 | pi_factor = pi2/(double)dir2rad->ndirs; /* 2(M_PI/ndirs) */ | |
| 1832 | |||
| 1833 | /* Round off the direction and return it as an average direction */ | ||
| 1834 | /* for the neighborhood. */ | ||
| 1835 | 334110 | avr = theta / pi_factor; | |
| 1836 | /* Need to truncate precision so that answers are consistent */ | ||
| 1837 | /* on different computer architectures when rounding doubles. */ | ||
| 1838 |
1/2✗ Branch 0 (30→31) not taken.
✓ Branch 1 (30→32) taken 334110 times.
|
334110 | avr = trunc_dbl_precision(avr, TRUNC_SCALE); |
| 1839 |
1/2✗ Branch 0 (33→34) not taken.
✓ Branch 1 (33→35) taken 334110 times.
|
334110 | *avrdir = sround(avr); |
| 1840 | |||
| 1841 | /* Really do need to map values > NDIRS back onto [0..NDIRS) range. */ | ||
| 1842 | 334110 | *avrdir %= dir2rad->ndirs; | |
| 1843 | } | ||
| 1844 | |||
| 1845 | /************************************************************************* | ||
| 1846 | ************************************************************************** | ||
| 1847 | #cat: num_valid_8nbrs - Given a block in an IMAP, counts the number of | ||
| 1848 | #cat: immediate neighbors that have a valid IMAP direction. | ||
| 1849 | |||
| 1850 | Input: | ||
| 1851 | imap - 2-D vector of directional ridge flows | ||
| 1852 | mx - horizontal coord of current block in IMAP | ||
| 1853 | my - vertical coord of current block in IMAP | ||
| 1854 | mw - width (in blocks) of the IMAP | ||
| 1855 | mh - height (in blocks) of the IMAP | ||
| 1856 | Return Code: | ||
| 1857 | Non-negative - the number of valid IMAP neighbors | ||
| 1858 | **************************************************************************/ | ||
| 1859 | 51995 | int num_valid_8nbrs(int *imap, const int mx, const int my, | |
| 1860 | const int mw, const int mh) | ||
| 1861 | { | ||
| 1862 | 51995 | int e_ind, w_ind, n_ind, s_ind; | |
| 1863 | 51995 | int nvalid; | |
| 1864 | |||
| 1865 | /* Initialize VALID IMAP counter to zero. */ | ||
| 1866 | 51995 | nvalid = 0; | |
| 1867 | |||
| 1868 | /* Compute neighbor coordinates to current IMAP direction */ | ||
| 1869 | 51995 | e_ind = mx+1; /* East index */ | |
| 1870 | 51995 | w_ind = mx-1; /* West index */ | |
| 1871 | 51995 | n_ind = my-1; /* North index */ | |
| 1872 | 51995 | s_ind = my+1; /* South index */ | |
| 1873 | |||
| 1874 | /* 1. Test NW IMAP value. */ | ||
| 1875 | /* If neighbor indices are within IMAP boundaries and it is VALID ... */ | ||
| 1876 |
4/4✓ Branch 0 (2→3) taken 3623 times.
✓ Branch 1 (2→4) taken 48372 times.
✓ Branch 2 (4→3) taken 8837 times.
✓ Branch 3 (4→5) taken 39535 times.
|
51995 | if((w_ind >= 0) && (n_ind >= 0) && (*(imap + (n_ind*mw) + w_ind) >= 0)) |
| 1877 | /* Bump VALID counter. */ | ||
| 1878 | 51995 | nvalid++; | |
| 1879 | |||
| 1880 | /* 2. Test N IMAP value. */ | ||
| 1881 |
4/4✓ Branch 0 (5→6) taken 50174 times.
✓ Branch 1 (5→8) taken 1821 times.
✓ Branch 2 (6→7) taken 39404 times.
✓ Branch 3 (6→8) taken 10770 times.
|
51995 | if((n_ind >= 0) && (*(imap + (n_ind*mw) + mx) >= 0)) |
| 1882 | 39404 | nvalid++; | |
| 1883 | |||
| 1884 | /* 3. Test NE IMAP value. */ | ||
| 1885 |
4/4✓ Branch 0 (8→9) taken 48519 times.
✓ Branch 1 (8→11) taken 3476 times.
✓ Branch 2 (9→10) taken 39703 times.
✓ Branch 3 (9→11) taken 8816 times.
|
51995 | if((n_ind >= 0) && (e_ind < mw) && (*(imap + (n_ind*mw) + e_ind) >= 0)) |
| 1886 | 39703 | nvalid++; | |
| 1887 | |||
| 1888 | /* 4. Test E IMAP value. */ | ||
| 1889 |
4/4✓ Branch 0 (11→12) taken 50292 times.
✓ Branch 1 (11→14) taken 1703 times.
✓ Branch 2 (12→13) taken 39460 times.
✓ Branch 3 (12→14) taken 10832 times.
|
51995 | if((e_ind < mw) && (*(imap + (my*mw) + e_ind) >= 0)) |
| 1890 | 39460 | nvalid++; | |
| 1891 | |||
| 1892 | /* 5. Test SE IMAP value. */ | ||
| 1893 |
4/4✓ Branch 0 (14→15) taken 48645 times.
✓ Branch 1 (14→17) taken 3350 times.
✓ Branch 2 (15→16) taken 39825 times.
✓ Branch 3 (15→17) taken 8820 times.
|
51995 | if((e_ind < mw) && (s_ind < mh) && (*(imap + (s_ind*mw) + e_ind) >= 0)) |
| 1894 | 39825 | nvalid++; | |
| 1895 | |||
| 1896 | /* 6. Test S IMAP value. */ | ||
| 1897 |
4/4✓ Branch 0 (17→18) taken 50300 times.
✓ Branch 1 (17→20) taken 1695 times.
✓ Branch 2 (18→19) taken 39564 times.
✓ Branch 3 (18→20) taken 10736 times.
|
51995 | if((s_ind < mh) && (*(imap + (s_ind*mw) + mx) >= 0)) |
| 1898 | 39564 | nvalid++; | |
| 1899 | |||
| 1900 | /* 7. Test SW IMAP value. */ | ||
| 1901 |
4/4✓ Branch 0 (20→21) taken 48498 times.
✓ Branch 1 (20→23) taken 3497 times.
✓ Branch 2 (21→22) taken 39749 times.
✓ Branch 3 (21→23) taken 8749 times.
|
51995 | if((w_ind >= 0) && (s_ind < mh) && (*(imap + (s_ind*mw) + w_ind) >= 0)) |
| 1902 | 39749 | nvalid++; | |
| 1903 | |||
| 1904 | /* 8. Test W IMAP value. */ | ||
| 1905 |
4/4✓ Branch 0 (23→24) taken 50145 times.
✓ Branch 1 (23→26) taken 1850 times.
✓ Branch 2 (24→25) taken 39314 times.
✓ Branch 3 (24→26) taken 10831 times.
|
51995 | if((w_ind >= 0) && (*(imap + (my*mw) + w_ind) >= 0)) |
| 1906 | 39314 | nvalid++; | |
| 1907 | |||
| 1908 | /* Return number of neighbors with VALID IMAP values. */ | ||
| 1909 | 51995 | return(nvalid); | |
| 1910 | } | ||
| 1911 | |||
| 1912 | /************************************************************************* | ||
| 1913 | ************************************************************************** | ||
| 1914 | #cat: smooth_imap - Takes a vector of integer directions and smooths them | ||
| 1915 | #cat: by analyzing the direction of adjacent neighbors. | ||
| 1916 | |||
| 1917 | Input: | ||
| 1918 | imap - vector of IMAP integer directions | ||
| 1919 | mw - width (in blocks) of the IMAP | ||
| 1920 | mh - height (in blocks) of the IMAP | ||
| 1921 | dir2rad - lookup table for converting integer directions | ||
| 1922 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1923 | Output: | ||
| 1924 | imap - vector of smoothed input values | ||
| 1925 | **************************************************************************/ | ||
| 1926 | |||
| 1927 | /************************************************************************* | ||
| 1928 | ************************************************************************** | ||
| 1929 | #cat: gen_nmap - Computes an NMAP from its associated 2D vector of integer | ||
| 1930 | #cat: directions (IMAP). Each value in the NMAP either represents | ||
| 1931 | #cat: a direction of dominant ridge flow in a block of the input | ||
| 1932 | #cat: grayscale image, or it contains a codes describing why such | ||
| 1933 | #cat: a direction was not procuded. | ||
| 1934 | #cat: For example, blocks near areas of high-curvature (such as | ||
| 1935 | #cat: with cores and deltas) will not produce reliable IMAP | ||
| 1936 | #cat: directions. | ||
| 1937 | |||
| 1938 | Input: | ||
| 1939 | imap - associated input vector of IMAP directions | ||
| 1940 | mw - the width (in blocks) of the IMAP | ||
| 1941 | mh - the height (in blocks) of the IMAP | ||
| 1942 | lfsparms - parameters and thresholds for controlling LFS | ||
| 1943 | Output: | ||
| 1944 | optr - points to the created NMAP | ||
| 1945 | Return Code: | ||
| 1946 | Zero - successful completion | ||
| 1947 | Negative - system error | ||
| 1948 | **************************************************************************/ | ||
| 1949 | |||
| 1950 | /************************************************************************* | ||
| 1951 | ************************************************************************** | ||
| 1952 | #cat: vorticity - Measures the amount of cummulative curvature incurred | ||
| 1953 | #cat: among the IMAP neighbors of the given block. | ||
| 1954 | |||
| 1955 | Input: | ||
| 1956 | imap - 2D vector of ridge flow directions | ||
| 1957 | mx - horizontal coord of current IMAP block | ||
| 1958 | my - vertical coord of current IMAP block | ||
| 1959 | mw - width (in blocks) of the IMAP | ||
| 1960 | mh - height (in blocks) of the IMAP | ||
| 1961 | ndirs - number of possible directions in the IMAP | ||
| 1962 | Return Code: | ||
| 1963 | Non-negative - the measured vorticity among the neighbors | ||
| 1964 | **************************************************************************/ | ||
| 1965 | 16 | int vorticity(int *imap, const int mx, const int my, | |
| 1966 | const int mw, const int mh, const int ndirs) | ||
| 1967 | { | ||
| 1968 | 16 | int e_ind, w_ind, n_ind, s_ind; | |
| 1969 | 16 | int nw_val, n_val, ne_val, e_val, se_val, s_val, sw_val, w_val; | |
| 1970 | 16 | int vmeasure; | |
| 1971 | |||
| 1972 | /* Compute neighbor coordinates to current IMAP direction */ | ||
| 1973 | 16 | e_ind = mx+1; /* East index */ | |
| 1974 | 16 | w_ind = mx-1; /* West index */ | |
| 1975 | 16 | n_ind = my-1; /* North index */ | |
| 1976 | 16 | s_ind = my+1; /* South index */ | |
| 1977 | |||
| 1978 | /* 1. Get NW IMAP value. */ | ||
| 1979 | /* If neighbor indices are within IMAP boundaries ... */ | ||
| 1980 |
1/2✓ Branch 0 (2→3) taken 16 times.
✗ Branch 1 (2→4) not taken.
|
16 | if((w_ind >= 0) && (n_ind >= 0)) |
| 1981 | /* Set neighbor value to IMAP value. */ | ||
| 1982 | 16 | nw_val = *(imap + (n_ind*mw) + w_ind); | |
| 1983 | else | ||
| 1984 | /* Otherwise, set the neighbor value to INVALID. */ | ||
| 1985 | nw_val = INVALID_DIR; | ||
| 1986 | |||
| 1987 | /* 2. Get N IMAP value. */ | ||
| 1988 |
1/2✓ Branch 0 (4→5) taken 16 times.
✗ Branch 1 (4→6) not taken.
|
16 | if(n_ind >= 0) |
| 1989 | 16 | n_val = *(imap + (n_ind*mw) + mx); | |
| 1990 | else | ||
| 1991 | n_val = INVALID_DIR; | ||
| 1992 | |||
| 1993 | /* 3. Get NE IMAP value. */ | ||
| 1994 |
1/2✓ Branch 0 (6→7) taken 16 times.
✗ Branch 1 (6→8) not taken.
|
16 | if((n_ind >= 0) && (e_ind < mw)) |
| 1995 | 16 | ne_val = *(imap + (n_ind*mw) + e_ind); | |
| 1996 | else | ||
| 1997 | ne_val = INVALID_DIR; | ||
| 1998 | |||
| 1999 | /* 4. Get E IMAP value. */ | ||
| 2000 |
1/2✓ Branch 0 (8→9) taken 16 times.
✗ Branch 1 (8→10) not taken.
|
16 | if(e_ind < mw) |
| 2001 | 16 | e_val = *(imap + (my*mw) + e_ind); | |
| 2002 | else | ||
| 2003 | e_val = INVALID_DIR; | ||
| 2004 | |||
| 2005 | /* 5. Get SE IMAP value. */ | ||
| 2006 |
1/2✓ Branch 0 (10→11) taken 16 times.
✗ Branch 1 (10→12) not taken.
|
16 | if((e_ind < mw) && (s_ind < mh)) |
| 2007 | 16 | se_val = *(imap + (s_ind*mw) + e_ind); | |
| 2008 | else | ||
| 2009 | se_val = INVALID_DIR; | ||
| 2010 | |||
| 2011 | /* 6. Get S IMAP value. */ | ||
| 2012 |
1/2✓ Branch 0 (12→13) taken 16 times.
✗ Branch 1 (12→14) not taken.
|
16 | if(s_ind < mh) |
| 2013 | 16 | s_val = *(imap + (s_ind*mw) + mx); | |
| 2014 | else | ||
| 2015 | s_val = INVALID_DIR; | ||
| 2016 | |||
| 2017 | /* 7. Get SW IMAP value. */ | ||
| 2018 |
1/2✓ Branch 0 (14→15) taken 16 times.
✗ Branch 1 (14→16) not taken.
|
16 | if((w_ind >= 0) && (s_ind < mh)) |
| 2019 | 16 | sw_val = *(imap + (s_ind*mw) + w_ind); | |
| 2020 | else | ||
| 2021 | sw_val = INVALID_DIR; | ||
| 2022 | |||
| 2023 | /* 8. Get W IMAP value. */ | ||
| 2024 |
1/2✓ Branch 0 (16→17) taken 16 times.
✗ Branch 1 (16→18) not taken.
|
16 | if(w_ind >= 0) |
| 2025 | 16 | w_val = *(imap + (my*mw) + w_ind); | |
| 2026 | else | ||
| 2027 | w_val = INVALID_DIR; | ||
| 2028 | |||
| 2029 | /* Now that we have all IMAP neighbors, accumulate vorticity between */ | ||
| 2030 | /* the neighboring directions. */ | ||
| 2031 | |||
| 2032 | /* Initialize vorticity accumulator to zero. */ | ||
| 2033 | 16 | vmeasure = 0; | |
| 2034 | |||
| 2035 | /* 1. NW & N */ | ||
| 2036 | 16 | accum_nbr_vorticity(&vmeasure, nw_val, n_val, ndirs); | |
| 2037 | |||
| 2038 | /* 2. N & NE */ | ||
| 2039 | 16 | accum_nbr_vorticity(&vmeasure, n_val, ne_val, ndirs); | |
| 2040 | |||
| 2041 | /* 3. NE & E */ | ||
| 2042 | 16 | accum_nbr_vorticity(&vmeasure, ne_val, e_val, ndirs); | |
| 2043 | |||
| 2044 | /* 4. E & SE */ | ||
| 2045 | 16 | accum_nbr_vorticity(&vmeasure, e_val, se_val, ndirs); | |
| 2046 | |||
| 2047 | /* 5. SE & S */ | ||
| 2048 | 16 | accum_nbr_vorticity(&vmeasure, se_val, s_val, ndirs); | |
| 2049 | |||
| 2050 | /* 6. S & SW */ | ||
| 2051 | 16 | accum_nbr_vorticity(&vmeasure, s_val, sw_val, ndirs); | |
| 2052 | |||
| 2053 | /* 7. SW & W */ | ||
| 2054 | 16 | accum_nbr_vorticity(&vmeasure, sw_val, w_val, ndirs); | |
| 2055 | |||
| 2056 | /* 8. W & NW */ | ||
| 2057 | 16 | accum_nbr_vorticity(&vmeasure, w_val, nw_val, ndirs); | |
| 2058 | |||
| 2059 | /* Return the accumulated vorticity measure. */ | ||
| 2060 | 16 | return(vmeasure); | |
| 2061 | } | ||
| 2062 | |||
| 2063 | /************************************************************************* | ||
| 2064 | ************************************************************************** | ||
| 2065 | #cat: accum_nbor_vorticity - Accumlates the amount of curvature measures | ||
| 2066 | #cat: between neighboring IMAP blocks. | ||
| 2067 | |||
| 2068 | Input: | ||
| 2069 | dir1 - first neighbor's integer IMAP direction | ||
| 2070 | dir2 - second neighbor's integer IMAP direction | ||
| 2071 | ndirs - number of possible IMAP directions | ||
| 2072 | Output: | ||
| 2073 | vmeasure - accumulated vorticity among neighbors measured so far | ||
| 2074 | **************************************************************************/ | ||
| 2075 | 128 | void accum_nbr_vorticity(int *vmeasure, const int dir1, const int dir2, | |
| 2076 | const int ndirs) | ||
| 2077 | { | ||
| 2078 | 128 | int dist; | |
| 2079 | |||
| 2080 | /* Measure difference in direction between a pair of neighboring */ | ||
| 2081 | /* directions. */ | ||
| 2082 | /* If both neighbors are not equal and both are VALID ... */ | ||
| 2083 |
4/4✓ Branch 0 (2→3) taken 62 times.
✓ Branch 1 (2→9) taken 66 times.
✓ Branch 2 (3→4) taken 51 times.
✓ Branch 3 (3→9) taken 11 times.
|
128 | if((dir1 != dir2) && (dir1 >= 0)&&(dir2 >= 0)){ |
| 2084 | /* Measure the clockwise distance from the first to the second */ | ||
| 2085 | /* directions. */ | ||
| 2086 | 51 | dist = dir2 - dir1; | |
| 2087 | /* If dist is negative, then clockwise distance must wrap around */ | ||
| 2088 | /* the high end of the direction range. For example: */ | ||
| 2089 | /* dir1 = 8 */ | ||
| 2090 | /* dir2 = 3 */ | ||
| 2091 | /* and ndirs = 16 */ | ||
| 2092 | /* 3 - 8 = -5 */ | ||
| 2093 | /* so 16 - 5 = 11 (the clockwise distance from 8 to 3) */ | ||
| 2094 |
2/2✓ Branch 0 (4→5) taken 28 times.
✓ Branch 1 (4→6) taken 23 times.
|
51 | if(dist < 0) |
| 2095 | 28 | dist += ndirs; | |
| 2096 | /* If the change in clockwise direction is larger than 90 degrees as */ | ||
| 2097 | /* in total the total number of directions covers 180 degrees. */ | ||
| 2098 |
2/2✓ Branch 0 (6→7) taken 28 times.
✓ Branch 1 (6→8) taken 23 times.
|
51 | if(dist > (ndirs>>1)) |
| 2099 | /* Decrement the vorticity measure. */ | ||
| 2100 | 28 | (*vmeasure)--; | |
| 2101 | else | ||
| 2102 | /* Otherwise, bump the vorticity measure. */ | ||
| 2103 | 23 | (*vmeasure)++; | |
| 2104 | } | ||
| 2105 | /* Otherwise both directions are either equal or */ | ||
| 2106 | /* one or both directions are INVALID, so ignore. */ | ||
| 2107 | 128 | } | |
| 2108 | |||
| 2109 | /************************************************************************* | ||
| 2110 | ************************************************************************** | ||
| 2111 | #cat: curvature - Measures the largest change in direction between the | ||
| 2112 | #cat: current IMAP direction and its immediate neighbors. | ||
| 2113 | |||
| 2114 | Input: | ||
| 2115 | imap - 2D vector of ridge flow directions | ||
| 2116 | mx - horizontal coord of current IMAP block | ||
| 2117 | my - vertical coord of current IMAP block | ||
| 2118 | mw - width (in blocks) of the IMAP | ||
| 2119 | mh - height (in blocks) of the IMAP | ||
| 2120 | ndirs - number of possible directions in the IMAP | ||
| 2121 | Return Code: | ||
| 2122 | Non-negative - maximum change in direction found (curvature) | ||
| 2123 | Negative - No valid neighbor found to measure change in direction | ||
| 2124 | **************************************************************************/ | ||
| 2125 | 38951 | int curvature(int *imap, const int mx, const int my, | |
| 2126 | const int mw, const int mh, const int ndirs) | ||
| 2127 | { | ||
| 2128 | 38951 | int *iptr; | |
| 2129 | 38951 | int e_ind, w_ind, n_ind, s_ind; | |
| 2130 | 38951 | int nw_val, n_val, ne_val, e_val, se_val, s_val, sw_val, w_val; | |
| 2131 | 38951 | int cmeasure, dist; | |
| 2132 | |||
| 2133 | /* Compute neighbor coordinates to current IMAP direction */ | ||
| 2134 | 38951 | e_ind = mx+1; /* East index */ | |
| 2135 | 38951 | w_ind = mx-1; /* West index */ | |
| 2136 | 38951 | n_ind = my-1; /* North index */ | |
| 2137 | 38951 | s_ind = my+1; /* South index */ | |
| 2138 | |||
| 2139 | /* 1. Get NW IMAP value. */ | ||
| 2140 | /* If neighbor indices are within IMAP boundaries ... */ | ||
| 2141 |
1/2✓ Branch 0 (2→3) taken 38951 times.
✗ Branch 1 (2→4) not taken.
|
38951 | if((w_ind >= 0) && (n_ind >= 0)) |
| 2142 | /* Set neighbor value to IMAP value. */ | ||
| 2143 | 38951 | nw_val = *(imap + (n_ind*mw) + w_ind); | |
| 2144 | else | ||
| 2145 | /* Otherwise, set the neighbor value to INVALID. */ | ||
| 2146 | nw_val = INVALID_DIR; | ||
| 2147 | |||
| 2148 | /* 2. Get N IMAP value. */ | ||
| 2149 |
1/2✓ Branch 0 (4→5) taken 38951 times.
✗ Branch 1 (4→6) not taken.
|
38951 | if(n_ind >= 0) |
| 2150 | 38951 | n_val = *(imap + (n_ind*mw) + mx); | |
| 2151 | else | ||
| 2152 | n_val = INVALID_DIR; | ||
| 2153 | |||
| 2154 | /* 3. Get NE IMAP value. */ | ||
| 2155 |
1/2✓ Branch 0 (6→7) taken 38951 times.
✗ Branch 1 (6→8) not taken.
|
38951 | if((n_ind >= 0) && (e_ind < mw)) |
| 2156 | 38951 | ne_val = *(imap + (n_ind*mw) + e_ind); | |
| 2157 | else | ||
| 2158 | ne_val = INVALID_DIR; | ||
| 2159 | |||
| 2160 | /* 4. Get E IMAP value. */ | ||
| 2161 |
1/2✓ Branch 0 (8→9) taken 38951 times.
✗ Branch 1 (8→10) not taken.
|
38951 | if(e_ind < mw) |
| 2162 | 38951 | e_val = *(imap + (my*mw) + e_ind); | |
| 2163 | else | ||
| 2164 | e_val = INVALID_DIR; | ||
| 2165 | |||
| 2166 | /* 5. Get SE IMAP value. */ | ||
| 2167 |
1/2✓ Branch 0 (10→11) taken 38951 times.
✗ Branch 1 (10→12) not taken.
|
38951 | if((e_ind < mw) && (s_ind < mh)) |
| 2168 | 38951 | se_val = *(imap + (s_ind*mw) + e_ind); | |
| 2169 | else | ||
| 2170 | se_val = INVALID_DIR; | ||
| 2171 | |||
| 2172 | /* 6. Get S IMAP value. */ | ||
| 2173 |
1/2✓ Branch 0 (12→13) taken 38951 times.
✗ Branch 1 (12→14) not taken.
|
38951 | if(s_ind < mh) |
| 2174 | 38951 | s_val = *(imap + (s_ind*mw) + mx); | |
| 2175 | else | ||
| 2176 | s_val = INVALID_DIR; | ||
| 2177 | |||
| 2178 | /* 7. Get SW IMAP value. */ | ||
| 2179 |
1/2✓ Branch 0 (14→15) taken 38951 times.
✗ Branch 1 (14→16) not taken.
|
38951 | if((w_ind >= 0) && (s_ind < mh)) |
| 2180 | 38951 | sw_val = *(imap + (s_ind*mw) + w_ind); | |
| 2181 | else | ||
| 2182 | sw_val = INVALID_DIR; | ||
| 2183 | |||
| 2184 | /* 8. Get W IMAP value. */ | ||
| 2185 |
1/2✓ Branch 0 (16→17) taken 38951 times.
✗ Branch 1 (16→18) not taken.
|
38951 | if(w_ind >= 0) |
| 2186 | 38951 | w_val = *(imap + (my*mw) + w_ind); | |
| 2187 | else | ||
| 2188 | w_val = INVALID_DIR; | ||
| 2189 | |||
| 2190 | /* Now that we have all IMAP neighbors, determine largest change in */ | ||
| 2191 | /* direction from current block to each of its 8 VALID neighbors. */ | ||
| 2192 | |||
| 2193 | /* Initialize pointer to current IMAP value. */ | ||
| 2194 | 38951 | iptr = imap + (my*mw) + mx; | |
| 2195 | |||
| 2196 | /* Initialize curvature measure to negative as closest_dir_dist() */ | ||
| 2197 | /* always returns -1=INVALID or a positive value. */ | ||
| 2198 | 38951 | cmeasure = -1; | |
| 2199 | |||
| 2200 | /* 1. With NW */ | ||
| 2201 | /* Compute closest distance between neighboring directions. */ | ||
| 2202 | 38951 | dist = closest_dir_dist(*iptr, nw_val, ndirs); | |
| 2203 | /* Keep track of maximum. */ | ||
| 2204 | 38951 | if(dist > cmeasure) | |
| 2205 | cmeasure = dist; | ||
| 2206 | |||
| 2207 | /* 2. With N */ | ||
| 2208 | 38951 | dist = closest_dir_dist(*iptr, n_val, ndirs); | |
| 2209 | 38951 | if(dist > cmeasure) | |
| 2210 | cmeasure = dist; | ||
| 2211 | |||
| 2212 | /* 3. With NE */ | ||
| 2213 | 38951 | dist = closest_dir_dist(*iptr, ne_val, ndirs); | |
| 2214 | 38951 | if(dist > cmeasure) | |
| 2215 | cmeasure = dist; | ||
| 2216 | |||
| 2217 | /* 4. With E */ | ||
| 2218 | 38951 | dist = closest_dir_dist(*iptr, e_val, ndirs); | |
| 2219 | 38951 | if(dist > cmeasure) | |
| 2220 | cmeasure = dist; | ||
| 2221 | |||
| 2222 | /* 5. With SE */ | ||
| 2223 | 38951 | dist = closest_dir_dist(*iptr, se_val, ndirs); | |
| 2224 | 38951 | if(dist > cmeasure) | |
| 2225 | cmeasure = dist; | ||
| 2226 | |||
| 2227 | /* 6. With S */ | ||
| 2228 | 38951 | dist = closest_dir_dist(*iptr, s_val, ndirs); | |
| 2229 | 38951 | if(dist > cmeasure) | |
| 2230 | cmeasure = dist; | ||
| 2231 | |||
| 2232 | /* 7. With SW */ | ||
| 2233 | 38951 | dist = closest_dir_dist(*iptr, sw_val, ndirs); | |
| 2234 | 38951 | if(dist > cmeasure) | |
| 2235 | cmeasure = dist; | ||
| 2236 | |||
| 2237 | /* 8. With W */ | ||
| 2238 | 38951 | dist = closest_dir_dist(*iptr, w_val, ndirs); | |
| 2239 | 38951 | if(dist > cmeasure) | |
| 2240 | cmeasure = dist; | ||
| 2241 | |||
| 2242 | /* Return maximum difference between current block's IMAP direction */ | ||
| 2243 | /* and the rest of its VALID neighbors. */ | ||
| 2244 | 38951 | return(cmeasure); | |
| 2245 | } | ||
| 2246 |