python数字图像处理之高级形态学处理


Posted in Python onApril 27, 2018

形态学处理,除了最基本的膨胀、腐蚀、开/闭运算、黑/白帽处理外,还有一些更高级的运用,如凸包,连通区域标记,删除小块区域等。

1、凸包

凸包是指一个凸多边形,这个凸多边形将图片中所有的白色像素点都包含在内。

函数为:

skimage.morphology.convex_hull_image(image)

输入为二值图像,输出一个逻辑二值图像。在凸包内的点为True, 否则为False

例:

import matplotlib.pyplot as plt
from skimage import data,color,morphology

#生成二值测试图像
img=color.rgb2gray(data.horse())
img=(img<0.5)*1

chull = morphology.convex_hull_image(img)

#绘制轮廓
fig, axes = plt.subplots(1,2,figsize=(8,8))
ax0, ax1= axes.ravel()
ax0.imshow(img,plt.cm.gray)
ax0.set_title('original image')

ax1.imshow(chull,plt.cm.gray)
ax1.set_title('convex_hull image')

python数字图像处理之高级形态学处理

convex_hull_image()是将图片中的所有目标看作一个整体,因此计算出来只有一个最小凸多边形。如果图中有多个目标物体,每一个物体需要计算一个最小凸多边形,则需要使用convex_hull_object()函数。

函数格式:skimage.morphology.convex_hull_object(image,neighbors=8)

输入参数image是一个二值图像,neighbors表示是采用4连通还是8连通,默认为8连通。

例:

import matplotlib.pyplot as plt
from skimage import data,color,morphology,feature

#生成二值测试图像
img=color.rgb2gray(data.coins())
#检测canny边缘,得到二值图片
edgs=feature.canny(img, sigma=3, low_threshold=10, high_threshold=50) 

chull = morphology.convex_hull_object(edgs)

#绘制轮廓
fig, axes = plt.subplots(1,2,figsize=(8,8))
ax0, ax1= axes.ravel()
ax0.imshow(edgs,plt.cm.gray)
ax0.set_title('many objects')
ax1.imshow(chull,plt.cm.gray)
ax1.set_title('convex_hull image')
plt.show()

python数字图像处理之高级形态学处理

2、连通区域标记

在二值图像中,如果两个像素点相邻且值相同(同为0或同为1),那么就认为这两个像素点在一个相互连通的区域内。而同一个连通区域的所有像素点,都用同一个数值来进行标记,这个过程就叫连通区域标记。在判断两个像素是否相邻时,我们通常采用4连通或8连通判断。在图像中,最小的单位是像素,每个像素周围有8个邻接像素,常见的邻接关系有2种:4邻接与8邻接。4邻接一共4个点,即上下左右,如下左图所示。8邻接的点一共有8个,包括了对角线位置的点,如下右图所示。

python数字图像处理之高级形态学处理

在skimage包中,我们采用measure子模块下的label()函数来实现连通区域标记。

函数格式:

skimage.measure.label(image,connectivity=None)

参数中的image表示需要处理的二值图像,connectivity表示连接的模式,1代表4邻接,2代表8邻接。

输出一个标记数组(labels), 从0开始标记。

import numpy as np
import scipy.ndimage as ndi
from skimage import measure,color
import matplotlib.pyplot as plt

#编写一个函数来生成原始二值图像
def microstructure(l=256):
  n = 5
  x, y = np.ogrid[0:l, 0:l] #生成网络
  mask = np.zeros((l, l))
  generator = np.random.RandomState(1) #随机数种子
  points = l * generator.rand(2, n**2)
  mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1
  mask = ndi.gaussian_filter(mask, sigma=l/(4.*n)) #高斯滤波
  return mask > mask.mean()

data = microstructure(l=128)*1 #生成测试图片

labels=measure.label(data,connectivity=2) #8连通区域标记
dst=color.label2rgb(labels) #根据不同的标记显示不同的颜色
print('regions number:',labels.max()+1) #显示连通区域块数(从0开始标记)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
ax1.imshow(data, plt.cm.gray, interpolation='nearest')
ax1.axis('off')
ax2.imshow(dst,interpolation='nearest')
ax2.axis('off')

fig.tight_layout()
plt.show()

在代码中,有些地方乘以1,则可以将bool数组快速地转换为int数组。

结果如图:有10个连通的区域,标记为0-9

python数字图像处理之高级形态学处理

如果想分别对每一个连通区域进行操作,比如计算面积、外接矩形、凸包面积等,则需要调用measure子模块的regionprops()函数。该函数格式为:

skimage.measure.regionprops(label_image)

返回所有连通区块的属性列表,常用的属性列表如下表:

属性名称 类型 描述
area int 区域内像素点总数
bbox tuple 边界外接框(min_row, min_col, max_row, max_col)
centroid array 质心坐标
convex_area int 凸包内像素点总数
convex_image ndarray 和边界外接框同大小的凸包
coords ndarray 区域内像素点坐标
Eccentricity  float 离心率
equivalent_diameter  float 和区域面积相同的圆的直径
euler_number int 区域欧拉数
extent  float 区域面积和边界外接框面积的比率
filled_area int 区域和外接框之间填充的像素点总数
perimeter  float 区域周长
label int 区域标记

3、删除小块区域

有些时候,我们只需要一些大块区域,那些零散的、小块的区域,我们就需要删除掉,则可以使用morphology子模块的remove_small_objects()函数。

函数格式:skimage.morphology.remove_small_objects(ar,min_size=64,connectivity=1,in_place=False)

参数:

ar: 待操作的bool型数组。

min_size: 最小连通区域尺寸,小于该尺寸的都将被删除。默认为64.

connectivity: 邻接模式,1表示4邻接,2表示8邻接

in_place: bool型值,如果为True,表示直接在输入图像中删除小块区域,否则进行复制后再删除。默认为False.

返回删除了小块区域的二值图像。

import numpy as np
import scipy.ndimage as ndi
from skimage import morphology
import matplotlib.pyplot as plt

#编写一个函数来生成原始二值图像
def microstructure(l=256):
  n = 5
  x, y = np.ogrid[0:l, 0:l] #生成网络
  mask = np.zeros((l, l))
  generator = np.random.RandomState(1) #随机数种子
  points = l * generator.rand(2, n**2)
  mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1
  mask = ndi.gaussian_filter(mask, sigma=l/(4.*n)) #高斯滤波
  return mask > mask.mean()

data = microstructure(l=128) #生成测试图片

dst=morphology.remove_small_objects(data,min_size=300,connectivity=1)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
ax1.imshow(data, plt.cm.gray, interpolation='nearest')
ax2.imshow(dst,plt.cm.gray,interpolation='nearest')

fig.tight_layout()
plt.show()

在此例中,我们将面积小于300的小块区域删除(由1变为0),结果如下图:

python数字图像处理之高级形态学处理

4、综合示例:阈值分割+闭运算+连通区域标记+删除小区块+分色显示

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from skimage import data,filter,segmentation,measure,morphology,color

#加载并裁剪硬币图片
image = data.coins()[50:-50, 50:-50]

thresh =filter.threshold_otsu(image) #阈值分割
bw =morphology.closing(image > thresh, morphology.square(3)) #闭运算

cleared = bw.copy() #复制
segmentation.clear_border(cleared) #清除与边界相连的目标物

label_image =measure.label(cleared) #连通区域标记
borders = np.logical_xor(bw, cleared) #异或
label_image[borders] = -1
image_label_overlay =color.label2rgb(label_image, image=image) #不同标记用不同颜色显示

fig,(ax0,ax1)= plt.subplots(1,2, figsize=(8, 6))
ax0.imshow(cleared,plt.cm.gray)
ax1.imshow(image_label_overlay)

for region in measure.regionprops(label_image): #循环得到每一个连通区域属性集
  
  #忽略小区域
  if region.area < 100:
    continue

  #绘制外包矩形
  minr, minc, maxr, maxc = region.bbox
  rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
               fill=False, edgecolor='red', linewidth=2)
  ax1.add_patch(rect)
fig.tight_layout()
plt.show()

python数字图像处理之高级形态学处理

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 专题四 文件基础知识
Mar 20 Python
Python批量提取PDF文件中文本的脚本
Mar 14 Python
Python使用Flask-SQLAlchemy连接数据库操作示例
Aug 31 Python
用python一行代码得到数组中某个元素的个数方法
Jan 28 Python
Django中多种重定向方法使用详解
Jul 17 Python
Anaconda+Pycharm环境下的PyTorch配置方法
Mar 13 Python
学python最电脑配置有要求么
Jul 05 Python
如何使用Django Admin管理后台导入CSV
Nov 06 Python
Python ellipsis 的用法详解
Nov 20 Python
python输出国际象棋棋盘的实例分享
Nov 26 Python
5 分钟读懂Python 中的 Hook 钩子函数
Dec 09 Python
Jupyter notebook 更改文件打开的默认路径操作
May 21 Python
python线程池threadpool实现篇
Apr 27 #Python
python数字图像处理之骨架提取与分水岭算法
Apr 27 #Python
python多线程之事件Event的使用详解
Apr 27 #Python
python线程池threadpool使用篇
Apr 27 #Python
Python实现删除时保留特定文件夹和文件的示例
Apr 27 #Python
python中yaml配置文件模块的使用详解
Apr 27 #Python
python 拷贝特定后缀名文件,并保留原始目录结构的实例
Apr 27 #Python
You might like
Laravel SQL语句记录方式(推荐)
2016/05/26 PHP
thinkPHP交易详情查询功能详解
2016/12/02 PHP
php中preg_replace正则替换用法分析【一次替换多个值】
2017/01/17 PHP
PHP策略模式定义与用法示例
2017/07/27 PHP
PHP实现二叉树深度优先遍历(前序、中序、后序)和广度优先遍历(层次)实例详解
2018/04/20 PHP
JavaScript For Beginners(转载)
2007/01/05 Javascript
JavaScript几种形式的树结构菜单
2010/05/10 Javascript
有关javascript的性能优化 (repaint和reflow)
2013/04/12 Javascript
js setTimeout()函数介绍及应用以倒计时为例
2013/12/12 Javascript
jquery uploadify 在FF下无效的解决办法
2014/09/26 Javascript
JavaScript日期时间与时间戳的转换函数分享
2015/01/31 Javascript
纯javascript响应式树形菜单效果
2015/11/10 Javascript
bootstrap读书笔记之CSS组件(上)
2016/10/17 Javascript
jQuery操作复选框(CheckBox)的取值赋值实现代码
2017/01/10 Javascript
基于jQuery代码实现圆形菜单展开收缩效果
2017/02/13 Javascript
js实现登录与注册界面
2017/11/01 Javascript
JS实现的ajax和同源策略(实例讲解)
2017/12/01 Javascript
代码详解javascript模块加载器
2018/03/04 Javascript
angularjs 动态从后台获取下拉框的值方法
2018/08/13 Javascript
[02:17]快乐加倍!DOTA2食人魔魔法师至宝+迎霜节活动上线
2019/12/22 DOTA
使用Python编写Linux系统守护进程实例
2015/02/03 Python
python获取当前日期和时间的方法
2015/04/30 Python
python显示生日是星期几的方法
2015/05/27 Python
pyqt 实现在Widgets中显示图片和文字的方法
2019/06/13 Python
使用Python做垃圾分类的原理及实例代码附源码
2019/07/02 Python
PyTorch实现重写/改写Dataset并载入Dataloader
2020/07/14 Python
租租车:国际租车、美国租车、欧洲租车、特价预订国外租车(中文服务)
2018/03/28 全球购物
美国围栏公司:Walpole Outdoors
2019/11/19 全球购物
工地资料员岗位职责
2013/12/31 职场文书
运动会广播稿100字
2014/01/11 职场文书
小区的门卫岗位职责
2014/10/01 职场文书
给老婆的保证书
2015/01/16 职场文书
工会经费申请报告
2015/05/15 职场文书
python 爬取哔哩哔哩up主信息和投稿视频
2021/06/07 Python
详细聊一聊mysql的树形结构存储以及查询
2022/04/05 MySQL
《火纹风花雪月无双》预告“神秘雇佣兵” 紫发剑客
2022/04/13 其他游戏