OpenCV-Python教程:32.使用GrabCut算法分割前景

理論

GranCut算法是Carsten Rother, Vladimir Kolmogorov & Andrew Blake from Microsoft Research Cambridge, UK在他們的論文“GrabCut”: interactive foreground extraction using iterated graph cuts里設(shè)計的。使用最小程度的用戶交互來分解前景姑原。

從用戶角度來看是怎么工作的呢?開始用戶畫一個矩形方塊把前景圖圈起來蜗巧,前景區(qū)域應(yīng)該完全在矩形內(nèi)二驰,然后算法反復(fù)進(jìn)行分割以達(dá)到最好效果召调。但是有些情況下,分割的不是很好支子,比如把前景給標(biāo)稱背景了等。在這種情況下用戶需要再潤色达舒,就在圖像上有缺陷的點給幾筆值朋。這幾筆的意思是說“嘿,這個區(qū)域應(yīng)該是前景巩搏,你把它標(biāo)成背景了昨登,下次迭代改過來”或者是反過來。那么在下次迭代贯底,結(jié)果會更好丰辣。

看下面的圖像撒强,首先球員和足球杯包在藍(lán)色矩形框里,然后用白色筆(指出前景)和黑色筆(指出背景)來做一些潤色

后臺發(fā)生了什么笙什?

·用戶輸入矩形飘哨,矩形外的所有東西都被確認(rèn)是背景。所有矩形內(nèi)的東西都是未知的琐凭,同樣的任何用戶輸入指定前景和背景的也都被認(rèn)為是硬標(biāo)記芽隆,在處理過程中不會變。

·計算機(jī)會根據(jù)我們給的數(shù)據(jù)做初始標(biāo)記统屈,它會標(biāo)記出前景和背景像素胚吁。

·現(xiàn)在回使用高斯混合模型(GMM)來為前景和背景建模

·根據(jù)我們給的數(shù)據(jù),GMM學(xué)習(xí)和創(chuàng)建新的像素分布愁憔。未知像素被標(biāo)為可能的前景或可能的背景(根據(jù)其他硬標(biāo)記像素的顏色統(tǒng)計和他們之間的關(guān)系)

·根據(jù)這個像素分布創(chuàng)建一個圖腕扶,圖中的節(jié)點是像素,另外還有兩個節(jié)點吨掌,源節(jié)點和匯節(jié)點蕉毯,每個前景像素和源節(jié)點相連,每個背景像素和匯節(jié)點相連思犁。

·源節(jié)點和匯節(jié)點連接的像素的邊的權(quán)重由像素是前景或者背景的概率決定代虾。像素之間的權(quán)重是由邊的信息或者像素的相似度決定。如果像素顏色有很大差異激蹲,他們之間的邊的權(quán)重就比較低棉磨。

·mincut算法是用來分割圖的,它用最小成本函數(shù)把圖切成兩個分開的源點和匯點学辱,成本函數(shù)是被切的邊的權(quán)重之和乘瓤。切完以后,所有連到源節(jié)點的像素稱為前景策泣,所有連到匯節(jié)點的稱為背景衙傀。

·過程持續(xù)直到分類覆蓋。

Demo

現(xiàn)在我們用OpenCV來做grabcut算法萨咕。OpenCV有個函數(shù)cv2.grabCut()來做這個统抬,我們先看看它的參數(shù):

·img - 輸入圖像

·mask - 這是掩圖,我們指定哪個區(qū)域是背景危队,前景以及可能是背景或者前景聪建。由下面的標(biāo)志位:cv2.GC_BGD, cv2.GC_FGD, cv2.PR_BGD, cv2.GC_PR_FGD, 或者簡單傳入0, 1, 2, 3.

·rect - 包含前景對象的矩形的坐標(biāo),格式(x, y, w, h).

·bdgModel, fgdModel - 算法內(nèi)部使用的數(shù)組茫陆, 你創(chuàng)建兩個np.float64 類型的0數(shù)組金麸,大小是(1, 65)

·iterCount - 算法運行的迭代次數(shù)

·mode - 應(yīng)該是cv2.GC_INIT_WITH_RECT 或者 cv2.GC_INIT_WITH_MASK或者兩者合并,決定我們是否畫矩形或者最終的潤色簿盅。

首先讓我們看看矩形模式挥下,我們加載圖片揍魂,創(chuàng)建一個類似的掩圖。我們創(chuàng)建fgdModel和bgdModel棚瘟。 我們給矩形參數(shù)愉烙。這些都很直接。讓算法運行5個迭代解取。Mode應(yīng)該是cv2.GC_INIT_WITH_RECT因為我們用了矩形步责。然后運行g(shù)rabcut。 它修改掩圖禀苦。在新的掩圖里蔓肯,像素會被標(biāo)記為四種標(biāo)志,來指明他們是背景/前景等振乏。所以我們修改 掩圖蔗包,所有的0-像素和2-像素被置0(背景)而所有的1-像素和3-像素被置1(前景像素)。現(xiàn)在我們最終的掩圖就緒慧邮。

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('messi5.jpg')
mask = np.zeros(img.shape[:2],np.uint8)

bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)

rect = (50,50,450,290)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,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()

可以看到梅西的頭發(fā)沒了调限,所以我們潤色一下,用1-像素確認(rèn)是前景误澳,同時有些地皮成了前景耻矮,還有l(wèi)ogo,我們需要移除他們忆谓,我們給一些0-像素潤色(確認(rèn)是背景)裆装。我們修改我們的結(jié)果掩圖。

實際上我做的是倡缠,我用繪圖軟件打開輸入圖片哨免,添加了另外一層,使用畫刷工具昙沦,把丟失的前景(頭發(fā)琢唾,謝,球等)用白色盾饮,不要的背景(logo采桃,地面)用黑色畫在這個新層上。然后把剩下的背景用灰色填充丐谋。然后在OpenCV里加載這個掩圖芍碧,編輯原始掩圖,代碼:

# newmask is the mask image I manually labelled
newmask = cv2.imread('newmask.png',0)

# whereever it is marked white (sure foreground), change mask=1
# whereever it is marked black (sure background), change mask=0
mask[newmask == 0] = 0
mask[newmask == 255] = 1

mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.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()

也可以不用矩形初始化而直接用掩圖模式号俐,用2-像素和3-像素(可能是背景/前景)標(biāo)記矩形區(qū)域,然后把我們確認(rèn)前景的標(biāo)為1-像素定庵,然后直接應(yīng)用grabCut函數(shù)吏饿,用mask 模式踪危。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市猪落,隨后出現(xiàn)的幾起案子贞远,更是在濱河造成了極大的恐慌,老刑警劉巖笨忌,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蓝仲,死亡現(xiàn)場離奇詭異,居然都是意外死亡官疲,警方通過查閱死者的電腦和手機(jī)袱结,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來途凫,“玉大人垢夹,你說我怎么就攤上這事∥眩” “怎么了果元?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長犀盟。 經(jīng)常有香客問我而晒,道長,這世上最難降的妖魔是什么阅畴? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任欣硼,我火速辦了婚禮,結(jié)果婚禮上恶阴,老公的妹妹穿的比我還像新娘诈胜。我一直安慰自己,他們只是感情好冯事,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布焦匈。 她就那樣靜靜地躺著,像睡著了一般昵仅。 火紅的嫁衣襯著肌膚如雪缓熟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天摔笤,我揣著相機(jī)與錄音够滑,去河邊找鬼。 笑死吕世,一個胖子當(dāng)著我的面吹牛彰触,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播命辖,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼况毅,長吁一口氣:“原來是場噩夢啊……” “哼分蓖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起尔许,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤么鹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后味廊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒸甜,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年余佛,在試婚紗的時候發(fā)現(xiàn)自己被綠了柠新。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡衙熔,死狀恐怖登颓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情红氯,我是刑警寧澤框咙,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站痢甘,受9級特大地震影響喇嘱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塞栅,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一者铜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧放椰,春花似錦作烟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至如蚜,卻和暖如春压恒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背错邦。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工探赫, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撬呢。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓伦吠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子讨勤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容