OpenCV-Python——第23章:使用 GrabCut 算法进行交互式前景提取

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。如有错误,欢迎指出,我会及时修改 https://blog.csdn.net/yukinoai/article/details/88577659

目录

0 原理       1 演示


0 原理

GrabCut算法是由微软剑桥研究院的Carsten_Rother,Vladimir_Kolmogorov和 Andrew_Blake 在文章《GrabCut”: interactive foreground extraction using iterated graph cuts》中共同提出的。此算法在提取前景的操作 过程中需要很少的人机交互,结果非常好。

整个算法过程如下:

  1. 用户输入一个矩形。矩形外的所有区域肯定都是背景(我们在前面已经提到,所有的对象都要包含在矩形框内)。矩形框内的东西是未知的。同样 用户确定前景和背景的任何操作都不会被程序改变。
  2. 计算机会对我们的输入图像做一个初始化标记。它会标记前景和背景像素。
  3. 使用一个高斯混合模型(GMM)对前景和背景建模。 • 根据我们的输入,GMM 会学习并创建新的像素分布。对那些分类未知 的像素(可能是前景也可能是背景),可以根据它们与已知分类(如背景) 的像素的关系来进行分类(就像是在做聚类操作)。
  4. 这样就会根据像素的分布创建一副图。图中的节点就是像素点。除了像 素点做节点之外还有两个节点:Source_node 和 Sink_node。所有的 前景像素都和 Source_node 相连。所有的背景像素都和 Sink_node 相 连。
  5. 将像素连接到 Source_node/end_node 的(边)的权重由它们属于同 一类(同是前景或同是背景)的概率来决定。两个像素之间的权重由边的 信息或者两个像素的相似性来决定。如果两个像素的颜色有很大的不同, 那么它们之间的边的权重就会很小。
  6. 使用 mincut 算法对上面得到的图进行分割。它会根据最低成本方程将图 分为 Source_node 和 Sink_node。成本方程就是被剪掉的所有边的权 重之和。在裁剪之后,所有连接到 Source_node 的像素被认为是前景, 所有连接到 Sink_node 的像素被认为是背景。
  7. 继续这个过程直到分类收敛

如下图所示

 

1 演示

cv2.grabCut(img, mask, rect, bdgModel, fgdModel, iterCount, mode)

  • img:输入图像
  • mask:掩模图像,用来确定那些区域是背景,前景,可能是前景/背景等。 可以设置为:cv2.GC_BGD,cv2.GC_FGD,cv2.GC_PR_BGD,cv2.GC_PR_FGD, 或者直接输入 0,1,2,3 也行。
  • rect:包含前景的矩形,格式为 (x,y,w,h)
  • bdgModel, fgdModel:算法内部使用的数组. 你只需要创建两个大小为 (1,65),数据类型为 np.float64 的数组。
  • iterCount:算法的迭代次数
  • mode:模式,可以设置为cv2.GC_INIT_WITH_RECT或cv2.GC_INIT_WITH_MASK, 也可以联合使用。这是用来确定我们进行修改的方式,矩形模式或者掩模模式。

举个例子:

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

src = cv2.imread('test28.jpg')
img = src.copy()

mask = np.zeros((img.shape[:2]), np.uint8)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
# 设置矩形位置
rect = (64, 60, 530, 180)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img = img*mask2[:, :, np.newaxis]

plt.subplot(121), plt.imshow(cv2.cvtColor(src, cv2.COLOR_BGR2RGB)),
plt.title('Original'), plt.axis('off')
plt.subplot(122), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('Target'), plt.axis('off')

plt.show()

结果如下:

猜你喜欢

转载自blog.csdn.net/yukinoai/article/details/88577659