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

mcm/FDS_MCM.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 "io_tiff_routine.h"
00042 #include <time.h>
00043 #include <math.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 
00104 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)
00105 
00106 {  
00107    float laplacian;
00108    laplacian = -4.0 * (*(ptr_in + i*n_col + j)) +
00109                        *(ptr_in + i_prev*n_col + j) + *(ptr_in + i*n_col + j_prev) + 
00110                                    *(ptr_in + i*n_col + j_next) + *(ptr_in + i_next*n_col + j);
00111    
00112    *(ptr_out+i*n_col + j)= *(ptr_in+i*n_col+j) + 0.5 * dt * laplacian;     
00113 }
00114 
00115 /*
00116  * Compute one iteration of the Mean Curvature Motion
00117  */
00118 
00239  static void mcm(float *ptr_out, float *ptr_in, size_t n_row, size_t n_col, float dt, float t_g)
00240  
00241  {
00242       unsigned int  i, j, i_next, i_prev, j_next, j_prev;
00243       float         grad, s_x, s_y, lambda0, lambda1, lambda2, lambda3, lambda4;
00244       
00245       /* iterate on j and i, following the array order */
00246       for (i=0; i<n_row; i++ )  {  
00247           
00248                   /* symmetry for borders */
00249           i_next = (i<n_row-1?i+1:i);
00250           i_prev = (i>0?i-1:i);
00251                
00252           for (j=0; j<n_col; j++)  {   
00253                         
00254                /* symmetry for borders */
00255               j_next = (j<n_col-1?j+1:j);
00256               j_prev = (j>0?j-1:j);         
00257                      
00258               /* computation of s_x, s_y and gradient */
00259               s_x= 2 * ( *(ptr_in+i*n_col+j_next) - *(ptr_in+i*n_col+j_prev) ) +
00260                  *(ptr_in+i_prev*n_col+j_next) - *(ptr_in+i_prev*n_col+j_prev) +
00261                  *(ptr_in+i_next*n_col+j_next) - *(ptr_in+i_next*n_col+j_prev);
00262               s_y= 2 * ( *(ptr_in+i_next*n_col+j) - *(ptr_in+i_prev*n_col+j) ) +
00263                  *(ptr_in+i_next*n_col+j_next) - *(ptr_in+i_prev*n_col+j_next) +
00264                  *(ptr_in+i_next*n_col+j_prev) - *(ptr_in+i_prev*n_col+j_prev);
00265               grad = 0.125 * sqrt( (s_x*s_x) + (s_y*s_y) );    
00266               
00267               if (grad>t_g) {
00268                  /* MCM diffusion */
00269                  grad*=8;   /* i.e. grad=\sqrt{s_x^2 + s_y^2} */
00270                  lambda0 = 0.5 - ( (s_x*s_x*s_y*s_y) / ( pow(grad,4) ) );
00271                  lambda1= 2 * lambda0 - ( (s_x*s_x) / (grad*grad) );
00272                  lambda2= 2 * lambda0 - ( (s_y*s_y) / (grad*grad) );
00273                  lambda3= -lambda0 + 0.5 * ( 1 - ( (s_x*s_y)/(grad*grad) ) );
00274                  lambda4= -lambda0 + 0.5 * ( 1 + ( (s_x*s_y)/(grad*grad) ) );
00275             
00276                  *(ptr_out+i*n_col + j)= *(ptr_in+i*n_col+j) + dt * (
00277                  -4 * lambda0 * (*(ptr_in+i*n_col+j)) +
00278                  lambda1 * (*(ptr_in+i*n_col+j_next) + *(ptr_in+i*n_col+j_prev)) +
00279                  lambda2 * (*(ptr_in+i_next*n_col+j) + *(ptr_in+i_prev*n_col+j)) +
00280                  lambda3 * (*(ptr_in+i_prev*n_col+j_prev) + *(ptr_in+i_next*n_col+j_next)) +
00281                  lambda4 * (*(ptr_in+i_prev*n_col+j_next) + *(ptr_in+i_next*n_col+j_prev)) );
00282                  }
00283               
00284               else
00285                 /* Heat Equation */
00286                  heat (ptr_out, ptr_in, n_col, i, i_prev, i_next, j, j_prev, j_next, dt);
00287               }
00288           }
00289  }
00290 
00291 
00292 /*
00293  * Main function section
00294  */
00295 
00305 int main(int argc, char *argv[])
00306 
00307 {  
00308    float        *data_in;                    /* input data */
00309    float            *ptr_in_rgb[3];
00310    float        *data_out;                   /* output data */
00311    float            *ptr_out_rgb[3];
00312    size_t       n_col, n_row;                /* number of columns and rows */
00313    size_t       n_channels;                  /* number of channels */
00314    float        *ptr_in, *ptr_out, *ptr_end;                    
00315    int          n_iter=0;                    /* number of iterations */
00316    float        R;                           /* normalization scale */
00317    float        t_g=4;                       /* gradient threshold */   
00318    float        dt=0.1;                      /* time step */ 
00319    float        n_iter_f;                                        /* final number of iterations */
00320    unsigned int k;
00321    int          m;
00322    clock_t      t0, t1;
00323      
00324    /*
00325     * argv[1] contains the normalized scale
00326     * argv[2] contains the input file name
00327     * argv[3] contains the output file name
00328     */   
00329    if (4!=argc)
00330       FATAL("Error in the number of arguments!\n");
00331    if (0==sscanf(argv[1],"%f", &R)) 
00332       FATAL("The third argument must be a float!\n");
00333     
00334    /* R<0 is an error because R must be a positive real number */
00335    if (0 > R) {
00336       printf("The normalized scale must be a positive real number!\n");
00337       return 0;
00338    }
00339    
00340    /* start clock */
00341    t0 = clock();
00342    
00343    /* number of iterations needed */
00344    n_iter_f= (R * R) / (2 * dt);
00345    
00346    /* round n_iter_f (must be integer) */   
00347    n_iter= (int) (n_iter_f+0.5);
00348 
00349    /* read the TIFF image */
00350    if (NULL == (data_in = read_tiff_f32(argv[2], &n_col, &n_row, &n_channels)))
00351       FATAL("error while reading the TIFF image");
00352    
00353    ptr_in_rgb[0] = data_in;
00354    ptr_in_rgb[1] = data_in + n_row * n_col;
00355    ptr_in_rgb[2] = data_in + 2 * n_row * n_col;
00356 
00357    /* look for identical RGB channels (check if the image is BW or true RGB) */
00358    if (1!=n_channels){
00359       n_channels = 1;
00360       for (k=0; k<(n_row*n_col-1); k++)
00361               if((*(ptr_in_rgb[0]+k)!= *(ptr_in_rgb[1]+k))||(*(ptr_in_rgb[0]+k)!=*(ptr_in_rgb[2]+k))){  
00362                 n_channels=3;
00363                 break;
00364               }
00365    }
00366   
00367    /* error if n_iter<0 */ 
00368    if (0>n_iter)
00369           printf("The number of iteration must be a positive number. \n");
00370    /* input=output if n_iter=0 */
00371    else if (0==n_iter) {
00372       write_tiff_f32(argv[3], data_in, n_col, n_row, n_channels);
00373    }
00374    else { 
00375       /* allocate memory for data_out */
00376       if (NULL == (data_out = (float *) malloc(n_channels* n_col * n_row * sizeof(float))))
00377          FATAL("allocation error");
00378           
00379           /* apply MCM to each RGB channel */
00380       ptr_out_rgb[0] = data_out;
00381       ptr_out_rgb[1] = data_out +  n_row * n_col;
00382       ptr_out_rgb[2] = data_out + 2 * n_row * n_col;
00383           for (k=0; k<n_channels; k++) {
00384                   /* initialize pointers */
00385           ptr_in  = ptr_in_rgb[k];
00386           ptr_out = ptr_out_rgb[k];
00387           ptr_end = ptr_in + n_row*n_col;
00388                   for (m=0; m<n_iter; m++)   {
00389               /* apply mean curvature motion */
00390               mcm (ptr_out, ptr_in, n_row, n_col, dt, t_g);
00391               /* update arrays */
00392               while (ptr_in<ptr_end) {
00393                     *ptr_in = *ptr_out;
00394                     ptr_in++;
00395                             ptr_out++;
00396               }
00397               ptr_in=ptr_in_rgb[k];
00398               ptr_out=ptr_out_rgb[k];
00399           }
00400          /* saturate values to [0,255] */ 
00401           while (ptr_in<ptr_end) {
00402                 if (*ptr_in>255) *ptr_in=255;
00403                 if (*ptr_in<0) *ptr_in=0;
00404                 ptr_in++;
00405                   }
00406       }
00407       /* write the output image */
00408       write_tiff_f32(argv[3], data_in, n_col, n_row, n_channels);
00409           /* free memory */
00410       free(data_out);
00411   }
00412    
00413    /* stop clock */
00414    t1 = clock();
00415    /* write in the stdout the time required by the algorithm */
00416    printf("Time elapsed = %f seconds\n", (double)(t1-t0)/(double)CLOCKS_PER_SEC);
00417    /* free memory */
00418    free(data_in);
00419    return 0;
00420 }

Generated on Thu Feb 17 2011 15:42:24 for fds_mcm by  doxygen 1.7.1