• Main Page
  • Related Pages
  • Files
  • File List
  • Globals

amss/FDS_AMSS.c

Go to the documentation of this file.
00001 
00035 /*
00036  * Pre processing
00037  */
00038 
00039 #include <stdlib.h>
00040 #include <tiffio.h>
00041 #include <time.h>
00042 #include <math.h>
00043 #include "io_tiff_routine.h"
00044 
00045 /*
00046  * Print error messages
00047  */
00048 
00049 
00051 #define FATAL(MSG)\
00052         do {\
00053           fprintf(stderr, MSG "\n");\
00054         abort();\
00055         } while (0);
00056 
00058 #define INFO(MSG)\
00059     do {\
00060         fprintf(stderr, MSG "\n");\
00061     } while (0);
00062 
00064 #define DEBUG(MSG)\
00065     do {\
00066         if (debug_flag)\
00067             fprintf(stderr, __FILE__ ":%03i " MSG "\n", __LINE__);\
00068     } while (0);
00069     
00070 
00071 /*
00072  * Compute one iteration of heat equation
00073  */
00074 
00103 static void heat (float *ptr_out, float *ptr_in, size_t n_col, int i, int i_prev, int i_next, int j, int j_prev, int j_next, float dt)
00104 
00105 {  
00106    float laplacian;
00107    laplacian = -4.0 * (*(ptr_in + i*n_col + j)) +
00108                        *(ptr_in + i_prev*n_col + j) + *(ptr_in + i*n_col + j_prev)
00109                                  + *(ptr_in + i*n_col + j_next) + *(ptr_in + i_next*n_col + j);
00110    *(ptr_out+i*n_col + j)= *(ptr_in+i*n_col+j) + dt * laplacian;
00111    
00112 }
00113 
00114 
00115 /*
00116  * Compute one iteration of the Affine Morphological Scale Space
00117  */
00118 
00259  static void amss(float *ptr_out, float *ptr_in, size_t n_row, size_t n_col, float dt, float t_g)
00260  
00261  {
00262       float         grad, s_x, s_y, eta0, eta1, eta2, eta3, eta4, l_comb;
00263       unsigned int  i, j, i_next, i_prev, j_next, j_prev;
00264   
00265       /* iterate on j and i, following the array order */
00266       for (i=0; i<n_row; i++ )  {  
00267 
00268                   /* symmetry for borders */
00269           i_next = (i<n_row-1?i+1:i);
00270           i_prev = (i>0?i-1:i);
00271                
00272           for (j=0; j<n_col; j++)  {   
00273                           
00274                           /* symmetry for borders */
00275               j_next = (j<n_col-1?j+1:j);
00276               j_prev = (j>0?j-1:j);         
00277                      
00278               /* computation of s_x, s_y and of the gradient */
00279               s_x= 2 * ( *(ptr_in+i*n_col+j_next) - *(ptr_in+i*n_col+j_prev) ) +
00280                  *(ptr_in+i_prev*n_col+j_next) - *(ptr_in+i_prev*n_col+j_prev) +
00281                  *(ptr_in+i_next*n_col+j_next) - *(ptr_in+i_next*n_col+j_prev);
00282               s_y= 2 * ( *(ptr_in+i_next*n_col+j) - *(ptr_in+i_prev*n_col+j) ) +
00283                  *(ptr_in+i_next*n_col+j_next) - *(ptr_in+i_prev*n_col+j_next) +
00284                  *(ptr_in+i_next*n_col+j_prev) - *(ptr_in+i_prev*n_col+j_prev);
00285               grad = 0.125 * sqrt( (s_x*s_x) + (s_y*s_y) );    
00286               
00287               if (grad<t_g)
00288                  /* Heat Equation */
00289                  heat (ptr_out, ptr_in, n_col, i, i_prev, i_next, j, j_prev, j_next, dt);
00290               else {
00291                  /* AMSS diffusion */
00292                  eta0 =0.5 * (s_x*s_x + s_y*s_y)- (s_x*s_x*s_y*s_y)/(s_x*s_x + s_y*s_y);
00293                  eta1= 2 * eta0 - (s_x*s_x);
00294                  eta2= 2 * eta0 - (s_y*s_y);
00295                  eta3= - eta0 + 0.5 * (s_x*s_x + s_y*s_y - s_x*s_y);
00296                  eta4= - eta0 + 0.5 * (s_x*s_x + s_y*s_y + s_x*s_y);
00297                  
00298                  l_comb= ( -4 * eta0 * ( *(ptr_in+i*n_col+j) ) +
00299                    eta1*( *(ptr_in+i*n_col+j_next) + *(ptr_in+i*n_col+j_prev) ) +
00300                    eta2*( *(ptr_in+i_next*n_col+j) + *(ptr_in+i_prev*n_col+j) ) +
00301                    eta3*( *(ptr_in+i_next*n_col+j_next) + *(ptr_in+i_prev*n_col+j_prev) ) +
00302                    eta4*( *(ptr_in+i_prev*n_col+j_next) + *(ptr_in+i_next*n_col+j_prev) ) );
00303                  
00304                  /* pow(x,y) which returns x^y requires that x>=0 */                
00305               if (l_comb>0) 
00306                  *(ptr_out+i*n_col+j)=
00307                     *(ptr_in+i*n_col+j) + 0.25 * dt * pow(l_comb,0.33333333);
00308               else 
00309                  *(ptr_out+i*n_col+j)=
00310                     *(ptr_in+i*n_col+j) - 0.25 * dt * pow(-l_comb,0.33333333);
00311               }
00312                   }
00313       }
00314  }
00315 
00316 
00317 /*
00318  * Main function section
00319  */
00320 
00331 int main(int argc, char *argv[])
00332 
00333 {  
00334    float        *data_in;                    /* input data */
00335    float            *ptr_in_rgb[3];
00336    float        *data_out;                   /* output data */
00337    float            *ptr_out_rgb[3];
00338    size_t       n_col, n_row;                /* number of columns and rows */ 
00339    size_t       n_channels;                  /* number of channels */
00340    float        *ptr_in, *ptr_out, *ptr_end;    
00341    int          n_iter=0;                    /* number of iterations */
00342    float        R;                           /* normalization scale */
00343    float        t_g;                         /* gradient threshold */   
00344    float        dt=0.1;                      /* time step */
00345    float        n_iter_f;
00346    int          m;
00347    unsigned int k;
00348    clock_t      t0, t1;
00349 
00350    /*
00351     * argv[1] contains the normalized scale
00352     * argv[2] contains the input file name
00353     * argv[3] contains the output file name
00354     */   
00355    if (4!=argc)
00356       FATAL("Error in the number of arguments!\n");
00357    if (0==sscanf(argv[1],"%f", &R)) 
00358       FATAL("The third argument must be a float!\n");
00359    
00360    /* R<0 is an error because R must be a positive real number */
00361    if (0 > R) {
00362       printf("The normalized scale must be a positive real number!\n");
00363       return 0;
00364       }
00365       
00366    /* start clock */
00367    t0 = clock();
00368        
00369    /* number of iteration needed */
00370    n_iter_f= 0.75 * ( pow(R,1.33333333) / dt );
00371     
00372    /* round n_iter_f (must be an integer) */
00373     n_iter= (int) (n_iter_f + 0.5);     
00374    
00375    /* read the TIFF image */
00376    if (NULL == (data_in = read_tiff_f32(argv[2], &n_col, &n_row, &n_channels)))
00377       FATAL("error while reading the TIFF image");
00378    
00379    ptr_in_rgb[0] = data_in;
00380    ptr_in_rgb[1] = data_in + n_row * n_col;
00381    ptr_in_rgb[2] = data_in + 2 * n_row * n_col;
00382 
00383   /* look for identical RGB channels (check if the image is BW or true RGB) */
00384    if (1!=n_channels){
00385       n_channels = 1;
00386       for (k=0; k<((n_row*n_col)-1); k++)
00387               if ( ( (*(ptr_in_rgb[0]+k)) != (*(ptr_in_rgb[1]+k) ))||
00388                    ( (*(ptr_in_rgb[0]+k)) != (*(ptr_in_rgb[2]+k) )) )  {  
00389                   n_channels=3;
00390                   break;
00391               }
00392    }
00393       
00394    /* error if n_iter<0 */ 
00395    if (0>n_iter)
00396           printf("The number of iteration must be a positive number. \n");
00397    /* input=output if n_iter=0 */
00398    else if (0==n_iter) {
00399       write_tiff_f32(argv[3], data_in, n_col, n_row, n_channels);
00400    }
00401    else { 
00402       /* memory allocation for data out*/
00403       if (NULL == (data_out = (float *) malloc(n_channels* n_col * n_row * sizeof(float))))
00404          FATAL("allocation error");
00405           
00406       /* apply MCM to each RGB channel */   
00407       ptr_out_rgb[0] = data_out;
00408       ptr_out_rgb[1] = data_out +  n_row * n_col;
00409       ptr_out_rgb[2] = data_out + 2 * n_row * n_col;
00410         
00411       for (k=0; k<n_channels; k++) {
00412           t_g=4;
00413                   /* initialize pointers */
00414           ptr_in=ptr_in_rgb[k];
00415           ptr_out=ptr_out_rgb[k];
00416           ptr_end=ptr_in + n_row*n_col;
00417           
00418           for (m=0; m<n_iter; m++)   {
00419               /* apply affine morphological scale space */
00420               amss(ptr_out, ptr_in, n_row, n_col, dt, t_g);
00421               /* decrease threshold after the first iteration */
00422               if (m==0) t_g=1;
00423               /* update arrays */
00424               while (ptr_in<ptr_end) {
00425                     *ptr_in = *ptr_out;
00426                     ptr_in++;
00427                             ptr_out++;
00428               }
00429               ptr_in=ptr_in_rgb[k];
00430               ptr_out=ptr_out_rgb[k];
00431           }
00432          /* saturate values to [0,255] */ 
00433           while (ptr_in<ptr_end){
00434                 if (*ptr_in>255) *ptr_in=255;
00435                 if (*ptr_in<0) *ptr_in=0;
00436                 ptr_in++;
00437                   }
00438         }
00439       /* write the output image */
00440       write_tiff_f32(argv[3], data_in, n_col, n_row, n_channels);
00441           /* free memory*/
00442       free(data_out);
00443   }
00444 
00445    /* stop clock */
00446    t1 = clock();
00447    /* write in the stdout the time required by the algorithm */
00448    printf("Time elapsed = %f seconds\n", (double)(t1-t0)/(double)CLOCKS_PER_SEC);
00449    
00450    free(data_in);
00451    return 0;
00452 }

Generated on Thu Feb 17 2011 15:42:31 for fds_amss by  doxygen 1.7.1