OpenCV3計算機視覺:Python實現 讀書筆記-第四章

第四章

使用分水嶺和GrabCut算法物體分割
  • GrabCut算法步驟
    • 在圖片中定義含有(若干個)物體的矩形
    • 矩形外的區域被認爲是背景
    • 對於用戶定義的矩形區域,用背景中的數據區別裏面的前景和背景
    • 用高斯混合模型對背景和前景建模,並將未定義的像素標記爲可能的前景或背景
    • 圖像中的每一個像素都被看作通過虛擬邊與周圍像素連接,而每條邊都有一個屬於前景或背景的概率,這基於它與周圍像素顏色上的相似性
    • 每一個像素會與一個前景和背景節點連接
    • 節點完成連接後,對於一條邊,兩端節點若屬於不同端,則切斷。
用GrabCut進行前景檢測
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('3_2.jpg')
mask = np.zeros(img.shape[:2],np.uint8) # 創建一個與所加載圖像同形狀的掩模,0填充

bgdModel = np.zeros((1,65),np.float64)  # 背景模型
fgdModel = np.zeros((1,65),np.float64)  # 前景模型

rect = ( 100 , 50 , 1024 , 1024 )
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,10,cv2.GC_INIT_WITH_RECT)   # 10爲迭代次數

# 至此,掩模已經變成包含0-3之間的值
# 0,2轉爲0;1,3轉爲1,保存在mask2
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img * mask2[:,:,np.newaxis]   # np.newaxis : 增加新維度

plt.subplot(121) , plt.imshow(img)
plt.title("grabcut")  , plt.xticks([]) , plt.yticks([])

plt.subplot(122) , plt.imshow(cv2.cvtColor(cv2.imread('3_2.jpg'),cv2.COLOR_BGR2RGB))
plt.title("original") , plt.xticks([]) , plt.yticks([])
plt.show()
分水嶺算法進行圖像分割
- 獲取二值圖像
- 獲取前景像素,前景爲0
- 獲取背景像素,255爲背景
- 背景與前景做減運算,獲取未知區域255
- 獲取標記圖,合成標記圖像(未知0,背景1,前景>1)
  • 將原圖和標記圖像輸入分水嶺算法
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('3_4.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret , thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

kernel = np.ones((3,3),np.uint8)
# morphologyEx變換去除噪聲數據(圖像膨脹後腐蝕),提取圖像特徵
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations=2)
# 對變換後的圖像膨脹操作,可得到大部分都是背景的區域
sure_bg = cv2.dilate(opening,kernel,iterations=3)
# 通過distanceTransform獲取確定的前景區域
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret , sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)

# 確定前景背景中重合部分
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)    # (重合即爲不確定區域,減運算結果存於unknown)

# 設置“柵欄”阻止水匯聚()
ret , markers = cv2.connectedComponents(sure_fg) # marker中背景區域爲0,其他爲1開始的整數

# 背景區域加1,這會將unknown區域設爲0
markers = markers + 1 # 保證背景是1
markers[unknown==255] = 0 # unknown置0(二值圖像背景[255]-前景[0]重合區域爲255)

# 打開門,讓水漫起來將“柵欄”染紅
markers = cv2.watershed(img,markers) #原圖和標記圖輸入分水嶺算法(0被識別爲unknown區域)
img[markers == -1] = [255,0,0]
plt.imshow(img)
plt.show()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章