交互式前景提取摘抄自《OpenCV轻松入门——面向Python》

交互式前景提取

摘抄自《OpenCV轻松入门——面向Python》

1.算法的基本过程基本步骤

在提取前景前,先用一个矩形框指定前景区域所在的大致范围,不断迭代的分割。
如果提取效果不太理想,可以用户干预提取过程:用户在初始图像的副本中(也可以是和原图像大小相等的任意图像),用白色标注出需要提取的前景图像,黑色标记为背景区域。然后将标记后的图像作为掩膜,让算法继续迭代提取前景从而得到结果。
####GrabCut算法的具体实施过程
1.将前景所在的大致位置使用矩形框标注出来。值得注意的是,此时的矩形框仅仅是前景所在的大致区域,其中既包含前景又包含背景,所以此区域实际是一个未定区域但是,该区域外的区域均被认定为”确定背景“
2.根据矩形框外部的”确定背景“数据来区分矩形框内的前景和背景
3.用高斯混合模型(Gaussians Mixture Model,GMM)对前景和背景建模。GMM会根据用户的输出学习并创建新的像素分布。对未分类的像素(可能是前景也可能是背景),根据其与已知的分类像素(前景和背景)的关系进行分类
4.根据图像分布情况生成一副图,图中的节点就是各个像素点。除了像素点之外,还有两个节点:前景节点和背景节点。所有的前景像素和前景节点相连,所有的背景像素和背景节点相连。每个像素连接到前景节点或者背景节点的边的权重由像素是前景或者背景的概率决定的。
5.图中的每个像素除了与前景节点或者背景节点相连接外,彼此之间还存在着连接。两个像素的边的权重值由他们的相似性决定,两个像素的颜色越接近,边的权重值越大
6.完成节点连接后,需要解决的问题变成了一幅联通的图。在该图上根据各自边的权重关系进行切割,将不同的点划分为前景节点和背景节点。
7.不断重复上述过程,直至分类收敛即可

在python中的opencv库中,实施交互式前景提取的函数是cv2.grabCut().
其语法格式为

mask,bgdModel,fgdModel=cv2.grabCut(img,mask,rect,bgbModel,fbgModel,iterCount[,mode])

式中:
img为输出图像,要求是8位3通道的
mask为掩膜图像,要求是八位单通道的。该参数用于确定前景区域、背景区域和不确定区域,可以设置为四种格式。
1.

cv2.GC_BGD:

表示确定背景,也可以用数值0表示。
2.

cv2.GC_FGD

表示确定前景,也可以用数值1表示。
3.

cv2.GC_PR_BGD

表示可能的背景,也可以用数值2表示。
4.

cv2.GC_PR_FGO

表示可能的前景,也可以用数值3表示。

在最后使用模板提取前景时,会将参数0和2合并作为背景(均当作0处理),
将参数1和3合并为前景(均当作1处理)。通常情况下,我们可以使用白色和黑色在掩膜图像上标记,再通过转换将其中的白色像素设置为0,黑色像素设置为1.

rect指包含前景对象的区域,该区域的部分被认为是”确定背景“。因此,在选取时务必确保让前景包含在rect指定的范围内;否则,rect外的前景部分是不会提取出来的。只有当参数mode的值被设置为矩形模式cv2.GC_INIT_WITH_RECT时,参数rect才有意义。其格式为(x,y,w,h),分别表示区域坐上角像素x轴和y轴以及区域的宽度和高度。使用掩膜模式时,将该值设置为none即可。

bgdModel为算法内部使用的数组,只需要创建一个大小为(1,65)的np.float64数组。

fgdModel为算法内部使用的数组,只需要创建一个大小为(1,65)的np.float64数组。

iterCount表示迭代次数。

mode表示迭代模式

当不使用手动修正时演示代码和效果如下

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

#======================读取原始图像
img=cv2.imread("2.png")
#将bgr图片转化成rgbtu图片方便matplotib库显示
orgb=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#创建一个和原图一样大小的全是0(黑)的三层图片数组,
mask=np.zeros(img.shape[:2],np.uint8)
#创建一个65个零的一维数组
bgdModel=np.zeros((1,65),np.float64)
fgdModel=np.zeros((1,65),np.float64)
#rect是一个确定为前景对象的区域,即需要扣出的部分
rect=(50,50,400,500)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2=np.where((mask==2)|(mask==0),0,1).astype('uint8')
ogc=img*mask2[:,:,np.newaxis]
ogc=cv2.cvtColor(ogc,cv2.COLOR_BGR2RGB)

plt.subplot(121)
plt.imshow(orgb)
plt.axis('off')

plt.subplot(122)
plt.imshow(ogc)
plt.axis('off')
plt.show()

在这里插入图片描述

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

#======================读取原始图像
img=cv2.imread("lena.png")
#将bgr图片转化成rgbtu图片方便matplotib库显示
orgb=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#创建一个和原图一样大小的全是0(黑)的三层图片数组,
mask=np.zeros(img.shape[:2],np.uint8)
#创建一个65个零的一维数组
bgdModel=np.zeros((1,65),np.float64)
fgdModel=np.zeros((1,65),np.float64)
#rect是一个确定为前景对象的区域,即需要扣出的部分
rect=(50,50,400,500)
#对前景进行初步提取
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
#以灰度图的方式读取图像
mask2=cv2.imread("lena 1.png",0)
cv2.imshow("mask2.0",mask2)
#以原图的方式读取图像
mask2Show=cv2.imread("lena.1.png",-1)
cv2.imshow("mask2show",mask2Show)
m2rgb=cv2.cvtColor(mask2Show,cv2.COLOR_BGR2RGB)
mask[mask2==0]=0
mask[mask2==255]=1
mask,bgd,fgd=cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
mask=np.where((mask==2)|(mask==0),0,1).astype('uint8')
ogc=img*mask[:,:,np.newaxis]
ogc=cv2.cvtColor(ogc,cv2.COLOR_BGR2RGB)


ogc=img*mask2[:,:,np.newaxis]
ogc=cv2.cvtColor(ogc,cv2.COLOR_BGR2RGB)

plt.subplot(121)
plt.imshow(m2rgb)
plt.axis('off')

plt.subplot(122)
plt.imshow(ogc)
plt.axis('off')

plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值