1. 程式人生 > >Python之opencv 分水嶺分割演算法

Python之opencv 分水嶺分割演算法

分水嶺分割演算法
分水嶺分割演算法的定義網上隨便百度一下就可以知道了,我就說一下我的理解,有不對的希望大家也可以幫忙指正。
對於分水嶺分割,我的理解是,一幅影象是由不同大小的灰度級畫素值構成的,可以把不同的大小想象成不同高度的山脈,接著在地表(就是從畫素灰度級0開始)向這個山脈地脈注入水,那麼當一個山脈與另一個山脈將要融合的線上就是影象的邊界,當水注入最高山脈後形成的現象就是整幅圖的邊界。

cv2.watershed(引數1,引數2)

Python中的分水嶺分割演算法有兩個引數,第一個引數是帶分割的影象,且為8位三通道彩色影象,第二個引數的掩碼,第二個引數必須是32位單通道的影象。下面是完整程式碼,在使用分水嶺分割演算法之前的步驟是為了獲取掩碼影象

import cv2
import numpy as np
img=cv2.imread(r'D:\Python Code\waterSgmention\water_coins.jpg')
cv2.imshow('img',img)
#將影象轉化為灰度影象
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#閾值化處理
ret,thresh=cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
cv2.imshow('thresh',thresh)

硬幣原圖 二值化影象

#noise removal
#opening operator是先腐蝕後膨脹,可以消除一些細小的邊界,消除噪聲 kernel=np.ones((3,3),np.uint8) opening=cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations=2) cv2.imshow('opening',opening)

二值化後由於影象存在一些噪聲(即白色的點),可以用形態學的開操作的處理。opening操作可以消除物體之間細小的粘縫,為了展示openin操作的效果,我將核心設定為5*5,並且迭代了5次,其效果如下:

opening

   獲得掩碼需要知道影象的前景和背景,在這裡我的理解是:前景就是有硬幣的影象,背景就是除硬幣之前的區域。我們要確保我們獲得的背景圖中不包含前景圖的區域,通過腐蝕操作,將硬幣的區域放大,那麼剩下的就一定是背景區域了,即可以確定背景圖
#sure background area
sure_bg=cv2.dilate(opening,kernel,iterations=3)
cv2.imshow('bg',sure_bg)

背景圖效果
背景圖效果

如上所說,確定前景,就是硬幣的區域
距離變化 可用來實現目標細化、骨架提取、形狀插值及匹配、粘連物體的分離等。距離變換是針對二值影象的一種變換。在二維空間中,一幅二值影象可以認為僅僅包含目標和背景兩種畫素,目標的畫素值為1,背景的畫素值為0;距離變換的結果不是另一幅二值影象,而是一幅灰度級影象,即距離影象,影象中每個畫素的灰度值為該畫素與距其最近的背景畫素間的距離(就是原二值影象中畫素值為1的畫素點與最近的畫素點為0的畫素點之間的距離)
由於掩碼是一幅二值影象,所以經過距離變化後還需要將影象進行二值化
這樣子的結果影象中畫素點為1的區域就一定是硬幣的位置,即前景圖

#finding sure foreground area
dist_transfrom=cv2.distanceTransform(opening,cv2.DIST_L2 ,5)
#cv2.imshow('dist_transfrom',dist_transfrom)
ret,sure_fg=cv2.threshold(dist_transfrom,0.7*dist_transfrom.max(),255,0)

cv2.imshow('sure_fg',sure_fg)

前景圖效果
sure_fg

   現在我們已經知道原影象的前景圖和背景圖了,但是還有一些區域是我們所不知道的就是原影象中硬幣與硬幣之間相連的那些或者疊加的區域,即邊界,通過背景圖減去前景圖可以大概的獲得這些未知的邊界
#finding unknow region
sure_fg=np.uint8(sure_fg)
unknow=cv2.subtract(sure_bg,sure_fg) #背景-前景
cv2.imshow('unknow',unknow)

邊界

官網上說connectedComponents函式可以使影象中標記背景畫素點為0,飛背景畫素點從1開始累加分別標記

ret,maker=cv2.connectedComponents(sure_fg)
maker=maker+1
maker[unknow==255]=0

最終使用分水嶺分割演算法

maker = cv2.watershed(img,maker)
cv2.imshow('maker',maker)
img[maker == -1] = [0,0,255]
cv2.imshow('result',img)

在經過分水嶺分割演算法後,邊界處會標記為-1
這裡寫圖片描述

這裡面有幾個點我還沒有很清楚的理解,等後續理解了再來更新
官網參考文獻