/* code for computing absolute distance function of a 2D shape */ /* the positon of the initial front and its position as it advances are marked as points on grid lines */ /* input: image: piecewise constant /* /* The boundary of the shape generically crosses gridlines between nodes */ /* output: absolute distance function */ #include #include #include #include #include #include #include #include #include #include #define MAX(A,B) (A>B) ? (A) : (B) #define MIN(A,B) (A=0) ? (A) : (-A) /* imagesizes: ccSchzSchz: 376H x 796W; sample count: 35 ccSchzNorms: 364H x 784W; sample count: 48 ccNorms: 324H x 780W; sample count: 20 ccKids : 400H x 896W; sample count: 30 ccDrugs: 324H x 708W; sample count: 14 */ #define sample_count 14 #define ydim 324 /* image height - dimension for i */ #define xdim 708 /* image width - dimension for j */ #define MaxDist 10000 typedef struct element { float dist; int row; int col; } HeapNode; FILE *infile,*outfile; char inname[128],outname[128],dir_name[128]; /* row and col are indices Tmat, not in pic */ unsigned char pic[ydim][xdim],outpic[ydim][xdim]; int length, heaplength; int IArray[ydim*xdim],JArray[ydim*xdim]; /* IArray and JArray store the coordinates of the bdry nodes the shape */ unsigned char Cmat[ydim][xdim]; int Bmat[ydim][xdim]; float dist[ydim][xdim],Tmat[ydim+2][xdim+2]; /* Cmat marks 'far' points as 3, 'close' or 'trial points' as 2 and 'accepted pts' as 1. far points = points not yet visited, trial points: points next to the front and outside the front. accepted pts = points inside the front. */ /* Bmat stores backpointer from the grid points to their index in the heap */ /* Tmat stores d-values (=time when the front arrives at the node) */ HeapNode H[ydim*xdim],TmpNode[1],Head[1]; /* Note that H,TmpNode and Head are pointers to HeapNode */ /* array for storing the heap. Note that heap index = array index +1 */ void calc_dist(); void upheap(HeapNode *,int, HeapNode *); void downheap(HeapNode *,int); void locateboundary(); float upwinddist(int,int); void calc_dist(); void output_results(); void run(); void calc_dist() { int i,j; int Iind, Jind,NIind,NJind,pos; /*Initialize */ for(i=0;i 0) if (Cmat[NIind-1][NJind-1] == 3) /* its d-value is unassigned */ { TmpNode->dist = upwinddist(NIind,NJind); TmpNode->row = NIind; TmpNode->col = NJind; Cmat[NIind-1][NJind-1] = 2; /* a new trial point */ upheap(H,heaplength,TmpNode); heaplength++; } /*North Neighbor*/ NIind = Iind-1; NJind = Jind; if(NIind > 0) if (Cmat[NIind-1][NJind-1] == 3) { TmpNode->dist = upwinddist(NIind,NJind); TmpNode->row = NIind; TmpNode->col = NJind; Cmat[NIind-1][NJind-1] = 2; upheap(H,heaplength,TmpNode); heaplength++; } /*East Neighbor*/ NIind = Iind; NJind = Jind+1; if(NJind <= xdim) if (Cmat[NIind-1][NJind-1] == 3) { TmpNode->dist = upwinddist(NIind,NJind); TmpNode->row = NIind; TmpNode->col = NJind; Cmat[NIind-1][NJind-1] = 2; upheap(H,heaplength,TmpNode); heaplength++; } /*South Neighbor*/ NIind = Iind+1; NJind = Jind; if(NIind <= ydim) if (Cmat[NIind-1][NJind-1] == 3) { TmpNode->dist = upwinddist(NIind,NJind); TmpNode->row = NIind; TmpNode->col = NJind; Cmat[NIind-1][NJind-1] = 2; upheap(H,heaplength,TmpNode); heaplength++; } } /*march the front forward */ while(heaplength>0) { *Head = *H; downheap(H,heaplength); heaplength--; Iind = Head->row; Jind = Head->col; Cmat[Iind-1][Jind-1] = 1; Tmat[Iind][Jind] = Head->dist; /*West Neighbor*/ NIind = Iind; NJind = Jind-1; if((NJind>0) && (Cmat[NIind-1][NJind-1]>1)) { TmpNode->dist = upwinddist(NIind,NJind); TmpNode->row = NIind; TmpNode->col = NJind; /*Update the heap*/ if (Cmat[NIind-1][NJind-1]==2) /*already a trial point*/ { pos = Bmat[NIind-1][NJind-1]; /* heap index of the point */ upheap(H,pos-1,TmpNode); /* pos-1 is the array index of the point */ } else { Cmat[NIind-1][NJind-1] = 2; upheap(H,heaplength,TmpNode); heaplength++; } } /*North Neighbor*/ NIind = Iind-1; NJind = Jind; if((NIind>0) && (Cmat[NIind-1][NJind-1]>1)) { TmpNode->dist = upwinddist(NIind,NJind); TmpNode->row = NIind; TmpNode->col = NJind; if (Cmat[NIind-1][NJind-1]==2) { pos = Bmat[NIind-1][NJind-1]; upheap(H,pos-1,TmpNode); } else { Cmat[NIind-1][NJind-1] = 2; upheap(H,heaplength,TmpNode); heaplength++; } } /*East Neighbor*/ NIind = Iind; NJind = Jind+1; if((NJind<=xdim) && (Cmat[NIind-1][NJind-1]>1)) { TmpNode->dist = upwinddist(NIind,NJind); TmpNode->row = NIind; TmpNode->col = NJind; if (Cmat[NIind-1][NJind-1]==2) { pos = Bmat[NIind-1][NJind-1]; upheap(H,pos-1,TmpNode); } else { Cmat[NIind-1][NJind-1] = 2; upheap(H,heaplength,TmpNode); heaplength++; } } /*South Neighbor*/ NIind = Iind+1; NJind = Jind; if((NIind<=ydim) && (Cmat[NIind-1][NJind-1]>1)) { TmpNode->dist = upwinddist(NIind,NJind); TmpNode->row = NIind; TmpNode->col = NJind; if (Cmat[NIind-1][NJind-1]==2) { pos = Bmat[NIind-1][NJind-1]; upheap(H,pos-1,TmpNode); } else { Cmat[NIind-1][NJind-1] = 2; upheap(H,heaplength,TmpNode); heaplength++; } } } for(i=0;i=1) d = w2+1; else d = (w1+w2+sqrt(2-(w1-w2)*(w1-w2)))/2; return d; } void upheap(HeapNode *init, int length,HeapNode *newnode) { /* init points to the root node. length = heap array index of the hole. heap index numbering starts at 1. (i.e. the numbering of tree nodes.) The index of the heap array = heap index - 1 */ /* For a heap structure, two objects are needed to describe it: the array of HeapNodes and the length of the array. length indicates where the upheap should begin, which means that at length+1 the heap array has hole and the upheap should begin there. The change of the number of nodes in the heap is maintained separately. We should not depend on either upheap or downheap to update it. So that the two function can be used flexibly. */ int flag,index,parentindex,Iind,Jind; index = length+1; /* heap index of the hole */ flag = 1; do{ parentindex = (int)floor(index/2); if(parentindex > 0) { if(newnode->dist<(init+parentindex-1)->dist) /* move the parent down */ { *(init+index-1) = *(init+parentindex-1); Iind = (init+parentindex-1)->row; Jind = (init+parentindex-1)->col; Bmat[Iind-1][Jind-1] = index; /* update backpointer */ index = parentindex; /* new location of the hole */ } else /* insert the newnode */ { *(init+index-1) = *newnode; Iind = newnode->row; Jind = newnode->col; Bmat[Iind-1][Jind-1] = index; flag = 0; } } else /* arrived at the root node */ { *(init+index-1) = *newnode; Iind = newnode->row; Jind = newnode->col; Bmat[Iind-1][Jind-1] = index; flag = 0; } } while(flag == 1); } void downheap(HeapNode *init,int length) /* downheap is called after removing the root node. */ { int index,Iind,Jind; index=1; /* heap index of the hole */ while(length>=2*index) /* not a leaf node */ { if(length>=(2*index+1)) /* both children present */ { if((init+2*index-1)->dist <= (init+2*index)->dist) /* left child smaller than right child, promote left */ { *(init+index-1) = *(init+2*index-1); Iind = (init+2*index-1)->row; Jind = (init+2*index-1)->col; Bmat[Iind-1][Jind-1] = index; /* update backpointer */ index = 2*index; /* new location of the hole */ } else /* promote right child */ { *(init+index-1) = *(init+2*index); Iind = (init+2*index)->row; Jind = (init+2*index)->col; Bmat[Iind-1][Jind-1] = index; index = 2*index+1; } } else /* only one child present, always on the left */ { *(init+index-1) = *(init+2*index-1); Iind = (init+2*index-1)->row; Jind = (init+2*index-1)->col; Bmat[Iind-1][Jind-1] = index; index = 2*index; } } if (index < length) /* hole at a leaf which is not the last leaf. insert the last leaf node here and then migrate upward */ upheap(init,index-1,init+length-1); } void output_results() { /* int i,j; float x,mx=0,mn=MaxDist+1,scale; for (i=0;i1) scale=255/x; else scale = 1; for (i=0;i