原文链接:https://blog.csdn.net/sgzqc/article/details/119682864

一、简介

  区域增长法是一种已受到计算机视觉界十分关注的图像分割方法。它是以区域为处理对象的,它考虑到区域内部和区域之间的同异性,尽量保持区域中像素的临近性和一致性的统一。这样就可以更好地分辨图像真正的边界。

  基于区域的分割方法的关键在于定义一个一致性准则,用来判断两个邻接的区域是否可以合并,一致则将两区域合并,直到不能合并为止。区域增长的方法是在图像上选定一个种子点,记录下该点的灰度值,作为一致性判断的标准阈值,此外还需要定义一个标准差。
算法的主要过程是,依次用图像的每一个像素的灰度值和标准阈值相减,判断结果是否小于标准差,是则将该点和种子点合并,不是则保持像素点的灰度值不变。这样处理后的图像就是用区域分割法处理后的边缘分割图像。

二、实例

下面我们通过一个例子来进行详细的解释

  上图示意的是区域增长的过程,图中的方格表示图像的像素点,方格中的数值表示像素点的灰度值。(a)表示开始选取的生长点,在生长的过程中,每个生长点都将本身上下左右4个像素点和初试选取的生长点比较灰度值,如果灰度值的差的绝对值在设定的阈值内,则认为这些点是属于相同区域并将其合并,否则将灰度差大于设定阈值的点删除,重复检查区域内的像素点,直到没有像素点可以合并位置。不妨设上图的阈值为2,(b)中4个点和初始点的灰度差都不大于2,所以合并;(c)中只有部分满足条件,所以只合并满足条件的像素点,并且(c)区域周围邻域中没有点再满足条件,因此生长结束。

三、算法步骤

通过上述示例,我们可以总结出区域增长法的一般步骤如下:
1)对图像自上而下,自左而右扫描,找到第1个还没有访问过的像素, 设该像素为(x0, y0);
2)以(x0, y0)为中心, 考虑(x0, y0)的8邻域像素(x, y),如果其邻域满足生长准则, 将(x, y)与(x0, y0)合并(在同一区域内), 同时将(x, y)压入堆栈;
3)从堆栈中取出一个像素, 把它当作(x0, y0)返回到上一步骤;
4)当堆栈为空时 返回到步骤1;
5)重复步骤1 - 4直到图像中的每个点都被访问过时,算法结束。

四、代码实现

1 读入彩色图像

img_name = "test.jpg"
img = cv2.imread(img_name)

结果如下:

2 灰度化

gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

结果如下:

3 二值化

def get_binary_img(img):
# gray img to bin image
bin_img = np.zeros(shape=(img.shape), dtype=np.uint8)
h = img.shape[0]
w = img.shape[1]
for i in range(h):
for j in range(w):
bin_img[i][j] = 255 if img[i][j] > 127 else 0
return bin_img
# 调用
bin_img = get_binary_img(gray_img)

结果如下:

4 选取初始种子点

  这里选择三个种子点作为初始点,种子点的坐标如下图紫色十字所示。

out_img = np.zeros(shape=(bin_img.shape), dtype=np.uint8)
# 选择初始3个种子点
seeds = [(176,255),(229,405),(347,165)]
for seed in seeds:
x = seed[0]
y = seed[1]
out_img[y][x] = 255

5 区域增长结果

# 8 邻域
directs = [(-1,-1), (0,-1), (1,-1), (1,0), (1,1), (0,1),(-1,1),(-1,0)]
visited = np.zeros(shape=(bin_img.shape), dtype=np.uint8)
while len(seeds):
seed = seeds.pop(0)# 将元素从列表中删弹出,默认最后一个
x = seed[0]
y = seed[1]
# visit point (x,y)
visited[y][x] = 1
for direct in directs:
cur_x = x + direct[0]
cur_y = y + direct[1]
# 非法
if cur_x <0 or cur_y<0 or cur_x >= w or cur_y >=h :
continue
# 没有访问过且属于同一目标
if (not visited[cur_y][cur_x]) and (bin_img[cur_y][cur_x]==bin_img[y][x]) :
out_img[cur_y][cur_x] = 255
visited[cur_y][cur_x] = 1
seeds.append((cur_x,cur_y))

结果如下:

6 获取目标

  以上步得到的二值图作为mask,去彩色图中取对应的部分即可。代码如下:

bake_img = img.copy()
h = bake_img.shape[0]
w = bake_img.shape[1]
for i in range(h):
for j in range(w):
if out_img[i][j] != 255:
bake_img[i][j][0] = 0
bake_img[i][j][1] = 0
bake_img[i][j][2] = 0

结果如下:

7 完整代码

通过区域增长法来提取前景目标

# -*- coding:utf-8 -*-
import cv2
import numpy as np def get_binary_img(img):
# gray img to bin image
bin_img = np.zeros(shape=(img.shape), dtype=np.uint8)
h = img.shape[0]
w = img.shape[1]
for i in range(h):
for j in range(w):
bin_img[i][j] = 255 if img[i][j] > 80 else 0
return bin_img
img_name = "test.jpg"
img = cv2.imread(img_name)
h = img.shape[0]
w = img.shape[1]
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 调用
bin_img = get_binary_img(gray_img)
out_img = np.zeros(shape=(bin_img.shape), dtype=np.uint8)
# 选择初始3个种子点
seeds = [(176,255),(229,205),(307,165)]
for seed in seeds:
x = seed[0]
y = seed[1]
out_img[y][x] = 255
# 8 邻域
directs = [(-1,-1), (0,-1), (1,-1), (1,0), (1,1), (0,1),(-1,1),(-1,0)]
visited = np.zeros(shape=(bin_img.shape), dtype=np.uint8)
while len(seeds):
seed = seeds.pop(0)
x = seed[0]
y = seed[1]
# visit point (x,y)
visited[y][x] = 1
for direct in directs:
cur_x = x + direct[0]
cur_y = y + direct[1]
# 非法
if cur_x <0 or cur_y<0 or cur_x >= w or cur_y >=h :
continue
# 没有访问过且属于同一目标
if (not visited[cur_y][cur_x]) and (bin_img[cur_y][cur_x]==bin_img[y][x]) :
out_img[cur_y][cur_x] = 255
visited[cur_y][cur_x] = 1
seeds.append((cur_x,cur_y))
bake_img = img.copy()
h = bake_img.shape[0]
w = bake_img.shape[1]
for i in range(h):
for j in range(w):
if out_img[i][j] != 255:
bake_img[i][j][0] = 0
bake_img[i][j][1] = 0
bake_img[i][j][2] = 0 cv2.imshow('image',img)
cv2.imshow('rowgrow',bake_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

通过设置阈值来控制生长条件

# -*- coding:utf-8 -*-
import cv2
import numpy as np def get_binary_img(img):
# gray img to bin image
bin_img = np.zeros(shape=(img.shape), dtype=np.uint8)
h = img.shape[0]
w = img.shape[1]
for i in range(h):
for j in range(w):
bin_img[i][j] = 255 if img[i][j] > 150 else 0
return bin_img
img_name = "test.jpg"
img = cv2.imread(img_name)
h = img.shape[0]
w = img.shape[1]
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print(gray_img ) # 调用
# bin_img = get_binary_img(gray_img)
out_img = np.zeros(shape=(gray_img.shape), dtype=np.uint8)
# 选择初始3个种子点
seeds = [(276,155)]
for seed in seeds:
x = seed[0]
y = seed[1]
out_img[y][x] = 255
# 8 邻域
directs = [(-1,-1), (0,-1), (1,-1), (1,0), (1,1), (0,1),(-1,1),(-1,0)]
visited = np.zeros(shape=(gray_img.shape), dtype=np.uint8)
while len(seeds):
seed = seeds.pop(0)
x = seed[0]
y = seed[1]
# visit point (x,y)
visited[y][x] = 1
for direct in directs:
cur_x = x + direct[0]
cur_y = y + direct[1]
# 非法
if cur_x <0 or cur_y<0 or cur_x >= w or cur_y >=h :
continue
# 没有访问过且属于同一目标
if (not visited[cur_y][cur_x]) and (abs(int(gray_img[cur_y][cur_x])-int(gray_img[y][x]))<5.0) :
out_img[cur_y][cur_x] = 255
visited[cur_y][cur_x] = 1
seeds.append((cur_x,cur_y))
bake_img = img.copy()
h = bake_img.shape[0]
w = bake_img.shape[1]
for i in range(h):
for j in range(w):
if out_img[i][j] != 255:
bake_img[i][j][0] = 0
bake_img[i][j][1] = 0
bake_img[i][j][2] = 0 cv2.imshow('rowgrow',bake_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Python图像分割之区域增长法的更多相关文章

  1. python操作mysql数据库增删改查的dbutils实例

    python操作mysql数据库增删改查的dbutils实例 # 数据库配置文件 # cat gconf.py #encoding=utf-8 import json # json里面的字典不能用单引 ...

  2. python字典dict的增、删、改、查操作

    ## python字典dict的增.删.改.查操作dict = {'age': 18, 'name': 'jin', 'sex': 'male', }#增# dict['heigh'] = 185 # ...

  3. ​​​​​​​ARCGIS API for Python进行城市区域提取

    ​ArcGIS API for Python主要用于Web端的扩展和开发,提供简单易用.功能强大的Python库,以及大数据分析能力,可轻松实现实时数据.栅格数据.空间数据等多源数据的接入和GIS分析 ...

  4. 使用Python实现子区域数据分类统计

    目录 前言 geopandas简介 子区域数据分类统计 总结 一.前言        最近碰到一个需求,需要统计某省内的所有市的某数据分布情况信息.现有该省的数据分布情况以及该省的行政区划数据.我通过 ...

  5. python学习(list增删改查、及常用方法)

    1.Python多条件判断: 多条件判断if: passelse: pass循环 while for i = 0 while i > 1: print('hello') else: print( ...

  6. python 为什么没有自增自减符

    >>> b = 5 >>> a = 5 >>> id(a) 162334512 >>> id(b) 162334512 > ...

  7. python中字典的‘增、删、改、查’

    python 字典的'增.删.改.查' 用 ipython 运行情况如下: #新建字典 In [1]: infos = {'name':'dongge','age':18} In [2]: infos ...

  8. Python之注册表增删改查(干货)

    在Windows平台下,对注册表的增删改查的需求比较多,微软提供了很多用于访问,修改注册表等的API,我们可以使用诸如bat,或者C++等各种方式去访问修改注册表.无所不能的python下如何完成这些 ...

  9. Python实现mysql数据库增删改查

    利用python操作mysql数据库用法简单,环境配置容易,本文将实现对库增.删.改.查的简易封装!   1. 环境配置 安装第三方包  ,导入模块 mysql.connector  pip inst ...

随机推荐

  1. tp phpexcel 导入后台访问方法

    public function addall(){ $Water = M('Waterrate'); $config = array( 'maxSize' => 0, 'rootPath' =& ...

  2. 文件包含 & LFI-labs靶场

    文件包含漏洞学习 冲冲冲,好好学习 2020.1.30 认真对待自己做出的每一个决定 知识与实践 Q:什么是文件包含? A:简单一句话,为了更好地使用代码的重用性,引入了文件包含函数,可以通过文件包含 ...

  3. 浅析php环境配置

    PHP作为开源的服务器端脚本语言,在web应用方面非常广泛.如果你想下载某些开源应用,github上php开源软件选择往往比Java还多.最近,研究了linux下php的安装,主要有以下体会. PHP ...

  4. noip模拟测试22

    考试总结:这次考试题,有好多部分分,导致了我在考试过程中一心想拿到这些部分分,对于正解没有留出时间进行思考,这是一个教训,在以后的考试中我一定要留出足够的思考时间,不要被部分分限制.还有,我的部分分也 ...

  5. expect命令和here document免交互

    目录 一.Here Document免交互 1.1 概述 1.2 语法格式 1.3 简单案例 1.4 支持变量替换 1.5 多行注释 1.6 完成自动划分磁盘免交互 二.Expect进行免交互 2.1 ...

  6. Android达到什么水平才能顺利拿到 20k 无压力?

    程序员分很多种类和等级,如果要提高达到20k的概率,有两个条件如果满足的话,则很容易达到: 1.一线城市:北上广深杭 2.互联网行业 如果你非得抬杠,我要在三线城市,做外包要赚20k的话,很难,我自己 ...

  7. 【笔记】衡量线性回归法的指标 MSE,RMS,MAE以及评价回归算法 R Square

    衡量线性回归法的指标 MSE,RMS,MAE以及评价回归算法 R Square 衡量线性回归法的指标 对于分类问题来说,我们将原始数据分成了训练数据集和测试数据集两部分,我们使用训练数据集得到模型以后 ...

  8. Linux部署Redis服务器

    一,Redis介绍 Redis如今已经成为Web开发社区最火热的内存数据库之一,随着Web2.0的快速发展,再加上半结构数据比重加大,网站对高效性能的需求也越来越多. 而且大型网站一般都有几百台或者更 ...

  9. 题解 queen(留坑)

    传送门 博客园突然打不开了,奇奇怪怪的-- 少写个等号没看出来 nm写反了没看出来 考完5min全拍出来了 手残属性加持 不对拍等于爆零 yysy,我连卢卡斯定理的存在都忘了-- 发现要让一大堆皇后能 ...

  10. 项目报错:Invalid bound statement (not found):

    出现这种错误有好多种情况,常见的错误有以下这些: 1.检查xml文件所在package名称是否和Mapper interface所在的包名 <mapper namespace="com ...