| 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: INIT.C | ||
| 49 | AUTHOR: Michael D. Garris | ||
| 50 | DATE: 03/16/1999 | ||
| 51 | UPDATED: 10/04/1999 Version 2 by MDG | ||
| 52 | UPDATED: 03/16/2005 by MDG | ||
| 53 | |||
| 54 | Contains routines responsible for allocation and/or initialization | ||
| 55 | of memories required by the NIST Latent Fingerprint System. | ||
| 56 | |||
| 57 | *********************************************************************** | ||
| 58 | ROUTINES: | ||
| 59 | init_dir2rad() | ||
| 60 | init_dftwaves() | ||
| 61 | get_max_padding() | ||
| 62 | get_max_padding_V2() | ||
| 63 | init_rotgrids() | ||
| 64 | alloc_dir_powers() | ||
| 65 | alloc_power_stats() | ||
| 66 | ***********************************************************************/ | ||
| 67 | |||
| 68 | #include <stdio.h> | ||
| 69 | #include <lfs.h> | ||
| 70 | |||
| 71 | /************************************************************************* | ||
| 72 | ************************************************************************** | ||
| 73 | #cat: init_dir2rad - Allocates and initializes a lookup table containing | ||
| 74 | #cat: cosine and sine values needed to convert integer IMAP | ||
| 75 | #cat: directions to angles in radians. | ||
| 76 | |||
| 77 | Input: | ||
| 78 | ndirs - the number of integer directions to be defined in a | ||
| 79 | semicircle | ||
| 80 | Output: | ||
| 81 | optr - points to the allocated/initialized DIR2RAD structure | ||
| 82 | Return Code: | ||
| 83 | Zero - successful completion | ||
| 84 | Negative - system error | ||
| 85 | **************************************************************************/ | ||
| 86 | 48 | int init_dir2rad(DIR2RAD **optr, const int ndirs) | |
| 87 | { | ||
| 88 | 48 | DIR2RAD *dir2rad; | |
| 89 | 48 | int i; | |
| 90 | 48 | double theta, pi_factor; | |
| 91 | 48 | double cs, sn; | |
| 92 | |||
| 93 | /* Allocate structure */ | ||
| 94 | 48 | dir2rad = (DIR2RAD *)g_malloc(sizeof(DIR2RAD)); | |
| 95 | |||
| 96 | /* Assign number of directions */ | ||
| 97 | 48 | dir2rad->ndirs = ndirs; | |
| 98 | |||
| 99 | /* Allocate cosine vector */ | ||
| 100 | 48 | dir2rad->cos = (double *)g_malloc(ndirs * sizeof(double)); | |
| 101 | |||
| 102 | /* Allocate sine vector */ | ||
| 103 | 48 | dir2rad->sin = (double *)g_malloc(ndirs * sizeof(double)); | |
| 104 | |||
| 105 | /* Pi_factor sets the period of the trig functions to NDIRS units in x. */ | ||
| 106 | /* For example, if NDIRS==16, then pi_factor = 2(PI/16) = .3926... */ | ||
| 107 | 48 | pi_factor = 2.0*M_PI/(double)ndirs; | |
| 108 | |||
| 109 | /* Now compute cos and sin values for each direction. */ | ||
| 110 |
2/2✓ Branch 0 (13→6) taken 768 times.
✓ Branch 1 (13→14) taken 48 times.
|
816 | for (i = 0; i < ndirs; ++i) { |
| 111 | 768 | theta = (double)(i * pi_factor); | |
| 112 | 768 | cs = cos(theta); | |
| 113 | 768 | sn = sin(theta); | |
| 114 | /* Need to truncate precision so that answers are consistent */ | ||
| 115 | /* on different computer architectures. */ | ||
| 116 |
2/2✓ Branch 0 (6→7) taken 384 times.
✓ Branch 1 (6→8) taken 384 times.
|
768 | cs = trunc_dbl_precision(cs, TRUNC_SCALE); |
| 117 |
2/2✓ Branch 0 (9→10) taken 336 times.
✓ Branch 1 (9→11) taken 432 times.
|
768 | sn = trunc_dbl_precision(sn, TRUNC_SCALE); |
| 118 | 768 | dir2rad->cos[i] = cs; | |
| 119 | 768 | dir2rad->sin[i] = sn; | |
| 120 | } | ||
| 121 | |||
| 122 | 48 | *optr = dir2rad; | |
| 123 | 48 | return(0); | |
| 124 | } | ||
| 125 | |||
| 126 | /************************************************************************* | ||
| 127 | ************************************************************************** | ||
| 128 | #cat: init_dftwaves - Allocates and initializes a set of wave forms needed | ||
| 129 | #cat: to conduct DFT analysis on blocks of the input image | ||
| 130 | |||
| 131 | Input: | ||
| 132 | dft_coefs - array of multipliers used to define the frequency for | ||
| 133 | each wave form to be computed | ||
| 134 | nwaves - number of wave forms to be computed | ||
| 135 | blocksize - the width and height of each block of image data to | ||
| 136 | be DFT analyzed | ||
| 137 | Output: | ||
| 138 | optr - points to the allocated/initialized DFTWAVES structure | ||
| 139 | Return Code: | ||
| 140 | Zero - successful completion | ||
| 141 | Negative - system error | ||
| 142 | **************************************************************************/ | ||
| 143 | 48 | int init_dftwaves(DFTWAVES **optr, const double *dft_coefs, | |
| 144 | const int nwaves, const int blocksize) | ||
| 145 | { | ||
| 146 | 48 | DFTWAVES *dftwaves; | |
| 147 | 48 | int i, j; | |
| 148 | 48 | double pi_factor, freq, x; | |
| 149 | 48 | double *cptr, *sptr; | |
| 150 | |||
| 151 | /* Allocate structure */ | ||
| 152 | 48 | dftwaves = (DFTWAVES *)g_malloc(sizeof(DFTWAVES)); | |
| 153 | |||
| 154 | /* Set number of DFT waves */ | ||
| 155 | 48 | dftwaves->nwaves = nwaves; | |
| 156 | /* Set wave length of the DFT waves (they all must be the same length) */ | ||
| 157 | 48 | dftwaves->wavelen = blocksize; | |
| 158 | |||
| 159 | /* Allocate list of wave pointers */ | ||
| 160 | 48 | dftwaves->waves = (DFTWAVE **)g_malloc(nwaves * sizeof(DFTWAVE *)); | |
| 161 | 48 | if(dftwaves == (DFTWAVES *)NULL){ | |
| 162 | /* Free memory allocated to this point. */ | ||
| 163 | g_free(dftwaves); | ||
| 164 | fprintf(stderr, "ERROR : init_dftwaves : malloc : dftwaves->waves\n"); | ||
| 165 | return(-21); | ||
| 166 | } | ||
| 167 | |||
| 168 | /* Pi_factor sets the period of the trig functions to BLOCKSIZE units */ | ||
| 169 | /* in x. For example, if BLOCKSIZE==24, then */ | ||
| 170 | /* pi_factor = 2(PI/24) = .26179... */ | ||
| 171 | 48 | pi_factor = 2.0*M_PI/(double)blocksize; | |
| 172 | |||
| 173 | /* Foreach of 4 DFT frequency coef ... */ | ||
| 174 |
2/2✓ Branch 0 (12→5) taken 192 times.
✓ Branch 1 (12→13) taken 48 times.
|
240 | for (i = 0; i < nwaves; ++i) { |
| 175 | /* Allocate wave structure */ | ||
| 176 | 192 | dftwaves->waves[i] = (DFTWAVE *)g_malloc(sizeof(DFTWAVE)); | |
| 177 | /* Allocate cosine vector */ | ||
| 178 | 192 | dftwaves->waves[i]->cos = (double *)g_malloc(blocksize * sizeof(double)); | |
| 179 | /* Allocate sine vector */ | ||
| 180 | 192 | dftwaves->waves[i]->sin = (double *)g_malloc(blocksize * sizeof(double)); | |
| 181 | |||
| 182 | /* Assign pointer nicknames */ | ||
| 183 | 192 | cptr = dftwaves->waves[i]->cos; | |
| 184 | 192 | sptr = dftwaves->waves[i]->sin; | |
| 185 | |||
| 186 | /* Compute actual frequency */ | ||
| 187 | 192 | freq = pi_factor * dft_coefs[i]; | |
| 188 | |||
| 189 | /* Used as a 1D DFT on a 24 long vector of pixel sums */ | ||
| 190 |
2/2✓ Branch 0 (10→9) taken 4608 times.
✓ Branch 1 (10→11) taken 192 times.
|
4800 | for (j = 0; j < blocksize; ++j) { |
| 191 | /* Compute sample points from frequency */ | ||
| 192 | 4608 | x = freq * (double)j; | |
| 193 | /* Store cos and sin components of sample point */ | ||
| 194 | 4608 | *cptr++ = cos(x); | |
| 195 | 4608 | *sptr++ = sin(x); | |
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | 48 | *optr = dftwaves; | |
| 200 | 48 | return(0); | |
| 201 | } | ||
| 202 | |||
| 203 | /************************************************************************* | ||
| 204 | ************************************************************************** | ||
| 205 | #cat: get_max_padding - Deterines the maximum amount of image pixel padding | ||
| 206 | #cat: required by all LFS processes. Padding is currently | ||
| 207 | #cat: required by the rotated grids used in DFT analyses, | ||
| 208 | #cat: rotated grids used in directional binarization, | ||
| 209 | #cat: and in the grid used for isotropic binarization. | ||
| 210 | #cat: The NIST generalized code enables the parameters | ||
| 211 | #cat: governing these processes to be redefined, so a check | ||
| 212 | #cat: at runtime is required to determine which process | ||
| 213 | #cat: requires the most padding. By using the maximum as | ||
| 214 | #cat: the padding factor, all processes will run safely | ||
| 215 | #cat: with a single padding of the input image avoiding the | ||
| 216 | #cat: need to repad for further processes. | ||
| 217 | |||
| 218 | Input: | ||
| 219 | imap_blocksize - the size (in pixels) of each IMAP block in the image | ||
| 220 | dirbin_grid_w - the width (in pixels) of the rotated grids used in | ||
| 221 | directional binarization | ||
| 222 | dirbin_grid_h - the height (in pixels) of the rotated grids used in | ||
| 223 | directional binarization | ||
| 224 | isobin_grid_dim - the dimension (in pixels) of the square grid used in | ||
| 225 | isotropic binarization | ||
| 226 | Return Code: | ||
| 227 | Non-negative - the maximum padding required for all processes | ||
| 228 | **************************************************************************/ | ||
| 229 | |||
| 230 | /************************************************************************* | ||
| 231 | ************************************************************************** | ||
| 232 | #cat: get_max_padding_V2 - Deterines the maximum amount of image pixel padding | ||
| 233 | #cat: required by all LFS (Version 2) processes. Padding is currently | ||
| 234 | #cat: required by the rotated grids used in DFT analyses and in | ||
| 235 | #cat: directional binarization. The NIST generalized code enables | ||
| 236 | #cat: the parameters governing these processes to be redefined, so a | ||
| 237 | #cat: check at runtime is required to determine which process | ||
| 238 | #cat: requires the most padding. By using the maximum as the padding | ||
| 239 | #cat: factor, all processes will run safely with a single padding of | ||
| 240 | #cat: the input image avoiding the need to repad for further processes. | ||
| 241 | |||
| 242 | Input: | ||
| 243 | map_windowsize - the size (in pixels) of each window centered about | ||
| 244 | each block in the image used in DFT analyses | ||
| 245 | map_windowoffset - the offset (in pixels) from the orgin of the | ||
| 246 | surrounding window to the origin of the block | ||
| 247 | dirbin_grid_w - the width (in pixels) of the rotated grids used in | ||
| 248 | directional binarization | ||
| 249 | dirbin_grid_h - the height (in pixels) of the rotated grids used in | ||
| 250 | directional binarization | ||
| 251 | Return Code: | ||
| 252 | Non-negative - the maximum padding required for all processes | ||
| 253 | **************************************************************************/ | ||
| 254 | 48 | int get_max_padding_V2(const int map_windowsize, const int map_windowoffset, | |
| 255 | const int dirbin_grid_w, const int dirbin_grid_h) | ||
| 256 | { | ||
| 257 | 48 | int dft_pad, dirbin_pad, max_pad; | |
| 258 | 48 | double diag; | |
| 259 | 48 | double pad; | |
| 260 | |||
| 261 | |||
| 262 | /* 1. Compute pad required for rotated windows used in DFT analyses. */ | ||
| 263 | |||
| 264 | /* Explanation of DFT padding: | ||
| 265 | |||
| 266 | B--------------------- | ||
| 267 | | window | | ||
| 268 | | | | ||
| 269 | | | | ||
| 270 | | A.......______|__________ | ||
| 271 | | : : | | ||
| 272 | |<-C-->: block: | | ||
| 273 | <--|--D-->: : | image | ||
| 274 | | ........ | | ||
| 275 | | | | | ||
| 276 | | | | | ||
| 277 | | | | | ||
| 278 | ---------------------- | ||
| 279 | | | ||
| 280 | | | ||
| 281 | | | ||
| 282 | |||
| 283 | Pixel A = Origin of entire fingerprint image | ||
| 284 | = Also origin of first block in image. Each pixel in | ||
| 285 | this block gets the same DFT results computed from | ||
| 286 | the surrounding window. Note that in general | ||
| 287 | blocks are adjacent and non-overlapping. | ||
| 288 | |||
| 289 | Pixel B = Origin of surrounding window in which DFT | ||
| 290 | analysis is conducted. Note that this window is not | ||
| 291 | completely contained in the image but extends to the | ||
| 292 | top and to the right. | ||
| 293 | |||
| 294 | Distance C = Number of pixels in which the window extends | ||
| 295 | beyond the image (map_windowoffset). | ||
| 296 | |||
| 297 | Distance D = Amount of padding required to hold the entire | ||
| 298 | rotated window in memory. | ||
| 299 | |||
| 300 | */ | ||
| 301 | |||
| 302 | /* Compute pad as difference between the MAP windowsize */ | ||
| 303 | /* and the diagonal distance of the window. */ | ||
| 304 | /* (DFT grids are computed with pixel offsets RELATIVE2ORIGIN.) */ | ||
| 305 | 48 | diag = sqrt((double)(2.0 * map_windowsize * map_windowsize)); | |
| 306 | 48 | pad = (diag-map_windowsize)/(double)2.0; | |
| 307 | /* Need to truncate precision so that answers are consistent */ | ||
| 308 | /* on different computer architectures when rounding doubles. */ | ||
| 309 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 48 times.
|
48 | pad = trunc_dbl_precision(pad, TRUNC_SCALE); |
| 310 | /* Must add the window offset to the rotational padding. */ | ||
| 311 |
1/2✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→7) taken 48 times.
|
48 | dft_pad = sround(pad) + map_windowoffset; |
| 312 | |||
| 313 | /* 2. Compute pad required for rotated blocks used in directional */ | ||
| 314 | /* binarization. Binarization blocks are applied to each pixel */ | ||
| 315 | /* in the input image. */ | ||
| 316 | 48 | diag = sqrt((double)((dirbin_grid_w*dirbin_grid_w)+ | |
| 317 | 48 | (dirbin_grid_h*dirbin_grid_h))); | |
| 318 | /* Assumption: all grid centers reside in valid/allocated memory. */ | ||
| 319 | /* (Dirbin grids are computed with pixel offsets RELATIVE2CENTER.) */ | ||
| 320 | 48 | pad = (diag-1)/(double)2.0; | |
| 321 | /* Need to truncate precision so that answers are consistent */ | ||
| 322 | /* on different computer architectures when rounding doubles. */ | ||
| 323 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 48 times.
|
48 | pad = trunc_dbl_precision(pad, TRUNC_SCALE); |
| 324 |
1/2✗ Branch 0 (11→12) not taken.
✓ Branch 1 (11→13) taken 48 times.
|
48 | dirbin_pad = sround(pad); |
| 325 | |||
| 326 | 48 | max_pad = max(dft_pad, dirbin_pad); | |
| 327 | |||
| 328 | /* Return the maximum of the two required paddings. This padding will */ | ||
| 329 | /* be sufficiently large for all purposes, so that padding of the */ | ||
| 330 | /* input image will only be required once. */ | ||
| 331 | 48 | return(max_pad); | |
| 332 | } | ||
| 333 | |||
| 334 | /************************************************************************* | ||
| 335 | ************************************************************************** | ||
| 336 | #cat: init_rotgrids - Allocates and initializes a set of offsets that address | ||
| 337 | #cat: individual rotated pixels within a grid. | ||
| 338 | #cat: These rotated grids are used to conduct DFT analyses | ||
| 339 | #cat: on blocks of input image data, and they are used | ||
| 340 | #cat: in isotropic binarization. | ||
| 341 | |||
| 342 | Input: | ||
| 343 | iw - width (in pixels) of the input image | ||
| 344 | ih - height (in pixels) of the input image | ||
| 345 | pad - designates the number of pixels to be padded to the perimeter | ||
| 346 | of the input image. May be passed as UNDEFINED, in which | ||
| 347 | case the specific padding required by the rotated grids | ||
| 348 | will be computed and returned in ROTGRIDS. | ||
| 349 | start_dir_angle - angle from which rotations are to start | ||
| 350 | ndirs - number of rotations to compute (within a semicircle) | ||
| 351 | grid_w - width of the grid in pixels to be rotated | ||
| 352 | grid_h - height of the grid in pixels to be rotated | ||
| 353 | relative2 - designates whether pixel offsets whould be computed | ||
| 354 | relative to the ORIGIN or the CENTER of the grid | ||
| 355 | Output: | ||
| 356 | optr - points to the allcated/initialized ROTGRIDS structure | ||
| 357 | Return Code: | ||
| 358 | Zero - successful completion | ||
| 359 | Negative - system error | ||
| 360 | **************************************************************************/ | ||
| 361 | 96 | int init_rotgrids(ROTGRIDS **optr, const int iw, const int ih, const int ipad, | |
| 362 | const double start_dir_angle, const int ndirs, | ||
| 363 | const int grid_w, const int grid_h, const int relative2) | ||
| 364 | { | ||
| 365 | 96 | ROTGRIDS *rotgrids; | |
| 366 | 96 | double pi_offset, pi_incr; | |
| 367 | 96 | int dir, ix, iy, grid_size, pw, grid_pad, min_dim; | |
| 368 | 96 | int *grid; | |
| 369 | 96 | double diag, theta, cs, sn, cx, cy; | |
| 370 | 96 | double fxm, fym, fx, fy; | |
| 371 | 96 | int ixt, iyt; | |
| 372 | 96 | double pad; | |
| 373 | |||
| 374 | /* Allocate structure */ | ||
| 375 | 96 | rotgrids = (ROTGRIDS *)g_malloc(sizeof(ROTGRIDS)); | |
| 376 | |||
| 377 | /* Set rotgrid attributes */ | ||
| 378 | 96 | rotgrids->ngrids = ndirs; | |
| 379 | 96 | rotgrids->grid_w = grid_w; | |
| 380 | 96 | rotgrids->grid_h = grid_h; | |
| 381 | 96 | rotgrids->start_angle = start_dir_angle; | |
| 382 | 96 | rotgrids->relative2 = relative2; | |
| 383 | |||
| 384 | /* Compute pad based on diagonal of the grid */ | ||
| 385 | 96 | diag = sqrt((double)((grid_w*grid_w)+(grid_h*grid_h))); | |
| 386 |
2/3✓ Branch 0 (3→4) taken 48 times.
✓ Branch 1 (3→10) taken 48 times.
✗ Branch 2 (3→16) not taken.
|
96 | switch(relative2){ |
| 387 | 48 | case RELATIVE2CENTER: | |
| 388 | /* Assumption: all grid centers reside in valid/allocated memory. */ | ||
| 389 | 48 | pad = (diag-1)/(double)2.0; | |
| 390 | /* Need to truncate precision so that answers are consistent */ | ||
| 391 | /* on different computer architectures when rounding doubles. */ | ||
| 392 |
1/2✗ Branch 0 (4→5) not taken.
✓ Branch 1 (4→6) taken 48 times.
|
48 | pad = trunc_dbl_precision(pad, TRUNC_SCALE); |
| 393 |
1/2✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→9) taken 48 times.
|
48 | grid_pad = sround(pad); |
| 394 | break; | ||
| 395 | 48 | case RELATIVE2ORIGIN: | |
| 396 | /* Assumption: all grid origins reside in valid/allocated memory. */ | ||
| 397 | 48 | min_dim = min(grid_w, grid_h); | |
| 398 | /* Compute pad as difference between the smallest grid dimension */ | ||
| 399 | /* and the diagonal distance of the grid. */ | ||
| 400 | 48 | pad = (diag-min_dim)/(double)2.0; | |
| 401 | /* Need to truncate precision so that answers are consistent */ | ||
| 402 | /* on different computer architectures when rounding doubles. */ | ||
| 403 |
1/2✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→12) taken 48 times.
|
48 | pad = trunc_dbl_precision(pad, TRUNC_SCALE); |
| 404 |
1/2✗ Branch 0 (13→14) not taken.
✓ Branch 1 (13→15) taken 48 times.
|
48 | grid_pad = sround(pad); |
| 405 | break; | ||
| 406 | ✗ | default: | |
| 407 | ✗ | fprintf(stderr, | |
| 408 | "ERROR : init_rotgrids : Illegal relative flag : %d\n", | ||
| 409 | relative2); | ||
| 410 | ✗ | g_free(rotgrids); | |
| 411 | ✗ | return(-31); | |
| 412 | } | ||
| 413 | |||
| 414 | /* If input padding is UNDEFINED ... */ | ||
| 415 |
1/2✗ Branch 0 (19→20) not taken.
✓ Branch 1 (19→21) taken 96 times.
|
96 | if(ipad == UNDEFINED) |
| 416 | /* Use the padding specifically required by the rotated grids herein. */ | ||
| 417 | ✗ | rotgrids->pad = grid_pad; | |
| 418 | else{ | ||
| 419 | /* Otherwise, input pad was specified, so check to make sure it is */ | ||
| 420 | /* sufficiently large to handle the rotated grids herein. */ | ||
| 421 |
1/2✗ Branch 0 (21→22) not taken.
✓ Branch 1 (21→25) taken 96 times.
|
96 | if(ipad < grid_pad){ |
| 422 | /* If input pad is NOT large enough, then ERROR. */ | ||
| 423 | ✗ | fprintf(stderr, "ERROR : init_rotgrids : Pad passed is too small\n"); | |
| 424 | ✗ | g_free(rotgrids); | |
| 425 | ✗ | return(-32); | |
| 426 | } | ||
| 427 | /* Otherwise, use the specified input pad in computing grid offsets. */ | ||
| 428 | 96 | rotgrids->pad = ipad; | |
| 429 | } | ||
| 430 | |||
| 431 | /* Total number of points in grid */ | ||
| 432 | 96 | grid_size = grid_w * grid_h; | |
| 433 | |||
| 434 | /* Compute width of "padded" image */ | ||
| 435 | 96 | pw = iw + (rotgrids->pad<<1); | |
| 436 | |||
| 437 | /* Center coord of grid (0-oriented). */ | ||
| 438 | 96 | cx = (grid_w-1)/(double)2.0; | |
| 439 | 96 | cy = (grid_h-1)/(double)2.0; | |
| 440 | |||
| 441 | /* Allocate list of rotgrid pointers */ | ||
| 442 | 96 | rotgrids->grids = (int **)g_malloc(ndirs * sizeof(int *)); | |
| 443 | |||
| 444 | /* Pi_offset is the offset in radians from which angles are to begin. */ | ||
| 445 | 96 | pi_offset = start_dir_angle; | |
| 446 | 96 | pi_incr = M_PI/(double)ndirs; /* if ndirs == 16, incr = 11.25 degrees */ | |
| 447 | |||
| 448 | /* For each direction to rotate a grid ... */ | ||
| 449 | 96 | for (dir = 0, theta = pi_offset; | |
| 450 |
2/2✓ Branch 0 (50→28) taken 1536 times.
✓ Branch 1 (50→51) taken 96 times.
|
1632 | dir < ndirs; dir++, theta += pi_incr) { |
| 451 | |||
| 452 | /* Allocate a rotgrid */ | ||
| 453 | 1536 | rotgrids->grids[dir] = (int *)g_malloc(grid_size * sizeof(int)); | |
| 454 | |||
| 455 | /* Set pointer to current grid */ | ||
| 456 | 1536 | grid = rotgrids->grids[dir]; | |
| 457 | |||
| 458 | /* Compute cos and sin of current angle */ | ||
| 459 | 1536 | cs = cos(theta); | |
| 460 | 1536 | sn = sin(theta); | |
| 461 | |||
| 462 | /* This next section of nested FOR loops precomputes a */ | ||
| 463 | /* rotated grid. The rotation is set up to rotate a GRID_W X */ | ||
| 464 | /* GRID_H grid on its center point at C=(Cx,Cy). The current */ | ||
| 465 | /* pixel being rotated is P=(Ix,Iy). Therefore, we have a */ | ||
| 466 | /* rotation transformation of point P about pivot point C. */ | ||
| 467 | /* The rotation transformation about a pivot point in matrix */ | ||
| 468 | /* form is: */ | ||
| 469 | /* | ||
| 470 | +- -+ | ||
| 471 | | cos(T) sin(T) 0 | | ||
| 472 | [Ix Iy 1] | -sin(T) cos(T) 0 | | ||
| 473 | | (1-cos(T))*Cx + Cy*sin(T) (1-cos(T))*Cy - Cx*sin(T) 1 | | ||
| 474 | +- -+ | ||
| 475 | */ | ||
| 476 | /* Multiplying the 2 matrices and combining terms yeilds the */ | ||
| 477 | /* equations for rotated coordinates (Rx, Ry): */ | ||
| 478 | /* Rx = Cx + (Ix - Cx)*cos(T) - (Iy - Cy)*sin(T) */ | ||
| 479 | /* Ry = Cy + (Ix - Cx)*sin(T) + (Iy - Cy)*cos(T) */ | ||
| 480 | /* */ | ||
| 481 | /* Care has been taken to ensure that (for example) when */ | ||
| 482 | /* BLOCKSIZE==24 the rotated indices stay within a centered */ | ||
| 483 | /* 34X34 area. */ | ||
| 484 | /* This is important for computing an accurate padding of */ | ||
| 485 | /* the input image. The rotation occurs "in-place" so that */ | ||
| 486 | /* outer pixels in the grid are mapped at times from */ | ||
| 487 | /* adjoining blocks. As a result, to keep from accessing */ | ||
| 488 | /* "unknown" memory or pixels wrapped from the other side of */ | ||
| 489 | /* the image, the input image should first be padded by */ | ||
| 490 | /* PAD=round((DIAG - BLOCKSIZE)/2.0) where DIAG is the */ | ||
| 491 | /* diagonal distance of the grid. */ | ||
| 492 | /* For example, when BLOCKSIZE==24, Dx=34, so PAD=5. */ | ||
| 493 | |||
| 494 | /* Foreach each y coord in block ... */ | ||
| 495 |
2/2✓ Branch 0 (48→30) taken 25344 times.
✓ Branch 1 (48→49) taken 1536 times.
|
26880 | for (iy = 0; iy < grid_h; ++iy) { |
| 496 | /* Compute rotation factors dependent on Iy (include constant) */ | ||
| 497 | 25344 | fxm = -1.0 * ((iy - cy) * sn); | |
| 498 | 25344 | fym = ((iy - cy) * cs); | |
| 499 | |||
| 500 | /* If offsets are to be relative to the grids origin, then */ | ||
| 501 | /* we need to subtract CX and CY. */ | ||
| 502 |
2/2✓ Branch 0 (30→31) taken 18432 times.
✓ Branch 1 (30→32) taken 6912 times.
|
25344 | if(relative2 == RELATIVE2ORIGIN){ |
| 503 | 18432 | fxm += cx; | |
| 504 | 18432 | fym += cy; | |
| 505 | } | ||
| 506 | |||
| 507 | /* foreach each x coord in block ... */ | ||
| 508 |
2/2✓ Branch 0 (46→33) taken 490752 times.
✓ Branch 1 (46→47) taken 25344 times.
|
516096 | for (ix = 0; ix < grid_w; ++ix) { |
| 509 | |||
| 510 | /* Now combine factors dependent on Iy with those of Ix */ | ||
| 511 | 490752 | fx = fxm + ((ix - cx) * cs); | |
| 512 | 490752 | fy = fym + ((ix - cx) * sn); | |
| 513 | /* Need to truncate precision so that answers are consistent */ | ||
| 514 | /* on different computer architectures when rounding doubles. */ | ||
| 515 |
2/2✓ Branch 0 (33→34) taken 41424 times.
✓ Branch 1 (33→35) taken 449328 times.
|
490752 | fx = trunc_dbl_precision(fx, TRUNC_SCALE); |
| 516 |
2/2✓ Branch 0 (36→37) taken 40896 times.
✓ Branch 1 (36→38) taken 449856 times.
|
490752 | fy = trunc_dbl_precision(fy, TRUNC_SCALE); |
| 517 |
2/2✓ Branch 0 (39→40) taken 39696 times.
✓ Branch 1 (39→41) taken 451056 times.
|
490752 | ixt = sround(fx); |
| 518 |
2/2✓ Branch 0 (42→43) taken 39696 times.
✓ Branch 1 (42→44) taken 451056 times.
|
490752 | iyt = sround(fy); |
| 519 | |||
| 520 | /* Store the current pixels relative */ | ||
| 521 | /* rotated offset. Make sure to */ | ||
| 522 | /* multiply the y-component of the */ | ||
| 523 | /* offset by the "padded" image width! */ | ||
| 524 | 490752 | *grid++ = ixt + (iyt * pw); | |
| 525 | }/* ix */ | ||
| 526 | }/* iy */ | ||
| 527 | }/* dir */ | ||
| 528 | |||
| 529 | 96 | *optr = rotgrids; | |
| 530 | 96 | return(0); | |
| 531 | } | ||
| 532 | |||
| 533 | /************************************************************************* | ||
| 534 | ************************************************************************** | ||
| 535 | #cat: alloc_dir_powers - Allocates the memory associated with DFT power | ||
| 536 | #cat: vectors. The DFT analysis is conducted block by block in the | ||
| 537 | #cat: input image, and within each block, N wave forms are applied | ||
| 538 | #cat: at M different directions. | ||
| 539 | |||
| 540 | Input: | ||
| 541 | nwaves - number of DFT wave forms | ||
| 542 | ndirs - number of orientations (directions) used in DFT analysis | ||
| 543 | Output: | ||
| 544 | opowers - pointer to the allcated power vectors | ||
| 545 | Return Code: | ||
| 546 | Zero - successful completion | ||
| 547 | Negative - system error | ||
| 548 | **************************************************************************/ | ||
| 549 | 48 | int alloc_dir_powers(double ***opowers, const int nwaves, const int ndirs) | |
| 550 | { | ||
| 551 | 48 | int w; | |
| 552 | 48 | double **powers; | |
| 553 | |||
| 554 | /* Allocate list of double pointers to hold power vectors */ | ||
| 555 | 48 | powers = (double **)g_malloc(nwaves * sizeof(double *)); | |
| 556 | /* Foreach DFT wave ... */ | ||
| 557 |
2/2✓ Branch 0 (6→4) taken 192 times.
✓ Branch 1 (6→7) taken 48 times.
|
288 | for(w = 0; w < nwaves; w++){ |
| 558 | /* Allocate power vector for all directions */ | ||
| 559 | 192 | powers[w] = (double *)g_malloc(ndirs * sizeof(double)); | |
| 560 | } | ||
| 561 | |||
| 562 | 48 | *opowers = powers; | |
| 563 | 48 | return(0); | |
| 564 | } | ||
| 565 | |||
| 566 | /************************************************************************* | ||
| 567 | ************************************************************************** | ||
| 568 | #cat: alloc_power_stats - Allocates memory associated with set of statistics | ||
| 569 | #cat: derived from DFT power vectors computed in a block of the | ||
| 570 | #cat: input image. Statistics are not computed for the lowest DFT | ||
| 571 | #cat: wave form, so the length of the statistics arrays is 1 less | ||
| 572 | #cat: than the number of DFT wave forms used. The staistics | ||
| 573 | #cat: include the Maximum power for each wave form, the direction | ||
| 574 | #cat: at which the maximum power occured, and a normalized value | ||
| 575 | #cat: for the maximum power. In addition, the statistics are | ||
| 576 | #cat: ranked in descending order based on normalized squared | ||
| 577 | #cat: maximum power. | ||
| 578 | |||
| 579 | Input: | ||
| 580 | nstats - the number of waves forms from which statistics are to be | ||
| 581 | derived (N Waves - 1) | ||
| 582 | Output: | ||
| 583 | owis - points to an array to hold the ranked wave form indicies | ||
| 584 | of the corresponding statistics | ||
| 585 | opowmaxs - points to an array to hold the maximum DFT power for each | ||
| 586 | wave form | ||
| 587 | opowmax_dirs - points to an array to hold the direction corresponding to | ||
| 588 | each maximum power value | ||
| 589 | opownorms - points to an array to hold the normalized maximum power | ||
| 590 | Return Code: | ||
| 591 | Zero - successful completion | ||
| 592 | Negative - system error | ||
| 593 | **************************************************************************/ | ||
| 594 | 48 | int alloc_power_stats(int **owis, double **opowmaxs, int **opowmax_dirs, | |
| 595 | double **opownorms, const int nstats) | ||
| 596 | { | ||
| 597 | 48 | int *wis, *powmax_dirs; | |
| 598 | 48 | double *powmaxs, *pownorms; | |
| 599 | |||
| 600 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 48 times.
|
48 | ASSERT_SIZE_MUL(nstats, sizeof(int)); |
| 601 |
1/2✓ Branch 0 (4→5) taken 48 times.
✗ Branch 1 (4→10) not taken.
|
48 | ASSERT_SIZE_MUL(nstats, sizeof(double)); |
| 602 | |||
| 603 | /* Allocate DFT wave index vector */ | ||
| 604 | 48 | wis = (int *)g_malloc(nstats * sizeof(int)); | |
| 605 | |||
| 606 | /* Allocate max power vector */ | ||
| 607 | 48 | powmaxs = (double *)g_malloc(nstats * sizeof(double)); | |
| 608 | |||
| 609 | /* Allocate max power direction vector */ | ||
| 610 | 48 | powmax_dirs = (int *)g_malloc(nstats * sizeof(int)); | |
| 611 | |||
| 612 | /* Allocate normalized power vector */ | ||
| 613 | 48 | pownorms = (double *)g_malloc(nstats * sizeof(double)); | |
| 614 | |||
| 615 | 48 | *owis = wis; | |
| 616 | 48 | *opowmaxs = powmaxs; | |
| 617 | 48 | *opowmax_dirs = powmax_dirs; | |
| 618 | 48 | *opownorms = pownorms; | |
| 619 | 48 | return(0); | |
| 620 | } | ||
| 621 | |||
| 622 | |||
| 623 | |||
| 624 |