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
  1. import SimpleITK as sitk
  2. from skimage import measure
  3. def lungmask(vol):
  4. #获取体数据的尺寸
  5. size = sitk.Image(vol).GetSize()
  6. #获取体数据的空间尺寸
  7. spacing = sitk.Image(vol).GetSpacing()
  8. #将体数据转为numpy数组
  9. volarray = sitk.GetArrayFromImage(vol)
  10. #根据CT值,将数据二值化(一般来说-300以下是空气的CT值)
  11. volarray[volarray>=-300]=1
  12. volarray[volarray<=- 300]=0
  13. #生成阈值图像
  14. threshold = sitk.GetImageFromArray(volarray)
  15. threshold.SetSpacing(spacing)
  16. #利用种子生成算法,填充空气
  17. ConnectedThresholdImageFilter = sitk.ConnectedThresholdImageFilter()
  18. ConnectedThresholdImageFilter.SetLower(0)
  19. ConnectedThresholdImageFilter.SetUpper(0)
  20. ConnectedThresholdImageFilter.SetSeedList([(0,0,0),(size[0]-1,size[1]-1,0)])
  21. #得到body的mask,此时body部分是0,所以反转一下
  22. bodymask = ConnectedThresholdImageFilter.Execute(threshold)
  23. bodymask = sitk.ShiftScale(bodymask,-1,-1)
  24. #用bodymask减去threshold,得到初步的lung的mask
  25. temp = sitk.GetImageFromArray(sitk.GetArrayFromImage(bodymask)-sitk.GetArrayFromImage(threshold))
  26. temp.SetSpacing(spacing)
  27. #利用形态学来去掉一定的肺部的小区域
  28. bm = sitk.BinaryMorphologicalClosingImageFilter()
  29. bm.SetKernelType(sitk.sitkBall)
  30. bm.SetKernelRadius(2)
  31. bm.SetForegroundValue(1)
  32. lungmask = bm.Execute(temp)
  33. #利用measure来计算连通域
  34. lungmaskarray = sitk.GetArrayFromImage(lungmask)
  35. label = measure.label(lungmaskarray,connectivity=2)
  36. props = measure.regionprops(label)
  37. #计算每个连通域的体素的个数
  38. numPix = []
  39. for ia in range(len(props)):
  40. numPix += [props[ia].area]
  41. #最大连通域的体素个数,也就是肺部
  42. maxnum = max(numPix)
  43. #遍历每个连通区域
  44. for i in range(len(numPix)):
  45. #如果当前连通区域不是最大值所在的区域,则当前区域的值全部置为0,否则为1
  46. if numPix[i]!=maxnum:
  47. label[label==i+1]=0
  48. else:
  49. label[label==i+1]=1
  50. label = label.astype("int16")
  51. l = sitk.GetImageFromArray(label)
  52. l.SetSpacing(spacing)
  53. return l
  54. def main():
  55. vol = sitk.ReadImage("Test.mha")
  56. volarray = sitk.GetArrayFromImage(vol)
  57. newvol = sitk.GetImageFromArray(volarray)
  58. newvol.SetSpacing(vol.GetSpacing())
  59. newvol.SetDirection(vol.GetDirection())
  60. newvol.SetOrigin(vol.GetOrigin())
  61. mask = lungmask(newvol)
  62. sitk.WriteImage(mask,"newlungmask.mha")
  63. if __name__ == "__main__":
  64. main()

胸部CT提取分割肺部的更多相关文章

  1. 一文带你解读:卷积神经网络自动判读胸部CT图像的机器学习原理

    本文介绍了利用机器学习实现胸部CT扫描图像自动判读的任务,这对我来说是一个有趣的课题,因为它是我博士论文研究的重点.这篇文章的主要参考资料是我最近的预印本 “Machine-Learning-Base ...

  2. lung 分割论文

    <4D Lung Tumor Segmentation via Shape Prior and Motion Cues > Abstract— Lung tumor segmentatio ...

  3. CT值及CT常用窗宽、窗位 [转]

    一.常用CT值 CT值的含义是:每个反应管内的荧光信号达到设定的域值时所经历的循环数.研究表明,每个模板的Ct值与该模板的起始拷贝数的 对数存在线性关系,起始拷贝数越多,Ct值越小.利用已知起始拷贝数 ...

  4. Oracle拆分字符串,字符串分割的函数。

    第一种:oracle字符串分割和提取 分割 create or replace function Get_StrArrayLength ( av_str varchar2, --要分割的字符串 av_ ...

  5. 12、多空格&多制表符文本之cut域分割终极方案

    解决方法分为如下三步: (1)        使用“tr”命令将制表符转换为空格: (2)        使用“tr”命令将多个重复空格删除,保留一个空格: (3)        使用“cut”命令进 ...

  6. ArcGIS把导入的shp按渔网区块分割成更小的文件

    前言 前端地图的开发需要导入城市的3D建筑白模,如果直接导入整个城市的json,文件大小高达76M,浏览器会直接崩溃,所以需要用ArcGIS分割成更小的文件后再给前端导入展示. ArcGIS版本:10 ...

  7. Candidate Generation and LUNA16 preprocessing

    在这个kernel中,我们将讨论有助于更好地理解问题陈述和数据可视化的方法. 我还将提供有用的资源和信息的链接. 此脚本是用Python编写的. 我建议人们在桌面上安装anaconda,因为here提 ...

  8. AI产品经理成长路

    AI产品经理成长路 https://www.jianshu.com/p/4b98314ad3c0 以下都是自己平时知识的一些总结,只是一些个人的愚见,下面出现的公司.书籍.视频.网站都是自己看过体验过 ...

  9. Case Study - 预测肺癌

    Problem 肺癌是发病率和死亡率增长最快,对人群健康和生命威胁最大的恶性肿瘤之一.近50年来许多国家都报道肺癌的发病率和死亡率均明显增高,男性肺癌发病率和死亡率均占所有恶性肿瘤的第一位,女性发病率 ...

随机推荐

  1. python经典面试算法题1.3:如何计算两个单链表所代表的数之和

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.2 如何实现链表的逆序 [华为笔试题] 难度系数:⭐⭐⭐ ...

  2. 2019年10月13日 计算机英语习题 wangqingchao

    Match the explanations in Column B with words and expressions in Columna. (搭配每组中意义相同的词或短语) Types of ...

  3. Java nio 空轮询bug到底是什么

    编者注:Java nio 空轮询bug也就是Java nio在Linux系统下的epoll空轮询问题. epoll机制是Linux下一种高效的IO复用方式,相较于select和poll机制来说.其高效 ...

  4. PHP+Swoole并发编程的魅力

    PHP语言是一个短生命周期的Web编程语言,很多PHPer已经形成了fpm下编程的思维定势.实际上在Swoole出现之后,这种串行化编程的模式早已被打破.使用Swoole完全可以轻易实现更灵活的并发编 ...

  5. CSS 技巧一则 -- 在 CSS 中使用三角函数绘制曲线图形及展示动画

    最近一直在使用 css-doodle 实现一些 CSS 效果. css-doodle 是一个基于 Web-Component 的库.允许我们快速的创建基于 CSS Grid 布局的页面,以实现各种 C ...

  6. 领扣(LeetCode)七进制数 个人题解

    给定一个整数,将其转化为7进制,并以字符串形式输出. 示例 1: 输入: 100 输出: "202" 示例 2: 输入: -7 输出: "-10" 注意: 输入 ...

  7. php设置随机ip访问

    当我们请求一个站点的时候,http报文头会携带一些ip信息,我们通过伪造这些信息,就可以形成不同ip访问请求的效果. header的头部CLIENT-IP和X-FORWARDED-FOR我们都设置为想 ...

  8. An end-to-end TextSpotter with Explicit Alignment and Attention

     An end-to-end TextSpotter with Explicit Alignment and Attention 论文下载:http://cn.arxiv.org/pdf/1803.0 ...

  9. websrom编译器

    webstorm less环境配置 备注: 安装node后,在命令行输入npm install -g less 即可安装less,打开webstorm setting-Tools-FileWatche ...

  10. 图解 Spring:HTTP 请求的处理流程与机制【1】

    2003 年,老兵哥初到中兴开始研究生实习,Spring 就是那年诞生的,2004 年 3 月发布了 1.0 版本,到现在已经超过 15 年了.从单体式分层架构到云原生微服务架构,它稳坐在 JAVA ...