├── test_image.jpg ├── test_result.jpg ├── README.md └── contour detection.py /test_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RajdeepMondal/Contour-Detection/HEAD/test_image.jpg -------------------------------------------------------------------------------- /test_result.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RajdeepMondal/Contour-Detection/HEAD/test_result.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Contour-Detection 2 | This is an implementation of the contour detection algorithm proposed in the paper Topological Structural Analysis of Digitized Binary Images by Border Following by Suzuki and Abe 1985. 3 | The function raster_scan() requires a zero-padded binary input image. 4 | The outputs are the contour coordinates, hierarchy of the contours and the corresponding border types. The images are assumed to be four-connected. 5 | # Results 6 | ![](test_image.jpg) 7 | ![](test_result.jpg) 8 | -------------------------------------------------------------------------------- /contour detection.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import ast 3 | # four-connected case 4 | """ 5 | Direction Reference: 6 | 7 | 1 8 | | 9 | | 10 | 2 <- - | - -> 0 11 | | 12 | | 13 | 3 14 | """ 15 | def next_cell(curr_pixel,curr_dir): 16 | i,j=curr_pixel 17 | save=None 18 | if curr_dir==0: 19 | r=i-1 20 | c=j 21 | new_dir=1 22 | save=[i,j+1] 23 | elif curr_dir==1: 24 | r=i 25 | c=j-1 26 | new_dir=2 27 | elif curr_dir==2: 28 | r=i+1 29 | c=j 30 | new_dir=3 31 | elif curr_dir==3: 32 | r=i 33 | c=j+1 34 | new_dir=0 35 | return r,c,new_dir,save 36 | 37 | def border_follow(img,start,prev,direction,NBD): 38 | curr=list(start) 39 | exam=list(prev) 40 | save=None 41 | save2=list(exam) 42 | contour=[] 43 | contour.append(list(curr)) 44 | while img[exam[0]][exam[1]]==0: 45 | exam[0],exam[1],direction,save_pixel=next_cell(curr,direction) 46 | if save_pixel!=None: 47 | save=list(save_pixel) 48 | if save2==exam: 49 | img[curr[0],curr[1]]=-NBD 50 | return contour 51 | if save!=None: 52 | img[curr[0]][curr[1]]=-NBD 53 | save=None 54 | elif (save==None or (save!=None and img[save[0]][save[1]]!=0)) and img[curr[0]][curr[1]]==1: img[curr[0]][curr[1]]=NBD 55 | else: pass 56 | prev=list(curr) 57 | curr=list(exam) 58 | contour.append(list(curr)) 59 | if direction>=2: direction=direction-2 60 | else: direction=2+direction 61 | flag=0 62 | start_next=list(curr) 63 | while True: 64 | if not(curr==start_next and prev==start and flag==1): 65 | flag=1 66 | exam[0],exam[1],direction,save_pixel=next_cell(curr,direction) 67 | if save_pixel!=None: 68 | save=list(save_pixel) 69 | while img[exam[0]][exam[1]]==0: 70 | exam[0],exam[1],direction,save_pixel=next_cell(curr,direction) 71 | if save_pixel!=None: 72 | save=list(save_pixel) 73 | if save!=None and img[save[0]][save[1]]==0: 74 | img[curr[0]][curr[1]]=-NBD 75 | save=None 76 | elif (save==None or (save!=None and img[save[0]][save[1]]!=0)) and img[curr[0]][curr[1]]==1: img[curr[0]][curr[1]]=NBD 77 | else: pass 78 | prev=list(curr) 79 | curr=list(exam) 80 | contour.append(list(curr)) 81 | if direction>=2: direction=direction-2 82 | else: direction=2+direction 83 | else: 84 | break 85 | return contour 86 | 87 | def raster_scan(img): 88 | rows,cols=img.shape 89 | LNBD=1 90 | NBD=1 91 | contours=[] 92 | parent=[] 93 | parent.append(-1) 94 | border_type=[] 95 | border_type.append(0) 96 | for i in range(1,rows-1): 97 | LNBD=1 98 | for j in range(1,cols-1): 99 | if img[i][j]==1 and img[i][j-1]==0: 100 | NBD+=1 101 | direction=2 102 | parent.append(LNBD) 103 | contour=border_follow(img,[i,j],[i,j-1],direction,NBD) 104 | contours.append(contour) 105 | border_type.append(1) 106 | if border_type[NBD-2]==1: parent.append(parent[NBD-2]) 107 | else: 108 | if img[i][j]!=1: LNBD=abs(img[i][j]) 109 | elif img[i][j]>=1 and img[i][j+1]==0: 110 | NBD+=1 111 | direction=0 112 | if img[i][j]>1: LNBD=img[i][j] 113 | parent.append(LNBD) 114 | contour=border_follow(img,[i,j],[i,j+1],direction,NBD) 115 | contours.append(contour) 116 | border_type.append(0) 117 | if border_type[NBD-2]==0: parent.append(parent[NBD-2]) 118 | else: 119 | if img[i][j]!=1: LNBD=abs(img[i][j]) 120 | return contours,parent,border_type 121 | 122 | img=np.array(ast.literal_eval(input())) 123 | contours,parent,border_type=raster_scan(img) 124 | print(contours) 125 | print(parent) 126 | print(border_type) 127 | --------------------------------------------------------------------------------