1 原理(略)
2 代码演示
OpenCV 提供了函数:cv2.grabCut()。我们来先看看它的参数:
- 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)
- bgModel,bgModel:算法内部使用的数组. 你只需要创建两个大小为 (1,65),数据类型为 np.flfloat64 的数组。
- iterCount: 算法的迭代次数
- mode 可以设置为 cv2.GC_INIT_WITH_RECT 或 cv2.GC_INIT_WITH_MASK,也可以联合使用。这是用来确定我们进行修改的方式,矩形模式或者掩模模式。
首先,我们来看使用矩形模式。加载图片,创建掩模图像,构建 bdgModel和 fgdModel。传入矩形参数。都是这么直接。让算法迭代 5 次。由于我们在使用矩形模式所以修改模式设置为cv2.GC_INIT_WITH_RECT。运行grabcut。算法会修改掩模图像,在新的掩模图像中,所有的像素被分为类:背景,前景,可能是背景/前景使用 4 个不同的标签标记(前面参数中提到过)。然后我们来修改掩模图像,所有的 0 像素和 1 像素都被归为 0(例如背景),所有的 1 像素和 3 像素都被归为 1(前景)。我们最终的掩模图像就这样准备好
了。用它和输入图像相乘就得到了分割好的图像。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('test.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
mask = np.zeros(img.shape[:2], np.uint8)
bgModel = np.zeros((1, 65), np.float64)
fgModel = np.zeros((1, 65), np.float64)
rect = (50, 50, 450, 290)
# 函数返回值是更新的mask,bgModel,bgModel
cv2.grabCut(img, mask, rect, bgModel, fgModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img_ = img * mask2[:, :, np.newaxis]
# plt.imshow(img),plt.colorbar(),plt.show()
plt.subplot(121), plt.imshow(img)
plt.title('img'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_)
plt.title('img_'), plt.xticks([]), plt.yticks([])
plt.show()
这里可以看到效果并不完美,但是可以制作新的掩膜图像,来进一步优化效果,这里不做展开。