算法工作原理
最初 用户在前景区域周围绘制一个矩形 前景区域应完全位于矩形部 。然后 算法会对其进行迭代分割 以获得最佳结果。做完了但在某些情况下 分割可能不会很好 例如 可能已将某些前景区域标记为背景 反之亦然。在这种情况下 需要用户进行精修。只需在图像错误分割区域上画些笔画。然后在下一次迭代中 将获得更好的结果。
主要使用cv.grabCut()函数来实现。
grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode) - mask, bgdModel, fgdModel
参数如下
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)。此参数仅在将模式设置为cv2.GC_INIT_WITH_MASK时使用bgdModel GrabCut内部建模背景时使用的临时数组fgdModel GrabCut在建模前景时使用的临时数组iterCount GrabCut在对前景和背景建模时执行的迭代次数。迭代次数越多 GrabCut运行的时间越长 理想情况下 结果会更好model 要么cv2.GC_INIT_WITH_RECT或cv2.GC_INIT_WITH_MASK 这分别取决于是用一个边框还是一个掩码初始化GrabCutOpenCV的GrabCut实现返回一个3元组
mask 应用GrabCut后的输出掩模
fgdMode 用于建模背景的临时数组(可以忽略此值)
fgdModel 用于建模前景的临时数组(可以忽略此值)
代码示例
from matplotlib import pyplot as plt import numpy as np import cv2 as cv img cv.imread( C:\Users\dell\Desktop\prac files\prac19.jpg ) mask np.zeros(img.shape[:2], np.uint8) bgdModel np.zeros((1, 65), np.float64) fgdModel np.zeros((1, 65), np.float64) rect (100, 100, 700, 500) cv.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv.GC_INIT_WITH_RECT) mask2 np.where((mask 2) | (mask 0), 0, 1).astype( uint8 ) img img*mask2[:, :, np.newaxis] #cv.imwrite( result.jpg , img) plt.imshow(img), plt.colorbar(), plt.show()
得到的结果会出现一些差错 一些背景被留了下来 一些前景被当作了背景 因此 将使用1像素 确保前景 进行精细修饰。同时 一些不需要的地面也出现在图片里 需要删除它们。在那里 给出一些0像素的修饰 确保背景 。在这里 无需直接在rect模式下初始化 而可以直接进入mask模式。只需用2像素或3像素 可能的背景/前景 标记mask图像中的矩形区域。然后像在第二个示例中一样 将sure_foreground标记为1像素。然后直接在mask模式下应用grabCut功能。
代码示例
#newmask为手动标记过的图像 newmask cv.imread( C:\Users\dell\Desktop\prac files\newmask.jpg , 0) # 标记为白色 确保前景 的地方 更改mask 1 # 标记为黑色 确保背景 的地方 更改mask 0 mask[newmask 0] 0 mask[newmask 255] 1 mask, bgdModel, fgdModel cv.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv.GC_INIT_WITH_MASK) mask np.where((mask 2) | (mask 0), 0, 1).astype( uint8 ) img img*mask[:, :, np.newaxis] plt.imshow(img), plt.colorbar(), plt.show()



