南山建网站,北京建站模板源码,贵阳网站托管,武夷山景区网站建设优点文章目录 使用 GrabCut 算法进行交互式前景提取目标理论演示 使用 GrabCut 算法进行交互式前景提取
目标
在本章中
我们将了解 GrabCut 算法如何提取图像中的前景我们将为此创建一个交互式应用程序。
理论
GrabCut 算法由英国剑桥微软研究院的 Carsten Rother、Vladimir K… 文章目录 使用 GrabCut 算法进行交互式前景提取目标理论演示 使用 GrabCut 算法进行交互式前景提取
目标
在本章中
我们将了解 GrabCut 算法如何提取图像中的前景我们将为此创建一个交互式应用程序。
理论
GrabCut 算法由英国剑桥微软研究院的 Carsten Rother、Vladimir Kolmogorov 和 Andrew Blake 设计。在他们的论文 “GrabCut”使用迭代图切割进行交互式前景提取 中。需要一种以最少的用户交互进行前景提取的算法结果就是 GrabCut。
从用户的角度来看它是如何工作的首先用户在前景区域周围绘制一个矩形前景区域应完全在矩形内。然后算法迭代地对其进行分割以获得最佳结果。完成。但在某些情况下分割效果并不好例如它可能将某些前景区域标记为背景反之亦然。在这种情况下用户需要进行精细的修饰。只需在存在错误结果的图像上进行一些描边即可。描边基本上表示“嘿这个区域应该是前景你将其标记为背景在下一次迭代中对其进行更正”*或将其相反标记为背景。然后在下一次迭代中您会得到更好的结果。
参见下图。第一个球员和足球被包裹在一个蓝色矩形中。然后用白色描边表示前景和黑色描边表示背景进行一些最后的修饰。我们得到了一个不错的结果。 那么背景会发生什么
用户输入矩形。此矩形之外的所有内容都将被视为确定的背景这就是之前提到您的矩形应包含所有对象的原因。矩形内的所有内容都是未知的。同样任何指定前景和背景的用户输入都被视为硬标记这意味着它们不会在此过程中发生变化。计算机根据我们提供的数据进行初始标记。它标记前景和背景像素或硬标记现在使用高斯混合模型 (GMM) 来建模前景和背景。根据我们提供的数据GMM 学习并创建新的像素分布。也就是说未知像素根据其与其他硬标记像素在颜色统计方面的关系被标记为可能的前景或可能的背景这就像聚类。根据此像素分布构建图形。图中的节点是像素。添加了另外两个节点源节点和接收器节点。每个前景像素都连接到源节点每个背景像素都连接到接收器节点。将像素连接到源节点/端节点的边的权重由像素为前景/背景的概率定义。像素之间的权重由边缘信息或像素相似性定义。如果像素颜色差异很大则它们之间的边缘将获得较低的权重。然后使用最小切割算法对图形进行分割。它将图形切成两个分离的源节点和接收器节点具有最小成本函数。成本函数是所有被切割边的权重之和。切割后所有连接到源节点的像素都变为前景而连接到接收器节点的像素都变为背景。该过程持续进行直到分类收敛。
如下图所示图片来源http://www.cs.ru.ac.za/research/g02m1682/ 演示
现在我们使用 OpenCV 进行 grabcut 算法。OpenCV 有函数 cv.grabCut() 用于此目的。我们 首先将看到它的参数
img - 输入图像mask - 这是一个掩码图像我们指定哪些区域是背景、前景或可能的背景/前景等。它通过以下标志完成cv.GC_BGD、cv.GC_FGD、cv.GC_PR_BGD、cv.GC_PR_FGD或者简单地将 0、1、2、3 传递给图像。rect - 它是包含前景对象的矩形的坐标格式为 (x,y,w,h)bdgModel、fgdModel - 这些是算法内部使用的数组。您只需创建两个大小为 (1,65) 的 np.float64 类型零数组。iterCount - 算法应运行的迭代次数。mode - 它应该是 cv.GC_INIT_WITH_RECT 或 cv.GC_INIT_WITH_MASK 或两者结合 决定我们绘制的是矩形还是最终的修饰笔触。
首先让我们看看矩形模式。我们加载图像创建一个类似的遮罩图像。我们创建 fgdModel 和 bgdModel。我们给出矩形参数。这一切都很简单。让算法运行 5 次迭代。模式应该是cv.GC_INIT_WITH_RECT因为我们使用的是矩形。然后运行 grabcut。它会修改遮罩图像。在新的遮罩图像中像素将用四个标志标记表示如上所述的背景/前景。因此我们修改了掩码将所有 0 像素和 2 像素都设置为 0即背景将所有 1 像素和 3 像素都设置为 1即前景像素。现在我们的最终掩码已准备就绪。只需将其与输入图像相乘即可获得分割后的图像。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as pltimg cv.imread(messi5.jpg)
mask np.zeros(img.shape[:2],np.uint8)bgdModel np.zeros((1,65),np.float64)
fgdModel np.zeros((1,65),np.float64)rect (50,50,450,290)
cv.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv.GC_INIT_WITH_RECT)mask2 np.where((mask2)|(mask0),0,1).astype(uint8)
img img*mask2[:,:,np.newaxis]plt.imshow(img),plt.colorbar(),plt.show()请参阅以下结果 哎呀梅西的头发不见了。*谁会喜欢没有头发的梅西*我们需要把它带回来。所以我们将用 1 像素确定的前景进行精细修饰。同时一些我们不想要的地面部分出现在图片中还有一些徽标。我们需要移除它们。我们在那里进行一些 0 像素修饰确定的背景。所以我们修改了前面案例中得到的蒙版就像我们现在所说的那样。
我实际上做的是我在绘画应用程序中打开输入图像并在图像上添加了另一个图层。使用绘画中的画笔工具我在这个新图层上用白色标记错过的前景头发、鞋子、球等用黑色标记不需要的背景如徽标、地面等。然后用灰色填充剩余的背景。然后在 OpenCV 中加载该蒙版图像使用新添加的蒙版图像中的相应值编辑我们获得的原始蒙版图像。检查下面的代码
# newmask is the mask image I manually labelled
newmask cv.imread(newmask.png,0)# wherever it is marked white (sure foreground), change mask1
# wherever it is marked black (sure background), change mask0
mask[newmask 0] 0
mask[newmask 255] 1mask, bgdModel, fgdModel cv.grabCut(img,mask,None,bgdModel,fgdModel,5,cv.GC_INIT_WITH_MASK)mask np.where((mask2)|(mask0),0,1).astype(uint8)
img img*mask[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()请参阅以下结果 就是这样。在这里您可以直接进入掩码模式而不是在矩形模式下初始化。只需用 2 像素或 3 像素可能的背景/前景标记掩码图像中的矩形区域。然后用 1 像素标记我们的 sure_foreground就像我们在第二个示例中所做的那样。然后直接在掩码模式下应用 grabCut函数。