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 taken 768 times.
✓ Branch 1 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 taken 384 times.
✓ Branch 1 taken 384 times.
|
768 | cs = trunc_dbl_precision(cs, TRUNC_SCALE); |
117 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 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 taken 192 times.
✓ Branch 1 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 taken 4608 times.
✓ Branch 1 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 not taken.
✓ Branch 1 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 not taken.
✓ Branch 1 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 not taken.
✓ Branch 1 taken 48 times.
|
48 | pad = trunc_dbl_precision(pad, TRUNC_SCALE); |
324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 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 taken 48 times.
✓ Branch 1 taken 48 times.
✗ Branch 2 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 not taken.
✓ Branch 1 taken 48 times.
|
48 | pad = trunc_dbl_precision(pad, TRUNC_SCALE); |
393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 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 not taken.
✓ Branch 1 taken 48 times.
|
48 | pad = trunc_dbl_precision(pad, TRUNC_SCALE); |
404 |
1/2✗ Branch 0 not taken.
✓ Branch 1 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 not taken.
✓ Branch 1 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 not taken.
✓ Branch 1 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 taken 1536 times.
✓ Branch 1 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 taken 25344 times.
✓ Branch 1 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 taken 18432 times.
✓ Branch 1 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 taken 490752 times.
✓ Branch 1 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 taken 41424 times.
✓ Branch 1 taken 449328 times.
|
490752 | fx = trunc_dbl_precision(fx, TRUNC_SCALE); |
516 |
2/2✓ Branch 0 taken 40896 times.
✓ Branch 1 taken 449856 times.
|
490752 | fy = trunc_dbl_precision(fy, TRUNC_SCALE); |
517 |
2/2✓ Branch 0 taken 39696 times.
✓ Branch 1 taken 451056 times.
|
490752 | ixt = sround(fx); |
518 |
2/2✓ Branch 0 taken 39696 times.
✓ Branch 1 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 1 taken 192 times.
✓ Branch 2 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 taken 48 times.
✗ Branch 1 not taken.
|
48 | ASSERT_SIZE_MUL(nstats, sizeof(int)); |
601 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
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 |