/* Lightness computation - Andrew Blake, Dept. CS, Edinburgh University. adjusted by Gavin Brelstaff 16/11/84. Altered to allow for a SQUARE GRID OF SKEWED TRIANGLES rather than equilaterals. WITH NON-FLOATING POINT VARIATION OF THE OVERRELAXTION PARAMETER, implemented by Gavin Brelstaff 21/11/84. Extended to pictures greater than 128x128 by Gavin Brelstaff 14/12/84. WITH LOGARITHMIC INPUT CONVERSION WITH OUTPUT OF MEAN ZERO both by Gavin Brelstaff 14/1/85 With threshold percentage option 4/2/85 Gavin Brelstaff. DEVELOPMENT CANNY THRESHOLD FILE INPUT OPTION 27/2/85 Gavin Brelstaff MORE DEVELOPMENT OF CANNY 19/3/85 picture format: first byte is image size (square image) if less than 128, else use -x option, then image grey data in left to right, top to bottom format. to run, see vision:light.doc */ #include #include /* for log function */ #define progname "light" #define flagU 0100 #define flagD 0200 #define MAXSIZE 100 /* max. image size */ #define MAXAREA MAXSIZE*MAXSIZE #define MAXCHAR 255 #define EOS '\0' short nbits = 0; /* picture scaling: nbits +8 bits */ long x[MAXAREA], rij[MAXAREA] ; /* pics: relaxing, initial */ char conflag[MAXAREA]; /* flags indicating existence of triangles and results of thresholding (top 2 bits) uij & dij */ char Mij[MAXAREA]; /* number of surrounding triangles*/ short asize ; /* pic dimensions */ long area; short header=1;/* set if pic file contains a header char */ float th_percentage=6.0; /* input parameter the threshold percentage*/ int th=100; /* threshold value for (gradient*gradient) */ #define MAXCHANGE 0 #define MAXITER 2000 int iter=900; /* maximum no of iterations */ int minchange=MAXCHANGE; /* min max-change for one iteration: stops */ /* program if max-change is less */ short freq=10; /* number of iters per reported change */ int prec=16; /* constant specifying precision of integer computation */ FILE *fp, *fq = NULL; /* input,output picture channels */ short SORpara = 8; /* The SOR relaxation parameter w */ /* in units of 16ths range 1 to 16*/ /* value 16 means Jacobi JOR */ char canny_file_name[32]; /* name file containing canny results */ #define CANNYFILE "canny.hyst" /* default canny file name */ char funcflag=1;/* set if Functional is to be computed */ char cflag=0; /* set if canny operator file is used as thresholding */ char gflag=0; /* set if canny operator file is used to guide thresholding */ char tflag=0; /* set if threshold specified */ char mflag=1; /* set if mean zero option for output */ char bflag=0; /* set if beeps for attention */ char sflag=0; /* set if output to screen is to be supressed */ char lflag=1; /* set if log conversion used */ char wflag=0; /* set if writing threshold flags to file */ char fflag=0; /* set if reading threshold flags from file */ char edge_file_name[32]; /* file name to send edge results to if wflag=1 */ char flag_file_name[32]; /* file name to get edges from if fflag=1 */ #define EDGEFILE "edgeU" /* default edge file name */ #define FLAGFILE "flagU" /* default flag file name */ typedef long (*PFL)(); PFL fnp; /* global pointer to function that multiplies*/ /* values (x) by the SORpara/16 using shifts */ /* to avoid slow floating point calculations */ /* functions that multiply by sixteenths using shifting op.s */ long fn1(x) long x;{return(x>>4);} long fn2(x) long x;{return(x>>3);} long fn3(x) long x;{return((x>>3)+(x>>4));} long fn4(x) long x;{return(x>>2);} long fn5(x) long x;{return((x>>2)+(x>>4));} long fn6(x) long x;{return((x>>2)+(x>>3));} long fn7(x) long x;{return((x>>2)+(x>>3)+(x>>4));} long fn8(x) long x;{return(x>>1);} long fn9(x) long x;{return((x>>1)+(x>>4));} long fn10(x) long x;{return((x>>1)+(x>>3));} /* e.g. returns 10x/16 */ long fn11(x) long x;{return((x>>1)+(x>>3)+(x>>4));} long fn12(x) long x;{return((x>>1)+(x>>2));} long fn13(x) long x;{return((x>>1)+(x>>2)+(x>>4));} long fn14(x) long x;{return((x>>1)+(x>>2)+(x>>3));} long fn15(x) long x;{return((x>>1)+(x>>2)+(x>>3)+(x>>4));} long fn16(x) long x;{return(x);} setfnpointer(l) /* sets function pointer to appropriate shifting function */ short l; { switch(l) { case(1): fnp=fn1;break; case(2): fnp=fn2;break; case(3): fnp=fn3;break; case(4): fnp=fn4;break; case(5): fnp=fn5;break; case(6): fnp=fn6;break; case(7): fnp=fn7;break; case(8): fnp=fn8;break; case(9): fnp=fn9;break; case(10): fnp=fn10;break; case(11): fnp=fn11;break; case(12): fnp=fn12;break; case(13): fnp=fn13;break; case(14): fnp=fn14;break; case(15): fnp=fn15;break; case(16): fnp=fn16;break; } } main(argc,argv) char **argv; { argv++; while ((argc>1)&&((*argv)[0] == '-')) { switch((*argv)[1]) { case 'j': sscanf(*argv+2,"%hd",&SORpara); if(SORpara<1 || SORpara>16) error("SOR parameter out of range 1 .. 16"); break; case 'x': sscanf(*argv+2,"%hd",&asize); if(asize<0||asize>MAXSIZE) error("picture to big"); header=0; break; case 'F': sscanf(*argv+2,"%hd",&freq); if(freq<1) error("bad reporting frequency"); break; case 'c': sscanf(*argv+2,"%s",canny_file_name); cflag=1; break; case 'g': sscanf(*argv+2,"%s",canny_file_name); gflag=1; break; case 's': /* supress output to screen flag */ sflag=1; break; case 'w': /* write threshold flag files */ sscanf(*argv+2,"%s",edge_file_name); wflag=1; break; case 'f': /* read threshold flag files */ sscanf(*argv+2,"%s",flag_file_name); fflag=1; break; case 'l': /* turn off logarithmic input conversion option */ lflag=0; break; case 'm': /* turn off mean-zero output option */ mflag=0; break; case 't': sscanf(*argv+2,"%f",&th_percentage); if(th_percentage<0.0) error("bad threshold percentage"); tflag=1; break; case 'i': sscanf(*argv+2,"%d",&iter); if(iter<0||MAXITER max) max = (*p); if (*p < min) min = (*p); } for (p=y,pend=y+area; pMAXCHAR) { scale(nbits-1); max = ((max+1)>>1); } } #define TMAX 256 #define TOP_INPUT_INTENSITY 256 log_scale(lflag,tflag) char lflag,tflag; { long log_table[TMAX]; /* temporary log conversion look up table */ double CONST; register long *p; register long i; if(!lflag){ nbits=0; if(tflag) th = ((int) th_percentage); /* set threshold option */ return(0); } /* 2^11 constant ensures discrimination between log values */ /* obtained from adjacent input levels: because without */ /* any mult-factor range would be 0 .. 8 */ nbits = 6; /* 11 + 3 - 8 */ /* global variable */ if(tflag) th=((int) ( (TOP_INPUT_INTENSITY<MAXSIZE) error("picture to big"); area = asize*asize; for (p=x,pend=x+area; p127) *p = 127; else if(*p<-128) *p = -128; } } scale(n) /* scale x,rij to n+8 bits */ { register long s, *ptop; register long *p,*q; s=n-nbits; nbits=n; if (s>0) { for (p=x,q=rij,ptop=x+area; p>s); *q++ = (*q>>s); } } } /* constants for connect threshold make_Rij and adjust*/ #define dirNNE 01 #define dirNEE 02 #define dirES 04 #define dirSSW 010 #define dirSWW 020 #define dirWN 040 #define bearN (dirWN|dirNNE) #define bearE (dirNEE|dirES) #define bearS (dirES|dirSSW) #define bearW (dirSSW|dirWN) #define bearNE (dirNNE|dirNEE) #define bearSW (dirSSW|dirSWW) #define offN (-asize) #define offNE (1-asize) #define offE 1 #define offS asize #define offSW (asize-1) #define offW (-1) connect() { register char *conp; long i; /* initialise conflag. all 6 adjacent exist. */ for (i=0,conp=conflag;i++th) #define gd ((g_down) >th) functional() { long *p; register char *conp; long i; float F=0,G=0; /* Functional and sigma |E|^2 */ for (i=0,p=x,conp=conflag;i++minchange); i++) { a=adjust(); if ((!sflag)&&!(i % freq)) fprintf(stderr,"%9ld%1s", a, (i%(5*freq) ? " " : "\n")); } if((!sflag)&&(i % (5*freq))) fprintf(stderr,"\n"); if(!sflag) fprintf(stderr,"total iterations: %d\n\n",i-1); }