GrabCut
-通过交互式的方式获得前景物体
GrabCut原理
- 用户指定前景的大体区域,剩下的为背景区域
- 用户还可以明确指定某些地方为前景或背景、
- GrabCut采用分段迭代的方式分析前景物体形成模型树
- 最后根据权重决定某个像素是前景还是背景
实战GrabCut
- 主体结构
- 鼠标事件的处理
- 调用GrabCut实现前景与背景的分离
鼠标事件处理程序编写
import cv2 as cv
import numpy as np
class App:
startX = 0
startY = 0
flag_rect = False
def onmouse(self,event,x,y,flags,param):
print('onmouse')
if event == cv.EVENT_LBUTTONDOWN:
self.startX = x
self.startY = y
self.flag_rect = True
print("EVENT_LBUTTONDOWN")
elif event == cv.EVENT_LBUTTONUP:
self.flag_rect = False
cv.rectangle(self.img, (self.startX, self.startY), (x, y), (0, 0, 255), 3)
print('EVENT_LBUTTONUP')
elif event == cv.EVENT_MOUSEMOVE:
if self.flag_rect == True:
self.img = self.img2.copy()
cv.rectangle(self.img, (self.startX, self.startY), (x, y), (255, 0, 0), 3)
print('EVENT_MOUSEMOVE')
def run(self):
cv.namedWindow('input')
cv.setMouseCallback('input', self.onmouse)
self.img = cv.imread('dog.jpeg')
self.img2 = self.img.copy()
while True:
cv.imshow("input", self.img)
k = cv.waitKey(100)
if k == 27:
break
if __name__ == '__main__':
A = App()
A.run()
GrabCut API
- grabCut(img, mask, rect, bgdModel, fgdModel, 5, mode)
- mask 生成的掩码
- BGD: 背景,0
- FGD:前景,1
- PR_BGD:可能是背景,2
- PR_FGD:可能是背景,3
- Model
- bgdModel,np.float64 type zero array of size (1,65).
- fgdModel,同上
- mode
- GC_INT_WITH_RECT
- GC_INT_WITH_MASK
import cv2 as cv
import numpy as np
class App:
startX = 0
startY = 0
flag_rect = False
rect = (0, 0, 0, 0)
def onmouse(self,event,x,y,flags,param):
print('onmouse')
if event == cv.EVENT_LBUTTONDOWN:
self.startX = x
self.startY = y
self.flag_rect = True
print("EVENT_LBUTTONDOWN")
elif event == cv.EVENT_LBUTTONUP:
self.flag_rect = False
cv.rectangle(self.img, (self.startX, self.startY), (x, y), (0, 0, 255), 3)
self.rect = (min(self.startX, x), min(self.startY, y), self.startX-x, self.startY-y)
print('EVENT_LBUTTONUP')
elif event == cv.EVENT_MOUSEMOVE:
if self.flag_rect == True:
self.img = self.img2.copy()
cv.rectangle(self.img, (self.startX, self.startY), (x, y), (255, 0, 0), 3)
print('EVENT_MOUSEMOVE')
def run(self):
cv.namedWindow('input')
cv.setMouseCallback('input', self.onmouse)
self.img = cv.imread('luban1.png')
self.img2 = self.img.copy()
self.mask = np.zeros(self.img.shape[:2], dtype=np.uint8)
self.output = np.zeros(self.img.shape, np.uint8)
while True:
cv.imshow("input", self.img)
cv.imshow('output', self.output)
k = cv.waitKey(100)
if k == 27:
break
elif k == ord('g'):
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
cv.grabCut(self.img2, self.mask, self.rect, bgdModel, fgdModel, 1, mode=cv.GC_INIT_WITH_RECT)
mask2 = np.where((self.mask == 1)|(self.mask == 3), 255, 0).astype("uint8")
self.output = cv.bitwise_and(self.img2, self.img2, mask=mask2)
if __name__ == '__main__':
A = App()
A.run()