本文介绍了python opencv之分水岭算法示例,分享给大家,具体如下:
目标
- 使用分水岭算法对基于标记的图像进行分割
- 使用函数cv2.watershed()
原理:
灰度图像可以被看成拓扑平面,灰度值高的区域可以看出山峰,灰度值低的区域可以看成是山谷。向每一个山谷当中灌不同颜色的水。水位升高,不同山谷的水会汇合,为防止不同山谷的水汇合,小在汇合处建立起堤坝。然后继续灌水,然后再建立堤坝,直到山峰都掩模。构建好的堤坝就是图像的分割。
此方法通常会得到过渡分割的结果,因为图像中的噪声以及其他因素。为了减少此影响,opencv使用基于标记的分水岭算法,此算法要设置哪些山谷中的汇合点,哪些不是。这是一种交互式的图像分割算法那。我们要给已知对象打上不同表情。如果某个区域肯定是前景或对象,就使用某个颜色或灰度值标签标记它。如果是背景那么使用其他颜色进行标记,其余不能确定的部分用0标记。然后使用分水岭算法,每次灌水,标签会被更新,当两个不同颜色的标签相遇就会构建堤坝,知道所有山峰掩模,最后得到的边界对象值是-1。
代码:
对挨在一起的对象进行分割。
使用Otsu's 二值化后的结果为
要出去图像中的白噪声。可以使用形态学运算,使用闭运算去除对象中的空洞。
靠近对象中心的区域是前景,离对象远的区域是背景,不确定的区域是边界。
首先提取硬币区域,使用腐蚀操作去掉边缘,剩下的就是硬币。但硬币没有接触时,此方法有效,但是由于硬币相互接触,就要使用另外一种有效的方法:距离变换加上合适的阈值。
之后,要寻找不确定是否是硬币的区域。这里需要膨胀操作。膨胀操作会将对象边界延伸到背景当中。由于边界区域被去除,现在就能知道哪些区域是前景,哪些是背景。
余下的区域不知道如何区分,那么使用分水岭算法。这些区域通常是前景与背景的交界处。从能否确认是否是背景的区域中减去确定是前景的区域就得到了边界。
(前景和背景)
(上面的图是直接使用作者的代码后生产的结果,提取到了前景,为了演示一下不确定的区域,调了一下计算前景的距离变换的参数,使得中间出现不确定的区域)
这里面使用个cv2.distanceTransform函数
该函数用于计算2值图象中所有像素离其最近的值为0像素的近似距离。
参数为
cv2.distanceTransform(src, distanceType, maskSize[, dst]) → dst #src为输入的二值图像。distanceType为计算距离的方式,可以是如下值 DIST_USER = ⑴, //!< User defined distance DIST_L1 = 1, //!< distance = |x1-x2| + |y1-y2| DIST_L2 = 2, //!< the simple euclidean distance DIST_C = 3, //!< distance = max(|x1-x2|,|y1-y2|) DIST_L12 = 4, //!< L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1)) DIST_FAIR = 5, //!< distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998 DIST_WELSCH = 6, //!< distance = c^2/2(1-exp(-(x/c)^2)), c = 2.9846 DIST_HUBER = 7 //!< distance = |x|<c "htmlcode">import numpy as np import cv2 from matplotlib import pyplot as plt img = cv2.imread('21.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) kernel = np.ones((3,3),np.uint8) opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2) # sure background area sure_bg = cv2.dilate(opening,kernel,iterations=3)#膨胀 # Finding sure foreground area dist_transform = cv2.distanceTransform(opening,1,5) ret, sure_fg = cv2.threshold(dist_transform,0.2*dist_transform.max(),255,0)#参数改小了,出现不确定区域 # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg,sure_fg)#减去前景 cv2.imshow('p',sure_fg) cv2.waitKey(0)现在知道了那些背景是硬币,可以创建标签。(与原图像大小相同,数据类型为int32的数组)。
对于已经确定分类的区域,也就是背景和前景,使用整数标记,不确定的区域是用0标记。可以使用cv2.connectedComponents()函数来实现此功能。它会将背景标记为0,其他标记为位从1开始的正整数。
但是,如果背景标记为0,那么分水岭算法会将其当成位置区域,所以使用不同的整数进行标记,对于不确定的区域,函数标记为0.
结果使用JET颜色地图表示。深蓝色未知区域,硬币区域使用不同颜色。其余部分用浅蓝色。
使用分水岭算法
效果不错
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。