首先,我们为什么要把标签换成轮廓表示
这是某一篇论文的原图,用两种颜色分别表示分割结果和ground truth.
想象一下,如果用实心标签显示,会怎么样?自然是很杂乱,看不清两者的区别在哪。
我们再看下一个例子:实心标签转轮廓标签
||||||||||||||||||||||||||||||||||||||||||||||||||||
如图,我们有标签的时候,想要获得他的边界进行展示,应该如何操作呢?
直接上代码:
def get_edge_points(img):
"""
get edge points of a binary segmentation result
"""
dim = len(img.shape)
if (dim == 2):
strt = ndimage.generate_binary_structure(2, 1)
else:
strt = ndimage.generate_binary_structure(3, 1)
ero = ndimage.morphology.binary_erosion(img, strt)
edge = np.asarray(img, np.uint8) - np.asarray(ero, np.uint8)
return edge
调用并保存结果
if __name__ == '__main__':
# 生成三维边缘轮廓
label_path = './8mask.nii.gz'
arr_ = nib.load(label_path)
arr = arr_.get_fdata()
affine = arr_.affine
contour = get_edge_points(arr)
save_contour = nib.Nifti1Image(contour, affine=affine)
nib.save(save_contour, 'segcontour.nii.gz')
这里用到了形态学的方法,大致思路就是 通过结构体做腐蚀运算 (ndimage.morphology.binary_erosion
),得到内部元素,再用
整
个
图
像
−
内
部
元
素
=
边
界
元
素
整个图像 - 内部元素 = 边界元素
整个图像−内部元素=边界元素
想简单知道原理的往下看,初步了解一下腐蚀原理,以及为何用腐蚀可以提取边界。
腐蚀运算函数
ndimage.morphology.binary_erosion(input, structure)
- input: 待腐蚀的图像
- structure: 结构体
对于使用结构体做腐蚀的简单理解
解释: 遍历结构A 的所有像素 Ai,如果 Ai 周围的结构和结构B是一致的,则 Ai 值保留,否则为0.
通过这个原理,我们得到的图像会比结构A 小很多,这就是腐蚀。
让我们来看一个具体的案例。
- 创建一个结构体
使用 ndimage.generate_binary_structure
from scipy import ndimage
strt = ndimage.generate_binary_structure(2, 1)
- 创建一个假的图像
import numpy as np
a = np.zeros((7,7), dtype=np.int)
a[1:6, 2:5] = 1
- 使用结构体腐蚀图像
fushi = ndimage.binary_erosion(a, strt).astype(a.dtype)
看到了吗? 使用这种结构体后,边界都变为0了,只有中间有值。
- 获取边界
boundary = a - fushi
恭喜!你已经得到边界了。
再回头去看看最开始的代码,是不是就容易理解了呢。
文章持续更新,可以关注微信公众号【医学图像人工智能实战营】获取最新动态,一个关注于医学图像处理领域前沿科技的公众号。坚持已实践为主,手把手带你做项目,打比赛,写论文。凡原创文章皆提供理论讲解,实验代码,实验数据。只有实践才能成长的更快,关注我们,一起学习进步~
我是Tina, 我们下篇博客见~
白天工作晚上写文,呕心沥血
觉得写的不错的话最后,求点赞,评论,收藏。或者一键三连