首页 > 编程语言 >区域生长算法与图像分割

区域生长算法与图像分割

时间:2023-05-07 23:24:06浏览次数:48  
标签:生长 分割 self cv2 像素 算法 区域 图像 grayImg

1. 区域生长

  区域生长是一种串行区域分割的图像分割方法。区域生长是指从某个像素出发,按照一定的准则,逐步加入符合相似性判据的邻近像素,当满足生长停止条件,区域生长终止。其中相似性判据可以是像素灰度值、颜色、纹理特征等图像信息。(另一种区域生长是先将图像分割成很多的一致性较强,如区域内像素灰度值相同的小区域,再按一定的规则将小区域融合成大区域,达到分割图像的目的)

2. 算法步骤 

  区域生长算法一般分为三个步骤:

  1. 确定生长种子点
  2. 规定生长准则
  3. 确定生长停止条件

  区域生长实现的步骤如下:

  1. 对图像顺序扫描,找到第1个还没有归属的像素, 设该像素为(x0, y0);

  2. 以(x0, y0)为中心, 考虑(x0, y0)的4邻域或者8邻域像素(x, y)如果(x0, y0)满足生长准则, 将(x, y)与(x0, y0)合并(在同一区域内), 同时将(x, y)压入堆栈;

  3. 从堆栈中取出一个像素, 把它当作(x0, y0)返回到步骤2;

  4. 当堆栈为空时,返回到步骤1;

  5. 重复步骤1 - 4直到图像中的每个点都有归属时。生长结束。

3.  常用生长准则 

  颜色距离相似度:欧式距离计算,用于计算两个像素点之间的颜色相似度,从而判断它们是否应该属于同一区域。对于当前区域中的每个像素点,如果其与邻近像素点的颜色相似度大于某个阈值,则将该邻近像素点加入当前区域。在灰度图像中常计算两个点的像素值之差或是计算已划分的区域的平均值与领域点的像素之差。

4.  算法过程理解

 

  假设现在我们生长区域为生长点的8邻域。规定生长准则为选取的种子点的像素值与遍历的点的像素值之差小于等于1,则划分为同一区域。下图中红色的为划分为了同一区域,加粗的红色数字为选取的种子点。

 5.  python实现

  4邻域的区域生长算法图片分割,生长准则为种子点与遍历点像素值之差小于某个阈值。自己拍的一个照片,效果如下:

                            

    python代码如下:

import cv2
import numpy as np

class RegionalGrowth:
    def __init__(self,imgPath):
        self.imgPath=imgPath

    def zh_cn(self,string):
        return string.encode("gbk").decode('UTF-8', errors='ignore')

    def showImg(self):
        #显示图片
        img=cv2.imread(self.imgPath)
        print(type(img.shape))
        window_name = self.zh_cn('图')
        cv2.namedWindow(window_name, 0)  # 为窗口定义名字
        cv2.resizeWindow(window_name, 736, 416)  # 设置窗口显示的大小:W、H
        cv2.imshow(window_name, img)  # 显示窗口的名字, 所要显示的图片
        cv2.waitKey(0)  # 等待参数为毫秒,参数为 0表示 无限等待
        cv2.destroyAllWindows()

def showGrayImg(self): # 显示图片 img = cv2.imread(self.imgPath) grayImg = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) # 灰度图Gray=0.299*R+0.587*G+0.114*B window_name ='CT' cv2.namedWindow(window_name, 0) # 为窗口定义名字 cv2.resizeWindow(window_name, 736, 416) # 设置窗口显示的大小:W、H cv2.imshow(window_name, grayImg ) # 显示窗口的名字, 所要显示的图片 cv2.imwrite(r'./images/ctgray.jpg',grayImg) cv2.waitKey(0) # 等待参数为毫秒,参数为 0表示 无限等待 cv2.destroyAllWindows() return grayImg def meanDiff(self,grayImg,seedMark): #计算同一区域的平均值与邻域的像素点之差 areaGrayImg=np.multiply(grayImg,seedMark)#同位置元素相乘 # areaSum=np.sum(areaGrayImg) # count=np.count_nonzero(areaGrayImg == 0) # meanArea=areaSum/count #或者直接使用np.mean meanArea=np.mean(areaGrayImg) return meanArea def regional_growth (self,grayImg,seeds,threshold=15,kind=0):#种子点与遍历点像素值之差小于某个阈值归并为同一区域 # 每次区域生长的时候的种子像素之间的八个邻接点 # connects = [(-1, -1), (0, -1), (1, -1), (1, 0), (1, 1),(0, 1), (-1, 1), (-1, 0)] connects = [ (0, -1), (1, 0), (0, 1), (-1, 0)]#4邻域 height, weight = grayImg.shape #得到图片像素的高与宽 seedMark = np.zeros(grayImg.shape)#初始化全为0,用来标记同一个区域 print(seedMark) seedList = [] for seed in seeds: seedList.append(seed) #选取种子开始生长,直到没有可以生长的种子 while(len(seedList)>0): #出栈一个种子 currentPoint=seedList.pop() #并将生长点对应seedMark点赋值1 seedMark[currentPoint[0],currentPoint[1]]=1 # 以种子点为中心,八邻域的像素进行比较 for i in range(4):#0~7 tmpX = currentPoint[0] + connects[i][0] tmpY = currentPoint[1] + connects[i][1] # 判断是否为图像外的点,若是则跳过。 如果种子点是图像的边界点,邻域点就会落在图像外 if tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= weight: continue # 判断邻域点和种子点的差值 if seedMark[tmpX, tmpY] == 0: #如果邻域点还未划分过 if kind==0: grayDiff = abs(int(grayImg[tmpX][tmpY])-int(grayImg[currentPoint[0]][currentPoint[1]])) if kind==1: grayDiff=abs(int(grayImg[tmpX][tmpY])-int(self.meanDiff(grayImg,seedMark))) #算区域内的平均值与领域点的差 # 归类 # 并作为下一个种子点放入seedList if grayDiff <= threshold: seedMark[tmpX, tmpY] = 1 seedList.append((tmpX, tmpY)) return seedMark if __name__ == '__main__': imgpath='./images/blue.jpg' rg=RegionalGrowth(imgpath) grayImg=rg.showGrayImg() seeds = [(973,996)]#初始种子 seedMarkBinary=rg.regional_growth(grayImg,seeds,2,0)#0表示使用种子点与邻域点比较,1表示选用区域平均值与邻域点比较 window_name = 'segment' cv2.namedWindow(window_name, 0) # 为窗口定义名字 cv2.resizeWindow(window_name, 736, 416) # 设置窗口显示的大小:W、H cv2.imshow(window_name, seedMarkBinary)#其中0 – 表示黑色, 1 – 表示白色 cv2.waitKey(0) cv2.destroyAllWindows()

6.   总结

  基于颜色相似度的区域生长可以应用于许多图像分割场景,例如医学图像分割、自然图像分割等。除了前面介绍的相似度生长准则,还有基于区域内灰度分布统计、基于区域形状等。另外,除了区域生长算法,还有OTSU算法、最大熵算法、自适应阈值法等都是基于阈值的分割算法。区域生长算法是一种计算量大,耗时长的算法。本文针对此图,也对区域的平均值与邻域点的差作为是否合并的尝试,通过调试不同的阈值,也未能达到好的效果,可能不同图片效果不同。

 

 参考资料:

https://huaweicloud.csdn.net/63807fcadacf622b8df891cc.html

https://blog.csdn.net/sinat_31608641/article/details/103228291

https://blog.csdn.net/weixin_43271137/article/details/130055631

https://blog.csdn.net/qq_42727880/article/details/108073661

若存在不足之处或错误之处,欢迎指正或评论!

标签:生长,分割,self,cv2,像素,算法,区域,图像,grayImg
From: https://www.cnblogs.com/wancy/p/17380386.html

相关文章

  • JS逆向 -- 某平台登录算法分析(RSA加密)
    一、输入账号密码,进行抓包二、F12打开开发者工具,抓包分析,password被加密了三、全局搜索password关键字,挨个分析,在箭头标记处找到了关键代码四、局部搜索,定位加密的关键点,通过JSEncrypt,setPublicKey等关键字分析是RSA加密五、代码编写1、调用RSA加密的基本代码编写functionaiyou(pw......
  • 扩展欧几里得算法
    扩展欧几里得算法前置条件:需要掌握裴蜀定理和欧几里得算法裴蜀定理:对于不全为0的整数a,b,一定有整数x,y,使得ax+by=gcd(a,b)欧几里得算法:gcd(a,b)==gcd(b,a%b)假设有组特解x0,y0,使得ax0+by0=gcd(a,b)则必有bx1+(a%b)y1=gcd(b,a%b)=gcd(a,......
  • 文心一言 VS chatgpt (15)-- 算法导论3.2 4~5题
    四、函数$\lceil\lgn\rceil!$多项式有界吗?函数$\lceil\lg\lgn\rceil!$多项式有界吗?文心一言:chatgpt:对于第一个问题,函数$\lceil\lgn\rceil!$是阶乘的形式,可以证明它是超多项式增长的,因此不是多项式有界的。对于第二个问题,函数$\lceil\lg\lgn\rceil!$......
  • 【算法基础】DFS深度优先算法 —— AcWing 843. n-皇后问题 AcWing 842. 排列数字
    n-皇后问题是一个经典的dfs深度优先遍历的题目,在题解这一题之前,将由浅入深,先讲解一个n-皇后问题的母题。-------AcWing842.排列数字 [AcWing842].排列数字题目概述给定一个整数 n,将数字 1∼n排成一排,将会有很多种排列方法。现在,请你按照字典序将所有的排列方法输出。输入格......
  • 文心一言 VS chatgpt (15)-- 算法导论3.2 4~5题
    四、函数多项式有界吗?函数多项式有界吗?文心一言:chatgpt:对于第一个问题,函数是阶乘的形式,可以证明它是超多项式增长的,因此不是多项式有界的。对于第二个问题,函数的增长速度比慢很多。虽然不是多项式,但是它是多项式有界的,也就是说,存在一个多项式和常数,使得当足够大时......
  • C语言基础算法
    1、计算Fibonacci数列Fibonacci数列又称斐波那契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21。C语言实现的代码如下:/* Displaying Fibonacci sequence up to nth term where n is entered by user. */#include <stdio.h>int main(){i......
  • 基于双目图像三维建模算法的测量目标物体体积计算matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:   2.算法涉及理论知识概要         双目立体视觉(BinocularStereoVision)是机器视觉的一种重要形式,它是基于视差原理并利用成像设备从不同的位置获取被测物体的两幅图像,通过计算图像对应点间的位置偏差,来获取物体三......
  • 高密度城市路线规划的遗传优化算法的matlab仿真,城市点数量达到500个
    1.算法仿真效果matlab2022a仿真结果如下:  2.算法涉及理论知识概要       遗传算法GA把问题的解表示成“染色体”,在算法中也即是以二进制编码的串。并且,在执行遗传算法之前,给出一群“染色体”,也即是假设解。然后,把这些假设解置于问题的“环境”中,并按适者生存的原......
  • 算法 | 快速排序详解
    1快速排序基本思想从待排序记录序列中选取一个记录(随机选取)作为基点,其关键字设为key,然后将其余关键字小于key的记录移到前面,而将关键字大于key的记录移到后面,结果将待排序记录序列分为两个子表,最后将关键字key的记录插入到分界线的位置。这个过程称为一趟快速排序。经过这一趟......
  • 基础算法
    位运算拆解:例如龟速乘和快速幂。状态压缩:可以用一个数字表示一个状态,不够长还可以用bitset。龟速乘通过对数字的每一位进行拆分,将乘法变成加法。代码#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;llmul(lla,llb,llp){ llans=0; while(b){ ......