前言:
继续前几天的工作,对图像处理工作进行改进,同时学习新的图像处理算法。今天学习了种子区域生长法图像分割算法。
正文:
基本思想:
区域生长的基本思想是将具有相似性质的像素集合起来构成区域。具体先对每个需要分割的区域找一个种子像素作为生长起点,然后将种子像素和周围邻域中与种子像素有相同或相似性质的像素(根据某种事先确定的生长或相似准则来判定)合并到种子像素所在的区域中。将这些新像素当作新的种子继续上面的过程,直到没有满足条件的像素可被包括进来。这样一个区域就生长成了。
简单来说下三个法则,对出需要分割的图像:
1、选取图像中的一点为种子点(种子点的选取需要具体情况具体分析)。
2、在种子点处进行8邻域或4邻域扩展,判定准则是:如果考虑的像素与种子像素灰度值差的绝对值小于某个门限T,则将该像素包括进种子像素所在的区域。
3、当不再有像素满足加入这个区域的准则时,区域生长停止。
区域生长实现的步骤如下:
1. 对图像顺序扫描!找到第1个还没有归属的像素, 设该像素为(x0, y0);
2. 以(x0, y0)为中心, 考虑(x0, y0)的8邻域像素(x, y),如果(x,, y)满足生长准则, 将(x, y)与(x0, y0)合并(在同一区域内), 同时将(x, y)压入堆栈;
3. 从堆栈中取出一个像素, 把它当作(x0, y0)返回到步骤2;
4. 当堆栈为空时!返回到步骤1;
代码如下:
import cv2
import numpy as np
#import Image
im = cv2.imread('8888.jpg')
im_shape = im.shape
height = im_shape[0]
width = im_shape[1]
class Point(object):
def __init__(self , x , y):
self.x = x
self.y = y
def getX(self):
return self.x
def getY(self):
return self.y
connects = [ Point(-1, -1), Point(0, -1), Point(1, -1), Point(1, 0), Point(1, 1), Point(0, 1), Point(-1, 1), Point(-1, 0)]
def get_dist(seed_location1,seed_location2):
l1 = im[seed_location1.x , seed_location1.y]
l2 = im[seed_location2.x , seed_location2.y]
count = np.sqrt(np.sum(np.square(l1-l2)))
return count
img_mark = np.zeros([height , width])
img_re = im.copy()
for i in range(height):
for j in range(width):
img_re[i, j][0] = 0
img_re[i, j][1] = 0
img_re[i, j][2] = 0
seed_list = []
seed_list.append(Point(10, 10))
T = 7#阈值
class_k = 1#类别
#生长一个类
while (len(seed_list) > 0):
seed_tmp = seed_list[0]
seed_list.pop(0)
img_mark[seed_tmp.x, seed_tmp.y] = class_k
for i in range(8):
tmpX = seed_tmp.x + connects[i].x
tmpY = seed_tmp.y + connects[i].y
if (tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= width):
continue
dist = get_dist(seed_tmp, Point(tmpX, tmpY))
#在种子集合中满足条件的点进行生长
if (dist < T and img_mark[tmpX, tmpY] == 0):
img_re[tmpX, tmpY][0] = im[tmpX, tmpY][0]
img_re[tmpX, tmpY][1] = im[tmpX, tmpY][1]
img_re[tmpX, tmpY][2] = im[tmpX, tmpY][2]
img_mark[tmpX, tmpY] = class_k
seed_list.append(Point(tmpX, tmpY))
cv2.imshow('OUTIMAGE' , img_re)
cv2.waitKey(0)