传统图像分割算法-基于区域的分割算法

这类方法按照图像的相似性准则划分不同的区域块。其中较为典型的方法优:种子区域生长法、分水岭法、区域分裂合并法。

种子区域生长法:首先通过一组表示不同区域的种子像素开始,逐步合并与种子周围相似的像素,从而扩大区域,直到无法合并像素点或者区域为止。这个相似性度量可以采用平均灰度值、纹理、颜色等信息。该方法的关键就是如何选择初始的种子像素以及生长准则。

区域分裂合并法:该方法首先要确定分裂合并的准则,然后对图像进行分裂(1->4;4->16...),直到相邻区域满足一致性特征时,将他们合并为一个大区域,直到所有区域不满足分裂合并准则为止。分裂的最差一种情况就是,分裂到单个像素级别,这就类似种子区域生长法了,合并与种子周围相似的像素。但是该方法不同于种子生长法,该方法可以从一个大的区域开始生长,而种子区域生长法只能从一个像素开始。

分水岭法:我们可以获取到图像中某个区域的中的最小灰度值(局部极小值),而这个像素点与周围的环境形成一个集水盆。而这个算法要做的就是不停的像这个集水盆中倒水,如果水位达到一定高度就会溢出,我们在这个溢出的位置修建堤坝。重复这个过程,知道图像中的所有点都被淹没,这时候所建立的堤坝就是分开各个盆地的分水岭。从而实现了图像的分割。该方法对于弱边缘有着较好的分割,但是图像中的噪声会造成过分割现象。

基于种子区域生长法Code实现:

 

import numpy as np
import cv2
#首先是区域生长一些函数的定义:
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

def getGrayDiff(img,currentPoint,tmpPoint):
    return abs(int(img[currentPoint.x,currentPoint.y]) - int(img[tmpPoint.x,tmpPoint.y]))

def selectConnects(p):
    if p != 0:
        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)]
    else:
        connects = [ Point(0, -1),  Point(1, 0),Point(0, 1), Point(-1, 0)]
    return connects

def regionGrow(img,seeds,thresh,p = 1):
    height, weight = img.shape
    seedMark = np.zeros(img.shape)
    seedList = []
    for seed in seeds:
        seedList.append(seed)
    label = 1
    connects = selectConnects(p)
    while(len(seedList)>0):
        currentPoint = seedList.pop(0)

        seedMark[currentPoint.x,currentPoint.y] = label
        for i in range(8):
            tmpX = currentPoint.x + connects[i].x
            tmpY = currentPoint.y + connects[i].y
            if tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= weight:
                continue
            grayDiff = getGrayDiff(img,currentPoint,Point(tmpX,tmpY))
            if grayDiff < thresh and seedMark[tmpX,tmpY] == 0:
                seedMark[tmpX,tmpY] = label
                seedList.append(Point(tmpX,tmpY))
    return seedMark

# 创建一个图像
image = np.ones((256, 256))
cv2.circle(image, (256//2, 256//2), int(100), (0,0,0), -1)
cv2.circle(image, (256//2, 256//2), int(50), (255,255,255), -1)
cv2.imwrite('test.png', 255*image)
# 分割中间白色部分
image_copy = image.copy()//255
seeds = [Point(256//2,256//2)]
binaryImg = regionGrow(image_copy,seeds,1)
cv2.imwrite('test1.png', 255 * binaryImg)

 结果:

原图 结果

 

 

 

 

 

posted @ 2022-10-31 16:57  九叶草  阅读(768)  评论(0编辑  收藏  举报