本文将介绍如何使用分水岭算法对触摸和重叠的图像中的对象进行分割和提取。
参考:https://www.pyimagesearch.com/2015/11/02/watershed-opencv/
分水岭算法是一种分割的经典算法,在提取图像中连接或重叠的图像中的对象(例如上图中的硬币)时特别有用。 使用传统的图像处理方法(例如阈值检测和轮廓检测),我们将无法从图像中提取每个硬币–但是,利用分水岭算法,我们能够准确地检测和提取每个硬币。

简单阀值和边缘轮廓检测很强大,但对于图片中有重叠和互相接触的对象,简单阀值和轮廓检测将无能为力。

简单阀值和边缘轮廓检测结果如下所示:
硬币数量对不上,也不准确。

要应用分水岭算法,我们需要定义与图像中的对象相对应的标记。这些标记可以是用户定义的,也可以应用图像处理技术(例如阈值)为我们找到标记。
在应用分水岭算法时,获取准确的标记至关重要。
给定标记,我们可以计算欧几里得距离变换并将距离图传递给分水岭函数本身,该分水岭函数从初始标记开始并向外移动,从而“淹没”距离图中的山谷。在分割过程中,水的“池”相遇的地方可以视为边界线。 分水岭算法的输出是一组标签,其中每个标签对应于图像中的唯一对象。从那里开始,我们要做的就是分别遍历每个标签并提取每个对象。

# import the necessary packages
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# 我们已成功检测到图像中的所有九个硬币。此外,我们还能够清晰地绘制每个硬币周围的边界。这与使用简单阈值检测和轮廓检测的先前示例形成了鲜明对比,在先前示例中,仅(错误地)检测到两个对象。image = cv2.imread('D:/pyimagesearch/images/coin4.jpg')
# 应用金字塔均值漂移滤波 以提高阈值设置步骤的准确性  【金字塔均值偏移滤波可以看做是对彩色图像平滑颜色的一种操作】
shifted = cv2.pyrMeanShiftFiltering(image, 21, 51)
cv2.imshow("Input", image)# 将经过金字塔均值偏移滤波处理的图像 读取为灰度图像
# 应用Otsu的阈值将背景从前景中分割出来:
gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("Thresh", thresh)# 分割的第一步:通过distance_transform_edt计算欧几里德距离变换(EDT Euclidean distance)功能 此函数为每个前景像素计算最接近零的欧几里得距离(即背景像素)。
D = ndimage.distance_transform_edt(thresh)
# 在距离图中找到峰值(即局部最大值)。我们将确保每个峰之间的距离至少为20像素。采用peak_local_max的输出功能,并使用8连接性应用连接组件分析。
localMax = peak_local_max(D, indices=False, min_distance=20,labels=thresh)# 该函数的输出为我们提供了标记 然后我们将其馈入分水岭函数
# 分水岭算法  假设我们的标记代表我们的距离图中的局部最小值(即山谷),因此我们采用D的负值。
# 分水岭函数返回标签矩阵,一个NumPy数组,其宽度和高度与我们的输入图像相同。每个像素值作为唯一的标签值。具有相同标签值的像素属于同一对象。
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))# 最后一步是简单地循环唯一标签值并提取每个唯一对象
# loop over the unique labels returned by the Watershed
# algorithm
for label in np.unique(labels):# label为0 默认为背景,忽略if label == 0:continue# 为我们的遮罩分配内存 并将属于当前标签的像素设置为255(白色)。mask = np.zeros(gray.shape, dtype="uint8")mask[labels == label] = 255# 检测到遮罩中的轮廓   并提取最大的轮廓-该轮廓将代表图像中给定对象的轮廓/边界。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)
# show the output image
cv2.imshow("Output", image)
cv2.waitKey(0)

Python OpenCV分水岭算法分割和提取重叠或有衔接的图像中的对象相关推荐

  1. Python+Opencv分水岭算法

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

  2. 关于Opencv 分水岭算法种子点(注水口)的选取问题

    Opencv 分水岭算法 void watershed( InputArray image, InputOutputArray markers ); 官方文档中这样表述分水岭算法种子的选取 /* Be ...

  3. Opencv 分水岭算法 watershed的图像分割

    分水岭算法 参考博客: (1)迈克老狼2012   https://www.cnblogs.com/mikewolf2002/p/3304118.html (2)-牧野-              h ...

  4. opencv 分水岭算法详细理论+实践

    分水岭算法看了两天了,基本原理看着挺简单,但是opencv中具体的实现方式看着还挺困难的.今天就说说我理解的地方,有很多不太理解的还得以后深入学习时候再补充. 基本原理:分水岭实则为两个盆地的交界处, ...

  5. Opencv分水岭算法——watershed自动图像分割用法

    分水岭算法是一种图像区域分割法,在分割的过程中,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水岭算法的一个重要特 ...

  6. Python+OpenCV:阈值分割

    Python+OpenCV:阈值分割 阈值分割 ############################################################################ ...

  7. python图像计数_检测并计数图像中的对象

    我试图用python编写一个脚本来检测和计算图像中的对象,但我失败得很惨.在 这是我第一次对计算机视觉感兴趣并尝试一些东西.我已经尝试过使用cv2模块(opencv),遵循关于特征匹配和模板匹配的教程 ...

  8. Python使用matplotlib可视化多个时间序列数据、在同一个可视化图像中可视化多个时间序列数据(Multiple Time Series)

    Python使用matplotlib可视化多个时间序列数据.在同一个可视化图像中可视化多个时间序列数据(Multiple Time Series) 目录

  9. OpenCV学习笔记(二):3种常用访问图像中像素的方式

    OpenCV学习笔记(二):3种常用访问图像中像素的方式 #include <opencv2/opencv.hpp>using namespace cv; using namespace ...

最新文章

  1. 【机器视觉案例】(5) AI视觉,远程手势控制虚拟计算器,附python完整代码
  2. 数学之美:“植物身上的黄金分割”
  3. pyqt5入门教程(三)
  4. 计算机组装维修期末考试题,2014计算机组装维修期末考试题(1)
  5. RIP RETE时间获得PHREAKY
  6. 2020 kali 切换中文显示_Kali设置中文
  7. [实践篇]13.9 如何使用gcore(ramdump)排查内存黑洞?
  8. 以太坊地址检测算法golang实现
  9. python斐波那契数列前20项_Python初学者笔记:打印出斐波那契数列的前10项
  10. 关于spoolsv.exe 报错,并打印服务停止的问题
  11. 学数学计算机考研,计算机考研考数学
  12. mysql isnum()_mysql 一些基础的语法和命令
  13. java-php-python-springboot线上教学平台计算机毕业设计
  14. 解析 Java 类和对象的初始化过程(zhuang张 国建 (guojian.zhang@gmail
  15. 龙格现象 图像对比及Python代码实现
  16. 微信抢红包代码 python_Python实现的微信红包提醒功能示例
  17. LeetCode 1.Minimum Path Sum 2.Unique Paths I and II
  18. pandas使用to_datetime函数将时间字符串转化为时间对象、其中月份内容为字母而非数字(例如,“January 2, 2022“)
  19. excel vlookup函数使用
  20. endnote中CWYW无文件_Endnote软件的使用,有图有干货!

热门文章

  1. 自动驾驶平台,阵营, 主要传感器与场景联系
  2. Android 编译源码 注意事项
  3. 网站项目必备——12款白富美型 jQuery 图片轮播插件
  4. HDU-1459.非常可乐(BFS )
  5. 闰年流程图(18网三袁昳)
  6. python几种数据类型的取值方式
  7. 20155308『网络对抗技术』Exp7:网络欺诈防范
  8. 自定义的类型转换器中怎样自定义错误消息?(待解答)
  9. 什么是IOC为什么要使用IOC
  10. Ubuntu下如何解压缩zip,tar,tar.gz,tar.bz2文件