分水岭算法
基于距离变换的分水岭分割算法一般流程:
1,输入图像
2,变换为灰度图像
3,二值化图像
4,距离变换
5,寻找种子点
6,生成marker
7,分水岭变换
8,输出图像
#20,分水岭算法
import cv2 as cv
import numpy as np
def image_Watershed(image):
print(image.shape)
#首先对原图像进行降噪处理
image=cv.pyrMeanShiftFiltering(image,10,100)
#将图像转化为灰度图像
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
#对灰度图像进行二值化处理
ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
#将二值化图像显示
cv.imshow("binary",binary)
#由于图像内部存在一些噪声点,因此先对图像进行形态学开操作
#设置形态学结构处理的核
kernel=cv.getStructuringElement(cv.MORPH_RECT,(3,3))
#对二值图像进行开运算操作之后再进行膨胀操作
open_image=cv.morphologyEx(binary,cv.MORPH_OPEN,kernel,iterations=2)
dilate_image=cv.dilate(open_image,kernel,iterations=3)
#显示图像
cv.imshow("od_image",dilate_image)
#距离变换
dist=cv.distanceTransform(dilate_image,cv.DIST_L2,3)
#将距离归一化处理
dist_output=cv.normalize(dist,0,1.0,cv.NORM_MINMAX)
#将距离变换的结果显示
cv.imshow("dist_demo",dist_output*60)
#根据阈值将marker选出并显示其二值化形式图像
ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)
surface_fg = np.uint8(surface)
cv.imshow("surface-bin", surface_fg)
unknown = cv.subtract(dilate_image, surface_fg)
ret, markers = cv.connectedComponents(surface_fg)
#打印出边界个数为25,这里把最外面的图像矩形框也算成为一个边界了
print(ret)
# 对marker进行分水岭变换
markers = markers + 1
#将像素值为0的为分水岭
markers[unknown==255] = 0
markers = cv.watershed(src, markers=markers)
#将分水岭边界设置为红色
src[markers==-1] = [0, 0, 255]
#显示结果
cv.imshow("result", src)
src = cv.imread(r'F:\OutputResult\SrcImage\coins3.jpg')
cv.imshow("src",src)
image_Watershed(src)
cv.waitKey(0)
cv.destroyAllWindows()
先进行二值化,然后进行开运算之后加上膨胀操作消除内部白色斑点效果如下:
最终输出结果:边框数为25个,这里把最外面的矩形框也算成了一个边界了。