#include <stdio.h>#include <malloc.h>#include <math.h>#include <stdint.h>#include <ppm.h>#include <gift_features.h>Go to the source code of this file.
Defines | |
| #define | square(x) ((x)*(x)) |
| #define | num_gabor_ranges 10 |
| #define | num_gabor_scales 3 |
| #define | num_gabors_per_scale 4 |
| #define | OLDFIXED 1 |
| #define | image_size 256 |
| #define | num_total_colour_blocks (256+64+16+4) |
| #define | smallest_colour_block 16 |
| #define | gabor_block_size 16 |
| #define | num_colour_scales 4 |
| #define | num_blocks_at_scale(i) (256>>i*2) |
| #define | gabor_ranges(i) (i+2+99989*(((i>>3)&1)&(i&1))) |
Functions | |
| void | init_feature_variables (uint32_t colmap_size, uint32_t **col_counts, uint32_t ***block_gabor_class, uint32_t ***gabor_histogram) |
| void | extract_gabor_features (PPM *im_hsv, uint32_t ***block_gabor_class, uint32_t ***gabor_histogram) |
| void | extract_mode_features (PPM *im, uint32_t *colmap, uint32_t colmap_size, uint32_t **col_counts, byte *block_mode, uint32_t *col_histogram) |
| enum ppm_error | write_mode_features (char *out_fname, uint32_t colmap_size, uint32_t *col_histogram, uint32_t ***block_gabor_class, uint32_t ***gabor_histogram, byte *block_mode) |
| void | fts2blocks (char *fts_fname, byte *block_mode, uint32_t *col_histogram) |
| enum ppm_error | write_feature_descriptions (FILE *out_file, int *colmap, int colmap_size) |
| #define gabor_block_size 16 |
Definition at line 79 of file extract_block_features.c.
Referenced by extract_gabor_features(), init_feature_variables(), write_feature_descriptions(), and write_mode_features().
| #define gabor_ranges | ( | i | ) | (i+2+99989*(((i>>3)&1)&(i&1))) |
Definition at line 98 of file extract_block_features.c.
Referenced by extract_gabor_features(), and write_feature_descriptions().
| #define image_size 256 |
Definition at line 71 of file extract_block_features.c.
Referenced by extract_mode_features(), fts2blocks(), init_feature_variables(), write_feature_descriptions(), and write_mode_features().
| #define num_blocks_at_scale | ( | i | ) | (256>>i*2) |
Definition at line 85 of file extract_block_features.c.
Referenced by init_feature_variables(), and write_feature_descriptions().
| #define num_colour_scales 4 |
Definition at line 84 of file extract_block_features.c.
Referenced by extract_mode_features(), fts2blocks(), init_feature_variables(), and write_feature_descriptions().
| #define num_gabor_ranges 10 |
Definition at line 56 of file extract_block_features.c.
Referenced by extract_gabor_features(), init_feature_variables(), write_feature_descriptions(), and write_mode_features().
| #define num_gabor_scales 3 |
Definition at line 61 of file extract_block_features.c.
Referenced by create_filter_kernels(), extract_gabor_features(), init_feature_variables(), main(), write_feature_descriptions(), and write_mode_features().
| #define num_gabors_per_scale 4 |
Definition at line 63 of file extract_block_features.c.
Referenced by create_filter_kernels(), extract_gabor_features(), gabor_filter(), init_feature_variables(), write_feature_descriptions(), and write_mode_features().
| #define num_total_colour_blocks (256+64+16+4) |
Definition at line 73 of file extract_block_features.c.
Referenced by fts2blocks(), main(), and write_mode_features().
| #define OLDFIXED 1 |
Definition at line 66 of file extract_block_features.c.
| #define smallest_colour_block 16 |
Definition at line 75 of file extract_block_features.c.
Referenced by extract_mode_features(), fts2blocks(), and write_feature_descriptions().
| #define square | ( | x | ) | ((x)*(x)) |
Definition at line 48 of file extract_block_features.c.
Referenced by extract_gabor_features(), extract_mode_features(), fts2blocks(), init_feature_variables(), write_feature_descriptions(), and write_mode_features().
| void extract_gabor_features | ( | PPM * | im_hsv, | |
| uint32_t *** | block_gabor_class, | |||
| uint32_t *** | gabor_histogram | |||
| ) |
Definition at line 126 of file extract_block_features.c.
References create_filter_kernels(), gabor_block_size, gabor_filter(), gabor_ranges, _PPM::height, MAX_HEIGHT, MAX_WIDTH, num_gabor_ranges, num_gabor_scales, num_gabors_per_scale, square, _PPM::value_plane_double_reversed, and _PPM::width.
Referenced by main().
00126 { 00127 00128 int i, j, x, y, k; 00129 int scale, orientation; 00130 int energy_class; 00131 PPM *value_plane; 00132 double *value_image_dbl, *filtered_image; 00133 double *conv; 00134 double *conv2; 00135 double gabor_mean; 00136 double * kernelsxy[num_gabor_scales*num_gabors_per_scale]; 00137 00138 /* for Gabor features, this is what I'm going to do: 00139 - Apply each of the 12 filters (3 scales, 4 orientations) to each 00140 pixel in the image. 00141 - Use 16x16 blocks only. 00142 - In each block find the rms energy of each filter. 00143 - quantize these into num_gabor_ranges levels, as specified in the 00144 "array" gabor_ranges[] 00145 */ 00146 00147 /* this is all created with one malloc, so that it can be cleared in one memset() call */ 00148 filtered_image = (double *)malloc(im_hsv->width*im_hsv->height*sizeof(double)*3); 00149 conv=&filtered_image[im_hsv->width*im_hsv->height]; 00150 conv2=&conv[im_hsv->width*im_hsv->height]; 00151 00152 create_filter_kernels(kernelsxy); 00153 00154 /* apply each filter to the image */ 00155 for (scale = 0; scale < num_gabor_scales; scale++) { 00156 for (orientation = 0; orientation < num_gabors_per_scale; orientation++) { 00157 00158 /* this clears conv, conv2, and filtered_image in one call. */ 00159 memset(filtered_image, 0, MAX_WIDTH*MAX_HEIGHT*sizeof(double)*3); 00160 00161 /* filter the image */ 00162 gabor_filter(im_hsv->value_plane_double_reversed, im_hsv->width, im_hsv->height, scale, orientation, kernelsxy, conv, conv2, filtered_image); 00163 00164 /* extract the rms energy for each block */ 00165 k = 0; /* block counter */ 00166 for (y = 0; y < im_hsv->height; y += gabor_block_size) { 00167 for (x = 0; x < im_hsv->width; x += gabor_block_size) { 00168 gabor_mean = 0; 00169 for (i = 0; (i < gabor_block_size) && (y+i < im_hsv->height); i++) { 00170 for (j = 0; (j < gabor_block_size) && (x+j < im_hsv->height); j++) { 00171 gabor_mean += square((filtered_image[(y + i)*im_hsv->width + (x + j)])); 00172 } 00173 } 00174 gabor_mean /= square(gabor_block_size); 00175 gabor_mean = sqrt(gabor_mean); 00176 00177 /* find the energy class for this block */ 00178 for (energy_class = 0; energy_class < num_gabor_ranges; energy_class++) { 00179 if (gabor_mean < gabor_ranges(energy_class)) 00180 break; 00181 } 00182 00183 /* store this class in the appropriate place */ 00184 block_gabor_class[scale][orientation][k] = energy_class; 00185 00186 /* increment the histogram entry for this combination */ 00187 gabor_histogram[scale][orientation][energy_class]++; 00188 00189 k++; /* increment block counter */ 00190 } 00191 } 00192 } 00193 } 00194 }
| void extract_mode_features | ( | PPM * | im, | |
| uint32_t * | colmap, | |||
| uint32_t | colmap_size, | |||
| uint32_t ** | col_counts, | |||
| byte * | block_mode, | |||
| uint32_t * | col_histogram | |||
| ) |
Definition at line 196 of file extract_block_features.c.
References _PPM::bytes_per_pixel, colmap2rgb_ppm(), destroy_ppm(), _PPM::height, hsv2rgb_ppm(), image_size, _PPM::max_col_comp, new_ppm(), num_colour_scales, PGM_RAW, _PPM::pixel, ppm_handle_error(), PPM_OK, PPM_RAW, smallest_colour_block, square, _PPM::type, _PPM::width, and write_ppm().
Referenced by main().
00196 { 00197 00198 int i, j, k, last_k, k1, m, n, r, x, y; 00199 byte colour; 00200 int scale, block_size, num_blocks, old_num_blocks; 00201 int max_count, mode_index; 00202 int b1, b2, b3, b4; 00203 #ifdef GENERATE_BLOCK_IMAGES 00204 PPM *out_image, *out_image_hsv, *out_image_rgb; 00205 enum ppm_error the_error; 00206 FILE *outfile; 00207 char out_fname[256]; 00208 #endif 00209 00210 #ifdef GENERATE_BLOCK_IMAGES 00211 /* make space for an HSV image of the same size as that read */ 00212 out_image = new_ppm(); 00213 out_image->type = PGM_RAW; 00214 out_image->width = im->width; 00215 out_image->height = im->height; 00216 out_image->max_col_comp = im->max_col_comp; 00217 out_image->bytes_per_pixel = 1; 00218 out_image->pixel = (byte *)malloc(out_image->width*out_image->height*sizeof(byte)); 00219 #endif 00220 00221 /* first extract the lowest level blocks, directly from the pixels of 00222 the PGM image */ 00223 scale = 0; 00224 block_size = smallest_colour_block; 00225 num_blocks = square(image_size/block_size); 00226 k = last_k = 0; 00227 for (y = 0; y < im->height; y += block_size) { 00228 for (x = 0; x < im->width; x += block_size) { 00229 for (n = 0; n < colmap_size; n++) { 00230 col_counts[k][n] = 0; 00231 } 00232 for (i = 0; (i < block_size) && (y+i < im->height); i++) { 00233 for (j = 0; (j < block_size) && (x+j < im->width); j++) { 00234 colour = im->pixel[(y + j)*im->width + (x + i)]; 00235 col_counts[k][colour]++; 00236 } 00237 } 00238 00239 /* find the mode */ 00240 max_count = mode_index = 0; 00241 for (n = 0; n < colmap_size; n++) { 00242 if (col_counts[k][n] > max_count) { 00243 max_count = col_counts[k][n]; 00244 mode_index = n; 00245 } 00246 } 00247 block_mode[k] = mode_index; 00248 k++; 00249 } 00250 } 00251 00252 #ifdef GENERATE_BLOCK_IMAGES 00253 /* generate an image with this */ 00254 k1 = 0; 00255 for (y = 0; y < im->height; y += block_size) { 00256 for (x = 0; x < im->width; x += block_size) { 00257 for (i = 0; i < block_size; i++) { 00258 for (j = 0; j < block_size; j++) { 00259 out_image->pixel[(y + j)*im->width + (x + i)] = block_mode[k1]; 00260 } 00261 } 00262 k1++; 00263 } 00264 } 00265 /* convert from the colour map to an HSV image */ 00266 if ((the_error = colmap2rgb_ppm(out_image, colmap, colmap_size, &out_image_hsv)) != PPM_OK) { 00267 ppm_handle_error(the_error); 00268 exit(1); 00269 } 00270 /* convert to RGB */ 00271 if ((the_error = hsv2rgb_ppm(out_image_hsv, &out_image_rgb)) != PPM_OK) { 00272 ppm_handle_error(the_error); 00273 exit(1); 00274 } 00275 /* write it */ 00276 sprintf(out_fname, "blocks_%dx%d.ppm", block_size, block_size); 00277 outfile = fopen(out_fname, "wb"); 00278 if ((the_error = write_ppm(outfile, out_image_rgb, PPM_RAW)) != PPM_OK) { 00279 ppm_handle_error(the_error); 00280 exit(1); 00281 } 00282 fclose(outfile); 00283 destroy_ppm(&out_image_rgb); 00284 destroy_ppm(&out_image_hsv); 00285 #endif 00286 00287 00288 /* now do the other scales */ 00289 for (scale = 1; scale < num_colour_scales; scale++) { 00290 block_size *= 2; 00291 num_blocks /= 4; 00292 r = (int)sqrt((double)num_blocks); 00293 for (i = 0; i < num_blocks; i++) { 00294 m = (i/r)*2*r; /* note: this first is *integer* division */ 00295 b1 = last_k + 2*i + m; 00296 b2 = last_k + 2*i + m + 1; 00297 b3 = last_k + 2*i + m + 2*r; 00298 b4 = last_k + 2*i + m + 2*r + 1; 00299 max_count = mode_index = 0; 00300 for (n = 0; n < colmap_size; n++) { 00301 col_counts[k + i][n] = 00302 col_counts[b1][n] + col_counts[b2][n] + 00303 col_counts[b3][n] + col_counts[b4][n]; 00304 if (col_counts[k + i][n] > max_count) { 00305 max_count = col_counts[k + i][n]; 00306 mode_index = n; 00307 } 00308 } 00309 block_mode[k + i] = mode_index; 00310 } 00311 #ifdef GENERATE_BLOCK_IMAGES 00312 /* generate an image with this */ 00313 for (y = 0; y < im->height; y += block_size) { 00314 for (x = 0; x < im->width; x += block_size) { 00315 for (i = 0; i < block_size; i++) { 00316 for (j = 0; j < block_size; j++) { 00317 out_image->pixel[(y + j)*im->width + (x + i)] = block_mode[k1]; 00318 } 00319 } 00320 k1++; 00321 } 00322 } 00323 /* convert from the colour map to an HSV image */ 00324 if ((the_error = colmap2rgb_ppm(out_image, colmap, colmap_size, &out_image_hsv)) != PPM_OK) { 00325 ppm_handle_error(the_error); 00326 exit(1); 00327 } 00328 /* convert to RGB */ 00329 if ((the_error = hsv2rgb_ppm(out_image_hsv, &out_image_rgb)) != PPM_OK) { 00330 ppm_handle_error(the_error); 00331 exit(1); 00332 } 00333 /* write it */ 00334 sprintf(out_fname, "blocks_%dx%d.ppm", block_size, block_size); 00335 outfile = fopen(out_fname, "wb"); 00336 if ((the_error = write_ppm(outfile, out_image_rgb, PPM_RAW)) != PPM_OK) { 00337 ppm_handle_error(the_error); 00338 exit(1); 00339 } 00340 fclose(outfile); 00341 destroy_ppm(&out_image_rgb); 00342 destroy_ppm(&out_image_hsv); 00343 #endif 00344 last_k = k; 00345 k += num_blocks; 00346 } 00347 00348 /* now finally consolidate all the colour counts to produce the 00349 histogram for the whole image */ 00350 k -= num_blocks; 00351 for (n = 0; n < colmap_size; n++) 00352 col_histogram[n] = 00353 col_counts[k][n] + col_counts[k + 1][n] + 00354 col_counts[k + 2][n] + col_counts[k + 3][n]; 00355 }
| void fts2blocks | ( | char * | fts_fname, | |
| byte * | block_mode, | |||
| uint32_t * | col_histogram | |||
| ) |
Definition at line 532 of file extract_block_features.c.
References _PPM::bytes_per_pixel, colmap2rgb_ppm(), destroy_ppm(), _PPM::height, hsv2rgb_ppm(), hsv_quantize_ppm(), _FEATURE_DATA::id, image_size, _PPM::max_col_comp, new_ppm(), num_colour_scales, num_total_colour_blocks, _PPM::pixel, ppm_handle_error(), PPM_OK, PPM_RAW, smallest_colour_block, square, _PPM::type, _PPM::width, and write_ppm().
Referenced by main().
00532 { 00533 00534 FILE *fts_file, *outfile; 00535 int num_features, feature_index; 00536 FEATURE_DATA *feature; 00537 int block_features_offset; 00538 int block_size, num_blocks, scale; 00539 int *colmap; 00540 int colmap_size = 18*3*3 + 4; 00541 int x, y, i, j, k; 00542 PPM *hsv_image, *qimage, *rgb_image; 00543 enum ppm_error the_error; 00544 char out_fname[256]; 00545 00546 /* read the number of features */ 00547 fts_file = fopen(fts_fname, "rb"); 00548 fread(&num_features, sizeof(int), 1, fts_file); 00549 00550 /* allocate space for the features */ 00551 feature = (FEATURE_DATA *)malloc(num_features*sizeof(FEATURE_DATA)); 00552 00553 /* read the features */ 00554 fread(feature, sizeof(FEATURE_DATA), num_features, fts_file); 00555 00556 fclose(fts_file); 00557 00558 /* "unpack" the features in the array */ 00559 feature_index = 0; 00560 00561 /* block features */ 00562 for (i = 0; i < num_total_colour_blocks; i++) { 00563 /* note that each block can have colmap_size values */ 00564 block_mode[i] = feature[feature_index].id - i*colmap_size; 00565 feature_index++; 00566 } 00567 block_features_offset = num_total_colour_blocks*colmap_size; 00568 00569 /* colour histogram features */ 00570 for (i = 0; i < colmap_size; i++) 00571 col_histogram[i] = 0; 00572 00573 for (; feature_index < num_features; feature_index++) { 00574 i = feature[feature_index].id - block_features_offset; 00575 col_histogram[i] = (byte)(feature[feature_index].frequency); 00576 } 00577 00578 /* make a dummy image so that we can generate a colour map */ 00579 hsv_image = new_ppm(); 00580 hsv_image->type = PPM_RAW; 00581 hsv_image->width = 256; 00582 hsv_image->height = 256; 00583 hsv_image->max_col_comp = 255; 00584 hsv_image->bytes_per_pixel = 3; 00585 hsv_image->pixel = (byte *)malloc(3*256*256*sizeof(byte)); 00586 hsv_quantize_ppm(hsv_image, &qimage, &colmap, 18, 3, 3, 4); 00587 destroy_ppm(&hsv_image); 00588 00589 /* now write the block images */ 00590 k = 0; 00591 block_size = smallest_colour_block; 00592 num_blocks = square(image_size/block_size); 00593 for (scale = 0; scale < num_colour_scales; scale++) { 00594 for (y = 0; y < 256; y += block_size) { 00595 for (x = 0; x < 256; x += block_size) { 00596 for (i = 0; i < block_size; i++) { 00597 for (j = 0; j < block_size; j++) { 00598 qimage->pixel[(y + j)*256 + (x + i)] = block_mode[k]; 00599 } 00600 } 00601 k++; 00602 } 00603 } 00604 /* convert from the colour map to an HSV image */ 00605 if ((the_error = colmap2rgb_ppm(qimage, colmap, colmap_size, &hsv_image)) != PPM_OK) { 00606 ppm_handle_error(the_error); 00607 exit(1); 00608 } 00609 /* convert to RGB */ 00610 if ((the_error = hsv2rgb_ppm(hsv_image, &rgb_image)) != PPM_OK) { 00611 ppm_handle_error(the_error); 00612 exit(1); 00613 } 00614 /* write it */ 00615 sprintf(out_fname, "fts2blocks_%dx%d.ppm", block_size, block_size); 00616 outfile = fopen(out_fname, "wb"); 00617 if ((the_error = write_ppm(outfile, rgb_image, PPM_RAW)) != PPM_OK) { 00618 ppm_handle_error(the_error); 00619 exit(1); 00620 } 00621 fclose(outfile); 00622 destroy_ppm(&hsv_image); 00623 destroy_ppm(&rgb_image); 00624 block_size *= 2; 00625 num_blocks /= 4; 00626 } 00627 }
| void init_feature_variables | ( | uint32_t | colmap_size, | |
| uint32_t ** | col_counts, | |||
| uint32_t *** | block_gabor_class, | |||
| uint32_t *** | gabor_histogram | |||
| ) |
Definition at line 105 of file extract_block_features.c.
References gabor_block_size, image_size, num_blocks_at_scale, num_colour_scales, num_gabor_ranges, num_gabor_scales, num_gabors_per_scale, and square.
Referenced by main().
00105 { 00106 00107 uint32_t i, j, k=0; 00108 /* colour features */ 00109 for (i = 0; i < num_colour_scales; i++) { 00110 for (j = 0; j < num_blocks_at_scale(i); j++) { 00111 col_counts[k++] = (uint32_t *)malloc(colmap_size*sizeof(uint32_t)); 00112 } 00113 } 00114 00115 /* Gabor features */ 00116 for (i = 0; i < num_gabor_scales; i++) { 00117 block_gabor_class[i] = (uint32_t **)malloc(num_gabors_per_scale*sizeof(uint32_t *)); 00118 gabor_histogram[i] = (uint32_t **)malloc(num_gabors_per_scale*sizeof(uint32_t *)); 00119 for (j = 0; j < num_gabors_per_scale; j++) { 00120 block_gabor_class[i][j] = (uint32_t *)malloc(square(image_size/gabor_block_size)*sizeof(uint32_t)); 00121 gabor_histogram[i][j] = (uint32_t *)calloc(num_gabor_ranges, sizeof(uint32_t)); 00122 } 00123 } 00124 }
| enum ppm_error write_feature_descriptions | ( | FILE * | out_file, | |
| int * | colmap, | |||
| int | colmap_size | |||
| ) |
Definition at line 629 of file extract_block_features.c.
References COL_HST, COL_POS, gabor_block_size, GABOR_HST, GABOR_POS, gabor_ranges, HUE, image_size, num_blocks_at_scale, num_colour_scales, num_gabor_ranges, num_gabor_scales, num_gabors_per_scale, PPM_OK, SATURATION, smallest_colour_block, square, and VALUE.
Referenced by main().
00629 { 00630 00631 int feature_index = 0; 00632 int block_size; 00633 int i, j, k; 00634 int scale, orientation; 00635 00636 /* block features */ 00637 block_size = smallest_colour_block; 00638 for (i = 0; i < num_colour_scales; i++) { 00639 for (j = 0; j < num_blocks_at_scale(i); j++) { 00640 for (k = 0; k < colmap_size; k++) { 00641 fprintf(out_file, "%d %d COL_POS block size = %dx%d position = %d H,S,V = %d, %d, %d\n", feature_index, COL_POS, block_size, block_size, j, colmap[3*k + HUE], colmap[3*k + SATURATION], colmap[3*k + VALUE]); 00642 feature_index++; 00643 } 00644 } 00645 block_size *= 2; 00646 } 00647 00648 /* colour histogram features */ 00649 for (i = 0; i < colmap_size; i++) { 00650 fprintf(out_file, "%d %d COL_HST H,S,V = %d, %d, %d\n", feature_index, COL_HST, colmap[3*i + HUE], colmap[3*i + SATURATION], colmap[3*i + VALUE]); 00651 feature_index++; 00652 } 00653 00654 /* gabor block features */ 00655 for (scale = 0; scale < num_gabor_scales; scale++) { 00656 for (orientation = 0; orientation < num_gabors_per_scale; orientation++) { 00657 /* blocks */ 00658 for (i = 0; i < square((image_size/gabor_block_size)); i++) { 00659 for (j = 0; j < num_gabor_ranges; j++) { 00660 #if num_gabor_ranges==16 /* technically, we should be checking the type.. */ 00661 fprintf(out_file, "%d %d GABOR_POS block size = %dx%d position = %d SCALE, ORIENTATION, ENERGY = %d, %d, %f\n", feature_index, GABOR_POS, gabor_block_size, gabor_block_size, i, scale, orientation, gabor_ranges(j)); 00662 #else 00663 #if num_gabor_ranges==10 00664 fprintf(out_file, "%d %d GABOR_POS block size = %dx%d position = %d SCALE, ORIENTATION, ENERGY = %d, %d, %d.000000\n", feature_index, GABOR_POS, gabor_block_size, gabor_block_size, i, scale, orientation, gabor_ranges(j)); 00665 #endif 00666 #endif 00667 feature_index++; 00668 } 00669 } 00670 } 00671 } 00672 00673 /* gabor histogram features */ 00674 for (scale = 0; scale < num_gabor_scales; scale++) { 00675 for (orientation = 0; orientation < num_gabors_per_scale; orientation++) { 00676 for (j = 0; j < num_gabor_ranges; j++) { 00677 fprintf(out_file, "%d %d GABOR_HST SCALE, ORIENTATION, ENERGY UPPER BOUND = %d, %d, %f\n", feature_index, GABOR_HST, scale, orientation, j); 00678 feature_index++; 00679 } 00680 } 00681 } 00682 00683 /* everything is OK if we got this far */ 00684 return(PPM_OK); 00685 }
| enum ppm_error write_mode_features | ( | char * | out_fname, | |
| uint32_t | colmap_size, | |||
| uint32_t * | col_histogram, | |||
| uint32_t *** | block_gabor_class, | |||
| uint32_t *** | gabor_histogram, | |||
| byte * | block_mode | |||
| ) |
HACK: convert all this features to floats.
WARNING: we write here floats into an integer field of a structure
Why is this necessary? The original version rounds at many places So we cannot just set FREQ_MAX=1. (WM)
Definition at line 357 of file extract_block_features.c.
References FILE_CLOSE_ERROR, FILE_OPEN_ERROR, FILE_WRITE_ERROR, FREQ_MAX, _FEATURE_DATA::frequency, gabor_block_size, _FEATURE_DATA::id, image_size, num_gabor_ranges, num_gabor_scales, num_gabors_per_scale, num_total_colour_blocks, PPM_OK, and square.
Referenced by main().
00357 { 00358 00359 FILE *out_file = NULL; 00360 int feature_index; 00361 int block_features_offset; 00362 int scale, orientation, energy_class; 00363 int num_features; 00364 FEATURE_DATA *feature; 00365 int i; 00366 00367 /***** count the features *****/ 00368 00369 /* we know that there will be a mode color for each block */ 00370 num_features = num_total_colour_blocks; 00371 00372 /* and there will be one for each non-zero histogram entry. Convert 00373 histogram entries to range [0, FREQ_MAX] while we're at it */ 00374 for (i = 0; i < colmap_size; i++) { 00375 col_histogram[i] = (int)(rint(FREQ_MAX*(double)col_histogram[i]/(double)(square(image_size)))); 00376 if (col_histogram[i] != 0) 00377 num_features++; 00378 } 00379 00380 #ifdef NO_FLAT_FEATURES 00381 /* count the block entries which are not of class zero (which indicates 00382 a filter response too low to write), and the non-zero gabor histogram 00383 entries */ 00384 for (scale = 0; scale < num_gabor_scales; scale++) { 00385 for (orientation = 0; orientation < num_gabors_per_scale; orientation++) { 00386 /* blocks */ 00387 for (i = 0; i < square((image_size/gabor_block_size)); i++) { 00388 if (block_gabor_class[scale][orientation][i] != 0) 00389 num_features++; 00390 } 00391 00392 /* histogram */ 00393 for (energy_class = 0; energy_class < num_gabor_ranges; energy_class++) { 00394 if (gabor_histogram[scale][orientation][energy_class] != 0) 00395 num_features++; 00396 } 00397 } 00398 } 00399 #else 00400 /* here we ARE storing features for filter responses in the lowest 00401 * energy band, so the number of block features is fixed (and v. 00402 * large!). We also count the non-zero gabor histogram entries */ 00403 00404 /* blocks */ 00405 num_features += num_gabor_scales*num_gabors_per_scale*square((image_size/gabor_block_size)); 00406 00407 /* histogram */ 00408 for (scale = 0; scale < num_gabor_scales; scale++) { 00409 for (orientation = 0; orientation < num_gabors_per_scale; orientation++) { 00410 for (energy_class = 0; energy_class < num_gabor_ranges; energy_class++) { 00411 if (gabor_histogram[scale][orientation][energy_class] != 0) 00412 num_features++; 00413 } 00414 } 00415 } 00416 #endif 00417 00418 #ifdef DEBUG 00419 fprintf(stderr, "Image contains %d features.\n", num_features); 00420 #endif 00421 00422 /* allocate space to store the features */ 00423 feature = (FEATURE_DATA *)malloc(num_features*sizeof(FEATURE_DATA)); 00424 00425 /***** store the features in the array *****/ 00426 feature_index = 0; 00427 00428 /* colour block features */ 00429 for (i = 0; i < num_total_colour_blocks; i++) { 00430 /* note that each block can have colmap_size values */ 00431 feature[feature_index].id = i*colmap_size + (int)block_mode[i]; 00432 feature[feature_index].frequency = FREQ_MAX; /* binary features */ 00433 feature_index++; 00434 } 00435 block_features_offset = num_total_colour_blocks*colmap_size; 00436 00437 /* colour histogram features */ 00438 for (i = 0; i < colmap_size; i++) { 00439 if (col_histogram[i] != 0) { 00440 feature[feature_index].id = block_features_offset + i; 00441 feature[feature_index].frequency = (freq_type)col_histogram[i]; 00442 feature_index++; 00443 } 00444 } 00445 block_features_offset += colmap_size; 00446 00447 /* gabor block features */ 00448 for (scale = 0; scale < num_gabor_scales; scale++) { 00449 for (orientation = 0; orientation < num_gabors_per_scale; orientation++) { 00450 /* blocks */ 00451 for (i = 0; i < square((image_size/gabor_block_size)); i++) { 00452 #ifdef NO_FLAT_FEATURES 00453 if (block_gabor_class[scale][orientation][i] != 0) { 00454 feature[feature_index].id = block_features_offset + block_gabor_class[scale][orientation][i]; 00455 feature[feature_index].frequency = FREQ_MAX; 00456 feature_index++; 00457 } 00458 #else 00459 feature[feature_index].id = block_features_offset + block_gabor_class[scale][orientation][i]; 00460 feature[feature_index].frequency = FREQ_MAX; 00461 feature_index++; 00462 #endif 00463 block_features_offset += num_gabor_ranges; 00464 } 00465 } 00466 } 00467 00468 /* gabor histogram features */ 00469 for (scale = 0; scale < num_gabor_scales; scale++) { 00470 for (orientation = 0; orientation < num_gabors_per_scale; orientation++) { 00471 for (energy_class = 0; energy_class < num_gabor_ranges; energy_class++) { 00472 if (gabor_histogram[scale][orientation][energy_class] != 0) { 00473 feature[feature_index].id = block_features_offset; 00474 feature[feature_index].frequency = (freq_type)rint(FREQ_MAX*(double)gabor_histogram[scale][orientation][energy_class]/(double)square((image_size/gabor_block_size))); 00475 feature_index++; 00476 } 00477 block_features_offset++; 00478 } 00479 } 00480 } 00481 00482 #ifdef DEBUG 00483 fprintf(stderr, "%d features found.\n", feature_index); 00484 fprintf(stderr, "block_features_offset = %d.\n", block_features_offset); 00485 #endif 00486 00487 00488 /***** now write the file *****/ 00489 00490 /* open it */ 00491 if ((out_file = fopen(out_fname, "wb")) == NULL) { 00492 fprintf(stderr, "Error opening file %s for writing.\n\n", out_fname); 00493 return(FILE_OPEN_ERROR); 00494 } 00495 00496 /* write the number of features */ 00497 if (fwrite(&num_features, sizeof(int), 1, out_file) != 1) { 00498 fprintf(stderr, "Error writing file %s.\n\n", out_fname); 00499 return(FILE_WRITE_ERROR); 00500 } 00501 00511 for(i=0; 00512 i<num_features; 00513 i++){ 00514 *((float*)&(feature[i].frequency))=((float)feature[i].frequency/(float)FREQ_MAX);//(WM HACK) 00515 }; 00516 00517 /* write the features, as a block */ 00518 if (fwrite(feature, sizeof(FEATURE_DATA), num_features, out_file) != num_features) { 00519 fprintf(stderr, "Error writing file %s.\n\n", out_fname); 00520 return(FILE_WRITE_ERROR); 00521 } 00522 00523 if (fclose(out_file) == EOF) { 00524 fprintf(stderr, "Error closing file %s.\n\n", out_fname); 00525 return(FILE_CLOSE_ERROR); 00526 } 00527 00528 /* everything is OK if we got this far */ 00529 return(PPM_OK); 00530 }
1.5.6