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

目标

在本章中,

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

我们将看到:cv.watershed()

理论

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

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

代码

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

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

20200123193207330.jpeg

我们先从寻找硬币的近似估计开始。因此,我们可以使用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)

20200123193207487.jpeg

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

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

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmRvdWFpbmk=,size_16,color_FFFFFF,t_70

剩下的区域是我们不知道的区域,无论是硬币还是背景。分水岭算法应该找到它。这些区域通常位于前景和背景相遇(甚至两个不同的硬币相遇)的硬币边界附近。我们称之为边界。可以通过从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)

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

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmRvdWFpbmk=,size_16,color_FFFFFF,t_70

现在我们可以确定哪些是硬币的区域,哪些是背景。因此,我们创建了标记(它的大小与原始图像的大小相同,但具有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中显示的结果。深蓝色区域显示未知区域。当然,硬币的颜色不同。剩下,肯定为背景的区域显示在较浅的蓝色,跟未知区域相比。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmRvdWFpbmk=,size_16,color_FFFFFF,t_70

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

markers = cv.watershed(img,markers)

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

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

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmRvdWFpbmk=,size_16,color_FFFFFF,t_70

附加资源

练习

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/539426.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux dns 问题吗,Linux下DNS的问题

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼Nov 9 06:36:22 BJ-linux kernel: end_request: I/O error, dev fd0, sector 0Nov 9 06:36:22 BJ-linux kernel: end_request: I/O error, dev fd0, sector 0Nov 9 06:37:06 BJ-linux system-config-network[4031]: - //etc/…

NEO从源码分析看共识协议

2019独角兽企业重金招聘Python工程师标准>>> 0x00 概论 不同于比特币使用的工作量证明(PoW)来实现共识,NEO提出了DBFT共识算法。DBFT改良自股权证明算法(PoS),我没有具体分析过PoS的源码&#x…

oracle实现id自增和设置主键

1、关于主键:在建表时指定primary key字句即可: create table test( id number(6) primary key, name varchar2(30) ); 如果是对于已经建好的表,想增加主键约束,则类似语法: alter table test add constraint p…

python scrapy框架基如何实现多线程_Python实现在线程里运行scrapy的方法

本文实例讲述了Python实现在线程里运行scrapy的方法。分享给大家供大家参考。具体如下: 如果你希望在一个写好的程序里调用scrapy,就可以通过下面的代码,让scrapy运行在一个线程里。 """ Code to run Scrapy crawler in a thr…

怎样在linux系统上安装r,Linux系统之路——如何在CentOS7.2安装R(示例代码)

使用ubuntu的小伙伴们直接使用命令sudo apt-get installr-base-dev或者r-base搞定。然而对于使用centos的我却一直卡在安装这一步,十分的悲催,只有羡慕的份,但也不至于在linux上使用不上R。办法还是有的,自己总结出两种方法&#…

自定义实现栈的功能

栈的定义:栈是一个数据集合,我们可以吧它理解为是一个只能在一端进行插入或者删除的列表。栈的特点:先进后出 Stack() 建立一个空的栈对象push() 吧一个元素添加到栈的最顶层pop() 删除栈最顶层的元素,并返回这个元素gettop() 取栈…

mybatis循环map的一些技巧

<foreach>标签的用法&#xff1a; 六个参数&#xff1a; collection&#xff1a;要循环的集合 index&#xff1a;循环索引&#xff08;不知道啥用。。&#xff09; item&#xff1a;集合中的一个元素&#xff08;item和collection&#xff0c;按foreach循环理解&#xff…

linux部署node web,nodejs怎么部署到Linux上?

nodejs怎么部署到Linux上&#xff1f;下面本篇文章就来给大家介绍一下在Linux上部署nodejs的方法&#xff0c;希望对大家有所帮助。nodejs部署到Linux上的方法如下&#xff1a;(建议先安装xshell和xftp)1、到nodejs官网下载压缩包(选择合适自己系统的版本)&#xff0c;放到Linu…

python树莓派 是什么_用树莓派和Python给你的植物浇水

我想指出&#xff0c;我绝不是电子学专家。如果你让我制作一个电路图或者解释某件电子产品工作原理的细节&#xff0c;我会一无所知。在生活中&#xff0c;我对电力的工作原理有了基本的了解&#xff0c;我只是胡乱摆弄了一下电子元件就完成了这个工程。话虽如此&#xff0c;当…

htmlspecialchars() 函数过滤XSS的问题

htmlspecialchars()函数的功能如下&#xff1a; htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。 预定义的字符是&#xff1a; & &#xff08;和号&#xff09;成为 &" &#xff08;双引号&#xff09;成为 " &#xff08;单引号&#xff09;成为 …

c语言中 字母对应的数值,C语言编程:求下式中每个字母所代表的数字

编写程序求解下式中各字母所代表的数字&#xff0c;不同的字母代表不同的数字。PEAR- ARA PEA*问题分析与算法设计类似的问题从计算机算法的角度来说是比较简单的&#xff0c;可以采用最常见的穷举方法解决。程序中采用循环穷举每个字母所可能代表的数字&#xff0c;然后将字母…

用mac的python写网络爬虫_在mac下使用python抓取数据

2015已经过去&#xff0c;这是2016的第一篇博文&#xff01; 祝大家新年快乐&#xff01; 但是我还有好多期末考试&#xff01; 还没开始复习&#xff0c;唉&#xff0c;一把辛酸泪&#xff01; 最近看了一遍彦祖的文章叫做 所以自己也想小试牛刀.于是便开始动手写,但初次接触,…

運輸配送信息Delivery_Information

为什么80%的码农都做不了架构师&#xff1f;>>> 運輸配送信息Delivery_Information 金銀倉會選用以下運輸公司&#xff0c;為客戶配送磁磚傢俬潔具&#xff1a; 佛山冠昌達中港運輸&#xff08;散貨或包車&#xff0c;近佛山石灣的磁磚倉庫&#xff0c;近樂從傢俬城…

linux的 dev vdal,RAZVOJ DELA NA DALJAVO V SLOVENIJI

摘要&#xff1a;V diplomskem delu bomo raziskovali razvoj dela na daljavo v Sloveniji. Naš poglavitni cilj je prikazati širjenje teledela v Sloveniji. Drugod po Evropi se že vrsto let uveljavlja tudi ta vrsta opravljanja dela, pri nas pa manj. O tem lah…

Spring+SpringMVC+Mybatis 多数据源整合

原文地址&#xff1a;http://blog.csdn.net/q908555281/article/details/50316137 ----------------------------------- 此篇文章是基于Spring3.0和mybatis3.2的总体大概流程 &#xff1a;1. 拷贝所需jar 2.写一个数据库切换的工具类&#xff1a;DataSourceContextHolder&am…

查看mysql sql执行器优化后的sql

EXPLAIN EXTENDED select s.* from student s where s.sid in ( select sid from sc where sc.cid 0 and sc.score 100); show WARNINGS;

git ssh拉取代码_win10下git初始安装及配置工作

git安装从https://git-scm.com/https://git-scm.com/download/win 中下载安装包&#xff0c;点击exe文件运行&#xff0c;选择安装路径即可安装。git配置初次运行git前的配置&#xff0c;新建文件夹1、 新建一个文件夹&#xff0c;用来存放代码的文件夹---2、 打开文件夹&#…

用ABAP 生成二维码 QR Code

除了使用我的这篇blogStep by step to create QRCode in ABAP Webdynpro提到的使用ABAP webdynpro生成二维码之外&#xff0c;也可以通过使用二维码在线生成网站提供的service来生成二维码。 二维码在线生成网站&#xff1a; www.makepic.com/qrcode.php 在网页上输入要生成的二…

c语言不用第三变量,C语言中几种不用第三变量交换两值的方法

int main(){int a3,b4;int *p(int *)malloc(sizeof(int));*p3;int *q(int *)malloc(sizeof(int));*q4;int a24,b27;printf("***位运算****/n");printf("转换前&#xff1a;%d %d/n",a,b);a^b^a^b;printf("转换后&#xff1a;%d %d/n",a,b);print…

联想m7400pro清零方法_联想打印机怎么清零 联想打印机清零方法【教程】

今天小编为读者挑选出了联想 打印机 部分机型的清零方式&#xff0c;希望阅读完这篇文章能帮助到各位。LJ3010A、LJ3116A、LJ3220A清零方式先点击控制面板上的“联机”按钮&#xff0c;让打印机处于脱机状态&#xff0c;再点击“执行”按钮进行打印。先点击控制面板上的“联机”…