GrabCut算法原理
(1)在图片中定义含有(一个或多个)物体的矩形。
(2)矩形外外的区域被自动认为是背景。
(3)对于用户定义的矩形区域,可用背景中的数据来区别它里面的前景和背景区域。
(4)用高斯混合模型(Gaussians Mixture Model,GMM)来对背景和前景建模,并将未定义的像素标记为可能的前景和背景。
(5)图像中的每一个像素都被看作通过虚拟边与周围像素的链接,而每条边都有一个属于前景或背景的概率,这基于它与周围像素颜色上的相似性。
(6)每一个像素(即算法中的节点)会与一个前景或背景节点链接。
(7)在节点完成链接后(可能与背景链接,也可能与前景链接),若节点之间的边属于不同终端(即一个节点属于前景,另一个节点属于背景),则会切断他们之间的边,这就能将图像各部分分割出来。
GrabCut步骤
opencv模块
import cv2
import numpy as np
Step1. 加载图像
img = cv2.imread(‘D:\untitled\aa\img.png’)
Step2. 创建掩模、背景图和前景图
mask返回一堆0,1,2,3的数组,shape[:2]形状切分宽和高,zeros创建0,0,0的数组
mask = np.zeros(img.shape[:2], np.uint8) # 创建大小相同的掩模
bgdModel = np.zeros((1,65), np.float64) # 创建背景图像
fgdModel = np.zeros((1,65), np.float64) # 创建前景图像
Step3. 初始化矩形区域
这个矩形必须完全包含前景
rect = (50,50,450,290)
rect = (275, 120, 170, 320)
rect = (x,y,w,h) x:左边距,y:上边距,w:宽,h:高
rect = (60,110,300,300)
Step4. GrubCut算法,迭代5次
mask的取值为0,1,2,3
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) # 迭代5次
cv2.GC_INIT_WITH_RECT:默认为0,表示框出的矩形图案
Step5. mask中,值为2和0的统一转化为0, 1和3转化为1
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype(‘uint8’)
img = img * mask2[:,:,np.newaxis] # np.newaxis 插入一个新维度,相当于将二维矩阵扩充为三维
cv2.imshow("dst", img)
cv2.waitKey(0)
cv2.imwrite(r"D:untitledaada.png",img)
完整代码
import cv2
import numpy as np
import math
#基于Grabcut算法的前景分割
src = cv2.imread("Gaussian_Blur.png")
src = cv2.resize(src, (0,0), fx=0.5, fy=0.5)
r = cv2.selectROI('input', src, False) # 返回 (x_min, y_min, w, h)
roi = src[int(r[1]):int(r[1]+r[3]), int(r[0]):int(r[0]+r[2])]# roi区域
mask = np.zeros(src.shape[:2], dtype=np.uint8)# 原图mask
rect = (int(r[0]), int(r[1]), int(r[2]), int(r[3])) # 矩形roi
bgdmodel = np.zeros((1,65),np.float64) # bg模型的临时数组
fgdmodel = np.zeros((1,65),np.float64) # fg模型的临时数组
cv2.grabCut(src,mask,rect,bgdmodel,fgdmodel, 11, mode=cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==1) + (mask==3), 255, 0).astype('uint8')# 提取前景和可能的前景区域
result = cv2.bitwise_and(src,src,mask=mask2)
cv2.imwrite('forward.png', result)
cv2.imshow("forard", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
只需更改src = cv2.imread("Gaussian_Blur.png")
中的Gaussian_Blur.png
,图片需要与代码在一个文件夹下,保存的图片也在相同文件夹下。