胸部CT提取分割肺部
1. 肺部分割提取简介
在处理胸部CT时,我们常常需要获取肺部的一个mask,也就是将肺部结构从数据中提取出来。二维图像还好说,但是三维图像就会变得复杂复杂一点。肺部的分割常常做后续操作的预处理,所以有必要提取提取一个肺部的mask,来辅助后面的操作,所以这里利用传统图像处理方法来提取了一下肺部,当时方法又很多,这里只是抛砖引玉,也许对有些数据不适用,可以对其进行改动。
2. 原理
利用阈值分割、种子填充图像形态学、图像连通域这些操作来进行肺部的分割。
2.1 阈值分割
这个好理解,一般来说CT值的范围是-1000-+1000,而基于简单的观察,肺部就是胸腔内两个大的空洞,所以可以首先对图像进行二值化处理,这里是将CT大于-300的位置置为1,小于-300置为0,这样就将数据分为了三部分,外部空气,内部空气,躯干组织。如下图所示。
2.2 种子填充
利用种子填充算法,将外部的空气和内部的躯干分割出来,给定两个种子,一般就能分出来。分割的效果如下。然后再用阈值图像减去这个躯干就能得到初步的肺部mask。此时肺部的值是1,组织值是0。
2.3 图像形态学
因为肺内部有许多纤维,所以看起来会有以下空洞(相对于肺部来说),要填补这些空洞,所以利用形态学里的闭操作(先膨胀,再腐蚀)。先膨胀肺部,将小的空洞填充,再腐蚀,恢复原来的大小。
2.4 连通域
最后保留最大的连通域,此时最大的连通域就是肺部。
2.5 效果
以下图片是使用3dslicer渲染出来的。







3.代码
依赖库
- SimpleITK
- skimage
import SimpleITK as sitk
from skimage import measure
def lungmask(vol):
#获取体数据的尺寸
size = sitk.Image(vol).GetSize()
#获取体数据的空间尺寸
spacing = sitk.Image(vol).GetSpacing()
#将体数据转为numpy数组
volarray = sitk.GetArrayFromImage(vol)
#根据CT值,将数据二值化(一般来说-300以下是空气的CT值)
volarray[volarray>=-300]=1
volarray[volarray<=- 300]=0
#生成阈值图像
threshold = sitk.GetImageFromArray(volarray)
threshold.SetSpacing(spacing)
#利用种子生成算法,填充空气
ConnectedThresholdImageFilter = sitk.ConnectedThresholdImageFilter()
ConnectedThresholdImageFilter.SetLower(0)
ConnectedThresholdImageFilter.SetUpper(0)
ConnectedThresholdImageFilter.SetSeedList([(0,0,0),(size[0]-1,size[1]-1,0)])
#得到body的mask,此时body部分是0,所以反转一下
bodymask = ConnectedThresholdImageFilter.Execute(threshold)
bodymask = sitk.ShiftScale(bodymask,-1,-1)
#用bodymask减去threshold,得到初步的lung的mask
temp = sitk.GetImageFromArray(sitk.GetArrayFromImage(bodymask)-sitk.GetArrayFromImage(threshold))
temp.SetSpacing(spacing)
#利用形态学来去掉一定的肺部的小区域
bm = sitk.BinaryMorphologicalClosingImageFilter()
bm.SetKernelType(sitk.sitkBall)
bm.SetKernelRadius(2)
bm.SetForegroundValue(1)
lungmask = bm.Execute(temp)
#利用measure来计算连通域
lungmaskarray = sitk.GetArrayFromImage(lungmask)
label = measure.label(lungmaskarray,connectivity=2)
props = measure.regionprops(label)
#计算每个连通域的体素的个数
numPix = []
for ia in range(len(props)):
numPix += [props[ia].area]
#最大连通域的体素个数,也就是肺部
maxnum = max(numPix)
#遍历每个连通区域
for i in range(len(numPix)):
#如果当前连通区域不是最大值所在的区域,则当前区域的值全部置为0,否则为1
if numPix[i]!=maxnum:
label[label==i+1]=0
else:
label[label==i+1]=1
label = label.astype("int16")
l = sitk.GetImageFromArray(label)
l.SetSpacing(spacing)
return l
def main():
vol = sitk.ReadImage("Test.mha")
volarray = sitk.GetArrayFromImage(vol)
newvol = sitk.GetImageFromArray(volarray)
newvol.SetSpacing(vol.GetSpacing())
newvol.SetDirection(vol.GetDirection())
newvol.SetOrigin(vol.GetOrigin())
mask = lungmask(newvol)
sitk.WriteImage(mask,"newlungmask.mha")
if __name__ == "__main__":
main()
胸部CT提取分割肺部的更多相关文章
- 一文带你解读:卷积神经网络自动判读胸部CT图像的机器学习原理
本文介绍了利用机器学习实现胸部CT扫描图像自动判读的任务,这对我来说是一个有趣的课题,因为它是我博士论文研究的重点.这篇文章的主要参考资料是我最近的预印本 “Machine-Learning-Base ...
- lung 分割论文
<4D Lung Tumor Segmentation via Shape Prior and Motion Cues > Abstract— Lung tumor segmentatio ...
- CT值及CT常用窗宽、窗位 [转]
一.常用CT值 CT值的含义是:每个反应管内的荧光信号达到设定的域值时所经历的循环数.研究表明,每个模板的Ct值与该模板的起始拷贝数的 对数存在线性关系,起始拷贝数越多,Ct值越小.利用已知起始拷贝数 ...
- Oracle拆分字符串,字符串分割的函数。
第一种:oracle字符串分割和提取 分割 create or replace function Get_StrArrayLength ( av_str varchar2, --要分割的字符串 av_ ...
- 12、多空格&多制表符文本之cut域分割终极方案
解决方法分为如下三步: (1) 使用“tr”命令将制表符转换为空格: (2) 使用“tr”命令将多个重复空格删除,保留一个空格: (3) 使用“cut”命令进 ...
- ArcGIS把导入的shp按渔网区块分割成更小的文件
前言 前端地图的开发需要导入城市的3D建筑白模,如果直接导入整个城市的json,文件大小高达76M,浏览器会直接崩溃,所以需要用ArcGIS分割成更小的文件后再给前端导入展示. ArcGIS版本:10 ...
- Candidate Generation and LUNA16 preprocessing
在这个kernel中,我们将讨论有助于更好地理解问题陈述和数据可视化的方法. 我还将提供有用的资源和信息的链接. 此脚本是用Python编写的. 我建议人们在桌面上安装anaconda,因为here提 ...
- AI产品经理成长路
AI产品经理成长路 https://www.jianshu.com/p/4b98314ad3c0 以下都是自己平时知识的一些总结,只是一些个人的愚见,下面出现的公司.书籍.视频.网站都是自己看过体验过 ...
- Case Study - 预测肺癌
Problem 肺癌是发病率和死亡率增长最快,对人群健康和生命威胁最大的恶性肿瘤之一.近50年来许多国家都报道肺癌的发病率和死亡率均明显增高,男性肺癌发病率和死亡率均占所有恶性肿瘤的第一位,女性发病率 ...
随机推荐
- beacon帧字段结构最全总结(一)——beacon基本结构
一.beacon帧主要结构 二.MAC header 1.Version:版本号,目前为止802.11只有一个版本,所以协议编号为0 2.Type:定义802.11帧类型,802.11帧分为管理帧( ...
- Python 基础 面向对象之二 三大特性
Python 基础 面向对象之二 三大特性 上一篇主要介绍了Python中,面向对象的类和对象的定义及实例的简单应用,本篇继续接着上篇来谈,在这一篇中我们重点要谈及的内容有:Python 类的成员.成 ...
- 提交代码到github托管
廖雪峰官网:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000,感觉初学很棒的一个地 ...
- PHP Laravel-包含你自己的帮助函数
你可能想创建一个在应用的任何地方都可以访问的函数,这个教程将帮你实现
- 通过C/C++,实现一元一次方程求解
通过C/C++,实现一元一次方程求解: #include <bits/stdc++.h> using namespace std; string str, str_l, str_r; st ...
- Pashmak and Parmida's problem(树状数组)
题目链接:http://codeforces.com/contest/459/problem/D 题意: 数列A, ai表示 i-th 的值, f(i,j, x) 表示[i,j]之间x的数目, 问:当 ...
- vux组件的样式变量的使用
使用x-header,查看文档发现有个样式变量,可以改变x-header的样式 这玩意怎么用呢? 1.在项目中创建一个.less样式文件,例如我这里是创建一个src/style/vux_theme.l ...
- 宋宝华: Linux内核编程广泛使用的前向声明(Forward Declaration)
本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者:宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 前向声明 编程定律 先强调一点:在一切可 ...
- numpy和matplotlib下载中出现的问题
在安装numpy的时候遇到如下所示的错误: 经过几个小时的查找,最终发现是pygame的路径不对导致.将pygame的具体路径加上后,问题解决.实施如下:得出一个结论:路径很重要,千万得小心哦. 报错 ...
- ctf比赛linux文件监控和恢复shell
之前参加ctf比赛时候临时写的,有很多不足,不过可以用,就贴出来分享给大家,希望对大家有帮助. 脚本一:记录当前目录情况 #!/bin/bashfunction getdir(){ for el ...