2017-06-16 11:39:29 llh_1178 阅读数 20426

我们在处理图像的时候,常常需要将图像的前景和背景做不同的处理,这时需要将前景和背景分割开。关于图像分割的方法我知道的有三种方法:K-means、分水岭和GrabCut算法进行物体分割。不能够肯定的比较出谁优谁劣,各种算法是分各种场合以及设定参数的优化。在此,只是简单介绍,学习之路任重而道远!

K-means方法进行分割:

它是一种最常用的聚类算法。因为,人们不需要手动的为数据集里的每个个体添加标签,能自动的发现集群结构,进行分类。是一种无监督的学习。那么是什么定义了集群的呢?答案是通过中心和形状定义的。然后,通过打分判断依据是:在这个集群中的分数高于在其他聚类中的分数和与本集群中心点比其他集群中心点更相似。具体的步骤是:首先,把观测分配给最近的中心点。然后,把集群中心点修改为被分配给原中心点观测的均值,反复这两步操作,直到全部收敛。

关于OpenCV下的kmean算法,函数为cv2.kmeans()
函数的格式为:kmeans(data, K, bestLabels, criteria, attempts, flags)

其中,K(分类数)和 attempts(Kmeans算法重复次数)是需要根据具体的图像进行优化的参数。像bestLabels预设分类标签可以不需要用None表示,criteria为迭代停止的模式选择,格式为(type,max_iter,epsilon),其中type又有两种选择:cv2.TERM_CRITERIA_EPS :精确度(误差)满足epsilon停止和cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过max_iter停止,也可以两者结合,满意任意一个就结束。而flags(初始类中心选择),有两种方法:cv2.KMEANS_PP_CENTERS ; cv2.KMEANS_RANDOM_CENTERS

下面,就尝试一下修改K(分类数)和 attempts(Kmeans算法重复次数)参数进行测试。

先将K设为默认值,调attempts次数。

# 以灰色导入图像
img = cv2.imread('messi5.jpg',0)#image read be 'gray'
plt.subplot(221),plt.imshow(img,'gray'),plt.title('original')
plt.xticks([]),plt.yticks([])

# 改变图像的维度
img1 = img.reshape((img.shape[0]*img.shape[1],1))
img1 = np.float32(img1)

# 设定一个criteria,
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,10,1.0)

# 设定一个初始类中心flags
flags = cv2.KMEANS_RANDOM_CENTERS
# 应用K-means
compactness,labels,centers = cv2.kmeans(img1,2,None,criteria,5,flags)
compactness_1,labels_1,centers_1 = cv2.kmeans(img1,2,None,criteria,10,flags)
compactness_2,labels_2,centers_2 = cv2.kmeans(img1,2,None,criteria,15,flags)
img2 = labels.reshape((img.shape[0],img.shape[1]))
img3 = labels_1.reshape((img.shape[0],img.shape[1]))
img4 = labels_2.reshape((img.shape[0],img.shape[1]))
plt.subplot(222),plt.imshow(img2,'gray'),plt.title('kmeans_attempts_5')
plt.xticks([]),plt.yticks([])
plt.subplot(223),plt.imshow(img3,'gray'),plt.title('kmeans_attempts_10')
plt.xticks([]),plt.yticks([])
plt.subplot(224),plt.imshow(img4,'gray'),plt.title('kmeans_attempts_15')
plt.xticks([]),plt.yticks([])
plt.savefig("kmeans_attempts.png")
plt.show()



可以看出attempts次数不同,是会造成图像分割差异的。

再来调K值,这里将attempts次数设为10.得到的图像为:


也可以看出K初始值不同,同样造成图像分割差异。所以,可以说这两个参数的优化是很重要的,但是,也不容易优化。看下一种方法:

分水岭算法

之所以叫分水岭算法,是因为它里面有“水”的概念。把图像中低密度的区域(变化很少)想象成山谷,图像中高密度的区域(变化很多)想象成山峰。开始向山谷中注入水直到不同的山谷中的水开始汇集。为了阻止不同山谷的水汇聚,可以设置一些栅栏,最后得到的栅栏就是图像分割。

img = cv2.imread("water_coins.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将颜色转变为灰色之后,可为图像设一个阈值,将图像二值化。
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
# 下面用morphologyEx变换来除去噪声数据,这是一种对图像进行膨胀之后再进行腐蚀的操作,它可以提取图像特征:
kernel = np.ones((3,3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations= 2)
# 通过对morphologyEx变换之后的图像进行膨胀操作,可以得到大部分都是背景的区域:
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 接着通过distanceTransform来获取确定前景区域,原理是应用一个阈值来决定哪些区域是前景,越是远离背景区域的边界的点越可能属于前景。
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
# 考虑前景和背景中有重合的部分,通过sure_fg和sure_bg的集合相减得到。
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
# 现在有了这些区域,就可以设定“栅栏”来阻止水汇聚了,这通过connectedComponents函数来完成
ret, markers = cv2.connectedComponents(sure_fg)
# 在背景区域上加1, 这会将unknown区域设置为0:
markers = markers + 1
markers[unknown==255] = 0
# 最后打开门,让水漫起来并把栅栏绘成红色
markers = cv2.watershed(img, markers)
img[markers == -1] = [255, 0, 0]
plt.imshow(img), plt.xticks([]),plt.yticks([])
plt.show()



能够看出还是能大多数完整分割。

接下来介绍GrabCut算法进行对图像的分割处理。

使用GrabCut算法的实现步骤为:
1)在图片中定义含有(一个或多个)物体的矩形
2)矩形外的区域被自动认为是背景
3)对于用户定义的矩形区域,可用背景中的数据来区别它里面的前景和背景区域
4)用高斯混合模型(GMM)来对背景和前景建模,并将末定义的像素标记为可能的前景或背景
5)图像中的每一个像素都被看作通过虚拟边与周围像素相连接,而每一条边都有一个属于前景或背景的概率,这基于它与周围像素颜色上的相似性
6)每一个像素会与一个前景或背景节点连接。若节点之间不属于同一个终端(就是两个相邻的节点,一个节点属于前景,一个节点属于背景),则会切断它们之间的边,这就将图像各个部分分割出来了。

import numpy as np
import cv2
from matplotlib import pyplot as plt

# 首先加载图片,然后创建一个与所加载图片同形状的掩模,并用0填充。
img = cv2.imread("messi5.jpg")
mask = np.zeros(img.shape[:2], np.uint8)

# 然后创建以0填充的前景和背景模型:
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
# 在实现GrabCut算法前,先用一个标识出想要隔离的对象的矩形来初始化它,这个矩形我们用下面的一行代码定义(x,y,w,h):
rect = (100, 50, 421, 378)
# 接下来用指定的空模型和掩摸来运行GrabCut算法
#mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) # 5是指算法的迭代次数。
# 然后,我们再设定一个掩模,用来过滤之前掩模中的值(0-3)。值为0和2的将转为0,值为1和3的将转化为1,这样就可以过滤出所有的0值像素(背景)。
mask2 = np.where((mask==2)|(mask==0), 0, 1).astype("uint8")
img = img * mask2[:, :, np.newaxis]
# 最后可视化展现分割前后的图像
plt.subplot(1, 2, 1)
plt.imshow(img)
plt.title("grabcut"), plt.xticks([]), plt.yticks([])

plt.subplot(1, 2, 2)
plt.imshow(cv2.imread("messi5.jpg"))
plt.title("original"), plt.xticks([]), plt.yticks([])
plt.savefig("grabcut.png")



可以看出来分割的并不完整,而且头发和手都没有被区分到前景中来,这是因为,在设定矩形的时候需要不断优化的,且因每一张图像都有差异,所以矩形的范围也是有差异的。还好在github上找到了一个grabcut算法脚本,能完美的解决这个问题。并用他的代码进行测试。如下图:





参考:

《OpenCV3计算机视觉Python语言实现》

OpenCV帮助文档:

http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_grabcut/py_grabcut.html

https://github.com/opencv/opencv/blob/master/samples/python/grabcut.py


2019-07-02 22:08:48 qq_37486501 阅读数 157

数字图像处理中的图像分割

  1. 图像分割: 将图像分割成若干个互不相交的区域
  2. 基于灰度的不连续性
    (1): 边缘检测
    [
    基于一阶微分的各种梯度算子:
    基于二阶微分的拉普拉斯算子
    高斯-拉普拉斯算子(LOG算子): 用高斯平滑去噪, 用拉普拉斯进行边缘检测
    ]
    (2):轮廓提取与跟踪
    轮廓提取: 掏空内部点, 背景白前景黑, 从左上角扫描为“黑”=0, 且8邻域也都为黑, 则说明该像素点是目标物体内部点, 置”白“=1
    轮廓跟踪: 顺序地找出目标区域边界上的像素点, 以跟踪目标边界, 并且同时记录边界信息(边界链码)
    (3):Hough变换
  3. 基于灰度的相似性
    (1):灰度阈值分割:
    用一个或者几个灰度阈值T 将图像的灰度级范围分成几个部分, 将每个像素的灰度值和阈值相比较, 根据比较结果将像素归类——前景目标与背景区分开
    (2): 基于区域的分割
    [
    区域生长: 灰度相似则扩展
    区域的分裂与合并 : 按某种一致性准则, 不断分裂, 合并区域
    ]
2017-01-05 10:07:28 sinat_36164665 阅读数 5366

图像分割

图像分割,广义来说,是根据图像的某些特征或特征集合例如灰度、颜色、纹理等的相似性准则对图像像素进行分组聚类,把图像平面划分成若干个具有某些一致性的不重叠区域。这使得同一区域中的像素特征是类似的,即具有一致性而不同区域间像素的特征存在突变,即具有非一致性。

条件(1)指出在对一幅图像的分割结果中全部子区域的总和并集应能包括图像中所有像素就是原图像,或者说分割应将图像中的每个像素都分进某个子区域中。

条件(2)指出在分割结果中各个子区域是互不重叠的,或者说在分割结果中一个像素不能同时属于两个区域。

条件(3)指出在分割结果中每个子区域都有独特的特性,或者说属于同一个区域中的像素应该具有某些相同特性。

条件(4)指出在分割结果中,不同的一子区域具有不同的特性,没有公共元素,或者说属于不同区域的像素应该具有一些不同的特性。

条件(5)要求分割结果中同一个子区域内的像素应该是连通的,即同一个子区域内的任意两个像素在该子区域内互相连通,或者说分割得到的区域是一个连通组元。最后需要指出的是,实际应用中图像分割不仅要把一幅图像分成满足上面五个条件的各具特性的区域而且需要把其中感兴趣的目标区域提取出来,只有这样才算真正完成了图像分割的任务。

图像分割方法主要分为:基于边缘检测的图像分割方法,基于区域的图像分割方法和基于特定理论的图像分割方法。

一、基于边缘检测的图像分割方法

边缘是指其周围像素灰度有阶跃变化的像素的集合,边缘检测技术可以按照处理的顺序分为并行边缘检测和串行边缘检测。

1.1图像分割算法评价

偏差法和优度法

偏差法一般需要提供一个理想分割图像作为比较标准,依此来计算实际分割结果与理想分割图像的差别,这种差别可以是基于错误分割像素点的位置,也可以是基于错误分割的像素数等。 

优度法一般是建立在人的视觉基础上,以某些图像特征为依据来评价分割效果。优度法在没有正确分割的先验知识的情况下,仅仅根据分割图像计算某种优度量值来评价分割算法的好坏。

目前常用的有区域一致性、区域对比度、区域形状参数等

(1)区域一致性

  

 

(4)综合评价函数

由于图像信息是复杂的,有时用一种测量参数无法准确衡量分割图像的质量,将几种测量参数综合考虑,根据图像分割的目的对不同测量参数赋予不同的权值,以得到准确的评价结果。在这里采用下面的综合评价函数                
2018-11-26 17:01:05 qq_40980917 阅读数 1823

电子科技大学 格拉斯哥学院 2017级谭茗珊
1.背景:
医学图像分割技术的发展是一个从人工分割到半自动分割和自动分割的逐步发展过程。早期的图像分割完全是靠人工完成的。完全的人工分割方法是在原始图像上直接画出期望的边界。这种方法费时费力,分割结果完全依赖于分割者的解剖知识和经验,而且分割结果难以再现;半自动的分割方法大大减少了人为因素的影响,而且分割速度快,分割精度高,但操作者的知识和经验仍然是图像分割过程的一个重要组成部分。近年来,由于大量的新兴技术如模糊技术和人工智能技术在图像分割中的应用,图像分割领域中也涌现出一些自动的分割技术。自动分割方法能完全脱离人为干预,由计算机实现医学图像分割的全过程。由于自动分割方法的运算量较大,目前大部分的自动分割方法都是在工作站上实现的。
2.摘要:
医学图像处理中图像分割是最具挑战性和最富有挑战性的课题,结构分析,运动分析,三维可视化等一系列操作均是以准确的图像分割为基础。由于医学影像设备成像技术的特点,使得图像存在噪声,导致图像中目标物体部分边缘不清晰,给图像分割造成一定难度。通过运用ITK-SNAP软件对图像进行预处理,使用python并搭建tensorflow环境,对图像加以训练和测试,不断改进算法改进现有MRI脑肿瘤图像分割算法,利用模糊C均值算法、区域增长算法、以及结合模糊相似度理论和区域结构识别技术的分割算法实现脑肿瘤MRI图像的分割,使其能够对图像进行准确识别,定性,定量分析,结果的准确性依据分割评价体系得以判断。

3.图像分割处理
3.1非线性平滑处理
由于磁共振图像在采集过程中,有脉冲干扰,因此图像具有较强的噪声,为了消除噪声,选用非线性平滑中值滤波预处理图片;
中值滤波是一种去除噪声的非线性处理方法。其基本思想是把数字图像中一点的值在该点的一个领域中各值的中值替代。
3.2全局阈值分割
一般图像分割是基于图像二值化的基础上进行的,其目的是可减少图像的灰度分布范围,简化运算,从而大大提高分割速度。
但如遇到特殊情况,例如脑部的头骨,高密度,灰度值高,处于亮区域,而我们感兴趣的区域(肿瘤)的灰度是软组织,灰度值低,处于暗区域。而肿瘤周围的软组织也是灰度值低的暗区域,与肿瘤的区别很小。此时,原始方法已不再能分辨。所以在程序中,必须舍弃。现有的二值化自动分割函数,改为手动的全局阈值分割。通过观察,设置特定的阈值点,从而进行有效手动分割,将处于亮区域的头骨和其他组织分割开,又保留了其他组织的原有特性。将其作为预处理图像

3.3肿瘤分割
经过手动的全局阈值分割后的图片,虽然消除了头骨的部分,但由于我们感兴趣的部分(肿瘤)并没有从周围组织里面分割出来,因此还需要进一步的处理。由于肿瘤和周围的组织灰度值比较接近,我们分别选用最大方差阈值法和形态学两种方法来处理。
3.3.1最大方差阈值法分割
最大方差阈值也叫大津阈值,他是在差别域最小二乘法原理的基础上推导出来的,不管是图像的直方图有无明显的双峰,此方法都能取得很好的效果。其原理是把直方图在某一阈值处分割成为两组,当被分成的两组间的方差为最大时,决定阈值。
3.3.2形态学分割
区域生长的基本思想是将具有相似性质的像素结合起来构成区域,具体是先对每个需要分割的区域找一个种子像素作为生长起点,然后将种子像素周围区域中与种子像素有相同或相似性质的像素种子合并到种子像素所在区域中,将这些新像素当作种子像素继续进行上面的过程,直到再也没有满足条件的像素可以被包括进来,这样,一个区域就生成了。经实验显示,采用形态学进行分割之后,脑部的肿瘤可以清晰地显示出来,但与此同时一些血管同时也显示出来了。
具体的算法步骤为:
求出图像的梯度;
采用圆形结构元素执行形态学开操作运算;
进行腐蚀运算;
采用圆形结构元素执行形态学闭运算操作;
进行膨胀运算;
经过开闭运算后,图像进行重建;
将重建的图像叠加在原有图像上。

4.结论:
由于医学图像的复杂多样性和分割问题的困难性,通常针对某项任务选用合适的算法,目前没有一个分割方法能适用于不同的任务,医学图像的分割方法有很多,最常用的方法是阈值分割法和形态学分割法。但通常,直接采用普通的阈值分割和形态学分割法,很难提取到满意的目标图像。本文分别对这两种方法稍作改进,采用图像阈值法时,先进行手动的阈值分割,然后再使用最大方差阈值法,效果更好;采用形态学分割时,圆形结构元素作为种子,也得到了目标图像。因此尽管医学图像分割比较复杂,只要灵活采用图像分割方法,可以得到比较满意的分割图像。

5.参考文献
[1]李彦东.卷积神经网络研究综述
[2]田捷.医学图像与医学分析[M].
[3]陈灵娜.一种新的肝肿瘤CT图像分割方法[J]
[4]马子睿.基于数字形态学的医学图像分割研究方法[J]
[5]俞海平.MRI脑肿瘤图像分割与矩特征研究[J]

2015-03-10 20:37:45 TonyShengTan 阅读数 2477


学习DIP第59天
转载请标明本文出处:http://blog.csdn.net/tonyshengtan ,出于尊重文章作者的劳动,转载请标明出处!文章代码已托管,欢迎共同开发:https://github.com/Tony-Tan/DIPpro
更多图像处理机器学习内容请访问最新网站www.faceai.com
#开篇废话
废话开始,今天本来只想写一篇,但晚上觉得还是快把区域分割简单介绍下,后面开始彩色图像类的知识学习和代码实现,下一篇介绍分水岭算法,这才是个头疼的算法,今天的区域分离(合并)相对比较好理解。
#算法原理

内容迁移至:http://www.face2ai.com/DIP-7-9-灰度图像-图像分割-区域分割之区域分离/

http://www.tony4ai.com/DIP-7-9-灰度图像-图像分割-区域分割之区域分离/

图像分割

阅读数 867

matlab数字图像处理——图像分割

博文 来自: weixin_43262648
没有更多推荐了,返回首页