作者:天元浪子

来源:Python作业辅导员

前言

CT是现代医学影像的主力设备,寻常百姓并不陌生。通常,一张CT片由多张连续断层扫描的图像组成。在医生眼中,CT片展示了人体器官的形态和性质,是判断病人健康状况的重要依据。对于普通人而言,CT片则像天书,几无大用。不过呢,总有不甘寂寞喜欢折腾的程序员,把看似无用的CT片玩出了新花样——用头部CT断层扫描片成功复原出了逼真的三维头像。

CT是如何变成三维头像的呢?

说白了,其实很简单,只需要3步:

  1. 准备一套头部CT断层扫描片。怎么准备?要么去网上找(我就是从网上下载的),要么自己扫描胶片。

  2. 按照断层顺序逐张读入图片,并垂直堆叠成一个numpy数组。

  3. 导入3D工具库WxGL,调用capsule函数,绘制三维头像。

我手头这套头部CT断层扫描片共有109张,是侧卧位的水平断层扫描,从一侧开始至另一侧结束。下图从左至右分别是第11张、第21张、第55张、第89张、第99张。不难看出,中间的一张面积最大,是鼻梁正中的断层图片,鼻尖朝向图片上方,越往两侧的图片,面积越小。

有了CT断层扫描片,接下来就是打开文件读取数据了。做这一步之前需要先导入pillow模块和numpy模块。假定CT文件保存在:

D:\XufiveGithub\wxgl\res\headCT这个路径下,每个文件名都以head+序号的方式命名,下面是读取数据的代码。

>>> from PIL import Image
>>> import numpy as np
>>> base_dir = r'D:\XufiveGithub\wxgl\res\headCT'
>>> data = list()
>>> for i in range(109):im = np.array(Image.open(r'%s\head%d.png'%(base_dir, i)))data.append(im)>>> data = np.stack(data, axis=0)

其实,读取数据的代码可以写得更简洁,使用列表推导式,只用一行就可以了。

>>> data = np.stack([np.array(Image.open(r'%s\head%d.png'%(base_dir, i))) for i in range(109)], axis=0)
>>> data.shape
(109, 256, 256, 4)

从data.shape可以看出,总共有109个断层,每个断层分辨率是256x256像素,每个像素有RGBA四个通道。比较每个通道的数据,就会发现,每个断层的RGBA四个通道是完全相同的,这是胶片扫描的特点决定的。

三维重建的基本原理是滤除完全透明的像素,用具有相同透明度且位置相邻的像素构建surface,因此数组data中只有透明通道(A通道)是我们需要的。

data = data[...,3] # 提取透明通道
>>> data.shape
(109, 256, 256)

现在data变成一个三维数组了。数组的0轴,即第1张到第109张CT片的方向,对应着头像的左右;数组的1轴,即每张CT片自上而下的方向,对应着头像的前后;数组的2轴,即每张CT片从左至右的方向,对应着头像的上下。3D工具库WxGL习惯将数据数组的0轴视为高度方向,不做调整的话,绘制出的头像将是水平侧卧的,就像CT片展示的那样。为了让头像立起来,需要将头像的上下方对应的数组2轴翻转到0轴之后,再上下翻转。

>>> data = np.rollaxis(data, 2, 0) # 2轴翻转至0轴,让头像立起来(倒立)
>>> data = np.flipud(data) # 上下翻转,头像正立
>>> data.shape
(256, 109, 256)

至此,数据处理算是完成了,不过,这些数据还没有空间定位,只是保持了相对的位置关系,我们需要给数据限定一个空间位置。由于CT片没有给出头部尺寸和分层厚度,只能按照通常的头像比例,给出头像在xyz轴上的空间范围。

x = np.linspace(-1, 1, data.shape[2]) # 头像前后范围:[-1, 1]
y = np.linspace(-0.65, 0.65, data.shape[1]) # 头像左右范围:[-0.65, 0.65]
z = np.linspace(-1, 1, data.shape[0]) # 头像高度范围:[-1, 1]

另外,还要滤除几乎完全透明的那些像素。我们暂且以最大值的1/8作为阈值,调整该阈值将会得到不同的重建效果。

level = data.max()/8 # 忽略低于此阈值的数据

万事俱备,只欠东风。是时候让wxgl一显身手了。

plt.capsule(data, x=x, y=y, z=z, level=level, color='#EEE9D4')
plt.show()

不要惊讶,只需要两行代码,一个逼真的三维头像呈现在眼前。这一切,仅仅依赖一套CT断层扫描片和WxGL这个3D工具库。

刚刚发布的0.7.3版3D工具库WxGL,新增了几个有趣的功能,其中之一就是刚刚用到的capsule函数。capsule意为胶囊,顾名思义,capsule函数可以从三维数据中找出等值面,并尝试构建出囊性结构(如果存在的话)。WxGL的安装非常简单,直接使用pip命令即可。如果在安装和使用WxGL的过程中遇到问题,请在文后留言,也可以直接到我的GitHub反馈问题。

pip install wxgl

最后,附上用头部CT断层扫描片复原三维头像的完整代码。

import numpy as np
from PIL import Image
from wxgl import wxplot as pltbase = r'D:\XufiveGithub\wxgl\res\headCT'
data = np.stack([np.array(Image.open(r'%s\head%d.png'%(base, i))) for i in range(109)], axis=0)data = data[...,3] # 提取透明通道
data = np.rollaxis(data, 2, 0) # 2轴翻转至0轴,让头像立起来(倒立)
data = np.flipud(data) # 上下翻转,头像正立x = np.linspace(-1, 1, data.shape[2]) # 头像前后范围:[-1, 1]
y = np.linspace(-0.65, 0.65, data.shape[1]) # 头像左右范围:[-0.65, 0.65]
z = np.linspace(-1, 1, data.shape[0]) # 头像高度范围:[-1, 1]
level = data.max()/8 # 忽略低于此阈值的数据plt.capsule(data, x=x, y=y, z=z, level=level, color='#EEE9D4')
plt.show(rotate=-1)

下图直观显示了不同的阈值对于三维重建结果的影响。

END

新闻

英伟达推出全球首个元宇宙平台

技术

想提高代码水平,做到这点

技术

Unet网络实现叶子病虫害图像分割

新闻

17岁少年因“泄愤”攻击航司系统

分享

点收藏

点点赞

点在看

CT片居然可以这么玩:用头部CT断层扫描片复原三维头像相关推荐

  1. 头部ct能检查出什么_做脑部CT对身体有伤害吗?看完你就知道了!

    在生活中,很多人出现头痛或者是在摔倒弄伤脑部后都需要进行CT检查,只有通CT检查才能够很好的诊断,而很多人都知道CT检查对身体的伤害性是很大的,尤其是小孩.所以很多人在屋檐进行CT检查的时候是有所抗拒 ...

  2. 头部ct能检查出什么_【安全用药】做CT检查时应注意什么?

    点击蓝字 关注我们 安安 徽徽,你知道做CT检查时应注意什么? 上腹部CT检查前患者至少禁食6小时.检查前15分钟喝温开水充盈胃部.CT检查时,患者会受到一定量X射线辐射,应避免过度扫描......本 ...

  3. 头部ct能检查出什么_脑部ct能检查出什么

    全国体检预约平台 脑部 ct 能检查出什么 颅脑的 CT 检查具有无痛苦,方便.安全,适宜任何人群和年龄段的患者.这种检查手段也 越来越广泛的运用在各种疾病的的临床诊断检查中.因为很多脑部的一些疾病和 ...

  4. matlab ct投影数据,3.医学影像系统实验-CT投影数据采集、反投影重建实验.ppt

    3.医学影像系统实验-CT投影数据采集.反投影重建实验 华中科技大学生命科学与技术学院 实验教学中心 张日欣 * 实验内容介绍 数字图像处理部分(12学时) CT投影数据采集.反投影重建实验(2学时) ...

  5. 头部 CT 图像三维重建

    开放数据集 开放数据集:http://headctstudy.qure.ai/dataset 其中某个样本:CQ500CT181 数据处理 导入可能要用的包 import pydicom import ...

  6. 充电口 米兔积木机器人_米兔积木机器人居然可以这么玩?!

    米兔积木机器人受到了广大网友的喜爱,今天上线了米兔积木机器人颜色传感器. 原来搭配上之后,机器人还可以这么玩! 无线连接 突破接口数量限制 米兔积木机器人颜色传感器采用了创新的无线连接模式,可以让颜色 ...

  7. 你居然用计算机玩csgo,新潮流,用CSGO来测试电脑性能!最后一个你一定没听过...

    原标题:新潮流,用CSGO来测试电脑性能!最后一个你一定没听过 很多的玩家们都很在意自己的电脑性能到达什么样的水平,大家也会钟情于用很多的跑分软件来测试自己的电脑性能与数值.但是今天小编给各位带来如何 ...

  8. Python字符串居然可以这样玩 到底怎么做到的 年薪50w程序员揭晓

    Python如何比较字符串?由于字符串是Python中最常用的数据类型,所以我们考虑简化字符串比较操作.在本教程中,我们将介绍如何创建字符串对象,如何使用引号,最重要的是在Python中比较字符串的七 ...

  9. python可以怎么玩_这波太炸了!Python脚本可视化居然可以这么玩!

    如同艺术家们用绘画让人们更贴切的感知世界,数据可视化也能让人们更直观的传递数据所要表达的信息.你知道Python脚本可视化有多好看么?就像下图这样,是不是感觉十分高端大气上档次: 以上示例都是通过Ry ...

最新文章

  1. OpenNI框架介绍
  2. 可视化监控指标展示工具 grafana 简介
  3. 简单认识Hexo的目录结构
  4. mac 10.9.5 安装hadoop 1.2.1 运行wordcount
  5. 说一说ffmpeg到处都在使用的ff_thread_once函数
  6. 一线大厂在机器学习方向的面试题(一)
  7. netty系列之:文本聊天室
  8. 一个好用的便利设置浏览器代理的Chrome扩展应用
  9. 《springcloud超级入门》Spring Boot简介《五》
  10. mysql view在测试过程的应用
  11. AI 人才遭疯抢,Google 为 22 岁印度毕业生开出 1000w+ 年薪
  12. 简单的shell命令
  13. 右)侧固定宽度,右(左)侧宽度自适应 ---清除浮动
  14. 8.4文件系统的管理与挂载2
  15. 优秀课件笔记之文件系统
  16. 均匀权重向量集合的生成
  17. 计算机有什么简便快捷方法,运行快捷键(电脑常用快捷键大全)
  18. 163邮箱如何注册呢?
  19. 超详细的新手8周跑步入门训练计划(从走跑开始)
  20. 友盟分享error:包名错误,确认与开放平台包名一致

热门文章

  1. Java多线程学习处理高并发问题
  2. 【亲测有效】如何在win10上激活Burp Suite,如何注册激活Burp Suite,破解Burp Suite的详细步骤
  3. 使用阿里云发布分布式网站,开发时候应该注意什么?
  4. RPC是什么?为什么要学习RPC?
  5. ExtJs 备忘录(3)—— Form表单(三) [ 数据验证 ]
  6. 【转载】【贪心】各种覆盖问题
  7. nginx虚拟目录配置
  8. 关于Iframe在IE6下不显示的bug
  9. java加载图片到缓存_Android实现图片异步加载并缓存到本地
  10. java io 缓冲流_记忆系列-Java IO的缓存输入输出流(高效流)