1 /*******************************************************************************
4 This software was developed at the National Institute of Standards and
5 Technology (NIST) by employees of the Federal Government in the course
6 of their official duties. Pursuant to title 17 Section 105 of the
7 United States Code, this software is not subject to copyright protection
8 and is in the public domain. NIST assumes no responsibility whatsoever for
9 its use by other parties, and makes no guarantees, expressed or implied,
10 about its quality, reliability, or any other characteristic.
13 This software was developed to promote biometric standards and biometric
14 technology testing for the Federal Government in accordance with the USA
15 PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
16 Specific hardware and software products identified in this software were used
17 in order to perform the software development. In no case does such
18 identification imply recommendation or endorsement by the National Institute
19 of Standards and Technology, nor does it imply that the products and equipment
20 identified are necessarily the best available for the purpose.
22 *******************************************************************************/
24 /***********************************************************************
25 LIBRARY: LFS - NIST Latent Fingerprint System
28 AUTHOR: Michael D. Garris
30 UPDATED: 03/16/2005 by MDG
32 Contains routines responsible for conducting Discrete Fourier
33 Transforms (DFT) analysis on a block of image data as part of
34 the NIST Latent Fingerprint System (LFS).
36 ***********************************************************************
44 ***********************************************************************/
50 /*************************************************************************
51 **************************************************************************
52 #cat: sum_rot_block_rows - Computes a vector or pixel row sums by sampling
53 #cat: the current image block at a given orientation. The
54 #cat: sampling is conducted using a precomputed set of rotated
55 #cat: pixel offsets (called a grid) relative to the orgin of
56 #cat: the image block.
59 blkptr - the pixel address of the origin of the current image block
60 grid_offsets - the rotated pixel offsets for a block-sized grid
61 rotated according to a specific orientation
62 blocksize - the width and height of the image block and thus the size
65 rowsums - the resulting vector of pixel row sums
66 **************************************************************************/
67 static void sum_rot_block_rows(int *rowsums
, const unsigned char *blkptr
,
68 const int *grid_offsets
, const int blocksize
)
72 /* Initialize rotation offset index. */
75 /* For each row in block ... */
76 for(iy
= 0; iy
< blocksize
; iy
++){
77 /* The sums are accumlated along the rotated rows of the grid, */
78 /* so initialize row sum to 0. */
80 /* Foreach column in block ... */
81 for(ix
= 0; ix
< blocksize
; ix
++){
82 /* Accumulate pixel value at rotated grid position in image */
83 rowsums
[iy
] += *(blkptr
+ grid_offsets
[gi
]);
89 /*************************************************************************
90 **************************************************************************
91 #cat: dft_power - Computes the DFT power by applying a specific wave form
92 #cat: frequency to a vector of pixel row sums computed from a
93 #cat: specific orientation of the block image
96 rowsums - accumulated rows of pixels from within a rotated grid
97 overlaying an input image block
98 wave - the wave form (cosine and sine components) at a specific
100 wavelen - the length of the wave form (must match the height of the
101 image block which is the length of the rowsum vector)
103 power - the computed DFT power for the given wave form at the
104 given orientation within the image block
105 **************************************************************************/
106 static void dft_power(double *power
, const int *rowsums
,
107 const DFTWAVE
*wave
, const int wavelen
)
110 double cospart
, sinpart
;
112 /* Initialize accumulators */
116 /* Accumulate cos and sin components of DFT. */
117 for(i
= 0; i
< wavelen
; i
++){
118 /* Multiply each rotated row sum by its */
119 /* corresponding cos or sin point in DFT wave. */
120 cospart
+= (rowsums
[i
] * wave
->cos
[i
]);
121 sinpart
+= (rowsums
[i
] * wave
->sin
[i
]);
124 /* Power is the sum of the squared cos and sin components */
125 *power
= (cospart
* cospart
) + (sinpart
* sinpart
);
128 /*************************************************************************
129 **************************************************************************
130 #cat: dft_dir_powers - Conducts the DFT analysis on a block of image data.
131 #cat: The image block is sampled across a range of orientations
132 #cat: (directions) and multiple wave forms of varying frequency are
133 #cat: applied at each orientation. At each orentation, pixels are
134 #cat: accumulated along each rotated pixel row, creating a vector
135 #cat: of pixel row sums. Each DFT wave form is then applied
136 #cat: individually to this vector of pixel row sums. A DFT power
137 #cat: value is computed for each wave form (frequency0 at each
138 #cat: orientaion within the image block. Therefore, the resulting DFT
139 #cat: power vectors are of dimension (N Waves X M Directions).
140 #cat: The power signatures derived form this process are used to
141 #cat: determine dominant direction flow within the image block.
144 pdata - the padded input image. It is important that the image
145 be properly padded, or else the sampling at various block
146 orientations may result in accessing unkown memory.
147 blkoffset - the pixel offset form the origin of the padded image to
148 the origin of the current block in the image
149 pw - the width (in pixels) of the padded input image
150 ph - the height (in pixels) of the padded input image
151 dftwaves - structure containing the DFT wave forms
152 dftgrids - structure containing the rotated pixel grid offsets
154 powers - DFT power computed from each wave form frequencies at each
155 orientation (direction) in the current image block
157 Zero - successful completion
158 Negative - system error
159 **************************************************************************/
160 int dft_dir_powers(double **powers
, unsigned char *pdata
,
161 const int blkoffset
, const int pw
, const int ph
,
162 const DFTWAVES
*dftwaves
, const ROTGRIDS
*dftgrids
)
166 unsigned char *blkptr
;
168 /* Allocate line sum vector, and initialize to zeros */
169 /* This routine requires square block (grid), so ERROR otherwise. */
170 if(dftgrids
->grid_w
!= dftgrids
->grid_h
){
171 fprintf(stderr
, "ERROR : dft_dir_powers : DFT grids must be square\n");
174 rowsums
= (int *)malloc(dftgrids
->grid_w
* sizeof(int));
175 if(rowsums
== (int *)NULL
){
176 fprintf(stderr
, "ERROR : dft_dir_powers : malloc : rowsums\n");
180 /* Foreach direction ... */
181 for(dir
= 0; dir
< dftgrids
->ngrids
; dir
++){
182 /* Compute vector of line sums from rotated grid */
183 blkptr
= pdata
+ blkoffset
;
184 sum_rot_block_rows(rowsums
, blkptr
,
185 dftgrids
->grids
[dir
], dftgrids
->grid_w
);
187 /* Foreach DFT wave ... */
188 for(w
= 0; w
< dftwaves
->nwaves
; w
++){
189 dft_power(&(powers
[w
][dir
]), rowsums
,
190 dftwaves
->waves
[w
], dftwaves
->wavelen
);
194 /* Deallocate working memory. */
200 /*************************************************************************
201 **************************************************************************
202 #cat: get_max_norm - Analyses a DFT power vector for a specific wave form
203 #cat: applied at different orientations (directions) to the
204 #cat: current image block. The routine retuns the maximum
205 #cat: power value in the vector, the direction at which the
206 #cat: maximum occurs, and a normalized power value. The
207 #cat: normalized power is computed as the maximum power divided
208 #cat: by the average power across all the directions. These
209 #cat: simple statistics are fundamental to the selection of
210 #cat: a dominant direction flow for the image block.
213 power_vector - the DFT power values derived form a specific wave form
214 applied at different directions
215 ndirs - the number of directions to which the wave form was applied
217 powmax - the maximum power value in the DFT power vector
218 powmax_dir - the direciton at which the maximum power value occured
219 pownorm - the normalized power corresponding to the maximum power
220 **************************************************************************/
221 static void get_max_norm(double *powmax
, int *powmax_dir
,
222 double *pownorm
, const double *power_vector
, const int ndirs
)
225 double max_v
, powsum
;
229 /* Find max power value and store corresponding direction */
230 max_v
= power_vector
[0];
233 /* Sum the total power in a block at a given direction */
234 powsum
= power_vector
[0];
236 /* For each direction ... */
237 for(dir
= 1; dir
< ndirs
; dir
++){
238 powsum
+= power_vector
[dir
];
239 if(power_vector
[dir
] > max_v
){
240 max_v
= power_vector
[dir
];
248 /* Powmean is used as denominator for pownorm, so setting */
249 /* a non-zero minimum avoids possible division by zero. */
250 powmean
= max(powsum
, MIN_POWER_SUM
)/(double)ndirs
;
252 *pownorm
= *powmax
/ powmean
;
255 /*************************************************************************
256 **************************************************************************
257 #cat: sort_dft_waves - Creates a ranked list of DFT wave form statistics
258 #cat: by sorting on the normalized squared maximum power.
261 powmaxs - maximum DFT power for each wave form used to derive
263 pownorms - normalized maximum power corresponding to values in powmaxs
264 nstats - number of wave forms used to derive statistics (N Wave - 1)
266 wis - sorted list of indices corresponding to the ranked set of
267 wave form statistics. These indices will be used as
268 indirect addresses when processing the power statistics
269 in descending order of "dominance"
271 Zero - successful completion
272 Negative - system error
273 **************************************************************************/
274 static int sort_dft_waves(int *wis
, const double *powmaxs
, const double *pownorms
,
280 /* Allocate normalized power^2 array */
281 pownorms2
= (double *)malloc(nstats
* sizeof(double));
282 if(pownorms2
== (double *)NULL
){
283 fprintf(stderr
, "ERROR : sort_dft_waves : malloc : pownorms2\n");
287 for(i
= 0; i
< nstats
; i
++){
288 /* Wis will hold the sorted statistic indices when all is done. */
290 /* This is normalized squared max power. */
291 pownorms2
[i
] = powmaxs
[i
] * pownorms
[i
];
294 /* Sort the statistic indices on the normalized squared power. */
295 bubble_sort_double_dec_2(pownorms2
, wis
, nstats
);
297 /* Deallocate the working memory. */
303 /*************************************************************************
304 **************************************************************************
305 #cat: dft_power_stats - Derives statistics from a set of DFT power vectors.
306 #cat: Statistics are computed for all but the lowest frequency
307 #cat: wave form, including the Maximum power for each wave form,
308 #cat: the direction at which the maximum power occured, and a
309 #cat: normalized value for the maximum power. In addition, the
310 #cat: statistics are ranked in descending order based on normalized
311 #cat: squared maximum power. These statistics are fundamental
312 #cat: to selecting a dominant direction flow for the current
313 #cat: input image block.
316 powers - DFT power vectors (N Waves X M Directions) computed for
317 the current image block from which the values in the
318 statistics arrays are derived
319 fw - the beginning of the range of wave form indices from which
320 the statistcs are to derived
321 tw - the ending of the range of wave form indices from which
322 the statistcs are to derived (last index is tw-1)
323 ndirs - number of orientations (directions) at which the DFT
324 analysis was conducted
326 wis - list of ranked wave form indicies of the corresponding
327 statistics based on normalized squared maximum power. These
328 indices will be used as indirect addresses when processing
329 the power statistics in descending order of "dominance"
330 powmaxs - array holding the maximum DFT power for each wave form
331 (other than the lowest frequecy)
332 powmax_dirs - array to holding the direction corresponding to
333 each maximum power value in powmaxs
334 pownorms - array to holding the normalized maximum powers corresponding
335 to each value in powmaxs
337 Zero - successful completion
338 Negative - system error
339 **************************************************************************/
340 int dft_power_stats(int *wis
, double *powmaxs
, int *powmax_dirs
,
341 double *pownorms
, double **powers
,
342 const int fw
, const int tw
, const int ndirs
)
345 int ret
; /* return code */
347 for(w
= fw
, i
= 0; w
< tw
; w
++, i
++){
348 get_max_norm(&(powmaxs
[i
]), &(powmax_dirs
[i
]),
349 &(pownorms
[i
]), powers
[w
], ndirs
);
352 /* Get sorted order of applied DFT waves based on normalized power */
353 if((ret
= sort_dft_waves(wis
, powmaxs
, pownorms
, tw
-fw
)))