OpenCV的分水嶺演算法

2021-10-07 08:58:26 字數 3675 閱讀 1500

本文使用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之分水嶺演算法

在許多實際的應用中,我們需要分割影象,但是無法從背景影象中獲得有用資訊。但是分水嶺演算法在這方面往往非常有效,它可以將影象中的邊緣轉化為 山脈 將均勻區域轉化為 山谷 這樣有助於分割目標。分水嶺演算法是一種記憶拓撲理論的數學形態學的分割方法,其基本思想是把影象看作測地學上的拓撲地貌,影象中每點畫素的...