本文使用python實現
import cv2 as cv
import numpy as np
def watershed_demo(src):
print(src.shape)
blurred = cv.pyrmeanshiftfiltering(src, 10, 100) # 去雜訊
gray = cv.cvtcolor(blurred, cv.color_bgr2gray) # 轉為灰度
ret, binary = cv.threshold(gray, 0, 255, cv.thresh_binary|cv.thresh_otsu) # 二值化
cv.imshow("binary_image", binary)
kernel = cv.getstructuringelement(cv.morph_rect, (3, 3)) # 產生乙個kernel
'''def getstructuringelement(shape: any, # 形狀
ksize: any, # kernel尺寸
anchor: any = none) -> none
'''mb = cv.morphologyex(binary, cv.morph_open, kernel, iterations=2) # 形態學操作
'''def morphologyex(src: any, # 原影象
op: any, # 操作型別
# morph_erode = 0, //腐蝕
# morph_dilate = 1, //膨脹
# morph_open = 2, //開操作
# morph_close = 3, //閉操作
# morph_gradient = 4, //梯度操作
# morph_tophat = 5, //頂帽操作
# morph_blackhat = 6, //黑帽操作
# morph_hitmiss = 7
kernel: any, # 用於膨脹操作的結構元素,kernel
dst: any = none,
anchor: any = none, # 參考點
iterations: any = none,
bordertype: any = none,
bordervalue: any = none) -> none
morph_open(開),內部就是進行了先腐蝕後膨脹的操作。
morph_close(閉),其實內部就是進行了先膨脹後腐蝕的操作。
morph_gradient(梯度),內部是膨脹減去腐蝕。
'''sure_bg = cv.dilate(mb, kernel, iterations=3) # 對輸入影象用特定結構元素進行膨脹操作
'''def dilate(src: any,
kernel: any,
dst: any = none,
anchor: any = none,
iterations: any = none,
bordertype: any = none,
bordervalue: any = none) -> none
'''cv.imshow("mor_opt", sure_bg)
# 距離變換
dist = cv.distancetransform(mb, cv.dist_l2, 3) # 距離變換
'''def distancetransform(src: any, # 二值化影象
distancetype: any, # 計算距離的型別,cv_dist_l1、cv_dist_l2 、cv_dist_c
masksize: any, # 距離變換掩碼矩陣的大小
dst: any = none,
dsttype: any = none) -> none
'''dist_output = cv.normalize(dist, 0, 1.0, cv.norm_minmax)
cv.imshow("distance_t", dist_output*50)
ret, su***ce = cv.threshold(dist, dist.max()*0.6, 255, cv.thresh_binary)
cv.imshow("su***ce_bin", su***ce)
su***ce_fg = np.uint8(su***ce)
unknown = cv.subtract(sure_bg, su***ce_fg) # 影象的相減操作
'''def subtract(src1: any,
src2: any,
dst: any = none,
mask: any = none, # 可選操作掩碼; 這是乙個8位單通道陣列,用於指定要更改的輸出陣列的元素。
dtype: any = none) -> none # 輸出陣列的可選深度
'''ret, markers = cv.connectedcomponents(su***ce_fg) # 連通域標識
'''def connectedcomponents(image: any, # image是threshold得到的二值圖
labels: any = none,
connectivity: any = none,
ltype: any = none) -> none
'''print(ret)
# 分水嶺
markers = markers + 1
markers[unknown == 255] = 0
markers = cv.watershed(src, markers=markers)
'''def watershed(image: any,
markers: any) -> none
第二個入參markers必須包含了種子點資訊。
在執行分水嶺函式watershed之前,必須對第二個引數markers進行處理,它應該包含不同區域的輪廓,
每個輪廓有乙個自己唯一的編號,輪廓的定位可以通過opencv中findcontours方法實現,這個是執行
分水嶺之前的要求。接下來執行分水嶺會發生什麼呢?演算法會根據markers傳入的輪廓作為種子(也就是
所謂的注水點),對影象上其他的畫素點根據分水嶺演算法規則進行判斷,並對每個畫素點的區域歸屬進行劃
定,直到處理完影象上所有畫素點。而區域與區域之間的分界處的值被置為「-1」,以做區分。
'''src[markers == -1] = [0, 0, 255]
cv.imshow("result_image", src)
src = cv.imread("c:/users/admin/desktop/21.jpg") # 開啟一張
cv.namedwindow("input image", cv.window_autosize) # 設定尺寸,自動
cv.imshow("input image", src) # 顯示影象
watershed_demo(src)
cv.waitkey(0)
cv.destroyallwindows()
結果 opencv 分水嶺演算法
分水嶺演算法是一種簡單的影象分割演算法,具體是人為規定兩點 以兩點為例 然後把這兩點看做低谷,向裡面注水,不停地蔓延,直到兩點形成的湖交界。opencv自帶了這個程式。摘抄如下,其中我做了一些修改。本程式的目的是測試分水嶺演算法 include include include include usi...
opencv實現分水嶺演算法
分水嶺演算法原理 iplimage marker mask 0 iplimage markers 0 iplimage img0 0,img 0,img gray 0,wshed 0 iplimage img gray 0,wshed 0 cvpoint prev pt void on mouse ...
OpenCV之分水嶺演算法
在許多實際的應用中,我們需要分割影象,但是無法從背景影象中獲得有用資訊。但是分水嶺演算法在這方面往往非常有效,它可以將影象中的邊緣轉化為 山脈 將均勻區域轉化為 山谷 這樣有助於分割目標。分水嶺演算法是一種記憶拓撲理論的數學形態學的分割方法,其基本思想是把影象看作測地學上的拓撲地貌,影象中每點畫素的...