圖像的分割與修複
圖像分割的基本概念
- 什麼是圖像分割
将前景物體從背景中分離出來。
- 圖像分割的方法
之前的很多方法都是圖像分割的前置步驟,比如腐蝕、膨脹、二值化等等。圖像分割方法又分為傳統的圖像分割方法和基于深度學習的圖像分割方法。
- 傳統的圖像分割方法
- 分水嶺法
- GrabCut方法
- MeanShift法
- 背景扣除
- 分水嶺法原理

上圖表示圖像有一定的梯度,0代表黑色,代表比較低窪的地方,白色是255,代表一個峰點。當我們使用不同的顔色向低窪處灌水。
當兩個低窪處的水要打通的時候,此時這個顔色就會産生一個沖突。在沖突點的地方設定一個邊界點,這樣就将不同的區域給分割開來。但它也是有問題的。
當圖像中存在過多的極小區域而産生許多小的集水盆,但實際上我們真正想要的是一個大塊,視為一個整體。但通過分水嶺法就可能分成很多的小塊。對于傳統的分水嶺法可能會把一張圖切割的很碎,不利于我們後面的處理。
但幸運的是,OpenCV的分水嶺法可以将一大塊分成一整塊。
- 分水嶺法的處理步驟
- 标記背景
- 标記前景
- 标記未知域
- 進行分割
現在我們要對這張圖檔進行分割
import cv2
import numpy as np
if __name__ == "__main__":
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
img = cv2.imread("/Users/admin/Documents/9527.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化,cv2.THRESH_OTSU表示自适應門檻值
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 進行兩次開運算
open = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# 進行一次膨脹
bg = cv2.dilate(open, kernel, iterations=1)
# 擷取前景物體,計算非0值到離它距離最近的0值之間的距離
# cv2.DIST_L2為距離的計算方式,這裡為歐式距離
# maskSize:掃描時的卷積核大小,L1時用3*3,L2時用5*5
dist = cv2.distanceTransform(open, cv2.DIST_L2, 5)
ret, fg = cv2.threshold(dist, 0.7 * dist.max(), 255, cv2.THRESH_BINARY)
fg = np.uint8(fg)
# 擷取未知區域
unknow = cv2.subtract(bg, fg)
# 建立連通域,求所有非0相同像素的連通域,它還有一個參數為連通周圍的4個還是
# 8個,預設為8個
ret, marker = cv2.connectedComponents(fg)
marker += 1
marker[unknow == 255] = 0
# 進行圖像分割
result = cv2.watershed(img, marker)
img[result == -1] = [0, 0, 255]
while True:
cv2.imshow('img', img)
key = cv2.waitKey()
if key & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
複制
運作結果
GrabCut方法