当前位置: 首页 > news >正文

数字图像处理(实践篇) 十六 基于分水岭算法的图像分割

目录

一 分水岭算法

二 利用OpenCV实现分水岭算法的过程

三 实践


一 分水岭算法

        基于任何灰度图像都可以视为地形表面,其中高强度表示山峰和山丘,而低强度表示山谷。首先,开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水位的上升,根据附近的山峰(梯度),来自不同山谷的水,显然具有不同的颜色,将开始合并。为了避免这种情况,我们需要在水汇合的位置建造水坝或屏障。如果继续注水和建造屏障的工作,直到所有的山峰都在水下。然后,之前创建的屏障会提供细分的结果。这就是分水岭背后的“哲学”。

        利用OpenCV实现分水岭算法的过程如下:

①首先,找到前景的近似估计值。可以使用 Otsu 的二值化操作实现。

②通过形态学处理对原始的图像img进行降噪操作。

注意:靠近物体中心的区域是前景,而远离物体的区域是背景。不确定的唯一区域是硬币的边界区域

③通过膨胀操作获取“确定的背景区域Background region"。

④利用距离变换函数cv2.distanceTransform()对图像进行处理,并对其结果进行阈值分割,得到”确定前景区域Front reign“。

⑤获取未知的区域UN。UN =img - Background region - Front reign

⑥利用cv.connectedComponents()实现图像的标注工作和对标注结果进行修正。

⑦使用分水岭分割函数cv.watershed()完成对图像的分割。

二 利用OpenCV实现分水岭算法的过程

①Otsu 的二值化操作的结果

img = cv2.imread(img_path)
im = img.copy()
gray = cv2.cvtColor(im, 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)

③确定的背景区域Background region。

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

 

④确定的前景区域。

dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
sure_fg = np.uint8(sure_fg)

 

⑤unknown区域。

unknown = cv2.subtract(sure_bg, sure_fg)

⑥利用cv.connectedComponents()实现图像的标注,并且对标注结果进行修正。

ret, markers = cv2.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers + 1
# Now, mark the region of unknown with zero
markers[unknown == 255] = 0

⑦使用分水岭分割函数cv.watershed()完成对目标的分割处理。 

markers = cv2.watershed(im, markers)
# The boundary region will be marked with -1.

三 实践

  • 代码
import numpy as np
import cv2
import matplotlib.pyplot as plt
def dealImg(img):b, g, r = cv2.split(img)img_rgb = cv2.merge([r, g, b])return img_rgb
def dealImageResult(img_path):img = cv2.imread(img_path)im = img.copy()gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)# noise removalkernel = np.ones((3, 3), np.uint8)opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)# sure background areasure_bg = cv2.dilate(opening, kernel, iterations=3)# sure foreground areadist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)sure_fg = np.uint8(sure_fg)unknown = cv2.subtract(sure_bg, sure_fg)# Marker labellingret, markers = cv2.connectedComponents(sure_fg)# Add one to all labels so that sure background is not 0, but 1markers = markers + 1# Now, mark the region of unknown with zeromarkers[unknown == 255] = 0markers = cv2.watershed(im, markers)# The boundary region will be marked with -1.im[markers == -1] = [255, 255, 0]fig = plt.figure(figsize=(10, 10))img = dealImg(img)im = dealImg(im)titles = ["im", " OTSU", "open", "sure_bg", "sure_fg", "unknown", "result_im"]images = [img, thresh, opening, sure_bg, sure_fg, unknown, im]for i in range(7):plt.subplot(2, 4, i + 1), plt.imshow(images[i], "gray")plt.title("{}".format(titles[i]), fontsize=20, ha='center')plt.xticks([]), plt.yticks([])#plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.3, hspace=0)# plt.tight_layout()plt.show()fig.savefig('test_results.jpg', bbox_inches='tight')
if __name__ == '__main__':dealImageResult("test.jpg")pass
  • 效果图

         从上图中可以看出,对于某些硬币,它们接触的区域可以被正确分割开,而对于某些硬币,则没有分割开。

前文回顾

 入门篇目录

 数字图像处理(入门篇)一 图像的数字化与表示

 数字图像处理(入门篇)二 颜色空间

 数字图像处理(入门篇)三 灰度化

 数字图像处理(入门篇)四 像素关系

 数字图像处理(入门篇)五 图像数据预处理之颜色空间转换

 数字图像处理(入门篇)六 图像数据预处理之坐标变化

 数字图像处理(入门篇)七 图像数据预处理之灰度变化

 数字图像处理(入门篇)八 图像数据预处理之直方图

 数字图像处理(入门篇)九 图像数据预处理之滤波

 数字图像处理(入门篇)十 边缘检测

 数字图像处理(入门篇)十一 形态学处理

 数字图像处理(入门篇)十二 自适应阈值分割

 数字图像处理(入门篇)十三 仿射变换

 数字图像处理(入门篇)十四 透视变换

实践篇目录

数字图像处理(实践篇)一 将图像中的指定目标用bBox框起来吧!

数字图像处理(实践篇)二 画出图像中目标的轮廓

数字图像处理(实践篇)三 将两张图像按照指定比例融合

数字图像处理(实践篇)四 图像拼接-基于SIFT特征点和RANSAC方法

数字图像处理(实践篇)五 使用Grabcut算法进行物体分割

数字图像处理(实践篇)六 利用hough变换进行直线检测

数字图像处理(实践篇)七 利用霍夫变换进行圆环检测

数字图像处理(实践篇)八 Harris角点检测

数字图像处理(实践篇)九 基于边缘的模板匹配

数字图像处理(实践篇)十 图像质量检测

数字图像处理(实践篇)十一 图像中的条形码解析

数字图像处理(实践篇)十二 基于小波变换的图像降噪

数字图像处理(实践篇)十三 数据增强之给图像添加噪声!

数字图像处理(实践篇)十四 图像金字塔

数字图像处理(实践篇)十五 基于傅里叶变换的高通滤波和低通滤波

相关文章:

  • 视频批量剪辑方法:AI智剪创新力,批量剪辑新风潮
  • mybatisplus调用oracle存储过程
  • Selenium/webdriver介绍以及工作原理
  • Day18——JDK新特性
  • vue3学习笔记
  • pbootcms建站
  • P1047 [NOIP2005 普及组] 校门外的树题解
  • Linux shell编程学习笔记34:eval 命令
  • Elastic Support Hub 转向语义搜索
  • 【广州华锐互动VRAR】VR戒毒科普宣传系统有效提高戒毒成功率
  • 常用的DDL:创建表、删除表、添加列、修改列、添加主键、外键、索引
  • Unity渲染Stats分析
  • 水位线和窗口
  • ssl什么是公钥和私钥?
  • qt-C++笔记之组件-分组框QGroupBox
  • 2017前端实习生面试总结
  • CentOS 7 防火墙操作
  • ESLint简单操作
  • JavaScript 基本功--面试宝典
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • sessionStorage和localStorage
  • 百度小程序遇到的问题
  • 将回调地狱按在地上摩擦的Promise
  • 讲清楚之javascript作用域
  • 如何胜任知名企业的商业数据分析师?
  • 什么软件可以剪辑音乐?
  • 使用 QuickBI 搭建酷炫可视化分析
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 一个项目push到多个远程Git仓库
  • 白色的风信子
  • postgresql行列转换函数
  • UI设计初学者应该如何入门?
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • %check_box% in rails :coditions={:has_many , :through}
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (AngularJS)Angular 控制器之间通信初探
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (四)linux文件内容查看
  • (转)Scala的“=”符号简介
  • .net refrector
  • .Net环境下的缓存技术介绍
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • [2018/11/18] Java数据结构(2) 简单排序 冒泡排序 选择排序 插入排序
  • [BPU部署教程] 教你搞定YOLOV5部署 (版本: 6.2)
  • [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]
  • [CSS] 点击事件触发的动画