一、分水嶺算法介紹
通過(guò)pycharm安裝時(shí)空門
問(wèn)題: 講一下分水嶺算法的原理、實(shí)現(xiàn)步驟、以及應(yīng)用。
回答:
分水嶺算法是一種基于圖像變換與分割的圖像分析算法,主要用于圖像分割。該算法可以解決很多圖像處理領(lǐng)域的問(wèn)題,例如醫(yī)學(xué)圖像分析、面部識(shí)別、數(shù)字水印等。下面將詳細(xì)介紹分水嶺算法的基本原理和實(shí)現(xiàn)步驟。
一、基本原理
分水嶺算法基于一種數(shù)學(xué)概念——圖像灰度級(jí)視為水面高度,圖像亮度高的點(diǎn)相當(dāng)于高水位,圖像亮度低的點(diǎn)相當(dāng)于低水位,圖像分割時(shí)會(huì)將種子點(diǎn)視為河流的發(fā)源地,河流順著最容易流動(dòng)的方向匯聚,最后形成的匯聚點(diǎn)之間就是圖像需要分割的部分。這個(gè)過(guò)程可以把整幅圖叫做“下雨”,黑色區(qū)域就是匯水區(qū),白色區(qū)域就是雪山區(qū),而水位就往著低的地方流。當(dāng)兩個(gè)黑色的匯水區(qū)相遇的時(shí)候,它們合并成一個(gè)。二、實(shí)現(xiàn)步驟
分水嶺算法的基本實(shí)現(xiàn)流程如下:
1.對(duì)圖像進(jìn)行預(yù)處理。首先對(duì)原始圖像進(jìn)行濾波和二值化,得到一個(gè)二值圖像。接著,對(duì)二值圖像執(zhí)行開運(yùn)算和閉運(yùn)算操作,填補(bǔ)空洞,平滑過(guò)渡,消除噪聲等。
2.尋找圖像的種子點(diǎn)。根據(jù)應(yīng)用需求,設(shè)置初始種子點(diǎn),對(duì)于每一個(gè)種子點(diǎn),都會(huì)生成一個(gè)分水嶺。
3.計(jì)算距離變換圖像。距離變換圖像是對(duì)二值圖像中每一個(gè)前景點(diǎn)離最近的背景點(diǎn)的距離進(jìn)行計(jì)算,這個(gè)距離就是該點(diǎn)的灰度值。
4.計(jì)算梯度圖像。梯度圖像是對(duì)距離變換圖像應(yīng)用Sobel、Prewitt算子等獲得的圖像,反映了圖像的邊緣信息,即像素值在垂直和水平方向上的變化率。
5.將距離變換圖像和梯度圖像相乘,得到一個(gè)新的圖像。
6.對(duì)于新的圖像進(jìn)行閾值處理,以唯一地定義圖像的每一個(gè)像素所屬的區(qū)域。這里的閾值可以根據(jù)圖像的需求進(jìn)行調(diào)整。
7.分水嶺變換操作。對(duì)于閾值處理后的圖像,通過(guò)分水嶺變換得到最終的分割結(jié)果。
8.對(duì)分割結(jié)果進(jìn)行后處理。對(duì)于分割結(jié)果進(jìn)行細(xì)化、合并以及消除孤立點(diǎn)等后處理操作,以獲得更好的效果。三、應(yīng)用
1.基于分水嶺算法的道路提取
這種應(yīng)用將圖像處理引進(jìn)到公路建設(shè)領(lǐng)域,以實(shí)現(xiàn)對(duì)交通道路的智能自動(dòng)化監(jiān)測(cè)。通過(guò)分水嶺算法對(duì)圖像進(jìn)行分割,然后根據(jù)道路特征進(jìn)行篩選,最后提取出公路。這種方法在實(shí)踐中表現(xiàn)出了很好的效果,能夠自動(dòng)識(shí)別多種復(fù)雜的路面拓?fù)浣Y(jié)構(gòu)。
2.基于分水嶺算法的肝臟圖像分割
該應(yīng)用將分水嶺算法應(yīng)用于醫(yī)學(xué)圖像處理中,通過(guò)對(duì)肝臟 CT 圖像的分割,實(shí)現(xiàn)對(duì)病變區(qū)域的定位和診斷。該方法的優(yōu)點(diǎn)在于具有高計(jì)算效率和良好的分割準(zhǔn)確性,可以很好地支持真實(shí)世界的醫(yī)學(xué)模型。
3.基于分水嶺算法的紅外圖像分割
該應(yīng)用將分水嶺算法應(yīng)用于紅外圖像分割中,主要用于航天器和無(wú)人機(jī)紅外圖像的定位和監(jiān)控。該方法依據(jù)熱源強(qiáng)度不同,將圖像分成不同的區(qū)域,從而實(shí)現(xiàn)對(duì)目標(biāo)的定位和跟蹤。該方法具有高魯棒性和準(zhǔn)確性,可以有效地處理復(fù)雜的紅外圖像。
總之,分水嶺算法是一種強(qiáng)大的圖像分割技術(shù),在不同領(lǐng)域中得到廣泛的應(yīng)用。它能夠幫助我們解決很多圖像處理問(wèn)題,提高生產(chǎn)效率和效果。隨著計(jì)算機(jī)技術(shù)的不斷發(fā)展,相信分水嶺算法在未來(lái)也會(huì)得到更廣泛的應(yīng)用與研究。
二、練習(xí)圖片(圖片來(lái)源網(wǎng)上,僅作學(xué)術(shù)交流分享,侵聯(lián)刪)

三、代碼
# -*- coding:utf-8 -*-
import cv2 as cv
import numpy as np
import cv2
def stackImages(scale,imgArray):
rows = len(imgArray)
cols = len(imgArray[0])
# & 輸出一個(gè) rows * cols 的矩陣(imgArray)
# print(rows,cols)
# & 判斷imgArray[0] 是不是一個(gè)list
rowsAvailable = isinstance(imgArray[0], list)
# & imgArray[][] 是什么意思呢?
# & imgArray[0][0]就是指[0,0]的那個(gè)圖片(我們把圖片集分為二維矩陣,第一行、第一列的那個(gè)就是第一個(gè)圖片)
# & 而shape[1]就是width,shape[0]是height,shape[2]是
width = imgArray[0][0].shape[1]
height = imgArray[0][0].shape[0]
# & 例如,我們可以展示一下是什么含義
# cv2.imshow("img", imgArray[0][1])
if rowsAvailable:
for x in range (0, rows):
for y in range(0, cols):
# & 判斷圖像與后面那個(gè)圖像的形狀是否一致,若一致則進(jìn)行等比例放縮;否則,先resize為一致,后進(jìn)行放縮
if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
else:
imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
# & 如果是灰度圖,則變成RGB圖像(為了弄成一樣的圖像)
if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
# & 設(shè)置零矩陣
imageBlank = np.zeros((height, width, 3), np.uint8)
hor = [imageBlank]*rows
hor_con = [imageBlank]*rows
for x in range(0, rows):
hor[x] = np.hstack(imgArray[x])
ver = np.vstack(hor)
# & 如果不是一組照片,則僅僅進(jìn)行放縮 or 灰度轉(zhuǎn)化為RGB
else:
for x in range(0, rows):
if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
else:
imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
hor= np.hstack(imgArray)
ver = hor
return ver
def watershed_demo(img):
# 圖像預(yù)處理
# 二值化前先進(jìn)性灰度化、其實(shí)也可以通過(guò)其他通道,這里用灰度圖就足夠了
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 固定閾值二值化,將大于thresh得像素點(diǎn)設(shè)置為maxval,
ret,binary = cv.threshold(gray,thresh=110,maxval=255,type = cv.THRESH_BINARY)
# 形態(tài)學(xué)開操作,先腐蝕后膨脹,去掉一些小噪聲
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE,(11,11))
open = cv.morphologyEx(binary,cv.MORPH_OPEN,kernel,iterations=1)
# 對(duì)二值化圖像進(jìn)行膨脹、用來(lái)后面于masker相減
kernel_dilate = cv.getStructuringElement(cv.MORPH_ELLIPSE,(40,40))
dilate = cv.dilate(open,kernel,iterations=1)
# distance transform
dist = cv.distanceTransform(open,cv.DIST_L2,3) # 距離變換,可以認(rèn)為中間部分距離越大、邊緣越小
dist_output = cv.normalize(dist,0,1.0,cv.NORM_MINMAX)*50 # 進(jìn)行歸一化
ret,surface = cv.threshold(dist,dist.max()*0.6,255,cv.THRESH_BINARY) # 對(duì)歸化的圖片再進(jìn)行二值化,對(duì)中間部分進(jìn)行截?cái)?/span>
surface_fg = np.uint8(surface) # 將圖片的格式轉(zhuǎn)為8位
unknown = cv.subtract(dilate,surface_fg) # 用膨脹之后的圖片于距離變換后二值化圖片進(jìn)行減操作
ret,markers = cv.connectedComponents(surface_fg) # 連通域操作
# watershed transform
markers = markers +1 #
markers[unknown ==255] =0
markers = cv.watershed(img,markers = markers)
# 去掉邊緣,因?yàn)榻?jīng)過(guò)分水嶺操作之后,多出了一個(gè)邊界
markers[0] = 1
markers[-1] = 1
markers[0:img.shape[0],0] = 1
markers[0:img.shape[0],-1] = 1
# 進(jìn)行連通域操作
open[markers ==-1] = 0 # 利用分水嶺出來(lái)的線條進(jìn)行分割
k3 = np.ones((4,4),np.uint8) # 進(jìn)行稍微的腐蝕
open = cv.erode(open,k3)
# num_labels:連通域數(shù)量、labels:大小和原圖一樣大,每一個(gè)連通域會(huì)及進(jìn)行標(biāo)記,stats:x,y,wh,s,centroid:中心
num_labels, labels, stats, centers = cv2.connectedComponentsWithStats(open, connectivity=8)
# 利用連通域進(jìn)行不同輪廓畫出不同顏色
output = np.zeros((img.shape[0], img.shape[1], 3), np.uint8)
for i in range(1, num_labels):
mask = labels == i
output[:, :, 0][mask] = np.random.randint(0, 255)
output[:, :, 1][mask] = np.random.randint(0, 255)
output[:, :, 2][mask] = np.random.randint(0, 255)
# 因?yàn)閐ist沒(méi)有轉(zhuǎn)換為8位,保存圖片打開之后是黑色的話就需要進(jìn)行格式轉(zhuǎn)換。
dist_output= cv2.normalize(dist_output, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
dist= cv2.normalize(dist, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
#為了圖片更加好看,對(duì)所有圖片轉(zhuǎn)化為3通道
gray = cv.cvtColor(gray,cv.COLOR_GRAY2BGR)
binary = cv.cvtColor(binary,cv.COLOR_GRAY2BGR)
open = cv.cvtColor(open,cv.COLOR_GRAY2BGR)
dilate = cv.cvtColor(dilate,cv.COLOR_GRAY2BGR)
dist = cv.cvtColor(dist,cv.COLOR_GRAY2BGR)
dist_output = cv.cvtColor(dist_output,cv.COLOR_GRAY2BGR)
surface = cv.cvtColor(surface,cv.COLOR_GRAY2BGR)
surface_fg = cv.cvtColor(surface_fg,cv.COLOR_GRAY2BGR)
unknown = cv.cvtColor(unknown,cv.COLOR_GRAY2BGR)
gray[markers ==-1] =[0,0,255]
binary[markers == -1] = [0, 0, 255]
open[markers == -1] = [0, 0, 255]
dilate[markers == -1] = [0, 0, 255]
dist[markers ==-1] =[0,0,255]
dist_output[markers ==-1] =[0,0,255]
# 下面語(yǔ)句就沒(méi)有影響,因?yàn)閟urface的時(shí)候進(jìn)行了8位的轉(zhuǎn)換
surface[markers == -1] = [0,0,255]
surface_fg[markers == -1] = [255, 0, 255]
unknown[markers == -1] = [255, 0,255]
img[markers == -1] = [255, 0, 255]
imgStack = stackImages(1, ([gray,binary,open], [dilate,dist,dist_output], [surface,surface_fg,unknown]))
result = cv2.addWeighted(img, 0.8, output, 0.5, 0) # 圖像權(quán)重疊加
for i in range(1, len(centers)):
cv2.drawMarker(result, (int(centers[i][0]), int(centers[i][1])), (0, 0, 255), 1, 20, 2)
cv.namedWindow("stack",0)
cv.imshow("stack",imgStack)
cv.namedWindow("out",0)
cv.imshow("out",result)
cv.imwrite("save_03.png",imgStack)
cv.imwrite("binary.png",open)
cv.imwrite("save_04.png", result)
img = cv.imread("1.png")
watershed_demo(img)
cv.namedWindow("img",0)
cv.imshow("img",img)
cv.waitKey(0)
cv.destroyAllWindows()
四、效果


五、Opencv專欄
1.理論系列:
第一章:pycharm、anaconda、opencv、pytorch、tensorflow、paddlex等環(huán)境配置大全總結(jié)【圖像處理py版本】
第二章:OpenCv算法的基本介紹與應(yīng)用
第三章:OpenCv圖片、視頻讀寫操作與基本應(yīng)用
第四章:OpenCv閾值分割/二值化(單通道、多通道圖片)總結(jié)
2.項(xiàng)目系列:
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-777168.html
項(xiàng)目一:四六級(jí)改卷系統(tǒng)
項(xiàng)目二:實(shí)戰(zhàn)篇:粘連物體分割——利用幾何分割實(shí)現(xiàn)瓶蓋分割檢測(cè)
項(xiàng)目三:實(shí)戰(zhàn)篇:粘連物體分割——利用幾何分割實(shí)現(xiàn)硬幣分割檢測(cè)
項(xiàng)目四:實(shí)戰(zhàn)篇:粘連物體分割——利用幾何分割實(shí)現(xiàn)細(xì)胞分割檢測(cè)
==》 項(xiàng)目五:實(shí)戰(zhàn)篇:粘連物體分割——利用分水嶺算法實(shí)現(xiàn)糖豆分割檢測(cè)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-777168.html
到了這里,關(guān)于【實(shí)戰(zhàn)篇:粘連物體分割——利用分水嶺算法實(shí)現(xiàn)糖豆分割檢測(cè)】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!