从CT图片到3D互动解剖教学模型的制作—以颅骨解剖结构教学模型制作为例
2017-11-29周瑶
周 瑶
黄冈职业技术学院附属医院, 湖北 黄冈 438000
从CT图片到3D互动解剖教学模型的制作—以颅骨解剖结构教学模型制作为例
周 瑶
黄冈职业技术学院附属医院, 湖北 黄冈 438000
文章探讨了从CT图片到3D互动解剖教学模型的制作过程:通过一个真实人体的CT图片,进行3D解剖数字模型制作,并利用Unity3D制作成可在多个平台运行并互动的软件,以利于医学解剖教学。
CT图片;3D;Mimics;Unity 3D;C#;解剖;教学
医学教学信息化因行业间的差别通常难以互通,而一些现代信息手段也难以应用在医学教学上。医学教学课堂以演示文稿为主,网站互动成为主要互动方法,不能提高学生互动兴趣[1]。文章试图结合医学解剖教学,借助一些软件,制作成可互动的3D解剖模型,为教师教学和学生学习提供信息化教学的思路。
1 设计思路
将人体结构转换成3D数字模型,再将数字模型导入Unity成为场景或游戏对象,用脚本控制互动操作,最后根据需要面向电脑、Web或手机发布应用。互动操作包含自由旋转3D解剖模型、放大缩小模型[2]、在模型上标记并能去掉标记、“内窥镜”查看内部结构等功能[3]。
2 通过Mimics软件制备3D建模
人体结构的来源依靠CT或MRI数字图片。该次示例采用CT(GE Optima CT660)导出头部DICOM格式图片305张(层距0.625 mm),导入Mimics 17.0软件,进行阈值分割(thresholding),并生成蒙板(Mask),通过计算(Calculate 3D),得到STL文件。阈值分割是否满意,以及是否需要进一步进行使用区域增长(region growing)或者手工处理(Edit mask 工具),完全依赖于操作者对人体解剖的熟悉程度。获取到我们需要的结构(如骨、肌肉、脏器、皮肤等),以及符合教学的精准程度,需要具备一定的实践经验。生成的STL文件可用于3D打印[4]。
打开3Ds Max软件,导入STL文件,形成组后,导出为fbx格式模型。在3Ds Max中要注意设置导出单位为Micrometer。这样,用CT图片处理成3D模型已经完成。
3 通过Unity软件制备互动解剖模型并发布
打开Unity软件,创建一个新的项目。导入准备好的fbx解剖模型,以及场景中需要的各种资源,如欢迎界面图片、按钮图片等。
3.1场景设计
场景设计以及互相切换如下图。欢迎界面可用专业特色图片做背景,并设计按钮分别跳转需要的场景(如图1所示)。
图1 各场景切换及相互关系
3.2主要场景搭建和主要脚本文件
欢迎场景主要功能是一些可跳转的按钮和帮助文件。设计3个按钮,分别为:跳转帮助界面,说明操作方法;跳转加载场景,并通过异步加载进入互动场景;链接到教师个人主页或网页。3个按钮均挂载同一脚本WelcomeAndGo.cs:
using UnityEngine;
using System.Collections;
public class WelcomeAndGo:MonoBehaviour{
void OnClick()
{
switch(this.gameObject.name){
case"play":
Application.LoadLevel("loadload");
break;
case"help":
Application.LoadLevel("Dohelp");
break;
case"about":
Application.OpenURL("http://www.hbhgzy.com.
cn/Index.html");
break;
}
}
}
加载等待场景是因为导入的3D解剖模型可多达近106个面,加载资源需要一段时间,故直接在Main Camera上加载script组件Loaderr.cs:
using UnityEngine;
using System.Collections;
public class Loaderr:MonoBehaviour
{
AsyncOperation async;
private float progress;
void Start()
{
StartCoroutine(loadScene());
}
IEnumerator loadScene()
{
yield return new WaitForEndOfFrame();
async=Application.LoadLevelAsync("playtext");
yield return async;
}
void Update()
{
progress=async.progress*100f;
}
void OnGUI()
{
GUI.Label(new Rect(Screen.width*0.48f,Screen.height*0.7f,Screen.width*0.3f,Screen.height*0.05f),progress+"%");
GUI.HorizontalSlider(new Rect(Screen.width*0.25f,Screen.height*0.75f,Screen.width*0.5f,Screen.height*0.1f),progress,1,100);
GUI.Label(new Rect(Screen.width*0.4f,Screen.height*0.8f,Screen.width*0.3f,Screen.height*0.05f),"场景加载中,请稍等......");
}
}
互动场景是主要场景,先导入先前制作的fbx解剖模型,并在模型上加载C#脚本NewMove.cs,可以使用键盘(WSAD以及→←↑↓)控制模型的旋转和缩放(Z、X):
using UnityEngine;
using System.Collections;
public class NewMove:MonoBehaviour{
private float angle;
void Start(){
angle=5f;
}
void Update()
{
if(Input.GetKey(KeyCode.W)||Input.GetKey(KeyCode.DownArrow))
{
transform.Rotate(Vector3.right,angle);
}else if(Input.GetKey(KeyCode.S)||Input.GetKey(KeyCode.UpArrow))
{
transform.Rotate(Vector3.right,angle*-1);
}
if(Input.GetKey(KeyCode.A)||Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(Vector3.forward,angle);
}else if(Input.GetKey(KeyCode.D)||Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(Vector3.forward,angle*-1);
}
if(Input.GetKey(KeyCode.X))
{
transform.localScale+=new Vector3(0.1f,0.1f,0.1f);
}else if(Input.GetKey(KeyCode.Z))
{
transform.localScale-=new Vector3(0.1f,0.1f,0.1f);
}
}
}
为了使操作更加直观,需要在场景中加载一些操作按钮脚本ButtonAndQuit.cs:
using UnityEngine;
using System.Collections;
public class ButtonAndQuit:MonoBehaviour
{
private float angle;
void Start()
{
angle=5f;
}
void OnGUI()
{
if(GUI.Button(new Rect(Screen.width-150,100,
100,50),"上翻")){transform.Rotate(Vector3.right,
angle);
}
if(GUI.Button(new Rect(Screen.width-150,200,
100,50),"下翻")){transform.Rotate(Vector3.right,
angle*-1);
}
if(GUI.Button(new Rect(Screen.width-200,150,
50,50),"左转")){transform.Rotate(Vector3.forward,
angle);
}
if(GUI.Button(new Rect(Screen.width-50,150,50,50),"右转")){transform.Rotate(Vector3.forward,
angle*-1);
}
if(GUI.Button(new Rect(Screen.width-150,Screen.height-50,100,50),"退出")){
Application.Quit();
}
if(GUI.Button(new Rect(Screen.width-150,Screen.height-150,100,50),"复位")){
Application.LoadLevel("playtext");
}
if(GUI.Button(new Rect(Screen.width-150,Screen.height-200,100,50),"内窥镜")){
Application.LoadLevel("EndMove");
}
if(GUI.Button(new Rect(Screen.width-150,Screen.height-100,100,50),"返回")){
Application.LoadLevel("wolcome");
}
}
}
另外,场景中加入一空游戏对象,加载以下脚本Signn.cs,以能够在互动时标记,方便教师讲解或学生作业(如图2所示)。
图2 头颅3D模型导入后制作的互动操作(缩放、旋转、标记)
using UnityEngine;
using System.Collections;
public class Signn:MonoBehaviour
{
void Update()
{
if(Input.GetMouseButtonDown(0)){
Ray rayy=Camera.main.ScreenPointToRay(Input.
mousePosition);
RaycastHit hit;
if(Physics.Raycast(rayy,out hit)){
if(hit.collider.gameObject.name=="head2017
0216"){
Vector3 pos=hit.point;
GameObject redboll=GameObject.CreatePrimi-
tive(PrimitiveType.Sphere);
redboll.transform.position=pos;
redboll.transform.localScale=hit.transform.localScale*0.05f;
redboll.renderer.material.color=Color.red;
if(Input.GetKey(KeyCode.Alpha1)){
redboll.renderer.material.color=Color.red;
}else if(Input.GetKey(KeyCode.Alpha2)){
redboll.renderer.material.color=Color.green;
}else if(Input.GetKey(KeyCode.Alpha3)){
redboll.renderer.material.color=Color.yellow;
}else if(Input.GetKey(KeyCode.Alpha4)){
redboll.renderer.material.color=Color.blue;
}
redboll.transform.parent=hit.transform;
redboll.AddComponent
}
}
}
}
}
该例左键点击标记一个小球,按1、2、3、4等数字键可改变不同颜色。右键点击时标记的小球消失,在生成的小球上需要另加一个组件,脚本DesoryBoll.cs另为:
using UnityEngine;
using System.Collections;
public class DesoryBoll:MonoBehaviour{
void Update()
{
if(Input.GetMouseButtonDown(1))
{
Ray rayyy=Camera.main.ScreenPointToRay(Input.
mousePosition);
RaycastHit hitt;
if(Physics.Raycast(rayyy,out hitt))
{
Destroy(hitt.collider.gameObject);
}
}
}
}
内窥镜场景是为了更好地观察一些腔隙内部的结构(如图3所示),在“内窥镜”(摄像机)按钮,导入一个新场景。场景的摄像机上加载一个自由视角脚本EndMouselook.cs。
图3 模拟“内窥镜”看到的颅后窝及枕骨大孔
using UnityEngine;
using System.Collections;
public class EndMouselook:MonoBehaviour
{
public enum RotationAxess
{
MouseXAndY=0,
Mouse X=1,
Mouse Y=2
}
public RotationAxess axes=RotationAxess.MouseXAndY;
public float sensitivity_X=20F;public float sensitivity_Y=20F;
public float minimum_Y=-360F;
public float maximum_Y=360F;
public Texture2D picture1;
public GameObject target;
float rotation_Y=0F;
void Update()
{
target=GameObject.Find("Player");
transform.position=target.transform.position;
if(axes==RotationAxess.MouseXAndY){
float rotation_X=transform.localEulerAngles.y+Input.GetAxis("Mouse X")*sensitivity_X;
rotation_Y+=Input.GetAxis("Mouse Y")*sen-
sitivity_Y;
rotation_Y=Mathf.Clamp(rotation_Y,minimum_Y,maximum_Y);
transform.localEulerAngles=new Vector3(-rotation_Y,rotation_X,0);
}else if(axes==RotationAxess.MouseX){
transform.Rotate(0,Input.GetAxis("Mouse X")*sensitivity_X,0);
} else {
rotation_Y+=Input.GetAxis("Mouse Y")*sen-
sitivity_Y;
rotation_Y=Mathf.Clamp(rotation_Y,minimum_Y,maximum_Y);
transform.localEulerAngles=new Vector3(-rotation_Y,transform.localEulerAngles.y,0);
}
}
void OnGUI()
{
GUI.DrawTexture(new Rect(0,0,Screen.width,Sc-
reen.height),picture1);
if(GUI.Button(new Rect(Screen.width-150,Screen.height-100,100,50),"返回")){
Application.LoadLevel("playtext");
}
}
}
另增加一个空游戏对象,除加载上一个脚本外,须加载一个移动操作脚本EndMove01.cs,并与摄像机绑定在一起:
using UnityEngine;
using System.Collections;
public class EndMove01:MonoBehaviour
{
public float speed;
void Start()
{
speed=0.005f;
}
void Update()
{
if(Input.GetKey(KeyCode.W)){
transform.Translate(Vector3.forward*speed);
}else if(Input.GetKey(KeyCode.S)){
transform.Translate(Vector3.back*speed);
}
if(Input.GetKey(KeyCode.A)){
transform.Translate(Vector3.right*speed);
}else if(Input.GetKey(KeyCode.D)){
transform.Translate(Vector3.left*speed);
}
}
}
至此,整个互动制作基本完成,测试各场景跳转及操作无误后即可进行发布。根据不同需要,可以向不同平台发布,如PC,Mac & Linux Standalone、Web Player[5]、Android、iOS等平台,以方便各种应用的需要。向PC平台发布时,生成的软件无须安装,双击exe文件即可在自建的窗口中运行。
目前,软件的Web发布是流行趋势,将项目向网页(Web)平台发布,各种浏览器均能在线或单机运行此项目,这样3D解剖互动即能实现远程互动。在发布之前,要求Unity软件安装Unity Web Player Full插件,否则离线将无法运行。发布生成的文件html即可用常规浏览器打开,这在网页建设中是十分有利的。而对html进行参数设置(MonoDevelop脚本编辑器),可以修改logo、进度条、背景色等,以改善软件的运行状态。
4 讨论
此次教学模型的制作,用到3个软件和一个编程语言(C#),最后制作出能在多种平台上应用和操作的软件,达到用于教学的目的。
其中,Mimics软件的应用需要专业解剖学知识,能准确取到符合要求的3D模型。不同解剖部位的分割需要对解剖结构相当熟悉,还需要有时间上的耐心和分割技巧。简易直观的培训材料能帮助教师完成这个项目。
3Ds Max软件的作用仅将STL文件转换成Fbx文件,但它根据要求录制3D视频文件,这也可以作为教学之需。
Unity软件在近几年的3D游戏制作中极为火热,对制作教学软件也十分有利:①互动操作的实现方便、直观。不仅在解剖结构上的旋转、缩放、场景转换时方便,还可开发出一些数字交互,如用“药”后的“人体”改变、医疗处置操作等。②角色控制和自动导航等实现人体自身生理变化。如“食物”的吸收与转化[6]、血流动力学、神经传导、分子构象、细胞生理等的变化,都可用软件表现出来。③Unity的离子系统可以用于模拟人体的呼吸气流、循环血流、呕吐、咳嗽、大小便等生理状态。④Unity的动画系统和关节(Joint),可以用于人体运动的各种状态或康复运动状态,通过脚本表达关节的转动(角度)或肌肉的收缩,角度和强度将受程序控制,还可用于产科产程过程教学[7]。⑤渲染和布料有利用于控制人体皮肤属性、病理切片或针灸学的腧穴[8]。如皮肤的黄染、苍白、青紫等病理变化,以及各种传染病的皮疹、皮肤病病变。
因此,该类教学软件的制作,需要熟悉Mimics等制模软件,精通医学各专业知识,同时,应熟悉Unity3D软件的应用,掌握一门编程语言,如C#或者JaveScr-ipt,用于表现各种生理、病理过程。
医学教学信息化的实现,是一个跨学科的项目,旨在把医学解剖和生理、病理使用计算机技术表达出来,以供学生学习或健康教育的开展和传播[9]。
[1]朱振东,张林,任铭新.3D动画技术在人体解剖学实验教学中的应用探索[J].中国高等医学教育,2016(9):120-121
[2]王刚,郭育卓,欧阳钧.3D多媒体软件系统在人体解剖学教学中的应用探索[J].解剖学研究,2015,37(1):69-71
[3]温小鹏,张广健,付军科,等.3D腔镜视频资料在腔镜手术教学中的应用[J].西北医学教育,2016,24(3):489-491
[4]李忠海,唐家广,王华东,等.3D打印技术在骨科临床教学中的应用初探[J].中国医学教育技术,2016,30(2):198-200
[5]杨天化,辛均益,安国防,等.Web 3D技术及其在解剖学教学中的应用研究[J].中国现代医生,2016,54(9):120-127
[6]闻永,汤华军,李俊,等.3D解剖模拟技术结合PBL教学模式在肛肠解剖教学中的应用探析[J].解剖学研究,2016,38(5):414-416
[7]李圣洁,熊振芳,李琳,等.3D虚拟展示技术在妇产科护理学教学中的应用的质性研究[J].护理研究,2016,30(9):3412-3413
[8]张季,张宏如,董海艳,等.基于Unity 3D技术的数字人体腧穴教学信息系统的设计与实现[J].中国医学教育技术,2014,28(2):139-142
[9]夏爽,李松峰,黄娜.3D解剖结构教学模型在人体解剖实验教学中的研究[J].中国继续医学教育,2016,8(31):16-17
ProductionofCTimages-to-3Dinteractiveanatomyteachingmodel:Takingtheskullasanexample
ZhouYao
AffiliatedHospitalofHuanggangVocationalandTechnicalCollege,Huanggang438000,China
This article discusses the process of making CT images-to-3D interactive anatomy teaching model. By using CT images of a real human body, we make a 3D anatomy digital model. We also make interactive software with Unity3D that can be run on multiple platforms so as to facilitate medical anatomy teaching.
computed tomography (CT) image; 3D; Mimics; Unity 3D; C#; anatomy; teaching
2017-03-31
周瑶(1973-),男,内蒙古托县人,副主任医师,本科,主要研究方向:医学教育、儿科医学。
G434
:A
:1004-5287(2017)05-0541-06
:10.13566/j.cnki.cmet.cn61-1317/g4.201705014