opencv教程(基于python)----grabcut前景提取

grabcut算法是微软的一个研究院提出的。算法在提取前景的操作中需要很少的人机交互,结果非常好。
通俗的说,一开始用户用户需要用一个矩形将前景区域框住。然后使用算法迭代分割。但有时分割的结构不够理想,会把前景和背景弄错,这时需要我们人为的修正了。
具体的原理

  • 用户输入一个矩形,矩形外的区域一定是背景,矩形内的东西是未知的
  • 计算机会对我们数据的图像做一个初始化的标记,她会标记前景和背景像素
  • 使用高斯混合模型(GMM)进行前景和背景的建模
  • 根据我们的数据,GMM会学习并创建新的像素分布对未知的像素可以根据他们与已知分类像素的关系进行分类
  • 这样就会根据像素的分布创建一幅图,图中的节点就是像素点。除了像素点之外还有两个节点:source和sink。所有的前景像素和source相连,背景像素和sink相连。
  • 像素链接到source/end(边)的权重有他们属于同一类的概率决定。两个像素之间的权重由边的信息或者是两个像素的相似性决定。如果两个像素的颜色有很大不同,他们之间边的权重就会很小
  • 使用mincut算法对上面的图像进行分割(这个算法没听说过)。她会根据最低的成本方程将图象分位source和sink。成本方程就是减掉边的权重之和。剪裁完成之后source被认为是前景,sink被认为是背景。
  • 继续上述过程知道分类收敛。

    下面介绍一下用到的主要函数grabcut

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

  • img是数的图像
  • mask是掩模图像,用来确定哪些区域是背景,哪些区域是前景。可以设置为cv2.GC_BGD定义了一个明显的背景像素。
    cv2.GC_FGD定义了一个明显的前景(对象)像素。
    cv2.GC_PR_BGD定义一个可能的背景像素。
    cv2.GC_PR_FGD定义了一个可能的前景像素。(具体的作用可以自己试一下)
  • rect是包含背景的矩形,该参数仅在使用时使用 mode==GC_INIT_WITH_RECT
  • bdgModel,fdgModel是算法内部使用的数组,需要自己创建两个大小为(1,65)数据类型为np.float64的数组。
  • iterCount是算法的迭代次数
  • mode可以设置为cv2.Gc_INIT_WITH_RECT或者cv2.GC_INIT_WITH_MASK.这个是来确定我们修改范式,矩阵模式或者掩模模式。
    矩阵模式中,算法会修改掩模图像,在新的掩模图像中,所有的像素被分位四类:背景,前景,可能是背景/前景石油4个不同的标签标记。下面看一下具体的例子。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img=cv2.imread('C:/Users/dell/Desktop/01.jpg')
mask=np.zeros((img.shape[:2]),np.uint8)
bgdModel=np.zeros((1,65),np.float64)
fgdModel=np.zeros((1,65),np.float64)
rect=(81,189,587,1041)
#这里计算了5次
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
#关于where函数第一个参数是条件,满足条件的话赋值为0,否则是1。如果只有第一个参数的话返回满足条件元素的坐标。
mask2=np.where((mask==2)|(mask==0),0,1).astype('uint8')
#mask2就是这样固定的
plt.subplot(1,2,1)
plt.imshow(img)
plt.title('original image ')
plt.xticks([])
plt.yticks([])
plt.subplot(1,2,2)
#这里的img也是固定的。
img=img*mask2[:,:,np.newaxis]
plt.imshow(img)
plt.title('target image')
plt.xticks([])
plt.yticks([])
plt.show()

opencv教程(基于python)----grabcut前景提取_第1张图片
算法的总体想过还是不错的,但是有点小瑕疵。原始图像中有个手模型也被误认为是前景了。不能完全怪算法,那个东西离人物的手很近而且颜色比较像,判断错误也是情理之中的。要解决这个错误就要认为的添加标记了。文档的做法是在目标区域用ps强加白色,背景部分强加黑色。

你可能感兴趣的:(opencv教程(基于python)----grabcut前景提取)