欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

Python+Opencv分水岭算法

发布时间:2023/12/15 python 24 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Python+Opencv分水岭算法 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

目录

    • 一、分水岭算法(Watershed)简介
    • 二、分水岭算法实现步骤
    • 三、阈值和轮廓检测硬币分割代码实现与分析
    • 四、分水岭硬币分割代码实现
    • 五、代码效果展示与分析
    • 参考资料
    • 注意事项

一、分水岭算法(Watershed)简介

  所有的灰度图像都可视为拓扑平面,我们将灰度值高的区域看成山峰,将灰度值低的区域看成山谷,我们向图像上所有的"山谷"中注入不同颜色的水,不断的注水,水位则会不断上升,注入的水将灌满山谷,并可能淹没山峰,为了防止不同颜色的山谷中的水溢出汇合,我们可在汇合的地方筑起堤坝,故可将堤坝看作是对图像的分割后形成的边界。具体的事例如下图所示。

二、分水岭算法实现步骤

步骤1-构建梯度图像。
步骤2-通过一定规则生成n个最初的注水区域(先验知识或局部梯度最小值)。
步骤3-往注水区域内加水,当两注水区域即将合并时,记录下此时的边界。
步骤4-当图像边缘彻底被分割成n个独立区域是算法结束。
具体的实现过程如下图所示:

三、阈值和轮廓检测硬币分割代码实现与分析

# coding=utf-8 # 导入python包 from __future__ import print_function from skimage.feature import peak_local_max from skimage.morphology import watershed from scipy import ndimage import argparse import imutils import cv2# 设置参数并进行参数解析 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to input image") args = vars(ap.parse_args())# 读取图片 image = cv2.imread(args["image"]) # 进行mean—shift滤波 shifted = cv2.pyrMeanShiftFiltering(image, 21, 51) cv2.imshow("Input", image)# 进行图片灰度化处理 gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY) # 进行阈值分割 thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] cv2.imshow("Thresh", thresh)# 在阈值图片中寻找轮廓 cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) print("[INFO] {} unique contours found".format(len(cnts)))# 遍历所有的轮廓并依次显示不同的结果 for (i, c) in enumerate(cnts):((x, y), _) = cv2.minEnclosingCircle(c)cv2.putText(image, "#{}".format(i + 1), (int(x) - 10, int(y)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)cv2.drawContours(image, [c], -1, (0, 255, 0), 2)# 显示输出结果 cv2.imshow("Image", image) cv2.waitKey(0)


  上图展示了使用阈值和轮廓的分割结果。通过观察上图我们可以发现,阈值分割并不能很好的将硬币区分开来,轮廓检测算法也不能很好的获取所有的硬币的完整轮廓,即这两种思路都不能很好的解决硬币检测问题。

四、分水岭硬币分割代码实现

# coding=utf-8 # 导入相应的python包 from skimage.feature import peak_local_max from skimage.morphology import watershed from scipy import ndimage import numpy as np import argparse import imutils import cv2# 设置并解析参数 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to input image") args = vars(ap.parse_args())# 读取图片 image = cv2.imread(args["image"]) # 进行mean shift滤波 shifted = cv2.pyrMeanShiftFiltering(image, 21, 51) cv2.imshow("Input", image)# 进行灰度化处理 gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY) # 进行阈值分割 thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] cv2.imshow("Thresh", thresh)# 计算从每个二元像素到最近零像素的精确欧几里得距离,然后在距离图中找到峰值 D = ndimage.distance_transform_edt(thresh) localMax = peak_local_max(D, indices=False, min_distance=20, labels=thresh)# 利用8连通性对局部峰进行连通分量分析,然后应用分水岭算法 markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0] labels = watershed(-D, markers, mask=thresh) print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))# 循环显示标签 for label in np.unique(labels):# 如果该标签为0,则表示其为背景,直接忽略if label == 0:continue# 为标签区域分配内存并将在mask上绘制结果mask = np.zeros(gray.shape, dtype="uint8")mask[labels == label] = 255# 在mask上检测轮廓并获得最大的一个轮廓cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)c = max(cnts, key=cv2.contourArea)# 画一个圈把物体围起来((x, y), r) = cv2.minEnclosingCircle(c)cv2.circle(image, (int(x), int(y)), int(r), (0, 255, 0), 2)cv2.putText(image, "#{}".format(label), (int(x) - 10, int(y)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)# 显示最终结果 cv2.imshow("Output", image) cv2.waitKey(0)

运行方法:python watershed_segement.py --image 图片 (这里的图片需要更换为自己的图片)

五、代码效果展示与分析


  上图展示了分水岭硬币分割代码的运行结果。通过观察这些结果,我们可以获得一些信息,即使用分水岭算法可以很好地将具有重叠的硬币分割开来,并自动的对图片中的硬币个数进行统计。

参考资料

[1] 参考链接

注意事项

[1] 该博客是本人原创博客,如果您对该博客感兴趣,想要转载该博客,请与我联系(qq邮箱:1575262785@qq.com),我会在第一时间回复大家,谢谢大家的关注.
[2] 由于个人能力有限,该博客可能存在很多的问题,希望大家能够提出改进意见。
[3] 如果您在阅读本博客时遇到不理解的地方,希望您可以联系我,我会及时的回复您,和您交流想法和意见,谢谢。
[4] 本文测试的图片可以通过该链接进行下载。网盘链接-提取码:w2ss。
[5] 本人业余时间承接各种本科毕设设计和各种小项目,包括图像处理(数据挖掘、机器学习、深度学习等)、matlab仿真、python算法及仿真等,有需要的请加QQ:1575262785详聊,备注“项目”!!!

总结

以上是生活随笔为你收集整理的Python+Opencv分水岭算法的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。