算法工作原理:
最初,用户在前景区域周围绘制一个矩形(前景区域应完全位于矩形部)。然后,算法会对其进行迭代分割,以获得最佳结果。做完了但在某些情况下,分割可能不会很好,例如,可能已将某些前景区域标记为背景,反之亦然。在这种情况下,需要用户进行精修。只需在图像错误分割区域上画些笔画。然后在下一次迭代中,将获得更好的结果。

主要使用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,这分别取决于是用一个边框还是一个掩码初始化GrabCut
  • OpenCV的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()