OpenCV使用 GrabCut 算法进行交互式前景提取
生活随笔
收集整理的這篇文章主要介紹了
OpenCV使用 GrabCut 算法进行交互式前景提取
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
OpenCV使用 GrabCut 算法進(jìn)行交互式前景提取
- 1. 效果圖
- 2. 源碼
- 參考
這篇博客將介紹如何使用Python,OpenCV中的GrabCut 算法來提取圖像中的前景,并為此創(chuàng)建一個(gè)交互式應(yīng)用程序。
1. 效果圖
官方示例——lena 原始圖 VS grabcut前景設(shè)置 VS 前景摳圖效果如下:
鼠標(biāo)右鍵繪制矩形,按下 ‘0’ 左鍵點(diǎn)擊標(biāo)記確定背景,按下 ‘1’ 左鍵標(biāo)記確定前景,按 ‘r’ 鍵重置矩形等繪制,按 ’s‘ 鍵保存結(jié)果圖,然后得到比較干凈友好的效果圖;
我最喜歡的穎寶,原始圖 VS GrabCut圖 VS 摳圖效果如下:
2. 源碼
# 使用GrabCut進(jìn)行交互式的前景提取(Interactive Image Segmentation using GrabCut algorithm)
# USAGE:
# python grabcut.py ml2.jpg# 運(yùn)行會(huì)呈現(xiàn)倆個(gè)窗口,輸入圖像及輸出圖像窗口
# 首先用鼠標(biāo)右鍵繪制一個(gè)前景的矩形框,按下 'n' 鍵進(jìn)行前景提取
# 然后按下鼠標(biāo)左鍵繪制任何區(qū)域,點(diǎn)、線等不規(guī)則區(qū)域,按下 'n' 鍵進(jìn)行前景提取# 按下鍵 '0' - 選擇確定背景
# 按下鍵 '1' - 選擇確定前景
# 按下鍵 '2' - 選擇可能背景
# 按下鍵 '3' - 選擇可能前景
# 按下鍵 'n' - 更新分割結(jié)果
# 按下鍵 'r' - 重置分割
# 按下鍵 's' - 保存分割的結(jié)果
# 按下鍵 'ESC' - 退出分割from __future__ import print_functionimport sysimport cv2 as cv
import numpy as npclass App():BLUE = [255, 0, 0] # 矩形顏色RED = [0, 0, 255] # 可能背景GREEN = [0, 255, 0] # 可能前景BLACK = [0, 0, 0] # 確定背景WHITE = [255, 255, 255] # 確定前景DRAW_BG = {'color': BLACK, 'val': 0}DRAW_FG = {'color': WHITE, 'val': 1}DRAW_PR_BG = {'color': RED, 'val': 2}DRAW_PR_FG = {'color': GREEN, 'val': 3}# 設(shè)置flagsrect = (0, 0, 1, 1)drawing = False # 是否繪制曲線rectangle = False # 是否繪制矩形rect_over = False # 是否矩形繪制完畢rect_or_mask = 100 # 選擇矩形或者蒙版value = DRAW_FG # 繪制初始化的前景thickness = 3 # 筆刷粗細(xì)def onmouse(self, event, x, y, flags, param):# 繪制矩形(按下鼠標(biāo)右鍵)if event == cv.EVENT_RBUTTONDOWN:self.rectangle = Trueself.ix, self.iy = x, yelif event == cv.EVENT_MOUSEMOVE:if self.rectangle == True:self.img = self.img2.copy()cv.rectangle(self.img, (self.ix, self.iy), (x, y), self.BLUE, 2)self.rect = (min(self.ix, x), min(self.iy, y), abs(self.ix - x), abs(self.iy - y))self.rect_or_mask = 0elif event == cv.EVENT_RBUTTONUP:self.rectangle = Falseself.rect_over = Truecv.rectangle(self.img, (self.ix, self.iy), (x, y), self.BLUE, 2)self.rect = (min(self.ix, x), min(self.iy, y), abs(self.ix - x), abs(self.iy - y))self.rect_or_mask = 0print(" Now press the key 'n' a few times until no further change \n")# 繪制接觸曲線if event == cv.EVENT_LBUTTONDOWN:if self.rect_over == False:print("first draw rectangle \n")else:self.drawing = Truecv.circle(self.img, (x, y), self.thickness, self.value['color'], -1)cv.circle(self.mask, (x, y), self.thickness, self.value['val'], -1)elif event == cv.EVENT_MOUSEMOVE:if self.drawing == True:cv.circle(self.img, (x, y), self.thickness, self.value['color'], -1)cv.circle(self.mask, (x, y), self.thickness, self.value['val'], -1)elif event == cv.EVENT_LBUTTONUP:if self.drawing == True:self.drawing = Falsecv.circle(self.img, (x, y), self.thickness, self.value['color'], -1)cv.circle(self.mask, (x, y), self.thickness, self.value['val'], -1)def run(self):# Loading imagesif len(sys.argv) == 2:filename = sys.argv[1] # for drawing purposeselse:print("No input image given, so loading default image, ml.jpg \n")print("Correct Usage: python grabcut.py <filename> \n")filename = 'ml.jpg'print(filename)self.img = cv.imread(filename)self.img2 = self.img.copy() # 復(fù)制原始圖像self.mask = np.zeros(self.img.shape[:2], dtype=np.uint8) # mask初始化為PR_BG可能背景self.output = np.zeros(self.img.shape, np.uint8) # 輸出圖像# 輸入輸出框cv.namedWindow('output')cv.namedWindow('input')cv.setMouseCallback('input', self.onmouse)cv.moveWindow('input', self.img.shape[1] + 10, 90)print(" Instructions: \n")print(" Draw a rectangle around the object using right mouse button \n")while (1):cv.imshow('output', self.output)cv.imshow('input', self.img)k = cv.waitKey(1)# 按鍵事件綁定if k == 27: # 按ESC退出breakelif k == ord('0'): # 繪制背景print(" mark background regions with left mouse button \n")self.value = self.DRAW_BGelif k == ord('1'): # 繪制前景print(" mark foreground regions with left mouse button \n")self.value = self.DRAW_FGelif k == ord('2'): # 繪制可能背景self.value = self.DRAW_PR_BGelif k == ord('3'): # 繪制可能前景self.value = self.DRAW_PR_FGelif k == ord('s'): # 保存結(jié)果bar = np.zeros((self.img.shape[0], 10, 3), np.uint8)res = np.hstack((self.img2, bar, self.img, bar, self.output))cv.imwrite('ml_grabcut_output.jpg', res)print(" Result saved as image \n")elif k == ord('r'): # 重置,重新進(jìn)行選中前景背景print("resetting \n")self.rect = (0, 0, 1, 1)self.drawing = Falseself.rectangle = Falseself.rect_or_mask = 100self.rect_over = Falseself.value = self.DRAW_FGself.img = self.img2.copy()self.mask = np.zeros(self.img.shape[:2], dtype=np.uint8) # mask initialized to PR_BGself.output = np.zeros(self.img.shape, np.uint8) # output image to be shownelif k == ord('n'): # 分離圖片print(""" For finer touchups, mark foreground and background after pressing keys 0-3and again press 'n' \n""")try:bgdmodel = np.zeros((1, 65), np.float64)fgdmodel = np.zeros((1, 65), np.float64)if (self.rect_or_mask == 0): # 使用矩形進(jìn)行g(shù)rabcutcv.grabCut(self.img2, self.mask, self.rect, bgdmodel, fgdmodel, 1, cv.GC_INIT_WITH_RECT)self.rect_or_mask = 1elif (self.rect_or_mask == 1): # 使用mask進(jìn)行g(shù)rabcutcv.grabCut(self.img2, self.mask, self.rect, bgdmodel, fgdmodel, 1, cv.GC_INIT_WITH_MASK)except:import tracebacktraceback.print_exc()mask2 = np.where((self.mask == 1) + (self.mask == 3), 255, 0).astype('uint8')self.output = cv.bitwise_and(self.img2, self.img2, mask=mask2)print('Done')if __name__ == '__main__':print(__doc__)App().run()cv.destroyAllWindows()
參考
- https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_grabcut/py_grabcut.html#grabcut
總結(jié)
以上是生活随笔為你收集整理的OpenCV使用 GrabCut 算法进行交互式前景提取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开个面馆投资多少钱?
- 下一篇: 回顾2021,展望2022