凤凰体育平台 分水岭算法(Python + OpenCV)

日期:2021-01-18 08:29:21 浏览量: 157

分水岭算法算法的思想

最常用的分水岭算法是1990年代提出的基于灰度图像分割的算法。分水岭算法是与自适应二值化有关的算法。下图显示了此方法的工作原理。假设图中对象的灰度值较低亚博全站 ,而背景灰度值较高。图中的曲线代表沿着平面的灰度直线,并且该直线穿过两个靠近的物体。

分水岭算法_乌镇分水墩_分水高级中学网站

图1

分水岭算法通常从低阈值开始,该阈值仍然可以正确分割每个对象,然后随着阈值逐渐增加并上升到最佳值(连接到接近背景的灰度值)分水岭算法,每个对象将不会合并。只要正确使用阈值,在此基础上添加一个最佳阈值(该阈值用于判断前景和背景)也将具有很好的区分效果。

分水岭算法_乌镇分水墩_分水高级中学网站

使用分水岭算法时,我们需要选择种子点(局部最小点),可以使用模板找到该种子点。实际上,这是在确定阈值华体会首页 ,即从阈值开始增加(可以理解为从底部注水开始,继续增加阈值),当阈值增加到最佳阈值时(可以理解为水是填充,是时候确定水坝了百家乐APP ,这时的水坝就是我们需要的边界分界线。

从以上分析可以看出,初始阈值(种子点)的选择对最终分割结果的影响更大。如果在阈值1处选择了初始阈值og真人 ,则低对比度的对象将在开始时丢失,并且将随着阈值的增加而与相邻对象合并(显然无法获得良好的分割效果)。如果将种子点的值选择为阈值2分水岭算法,则对象1和对象2将在开始时合并。最终阈值(dam)决定了最终边界与实际对象的拟合程度。

乌镇分水墩_分水岭算法_分水高级中学网站

OpenCV的分水岭算法亚博代理 ,关键是如何找到满足API要求的注释矩阵生成器(矩阵的大小与图像矩阵相同)。该代码使用cv2.connectedComponent()语句比较图像对象进行注释。

OpenCV + Python语句

乌镇分水墩_分水岭算法_分水高级中学网站

# import cv2
# import numpy as np
# from matplotlib import pyplot as plt
# img_color = cv2.imread("sources/coins.jpg",1)
# img_gray = cv2.cvtColor(img_color,cv2.COLOR_BGR2GRAY)
# img_gray = cv2.Canny(img_gray, 100,180)
#
# img_contours,contours, hierarchy = cv2.findContours(img_gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
# cv2.drawContours(img_color,contours,-1,(0,0,255),2)  # 画出轮廓
#
# retval, markers = cv2.connectedComponents(img_contours)
# # cv2.watershed(img_contours, markers)
# print(markers[])
# cv2.imshow("1",markers)
# cv2.waitKey(0)
"""
完成分水岭算法步骤:
1、加载原始图像
2、阈值分割,将图像分割为黑白两个部分
3、对图像进行开运算,即先腐蚀在膨胀
4、对开运算的结果再进行 膨胀,得到大部分是背景的区域
5、通过距离变换 Distance Transform 获取前景区域
6、背景区域sure_bg 和前景区域sure_fg相减,得到即有前景又有背景的重合区域
7、连通区域处理
8、最后使用分水岭算法
"""
import cv2
import numpy as np
# Step1. 加载图像
img = cv2.imread('sources/Road.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Step2.阈值分割,将图像分为黑白两部分
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# cv2.imshow("thresh", thresh)
# Step3. 对图像进行“开运算”,先腐蚀再膨胀
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# cv2.imshow("opening", opening)
# Step4. 对“开运算”的结果进行膨胀,得到大部分都是背景的区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
cv2.imshow("sure_bg", sure_bg)
# Step5.通过distanceTransform获取前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)  # DIST_L1 DIST_C只能 对应掩膜为3    DIST_L2 可以为3或者5
ret, sure_fg = cv2.threshold(dist_transform, 0.1 * dist_transform.max(), 255, 0)
cv2.imshow("sure_fg", sure_fg)
# Step6. sure_bg与sure_fg相减,得到既有前景又有背景的重合区域   #此区域和轮廓区域的关系未知 
sure_fg = np.uint8(sure_fg)
unknow = cv2.subtract(sure_bg, sure_fg)
# Step7. 连通区域处理
ret, markers = cv2.connectedComponents(sure_fg,connectivity=8) #对连通区域进行标号  序号为 0 - N-1 
markers = markers + 1           #OpenCV 分水岭算法对物体做的标注必须都 大于1 ,背景为标号 为0  因此对所有markers 加1  变成了  1  -  N
#去掉属于背景区域的部分(即让其变为0,成为背景)
# 此语句的Python语法 类似于if ,“unknow==255” 返回的是图像矩阵的真值表。
markers[unknow==255] = 0   
# Step8.分水岭算法
markers = cv2.watershed(img, markers)  #分水岭算法后,所有轮廓的像素点被标注为  -1 
print(markers)
img[markers == -1] = [0, 0, 255]   # 标注为-1 的像素点标 红
cv2.imshow("dst", img)
cv2.waitKey(0)

前几步中的形态处理(开放操作和扩张)和距离变换都是为了找到种子点。找到种子点后(即标记了原始图像),将执行分水岭算法

分水岭算法_乌镇分水墩_分水高级中学网站

效果图片

图2