⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccribbons.c

📁 Computing 2D Skeleton
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Program:  finds ribbon-like parts                        *//* TRACKS BRANCHES by following ridges of grd  */ /*  Problem: Does not handle triple points very well       *//* problem: cannot distinguish between short necks(# pixel = beta) and short protrusion; the program ignores both (see test().) Perhaps, both should be filled in as bdry pts because when two parts are separated by a very narrow neck, they might as well be treated as disjoint.  	Alternatively, if the branch can be continued from 	two ends, it is not a short protrusion. check if 	the complement of sk1 in a small nbhd of the complete 	skeleton is connected or not */  /* possible improvements:   it might be possible to simplify fill_gaps(). At present, to bridge a gap in sk1, it tracks along ridges of grd in sk2 in order to find a path along the gap with minimum cost. NOTE: We cannot simply track along sk2 in case there is a junction along the way. Nor can we trace gaps in sk1 by tracking values of v since, if a saddle point is missed, v will decrease towards the saddle point and then increase.  In prune(),if the branch is too long (here, >10 pixels), calculate the actual length by dividing the branch into tow segments as done in fill_gaps().   /*/* Assumes that image is piecewise constant                 *//*                                                          *//*                                                          *//* Inputs:  the image and the ABSOLUTE distance function    *//*                                                          *//*                                                          *//* Date:     August, 2002                                   *//*                                                          *//*                                                          */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <fcntl.h>#include <unistd.h>#include <sioux.h>#include <MacTypes.h>#include <Fonts.h>#include <math.h>#define ydim 364  /* vertical y-dimension: index i  */#define xdim 784  /* horizontal x-dimension:  index j  */#define upper_threshold 70#define middle_threshold 45#define lower_threshold 10/* (1) upper threshold = degree angle between 0 and 90                   = minimum angle that a chord must make                     with the tangent to shape bdry (2) middle threshold is used to create points bridging gaps in the skeleton obtained by thresholding at upper_threshold. If middle threshold is too high, it will miss some of the gaps. If it is too low,then it finds too many points going beyond the gap  (3) lower_threshold is used to constuct fairly full skeleton  which is then used to find the endpts of the branches of the skeleon obtained after bridging short gaps created by thresholding. */#define beta 2.01#define L 20/* beta is the cost of each connected component of sk1 *//* eliminates branches with number of pixels<=L if their costis beyond the threshold */ #define N 15 /* max size for local nbhd in ridge_gr()   *//* N must be odd */#define MAX(A,B) ((A)>(B) ? (A) : (B))#define MIN(A,B) ((A)>(B) ? (B) : (A))#define ABS(A) ((A)>=0 ? (A) : -(A))/* file names */FILE *infile,*outfile;char buf[64],buf1[64],buf2[64],inname[128];char d_name[128],outname[128];/* Program variables */unsigned char pic[ydim][xdim];unsigned char outsk[ydim][xdim];unsigned char outsgmt[ydim][xdim];unsigned char outgr[ydim][xdim];unsigned char sk[ydim][xdim];unsigned char sgmt[ydim][xdim];unsigned char nbhd_size[ydim][xdim];unsigned char bdry[ydim][xdim];unsigned char endpts[ydim][xdim];unsigned char tmp[ydim][xdim];int mark[2][ydim][xdim],branchcnt[2];int Iarray[2][xdim*ydim],Jarray[2][xdim*ydim],arr_len[2];float distance[xdim*ydim];int length[2][xdim*ydim];float cost[2][xdim*ydim];float v[ydim][xdim];float gr[ydim][xdim],grd[ydim][xdim];float tol[(N-1)/2],tol_d[(N-1)/2]; /* margin of error in angles */* global variables */int ibb,inn,jbb,jnn;void local_grad();void convert_gr();void ridge_gr();void construct_sk();void initialize_sk();void ave_cost(int,int);void confirm_endpts();void fill_gaps();void complete_sk();void prune();void connect(int,int,int,int,int);void segment();void output_results();void run();       void local_grad()   /*     CALCULATES grad USING 4 DIFFERENT WAYS:     given coordinates and then rotating it by angle    whose tangent equals 0.5,1 and 2   */       {      int i,j,k,i1,j1,i2,j2,i3,j3;      int count,flag;      double x,y,q,q1;             for (i=0;i<ydim;i++) for (j=0;j<xdim;j++)      {        if (bdry[i][j]>0) gr[i][j]=1;        else if (i*j*(ydim-1-i)*(xdim-1-j)==0) gr[i][j]=1;        else        {         ibb = i-1; inn = i+1; jbb = j-1; jnn = j+1;         flag=0;         k = pic[i][j];         i1=i;j1=jbb;         i2=ibb;j2=jbb;         i3=ibb;j3=j;         count=bdry[i1][j1]+bdry[i2][j2]+bdry[i3][j3];         if (count==3)         {           if (pic[i2][j2]==k) gr[i][j]=0.707107;           else gr[i][j]=1;           flag = 1;         }                  if (flag==0)         {           i1=i3;j1=j3;           i2=ibb;j2=jnn;           i3=i;j3=jnn;           count=bdry[i1][j1]+bdry[i2][j2]+bdry[i3][j3];           if (count==3)           {             if (pic[i2][j2]==k) gr[i][j]=0.707107;             else gr[i][j]=1;             flag = 1;           }         }                  if (flag==0)         {           i1=i3;j1=j3;           i2=inn;j2=jnn;           i3=inn;j3=j;           count=bdry[i1][j1]+bdry[i2][j2]+bdry[i3][j3];           if (count==3)           {             if (pic[i2][j2]==k) gr[i][j]=0.707107;             else gr[i][j]=1;             flag = 1;           }         }                  if (flag==0)         {           i1=i3;j1=j3;           i2=inn;j2=jbb;           i3=i;j3=jbb;           count=bdry[i1][j1]+bdry[i2][j2]+bdry[i3][j3];           if (count==3)           {             if (pic[i2][j2]==k) gr[i][j]=0.707107;             else gr[i][j]=1;             flag = 1;           }         }                          if (flag==0)         {           x = v[i][jnn]-v[i][jbb];           y = v[inn][j]-v[ibb][j];                    q = (x*x+y*y)/4;                   x = v[inn][jnn]-v[ibb][jbb];           y = v[inn][jbb]-v[ibb][jnn];           q1 = (x*x+y*y)/8;           if (q1<q) q = q1;                     x = (v[inn][jbb]+v[inn][j]-v[ibb][j]-v[ibb][jnn])/2;           y = (v[inn][jnn]+v[i][jnn]-v[i][jbb]-v[ibb][jbb])/2;           q1 = (x*x+y*y)/5;           if (q1<q) q = q1;                     x = (v[inn][jbb]+v[i][jbb]-v[i][jnn]-v[ibb][jnn])/2;           y = (v[inn][jnn]+v[inn][j]-v[ibb][j]-v[ibb][jbb])/2;           q1 = (x*x+y*y)/5;           if (q1<q) q = q1;                     if (q>1) q = 1;            if (q>0) gr[i][j] = sqrt(q);           else gr[i][j] = 0;         }         gr[i][j] = MIN(gr[i][j],1);        }      }   }               void ridge_gr() /* traveses the boundary pixels of NxN nbhds */ {    int i,j,m,n,k,kk,p,q;    int k0,k1,count;    int h,hh,H;    int flag,reset_flag,bdry_flag;    int ii[4*N-4],jj[4*N-4],check[4*N-4];    float v0,z,d[4*N-4];    float slope[4*N-4],last,now,next;    float grx,grmn,accept;        local_grad(); /* makes a rough estimate of ridge_gr */                       /* tends to be more accurate near jcns */         for (i=0;i<ydim;i++) for (j=0;j<xdim;j++) nbhd_size[i][j]=1;        h = (N-1)/2;    H = 8*h;    for (p=-h;p<h+1;p++) for (q=-h;q<h+1;q++)    if ((p+h)*(p-h)*(q+h)*(q-h)==0)    {      k = p+q+2*h;      if (p-q>0) k = H-k;      z = p*p+q*q;      d[k] = sqrt((double) z); /* distance from the origin */      ii[k] = p; jj[k] = q;     }            /* begin scanning */    for (i=h;i<ydim-h;i++) for (j=h;j<xdim-h;j++)    if (bdry[i][j]==0)  if (gr[i][j]<0.99)     {               /* adjust the nbhd size to avoid bdry */     reset_flag = 0;     do     {/* printf("h=%d\n",h);*/       bdry_flag = 0;       hh = h+1;       for (m=i-hh;m<i+hh+1;m++) for (n=j-hh;n<j+hh+1;n++)          if (bdry[m][n]>0) bdry_flag = 1;   /*  if (bdry[m][n]>0){printf("bdry pt at (%d %d), v=%f\n",m,n,v[m][n]);flag=1;} */       if (bdry_flag>0) {h--, reset_flag=1;}     }     while ((bdry_flag>0)&&(h>1));                    if (bdry_flag==0)      {        nbhd_size[i][j] = h;       if (reset_flag>0) /* recalculate nbhd geometry */       {         H = 8*h;         for (p=-h;p<h+1;p++) for (q=-h;q<h+1;q++)         if ((p+h)*(p-h)*(q+h)*(q-h)==0)         {           k = p+q+2*h;           if (p-q>0) k = H-k;           z = p*p+q*q;           d[k] = sqrt((double) z); /* distance from the origin */           ii[k] = p; jj[k] = q;          }       }              /* calculate directional gradients */      /* direction points from the  perimeter to the center (i,j) */        v0 = v[i][j];       for (m=i-h;m<i+h+1;m++) for (n=j-h;n<j+h+1;n++)       if ((m-i+h)*(m-i-h)*(n-j+h)*(n-j-h)==0)       /* scans only the perimeter of the nbhd */       {          p = m-i; q = n-j;          k = p+q+2*h;          if (p-q>0) k = H-k;          slope[k] = (v0-v[m][n])/d[k];       }              /* find local maxima of slopes around the nbhd perimeter */       for (k=0;k<H;k++) check[k]=0;       last = slope[H-1];       now = slope[0];       z = -2; /* z tracks value of global max */       for (k=0;k<H;k++)       {         next = slope[(k+1)%H];         if (now-last>0) if (now-next>0) /* local max */         {           check[k] = 1; /* mark the direction */           if (now>z) {z = now; kk = k;} /* current global max */         }         last = now; now = next;       } /*  if (i==442) if (j==369)  *//* if (i>286) if (i<289) if (j==103) *//* {  printf("\nat (%d %d), nbhd: %d\n",i,j,h);   for (k=0;k<H;k++) if (check[k]>0)printf("k:%d (%d %d),gr:%f,chk:%d\n",k,ii[k],jj[k],slope[k],check[k]);  }*/      /* calculate cosine of angles between successive maximal rays */        accept=(h-1)/sqrt((double) h*h+0.25); /* Maximal rays should have slope of 1; but due to inaccuarcy in slopes, arising because the maximal rays may be off the grid line contributing error factor of h/sqrt(h*h+.5*.5) and because the point (i,j) may be off the ridge contributing the factor (h-1)/h, accept if the slope > (h-1)/sqrt((double) h*h+0.25) */       count = 0; /* number of maximal rays */       grmn = 1;       /* grmn tracks minimum value; */             if (z>accept) /* first ray to shape bdry */       {        k0 = kk;        for (k=kk;k<kk+H;k++)        if ((k%H)==k0)        {          k0 = k%H;  /* current ray */          flag = 0;          /* find next ray to shape bdry */          for (q=1;q<H;q++)           {            if (check[(k+q)%H]>0) /* is local max */            if (slope[(k+q)%H]>accept)             {              flag = 1;              count++;              k1 = (k+q)%H; /* next ray */              break;            }            }                  if (flag>0) /* calc ridge gradient */          {            grx = (ii[k0]*ii[k1]+jj[k0]*jj[k1])/(d[k0]*d[k1]);            grx = ABS(1+grx)/2;            if (grx>0.0001) grx = sqrt((double) grx);            if (grx<grmn)  grmn=grx;            /* if (i==442) if (j==369)printf("(%d %d) k0 %d k1 %d, kk %d gr %f %f\n",i,j,k0,k1,count,grx,gr[i][j]); */            k0 = k1; /* new current ray */                               } /* else k0 remains unchanged */        }       }       if (count>=2) if (grmn<gr[i][j]) gr[i][j]=grmn;       /* if count<2; the point (i,j) is not on the ridge */      }     if (reset_flag>0)     {       h = (N-1)/2;       H = 8*h;       for (p=-h;p<h+1;p++) for (q=-h;q<h+1;q++)       if ((p+h)*(p-h)*(q+h)*(q-h)==0)       {         k = p+q+2*h;         if (p-q>0) k = H-k;         z = p*p+q*q;         d[k] = sqrt((double) z); /* distance from the origin */         ii[k] = p; jj[k] = q;       }     }   }     convert_gr();/*  p=364; q=294;  for (i=p-1;i<p+2;i++) for (j=q-1;j<q+2;j++)printf("grd(%d %d)=%f\n",i,j,grd[i][j]);  */   }   void convert_gr() /* converts gr to angle in degrees */ /* removes skeleton points too near the bdry and bear small angles */ {   int i,j,h;   float x;      h = (N-1)/2;   for (j=2;j<=h;j++)   {     tol[j] = atanf((float) (0.5/j));     tol_d[j] =  57.2958*tol[j];   }   tol[1] = tol[2];   tol_d[1]=tol_d[2];      /* convert to angle that the chord makes with   tangent to shape bdry (radians) */   for (i=0;i<ydim;i++) for (j=0;j<xdim;j++)   {      x = acosf(gr[i][j]);            /* threshold weak edges */      h = nbhd_size[i][j];      if (h==1)      if (x<tol[h]) x = 0;            /* convert to degrees */      grd[i][j] = 57.2958*x;    } }               void construct_sk() {    initialize_sk();     fill_gaps();    complete_sk();    prune(); /*    segment(); */ }       void initialize_sk()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -