Changeset 215

Show
Ignore:
Timestamp:
03/31/06 13:24:05 (3 years ago)
Author:
goodea
Message:

checking in Dhiraj's stuff for face detector, he doesn't yet have an account

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/projects/viola-jones/Makefile

    r160 r215  
    1212 
    1313# the name of this project 
    14 PROJECT=hello_world 
     14PROJECT=viola-jones 
    1515 
    1616 
  • trunk/projects/viola-jones/main.c

    r161 r215  
    77#include <cc3.h> 
    88#include <cc3_ilp.h> 
    9  
    10  
    11 /* simple hello world, showing features and compiling*/ 
     9#include "main.h" 
     10 
     11 
     12/* ---global variables----*/ 
     13 
     14// kind of buffer to get the image rows from fifo to compute integral image 
     15cc3_image_t cc3_img_tmp; 
     16 
     17// keep track of detected faces 
     18uint8_t cc3_num_detected_faces = 0; 
     19 
     20// row counter in the integral image to denote the current "top row" 
     21// i.e. the row for which the sub-windows are being evaluated for features 
     22uint8_t cc3_row_counter_ii; 
     23 
     24// row counter in the actual but cropped image (i.e. with top & bottom offset) 
     25uint8_t cc3_row_counter_cropped_img; 
     26 
     27// row counter in the actual full image 
     28uint16_t cc3_row_counter_actual_img;   
     29 
     30// integral image counter (for many rows, integral image has been calculated) 
     31uint16_t cc3_row_counter_calc_ii; 
     32 
     33uint32_t mean_val;       // mean for a subwinow 
     34uint64_t sum_pix;        // sum of pixels in a sub-window 
     35uint64_t sum_pix_sq; // sum of squares of pixels in a subwindow 
     36uint32_t std;        // standard deviation 
     37uint64_t var;        // variance 
     38 
     39// array to store rows while transfering b/w fifo and ii 
     40static uint8_t image_row[176*3]; 
     41 
     42 
     43FILE* fp; 
     44 
     45// function to get the current segment from the actual image 
     46void cc3_get_curr_segment() 
     47
     48  cc3_pixel_t pix_temp; 
     49   
     50 
     51  if (cc3_row_counter_cropped_img == 0)  // first time 
     52    { 
     53      // load the upper "CC3_INTEGRAL_IMG_HEIGHT" rows 
     54      for (uint8_t i = 0; i < CC3_INTEGRAL_IMG_HEIGHT; i++) 
     55        { 
     56          // get a row.. 
     57          cc3_pixbuf_read_rows(cc3_img_tmp.pix, cc3_img_tmp.width, cc3_img_tmp.height); 
     58           
     59          // copy the first pixel 
     60          cc3_get_pixel(&cc3_img_tmp, 0, 0, &pix_temp); 
     61          cc3_integral_image[i][0] = pix_temp.channel[1]; // only green channel 
     62          //      cc3_integral_image[i][0] = (3*pix_temp.channel[0]+6*pix_temp.channel[1]+pix_temp.channel[2])/10; // rgb->gray  
     63 
     64          printf("writing to file %u \n\r", i); 
     65          fprintf(fp, "%d ", cc3_integral_image[i][0]); 
     66          printf("wrot to file %u \n\r", i); 
     67           
     68          // start copying from the next pixel and calculate cumulative sum at the same time 
     69          for (uint16_t j = 1; j < cc3_img_tmp.width; j++) 
     70            { 
     71              cc3_get_pixel(&cc3_img_tmp, j, 0, &pix_temp); 
     72              cc3_integral_image[i][j] = pix_temp.channel[1]; // only green channel 
     73              //  cc3_integral_image[i][j] = (3*pix_temp.channel[0]+6*pix_temp.channel[1]+pix_temp.channel[2])/10; // rgb->gray  
     74              fprintf( fp,"%d ",cc3_integral_image[i][j] ); 
     75               
     76              // compute cumulative sum across the row 
     77              cc3_integral_image[i][j] += cc3_integral_image[i][j-1]; 
     78            } 
     79          fprintf( fp, "\n" ); 
     80        } 
     81       
     82      // find cumulative sum along columns to complete the integral image computation 
     83      for (uint16_t j = 0; j < CC3_INTEGRAL_IMG_WIDTH; j++) 
     84         { 
     85           for (uint16_t i = 1; i < CC3_INTEGRAL_IMG_HEIGHT; i++)  // start from second row 
     86             { 
     87               cc3_integral_image[i][j]+=cc3_integral_image[i-1][j]; 
     88             } 
     89         } 
     90 
     91 
     92      // printf the integral image 
     93      for (uint16_t j = 0; j < CC3_INTEGRAL_IMG_HEIGHT; j++) 
     94        { 
     95           for (uint16_t i = 0; i < CC3_INTEGRAL_IMG_WIDTH; i++) 
     96             { 
     97               //              printf("%ld ", cc3_integral_image[j][i] ); 
     98             } 
     99           //      printf("\n\r"); 
     100        } 
     101          
     102    } 
     103   
     104  else  
     105    {  
     106      // get a new row 
     107      cc3_pixbuf_read_rows(cc3_img_tmp.pix, cc3_img_tmp.width, cc3_img_tmp.height); 
     108           
     109      uint8_t newly_added_row = cc3_row_counter_calc_ii % CC3_INTEGRAL_IMG_HEIGHT; 
     110      uint8_t prev_row = (cc3_row_counter_calc_ii - 1 + CC3_INTEGRAL_IMG_HEIGHT) % CC3_INTEGRAL_IMG_HEIGHT;  
     111        
     112      // copy the first pixel 
     113      cc3_get_pixel(&cc3_img_tmp, 0, 0, &pix_temp); 
     114      cc3_integral_image[newly_added_row][0] = pix_temp.channel[1]; 
     115      //      cc3_integral_image[newly_added_row][0] = (3*pix_temp.channel[0]+6*pix_temp.channel[1]+pix_temp.channel[2])/10; // rgb->gray  
     116      fprintf( fp,"%d ",cc3_integral_image[newly_added_row][0] ); 
     117       
     118      // read the row, from next pixel onward and compute cum sum across the row 
     119      for (uint16_t j = 1; j < cc3_img_tmp.width; j++) 
     120        { 
     121          cc3_get_pixel(&cc3_img_tmp, j, 0, &pix_temp); 
     122          cc3_integral_image[newly_added_row][j] = pix_temp.channel[1]; 
     123          //      cc3_integral_image[newly_added_row][j] = (3*pix_temp.channel[0] + 6*pix_temp.channel[1] + pix_temp.channel[2])/10; 
     124          fprintf( fp,"%d ",cc3_integral_image[newly_added_row][j] ); 
     125 
     126          // compute cumulative sum across the row 
     127          cc3_integral_image[newly_added_row][j] += cc3_integral_image[newly_added_row][j-1]; 
     128        } 
     129       fprintf( fp, "\n" ); 
     130 
     131       printf("%s %d \n\r", "New Row...", cc3_row_counter_calc_ii); 
     132       // find cumulative sum along columns to complete the integral image computation 
     133       for (uint16_t j = 0; j < CC3_INTEGRAL_IMG_WIDTH; j++) 
     134         { 
     135           cc3_integral_image[newly_added_row][j]+=cc3_integral_image[prev_row][j]; 
     136           //   printf("%ld ", cc3_integral_image[newly_added_row][j] ); 
     137         } 
     138       //            printf("\n\r"); 
     139       
     140    } 
     141
     142 
     143 
     144 
     145/*  
     146 * function to get the feature value for a particular sub-window 
     147 * 
     148 */ 
     149int16_t cc3_get_feat_val(uint8_t feat_num, uint8_t curr_scale, uint16_t x, uint16_t y) 
     150
     151  int32_t fval = 0; 
     152  uint16_t x_in_ii, y_in_ii; 
     153 
     154  // evaluate the subwindow for this feature 
     155  for (uint8_t pt=0; pt < 9 ; pt++) 
     156    { 
     157      x_in_ii = x + CC3_FACE_FEATURES[feat_num][curr_scale].x[pt]; 
     158      y_in_ii = (y + CC3_FACE_FEATURES[feat_num][curr_scale].y[pt]) % CC3_INTEGRAL_IMG_HEIGHT; // circular warping 
     159      fval+=cc3_integral_image[y_in_ii][x_in_ii]*CC3_FACE_FEATURES[feat_num][curr_scale].val_at_corners[pt]; 
     160    } 
     161 
     162  // taking into account the effect of normalization 
     163  //  printf("%s %d", "fval before std", fval); 
     164  fval = fval/((int32_t)std); 
     165  //  printf("%s %d", "fval after std", fval); 
     166 
     167  // check if fval < threshold 
     168  if (fval*CC3_FACE_FEATURES[feat_num][curr_scale].parity < CC3_FACE_FEATURES[feat_num][curr_scale].thresh*CC3_FACE_FEATURES[feat_num][curr_scale].parity) 
     169    return CC3_FACE_FEATURES[feat_num][curr_scale].alpha; 
     170  else  
     171    return 0; 
     172
     173 
     174 
     175/*-------------- main starts from here---------------*/ 
    12176int main (void) 
    13177{ 
    14     uint32_t start_time,val; 
    15     char c; 
    16     FILE *fp; 
    17     cc3_image_t img; 
    18  
     178 
     179  int16_t val;  
     180// don't know why its here...just dont feel like removing it...has been the sole variable that has stood the test of time...:-) 
     181// i feel bonded .... 
     182 
     183  // feature value for a particular sudwindow 
     184  // int16_t feat_val; 
     185 
     186   uint8_t x2, y2; // lowe right sub-window coordinates 
     187   uint64_t num_pixels; // no. of pixels in a subwindow 
     188 
     189   int32_t temp1, temp2; // temp variables used for computations 
     190   
    19191    // setup system     
    20192    cc3_system_setup (); 
     
    22194    // configure uarts 
    23195    cc3_uart_init (0, CC3_UART_RATE_115200,CC3_UART_MODE_8N1,CC3_UART_BINMODE_BINARY); 
    24     // Make it so that stdout and stdin are not buffered 
    25     val=setvbuf(stdout, NULL, _IONBF, 0 ); 
    26     val=setvbuf(stdin, NULL, _IONBF, 0 ); 
    27      
     196    
    28197    cc3_camera_init (); 
    29     
     198  
    30199    cc3_set_colorspace(CC3_RGB); 
    31200    cc3_set_resolution(CC3_LOW_RES); 
    32201    cc3_set_auto_white_balance(true); 
    33202    cc3_set_auto_exposure(true); 
    34     
    35203      
    36     printf("Hello World...\n"); 
     204    printf("Face Detector...\n\r"); 
    37205     
    38206    cc3_clr_led (0); 
     
    44212    cc3_set_led (0); 
    45213 
    46  
    47     // sample showing how to write to the MMC card 
    48     printf( "Type y to test MMC card, type n if you do not have the card\n" ); 
    49     c=getchar(); 
    50     if(c=='y' || c=='Y' ) 
    51     {  
    52         printf("\nMMC test...\n"); 
    53         fp = fopen("c:/test.txt", "w"); 
    54         fprintf( fp, "This will be written to the MMC...\n" );  
    55         fclose(fp); 
    56         printf( "A string was written to test.txt on the mmc card.\n" ); 
    57     } 
    58  
    59     // sample showing how to read button 
    60     printf("push button on camera back to continue\n"); 
    61     start_time=cc3_timer(); 
    62     while(!cc3_read_button()); 
    63     cc3_set_led(1); 
    64     // sample showing how to use timer 
    65     printf( "It took you %dms to press the button\n",cc3_timer()-start_time ); 
    66     
    67  
    68  
    69     // setup an image structure 
    70     img.channels=3; 
    71     img.width=cc3_g_current_frame.width; 
    72     img.height=1;  // image will hold just 1 row for scanline processing 
    73     img.pix = malloc(3 * img.width);  // malloc! 
    74    
    75     printf( "Now we will use image data...\n" );  
    76     val=0; 
    77     /*  
    78      * Track the brightest red spot on the image 
    79      */  
    80     while(1) 
    81     { 
    82     uint16_t my_x, my_y; 
    83     uint8_t max_red; 
    84     cc3_pixel_t my_pix; 
    85     max_red=0; 
    86     my_x=0; 
    87     my_y=0; 
    88      
    89     if(val&0x1) cc3_set_led(0); else cc3_clr_led(0);  
    90     if(val&0x2) cc3_set_led(1); else cc3_clr_led(1);  
    91     if(val&0x3) cc3_set_led(2); else cc3_clr_led(2);  
    92     if(val&0x4) cc3_set_led(3); else cc3_clr_led(3); 
    93     val++;  
    94  
    95     // This tells the camera to grab a new frame into the fifo and reset 
    96     // any internal location information. 
    97     cc3_pixbuf_load(); 
    98         for(uint16_t y=0; y<cc3_g_current_frame.height; y++ ) 
    99         { 
    100                 // FIXME: add cc3_pixbug img read rows 
    101                 // read a row into the image picture memory from the camera  
    102                 cc3_pixbuf_read_rows(img.pix, img.width, 1);     
    103                 for(uint16_t x=0; x<img.width; x++ ) 
    104                 { 
    105                 // get a pixel from the img row memory 
    106                 cc3_get_pixel( &img, x, 0, &my_pix ); 
    107                 if(my_pix.channel[CC3_RED]>max_red) 
    108                         { 
    109                         max_red=my_pix.channel[CC3_RED]; 
    110                         my_x=x; 
    111                         my_y=y; 
    112                         } 
    113                 }        
    114          
    115         } 
    116  
    117     printf( "Found max red value %d at %d, %d\n",max_red,my_x,my_y ); 
    118     // sample non-blocking serial routine 
    119     if(!cc3_uart_has_data(0) ) break;  
    120     } 
    121     free(img.pix);  // don't forget to free! 
    122     printf( "You pressed %c to escape\n",fgetc(stdin) ); 
    123  
     214    // setup integral image structure 
     215    cc3_img_tmp.channels=3; // RGB color  
     216    cc3_img_tmp.width=cc3_g_current_frame.width;  // equal to Int_Img_Width 
     217    cc3_img_tmp.height = 1;  // image will hold just 1 row for scanline processing 
     218    // if ((cc3_img_tmp.pix = malloc(cc3_img_tmp.width*cc3_img_tmp.channels)) == NULL) 
     219    //      printf("Cannot allocate memory \n\r");  // malloc! (to hold one row RGB) 
     220     cc3_img_tmp.pix = &image_row; 
     221 
     222    if (cc3_img_tmp.width != CC3_INTEGRAL_IMG_WIDTH) 
     223      printf("Error...image width and integral image width different \n\r"); 
     224 
     225     
     226    fp=fopen("c:/test.pgm","w" ); 
     227    fprintf( fp, "P2\n%d %d\n255\n", cc3_g_current_frame.width, cc3_g_current_frame.height-top_offset-bottom_offset ); 
     228 
     229    while(1)  
     230      { 
     231        cc3_num_detected_faces = 0; 
     232 
     233        printf(" New Frame...\n\r"); 
     234        // This tells the camera to grab a new frame into the fifo and reset 
     235        // any internal location information. 
     236        cc3_pixbuf_load(); 
     237         
     238        printf(" captured the image \n\r"); 
     239        // discard some top rows, given by top_offset 
     240        for (uint8_t i = 0; i < top_offset ; i++) 
     241          { 
     242            cc3_pixbuf_read_rows(cc3_img_tmp.pix, cc3_img_tmp.width, cc3_img_tmp.height); 
     243          } 
     244         
     245         
     246        printf(" read top offset \n\r"); 
     247        // indicating how many rows have we read in the actual full image 
     248        // top_offset rows are discarded and next "CC3_INTEGRAL_IMG_HEIGHT" rows are read in the first  
     249        // instance of the following for loop 
     250        cc3_row_counter_actual_img = (top_offset-1)+1;   // index starts from 0 
     251        cc3_row_counter_ii = 0; 
     252        cc3_row_counter_cropped_img = 0; 
     253        cc3_row_counter_calc_ii = (CC3_INTEGRAL_IMG_HEIGHT - 1);  
     254         
     255        printf(" reached the main while loop \n\r"); 
     256        // iterating over the rows of the actual image until the bottom offset 
     257        while (cc3_row_counter_actual_img < (CC3_IMAGE_HEIGHT - bottom_offset)) 
     258          {  
     259            //  printf("%s %d \n\r", "CURRENT ROW ",cc3_row_counter_cropped_img); 
     260            if (cc3_row_counter_calc_ii < CC3_IMAGE_HEIGHT - top_offset - bottom_offset) // check if we need to load any more rows? 
     261              { 
     262                // get the current segment and its integral image 
     263                cc3_get_curr_segment(); 
     264              } 
     265             
     266            //   printf("got the curr seg \n\r"); 
     267            for (uint8_t curr_scale_idx = 0; curr_scale_idx < CC3_NUM_SCALES; curr_scale_idx++) 
     268              { 
     269                 
     270                //      printf (" Current scale %d \n\r", CC3_SCALES[curr_scale_idx]); 
     271                // check if we need to evaluate subwindows at this scale for this sub-window 
     272                if (cc3_rows_to_eval_feat[cc3_row_counter_cropped_img][curr_scale_idx] == 1) 
     273                  {  
     274                    // iterate over all horizontal shifted sub-window 
     275                    for (uint8_t curr_pos_x =0; curr_pos_x < CC3_INTEGRAL_IMG_WIDTH - CC3_SCALES[curr_scale_idx]; curr_pos_x+=CC3_WIN_STEPS[curr_scale_idx]) 
     276                      {  
     277                        //      printf ("current pos_x %d \n\r",curr_pos_x); 
     278                        // compute the standard deviation for this window 
     279                        x2 = curr_pos_x + CC3_SCALES[curr_scale_idx]-1 ; 
     280                        y2 = (cc3_row_counter_ii + CC3_SCALES[curr_scale_idx]-1) % CC3_INTEGRAL_IMG_HEIGHT; 
     281                        if (x2 >= CC3_INTEGRAL_IMG_WIDTH )  
     282                          { 
     283                            printf("Error....width outside limits!! \n\r"); 
     284                          } 
     285                         
     286 
     287                        // Don't consider the first row and first column in the sub-window for calculating  
     288                        // std 
     289                        num_pixels = (CC3_SCALES[curr_scale_idx]-1)*(CC3_SCALES[curr_scale_idx]-1); 
     290                         
     291                        temp1 = cc3_integral_image[cc3_row_counter_ii][curr_pos_x] -  cc3_integral_image[cc3_row_counter_ii][x2]; 
     292                        temp2 = cc3_integral_image[y2][x2] - cc3_integral_image[y2][curr_pos_x]; 
     293                        sum_pix = (uint32_t) (temp1 + temp2);  
     294                        mean_val = sum_pix/num_pixels; 
     295                         
     296                        //      printf("%s %u %u %u %u \n\r"," II ",  cc3_integral_image[cc3_row_counter_ii+1][curr_pos_x+1], cc3_integral_image[cc3_row_counter_ii+1][x2], cc3_integral_image[y2][curr_pos_x+1], cc3_integral_image[y2][x2]); 
     297 
     298                        //              printf("%s %d \n\r", "Mean: ", mean_val); 
     299                        //                      printf("%s %d \n\r", "Num Pixels: ", num_pixels); 
     300                        sum_pix_sq = 0; 
     301                        for (uint8_t i = (cc3_row_counter_ii+1) % CC3_INTEGRAL_IMG_HEIGHT; i != (y2+1)% CC3_INTEGRAL_IMG_HEIGHT; ) 
     302                          { 
     303                            for (uint8_t j = curr_pos_x+1; j <= x2; j++) 
     304                              { 
     305                                temp2 = (i-1+CC3_INTEGRAL_IMG_HEIGHT) % CC3_INTEGRAL_IMG_HEIGHT; 
     306                                temp1 = cc3_integral_image[i][j] - cc3_integral_image[i][j-1]; 
     307                                temp2 = -cc3_integral_image[temp2][j] + cc3_integral_image[temp2][j-1]; 
     308                                temp1 = temp1+temp2; 
     309                                 
     310                                //      if (cc3_row_counter_ii == 0) 
     311                                //       printf("%s %u \n\r", "  ",temp1); 
     312 
     313                                sum_pix_sq+=temp1*temp1; 
     314                              } 
     315                            //      printf("\n"); 
     316                            i = (i+1) % CC3_INTEGRAL_IMG_HEIGHT;  
     317                          } 
     318                         
     319                        uint64_t numer, denom; 
     320                        //              printf("%s %d %d %d \n\r","current wind ",cc3_row_counter_cropped_img, curr_pos_x, CC3_SCALES[curr_scale_idx]); 
     321                        //                      printf("%s %u \n\r", "Sum_pix ",sum_pix); 
     322                        //                      printf("%s %u \n\r", "Square Sum Pix: ",sum_pix_sq);  
     323                         
     324                        numer = (num_pixels*sum_pix_sq); 
     325                        numer =  (numer - sum_pix*sum_pix); 
     326                        //      printf("%s %u \n\r", "var: numerator", numer); 
     327                         
     328                        denom = (num_pixels*num_pixels); 
     329                        //      printf("%s %u \n\r", "var: denom", denom); 
     330                         
     331                        var = numer/denom;            //variance 
     332                        //      var = (sum_pix_sq/num_pixels) - mean_val*mean_val; 
     333                        //      mean_val = sum_pix/num_pixels; 
     334                         
     335                        //                      printf("%s %u \n\r", "Var ",var); 
     336                        //printf("%s %u \n\r", "Mean: ", mean_val); 
     337                         
     338                        if (var < 25) 
     339                          { 
     340                            std = 1;  // basically reject the windows with this variance 
     341                          } 
     342                         
     343                        else 
     344                          { 
     345                            // find the standard deviation 
     346                            for (uint64_t i = 4; i < var/2 ; i++) 
     347                              { 
     348                                if ((i*i <= var) & ((i+1)*(i+1) > var)) 
     349                                  { 
     350                                    if ((var - i*i) < ((i+1)*(i+1) - var)) 
     351                                      std = i; 
     352                                    else  
     353                                      std = i+1; 
     354                                     
     355                                    break; 
     356                                  } 
     357                              } 
     358                          } 
     359                         
     360                        //                      printf("%s %u \n\r\n", "STD ",std); 
     361                         
     362                        //      std = 5; 
     363                         
     364                        if ( (std > 4) & (mean_val > 20) & (mean_val < 200)) // check for face only if std > 3, otherwise its too uniform  
     365                          { 
     366                            //      printf("%s \n\r\n", "Checking for face "); 
     367                             
     368                            int16_t feat_sum = 0; 
     369                            //      int16_t curr_sum; 
     370                            // compute the val of this sub-window for all the features 
     371                            for (uint8_t curr_feat_idx = 0; curr_feat_idx < CC3_NUM_FEATURES; curr_feat_idx++) 
     372                              { 
     373                                feat_sum+=cc3_get_feat_val(curr_feat_idx, curr_scale_idx, curr_pos_x, cc3_row_counter_ii); 
     374                                //              printf("%s %d \n\r", "feat alpha ", curr_sum); 
     375                                //                              feat_sum+=curr_sum; 
     376                              } 
     377                             
     378                            //      printf("After finding feat val \n\r"); 
     379                             
     380                            // check if its a face 
     381                            if (feat_sum > CC3_GLOBAL_THRESHOLD) 
     382                              { 
     383                                //      printf("Found a face \n\r"); 
     384                                //                              printf(" global thersh %d \n\r",CC3_GLOBAL_THRESHOLD); 
     385                                // found a face....or the code says so..(and hope so!!!) 
     386                                if (cc3_num_detected_faces < CC3_MAX_FACES ) 
     387                                  { 
     388                                    //                              printf(" Face found... %d \n\r", cc3_num_detected_faces); 
     389                                     
     390                                    cc3_faces[cc3_num_detected_faces][0] = curr_pos_x; 
     391                                    cc3_faces[cc3_num_detected_faces][1] = cc3_row_counter_cropped_img; // + top_offset; 
     392                                    cc3_faces[cc3_num_detected_faces][2] = CC3_SCALES[curr_scale_idx]; 
     393                                    cc3_num_detected_faces++; 
     394                                  } 
     395                                 
     396                                // as of now, if MAX_FACES already reached, do nothing...(for a change, Relax!!) 
     397                                 
     398                              } 
     399                             
     400                            //      printf("end of detecing face \n\r"); 
     401                          } // end of if (std > 5) 
     402                         
     403                        //      printf(" end of iterating over horizintally shisted win \n\r"); 
     404                      } // end of iterating over horizontally shifted sub-windows 
     405                  } 
     406                 
     407                //      printf(" End of iterating over all scales \n\r"); 
     408                //              printf(" Printing the val of cc3_row_counter_cropped_img %d \n\r",cc3_row_counter_cropped_img); 
     409              } // end of iterating over all scales 
     410             
     411            //         printf("End for curr cropped row %d \n\r", cc3_row_counter_cropped_img); 
     412             
     413            // increment the row counters 
     414            cc3_row_counter_actual_img++; 
     415            cc3_row_counter_cropped_img++; 
     416            cc3_row_counter_ii = (cc3_row_counter_ii + 1) % CC3_INTEGRAL_IMG_HEIGHT; // circular wrapping of integral image row counter 
     417            cc3_row_counter_calc_ii++; 
     418             
     419             
     420          } // end of iterating over all the rows in the actual image (upto bottom_offset) 
     421         
     422        printf("No. of faces : %d \n\r", cc3_num_detected_faces);      
     423         
     424        for (uint8_t i = 0; i < cc3_num_detected_faces; i++) 
     425          printf ( " Face at x=%d, y=%d scale=%d \n\r",cc3_faces[i][0], cc3_faces[i][1], cc3_faces[i][2]); 
     426         
     427        fclose(fp); 
     428        //      printf(" file closed..."); 
     429         
     430        break; 
     431         
     432        // sample non-blocking serial routine 
     433                if(!cc3_uart_has_data(0) ) break;  
     434      } // end of while  
     435     
     436     
     437     
     438    free(cc3_img_tmp.pix);  // don't forget to free! 
     439    printf( "You pressed %c to escape \n\r",fgetc(stdin) ); 
     440     
    124441    // stdio actually works...  
    125442    printf( "Type in a number followed by return to test scanf: " ); 
     
    129446    printf( "Good work, now try something on your own...\n" ); 
    130447    while(1); 
    131  
    132   return 0; 
     448     
     449    return 0; 
    133450} 
    134451