├── README.md ├── __pycache__ └── _stack.cpython-36.pyc ├── _stack.py ├── demo ├── demo1.jpg ├── demo2.jpg ├── demo3.jpg ├── demo4.jpg └── demo5.jpg ├── growSeed.py ├── growSeed_bbox.py ├── growSeed_filter.py └── img ├── lena.jpg ├── rice.jpg ├── test1.bmp ├── test2.bmp ├── test3.jpg └── xray.jpg /README.md: -------------------------------------------------------------------------------- 1 | # 种子生长算法代码 2 | 3 | ### 算法步骤: 4 | 5 | 1.对图像顺序扫描,找到第一个还没有标记的像素,设该像素为`(x0,y0)`,若之前已有k类,则标记`(x0,y0)`为第k+1类,并把`(x0,y0)`压入堆栈`stack` 6 | 7 | 2.,从堆栈中取出一个像素当做`(x0,y0)`,以`(x0,y0)`为中心考虑`(x0,y0)`的8领域(或者4领域)的像素`(x,y)`,如果`(x,y)`与`(x0,y0)`像素值在一定范围内,把`(x,y)`也标记为第k+1类,并把`(x,y)`压入堆栈`stack` 8 | 9 | 3.重复执行步骤2直到堆栈为空,当堆栈为空时,返回到步骤1 10 | 11 | 4.重复执行步骤1-3直到图像中的每个点都被标记,生长结束。 12 | 13 | ### 使用方法: 14 | 15 | 1.img中是测试图片 16 | 17 | 2.growseed.py可以演示种子生长的具体流程 18 | 19 | 3.growseed_filter.py添加了面积的计算,其中面积小于`threshold`的会被过滤掉,最终输出一个随机颜色类别表示的标记图片 20 | 21 | 4.**本代码只适合灰度图像** 22 | 23 | ### 示例图片: 24 | 25 | 输入二值图像 26 | 27 | ![输入二值图像](demo/demo1.jpg) 28 | 29 | ![](demo/demo2.jpg) 30 | 31 | 输出面积过滤后的图像 32 | 33 | 34 | 35 | ![](demo/demo3.jpg) 36 | 37 | ![](demo/demo4.jpg) 38 | 39 | 40 | 41 | 用于车牌检测 42 | 43 | ![](demo/demo5.jpg) 44 | 45 | 46 | ### Enjoy Yourself! 47 | ======= -------------------------------------------------------------------------------- /__pycache__/_stack.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/__pycache__/_stack.cpython-36.pyc -------------------------------------------------------------------------------- /_stack.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | * @Author: ZQ.Pei 4 | * @Date: 2018-06-03 16:59:39 5 | * @Last Modified by: ZQ.Pei 6 | * @Last Modified time: 2018-06-03 16:59:39 7 | ''' 8 | 9 | class Stack(object): 10 | def __init__(self): 11 | self._item = [] 12 | 13 | def push(self, value): 14 | self._item.append(value) 15 | 16 | def pop(self): 17 | return self._item.pop() 18 | 19 | def size(self): 20 | return len(self._item) 21 | 22 | def is_empty(self): 23 | return True if self.size() == 0 else False 24 | 25 | def empty(self): 26 | self._item = [] 27 | 28 | 29 | -------------------------------------------------------------------------------- /demo/demo1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/demo/demo1.jpg -------------------------------------------------------------------------------- /demo/demo2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/demo/demo2.jpg -------------------------------------------------------------------------------- /demo/demo3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/demo/demo3.jpg -------------------------------------------------------------------------------- /demo/demo4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/demo/demo4.jpg -------------------------------------------------------------------------------- /demo/demo5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/demo/demo5.jpg -------------------------------------------------------------------------------- /growSeed.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | * @Author: ZQ.Pei 4 | * @Date: 2018-06-03 16:59:35 5 | * @Last Modified by: ZQ.Pei 6 | * @Last Modified time: 2018-06-03 16:59:35 7 | ''' 8 | 9 | from _stack import Stack 10 | import cv2 11 | import numpy as np 12 | import time 13 | 14 | 15 | class GrowSeedAlgo(object): 16 | ''' 17 | only for binary image 18 | ''' 19 | def __init__(self, im=None, im_path=None): 20 | self.stack = Stack() 21 | 22 | if im is not None: 23 | self.im = im 24 | elif im_path is not None: 25 | self.imread(im_path) 26 | else: 27 | raise ValueError("No Input image!") 28 | 29 | 30 | self.im_size = self.im.shape 31 | self.im_height, self.im_width = self.im_size 32 | self.im_label = np.full_like(self.im, 0) 33 | #import ipdb; ipdb.set_trace() 34 | self.max_label = 0 35 | 36 | 37 | 38 | 39 | def imread(self, img_path): 40 | self.im_path = im_path 41 | self.im = cv2.imread(im_path) 42 | 43 | 44 | def start(self): 45 | for x0 in range(self.im_height): 46 | for y0 in range(self.im_width): 47 | if self.im_label[x0,y0] == 0 and self.im[x0,y0] != 0: # self.im[x0,y0]!=0 get rid of background 48 | self.max_label += 1 49 | self.im_label[x0,y0] = self.max_label 50 | self.stack.push((x0,y0)) 51 | while not self.stack.is_empty(): 52 | x,y = self.stack.pop() 53 | self.grow(x,y) 54 | cv2.imshow('growseed',self.im_label/self.max_label) 55 | cv2.waitKey(0) 56 | 57 | def grow(self, x0,y0): 58 | current_label = self.im_label[x0,y0] 59 | for x,y in self._get_neighbour(x0,y0): 60 | if self.im_label[x,y] == 0 and self.im[x,y] == self.im[x0,y0]: # threshold 61 | self.im_label[x,y] = current_label 62 | self.stack.push((x,y)) 63 | 64 | 65 | #print((self.im_label/self.max_label).shape) 66 | #cv2.imshow('growseed',self.im_label/self.max_label) 67 | #cv2.waitKey(1) 68 | 69 | def _get_neighbour(self, x0, y0): 70 | neighbour = [] 71 | for i in (-1,0,1): 72 | for j in (-1,0,1): 73 | if (i,j) == (0,0): 74 | continue 75 | x = x0+i 76 | y = y0+j 77 | if self._in_region(x,y): 78 | neighbour.append((x,y)) 79 | return neighbour 80 | 81 | def _in_region(self, x,y): 82 | return True if 0<=x125)*255).astype(np.uint8)[:,:] 95 | #cv2.imshow('bin_im',bin_im) 96 | #cv2.waitKey(0) 97 | 98 | gs = GrowSeedAlgo(im=bin_im) 99 | gs.start() 100 | 101 | if __name__ == '__main__': 102 | main() -------------------------------------------------------------------------------- /growSeed_bbox.py: -------------------------------------------------------------------------------- 1 | from _stack import Stack 2 | import cv2 3 | import numpy as np 4 | 5 | 6 | class GrowSeedAlgo(object): 7 | ''' 8 | only for binary image 9 | ''' 10 | def __init__(self, im=None, im_path=None): 11 | self.stack = Stack() 12 | 13 | if im is not None: 14 | self.im = im 15 | elif im_path is not None: 16 | self.imread(im_path) 17 | else: 18 | raise ValueError("No Input image!") 19 | 20 | 21 | self.im_height, self.im_width = self.im.shape 22 | self.im_label = np.full_like(self.im, 0, dtype=int) 23 | self.im_area = self.im.size 24 | 25 | self.max_label = 0 26 | self.label_area = {} 27 | self.label_color = {} 28 | 29 | 30 | def imread(self, img_path): 31 | self.im_path = im_path 32 | self.im = cv2.imread(im_path) 33 | 34 | def output(self, threshold=0.05): 35 | im_out = np.zeros_like(self.im) 36 | im_out = np.stack((im_out,im_out,im_out),axis=2) 37 | for label_idx in range(1,self.max_label+1): 38 | if self.label_area[label_idx]/self.im_area > threshold: # areas smaller than threshold will be treated as background!!! 39 | rand_color = np.random.randint(0,255),np.random.randint(0,255),np.random.randint(0,255) 40 | im_out[np.where(self.im_label==label_idx)]=rand_color 41 | 42 | self.label_color[label_idx] = rand_color 43 | 44 | #cv2.imshow('output',im_out) 45 | #cv2.waitKey(0) 46 | 47 | def drawBbox(self, threshold=0.05): 48 | im_out = self.im.copy() 49 | im_out = im_out[:,:,np.newaxis].repeat(3, axis=2) 50 | for label_idx in range(1,self.max_label+1): 51 | if self.label_area[label_idx]/self.im_area > threshold: # areas smaller than threshold will be treated as background!!! 52 | ys, xs = np.where(self.im_label==label_idx) 53 | xmin = xs.min() 54 | xmax = xs.max() 55 | ymin = ys.min() 56 | ymax = ys.max() 57 | #print(xmin,ymin,xmax,ymax) 58 | 59 | rand_color = self.label_color[label_idx] 60 | cv2.rectangle(im_out, (xmin,ymin), (xmax,ymax), rand_color, 2) 61 | 62 | 63 | cv2.imshow('bbox', im_out) 64 | cv2.waitKey(100) 65 | 66 | cv2.waitKey(0) 67 | 68 | 69 | def start(self): 70 | for x0 in range(self.im_height): 71 | for y0 in range(self.im_width): 72 | if self.im_label[x0,y0] == 0 and self.im[x0,y0] != 0: # ignoring the background 73 | self.max_label += 1 74 | self.im_label[x0,y0] = self.max_label 75 | self.stack.push((x0,y0)) 76 | tmp_area = 1 # tmp_area is the area of growned region in this round 77 | while not self.stack.is_empty(): 78 | x,y = self.stack.pop() 79 | #if self.max_label == 256: 80 | #import ipdb; ipdb.set_trace() 81 | tmp_area += self.grow(x,y) 82 | 83 | self.label_area[self.max_label] = tmp_area 84 | 85 | #print(self.max_label) 86 | #cv2.imshow('growseed',self.im_label/self.max_label) 87 | #cv2.waitKey(1) 88 | 89 | threshold = 0 90 | self.output(threshold) 91 | self.drawBbox(threshold) 92 | 93 | def grow(self, x0,y0): 94 | tmp = 0 95 | current_label = self.im_label[x0,y0] 96 | for x,y in self._get_neighbour(x0,y0): 97 | if self.im_label[x,y] == 0 and self.im[x,y] == self.im[x0,y0]: # threshold 98 | self.im_label[x,y] = current_label 99 | self.stack.push((x,y)) 100 | tmp += 1 101 | #cv2.imshow('growseed',self.im_label/self.max_label) 102 | #cv2.waitKey(1) 103 | return tmp 104 | 105 | def _get_neighbour(self, x0, y0): 106 | neighbour = [] 107 | for i in (-1,0,1): 108 | for j in (-1,0,1): 109 | if (i,j) == (0,0): 110 | continue 111 | x = x0+i 112 | y = y0+j 113 | if self._in_region(x,y): 114 | neighbour.append((x,y)) 115 | return neighbour 116 | 117 | def _in_region(self, x,y): 118 | return True if 0<=x128)*255).astype(np.uint8) 127 | 128 | # sometimes background is white not black 129 | # random sample a few points, to decide whether to inverse the picture 130 | num_random_pts = 100 131 | np.random.seed(10) 132 | random_sample_pts = [np.random.choice(bin_im.shape[0], num_random_pts), np.random.choice(bin_im.shape[1], num_random_pts)] 133 | inverse = True if np.mean(bin_im[random_sample_pts]) > 128 else False 134 | if inverse: 135 | bin_im = 255 - bin_im 136 | 137 | #cv2.imshow('bin_im',bin_im) 138 | #cv2.waitKey(0) 139 | 140 | gs = GrowSeedAlgo(im=bin_im) 141 | gs.start() 142 | 143 | if __name__ == '__main__': 144 | main() -------------------------------------------------------------------------------- /growSeed_filter.py: -------------------------------------------------------------------------------- 1 | from _stack import Stack 2 | import cv2 3 | import numpy as np 4 | 5 | 6 | class GrowSeedAlgo(object): 7 | ''' 8 | only for binary image 9 | ''' 10 | def __init__(self, im=None, im_path=None): 11 | self.stack = Stack() 12 | 13 | if im is not None: 14 | self.im = im 15 | elif im_path is not None: 16 | self.imread(im_path) 17 | else: 18 | raise ValueError("No Input image!") 19 | 20 | 21 | self.im_size = self.im.shape 22 | self.im_height, self.im_width = self.im_size 23 | self.im_label = np.full_like(self.im, 0).astype(np.int) 24 | 25 | self.max_label = 0 26 | self.label_area = {} 27 | 28 | 29 | def imread(self, img_path): 30 | self.im_path = im_path 31 | self.im = cv2.imread(im_path) 32 | 33 | def output(self, threshold=20): 34 | im_out = np.zeros_like(self.im) 35 | im_out = np.stack((im_out,im_out,im_out),axis=2) 36 | for label_idx in range(1,self.max_label+1): 37 | if self.label_area[label_idx] > threshold: # areas smaller than threshold will be treated as background!!! 38 | rand_color = np.random.randint(0,255),np.random.randint(0,255),np.random.randint(0,255) 39 | im_out[np.where(self.im_label==label_idx)]=rand_color 40 | 41 | cv2.imshow('output',im_out) 42 | cv2.waitKey(0) 43 | 44 | 45 | def start(self): 46 | for x0 in range(self.im_height): 47 | for y0 in range(self.im_width): 48 | if self.im_label[x0,y0] == 0 and self.im[x0,y0] != 0: # ignoring the background 49 | self.max_label += 1 50 | self.im_label[x0,y0] = self.max_label 51 | self.stack.push((x0,y0)) 52 | tmp_area = 1 # tmp_area is the area of growned region in this round 53 | while not self.stack.is_empty(): 54 | x,y = self.stack.pop() 55 | tmp_area += self.grow(x,y) 56 | 57 | self.label_area[self.max_label] = tmp_area 58 | #cv2.imshow('growseed',self.im_label/self.max_label) 59 | #cv2.waitKey(0) 60 | 61 | self.output(threshold=20) 62 | 63 | def grow(self, x0,y0): 64 | tmp = 0 65 | current_label = self.im_label[x0,y0] 66 | for x,y in self._get_neighbour(x0,y0): 67 | if self.im_label[x,y] == 0 and self.im[x,y] == self.im[x0,y0]: # threshold 68 | self.im_label[x,y] = current_label 69 | self.stack.push((x,y)) 70 | tmp += 1 71 | #cv2.imshow('growseed',self.im_label/self.max_label) 72 | #cv2.waitKey(1) 73 | return tmp 74 | 75 | def _get_neighbour(self, x0, y0): 76 | neighbour = [] 77 | for i in (-1,0,1): 78 | for j in (-1,0,1): 79 | if (i,j) == (0,0): 80 | continue 81 | x = x0+i 82 | y = y0+j 83 | if self._in_region(x,y): 84 | neighbour.append((x,y)) 85 | return neighbour 86 | 87 | def _in_region(self, x,y): 88 | return True if 0<=x>>>>>> ab20c84e6e259e3ac15ddd06471245e451442ffe 98 | #cv2.imshow('ori_im',ori_im) 99 | #cv2.waitKey(0) 100 | bin_im = ((ori_im>125)*255).astype(np.uint8) 101 | #cv2.imshow('bin_im',bin_im) 102 | #cv2.waitKey(0) 103 | 104 | gs = GrowSeedAlgo(im=bin_im) 105 | gs.start() 106 | 107 | if __name__ == '__main__': 108 | main() 109 | -------------------------------------------------------------------------------- /img/lena.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/img/lena.jpg -------------------------------------------------------------------------------- /img/rice.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/img/rice.jpg -------------------------------------------------------------------------------- /img/test1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/img/test1.bmp -------------------------------------------------------------------------------- /img/test2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/img/test2.bmp -------------------------------------------------------------------------------- /img/test3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/img/test3.jpg -------------------------------------------------------------------------------- /img/xray.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZQPei/Seeded-Region-Growing-Algorithm/2214b5c68a3d83c7b1665464b6e0f6a6065db16b/img/xray.jpg --------------------------------------------------------------------------------