目标

在本章中,

我们将学习使用分水岭算法实现基于标记的图像分割

我们将看到:cv.watershed()

理论

任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水位的上升,根据附近的山峰(坡度),来自不同山谷的水明显会开始合并,颜色也不同。为了避免这种情况,你要在水融合的地方建造屏障。你继续填满水,建造障碍,直到所有的山峰都在水下。然后你创建的屏障将返回你的分割结果。这就是Watershed背后的“思想”。你可以访问Watershed的CMM网页,了解它与一些动画的帮助。

但是这种方法会由于图像中的噪声或其他不规则性而产生过度分割的结果。因此OpenCV实现了一个基于标记的分水岭算法,你可以指定哪些是要合并的山谷点,哪些不是。这是一个交互式的图像分割。我们所做的是给我们知道的对象赋予不同的标签。用一种颜色(或强度)标记我们确定为前景或对象的区域,用另一种颜色标记我们确定为背景或非对象的区域,最后用0标记我们不确定的区域。这是我们的标记。然后应用分水岭算法。然后我们的标记将使用我们给出的标签进行更新,对象的边界值将为-1。

代码

下面我们将看到一个有关如何使用距离变换和分水岭来分割相互接触的对象的示例。

考虑下面的硬币图像,硬币彼此接触。即使你设置阈值,它也会彼此接触。

我们先从寻找硬币的近似估计开始。因此,我们可以使用Otsu的二值化。

import numpy as np

import cv2 as cv

from matplotlib import pyplot as plt

img = cv.imread('coins.png')

gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

ret, thresh = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV cv.THRESH_OTSU)

现在我们需要去除图像中的任何白点噪声。为此,我们可以使用形态学扩张。要去除对象中的任何小孔,我们可以使用形态学侵蚀。因此,现在我们可以确定,靠近对象中心的区域是前景,而离对象中心很远的区域是背景。我们不确定的唯一区域是硬币的边界区域。

因此,我们需要提取我们可确定为硬币的区域。侵蚀会去除边界像素。因此,无论剩余多少,我们都可以肯定它是硬币。如果物体彼此不接触,那将起作用。但是,由于它们彼此接触,因此另一个好选择是找到距离变换并应用适当的阈值。接下来,我们需要找到我们确定它们不是硬币的区域。为此,我们扩张了结果。膨胀将对象边界增加到背景。这样,由于边界区域已删除,因此我们可以确保结果中背景中的任何区域实际上都是背景。参见下图。

剩下的区域是我们不知道的区域,无论是硬币还是背景。分水岭算法应该找到它。这些区域通常位于前景和背景相遇(甚至两个不同的硬币相遇)的硬币边界附近。我们称之为边界。可以通过从sure_bg区域中减去sure_fg区域来获得。

# 噪声去除

kernel = np.ones((3,3),np.uint8)

opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 2)

# 确定背景区域

sure_bg = cv.dilate(opening,kernel,iterations=3)

# 寻找前景区域

dist_transform = cv.distanceTransform(opening,cv.DIST_L2,5)

ret, sure_fg = cv.threshold(dist_transform,0.7*dist_transform.max(),255,0)

# 找到未知区域

sure_fg = np.uint8(sure_fg)

unknown = cv.subtract(sure_bg,sure_fg)

查看结果。在阈值图像中,我们得到了一些硬币区域,我们确定它们是硬币,并且现在已分离它们。(在某些情况下,你可能只对前景分割感兴趣,而不对分离相互接触的对象感兴趣。在那种情况下,你无需使用距离变换,只需侵蚀就足够了。侵蚀只是提取确定前景区域的另一种方法。)

现在我们可以确定哪些是硬币的区域,哪些是背景。因此,我们创建了标记(它的大小与原始图像的大小相同,但具有int32数据类型),并标记其中的区域。我们肯定知道的区域(无论是前景还是背景)都标有任何正整数,但是带有不同的整数,而我们不确定的区域则保留为零。为此,我们使用cv.connectedComponents()。它用0标记图像的背景,然后其他对象用从1开始的整数标记。

但是我们知道,如果背景标记为0,则分水岭会将其视为未知区域。所以我们想用不同的整数来标记它。相反,我们将未知定义的未知区域标记为0。

# 类别标记

ret, markers = cv.connectedComponents(sure_fg)

# 为所有的标记加1,保证背景是0而不是1

markers = markers 1

# 现在让所有的未知区域为0

markers[unknown==255] = 0

参见JET colormap中显示的结果。深蓝色区域显示未知区域。当然,硬币的颜色不同。剩下,肯定为背景的区域显示在较浅的蓝色,跟未知区域相比。

现在我们的标记已准备就绪。现在是最后一步的时候了,使用分水岭算法。然后标记图像将被修改。边界区域将标记为-1。

markers = cv.watershed(img,markers)

img[markers == -1] = [255,0,0]

请参阅下面的结果。对某些硬币,它们接触的区域被正确地分割,而对于某些硬币,却不是。

附加资源

练习

OpenCV samples has an interactive sample on watershed segmentation, watershed.py. Run it, Enjoy it, then learn it.

python图像分割算法_OpenCV-Python 图像分割与Watershed算法 | 三十四相关推荐

  1. python程序设计实验指导书第1版实验三十四_《python编程基础》实验指导书.doc

    <python编程基础>实验指导书 PAGE 南 阳 理 工 学 院 <python编程基础>实验指导书 (2014版) 软件学院·软件工程教研室 2011.3 目录 TOC ...

  2. [Python人工智能] 三十四.Bert模型 (3)keras-bert库构建Bert模型实现微博情感分析

    从本专栏开始,作者正式研究Python深度学习.神经网络及人工智能相关知识.前一篇文章开启了新的内容--Bert,首先介绍Keras-bert库安装及基础用法及文本分类工作.这篇文章将通过keras- ...

  3. PhotoShop算法实现高级篇--色彩特效(三十五)

    PhotoShop算法实现高级篇--色彩特效(三十五) kezunhai@gmail.com http://blog.csdn.net/kezunhai Photoshop中有很多色彩特效,本文介绍几 ...

  4. PhotoShop算法实现高级篇-剪纸艺术滤镜(三十二)

    PhotoShop算法实现高级篇-剪纸艺术滤镜(三十二) kezunhai@gmail.com http://blog.csdn.net/kezunhai 剪纸是中国古代乃至今日的传统艺术,它的团简单 ...

  5. 程序员编程艺术第三十四~三十五章:格子取数问题,完美洗牌算法

    第三十四~三十五章:格子取数,完美洗牌算法 作者:July.caopengcs.绿色夹克衫.致谢:西芹_new,陈利人, Peiyush Jain,白石,zinking. 时间:二零一三年八月二十三日 ...

  6. 程序员编程艺术第三十四 三十五章 格子取数问题,完美洗牌算法

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 第三十四 ...

  7. python图像分割算法_Opencv(二)—图像分割之分水岭算法!

    做图像处理时,我们可能会遇到一个问题:我们只需要图片的一部分区域,如何把图片中的某部分区域提取出来 或者 图像想要的区域用某种颜色(与其它区域颜色不一致)标记起来 ,以上描述的问题在像处理领域称为 图 ...

  8. OpenCV系列之图像分割与Watershed算法 | 三十四

    目标 在本章中, 我们将学习使用分水岭算法实现基于标记的图像分割 我们将看到:cv.watershed() 理论 任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷.你开始用不同 ...

  9. python绘制汉字_OpenCV Python 绘制中文字

    By 凌顺 2019年9月12日 本示例使用的OpenCV版本是:4.1.1 运行Python的编辑器:Jupyter notebook 示例目的 通过使用PLI在图片上添加中文字符. PIL(Pyt ...

最新文章

  1. Vim杂记:Sublime的配色方案
  2. wince导航_宁可用手机导航,也不用汽车导航?
  3. 48session的生命周期
  4. 手机连接投影机的步骤_家用投影仪如何安装 家用投影仪安装方法【步骤详解】...
  5. js 转php json string,JS里字符串转json方法总结
  6. 使用FCKeditor2.2图片上传的小技巧
  7. Android中判断用户多次连续点击
  8. 如何确定一家培训机构值得信赖
  9. python读取同花顺数据_python爬取同花顺数据
  10. 1. 软件开发流程与QA工作流程
  11. 盒子模型与内外边距设置
  12. 关于百度搜索引擎优化的常见问题
  13. CSS3的2D动画属性
  14. C++为什么空格无法输出_47个快捷键、50个CAD技巧,终于知道为什么别人用CAD总比我快了!...
  15. 九龙证券|二股东迎大变革,这只零售股连收4板
  16. GlobalWoZ: 面向全球通用的人机对话系统——快速构建多语对话能力初探
  17. cas自定义登陆认证
  18. 下载及配置maven详细步骤
  19. shell 脚本处理多行文本的记录 -- awk
  20. vs2017无法下载安装文件,请检查internet连接

热门文章

  1. Apache Hadoop 启动报错:masternode:ssh: connect to host master port 22: Connection timed out 总结
  2. 计算机基本的应用是,计算机统考应用基础练习题
  3. 依赖配置中心实现注有@ConfigurationProperties的bean相关属性刷新
  4. mgg mysql_mgg文件怎么转换mp3格式?
  5. python播放本地视频_python opencv 读取本地视频文件 修改ffmpeg的方法
  6. 小说中场景的功能_《流浪地球》:从小说到电影
  7. android获取图片方向并旋转,Android 判断imageview角度并旋转
  8. c++ 二次开发 良田高拍仪_六枝特良田LYV-850加工中心导轨配套防护罩日常维修
  9. 主动断开socket链接_TCP连接与断开详解(socket通信)
  10. mysql安装、导入数据脚本