Python图像处理:基于边缘/区域的图像分割
yuyutoo 2024-10-13 00:29 3 浏览 0 评论
图像分割的概念
图像分割是将图像分割成不同的区域或类别,并使这些区域或类别对应于不同的目标或局部目标。每个区域包含具有相似属性的像素,并且图像中的每个像素都分配给这些类别之一。一个好的图像分割通常指同一类别的像素具有相似的强度值并形成一个连通区域,而相邻的不同类别的像素具有不同的值。这样做的目的是简化成改变图像的表示形式,使其更有意义、更易于分析。
如果分割做得好,那么图像分析的所有其他阶段都将变得更简单。因此,分割的质量和可靠性决定了图像分析是否成功。但是如何将图像分割成正确的片段通常是一个非常具有挑战性的问题。
分割技术可以是非上下文的(不考虑图像中特征和组像素之间的空间关系,只考虑一些全局属性,例如颜色或灰度),也可以是上下文的(另外利用空间关系,例如对具有相似灰度的空间封闭像素分组)。在本章中,我们将讨论不同的分割技术,并使用scikit-image、python-opencv(cv2)和SimpleITK库函数演示基于Python的图像分割实现。为此,从导入本章所需的库开始,如下面的代码所示:
import numpy as np
from skimage.transform import (hough_line, hough_line_peaks, hough_circle,
hough_circle_peaks)
from skimage.draw import circle_perimeter
from skimage.feature import canny
from skimage.data import astronaut
from skimage.io import imread, imsave
from skimage.color import rgb2gray, gray2rgb, label2rgb
from skimage import img_as_float
from skimage.morphology import skeletonize
from skimage import data, img_as_float
import matplotlib.pyplot as pylab
from matplotlib import cm
from skimage.filters import sobel, threshold_otsu
from skimage.feature import canny
from skimage.segmentation import felzenszwalb, slic, quickshift, watershed
from skimage.segmentation import mark_boundaries, find_boundaries
本节的这个例子源自scikit-image文档,它演示了如何从背景中分割目标。先使用基于边缘的分割算法,然后使用基于区域的分割算法。将源自skimage.data的硬币图像作为输入图像,在较幽暗的背景下勾勒出了硬币的轮廓。
如下代码实现了显示其灰度图像及其强度直方图:
coins = data.coins()
hist = np.histogram(coins, bins=np.arange(0, 256), normed=True)
fig, axes = pylab.subplots(1, 2, figsize=(20, 10))
axes[0].imshow(coins, cmap=pylab.cm.gray, interpolation='nearest')
axes[0].axis('off'), axes[1].plot(hist[1][:-1], hist[0], lw=2)
axes[1].set_title('histogram of gray values')
pylab.show()
运行上述代码,输出结果如图8-4所示。
图8-4 硬币图像及其灰度直方图
8.4.1 基于边缘的图像分割
在本例中,我们将尝试使用基于边缘的分割来描绘硬币的轮廓。为此,先使用Canny边缘检测器获取特征的边缘,如下面的代码所示:
edges = canny(coins, sigma=2)
fig, axes = pylab.subplots(figsize=(10, 6))
axes.imshow(edges, cmap=pylab.cm.gray, interpolation='nearest')
axes.set_title('Canny detector'), axes.axis('off'), pylab.show()
运行上述代码,使用Canny边缘检测器得到的硬币轮廓如图8-5所示。
图8-5 使用Canny边缘检测器得到的硬币轮廓
然后使用scipy ndimage模块中的形态学函数binary_fill_holes()填充这些轮廓,如下面的代码所示:
from scipy import ndimage as ndi
fill_coins = ndi.binary_fill_holes(edges)
fig, axes = pylab.subplots(figsize=(10, 6))
axes.imshow(fill_coins, cmap=pylab.cm.gray, interpolation='nearest')
axes.set_title('filling the holes'), axes.axis('off'), pylab.show()
运行上述代码,输出硬币的填充轮廓,如图8-6所示。
图8-6 硬币的填充轮廓
可以看到,有一枚硬币的轮廓没有被填满。在接下来的步骤中,我们将通过为有效目标设置最小尺寸,并再次使用形态学函数来删除诸如此类小伪目标。这次使用的是scikit-image形态学模块的remove_small_objects()函数,如下面的代码所示:
from skimage import morphology
coins_cleaned = morphology.remove_small_objects(fill_coins, 21)
fig, axes = pylab.subplots(figsize=(10, 6))
axes.imshow(coins_cleaned, cmap=pylab.cm.gray, interpolation='nearest')
axes.set_title('removing small objects'), axes.axis('off'), pylab.show()
运行上述代码,输出结果如图8-7所示。
图8-7 删除未填充的硬币轮廓
但这种方法并不是很健壮,因为没有完全闭合的轮廓没有被正确填充,如图8-6中还有一枚没有填充的硬币一样。
8.4.2 基于区域的图像分割
在本节中,我们将使用形态学分水岭算法对同一幅图像应用基于区域的分割方法。先直观地阐述分水岭算法的基本步骤。
形态学分水岭算法
任何灰度图像都可以看作一个地形地貌面。如果这个面从它的最小值被淹没,并且阻止了不同来源的水的汇合,那么图像就被分割成两个不同的集合,即集水盆和分水岭线。如果将这种变换应用于图像梯度,在理论上集水盆应与图像的同质的灰度区域(片段)相对应。
然而,在实际应用中,由于梯度图像中存在噪声或局部不规则性,使用变换会对图像进行过度分割。为了防止过度分割,使用一组预定义标记,并从这些标记开始对地表面进行注水淹没。因此,通过分水岭变换分割图像的步骤如下:
(1)找到标记和分割准则(用于分割区域的函数,通常是图像对比度/梯度);
(2)利用这两个元素运行标记控制的分水岭算法。
现在,使用scikit-image中的形态学分水岭算法实现从图像的背景中分离出前景硬币。首先,使用图像的sobel梯度找到图像的高程图,如下面的代码所示:
elevation_map = sobel(coins)
fig, axes = pylab.subplots(figsize=(10, 6))
axes.imshow(elevation_map, cmap=pylab.cm.gray, interpolation='nearest')
axes.set_title('elevation map'), axes.axis('off'), pylab.show()
运行上述代码,输出高程图,如图8-8所示。
图8-8 利用sobel梯度得到硬币图像的高程图
紧接着,基于灰度值直方图的极值部分,计算背景标记和硬币标记,如下面的代码所示:
markers = np.zeros_like(coins)
markers[coins < 30] = 1
markers[coins > 150] = 2
print(np.max(markers), np.min(markers))
fig, axes = pylab.subplots(figsize=(10, 6))
a = axes.imshow(markers, cmap=plt.cm.hot, interpolation='nearest')
plt.colorbar(a)
axes.set_title('markers'), axes.axis('off'), pylab.show()
运行上述代码,输出结果如图8-9所示,图中还示出标记数组的热度图。
图8-9 背景标记和硬币标记——热度图
最后,利用分水岭变换,从确定的标记点开始注入高程图的区域,如下面的代码所示:
segmentation = morphology.watershed(elevation_map, markers)
fig, axes = pylab.subplots(figsize=(10, 6))
axes.imshow(segmentation, cmap=pylab.cm.gray, interpolation='nearest')
axes.set_title('segmentation'), axes.axis('off'), pylab.show()
运行上述代码,输出使用形态学分水岭算法进行分割后所得到的二值图像,如图8-10所示。
图8-10 使用形态学分水岭算法进行分割后的二值图像
最后一种方法的效果更好,可以将硬币分割并单独标记出来,如下面的代码所示:
segmentation = ndi.binary_fill_holes(segmentation - 1)
labeled_coins, _ = ndi.label(segmentation)
image_label_overlay = label2rgb(labeled_coins, image=coins)
fig, axes = pylab.subplots(1, 2, figsize=(20, 6), sharey=True)
axes[0].imshow(coins, cmap=pylab.cm.gray, interpolation='nearest')
axes[0].contour(segmentation, [0.5], linewidths=1.2, colors='y')
axes[1].imshow(image_label_overlay, interpolation='nearest')
for a in axes:
a.axis('off')
pylab.tight_layout(), pylab.show()
运行上述代码,输出被分水岭线(等值线)分割和标记后的硬币,如图8-11所示。
图8-11 分水岭线分割后的硬币和标记后的硬币
本文摘自《Python图像处理实战》
本书介绍如何使用流行的Python图像处理库(如PIL、scikit-image、python-opencv、SciPy ndimage和SimpleITK)、机器学习库(scikit-learn)和深度学习库(TensorFlow、Keras)解决图像处理问题。通过学习本书,读者能够通过编写程序代码来实现复杂的图像处理(如图像增强、滤波、复原、分割、分类和目标检测),还能够掌握用机器学习和深度学习模型来解决复杂的图像处理问题的方法。
本书从基础开始,通过书中所提供的Python可重现实现来引导读者逐步进阶。本书从经典的图像处理技术开始,探索图像处理算法的进化历程,直至图像处理或计算机视觉与深度学习方面的最新进展。读者将学习如何用Python的PIL、scikit-image和SciPy ndimage等图像处理库编写Python 3代码片段,以及如何快速实现复杂的图像处理算法,如图像增强、滤波、分割、目标检测和分类。读者还将学习如何使用scikit-learn库和机器学习模型,并随后探索深度卷积神经网络(CNN),如TensorFlow/Keras VGG-19,用端到端深度学习YOLO模型进行目标检测,将DeepLab V3+用于语义分割和神经中枢式的转移模型等。读者还会学到一些高级图像处理技术问题,如图像内画、梯度混合、变分去噪、接缝雕刻、绗缝和变形。在本书最后,读者还将学习有效的图像处理的各种实现算法。
本书循着“高度实用”的宗旨来引导读者学习一系列图像处理的概念/算法,以帮助读者详细了解如何用高级的Python库函数实现这些算法。
相关推荐
- YAML配置文件简介及使用(yaml 配置)
-
简介YAML是"YAMLAin'taMarkupLanguage"(YAML不是一种标记语言)的缩写。相比JSON格式的方便。...
- 教你如何解决最常见的58种网络故障排除方法
-
1.故障现象:网络适配器(网卡)设置与计算机资源有冲突。分析、排除:通过调整网卡资源中的IRQ和I/O值来避开与计算机其它资源的冲突。有些情况还需要通过设置主板的跳线来调整与其它资源的冲突。2.故障现...
- 一分钟带你了解服务器网卡(服务器网卡怎么用)
-
今天小编和大家聊一下服务器的网卡。什么是网卡?简单说网卡就是计算机与局域网互连的设备。计算机主要通过网卡接入网络。网卡又称为网络适配器或网络接口卡NIC(NetworkinterfaceCard)...
- linux文件之ssh配置文件的含义与作用
-
ssh远程登录命令是操作系统(包括linux和window系统)下常用的操作命令,可以帮助用户,远程登录服务器系统,查看,操作系统相关信息。linux系统对于ssh命令有专门保存其相关配置的目录和文件...
- Cilium 官方文档翻译 - IPAM(二)Kubernetes Host模式
-
KubernetesHostScopeciliumIPAM的kuberneteshost-scope模式通过选项ipam:kubernetes开启,将集群IP地址分配委托给每个独立的节点,并...
- 域名劫持跳转,域名劫持跳转的解决办法只需5步
-
简单来说,域名劫持就是把原本准备访问某网站的用户,在不知不觉中,劫持到仿冒的网站上,例如用户准备访问某家知名品牌的网上商店,黑客就可以通过域名劫持的手段,把其带到假的网上商店,同时收集用户的ID信息和...
- Linux 磁盘和文件系统管理(linux磁盘管理fdisk)
-
1检测并确认新硬盘...
- windows host文件怎么恢复?局域网访问全靠这些!
-
windowshost文件怎么恢复?windowshost文件是常用网址域名及其相应IP地址建立一个关联文件,通过这个host文件配置域名和IP的映射关系,以提高域名解析的速度,方便局域网用户使用...
- Nginx配置文件详解与优化建议(nginx 配置详解)
-
1、概述今天来详解一下Nginx的配置文件,以及给出一些配置建议,希望能对大家有所帮助。...
- Mac电脑hosts文件锁定,如何修改hosts文件权限
-
有时候我们需要修改hosts文件,但是网上很多教程都行不通,使用sudo命令也不行。其实有一个很简单的方法。打开终端命令行,使用如下命令即可:sudochflags-hvnoschg/etc/...
- windows电脑如何修改hosts文件?(windows 修改hosts文件)
-
先来简单说下电脑host的作用hosts文件的作用:hosts文件是一个用于储存计算机网络中各节点信息的计算机文件;作用是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中...
- Vigilante恶意软件行为怪异:修改Hosts文件以阻止受害者访问盗版网站
-
Sophos刚刚报道了一款名叫Vigilante的恶意软件,但其行为却让许多受害者感到不解。与其它专注于偷密码、搞破坏、或勒索赎金的恶意软件不同,Vigilante会通过修改Hosts文件...
- hosts文件无法修改几种现象和解决方法
-
第一种、hosts文件修改完不是直接保存而是弹出另存为窗口解决:1、右击hosts文件——属性——把“只读”前面勾去掉。第二种、打开hosts文件时提示“你没有权限打开该文件,请向文件的所有者或管理员...
- hosts文件位置在哪里,教你hosts文件位置在哪里
-
Hosts是一个没有扩展名的系统文件,其基本作用就是将一些常用的网址域名与其对应的IP地址建立一个关联"数据库",当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的I...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
推荐7个模板代码和其他游戏源码下载的网址
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
【开源分享】2024在线客服系统PHP源码(安装教程+全新UI)
-
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)