Thread: How to filter the corners in image to get mouth corners only?

  1. #1
    Registered User
    Join Date
    Oct 2007
    Posts
    17

    How to filter the corners in image to get mouth corners only?

    Hi guys,
    I used SUSAN corner detector to detect the corners in a mouth ROI.
    The input image as attached "m-004-1.pgm" and ouput image "004-c.pgm".
    I have changed to .bmp format in order to upload here.
    How can i get rid of other corners and get only the mouth corners? Where should i modify the code?
    This is the code:
    Code:
    /* {{{ Copyright etc. */
    
    /**********************************************************************\
    
      SUSAN Version 2l by Stephen Smith
      Oxford Centre for Functional Magnetic Resonance Imaging of the Brain,
      Department of Clinical Neurology, Oxford University, Oxford, UK
      (Previously in Computer Vision and Image Processing Group - now
      Computer Vision and Electro Optics Group - DERA Chertsey, UK)
      Email:    [email protected]
      WWW:      http://www.fmrib.ox.ac.uk/~steve
    
      (C) Crown Copyright (1995-1999), Defence Evaluation and Research Agency,
      Farnborough, Hampshire, GU14 6TD, UK
      DERA WWW site:
      http://www.dera.gov.uk/
      DERA Computer Vision and Electro Optics Group WWW site:
      http://www.dera.gov.uk/imageprocessing/dera/group_home.html
      DERA Computer Vision and Electro Optics Group point of contact:
      Dr. John Savage, [email protected], +44 1344 633203
    
      A UK patent has been granted: "Method for digitally processing
      images to determine the position of edges and/or corners therein for
      guidance of unmanned vehicle", UK Patent 2272285. Proprietor:
      Secretary of State for Defence, UK. 15 January 1997
    
      This code is issued for research purposes only and remains the
      property of the UK Secretary of State for Defence. This code must
      not be passed on without this header information being kept
      intact. This code must not be sold.
    
    \**********************************************************************/
    
    /* }}} */
    /* {{{ defines, includes and typedefs */
    
    /* ********** Optional settings */
    
    #ifndef PPC
    typedef int        TOTAL_TYPE; /* this is faster for "int" but should be "float" for large d masks */
    #else
    typedef float      TOTAL_TYPE; /* for my PowerPC accelerator only */
    #endif
    
    #define FOPENB           /* uncomment if using djgpp gnu C for DOS or certain Win95 compilers */
    #define SEVEN_SUPP           /* size for non-max corner suppression; SEVEN_SUPP or FIVE_SUPP */
    #define MAX_CORNERS   15000  /* max corners per frame */
    
    /* ********** Leave the rest - but you may need to remove one or both of sys/file.h and malloc.h lines */
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    //#include <sys/file.h>    /* may want to remove this line */
    //#include <malloc.h>      /* may want to remove this line */
    #define  exit_error(IFB,IFC) { fprintf(stderr,IFB,IFC); exit(0); }
    #define  FTOI(a) ( (a) < 0 ? ((int)(a-0.5)) : ((int)(a+0.5)) )
    typedef  unsigned char uchar;
    typedef  struct {int x,y,info, dx, dy, I;} CORNER_LIST[MAX_CORNERS];
    
    /* }}} */
    /* {{{ usage() */
    
    usage()
    {
      printf("Usage: susan <in.pgm> <out.pgm> [options]\n\n");
    
      printf("-s : Smoothing mode (default)\n");
      printf("-e : Edges mode\n");
      printf("-c : Corners mode\n\n");
    
      printf("See source code for more information about setting the thresholds\n");
      printf("-t <thresh> : Brightness threshold, all modes (default=20)\n");
      printf("-d <thresh> : Distance threshold, smoothing mode, (default=4) (use next option instead for flat 3x3 mask)\n");
      printf("-3 : Use flat 3x3 mask, edges or smoothing mode\n");
      printf("-n : No post-processing on the binary edge map (runs much faster); edges mode\n");
      printf("-q : Use faster (and usually stabler) corner mode; edge-like corner suppression not carried out; corners mode\n");
      printf("-b : Mark corners/edges with single black points instead of black with white border; corners or edges mode\n");
      printf("-p : Output initial enhancement image only; corners or edges mode (default is edges mode)\n");
    
      printf("\nSUSAN Version 2l (C) 1995-1997 Stephen Smith, DRA UK. [email protected]\n");
    
      exit(0);
    }
    
    /* }}} */
    /* {{{ get_image(filename,in,x_size,y_size) */
    
    /* {{{ int getint(fp) derived from XV */
    
    int getint(fd)
      FILE *fd;
    {
      int c, i;
      char dummy[10000];
    
      c = getc(fd);
      while (1) /* find next integer */
      {
        if (c=='#')    /* if we're at a comment, read to end of line */
          fgets(dummy,9000,fd);
        if (c==EOF)
          exit_error("Image %s not binary PGM.\n","is");
        if (c>='0' && c<='9')
          break;   /* found what we were looking for */
        c = getc(fd);
      }
    
      /* we're at the start of a number, continue until we hit a non-number */
      i = 0;
      while (1) {
        i = (i*10) + (c - '0');
        c = getc(fd);
        if (c==EOF) return (i);
        if (c<'0' || c>'9') break;
      }
    
      return (i);
    }
    
    /* }}} */
    
    void get_image(filename,in,x_size,y_size)
      char           filename[200];
      unsigned char  **in;
      int            *x_size, *y_size;
    {
    FILE  *fd;
    char header [100];
    int  tmp;
    
    #ifdef FOPENB
      if ((fd=fopen(filename,"rb")) == NULL)
    #else
      if ((fd=fopen(filename,"r")) == NULL)
    #endif
        exit_error("Can't input image %s.\n",filename);
    
      /* {{{ read header */
      header[0]=fgetc(fd);
      header[1]=fgetc(fd);
      if(!(header[0]=='P' && header[1]=='5'))
        exit_error("Image %s does not have binary PGM header.\n",filename);
    
      *x_size = getint(fd);
      *y_size = getint(fd);
    //  printf("x=%d y=%d\n",*x_size,*y_size);
      tmp = getint(fd);
    /* }}} */
    
      *in = (uchar *) malloc(*x_size * *y_size);
    
      if (fread(*in,1,*x_size * *y_size,fd) == 0)
        exit_error("Image %s is wrong size.\n",filename);
    
      fclose(fd);
    }
    
    /* }}} */
    /* {{{ put_image(filename,in,x_size,y_size) */
    
    put_image(filename,in,x_size,y_size)
      char filename [100],
           *in;
      int  x_size,
           y_size;
    {
    FILE  *fd;
    
    #ifdef FOPENB
      if ((fd=fopen(filename,"wb")) == NULL) 
    #else
      if ((fd=fopen(filename,"w")) == NULL) 
    #endif
        exit_error("Can't output image%s.\n",filename);
    
      fprintf(fd,"P5\n");
      fprintf(fd,"%d %d\n",x_size,y_size);
      fprintf(fd,"255\n");
      
      if (fwrite(in,x_size*y_size,1,fd) != 1)
        exit_error("Can't write image %s.\n",filename);
    
      fclose(fd);
    }
    
    /* }}} */
    /* {{{ int_to_uchar(r,in,size) */
    
    int_to_uchar(r,in,size)
      uchar *in;
      int   *r, size;
    {
    int i,
        max_r=r[0],
        min_r=r[0];
    
      for (i=0; i<size; i++)
        {
          if ( r[i] > max_r )
            max_r=r[i];
          if ( r[i] < min_r )
            min_r=r[i];
        }
    
      /*printf("min=%d max=%d\n",min_r,max_r);*/
    
      max_r-=min_r;
    
      for (i=0; i<size; i++)
        in[i] = (uchar)((int)((int)(r[i]-min_r)*255)/max_r);
    }
    
    /* }}} */
    /* {{{ setup_brightness_lut(bp,thresh,form) */
    
    void setup_brightness_lut(bp,thresh,form)
      uchar **bp;
      int   thresh, form;
    {
    int   k;
    float temp;
    
      *bp=(unsigned char *)malloc(516);
      *bp=*bp+258;
    
      for(k=-256;k<257;k++)
      {
        temp=((float)k)/((float)thresh);
        temp=temp*temp;
        if (form==6)
          temp=temp*temp*temp;
        temp=100.0*exp(-temp);
        *(*bp+k)= (uchar)temp;
      }
    }
    
    /* }}} */
    /* {{{ susan principle */
    
    /* {{{ susan_principle(in,r,bp,max_no,x_size,y_size) */
    
    susan_principle(in,r,bp,max_no,x_size,y_size)
      uchar *in, *bp;
      int   *r, max_no, x_size, y_size;
    {
    int   i, j, n;
    uchar *p,*cp;
    
      memset (r,0,x_size * y_size * sizeof(int));
    
      for (i=3;i<y_size-3;i++)
        for (j=3;j<x_size-3;j++)
        {
          n=100;
          p=in + (i-3)*x_size + j - 1;
          cp=bp + in[i*x_size+j];
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-3; 
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-5;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-6;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=2;
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-6;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-5;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-3;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
    
          if (n<=max_no)
            r[i*x_size+j] = max_no - n;
        }
    }
    
    /* }}} */
    /* {{{ susan_principle_small(in,r,bp,max_no,x_size,y_size) */
    
    susan_principle_small(in,r,bp,max_no,x_size,y_size)
      uchar *in, *bp;
      int   *r, max_no, x_size, y_size;
    {
    int   i, j, n;
    uchar *p,*cp;
    
      memset (r,0,x_size * y_size * sizeof(int));
    
      max_no = 730; /* ho hum ;) */
    
      for (i=1;i<y_size-1;i++)
        for (j=1;j<x_size-1;j++)
        {
          n=100;
          p=in + (i-1)*x_size + j - 1;
          cp=bp + in[i*x_size+j];
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-2; 
    
          n+=*(cp-*p);
          p+=2;
          n+=*(cp-*p);
          p+=x_size-2;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
    
          if (n<=max_no)
            r[i*x_size+j] = max_no - n;
        }
    }
    
    /* }}} */
    
    /* }}} */
    /* {{{ smoothing */
    
    /* {{{ median(in,i,j,x_size) */
    
    uchar median(in,i,j,x_size)
      uchar *in;
      int   i, j, x_size;
    {
    int p[8],k,l,tmp;
    
      p[0]=in[(i-1)*x_size+j-1];
      p[1]=in[(i-1)*x_size+j  ];
      p[2]=in[(i-1)*x_size+j+1];
      p[3]=in[(i  )*x_size+j-1];
      p[4]=in[(i  )*x_size+j+1];
      p[5]=in[(i+1)*x_size+j-1];
      p[6]=in[(i+1)*x_size+j  ];
      p[7]=in[(i+1)*x_size+j+1];
    
      for(k=0; k<7; k++)
        for(l=0; l<(7-k); l++)
          if (p[l]>p[l+1])
          {
            tmp=p[l]; p[l]=p[l+1]; p[l+1]=tmp;
          }
    
      return( (p[3]+p[4]) / 2 );
    }
    
    /* }}} */
    /* {{{ enlarge(in,tmp_image,x_size,y_size,border) */
    
    /* this enlarges "in" so that borders can be dealt with easily */
    
    enlarge(in,tmp_image,x_size,y_size,border)
      uchar **in;
      uchar *tmp_image;
      int   *x_size, *y_size, border;
    {
    int   i, j;
    
      for(i=0; i<*y_size; i++)   /* copy *in into tmp_image */
        memcpy(tmp_image+(i+border)*(*x_size+2*border)+border, *in+i* *x_size, *x_size);
    
      for(i=0; i<border; i++) /* copy top and bottom rows; invert as many as necessary */
      {
        memcpy(tmp_image+(border-1-i)*(*x_size+2*border)+border,*in+i* *x_size,*x_size);
        memcpy(tmp_image+(*y_size+border+i)*(*x_size+2*border)+border,*in+(*y_size-i-1)* *x_size,*x_size);
      }
    
      for(i=0; i<border; i++) /* copy left and right columns */
        for(j=0; j<*y_size+2*border; j++)
        {
          tmp_image[j*(*x_size+2*border)+border-1-i]=tmp_image[j*(*x_size+2*border)+border+i];
          tmp_image[j*(*x_size+2*border)+ *x_size+border+i]=tmp_image[j*(*x_size+2*border)+ *x_size+border-1-i];
        }
    
      *x_size+=2*border;  /* alter image size */
      *y_size+=2*border;
      *in=tmp_image;      /* repoint in */
    }
    
    /* }}} */
    /* {{{ void susan_smoothing(three_by_three,in,dt,x_size,y_size,bp) */
    
    void susan_smoothing(three_by_three,in,dt,x_size,y_size,bp)
      int   three_by_three, x_size, y_size;
      uchar *in, *bp;
      float dt;
    {
    /* {{{ vars */
    
    float temp;
    int   n_max, increment, mask_size,
          i,j,x,y,area,brightness,tmp,centre;
    uchar *ip, *dp, *dpt, *cp, *out=in,
          *tmp_image;
    TOTAL_TYPE total;
    
    /* }}} */
    
      /* {{{ setup larger image and border sizes */
    
      if (three_by_three==0)
        mask_size = ((int)(1.5 * dt)) + 1;
      else
        mask_size = 1;
    
      total=0.1; /* test for total's type */
      if ( (dt>15) && (total==0) )
      {
        printf("Distance_thresh (%f) too big for integer arithmetic.\n",dt);
        printf("Either reduce it to <=15 or recompile with variable \"total\"\n");
        printf("as a float: see top \"defines\" section.\n");
        exit(0);
      }
    
      if ( (2*mask_size+1>x_size) || (2*mask_size+1>y_size) )
      {
        printf("Mask size (1.5*distance_thresh+1=%d) too big for image (%dx%d).\n",mask_size,x_size,y_size);
        exit(0);
      }
    
      tmp_image = (uchar *) malloc( (x_size+mask_size*2) * (y_size+mask_size*2) );
      enlarge(&in,tmp_image,&x_size,&y_size,mask_size);
    
    /* }}} */
    
      if (three_by_three==0)
      {     /* large Gaussian masks */
        /* {{{ setup distance lut */
    
      n_max = (mask_size*2) + 1;
    
      increment = x_size - n_max;
    
      dp     = (unsigned char *)malloc(n_max*n_max);
      dpt    = dp;
      temp   = -(dt*dt);
    
      for(i=-mask_size; i<=mask_size; i++)
        for(j=-mask_size; j<=mask_size; j++)
        {
          x = (int) (100.0 * exp( ((float)((i*i)+(j*j))) / temp ));
          *dpt++ = (unsigned char)x;
        }
    
    /* }}} */
        /* {{{ main section */
    
      for (i=mask_size;i<y_size-mask_size;i++)
      {
        for (j=mask_size;j<x_size-mask_size;j++)
        {
          area = 0;
          total = 0;
          dpt = dp;
          ip = in + ((i-mask_size)*x_size) + j - mask_size;
          centre = in[i*x_size+j];
          cp = bp + centre;
          for(y=-mask_size; y<=mask_size; y++)
          {
            for(x=-mask_size; x<=mask_size; x++)
    	{
              brightness = *ip++;
              tmp = *dpt++ * *(cp-brightness);
              area += tmp;
              total += tmp * brightness;
            }
            ip += increment;
          }
          tmp = area-10000;
          if (tmp==0)
            *out++=median(in,i,j,x_size);
          else
            *out++=((total-(centre*10000))/tmp);
        }
      }
    
    /* }}} */
      }
      else
      {     /* 3x3 constant mask */
        /* {{{ main section */
    
      for (i=1;i<y_size-1;i++)
      {
        for (j=1;j<x_size-1;j++)
        {
          area = 0;
          total = 0;
          ip = in + ((i-1)*x_size) + j - 1;
          centre = in[i*x_size+j];
          cp = bp + centre;
    
          brightness=*ip++; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
          brightness=*ip++; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
          brightness=*ip; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
          ip += x_size-2;
          brightness=*ip++; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
          brightness=*ip++; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
          brightness=*ip; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
          ip += x_size-2;
          brightness=*ip++; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
          brightness=*ip++; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
          brightness=*ip; tmp=*(cp-brightness); area += tmp; total += tmp * brightness;
    
          tmp = area-100;
          if (tmp==0)
            *out++=median(in,i,j,x_size);
          else
            *out++=(total-(centre*100))/tmp;
        }
      }
    
    /* }}} */
      }
    }
    
    /* }}} */
    
    /* }}} */
    /* {{{ edges */
    
    /* {{{ edge_draw(in,corner_list,drawing_mode) */
    
    edge_draw(in,mid,x_size,y_size,drawing_mode)
      uchar *in, *mid;
      int x_size, y_size, drawing_mode;
    {
    int   i;
    uchar *inp, *midp;
    
      if (drawing_mode==0)
      {
        /* mark 3x3 white block around each edge point */
        midp=mid;
        for (i=0; i<x_size*y_size; i++)
        {
          if (*midp<8) 
          {
            inp = in + (midp - mid) - x_size - 1;
            *inp++=255; *inp++=255; *inp=255; inp+=x_size-2;
            *inp++=255; *inp++;     *inp=255; inp+=x_size-2;
            *inp++=255; *inp++=255; *inp=255;
          }
          midp++;
        }
      }
    
      /* now mark 1 black pixel at each edge point */
      midp=mid;
      for (i=0; i<x_size*y_size; i++)
      {
        if (*midp<8) 
          *(in + (midp - mid)) = 0;
        midp++;
      }
    }
    
    /* }}} */
    /* {{{ susan_thin(r,mid,x_size,y_size) */
    
    /* only one pass is needed as i,j are decremented if necessary to go
       back and do bits again */
    
    susan_thin(r,mid,x_size,y_size)
      uchar *mid;
      int   *r, x_size, y_size;
    {
    int   l[9], centre, nlinks, npieces,
          b01, b12, b21, b10,
          p1, p2, p3, p4,
          b00, b02, b20, b22,
          m, n, a, b, x, y, i, j;
    uchar *mp;
    
      for (i=4;i<y_size-4;i++)
        for (j=4;j<x_size-4;j++)
          if (mid[i*x_size+j]<8)
          {
            centre = r[i*x_size+j];
            /* {{{ count number of neighbours */
    
            mp=mid + (i-1)*x_size + j-1;
    
            n = (*mp<8) +
                (*(mp+1)<8) +
                (*(mp+2)<8) +
                (*(mp+x_size)<8) +
                (*(mp+x_size+2)<8) +
                (*(mp+x_size+x_size)<8) +
                (*(mp+x_size+x_size+1)<8) +
                (*(mp+x_size+x_size+2)<8);
    
    /* }}} */
            /* {{{ n==0 no neighbours - remove point */
    
            if (n==0)
              mid[i*x_size+j]=100;
    
    /* }}} */
            /* {{{ n==1 - extend line if I can */
    
            /* extension is only allowed a few times - the value of mid is used to control this */
    
            if ( (n==1) && (mid[i*x_size+j]<6) )
            {
              /* find maximum neighbour weighted in direction opposite the
                 neighbour already present. e.g.
                 have: O O O  weight r by 0 2 3
                       X X O              0 0 4
                       O O O              0 2 3     */
    
              l[0]=r[(i-1)*x_size+j-1]; l[1]=r[(i-1)*x_size+j]; l[2]=r[(i-1)*x_size+j+1];
              l[3]=r[(i  )*x_size+j-1]; l[4]=0;                 l[5]=r[(i  )*x_size+j+1];
              l[6]=r[(i+1)*x_size+j-1]; l[7]=r[(i+1)*x_size+j]; l[8]=r[(i+1)*x_size+j+1];
    
              if (mid[(i-1)*x_size+j-1]<8)        { l[0]=0; l[1]=0; l[3]=0; l[2]*=2; 
                                                    l[6]*=2; l[5]*=3; l[7]*=3; l[8]*=4; }
              else { if (mid[(i-1)*x_size+j]<8)   { l[1]=0; l[0]=0; l[2]=0; l[3]*=2; 
                                                    l[5]*=2; l[6]*=3; l[8]*=3; l[7]*=4; }
              else { if (mid[(i-1)*x_size+j+1]<8) { l[2]=0; l[1]=0; l[5]=0; l[0]*=2; 
                                                    l[8]*=2; l[3]*=3; l[7]*=3; l[6]*=4; }
              else { if (mid[(i)*x_size+j-1]<8)   { l[3]=0; l[0]=0; l[6]=0; l[1]*=2; 
                                                    l[7]*=2; l[2]*=3; l[8]*=3; l[5]*=4; }
              else { if (mid[(i)*x_size+j+1]<8)   { l[5]=0; l[2]=0; l[8]=0; l[1]*=2; 
                                                    l[7]*=2; l[0]*=3; l[6]*=3; l[3]*=4; }
              else { if (mid[(i+1)*x_size+j-1]<8) { l[6]=0; l[3]=0; l[7]=0; l[0]*=2; 
                                                    l[8]*=2; l[1]*=3; l[5]*=3; l[2]*=4; }
              else { if (mid[(i+1)*x_size+j]<8)   { l[7]=0; l[6]=0; l[8]=0; l[3]*=2; 
                                                    l[5]*=2; l[0]*=3; l[2]*=3; l[1]*=4; }
              else { if (mid[(i+1)*x_size+j+1]<8) { l[8]=0; l[5]=0; l[7]=0; l[6]*=2; 
                                                    l[2]*=2; l[1]*=3; l[3]*=3; l[0]*=4; } }}}}}}}
    
              m=0;     /* find the highest point */
              for(y=0; y<3; y++)
                for(x=0; x<3; x++)
                  if (l[y+y+y+x]>m) { m=l[y+y+y+x]; a=y; b=x; }
    
              if (m>0)
              {
                if (mid[i*x_size+j]<4)
                  mid[(i+a-1)*x_size+j+b-1] = 4;
                else
                  mid[(i+a-1)*x_size+j+b-1] = mid[i*x_size+j]+1;
                if ( (a+a+b) < 3 ) /* need to jump back in image */
    	    {
                  i+=a-1;
                  j+=b-2;
                  if (i<4) i=4;
                  if (j<4) j=4;
    	    }
    	  }
            }
    
    /* }}} */
            /* {{{ n==2 */
    
            if (n==2)
    	{
              /* put in a bit here to straighten edges */
              b00 = mid[(i-1)*x_size+j-1]<8; /* corners of 3x3 */
              b02 = mid[(i-1)*x_size+j+1]<8;
    	  b20 = mid[(i+1)*x_size+j-1]<8;
              b22 = mid[(i+1)*x_size+j+1]<8;
              if ( ((b00+b02+b20+b22)==2) && ((b00|b22)&(b02|b20)))
    	  {  /* case: move a point back into line.
                    e.g. X O X  CAN  become X X X
                         O X O              O O O
                         O O O              O O O    */
                if (b00) 
    	    {
                  if (b02) { x=0; y=-1; }
                  else     { x=-1; y=0; }
    	    }
                else
    	    {
                  if (b02) { x=1; y=0; }
                  else     { x=0; y=1; }
    	    }
                if (((float)r[(i+y)*x_size+j+x]/(float)centre) > 0.7)
    	    {
                  if ( ( (x==0) && (mid[(i+(2*y))*x_size+j]>7) && (mid[(i+(2*y))*x_size+j-1]>7) && (mid[(i+(2*y))*x_size+j+1]>7) ) ||
                       ( (y==0) && (mid[(i)*x_size+j+(2*x)]>7) && (mid[(i+1)*x_size+j+(2*x)]>7) && (mid[(i-1)*x_size+j+(2*x)]>7) ) )
    	      {
                    mid[(i)*x_size+j]=100;
                    mid[(i+y)*x_size+j+x]=3;  /* no jumping needed */
    	      }
    	    }
    	  }
              else
              {
                b01 = mid[(i-1)*x_size+j  ]<8;
                b12 = mid[(i  )*x_size+j+1]<8;
                b21 = mid[(i+1)*x_size+j  ]<8;
                b10 = mid[(i  )*x_size+j-1]<8;
                /* {{{ right angle ends - not currently used */
    
    #ifdef IGNORETHIS
                if ( (b00&b01)|(b00&b10)|(b02&b01)|(b02&b12)|(b20&b10)|(b20&b21)|(b22&b21)|(b22&b12) )
    	    { /* case; right angle ends. clean up.
                     e.g.; X X O  CAN  become X X O
                           O X O              O O O
                           O O O              O O O        */
                  if ( ((b01)&(mid[(i-2)*x_size+j-1]>7)&(mid[(i-2)*x_size+j]>7)&(mid[(i-2)*x_size+j+1]>7)&
                                        ((b00&((2*r[(i-1)*x_size+j+1])>centre))|(b02&((2*r[(i-1)*x_size+j-1])>centre)))) |
                       ((b10)&(mid[(i-1)*x_size+j-2]>7)&(mid[(i)*x_size+j-2]>7)&(mid[(i+1)*x_size+j-2]>7)&
                                        ((b00&((2*r[(i+1)*x_size+j-1])>centre))|(b20&((2*r[(i-1)*x_size+j-1])>centre)))) |
                       ((b12)&(mid[(i-1)*x_size+j+2]>7)&(mid[(i)*x_size+j+2]>7)&(mid[(i+1)*x_size+j+2]>7)&
                                        ((b02&((2*r[(i+1)*x_size+j+1])>centre))|(b22&((2*r[(i-1)*x_size+j+1])>centre)))) |
                       ((b21)&(mid[(i+2)*x_size+j-1]>7)&(mid[(i+2)*x_size+j]>7)&(mid[(i+2)*x_size+j+1]>7)&
                                        ((b20&((2*r[(i+1)*x_size+j+1])>centre))|(b22&((2*r[(i+1)*x_size+j-1])>centre)))) )
    	      {
                    mid[(i)*x_size+j]=100;
                    if (b10&b20) j-=2;
                    if (b00|b01|b02) { i--; j-=2; }
      	      }
    	    }
    #endif
    
    /* }}} */
                if ( ((b01+b12+b21+b10)==2) && ((b10|b12)&(b01|b21)) &&
                     ((b01&((mid[(i-2)*x_size+j-1]<8)|(mid[(i-2)*x_size+j+1]<8)))|(b10&((mid[(i-1)*x_size+j-2]<8)|(mid[(i+1)*x_size+j-2]<8)))|
                    (b12&((mid[(i-1)*x_size+j+2]<8)|(mid[(i+1)*x_size+j+2]<8)))|(b21&((mid[(i+2)*x_size+j-1]<8)|(mid[(i+2)*x_size+j+1]<8)))) )
    	    { /* case; clears odd right angles.
                     e.g.; O O O  becomes O O O
                           X X O          X O O
                           O X O          O X O     */
                  mid[(i)*x_size+j]=100;
                  i--;               /* jump back */
                  j-=2;
                  if (i<4) i=4;
                  if (j<4) j=4;
    	    }
    	  }
    	}
    
    /* }}} */
            /* {{{ n>2 the thinning is done here without breaking connectivity */
    
            if (n>2)
            {
              b01 = mid[(i-1)*x_size+j  ]<8;
              b12 = mid[(i  )*x_size+j+1]<8;
              b21 = mid[(i+1)*x_size+j  ]<8;
              b10 = mid[(i  )*x_size+j-1]<8;
              if((b01+b12+b21+b10)>1)
              {
                b00 = mid[(i-1)*x_size+j-1]<8;
                b02 = mid[(i-1)*x_size+j+1]<8;
    	    b20 = mid[(i+1)*x_size+j-1]<8;
    	    b22 = mid[(i+1)*x_size+j+1]<8;
                p1 = b00 | b01;
                p2 = b02 | b12;
                p3 = b22 | b21;
                p4 = b20 | b10;
    
                if( ((p1 + p2 + p3 + p4) - ((b01 & p2)+(b12 & p3)+(b21 & p4)+(b10 & p1))) < 2)
                {
                  mid[(i)*x_size+j]=100;
                  i--;
                  j-=2;
                  if (i<4) i=4;
                  if (j<4) j=4;
                }
              }
            }
    
    /* }}} */
          }
    }
    
    /* }}} */
    /* {{{ susan_edges(in,r,sf,max_no,out) */
    
    susan_edges(in,r,mid,bp,max_no,x_size,y_size)
      uchar *in, *bp, *mid;
      int   *r, max_no, x_size, y_size;
    {
    float z;
    int   do_symmetry, i, j, m, n, a, b, x, y, w;
    uchar c,*p,*cp;
    
      memset (r,0,x_size * y_size * sizeof(int));
    
      for (i=3;i<y_size-3;i++)
        for (j=3;j<x_size-3;j++)
        {
          n=100;
          p=in + (i-3)*x_size + j - 1;
          cp=bp + in[i*x_size+j];
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-3; 
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-5;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-6;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=2;
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-6;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-5;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-3;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
    
          if (n<=max_no)
            r[i*x_size+j] = max_no - n;
        }
    
      for (i=4;i<y_size-4;i++)
        for (j=4;j<x_size-4;j++)
        {
          if (r[i*x_size+j]>0)
          {
            m=r[i*x_size+j];
            n=max_no - m;
            cp=bp + in[i*x_size+j];
    
            if (n>600)
            {
              p=in + (i-3)*x_size + j - 1;
              x=0;y=0;
    
              c=*(cp-*p++);x-=c;y-=3*c;
              c=*(cp-*p++);y-=3*c;
              c=*(cp-*p);x+=c;y-=3*c;
              p+=x_size-3; 
        
              c=*(cp-*p++);x-=2*c;y-=2*c;
              c=*(cp-*p++);x-=c;y-=2*c;
              c=*(cp-*p++);y-=2*c;
              c=*(cp-*p++);x+=c;y-=2*c;
              c=*(cp-*p);x+=2*c;y-=2*c;
              p+=x_size-5;
        
              c=*(cp-*p++);x-=3*c;y-=c;
              c=*(cp-*p++);x-=2*c;y-=c;
              c=*(cp-*p++);x-=c;y-=c;
              c=*(cp-*p++);y-=c;
              c=*(cp-*p++);x+=c;y-=c;
              c=*(cp-*p++);x+=2*c;y-=c;
              c=*(cp-*p);x+=3*c;y-=c;
              p+=x_size-6;
    
              c=*(cp-*p++);x-=3*c;
              c=*(cp-*p++);x-=2*c;
              c=*(cp-*p);x-=c;
              p+=2;
              c=*(cp-*p++);x+=c;
              c=*(cp-*p++);x+=2*c;
              c=*(cp-*p);x+=3*c;
              p+=x_size-6;
        
              c=*(cp-*p++);x-=3*c;y+=c;
              c=*(cp-*p++);x-=2*c;y+=c;
              c=*(cp-*p++);x-=c;y+=c;
              c=*(cp-*p++);y+=c;
              c=*(cp-*p++);x+=c;y+=c;
              c=*(cp-*p++);x+=2*c;y+=c;
              c=*(cp-*p);x+=3*c;y+=c;
              p+=x_size-5;
    
              c=*(cp-*p++);x-=2*c;y+=2*c;
              c=*(cp-*p++);x-=c;y+=2*c;
              c=*(cp-*p++);y+=2*c;
              c=*(cp-*p++);x+=c;y+=2*c;
              c=*(cp-*p);x+=2*c;y+=2*c;
              p+=x_size-3;
    
              c=*(cp-*p++);x-=c;y+=3*c;
              c=*(cp-*p++);y+=3*c;
              c=*(cp-*p);x+=c;y+=3*c;
    
              z = sqrt((float)((x*x) + (y*y)));
              if (z > (0.9*(float)n)) /* 0.5 */
    	  {
                do_symmetry=0;
                if (x==0)
                  z=1000000.0;
                else
                  z=((float)y) / ((float)x);
                if (z < 0) { z=-z; w=-1; }
                else w=1;
                if (z < 0.5) { /* vert_edge */ a=0; b=1; }
                else { if (z > 2.0) { /* hor_edge */ a=1; b=0; }
                else { /* diag_edge */ if (w>0) { a=1; b=1; }
                                       else { a=-1; b=1; }}}
                if ( (m > r[(i+a)*x_size+j+b]) && (m >= r[(i-a)*x_size+j-b]) &&
                     (m > r[(i+(2*a))*x_size+j+(2*b)]) && (m >= r[(i-(2*a))*x_size+j-(2*b)]) )
                  mid[i*x_size+j] = 1;
              }
              else
                do_symmetry=1;
            }
            else 
              do_symmetry=1;
    
            if (do_symmetry==1)
    	{ 
              p=in + (i-3)*x_size + j - 1;
              x=0; y=0; w=0;
    
              /*   |      \
                   y  -x-  w
                   |        \   */
    
              c=*(cp-*p++);x+=c;y+=9*c;w+=3*c;
              c=*(cp-*p++);y+=9*c;
              c=*(cp-*p);x+=c;y+=9*c;w-=3*c;
              p+=x_size-3; 
      
              c=*(cp-*p++);x+=4*c;y+=4*c;w+=4*c;
              c=*(cp-*p++);x+=c;y+=4*c;w+=2*c;
              c=*(cp-*p++);y+=4*c;
              c=*(cp-*p++);x+=c;y+=4*c;w-=2*c;
              c=*(cp-*p);x+=4*c;y+=4*c;w-=4*c;
              p+=x_size-5;
        
              c=*(cp-*p++);x+=9*c;y+=c;w+=3*c;
              c=*(cp-*p++);x+=4*c;y+=c;w+=2*c;
              c=*(cp-*p++);x+=c;y+=c;w+=c;
              c=*(cp-*p++);y+=c;
              c=*(cp-*p++);x+=c;y+=c;w-=c;
              c=*(cp-*p++);x+=4*c;y+=c;w-=2*c;
              c=*(cp-*p);x+=9*c;y+=c;w-=3*c;
              p+=x_size-6;
    
              c=*(cp-*p++);x+=9*c;
              c=*(cp-*p++);x+=4*c;
              c=*(cp-*p);x+=c;
              p+=2;
              c=*(cp-*p++);x+=c;
              c=*(cp-*p++);x+=4*c;
              c=*(cp-*p);x+=9*c;
              p+=x_size-6;
        
              c=*(cp-*p++);x+=9*c;y+=c;w-=3*c;
              c=*(cp-*p++);x+=4*c;y+=c;w-=2*c;
              c=*(cp-*p++);x+=c;y+=c;w-=c;
              c=*(cp-*p++);y+=c;
              c=*(cp-*p++);x+=c;y+=c;w+=c;
              c=*(cp-*p++);x+=4*c;y+=c;w+=2*c;
              c=*(cp-*p);x+=9*c;y+=c;w+=3*c;
              p+=x_size-5;
     
              c=*(cp-*p++);x+=4*c;y+=4*c;w-=4*c;
              c=*(cp-*p++);x+=c;y+=4*c;w-=2*c;
              c=*(cp-*p++);y+=4*c;
              c=*(cp-*p++);x+=c;y+=4*c;w+=2*c;
              c=*(cp-*p);x+=4*c;y+=4*c;w+=4*c;
              p+=x_size-3;
    
              c=*(cp-*p++);x+=c;y+=9*c;w-=3*c;
              c=*(cp-*p++);y+=9*c;
              c=*(cp-*p);x+=c;y+=9*c;w+=3*c;
    
              if (y==0)
                z = 1000000.0;
              else
                z = ((float)x) / ((float)y);
              if (z < 0.5) { /* vertical */ a=0; b=1; }
              else { if (z > 2.0) { /* horizontal */ a=1; b=0; }
              else { /* diagonal */ if (w>0) { a=-1; b=1; }
                                    else { a=1; b=1; }}}
              if ( (m > r[(i+a)*x_size+j+b]) && (m >= r[(i-a)*x_size+j-b]) &&
                   (m > r[(i+(2*a))*x_size+j+(2*b)]) && (m >= r[(i-(2*a))*x_size+j-(2*b)]) )
                mid[i*x_size+j] = 2;	
            }
          }
        }
    }
    
    /* }}} */
    /* {{{ susan_edges_small(in,r,sf,max_no,out) */
    
    susan_edges_small(in,r,mid,bp,max_no,x_size,y_size)
      uchar *in, *bp, *mid;
      int   *r, max_no, x_size, y_size;
    {
    float z;
    int   do_symmetry, i, j, m, n, a, b, x, y, w;
    uchar c,*p,*cp;
    
      memset (r,0,x_size * y_size * sizeof(int));
    
      max_no = 730; /* ho hum ;) */
    
      for (i=1;i<y_size-1;i++)
        for (j=1;j<x_size-1;j++)
        {
          n=100;
          p=in + (i-1)*x_size + j - 1;
          cp=bp + in[i*x_size+j];
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
          p+=x_size-2; 
    
          n+=*(cp-*p);
          p+=2;
          n+=*(cp-*p);
          p+=x_size-2;
    
          n+=*(cp-*p++);
          n+=*(cp-*p++);
          n+=*(cp-*p);
    
          if (n<=max_no)
            r[i*x_size+j] = max_no - n;
        }
    
      for (i=2;i<y_size-2;i++)
        for (j=2;j<x_size-2;j++)
        {
          if (r[i*x_size+j]>0)
          {
            m=r[i*x_size+j];
            n=max_no - m;
            cp=bp + in[i*x_size+j];
    
            if (n>250)
    	{
              p=in + (i-1)*x_size + j - 1;
              x=0;y=0;
    
              c=*(cp-*p++);x-=c;y-=c;
              c=*(cp-*p++);y-=c;
              c=*(cp-*p);x+=c;y-=c;
              p+=x_size-2; 
    
              c=*(cp-*p);x-=c;
              p+=2;
              c=*(cp-*p);x+=c;
              p+=x_size-2;
    
              c=*(cp-*p++);x-=c;y+=c;
              c=*(cp-*p++);y+=c;
              c=*(cp-*p);x+=c;y+=c;
    
              z = sqrt((float)((x*x) + (y*y)));
              if (z > (0.4*(float)n)) /* 0.6 */
              {
                do_symmetry=0;
                if (x==0)
    	      z=1000000.0;
    	    else
    	      z=((float)y) / ((float)x);
    	    if (z < 0) { z=-z; w=-1; }
                else w=1;
                if (z < 0.5) { /* vert_edge */ a=0; b=1; }
                else { if (z > 2.0) { /* hor_edge */ a=1; b=0; }
                else { /* diag_edge */ if (w>0) { a=1; b=1; }
                                       else { a=-1; b=1; }}}
                if ( (m > r[(i+a)*x_size+j+b]) && (m >= r[(i-a)*x_size+j-b]) )
                  mid[i*x_size+j] = 1;
              }
              else
                do_symmetry=1;
            }
            else
              do_symmetry=1;
    
            if (do_symmetry==1)
    	{ 
              p=in + (i-1)*x_size + j - 1;
              x=0; y=0; w=0;
    
              /*   |      \
                   y  -x-  w
                   |        \   */
    
              c=*(cp-*p++);x+=c;y+=c;w+=c;
              c=*(cp-*p++);y+=c;
              c=*(cp-*p);x+=c;y+=c;w-=c;
              p+=x_size-2; 
    
              c=*(cp-*p);x+=c;
              p+=2;
              c=*(cp-*p);x+=c;
              p+=x_size-2;
    
              c=*(cp-*p++);x+=c;y+=c;w-=c;
              c=*(cp-*p++);y+=c;
              c=*(cp-*p);x+=c;y+=c;w+=c;
    
              if (y==0)
                z = 1000000.0;
              else
                z = ((float)x) / ((float)y);
              if (z < 0.5) { /* vertical */ a=0; b=1; }
              else { if (z > 2.0) { /* horizontal */ a=1; b=0; }
              else { /* diagonal */ if (w>0) { a=-1; b=1; }
                                    else { a=1; b=1; }}}
              if ( (m > r[(i+a)*x_size+j+b]) && (m >= r[(i-a)*x_size+j-b]) )
                mid[i*x_size+j] = 2;	
            }
          }
        }
    }
    
    /* }}} */
    
    /* }}} */
    /* {{{ corners */
    
    /* {{{ corner_draw(in,corner_list,drawing_mode) */
    
    corner_draw(in,corner_list,x_size,drawing_mode)
      uchar *in;
      CORNER_LIST corner_list;
      int x_size, drawing_mode;
    {
    uchar *p;
    int   n=0;
    
      while(corner_list[n].info != 7)
      {
        if (drawing_mode==0)
        {
          p = in + (corner_list[n].y-1)*x_size + corner_list[n].x - 1;
          *p++=255; *p++=255; *p=255; p+=x_size-2;
          *p++=255; *p++=0;   *p=255; p+=x_size-2;
          *p++=255; *p++=255; *p=255;
          n++;
        }
        else
        {
          p = in + corner_list[n].y*x_size + corner_list[n].x;
          *p=0;
          n++;
        }
      }
    }
    
    /* }}} */
    /* {{{ susan(in,r,sf,max_no,corner_list) */
    
    susan_corners(in,r,bp,max_no,corner_list,x_size,y_size)
      uchar       *in, *bp;
      int         *r, max_no, x_size, y_size;
      CORNER_LIST corner_list;
    {
    int   n,x,y,sq,xx,yy,
          i,j,*cgx,*cgy;
    float divide;
    uchar c,*p,*cp;
    
      memset (r,0,x_size * y_size * sizeof(int));
    
      cgx=(int *)malloc(x_size*y_size*sizeof(int));
      cgy=(int *)malloc(x_size*y_size*sizeof(int));
    
      for (i=5;i<y_size-5;i++)
        for (j=5;j<x_size-5;j++) {
            n=100;
            p=in + (i-3)*x_size + j - 1;
            cp=bp + in[i*x_size+j];
    
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p);
            p+=x_size-3; 
    
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p);
            p+=x_size-5;
    
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p);
            p+=x_size-6;
    
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p);
          if (n<max_no){    /* do this test early and often ONLY to save wasted computation */
            p+=2;
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p);
          if (n<max_no){
            p+=x_size-6;
    
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p);
          if (n<max_no){
            p+=x_size-5;
    
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p);
          if (n<max_no){
            p+=x_size-3;
    
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p);
    
            if (n<max_no)
            {
                x=0;y=0;
                p=in + (i-3)*x_size + j - 1;
    
                c=*(cp-*p++);x-=c;y-=3*c;
                c=*(cp-*p++);y-=3*c;
                c=*(cp-*p);x+=c;y-=3*c;
                p+=x_size-3; 
        
                c=*(cp-*p++);x-=2*c;y-=2*c;
                c=*(cp-*p++);x-=c;y-=2*c;
                c=*(cp-*p++);y-=2*c;
                c=*(cp-*p++);x+=c;y-=2*c;
                c=*(cp-*p);x+=2*c;y-=2*c;
                p+=x_size-5;
        
                c=*(cp-*p++);x-=3*c;y-=c;
                c=*(cp-*p++);x-=2*c;y-=c;
                c=*(cp-*p++);x-=c;y-=c;
                c=*(cp-*p++);y-=c;
                c=*(cp-*p++);x+=c;y-=c;
                c=*(cp-*p++);x+=2*c;y-=c;
                c=*(cp-*p);x+=3*c;y-=c;
                p+=x_size-6;
    
                c=*(cp-*p++);x-=3*c;
                c=*(cp-*p++);x-=2*c;
                c=*(cp-*p);x-=c;
                p+=2;
                c=*(cp-*p++);x+=c;
                c=*(cp-*p++);x+=2*c;
                c=*(cp-*p);x+=3*c;
                p+=x_size-6;
        
                c=*(cp-*p++);x-=3*c;y+=c;
                c=*(cp-*p++);x-=2*c;y+=c;
                c=*(cp-*p++);x-=c;y+=c;
                c=*(cp-*p++);y+=c;
                c=*(cp-*p++);x+=c;y+=c;
                c=*(cp-*p++);x+=2*c;y+=c;
                c=*(cp-*p);x+=3*c;y+=c;
                p+=x_size-5;
    
                c=*(cp-*p++);x-=2*c;y+=2*c;
                c=*(cp-*p++);x-=c;y+=2*c;
                c=*(cp-*p++);y+=2*c;
                c=*(cp-*p++);x+=c;y+=2*c;
                c=*(cp-*p);x+=2*c;y+=2*c;
                p+=x_size-3;
    
                c=*(cp-*p++);x-=c;y+=3*c;
                c=*(cp-*p++);y+=3*c;
                c=*(cp-*p);x+=c;y+=3*c;
    
                xx=x*x;
                yy=y*y;
                sq=xx+yy;
                if ( sq > ((n*n)/2) )
                {
                  if(yy<xx) {
                    divide=(float)y/(float)abs(x);
                    sq=abs(x)/x;
                    sq=*(cp-in[(i+FTOI(divide))*x_size+j+sq]) +
                       *(cp-in[(i+FTOI(2*divide))*x_size+j+2*sq]) +
                       *(cp-in[(i+FTOI(3*divide))*x_size+j+3*sq]);}
                  else {
                    divide=(float)x/(float)abs(y);
                    sq=abs(y)/y;
                    sq=*(cp-in[(i+sq)*x_size+j+FTOI(divide)]) +
                       *(cp-in[(i+2*sq)*x_size+j+FTOI(2*divide)]) +
                       *(cp-in[(i+3*sq)*x_size+j+FTOI(3*divide)]);}
    
                  if(sq>290){
                    r[i*x_size+j] = max_no-n;
                    cgx[i*x_size+j] = (51*x)/n;
                    cgy[i*x_size+j] = (51*y)/n;}
                }
    	}
    }}}}}}}}}}}}}}}}}}}
    
      /* to locate the local maxima */
      n=0;
      for (i=5;i<y_size-5;i++)
        for (j=5;j<x_size-5;j++) {
           x = r[i*x_size+j];
           if (x>0)  {
              /* 5x5 mask */
    #ifdef FIVE_SUPP
              if (
                  (x>r[(i-1)*x_size+j+2]) &&
                  (x>r[(i  )*x_size+j+1]) &&
                  (x>r[(i  )*x_size+j+2]) &&
                  (x>r[(i+1)*x_size+j-1]) &&
                  (x>r[(i+1)*x_size+j  ]) &&
                  (x>r[(i+1)*x_size+j+1]) &&
                  (x>r[(i+1)*x_size+j+2]) &&
                  (x>r[(i+2)*x_size+j-2]) &&
                  (x>r[(i+2)*x_size+j-1]) &&
                  (x>r[(i+2)*x_size+j  ]) &&
                  (x>r[(i+2)*x_size+j+1]) &&
                  (x>r[(i+2)*x_size+j+2]) &&
                  (x>=r[(i-2)*x_size+j-2]) &&
                  (x>=r[(i-2)*x_size+j-1]) &&
                  (x>=r[(i-2)*x_size+j  ]) &&
                  (x>=r[(i-2)*x_size+j+1]) &&
                  (x>=r[(i-2)*x_size+j+2]) &&
                  (x>=r[(i-1)*x_size+j-2]) &&
                  (x>=r[(i-1)*x_size+j-1]) &&
    	      (x>=r[(i-1)*x_size+j  ]) &&
    	      (x>=r[(i-1)*x_size+j+1]) &&
    	      (x>=r[(i  )*x_size+j-2]) &&
    	      (x>=r[(i  )*x_size+j-1]) &&
    	      (x>=r[(i+1)*x_size+j-2]) )
    #endif
    #ifdef SEVEN_SUPP
              if ( 
                    (x>r[(i-3)*x_size+j-3]) &&
                    (x>r[(i-3)*x_size+j-2]) &&
                    (x>r[(i-3)*x_size+j-1]) &&
                    (x>r[(i-3)*x_size+j  ]) &&
                    (x>r[(i-3)*x_size+j+1]) &&
                    (x>r[(i-3)*x_size+j+2]) &&
                    (x>r[(i-3)*x_size+j+3]) &&
    
                    (x>r[(i-2)*x_size+j-3]) &&
                    (x>r[(i-2)*x_size+j-2]) &&
                    (x>r[(i-2)*x_size+j-1]) &&
                    (x>r[(i-2)*x_size+j  ]) &&
                    (x>r[(i-2)*x_size+j+1]) &&
                    (x>r[(i-2)*x_size+j+2]) &&
                    (x>r[(i-2)*x_size+j+3]) &&
    
                    (x>r[(i-1)*x_size+j-3]) &&
                    (x>r[(i-1)*x_size+j-2]) &&
                    (x>r[(i-1)*x_size+j-1]) &&
                    (x>r[(i-1)*x_size+j  ]) &&
                    (x>r[(i-1)*x_size+j+1]) &&
                    (x>r[(i-1)*x_size+j+2]) &&
                    (x>r[(i-1)*x_size+j+3]) &&
    
                    (x>r[(i)*x_size+j-3]) &&
                    (x>r[(i)*x_size+j-2]) &&
                    (x>r[(i)*x_size+j-1]) &&
                    (x>=r[(i)*x_size+j+1]) &&
                    (x>=r[(i)*x_size+j+2]) &&
                    (x>=r[(i)*x_size+j+3]) &&
    
                    (x>=r[(i+1)*x_size+j-3]) &&
                    (x>=r[(i+1)*x_size+j-2]) &&
                    (x>=r[(i+1)*x_size+j-1]) &&
                    (x>=r[(i+1)*x_size+j  ]) &&
                    (x>=r[(i+1)*x_size+j+1]) &&
                    (x>=r[(i+1)*x_size+j+2]) &&
                    (x>=r[(i+1)*x_size+j+3]) &&
    
                    (x>=r[(i+2)*x_size+j-3]) &&
                    (x>=r[(i+2)*x_size+j-2]) &&
                    (x>=r[(i+2)*x_size+j-1]) &&
                    (x>=r[(i+2)*x_size+j  ]) &&
                    (x>=r[(i+2)*x_size+j+1]) &&
                    (x>=r[(i+2)*x_size+j+2]) &&
                    (x>=r[(i+2)*x_size+j+3]) &&
    
                    (x>=r[(i+3)*x_size+j-3]) &&
                    (x>=r[(i+3)*x_size+j-2]) &&
                    (x>=r[(i+3)*x_size+j-1]) &&
                    (x>=r[(i+3)*x_size+j  ]) &&
                    (x>=r[(i+3)*x_size+j+1]) &&
                    (x>=r[(i+3)*x_size+j+2]) &&
                    (x>=r[(i+3)*x_size+j+3]) )
    #endif
    {
    corner_list[n].info=0;
    corner_list[n].x=j;
    corner_list[n].y=i;
    corner_list[n].dx=cgx[i*x_size+j];
    corner_list[n].dy=cgy[i*x_size+j];
    corner_list[n].I=in[i*x_size+j];
    //printf("x=%d,y=%d\n",corner_list[n].x,corner_list[n].y);
    n++;
    if(n==MAX_CORNERS){
          fprintf(stderr,"Too many corners.\n");
          exit(1);
             }}}}
    corner_list[n].info=7;
    
    free(cgx);
    free(cgy);
    
    }
    
    /* }}} */
    /* {{{ susan_quick(in,r,sf,max_no,corner_list) */
    
    susan_corners_quick(in,r,bp,max_no,corner_list,x_size,y_size)
      uchar       *in, *bp;
      int         *r, max_no, x_size, y_size;
      CORNER_LIST corner_list;
    {
    int   n,x,y,i,j;
    uchar *p,*cp;
    
      memset (r,0,x_size * y_size * sizeof(int));
    
      for (i=7;i<y_size-7;i++)
        for (j=7;j<x_size-7;j++) {
            n=100;
            p=in + (i-3)*x_size + j - 1;
            cp=bp + in[i*x_size+j];
    
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p);
            p+=x_size-3;
    
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p);
            p+=x_size-5;
    
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p);
            p+=x_size-6;
    
            n+=*(cp-*p++);
            n+=*(cp-*p++);
            n+=*(cp-*p);
          if (n<max_no){
            p+=2;
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p);
          if (n<max_no){
            p+=x_size-6;
    
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p);
          if (n<max_no){
            p+=x_size-5;
    
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p);
          if (n<max_no){
            p+=x_size-3;
    
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p++);
          if (n<max_no){
            n+=*(cp-*p);
    
            if (n<max_no)
              r[i*x_size+j] = max_no-n;
    }}}}}}}}}}}}}}}}}}}
    
      /* to locate the local maxima */
      n=0;
      for (i=7;i<y_size-7;i++)
        for (j=7;j<x_size-7;j++) {
           x = r[i*x_size+j];
           if (x>0)  {
              /* 5x5 mask */
    #ifdef FIVE_SUPP
              if (
                  (x>r[(i-1)*x_size+j+2]) &&
                  (x>r[(i  )*x_size+j+1]) &&
                  (x>r[(i  )*x_size+j+2]) &&
                  (x>r[(i+1)*x_size+j-1]) &&
                  (x>r[(i+1)*x_size+j  ]) &&
                  (x>r[(i+1)*x_size+j+1]) &&
                  (x>r[(i+1)*x_size+j+2]) &&
                  (x>r[(i+2)*x_size+j-2]) &&
                  (x>r[(i+2)*x_size+j-1]) &&
                  (x>r[(i+2)*x_size+j  ]) &&
                  (x>r[(i+2)*x_size+j+1]) &&
                  (x>r[(i+2)*x_size+j+2]) &&
                  (x>=r[(i-2)*x_size+j-2]) &&
                  (x>=r[(i-2)*x_size+j-1]) &&
                  (x>=r[(i-2)*x_size+j  ]) &&
                  (x>=r[(i-2)*x_size+j+1]) &&
                  (x>=r[(i-2)*x_size+j+2]) &&
                  (x>=r[(i-1)*x_size+j-2]) &&
                  (x>=r[(i-1)*x_size+j-1]) &&
    	      (x>=r[(i-1)*x_size+j  ]) &&
    	      (x>=r[(i-1)*x_size+j+1]) &&
    	      (x>=r[(i  )*x_size+j-2]) &&
    	      (x>=r[(i  )*x_size+j-1]) &&
    	      (x>=r[(i+1)*x_size+j-2]) )
    #endif
    #ifdef SEVEN_SUPP
              if ( 
                    (x>r[(i-3)*x_size+j-3]) &&
                    (x>r[(i-3)*x_size+j-2]) &&
                    (x>r[(i-3)*x_size+j-1]) &&
                    (x>r[(i-3)*x_size+j  ]) &&
                    (x>r[(i-3)*x_size+j+1]) &&
                    (x>r[(i-3)*x_size+j+2]) &&
                    (x>r[(i-3)*x_size+j+3]) &&
    
                    (x>r[(i-2)*x_size+j-3]) &&
                    (x>r[(i-2)*x_size+j-2]) &&
                    (x>r[(i-2)*x_size+j-1]) &&
                    (x>r[(i-2)*x_size+j  ]) &&
                    (x>r[(i-2)*x_size+j+1]) &&
                    (x>r[(i-2)*x_size+j+2]) &&
                    (x>r[(i-2)*x_size+j+3]) &&
    
                    (x>r[(i-1)*x_size+j-3]) &&
                    (x>r[(i-1)*x_size+j-2]) &&
                    (x>r[(i-1)*x_size+j-1]) &&
                    (x>r[(i-1)*x_size+j  ]) &&
                    (x>r[(i-1)*x_size+j+1]) &&
                    (x>r[(i-1)*x_size+j+2]) &&
                    (x>r[(i-1)*x_size+j+3]) &&
    
                    (x>r[(i)*x_size+j-3]) &&
                    (x>r[(i)*x_size+j-2]) &&
                    (x>r[(i)*x_size+j-1]) &&
                    (x>=r[(i)*x_size+j+1]) &&
                    (x>=r[(i)*x_size+j+2]) &&
                    (x>=r[(i)*x_size+j+3]) &&
    
                    (x>=r[(i+1)*x_size+j-3]) &&
                    (x>=r[(i+1)*x_size+j-2]) &&
                    (x>=r[(i+1)*x_size+j-1]) &&
                    (x>=r[(i+1)*x_size+j  ]) &&
                    (x>=r[(i+1)*x_size+j+1]) &&
                    (x>=r[(i+1)*x_size+j+2]) &&
                    (x>=r[(i+1)*x_size+j+3]) &&
    
                    (x>=r[(i+2)*x_size+j-3]) &&
                    (x>=r[(i+2)*x_size+j-2]) &&
                    (x>=r[(i+2)*x_size+j-1]) &&
                    (x>=r[(i+2)*x_size+j  ]) &&
                    (x>=r[(i+2)*x_size+j+1]) &&
                    (x>=r[(i+2)*x_size+j+2]) &&
                    (x>=r[(i+2)*x_size+j+3]) &&
    
                    (x>=r[(i+3)*x_size+j-3]) &&
                    (x>=r[(i+3)*x_size+j-2]) &&
                    (x>=r[(i+3)*x_size+j-1]) &&
                    (x>=r[(i+3)*x_size+j  ]) &&
                    (x>=r[(i+3)*x_size+j+1]) &&
                    (x>=r[(i+3)*x_size+j+2]) &&
                    (x>=r[(i+3)*x_size+j+3]) )
    #endif
    {
    corner_list[n].info=0;
    corner_list[n].x=j;
    corner_list[n].y=i;
    x = in[(i-2)*x_size+j-2] + in[(i-2)*x_size+j-1] + in[(i-2)*x_size+j] + in[(i-2)*x_size+j+1] + in[(i-2)*x_size+j+2] +
        in[(i-1)*x_size+j-2] + in[(i-1)*x_size+j-1] + in[(i-1)*x_size+j] + in[(i-1)*x_size+j+1] + in[(i-1)*x_size+j+2] +
        in[(i  )*x_size+j-2] + in[(i  )*x_size+j-1] + in[(i  )*x_size+j] + in[(i  )*x_size+j+1] + in[(i  )*x_size+j+2] +
        in[(i+1)*x_size+j-2] + in[(i+1)*x_size+j-1] + in[(i+1)*x_size+j] + in[(i+1)*x_size+j+1] + in[(i+1)*x_size+j+2] +
        in[(i+2)*x_size+j-2] + in[(i+2)*x_size+j-1] + in[(i+2)*x_size+j] + in[(i+2)*x_size+j+1] + in[(i+2)*x_size+j+2];
    
    corner_list[n].I=x/25;
    /*corner_list[n].I=in[i*x_size+j];*/
    x = in[(i-2)*x_size+j+2] + in[(i-1)*x_size+j+2] + in[(i)*x_size+j+2] + in[(i+1)*x_size+j+2] + in[(i+2)*x_size+j+2] -
       (in[(i-2)*x_size+j-2] + in[(i-1)*x_size+j-2] + in[(i)*x_size+j-2] + in[(i+1)*x_size+j-2] + in[(i+2)*x_size+j-2]);
    x += x + in[(i-2)*x_size+j+1] + in[(i-1)*x_size+j+1] + in[(i)*x_size+j+1] + in[(i+1)*x_size+j+1] + in[(i+2)*x_size+j+1] -
            (in[(i-2)*x_size+j-1] + in[(i-1)*x_size+j-1] + in[(i)*x_size+j-1] + in[(i+1)*x_size+j-1] + in[(i+2)*x_size+j-1]);
    
    y = in[(i+2)*x_size+j-2] + in[(i+2)*x_size+j-1] + in[(i+2)*x_size+j] + in[(i+2)*x_size+j+1] + in[(i+2)*x_size+j+2] -
       (in[(i-2)*x_size+j-2] + in[(i-2)*x_size+j-1] + in[(i-2)*x_size+j] + in[(i-2)*x_size+j+1] + in[(i-2)*x_size+j+2]);
    y += y + in[(i+1)*x_size+j-2] + in[(i+1)*x_size+j-1] + in[(i+1)*x_size+j] + in[(i+1)*x_size+j+1] + in[(i+1)*x_size+j+2] -
            (in[(i-1)*x_size+j-2] + in[(i-1)*x_size+j-1] + in[(i-1)*x_size+j] + in[(i-1)*x_size+j+1] + in[(i-1)*x_size+j+2]);
    corner_list[n].dx=x/15;
    corner_list[n].dy=y/15;
    n++;
    if(n==MAX_CORNERS){
          fprintf(stderr,"Too many corners.\n");
          exit(1);
             }}}}
    corner_list[n].info=7;
    }
    
    /* }}} */
    
    /* }}} */
    /* {{{ main(argc, argv) */
    
    main(argc, argv)
      int   argc;
      char  *argv [];
    {
    /* {{{ vars */
    
    FILE   *ofp;
    char   filename [80],
           *tcp;
    uchar  *in, *bp, *mid;
    float  dt=4.0;
    int    *r,
           argindex=3,
           bt=10,		/*10(M),11(F),13(edge),24(M/F)*/
           principle=0,
           thin_post_proc=1,
           three_by_three=0,
           drawing_mode=0,
           susan_quick=0,
           max_no_corners=1850,
           max_no_edges=2650,
           mode = 0, i,
           x_size, y_size;
    CORNER_LIST corner_list;
    
    /* }}} */
    
      if (argc<3)
        usage();
    
      get_image(argv[1],&in,&x_size,&y_size);
    
    
      /* {{{ look at options */
    
      while (argindex < argc)
      {
        tcp = argv[argindex];
        if (*tcp == '-')
          switch (*++tcp)
          {
            case 's': /* smoothing */
              mode=0;
    	  break;
            case 'e': /* edges */
              mode=1;
    	  break;
            case 'c': /* corners */
              mode=2;
    	  break;
            case 'p': /* principle */
              principle=1;
    	  break;
            case 'n': /* thinning post processing */
              thin_post_proc=0;
    	  break;
            case 'b': /* simple drawing mode */
              drawing_mode=1;
    	  break;
            case '3': /* 3x3 flat mask */
              three_by_three=1;
    	  break;
            case 'q': /* quick susan mask */
              susan_quick=1;
    	  break;
    	case 'd': /* distance threshold */
              if (++argindex >= argc){
    	    printf ("No argument following -d\n");
    	    exit(0);}
    	  dt=atof(argv[argindex]);
              if (dt<0) three_by_three=1;
    	  break;
    	case 't': /* brightness threshold */
              if (++argindex >= argc){
    	    printf ("No argument following -t\n");
    	    exit(0);}
    	  bt=atoi(argv[argindex]);
    	  break;
          }	    
          else
            usage();
        argindex++;
      }
    
      if ( (principle==1) && (mode==0) )
        mode=1;
    
    /* }}} */
      /* {{{ main processing */
    
      switch (mode)
      {
        case 0:
          /* {{{ smoothing */
    
          setup_brightness_lut(&bp,bt,2);
          susan_smoothing(three_by_three,in,dt,x_size,y_size,bp);
          break;
    
    /* }}} */
        case 1:
          /* {{{ edges */
    
          r   = (int *) malloc(x_size * y_size * sizeof(int));
          setup_brightness_lut(&bp,bt,6);
    
          if (principle)
          {
            if (three_by_three)
              susan_principle_small(in,r,bp,max_no_edges,x_size,y_size);
            else
              susan_principle(in,r,bp,max_no_edges,x_size,y_size);
            int_to_uchar(r,in,x_size*y_size);
          }
          else
          {
            mid = (uchar *)malloc(x_size*y_size);
            memset (mid,100,x_size * y_size); /* note not set to zero */
    
            if (three_by_three)
              susan_edges_small(in,r,mid,bp,max_no_edges,x_size,y_size);
            else
              susan_edges(in,r,mid,bp,max_no_edges,x_size,y_size);
            if(thin_post_proc)
              susan_thin(r,mid,x_size,y_size);
            edge_draw(in,mid,x_size,y_size,drawing_mode);
          }
    
          break;
    
    /* }}} */
        case 2:
          /* {{{ corners */
    
          r   = (int *) malloc(x_size * y_size * sizeof(int));
          setup_brightness_lut(&bp,bt,6);
    
          if (principle)
          {
            susan_principle(in,r,bp,max_no_corners,x_size,y_size);
            int_to_uchar(r,in,x_size*y_size);
          }
          else
          {
            if(susan_quick)
              susan_corners_quick(in,r,bp,max_no_corners,corner_list,x_size,y_size);
            else
              susan_corners(in,r,bp,max_no_corners,corner_list,x_size,y_size);
              corner_draw(in,corner_list,x_size,drawing_mode);
          }
    
          break;
    
    /* }}} */
      }    
    
    /* }}} */
    
      put_image(argv[2],in,x_size,y_size);
    }
    
    /* }}} */
    Thank you.

    Best Regards,
    Tommy

  2. #2
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    UK Defense code for unmanned vehicles?

    Me thinks you may need to consult some 1337 hackers to solve this one.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Do you _REALLY_ think that someone will go through some pretty complex algorithms and 1800+ lines of code, understand how that code works, and tell you what to do?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Mats, do you understand it?

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by JFonseka View Post
    Mats, do you understand it?
    Nope. But I haven't spent any time looking at it other than copy'n'paste into Emacs to get the line count.

    But code like this:
    [code]
    x = in[(i-2)*x_size+j-2] + in[(i-2)*x_size+j-1] + in[(i-2)*x_size+j] + in[(i-2)*x_size+j+1] + in[(i-2)*x_size+j+2] +
    in[(i-1)*x_size+j-2] + in[(i-1)*x_size+j-1] + in[(i-1)*x_size+j] + in[(i-1)*x_size+j+1] + in[(i-1)*x_size+j+2] +
    in[(i )*x_size+j-2] + in[(i )*x_size+j-1] + in[(i )*x_size+j] + in[(i )*x_size+j+1] + in[(i )*x_size+j+2] +
    in[(i+1)*x_size+j-2] + in[(i+1)*x_size+j-1] + in[(i+1)*x_size+j] + in[(i+1)*x_size+j+1] + in[(i+1)*x_size+j+2] +
    in[(i+2)*x_size+j-2] + in[(i+2)*x_size+j-1] + in[(i+2)*x_size+j] + in[(i+2)*x_size+j+1] + in[(i+2)*x_size+j+2];
    [/code
    isn't exactly what I'd call "immediately obvious".

    The obvious PROBLEM with the picture shown is that moustache has more contrast than the mouth, but how to identify that the face has a (dark) moustache and then adjust the contrast so that you identify the mouth instead is the key question here - I have no idea how you'd do that.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Quote Originally Posted by matsp View Post
    Nope. But I haven't spent any time looking at it other than copy'n'paste into Emacs to get the line count.

    But code like this:
    [code]
    x = in[(i-2)*x_size+j-2] + in[(i-2)*x_size+j-1] + in[(i-2)*x_size+j] + in[(i-2)*x_size+j+1] + in[(i-2)*x_size+j+2] +
    in[(i-1)*x_size+j-2] + in[(i-1)*x_size+j-1] + in[(i-1)*x_size+j] + in[(i-1)*x_size+j+1] + in[(i-1)*x_size+j+2] +
    in[(i )*x_size+j-2] + in[(i )*x_size+j-1] + in[(i )*x_size+j] + in[(i )*x_size+j+1] + in[(i )*x_size+j+2] +
    in[(i+1)*x_size+j-2] + in[(i+1)*x_size+j-1] + in[(i+1)*x_size+j] + in[(i+1)*x_size+j+1] + in[(i+1)*x_size+j+2] +
    in[(i+2)*x_size+j-2] + in[(i+2)*x_size+j-1] + in[(i+2)*x_size+j] + in[(i+2)*x_size+j+1] + in[(i+2)*x_size+j+2];
    [/code
    isn't exactly what I'd call "immediately obvious".

    The obvious PROBLEM with the picture shown is that moustache has more contrast than the mouth, but how to identify that the face has a (dark) moustache and then adjust the contrast so that you identify the mouth instead is the key question here - I have no idea how you'd do that.

    --
    Mats
    Examine the RGB values I guess?

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    As it's a black and white sample, my guess is that RGB is quite meaningless.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Well some kind of colour value system.

  9. #9
    Registered User
    Join Date
    Oct 2007
    Posts
    17
    The source code can be reached at http://users.fmrib.ox.ac.uk/~steve/susan/susan2l.c
    Yup, the key point is how to get rid of moustache.
    The terms and modification shouldbe done under susan_corners() subroutine.
    Thanks for the feedback.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Even the "susan_corners" function is about 280 lines long, so not exactly a TINY piece of code to understand. [and another 30 or so lines longer if you use newlines after the line of "}}}}}}}}}" ending some huge and deep nested if-statement].

    I stilll say "Do you really expect anyone to fix your problem for you?"

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    How much programming experience do you need to write code like that.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by JFonseka View Post
    How much programming experience do you need to write code like that.
    By the looks of it, not a whole lot, but you need to keep at it for a while... ;-)

    There is a whole lot of repetitions in the code, that I personally think should be for-loops or other such things, but suggestions to change the code in such ways will not solve the original posters problems.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    The program is simple (if somewhat long).

    The really hard part is all the mathematics and algorithm knowledge which backs it up. Coming up with that in the first place is many months at PhD level.

    It's certainly not going to be a few lines of code, figured out in a few minutes simply from looking at the code posted on the message board.

    At the very least, the OP needs a detailed (and I do mean detailed, like recite large blocks from memory) understanding of the principles behind it. So unless you've already done 6 months to a year of book work, it's not going to happen.

    It would be like asking on a Biology board "Here's a DNA sequence, tell me which diseases it causes".

    IMO, the OP needs to stop kidding themselves that they can do the job they've been assigned.
    http://cboard.cprogramming.com/showthread.php?t=95170

    Something like this requires an extended commitment of time, and that's something which a board primarily focussed on helping newbies understand the details of C and C++ programming could support. What you really need is something like a new sourceforge project where a few interested parties can share the code, or maybe something like rentacoder.com and see if you can locate a machine vision expert (probably not cheap).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem reading tiff image files?
    By compz in forum C++ Programming
    Replies: 9
    Last Post: 10-30-2009, 04:17 AM
  2. Replies: 1
    Last Post: 05-27-2009, 12:46 PM
  3. Simple Image Processing
    By ejohns85 in forum C++ Programming
    Replies: 4
    Last Post: 03-19-2009, 12:10 PM
  4. Image Processing on mouth ROI
    By tommy_chai in forum C Programming
    Replies: 2
    Last Post: 11-20-2007, 09:05 AM
  5. Replies: 4
    Last Post: 03-02-2003, 09:12 AM