日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

OpenCV-Python學(xué)習(xí)筆記(十八):使用 GrabCut 算法進(jìn)行

系統(tǒng) 2096 0

Interactive Foreground Extraction using GrabCut Algorithm:

目標(biāo)
在本節(jié)中我們將要學(xué)習(xí):
? GrabCut 算法原理,使用 GrabCut 算法提取圖像的前景
? 創(chuàng)建一個交互是程序完成前景提取?

原理
GrabCut 算法是由微軟劍橋研究院的 Carsten_Rother, Vladimir_Kolmogorov和 Andrew_Blake 在文章《GrabCut”: interactive foreground extraction using iterated graph cuts》中共同提出的。此算法在提取前景的操作過程中需要很少的人機(jī)交互,結(jié)果非常好。?

從用戶的角度來看它到底是如何工作的呢?開始時用戶需要用一個矩形將前景區(qū)域框住(前景區(qū)域應(yīng)該完全被包括在矩形框內(nèi)部)。然后算法進(jìn)行迭代式分割直達(dá)達(dá)到最好結(jié)果。但是有時分割的結(jié)果不夠理想,比如把前景當(dāng)成了背景,或者把背景當(dāng)成了前景。在這種情況下,就需要用戶來進(jìn)行修改了。用戶只需要在不理想的部位畫一筆(點(diǎn)一下鼠標(biāo))就可以了。畫一筆就等于在告訴計算機(jī):“嗨,老兄,你把這里弄反了,下次迭代的時候記得改過來呀!”。然后,在下一輪迭代的時候你就會得到一個更好的結(jié)果了。

如下圖所示。運(yùn)動員和足球被藍(lán)色矩形包圍在一起。其中有我做的幾個修正,白色畫筆表明這里是前景,黑色畫筆表明這里是背景。最后我得到了一個很好的結(jié)果。??

OpenCV-Python學(xué)習(xí)筆記(十八):使用 GrabCut 算法進(jìn)行交互式前景提取_第1張圖片

在整個過程中到底發(fā)生了什么呢?
? 用戶輸入一個矩形。矩形外的所有區(qū)域肯定都是背景(我們在前面已經(jīng)提到,所有的對象都要包含在矩形框內(nèi))。矩形框內(nèi)的東西是未知的。同樣用戶確定前景和背景的任何操作都不會被程序改變。

? 計算機(jī)會對我們的輸入圖像做一個初始化標(biāo)記。它會標(biāo)記前景和背景像素。?

? 使用一個高斯混合模型(GMM)對前景和背景建模。
? 根據(jù)我們的輸入, GMM 會學(xué)習(xí)并創(chuàng)建新的像素分布。對那些分類未知的像素(可能是前景也可能是背景),可以根據(jù)它們與已知分類(如背景)的像素的關(guān)系來進(jìn)行分類(就像是在做聚類操作)。

? 這樣就會根據(jù)像素的分布創(chuàng)建一副圖。圖中的節(jié)點(diǎn)就是像素點(diǎn)。除了像素點(diǎn)做節(jié)點(diǎn)之外還有兩個節(jié)點(diǎn): Source_node 和 Sink_node。所有的前景像素都和 Source_node 相連。所有的背景像素都和 Sink_node 相連。?

? 將像素連接到 Source_node/end_node 的邊的權(quán)值由像素作為前景/背景的概率來定義。像素之間的權(quán)重由邊緣信息或像素相似度定義。如果像素顏色有較大的差異,它們之間的邊緣會得到較低的權(quán)重。

? 然后利用mincut算法對圖像進(jìn)行分割。利用最小代價函數(shù)將圖分割為兩個分離的 Source_node 和 Sink_node。代價函數(shù)是所有被切割邊的權(quán)值之和。切割后,所有連接到 Source_node 的像素被認(rèn)為是前景,所有連接到 Sink_node 的像素被認(rèn)為是背景。

? 繼續(xù)這個過程直到分類收斂。?

下圖演示了這個過程(Image Courtesy: http://www.cs.ru.ac.za/research/g02m1682/):?

OpenCV-Python學(xué)習(xí)筆記(十八):使用 GrabCut 算法進(jìn)行交互式前景提取_第2張圖片

示例

現(xiàn)在我們進(jìn)入 OpenCV 中的 grabcut 算法。 OpenCV 提供了函數(shù): cv2.grabCut() 。我們來先看看它的參數(shù):

? img - 輸入圖像
? mask-掩模圖像,用來確定那些區(qū)域是背景,前景,可能是前景/背景等。可以設(shè)置為:cv2.GC_BGD,cv2.GC_FGD,cv2.GC_PR_BGD,cv2.GC_PR_FGD,或者直接輸入 0,1,2,3 也行。
? rect - 包含前景的矩形,格式為 (x,y,w,h)
? bdgModel, fgdModel - 算法內(nèi)部使用的數(shù)組. 你只需要創(chuàng)建兩個大小為 (1,65),數(shù)據(jù)類型為 np.float64 的數(shù)組。
? iterCount - 算法的迭代次數(shù)
? mode 可以設(shè)置為 cv2.GC_INIT_WITH_RECT 或 cv2.GC_INIT_WITH_MASK,也可以聯(lián)合使用。這是用來確定我們進(jìn)行修改的方式,矩形模式或者掩模模式。

首先,我們來看使用矩形模式。加載圖片,創(chuàng)建掩模圖像,構(gòu)建 bdgModel和 fgdModel。傳入矩形參數(shù)。都是這么直接。讓算法迭代 5 次。由于我們在使用矩形模式所以修改模式設(shè)置為 cv2.GC_INIT_WITH_RECT。運(yùn)行g(shù)rabcut。算法會修改掩模圖像,在新的掩模圖像中,所有的像素被分為四類:背景,前景,可能是背景/前景使用 4 個不同的標(biāo)簽標(biāo)記(前面參數(shù)中提到過)。然后我們來修改掩模圖像,所有的 0 像素和 2?像素都被歸為 0(背景),所有的 1 像素和 3 像素都被歸為 1(前景)。我們最終的掩模圖像就這樣準(zhǔ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)
# 函數(shù)的返回值是更新的 mask, bgdModel, fgdModel
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()
            
          

?結(jié)果如下:

OpenCV-Python學(xué)習(xí)筆記(十八):使用 GrabCut 算法進(jìn)行交互式前景提取_第3張圖片

哎呀,梅西的頭發(fā)被我們弄沒了!讓我們來幫他找回頭發(fā)。所以我們要在那里畫一筆(設(shè)置像素為 1,肯定是前景)。同時還有一些我們并不需要的草地。我們需要去除它們,我們再在這個區(qū)域畫一筆(設(shè)置像素為 0,肯定是背景)。現(xiàn)在可以象前面提到的那樣來修改掩模圖像了。

實(shí)際上我是怎么做的呢?我們使用圖像編輯軟件打開輸入圖像,添加一個圖層,使用筆刷工具在需要的地方(比如頭發(fā),鞋子,球等)使用白色繪制;使用黑色筆刷在不需要的地方繪制(比如, logo,草地等)。然后將其他地方用灰色填充,保存成新的掩碼圖像。在 OpenCV 中導(dǎo)入這個掩模圖像,根據(jù)新的掩碼圖像對原來的掩模圖像進(jìn)行編輯。代碼如下:

            
              # 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()
            
          

?結(jié)果如下:

OpenCV-Python學(xué)習(xí)筆記(十八):使用 GrabCut 算法進(jìn)行交互式前景提取_第4張圖片

就是這樣。你也可以不使用矩形初始化,直接進(jìn)入掩碼圖像模式。使用 2像素和 3 像素(可能是背景/前景)對矩形區(qū)域的像素進(jìn)行標(biāo)記。然后象我們在第二個例子中那樣對肯定是前景的像素標(biāo)記為 1 像素。然后直接在掩模圖像模式下使用 grabCut 函數(shù)。

OpenCV 自帶的示例中有一個使用 grabcut 算法的交互式工具 grabcut.py。

參考資料:

1.?OpenCV官方文檔-Interactive Foreground Extraction using GrabCut Algorithm

2.《OpenCV-Python 中文教程》(段力輝 譯)

?

?

?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 古交市| 利津县| 哈密市| 济源市| 铁力市| 陵水| 会东县| 平阳县| 克东县| 台中市| 贵阳市| 民县| 客服| 安多县| 枝江市| 和林格尔县| 聂拉木县| 尤溪县| 邻水| 东光县| 星子县| 旺苍县| 伊金霍洛旗| 西平县| 鄢陵县| 荆州市| 桑植县| 宜州市| 白玉县| 台江县| 镇远县| 凤翔县| 禹州市| 仁寿县| 大冶市| 交口县| 肃宁县| 靖西县| 丰县| 宜君县| 荣成市|