摘 要
随着计算机技术的迅速发展,数字图像处理技术在医学领域的研究和应用日益深入和广泛。现代医学已越来越离不开医学图像处理技术。医学图像处理技术在临床诊断、教学科研等方面发挥了重要的作用。计算机图像处理技术与影像技术的结合从根本上改变了医务人员进行诊断的传统方式。充分地利用这些技术可以提高诊断的正确性和准确性,提高诊断效率,降低医疗成本,可以更加充分地发挥各种医疗设备的功能。而且,随着数字化、智能化进程的深人,图像处理技术在医疗卫生领域将会有更加广阔的应用前景。
Java是Sun公司推出的一种面向对象编程语言。Java非常适合于企业网络和Internet环境,现已成为Internet中最受欢迎、最有影响的编程语言之一。目前国内使用Java语言开发的图像处理系统比较少,这也增加了这方面的研究价值。
本文首先对图像增强和图像分割中的几种算法进行了介绍,包括线性灰度变换,伪彩色处理,平滑处理,中值滤波,阈值分割,边缘检测等。然后用Java语言对上述各算法编程实现,并设计Java GUI(图形用户界面)用来显示图像处理的结果,以及创建一个数据库用于存储医学图像。
关键词:医学图像;图像增强;图像分割;面向对象
Abstract
As the computer technique’s quickly development, the image process technique having been more deeply and widely in the use and study of medical science. The modern medical science can not work well without the medical image processing technology; it has made an important use in clinical diagnosis and education study. The combination of the image processing technique and imaging technique has changed the way that traditional diagnosis.Make adequately use of this techniques will be increase accuracy, increase the efficiency of diagnosis, decrease the cost of medical treatment and make the most use of function with medical treatment equipments. Moreover, as the deeply with the arithmetic figure and the intelligence, the image processing technique will have a more wonderful future.
Java is a kind of object-oriented programming language from the company of Sun. The Java is becoming a most welcome and influence programming language which suits for the business network and the environment of internet. Currently, use Java language to developed image processing system is not very frequencyin our country. So, this is a cause of increasing the value of study.
This project introduces some kinds of algorithms in image enhancement and image segmentation. It includes linear grey level transformation, pseudo-color processing, smooth processing, median filter, threshold segmentation, edge detection and so on. Then, use Java to program and realize. And show the result of image processing using Java GUI (Graphical User Interface), as well as create a database to stock medical image.
Key Words: medical image; image enhancement; image segmentation; object-oriented
目录
1 引言
2 医学图像处理概述
2.1 什么是医学图像处理
2.2 医学图像处理及研究内容
2.2.1 超声图像
2.2.2 X射线图像
2.2.3 磁共振成像
2.2.4 核医学成像
2.3 医学图像处理技术新进展
3 Java语言的特点
3.1 面向对象编程
3.1.1 抽象
3.1.2 面向对象编程的3个原则
3.2 Java的特性
3.3 Java语言的前景
4 Java语言实现图像处理
4.1 图像增强技术
4.1.1 灰度变换
4.1.2 伪彩色处理
4.1.3 平滑化处理
4.1.4 其他图像增强技术
4.2 图像分割技术
4.2.1 阈值分割法
4.2.2 边缘检测法
4.3 图像复原技术
4.4 本章小结
5 设计流程
5.1 主流程图
5.2 图像处理界面
5.3 图像的加载
5.4 图像的处理
5.5 数据库的建立
6 开发工具
6.1 JCreator概述
6.2 JCreator编辑界面的组成
结 论
致 谢
参考文献
附录A 英文原文
附录B 中文翻译
附录C 源程序
1 引言
数字图像处理技术是20世纪60年代随着计算机技术和超大规模集成电路的发展而产生、发展和不断成熟起来的一个新兴技术领域,它在理论上和实际应用中都取得了巨大的成就。
视觉是人类最重要的感知手段,图像又是视觉的基础。早期图像处理的目的是改善图像质量,它以人为对象,以改善人的视觉效果为目的。图像处理中输入的是质量低的图像,输出的是改善质量后的图像。常用的图像处理方法有图像增强、复原、编码、压缩等。首次获得成功应用的是美国喷气推进实验室(JPL)。他们对航天探测器徘徊者7号在1964年发回的几千张月球照片进行图像处理,如几何校正、灰度变换、去除噪声等,并考虑了太阳位置和月球环境的影响,由计算机成功地绘制出月球表面地图,获得了巨大的成功。随后又对探测飞船发回的近十万张照片进行更为复杂的图像处理,获得了月球的地形图、彩色图及全景镶嵌图,为人类登月创举奠定了坚实的基础,也推动了数字图像处理这门学科的诞生。在以后的宇航空间技术探测研究中,数字图像处理技术都发挥了巨大的作用。
数字图像处理技术取得的另一个巨大成就是在医学上。1972年英国EMI公司工程师Housfield发明了用于头颅诊断的X射线计算机断层摄影装置,也就是我们通常所说的CT(Computer Tomograph)。CT的基本方法是根据人的头部截面的投影,经计算机处理来重建截面图像,称为图像重建。1975年EMI公司又成功研制出全身用的CT装置,获得了人体各个部位鲜明清晰的断层图像。1979年,这项无损伤诊断技术被授予诺贝尔奖,以表彰它对人类做出的划时代贡献。
从20世纪70年代中期开始,随着计算机技术和人工智能、思维科学研究的迅速发展,数字图像处理技术向更高、更深层次发展。人们已开始研究如何用计算机系统解释图像,类似人类视觉系统理解外部世界,这被称为图像理解或计算机视觉。很多国家,特别是发达国家投入更多的人力、物力到这项研究,取得了不少重要的研究成果。其中代表性的成果是70年代末MIT的Marr提出的视觉计算理论,这个理论成为计算机视觉领域其后十多年的主导思想。
20世纪80年代末期,人们开始将其应用于地理信息系统,研究海图的自动读入、自动生成方法。数字图像处理技术的应用领域不断拓展。
数字图像处理技术的大发展是从20世纪90年代初开始的。自1986年以来,小波理论与变换方法迅速发展,它克服了傅里叶分析不能用于局部分析等方面的不足之处,被认为是调和分析半个世纪以来工作之结晶。Mallat在1988年有效地将小波分析应用于图像分解和重构。小波分析被认为是信号与图像分析在数学方法上的重大突破。随后数字图像处理技术迅猛发展,到目前为止,图像处理在图像通讯、办公自动化系统、地理信息系统、医疗设备、卫星照片传输及分析和工业自动化领域的应用越来越多。
进入21世纪,随着计算机技术的迅猛发展和相关理论的不断完善,数字图像处理技术在许多应用领域受到广泛重视并取得了重大的开拓性成就。属于这些领域的有航空航天、生物医学工程、工业检测、机器人视觉、公安司法、军事制导、文化艺术等。该技术成为一门引人注目、前景远大的新型学科。
2 医学图像处理概述
近年来,随着计算机及其相关技术的迅速发展,图像处理技术日益成熟,使得该技术深入到医学领域的方方面面,开创了数字医疗的新时代。
借助图像处理技术的有力手段,医学图像的质量和显示方法可以得到极大的改善,从而使得诊断水平可以借助于图像处理与分析手段来得到极大的改善,这不仅可以基于现有的医学图像设备来极大地提高医学临床诊断水平,而且能为医学培训、医学研究与教学、计算机辅助临床外科手术等提供电子实现手段,为医学的研究与发展提供坚实的基础,具有无可估量的价值。
2.1 什么是医学图像处理
医学图像处理就是利用计算机系统对生物医学图像进行的具有临床医学意义的处理和分析。
医学图像处理是一个很复杂的过程。医学图像作为一种信息源,也和其它有关病人的信息一样,是医生做出判断时的依据。医生在判读医学图像时,要把图像与他的解剖学、生理学和病理学等知识作对照,还要根据经验来捕捉图像中的有重要意义的细节和特征。所以要从一幅或几幅医学图像中判断出是否有异常,或属于什么疾病,是一种高级的脑力劳动。任意拿一张有异常的CT图像、X线照片或超声图像来看,如果不是训练有素的医生,是难以发现图像上的异常的。所以对医学图像进行处理显得尤为重要。
2.2 医学图像处理及研究内容
2.2.1 超声图像
超声是超过正常人耳能听到的声波,频率在20 000赫兹(Hertz,Hz)以上。超声检查是利用超声的物理特性和人体器官组织声学性质上的差异,以波形、曲线或图像的形式显示和记录,借以进行疾病诊断的检查方法。40年代初就已探索利用超声检查人体,50年代已研究、使用超声使器官构成超声层面图像,70年代初又发展了实时超声技术,可观察心脏及胎儿活动。超声诊断由于设备不似CT或MRI设备那样昂贵,可获得器官的任意断面图像,还可观察运动器官的活动情况,成像快,诊断及时,无痛苦与危险,属于非损伤性检查,因此,在临床上应用已普及,是医学影像学中的重要组成部分。不足之处在于图像的对比分辨力和空间分辨力不如CT和MRI高。
超声在介质中以直线传播,有良好的指向性。这是可以用超声对人体器官进行探测的基础。当超声传经两种声阻抗不同相邻介质的界面时其声阻抗差大于0.1%,而界面又明显大于波长,即大界面时,则发生反射,一部分声能在界面后方的相邻介质中产生折射,超声继续传播,遇到另一个界面再产生反射,直至声能耗竭。反射回来的超声为回声。声阻抗差越大,则反射越强,如果界面比波长小,即小界面时,则发生散射。超声在介质中传播还发生衰减,即振幅与强度减小。衰减与介质的衰减系数成正比,与距离平方成反比,还与介质的吸收及散射有关。
人体结构对超声而言是一个复杂的介质,各种器官与组织,包括病理组织有它特定的声阻抗和衰减特性。因而构成声阻抗上的差别和衰减上的差异。超声射入体内,由表面到深部,将经过不同声阻抗和不同衰减特性的器官与组织,从而产生不同的反射与衰减。这种不同的反射与衰减是构成超声图像的基础。将接收到的回声,根据回声强弱,用明暗不同的光点依次显示在影屏上,则可显出人体的断面超声图像,称这为声像图。人体器官表面有被膜包绕,被膜同其下方组织的声阻抗差大,形成良好界面反射,声像图上出现完整而清晰的周边回声,从而显出器官的轮廓。根据周边回声能判断器官的形状与大小。
图2.1 急性阑尾超声影像
2.2.2 X射线图像
X线图像是当前临床应用最广泛的一种医学图像,如何从X线图像获得更多的信息,是提高诊断技术水平的一个重要方向。
X线图像建立在当X线透过人体时,各种脏器与组织对X线的不同吸收程度的基础上,因而在接收端将得到不同的射线强度。接收端射线强度的变化,如被记录在底片上就变成灰度的变化。
基于这个原理,所得的X线图像是把三维结构的人体在二维空间中投影成像的技术,是人体内各层结构重叠后的图像。因此,处理的基本目的是要在图片上把特定的脏器轮廓从周围的结构中分离出来。几十年来,X线技术的发展可以说大都是为了提高X线图像的分辨能力。例如,各种X线照片的处理技术(包括增强,分割,识别等),X线断层摄影技术,X线CT技术,X线减影技术等。此外,也要尽可能减少病人和医生所受到的X线辐射剂量。
图2.2 骨纤维异常增殖症X光片
2.2.3 磁共振成像
核磁共振(MRI)又叫核磁共振成像技术。是继CT后医学影像学的又一重大进步。自80年代应用以来,它以极快的速度得到发展。其基本原理:是将人体置于特殊的磁场中,用无线电射频脉冲激发人体内氢原子核,引起氢原子核共振,并吸收能量。在停止射频脉冲后,氢原子核按特定频率发出射电信号,并将吸收的能量释放出来,被体外的接受器收录,经电子计算机处理获得图像,这就叫做核磁共振成像。
核磁共振是一种物理现象,作为一种分析手段广泛应用于物理、化学生物等领域,到1973年才将它用于医学临床检测。为了避免与核医学中放射成像混淆,把它称为核磁共振成像术(MR)。
MR是一种生物磁自旋成像技术,它是利用原子核自旋运动的特点,在外加磁场内,经射频脉冲激后产生信号,用探测器检测并输入计算机,经过处理转换在屏幕上显示图像。
MR提供的信息量不但大于医学影像学中的其他许多成像术,而且不同于已有的成像术,因此,它对疾病的诊断具有很大的潜在优越性。它可以直接作出横断面、矢状面、冠状面和各种斜面的体层图像,不会产生CT检测中的伪影;不需注射造影剂;无电离辐射,对机体没有不良影响。MR对检测脑内血肿、脑外血肿、脑肿瘤、颅内动脉瘤、动静脉血管畸形、脑缺血、椎管内肿瘤、脊髓空洞症和脊髓积水等颅脑常见疾病非常有效,同时对腰椎椎间盘后突、原发性肝癌等疾病的诊断也很有效。
图2.3 颅脑病变MR影像
MR也存在不足之处。它的空间分辨率不及CT,带有心脏起搏器的患者或有某些金属异物的部位不能作MR的检查,另外价格比较昂贵。
2.2.4 核医学成像
将放射性同位素(RI)作为示踪物质,直接注入人体,并在体外用测定器对它的分布、聚集、变化等进行测定记录,所得的图像即为核医学图像。
核医学图像与其它用作诊断的医学图像相比,是有其特长的。首先,由于可以选择对特定脏器的生理作用有关联的放射性药物,因而可对不同的脏器做图像观察和分析研究,即有做选择性造影的能力;其次,由于放射性药物可以有不同的寿命,因而有可能对放射性物质在体内的活动进行长时间的观察,从而有可能测定体内各脏器的摄取、排泄、循环以及代谢等机能,即具有动态机能测定的能力,这些重大特长都是其它医学图像所不具有的。由于核医学图像具有的“选择性造影能力”和“动态机能测定能力”,所以虽然它有一系列的缺点,但在临床诊断中还是得到了广泛的应用。
核医学图像存在的弱点与检测方法有关。首先,由于被检查人员和操作人员所受辐射量的原因,做检查时用的放射性同位素剂量是不大的,而γ线的放射是同位素衰变的一种随机现象,所以核医学图像中含有较大的时间统计误差。为了使两个区域检测到的γ线数的变化不被统计涨落所淹没,同时又不增加同位素剂量,只好扩大每个区域的面积。这就导致核医学图像空间分辨率的降低。
正是由于核医学图像的空间分辨率低、信噪比低以及对比度低这些特点,使得在利用核医学图像做诊断时,医生的主观介入较多,往往造成解释上的差异。因此,引入图像处理技术和识别技术,对核医学图像来讲尤为重要。
图2.4显示了一种叫做“正电子放射断层”(PET)的核成像。
图2.4 PET图像
2.3医学图像处理技术新进展
1.医学图像处理技术
医学图像处理技术包括很多方面,图像分割、图像配准和融合以及伪彩色处理技术和纹理分析在医学领域的应用和发展越来越广泛。
图像分割就是把图像中具有特殊涵义的不同区域分开来,这些区域使互不相交的每一个区域都满足特定区域的一致性。它是图像处理与图像分析中的一个经典问题。图像分割技术发展至今,已在灰度阈值分割法、边缘检测分割法、区域跟踪分割法的基础上结合特定的理论工具有了更进一步的发展。比如基于三维可视化系统结合Fast Marching算法和Watershed变换的医学图像分割方法,能得到快速、准确的分割结果。
图像分割同时又是进行三维重建的基础,分割的效果直接影响到三维重建后模型的精确性,分割可以帮助医生将感兴趣的物体(病变组织等)提取出来,帮助医生能够对病变组织进行定性及定量的分析,从而提高医生诊断的准确性和科学性。
医学图像配准是通过寻找某种空间变换,使两幅图像的对应点达到空间位置和解剖结构上的完全一致。要求配准的结构能使两幅图像上所有的解剖点,或至少是所有具有诊断意义以及手术区域的点都达到匹配。目前医学图像配准方法有基于外部特征的图像配准(有框架)和基于图像内部特征的图像配准(无框架)两种方法。后者由于其无创性和可回溯性,已成为配准算法的研究中心。基于互信息的弹性形变模型也逐渐成为研究热点。
图像配准是图像融合的前提,是公认难度较大的图像处理技术,也是决定医学图像融合技术发展的关键技术。近年来国外在图像配准方面研究很多,如几何矩的配准、利用图像的相关系数、样条插值等多项式变换对图像进行配准。国内研究人员也提出了一些相应的算法:一致图像配准方法、金字塔式多层次图像配准方法、基于互信息的方法。在努力提高配准精度的同时,目前提出的多种方法都力求整个过程自动化,其结果导致实现算法的过程复杂而耗费时间。
不同的医学图像提供了相关脏器的不同信息,图像融合的潜力在于综合处理应用这些成像设备所得信息以获得新的有助于临床诊断的信息。利用可视化软件,对多种模态的图像进行图像融合,可以准确地确定病变体的空间位置、大小、几何形状及它与周围生物组织之间的空间关系,从而及时高效地诊断疾病,也可以用在手术计划的制定、病理变化的跟踪、治疗效果的评价等方面。在放疗中,利用MR图像勾勒画出肿瘤的轮廓线,也就是描述肿瘤的大小;利用CT图像计算出放射剂量的大小以及剂量的分布,以便修正治疗方案。在制定手术方案时,对病变与周围组织关系的了解是手术成功与否的关键,所以CT与MR图像的融合为外科手术提供有利的佐证,甚至为进一步研究肿瘤的生长发育过程及早期诊断提供新的契机。在CT成像中,由于骨组织对X线有较大的吸收系数,因此对骨组织很敏感;而在MR成像中,骨组织含有较低的质子密度,所以MR对骨组织和钙化点信号较弱,融合后的图像对病变的定性、定位有很大的帮助。由于不同医学成像设备的成像机制不同,其图像质量、空间与时间特性有很大差别。因此,实现医学图像的融合、图像数据转换、图像数据相关、图像数据库和数据理解都是亟待解决的关键技术。
对一幅黑白图像,人眼一般只能辨别出4到5比特的灰度级别,而人眼能辨别出上千种不同的颜色。针对这一特点,人们往往将黑白图像经过处理变为彩色图像,充分发挥人眼对彩色的视觉能力,从而使观察者能从图像中取得更多的信息,这就是伪彩色图像处理技术。经过伪彩色处理技术,即密度分割技术,提高了对图像特征的识别。通过临床研究对X线、CT、MRI、B超和电镜等图片均进行了伪彩色技术的尝试,取得了良好的效果,部分图片经过处理后可以显现隐性病灶。
纹理是人类视觉的一个重要组成部分,迄今为止还难以适当地为纹理建模。为此有关专家进行了大量的探索研究,但未能获得有关纹理的分析、分类、分割及其综合的有效解释。有研究针对肝脏疾病难以根除、危害面广的问题,采用灰度梯度共生矩阵的方法,分别提取纤维化肝组织和正常肝组织的CT图像的纹理特征,提出了基于友度梯度共生矩阵的小梯度优势、灰度均方差、灰度嫡等参数作为图像的纹理特征量。通过选取的纹理参数,可以看到正常组和异常组之间存在显著性差异,为纤维化CT图像临床诊断提供了依据。
2.三维医学图像的可视化
三维医学图像的可视化通常是利用人类的视觉特性,通过计算机对二维数字断层图像序列形成的三维体数据进行处理,使其变换为具有直观立体效果的图像来展示人体组织的三维形态。三维医学图像可视化技术通常分为面绘制和体绘制两种方法。
医学数据的可视化,已成为数据可视化领域中最为活跃的研究领域之一。实现三维数据可视化的方法很多,空间域方法的典型算法包括:射线投射法、足迹法、剪切一曲变法(目前被认为是一种速度最快的体绘制算法)等;变换域方法的典型算法有频域体绘制法和基于小波的体绘制法,其中小波的体绘制技术显现出较好的前景。
随着互联网技术不断发展,跨越空间限制的远程虚拟现实技术已经逐步成为可能。基于虚拟现实技术利用美国国家医学图书馆VHP(Visible Human Project)完整数据重建可视人体,综合VTK, VRML和OperFGL等可视化平台的优势,采用三维互动、空间电磁定位、立体视觉等虚拟现实技术,实现了全数字可拆装人体骨骼的本地和远程互动学习。三维虚拟现实让邀游人体世界成为可能,可以呈现一个物理上并不存在但又实实在在看得见、摸得着的真实人体,使用者可以无数次地解剖这个虚拟人以了解人体的结构。
在临床方面,提出了一种用AVS/Express开发的基于PC的Le Fort手术模型系统原型。利用AVS用xpress大量预制的可视化编程对象模块,快速构建系统的结构框架和功能模块,生成的原型能对以DICOM(Digital Imaging and Communications in Medicine)格式存储的颅颌面CT序列断层图像进行预处理,并进行三维重建,在交互式操作环境中,显示颅颌面各种组织的解剖结构,进行相应的三维测量,模拟Le Fort I手术的截骨头,对截骨段实行任意的平移颌旋转。在体视化方面一直致力于提高重建速度(实时显示利于交互操作),使重建效果理想,减少冗余信息及存储空间。
3.针对PACS的图像压缩
图像存档及通信系统(picture archiving and communication system,PACS)是近年来国内外新兴的医学影像信息技术,是专门为医学图像管理而设计的,包括图像获取、处理、存储、显示或打印的软硬件系统,是医学影像、数字化图像技术、计算机技术和网络通信技术相结合的产物。显然,计算机网络是PACS的重要组成部分,它负责提供底层图像传输服务,是PACS的软硬件基础,正是通过各个层次的网络才将PACS中的图像获取、存储显示以及医疗数据的管理等单元连为一体,使之形成一个统一、高性能的系统. PACS需要解决数据传输和图像存储的问题,如何利用有限的存储空间存储更多的图像,医学图像压缩是关键的技术之一,也是近年来图像处理技术中的一个重点研究的问题。
医学图像的压缩无疑是减低应用系统成本,提高网络传输效率,减少存储空间的一个重要途径。DICOM作为医学图像与通信的重要标准,加入了对图像压缩算法的支持。目前DICOM正在研究对最新的压缩标准JPEG2000支持的可能性。随着新一代静态图像压缩标准JPEG2000的发展,小波理论在这个领域成为研究的热点。
医学图像是医学诊断和疾病治疗的重要根据,在临床上具有非常重要的应用价值。确保医学图像压缩后的高保真度是医学图像压缩首要考虑的因素,现在医学图像上常常采用无损压缩,因为它能够精确地还原原图像。但是无损图像压缩的压缩比很低,一般为1∶2~4,而有损图像压缩的压缩比可以高达1∶50,甚至更高。所以将这两种压缩方法在保证使用要求的基础上结合起来,在获取高的压缩质量的前提下提高压缩比,这也是目前医学图像研究领域的一个热点。
3 Java语言的特点
3.1 面向对象编程
Java的核心是面向对象编程。事实上,所有的Java程序都是面向对象的,你别无选择。这一点与C++不同,因为在那里你可以选择是否面向对象编程。面向对象编程与Java密不可分,因此,在你编写哪怕是最简单的Java程序以前,也必须理解它的基本原则。
3.1.1 抽象
面向对象编程的一个实质性的要素是抽象。人们通过抽象(abstraction)处理复杂性。例如,人们不会把一辆汽车想象成由几万个互相独立的部分所组成的一套装置,而是把汽车想成一个具有自己独特行为的对象。这种抽象使人们可以很容易地将一辆汽车开到杂货店,而不会因组成汽车各部分零件过于复杂而不知所措。他们可以忽略引擎、传动及刹车系统的工作细节,将汽车作为一个整体来加以利用。
使用层级分类是管理抽象的一个有效方法。它允许你根据物理意义将复杂的系统分解为更多更易处理的小块。从外表看,汽车是一个独立的对象。一旦到了内部,你会看到汽车由若干子系统组成:驾驶系统,制动系统,音响系统,安全带,供暖,便携电话,等等。再进一步细分,这些子系统由更多的专用元件组成。例如,音响系统由一台收音机、一个CD播放器、或许还有一台磁带放音机组成。从这里得到的重要启发是,你通过层级抽象对复杂的汽车(或任何另外复杂的系统)进行管理。
复杂系统的分层抽象也能被用于计算机程序设计。传统的面向过程程序的数据经过抽象可用若干个组成对象表示,程序中的过程步骤可看成是在这些对象之间进行消息收集。这样,每一个对象都有它自己的独特行为特征。你可以把这些对象当作具体的实体,让它们对告诉它们做什么事的消息做出反应。这是面向对象编程的本质。
面向对象的概念是Java的核心,对程序员来讲,重要的是要理解这些概念怎么转化为程序。你将会发现,在任何主要的软件工程项目中,软件都不可避免地要经历概念提出、成长、衰老这样一个生命周期,而面向对象的程序设计,可以使软件在生命周期的每一个阶段都处变不惊,有足够的应变能力。例如,一旦你定义好了对象和指向这些对象的简明的、可靠的接口,你就能很从容很自信地解除或更替旧系统的某些组成部分。
3.1.2 面向对象编程的3个原则
所有面向对象的编程语言都提供帮助你实现面向对象模型的机制,这些机制是封装,继承及多态性。当然,Java也不例外。
封装:封装(Encapsulation)是将代码及其处理的数据绑定在一起的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。理解封装性的一个方法就是把它想成一个黑匣子,它可以阻止在外部定义的代码随意访问内部代码和数据。对黑匣子内代码和数据的访问通过一个适当定义的接口严格控制。封装代码的好处是每个人都知道怎么访问它,但却不必考虑它的内部实现细节,也不必害怕使用不当会带来负面影响。
Java封装的基本单元是类。一个类(class)定义了将被一个对象集共享的结构和行为(数据和代码)。一个给定类的每个对象都包含这个类定义的行为和结构,好像它们是从同一个类的模子中铸造出来似的。因为这个原因,对象有时被看作是类的实例(instances of a class)。所以,类是一种逻辑结构,而对象是真正存在的物理实体。
当创建一个类时,你要指定组成那个类的代码和数据。从总体上讲,这些元素都被称为该类的成员(members)。具体地说,类定义的数据称为成员变量(member variables)或实例变量(instance variables)。操作数据的代码称为成员方法(member methods)或简称方法(methods)。如果你对C/C++熟悉,可以这样理解:Java程序员所称的方法,就是C/C++程序员所称的函数(function)。在完全用Java编写的程序中,方法定义如何使用成员变量。这意味着一个类的行为和接口是通过方法来定义的,类这些方法对它的实例数据进行操作。
既然类的目的是封装复杂性,在类的内部就应该有隐藏实现复杂性机制。类中的每个方法或变量都可以被标记为私有(private)或公共(public)。类的公共接口代表类的外部用户需要知道或可以知道的每件事情;私有方法和数据仅能被一个类的成员代码所访问,其他任何不是类的成员的代码都不能访问私有的方法或变量。既然类的私有成员仅能被程序中的其他部分通过该类的公共方法访问,那么你就能保证不希望发生的事情就一定不会发生。当然,公共接口应该小心仔细设计,不要过多暴露类的内部内容。
继承:继承(Inheritance)是一个对象获得另一个对象的属性的过程。继承很重要,因为它支持了按层分类的概念。大多数知识都可以按层级(即从上到下)分类管理。使用了继承,一个对象就只需定义使它在所属类中独一无二的属性即可,因为它可以从它的父类那儿继承所有的通用属性。所以,可以这样说,正是继承机制使一个对象成为一个更具通用类的一个特定实例成为可能。
继承性与封装性相互作用。如果一个给定的类封装了一些属性,那么它的任何子类将具有同样的属性,而且还添加了子类自己特有的属性。这是面向对象的程序在复杂性上呈线性而非几何性增长的一个关键概念。新的子类继承它的所有祖先的所有属性。它不与系统中其余的多数代码产生无法预料的相互作用。
多态性:多态性(polymorphism ,来自于希腊语,表示“多种形态”)是允许一个接口被多个同类动作使用的特性,具体使用哪个动作与应用场合有关,下面我们以一个后进先出型堆栈为例进行说明。假设你有一个程序,需要3种不同类型的堆栈。一个堆栈用于整数值,一个用于浮点数值,一个用于字符。尽管堆栈中存储的数据类型不同,但实现每个栈的算法是一样的。如果用一种非面向对象的语言,你就要创建3个不同的堆栈程序,每个程序一个名字。但是,如果使用Java,由于它具有多态性,你就可以创建一个通用的堆栈程序集,它们共享相同的名称。
多态性的概念经常被说成是“一个接口,多种方法”。这意味着可以为一组相关的动作设计一个通用的接口。多态性允许同一个接口被同一类的多个动作使用,这样就降低了程序的复杂性。选择应用于每一种情形的特定的动作(specific action)(即方法)是编译器的任务,程序员无需手工进行选择。你只需记住并且使用通用接口即可。
如果用得当,在由多态性、封装性和继承性共同组成的编程环境中可以写出比面向过程模型环境更健壮、扩展性更好的程序。精心设计的类层级结构是重用你花时间和努力改进并测试过的程序的基础,封装可以使你在不破坏依赖于类公共接口的代码基础上对程序进行升级迁移,多态性则有助于你编写清楚、易懂、易读、易修改的程序。
除了面向对象特性外,Java还具有其它的特点。
3.2 Java的特性
作为一种程序语言,Java拥有许多重要的特性:简单的、面向对象的、网络的、解释的、健壮的、安全的、可移植的、高性能的、多线程以及动态性。
前面已对面向对象特性做了具体的说明,下面针对其它的特性加以说明。
1.简单性:Java语言通过提供最基本的方法来完成指定的任务 ,只需理解一些基本的概念 ,就可以用它编写出适合于各种情况的应用程序。 Java略去了运算符重载、多重继承等模糊的概念,并且通过实现自动垃圾收集大大简化了程序设计者的内存管理工作。另外,Java也适合于在小型机上运行,它的基本解释器及类的支持只有 40KB左右,加上标准类库和线程的支持也只有215KB左右。库和线程的支持也只有 215KB左右。
2.网络性:Java本身等于就是通过学习网络而产生的,它的许多功能与应用都是与网络相关,从最初的确良Applet、简化的Socket、交互式的JSP/Servlet网络程序到今日热门的Web Serivice等,都注定了Java在网络相关的领域占有一席之地。事实上,Java应用最多的领域也正是网络服务这一块。
3.解释执行:Java解释器直接对 Java字节码进行解释执行。字节码本身携带了许多编译时信息,使得连接过程更加简单。
4.健壮性:Java将C/C++中一些功能强大但不容易掌握的功能去除了。以指针功能为例,即使是有经验的开发人员在使用指针功能时也得小心翼翼,避免编写出使程序崩溃的错误,诸如此类的功能在Java中被去除,为的是让Java在使用时更为简单,编写出来的程序更为健壮。
5.安全性:用于网络、分布环境下的 Java必须要防止病毒的入侵。 Java不支持指针, 一切对内存的访问都必须通过对象的实例变量来实现 ,这样就防止程序员使用“特洛伊”木马等欺骗手段访问对象的私有成员,同时也避免了指针操作中容易产生的错误。
6.可移植性:又可称为独立于平台性。是指无需修改程序便能够运行在不同的计算机环境中。Java程序被编译成一种名为字节码的文件,字节码可被任何带有Java解释器的操作系统、软件或设备运行。
7.高性能:一般情况下,可移植性,稳定性和安全性几乎总是以牺牲性能为代价的,解释型语言的执行效率一般也要低于直接执行源码的速度。但Java所采用的措施却很好的弥补了这些性能差距。Java字节码格式的设计充分考虑了性能的因素,其字节码的格式非常简单,这使得经由Java解释器解释执行后可产生高效的机器码。Java编译器生成的字节码和机器码的执行效率相差无几。据统计,Java字节码的执行效率非常的接近于由C和C++生成的机器码的执行效率。
8.多线程:多线程机制使应用程序能够并行执行
9.动态性:Java的设计使它适合于一个不断发展的环境。在类库中可以自由地加入新的方法和实例变量而不会影响用户程序的执行。并且 Java通过接口来支持多重继承
3.3 Java语言的前景
Java语言有着广泛的应用前景,大体上可以从以下几个方面来考虑其应用:
1.所有面向对象的应用开发,包括面向对象的事件描述、处理、综合等;
2.计算过程的可视化、可操作化的软件的开发;
3.动态画面的设计,包括图形图像的调用;
4.交互操作的设计(选择交互、定向交互、控制流程等);
5. Internet的系统管理功能模块的设计,包括Web页面的动态设计、管理和交互操作设计等;
6.Intranet(企业内部网)上的软件开发(直接面向企业内部用户的软件);
7.与各类数据库连接查询的SQL语句实现;
8.进行手机通讯和其他的一些嵌入式的开发(比如手机和网络游戏);
9.其它应用类型的程序。
4 Java语言实现图像处理
4.1 图像增强技术
数字图像的增强是图像处理中的一个重要研究内容之一,是图像处理的一项基本技术。图像增强是指按特定的需要突出一幅图像的某些信息,同时,削弱或除去某些不需要的信息的处理方法。
图像增强在人眼对图像的识别中很重要。人眼有这样一视觉特性:由人眼的视觉和人的心理特性可知,变化幅度较大,细节丰富的区域容易引起人眼的注意,而变化平坦的区域则不容易注意。在人们对视觉的研究中,进行过如下实验,将两幅图同时放在测试者的视野中,其中一幅有黑色线条,另一幅全部都为白色,用仪器分别记录下眼睛注视两幅图的时间,结果表明了人眼有70%的时间在注视带线条的那一幅,这说明变化剧烈的图像更吸引人的注意力,对灰度图像而言,人眼会将注意力集中在灰度值变化大的区域。根据人眼的这一视觉特性,图像处理中对灰度图像的增强就是为了解决这一视觉上的障碍。
图像增强的方法分为两大类:空间域方法和频率域方法。
空间域增强是指增强构成图像的像素。空间域方法是直接对这些像素操作的过程。空间域处理可由下式定义:
(4.1)
其中是增强处理前的图像函数,是增强处理后的图像函数,是对的一种操作,其定义在的邻域。式(4.1)可用图4.1表示。
图4.1 空间域方法示意图
频率域方法是在图像的某种变换域内对图像的变换值进行运算,如表示增强处理前的图像函数,表示空间运算函数,增强处理后的图像函数是由和的卷积的,即
(4.2)
根据卷积理论,在频域中有下面的变换关系
(4.3)
这里、和分别表示、和的傅立叶变换,称为传递函数。
在实际应用中,可根据需要先对图像函数进行傅立叶变换,并选定传递函数,然后由式(4.3)计算出,最后通过傅立叶反变换得出增强处理后的图像函数,即
(4.4)
4.1.1 灰度变换
如果一幅图像灰度的对比度差,图像的质量就不好。为了改善图像灰度的对比度,可以对图像中样点的灰度进行刻度尺方面的改变。假设和分别表示原始图像及增强处理后图像像素的灰度。这样使原始图像的像素灰度转换成增强后图像对应像素的灰度转换关系的一般表达式为
(4.5)
线性灰度变换的一般表达式
(4.6)
其中:a为图像的对比度,如果a>1,对比度增强,如果a<1,对比度减弱。
b为图像的亮度,如果b>0,亮度增强,如果b<0,亮度降低。
下面来看一下线性灰度变换的Java代码实现,如下只列出如何实现算法的代码。
;
green=(int)(a * green + b);
blue=(int)(a * blue + b);
if(red>=255)
{
red=255;
}
if(green>=255)
{
green=255;
}
if(blue>=255)
{
blue=255;
}
a是调整图像对比度的变量,b是调整图像亮度的变量。由于R、G、B分量空间范围是0~255,所以需设置一个限定条件,防止越界。
从图4.2中可以清晰的对比出经线性变换后的图像更容易观察出病灶,进而减少误诊率。
图4.2 左图为原始图像,右图为经线性灰度变换后图像
上述所讨论的线性变换为正比变换,下面简要说明一下反比变换,在某些情况下,反比变换得到的图像更容易观察出病变。
灰度级范围为[0,L-1]的图像反转变换的表达式为:
(4.7)
其中:和分别表示处理前后的像素值。
用这种方式倒转图像的强度产生图像反转的对等图像。这种处理尤其适用于增强嵌入于图像暗色区域的白色或灰色细节,特别是当黑色面积占主导地位时。一个例子示于图4.3,原始图像为一乳房的数字X照片,可看到有一小块病变。尽管事实上两幅图在视觉内容上都一样,但注意,在这种特殊情况下,分析乳房组织结构时反转图像要容易得多。
下面来看一下反比变换的Java代码实现,如下只列出了某一像素点反比变换代码。
int red=255-cm.getRed(pixels[i*iw+j]);
int green=255-cm.getGreen(pixels[i*iw+j]);
int blue=255-cm.getBlue(pixels[i*iw+j]);
图4.3 左图为原始数字乳房照片,右图为反变换得到的反转图像
4.1.2 伪彩色处理
伪彩色处理是用彩色来代替像素灰度值的一种技术。由于人眼对彩色的分辨率远高于对灰度差的分辨率,所以这种技术可用来识别灰度差较小的像素。这是一种视觉效果明显而技术又不是很复杂的图像增强技术。灰度图像中,如果相邻像素点的灰度相差不大,人眼将无法从图像中提取相应的信息,因为人眼分辨灰度的能力很差,一般只有几十个数量级,但是人眼对彩色信号的分辨率却很强,这样将黑白图像转换为彩色图像后,人眼可以提取更多的信息量。在转换过程中,对灰度图像中的每一个像素点,取得该点的灰度值并送入红、绿、蓝三个通道实施不同的变换,产生相应的红、绿、蓝的亮度值。
图4.4是一种简单的映射变换曲线,按照这张曲线图,可以轻松地将灰度图像的256个灰度级转换为一幅伪彩色图像。
图4.4 一种简单的映射变换曲线
由图4.4所示的伪彩色还原映射变换曲线图,得到如下映射函数,其中,、、表示伪彩色灰度值,表示原始灰度图像的灰度值。
(4.8)
(4.9)
(4.10)
公式(4.8)、(4.9)、(4.10)给出了一种通过映射变换曲线给灰度着色的方法,其Java代码实现如下:
;
int alpha=cm.getAlpha(pixels[i*iw+j]);
int red,green,blue ;
switch(grey/64)
{
case 0:red = 0;green = 4 * green;blue = 255;break;
case 1:red = 0;green = 255;blue = 511 - 4 * grey;break;
case 2:red = 4 * grey – 511;green = 255;blue = 0;break;
case 3:red = 255;green = 1023 - 4 * grey;blue = 0;break;
}
pixels[i*iw+j]=alpha<<24|red<<16|green<<8|blue;
grey为某像素点的灰度值,因为图像已经是灰度色,所以在这里只取蓝色分量作为灰度进行运算。
上面给出了一种通过映射变换曲线给灰度着色的方法,下面再给出一种通过色彩表映射的方法给灰度着色。对于任意一幅图像,可以先将灰度降到16级,然后根据灰度与相应的颜色对应关系,求出新的颜色。表4.1表示不同灰度级与相应的颜色对应关系。表中的序号表示0~15共16个灰度级,序号下方就是该灰度级将要映射的颜色。
表4.1 灰度级颜色对照表
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
黑 | 深蓝 | 深绿 | 深红 | 深灰 | 蓝紫 | 蓝 | 草绿 |
#000000 | #000055 | #005500 | #550000 | #3F3F3F | #550055 | #0000FF | #555500 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
绿 | 红 | 灰 | 青 | 黄 | 白 | 深蓝绿 | 紫 |
#00FF00 | #FF0000 | #808080 | #00FFFF | #FFFF00 | #FFFFFF | #005555 | #FF00FF |
色彩表映射的方法很简单:只需将原图像中所有灰度值 oldGray降为16级灰度,即对于任意一点,其新的灰度级为:
newGray=16×oldGray / 255 (4.11)
然后根据新的灰度级与表4.1进行对照,求出新的颜色。其Java代码实现如下:
int alpha=cm.getAlpha(pixels[i*iw+j]);
int grey = pixels[i*iw+j]&0xff;
int[] colorTable = {0x000000,0x000055,0x005500,0x550000,0x3F3F3F,
0x550055,0x0000FF,0x555500,0x00FF00,0xFF0000,0x808080,
0x00FFFF,0xFFFF00,0xFFFFFF,0x005555,0xFF00FF};
int newGrey = grey * 16 / 255;
pixels[i*iw+j]=alpha<<24|colorTable[newGrey];
其实从伪彩色的概念就可以理解,伪彩色不是真彩色,是一种人为着色。所以在处理这项技术时,方法是多种多样的。除了上面提到的16级灰度着色外,还可以采用更多级的灰度着色,如256级灰度着色。总之,不管怎样构造这张色彩表,它都是一种人为着色,其目的就是要突出目标,方便人查看。
图4.5 左图为原始图像,右图为经256级灰度着色后图像
4.1.3平滑化处理
图像的平滑处理技术即图像的去噪声处理。主要是为了去除实际成像过程中,因成像设备和环境所造成的图像失真,提取有用信息。图像平滑处理在消除或减弱图像噪声和假轮廓的同时,对图像细节也有一定的衰减作用。因此,图像平滑的直观效果是图像噪声和假轮廓得以去除或衰减,但同时图像将变得比处理前模糊了,模糊的程度要看对高频成份的衰减程度而定。
邻域平均法:邻域平均法是一种简单的在空间对图像进行平滑处理的方法,它易于实现,效果也较好。邻域平均法的基本思想是:由于噪声是图像上的一些样点的灰度造成突变,那么就可以以这样的样点为中心取一个邻域,用邻域内其他样点的灰度平均值来代替要处理的样点的灰度,其结果对亮度突变的点产生了“平滑”的效果。
假设图4.6是在某一图像中取一个邻域,其中e点认为是噪声点,那么就以e点为中心取了这样一个邻域,在处理后图像中e点的灰度值为
(4.12)
式中a、b、c、d、f、g、h、i分别为邻域内各个样点的灰度值
a | b | c |
d | e | f |
g | h | i |
图4.6 以e为中心的一个邻域
下面来看平滑化处理的核心代码:
ColorModel cm=ColorModel.getRGBdefault();
for(int i=1;i<ih-1;i++)
{
for(int j=1;j<iw-1;j++)
{
int alpha=cm.getAlpha(pixels[i*iw+j]);
int red=cm.getRed(pixels[i*iw+j]);
int green=cm.getGreen(pixels[i*iw+j]);
int blue=cm.getBlue(pixels[i*iw+j]);
int red1=cm.getRed(pixels[(i-1)*iw+j-1]);
int red2=cm.getRed(pixels[(i-1)*iw+j]);
int red3=cm.getRed(pixels[(i-1)*iw+j+1]);
int red4=cm.getRed(pixels[i*iw+j-1]);
int red6=cm.getRed(pixels[i*iw+j+1]);
int red7=cm.getRed(pixels[(i+1)*iw+j-1]);
int red8=cm.getRed(pixels[(i+1)*iw+j]);
int red9=cm.getRed(pixels[(i+1)*iw+j+1]);
int averageRed=(red1+red2+red3+red4+red6+red7+red8+red9)/8;
int green1=cm.getGreen(pixels[(i-1)*iw+j-1]);
int green2=cm.getGreen(pixels[(i-1)*iw+j]);
int green3=cm.getGreen(pixels[(i-1)*iw+j+1]);
int green4=cm.getGreen(pixels[i*iw+j-1]);
int green6=cm.getGreen(pixels[i*iw+j+1]);
int green7=cm.getGreen(pixels[(i+1)*iw+j-1]);
int green8=cm.getGreen(pixels[(i+1)*iw+j]);
int green9=cm.getGreen(pixels[(i+1)*iw+j+1]);
int averageGreen=(green1+green2+green3+green4+green6+green7+
green8+green9)/8;
int blue1=cm.getBlue(pixels[(i-1)*iw+j-1]);
int blue2=cm.getBlue(pixels[(i-1)*iw+j]);
int blue3=cm.getBlue(pixels[(i-1)*iw+j+1]);
int blue4=cm.getBlue(pixels[i*iw+j-1]);
int blue6=cm.getBlue(pixels[i*iw+j+1]);
int blue7=cm.getBlue(pixels[(i+1)*iw+j-1]);
int blue8=cm.getBlue(pixels[(i+1)*iw+j]);
int blue9=cm.getBlue(pixels[(i+1)*iw+j+1]);
int averageBlue=(blue1+blue2+blue3+blue4+blue6+blue7+blue8+blue9)/8;
pixels[i*iw+j]=alpha<<24|averageRed<<16|averageGreen<<8|averageBlue;
}
}
图4.7 左图为原始图像,右图为平滑处理后的图像
从图4.7中可以看出,虽然经过平滑处理后图像变得比处理前模糊了,但可以去除实际成像过程中,因成像设备和环境所造成的图像失真,即消除或减弱图像噪声和假轮廓,提取有用信息。
4.1.4其他图像增强技术
在前面几节,介绍了三种常用的医学图像增强技术,由于篇幅的原因,还有几种技术并不做详细的讨论,在此,做一简单的介绍,功能本人已经实现,代码见附录C。
中值滤波:低通滤波可以减弱图像中的噪声,但同时也使图像细节模糊了;而高通滤波增强了图像中的边缘细节,但同时也增强了噪声信号。中值滤波是介于两者,在一定条件下,中值滤波方法可以做到既减弱了噪声又保护了图像的细节,得到较好的处理效果。
中值滤波的基本思想是把数字序列中一点的值用该点的一个邻域中各点的中值来代替。假设有一组数值,,,……,,且这个数值按大小顺序排列成……,则这个数组的中值为
(4.13)
锐化处理:图像在传输和转换过程中,一般来讲,质量都要降低,除了噪声的因素之外,图像一般都要变得模糊一些。这主要因为图像的传输或转换系统的传递函数对高频成分的衰减作用,造成图像的细节轮廓不清晰。图像锐化的作用就是补偿图像的轮廓,使图像较清晰。
如果说对图像取平均的效果是使图像的细节变模糊,而微分与积分在数学上是相对立的,因此可以说微分处理将使图像的细节清晰。根据上述思想引入了微分尖锐化处理方法。梯度是一种微分运算,在微分尖锐化处理方法中最常用的就是梯度法,它的基本思想是:设图像函数为,它的梯度为,数字图像某样点处的梯度值和邻近样点间的灰度差成正比,因此在图像灰度变化平缓区域较小,在线条轮廓处等灰度变化快的区域,较大,这样就可以用梯度值来代替处的灰度值,经过这样变换后的图像在线条轮廓等灰度突变处更明显,从而达到锐化的目的。
4.2 图像分割技术
图像分割的直接结果是得到了区域内的像素集合,或位于区域边界上的像素集合,这两个集合是互补的。在图像分析应用中我们感兴趣的常常仅是图像中的某些区域,通常称之为目标。
图像分割是图像处理的另一个重要分支,它的输出不一定是一幅完整的图像,可能是图像的某些特性描述,其目的是从一幅图像中找出所需要的目标,或将图像划分成性质不同的若干区域。
医学图像分割就是一个根据区域间的相似或不同把图像分割成若干区域的过程。目前,主要以各种细胞、组织与器官的图像作为处理的对象。例如磁共振颅脑图像的分割,其目的就在于清晰地描绘出颅脑各个解剖结构的边界,如灰质、白质、脑脊液以及MR图像中的其它组织。
4.2.1阈值分割法
从一幅图像中找到目标最常用的方法是在该图像中确定区分目标与背景分界点,即阈值,例如一幅图像的分布范围[z1,zk],令为z1 与zk之间的任意值,选取为阈值可将图像变为
(4.14)
其中为图像在点像素的灰度值。由些可以获得一幅分割后的二值图像。(4.14)式也可以写成更一般的形式,即
(4.15)
上式表示,将图像像素各点的灰度值与门限值T比较.如果像素的灰度值大于或等于门限值,则设为一种灰度值,如果小于,则设为另一种灰度值。
也可以将阈值设为一个灰度范围[,],如果图像的灰度落在该范围内,则灰度全部变为1,其余像素的灰度级都变为零,即
(4.16)
在某些情况下,也可以设置灰度门限值,凡灰度级高于此门限值的像素,均保持原灰度级不变,其余像素的灰度级变为零,分割后的图像可表示为
(4.17)
假设某一图像中,凡是属于“目标”部分的像素点的灰度级都比较高,而属于“背景”部分像素点的灰度级都比较低,这样在“目标”与“背景”两部分间可能存在一个灰度的边界,这个边界就可以作为灰度的阈值,根据图像像素点的灰度即将图像空间划分成一些区域,在这些区域内部其特性是相同的,或者说是均匀的,两个相邻区域彼此特性是不相同的,其间存在着边界,这个边界称为灰度阈值,这种方法称为灰度阈值分割法。如果能通过某种科学的方法求出一个阈值,并认为灰度值大于的点属于目标点,而灰度值小于的点是背景点,那么就可以从一整幅图像中找到目标部分了。
Java代码实现图像二值化处理:
int grey=100;
String s=JOptionPane.showInputDialog(null,"输入二值化的
阈值(0-255):",100);
if(s!=null)
{
grey=Integer.parseInt(s);
}
if(grey>255)
{
grey=255;
}else if(grey<0)
{
grey=0;
}
ColorModel cm=ColorModel.getRGBdefault();
for(int i=0;i<iw*ih;i++)
{
int red,green,blue;
int alpha=cm.getAlpha(pixels[i]);
if(cm.getRed(pixels[i])>grey)
{
red = 255;
}else{ red=0;}
if(cm.getGreen(pixels[i])>grey)
{
green=255;
}else{green=0;}
if(cm.getBlue(pixels[i])>grey)
{
blue=255;
}else{blue=0;}
pixels[i]=alpha<<24|red<<16|green<<8|blue;
}
图4.8 左图为原始颅骨图像,右图为经二值化处理后的图像
从图4.8中可以看出,选择适当的阈值对图像进行二值化处理后可以清晰的观察出病灶位置及大小,实现了将病灶分割出来,方便了医生诊断。
4.2.2 边缘检测法
图像边缘对图像识别和计算机分析十分有用。边缘提取首先检查出图像局部性特性的不连续性,然后再将这些不连续的边缘像素连成完备的边界。边缘的特性是沿边缘走向的像素变化平缓,而垂直与边缘方向的像素变化剧烈。所以,从这个意义上讲,提取边缘的算法就是检查出符合边缘特性的边缘像素的数学算子。
常用的边缘检测算子有Roberts算子、Laplace算子、Sobel算子等。
1. Roberts算子
图像的梯度定义为
(4.18)
梯度的模为
(4.19)
通常把梯度的模就叫做图像的梯度。Roberts算子是用斜向上4个像素交叉差分来表示梯度的,即
(4.20)
上式也可以简化为
(4.21)
或
也可以表示成掩模的形式如图4.9所示
1 0 0 -1 | 0 1 -1 0 |
图4.9 Roberts算子
2.Laplace算子
可以利用对图像的各个像素的二阶导数和之和的方法寻找边界。即
(4.22)
对于数字图像,可以用差分近似微分,即可对图像的每个像素取方向和方向的二阶差分之和来近似上式,因此有
(4.23)
0 | 1 | 0 |
1 | -4 | 1 |
0 | 1 | 0 |
这就是Laplace算子,它是一个与边缘方向无关的边缘点检测算子。由于在实际检测中一般只关心边缘点的位置而不关心其周围的灰度差值,因此这种
与方向无关的边缘检测算子对检出边缘点是合适的。
Laplace算子相当于一个图4.10所示的滤波器。
图4.10Laplace算子
3.Sobel算子
Sobel算子是一种简单常用的算子,它是对数字图像的每个像素,考查其相邻点像素灰度的加权差,即
(4.24)
Sobel算子可以写成图4.11的掩膜形式。
1 | 0 | -1 | 1 | 2 | 1 | |
2 | 0 | -2 | 0 | 0 | 0 | |
1 | 0 | -1 | -1 | -2 | -1 |
图4.11 Sobel算子
Java语言实现Robert梯度算法:
ColorModel cm=ColorModel.getRGBdefault();
for(i=1;i<ih-1;i++)
{
for(int j=1;j<iw-1;j++)
{
int alpha=cm.getAlpha(pixels[i*iw+j]);
int red5=cm.getRed(pixels[i*iw+j]);
int red6=cm.getRed(pixels[i*iw+j+1]);
int red8=cm.getRed(pixels[(i+1)*iw+j]);
int red9=cm.getRed(pixels[(i+1)*iw+j+1]);
int robertRed=Math.max(Math.abs(red5-red9),Math.abs(red8-red6));
int green5=cm.getGreen(pixels[i*iw+j]);
int green6=cm.getGreen(pixels[i*iw+j+1]);
int green8=cm.getGreen(pixels[(i+1)*iw+j]);
int green9=cm.getGreen(pixels[(i+1)*iw+j+1]);
int robertGreen=Math.max(Math.abs(green5-green9),
Math.abs(green8-green6)); int blue5=cm.getBlue(pixels[i*iw+j]);
int blue6=cm.getBlue(pixels[i*iw+j+1]);
int blue8=cm.getBlue(pixels[(i+1)*iw+j]);
int blue9=cm.getBlue(pixels[(i+1)*iw+j+1]);
int robertBlue=Math.max(Math.abs(blue5-blue9),Math.abs(blue8-blue6));
;
}
}
图4.12 左图为原始骨骼图像,右图为经边缘检测后的图像
从图像中可以观察出,经边缘检测后腿部骨骼的边缘清晰的显示出来,从医学角度上看,医生可以根据骨骼的边缘信息进行直观的诊断,更加容易确诊。
4.3 图像复原技术
图像复原和前面讨论的图像增强的目的都是改善图像质量,但改善的方法和评价的标准则不同。图像增强是突出图像中感兴趣的特征,衰减那些不需要的信息,因此它不考虑图像退化的真实物理过程,增强后的图像也不一定去逼近原始图像;而图像复原则是针对图像的退化原因设法进行补偿,这就需要对图像的退化过程有一定的先验知识,利用图像退化的逆过程去恢复原始图像,使复原后的图像尽可能地接近原图像,因此,复原应有一个客观的质量标准,以指导实际复原接近最佳。
本人并没有太多涉及图像复原方向的内容,在这里只对这种技术作一些简单的理论介绍。
如图4.13所示,退化过程中可以被模型化为一个退化函数和一个加性噪声项,处理一幅输入图像产生一幅退化图像。给定和关于退化函数的一些知识以及外加噪声项,图像复原的目的是获得关于原始图像的近似估计。通常我们希望这一估计尽可能接近原始输入图像,并且和的信息知道得越多,所得到的就会越接近。
噪声
图4.13 图像退化/复原过程的模型
复原前,图4.13中的输出关系可表示为:
(4.25)
为了讨论方便,可将噪声假设为零,则。如果
(4.26)
则系统是一个线性系统。这里,和是比例常数,和是任意两幅输入图像。
若==1,式(4.26)变为:
(4.27)
这就是所谓的加性。这一特性简单地表明,如果为线性算子,那么,两个输入之和的响应等于两个响应之和。
如果,式(4.26)变为:
(4.28)
这称为均匀性。它表明任何与常数相乘的输入的响应等于该输入响应乘以相同的常数。即一个线性算子具有加性和均匀性。
对于任意,和,如果
(4.29)
则一个具有输入输出关系的系统称为位置不变系统(或空间不变系统)。这个定义说明图像中任一点的响应只取决于在该点的输入值,而与该点的位置无关。
如果将退化过程看成是线性空间不变的,就可以利用线性系统的理论来解决图像的复原问题,而且实际中大多数退化过程中是可以用线性空间不变系统近似的。但这种假设并不总是合理的,讨论非线性空间变化的退化模型可能更具有普遍的实际意义,也会更加准确,但同时由于问题的解算过于困难而难以实现。
4.4 本章小结
图像是信息可视化的重要手段。一幅医学图像以直观的形式给医生提供辅助诊断和治疗的信息。但是,从仪器出来的原始图像由于受到成像设备和获取条件等因素的影响,可能出现图像质量的退化,甚至伪迹;而高质量的图像有时也很难用肉眼直接得到有用的诊断信息。所以对医学图像进行处理显得特别的重要。要对医学图像进行处理,首要的任务就是对获取的图像进行增强和分割,即滤除噪声和干扰,突出感兴趣的区域或边缘,从面为进一步分析和处理奠定基础,从图像得到定量和更深刻的信息。
5 设计流程
5.1 主流程图
本系统的总体设计流程图如图5.1所示
图5.1 总体设计流程图
程序设计流程图大体介绍:
首先设计Java GUI即Java用户图形界面,对其中的按钮,菜单添加事件监听器,以便能够当用户触发事件做出相应的响应,然后添加了文件选择器以及连接数据库并实现了数据库查询、插入功能,使用户可以从本地磁盘或从数据库中查询图像。将图像显示在GUI后就可以通过相应的按钮对图像进行处理。
具体模块的实现将在以下几节中详细介绍。
5.2 图像处理界面
本设计的图形用户界面如图5.2所示。
图5.2 图像处理界面
在这个界面中,无论是按钮还是菜单选项,都添加了监听器用来监听是否有事件发生,并且都有一个相应的事件处理器。当用户单击其中任何一个都会触发相应的事件,然后将事件发送到事件处理器中进行处理。界面的左侧用于显示载入的图像,即原始图像,右侧用于显示处理后图像,以便对处理前后的图像进行对比。详细代码参见附录C。
5.3 图像的加载
图像加载的流程图如图5.3所示。
图5.3 图像加载流程图
本设计可以处理从本地磁盘或从数据库中调出的图像,但有一个共同点就是所采用的加载方式是一样的,都是利用MediaTracker类的对象跟踪图像的加载,看如下代码:
MediaTracker tracker = new MediaTracker(this);
Image im=Toolkit.getDefaultToolkit( ).getImage(filename);
tracker.addImage(im,0);
MediaTracker类是一个跟踪多种媒体对象状态的实用工具类。媒体对象可以包括音频剪辑和图像,但目前仅支持图像。要使用媒体跟踪器,需要创建一个MediaTracker实例,然后对每个要跟踪的图像调用其addImage方法。另外,还可以为每个图像分配一个惟一的标识符,此标识符可控制获取图像的优先级顺序。此处将标识符设置为0。Image是表示图形图像的所有类的超类。Toolkit.getDefaultToolkit( ).getImage(filename);返回一幅图像,类型为Image。该图像从指定文件filename中获取像素数据。同时也为调用Image类中的获取图像长和宽的方法创造了条件。接着看下面的代码:
int iw=im.getWidth(this);
int ih=im.getHeight(this);
int[] pixels=new int[iw*ih];
以上三段代码是对图像im分别获得其长和宽,然后创建数组,数组的长度为图像长和宽的乘积,即为图像中点的数量。
try{
;
pg.grabPixels( );
}catch (InterruptedException e) {
e.printStackTrace( );
}
PixelGrabber类实现可以附加在Image或ImageProducer对象上以获得该图像像素子集的ImageConsumer。上述代码首先创建一个PixelGrabber对象,以便从指定的图像im中将像素矩形部分(0,0,iw,ih)抓取到给定的数组pixels中。以默认的RGB ColorModel形式将像素存储到数组中。然后调用grabPixels()方法请求Image开始传递像素,并等待传递完相关矩形中的所有像素。如果成功抓取了像素,则返回true;在中止、有错误或超时的情况下返回false。所以将其放在try语句中,以捕获异常。
ImageProducer ip=new MemoryImageSource(iw,ih,pixels,0,iw);
Image tmp=createImage(ip);
repaint();
MemoryImageSource类是ImageProducer接口的一个实现,该接口使用一个数组为Image生成像素值。上面语句构造一个使用默认RGB ColorModel中的整数数组为Image对象生成数据的ImageProducer对象,然后createImage使用指定的图像生成器创建一幅图像。repaint( )方法会自动调用paint( ),将图像显示在组件上。(如图5.4所示)
public void paint(Graphics g)
{
if(flagLoad)
{
g.drawImage(tmp,9,171,this);
}
}
图5.4 加载图像
5.4 图像的处理
本设计中所实现的灰度变换、伪彩色处理、平滑处理、阈值分割及边缘检测所采用的方法是对图像中各像素的R、G、B三个分量做运算。其流程图如图5.5所示。
图5.5 灰度变换、伪彩色处理、平滑处理、阈值分割及边缘检测流程图
如果图像已加载,则首先创建一个ColorModel对象,此ColorModel抽象类封装了将像素值转换为颜色分量(例如,红色、绿色和蓝色)和alpha分量的方法。为了将图像呈现到屏幕、打字机或其他图像上,必须将像素值转换为颜色和alpha分量。看如下代码:
ColorModel cm=ColorModel.getRGBdefault();
for(i=0;i<ih;i++)
{
for(int j=0;j<iw;j++)
{
int alpha=cm.getAlpha(pixels[i*iw+j]);
int red=cm.getRed(pixels[i*iw+j]);
int green=cm.getGreen(pixels[i*iw+j]);
int blue=cm.getBlue(pixels[i*iw+j]);
}
}
上面的语句可得到每个像素点的R、G、B及alpha分量的值,然后通过对各点的R、G、
B做运算即可实现图像的处理。最后将运算后图像的颜色分量及alpha分量值存入像素数组pixels中,应用MemoryImageSource类中的方法产生图像。
例如:下面的代码是实现图像反转灰度变换模块的完整代码。其结果如图5.6所示。
public void jfanzhuan_ActionPerformed(ActionEvent e)
{
if(flagLoad)
{
ColorModel cm=ColorModel.getRGBdefault(); for(i=0;i<ih;i++)
{
for(int j=0;j<iw;j++)
{
int alpha=cm.getAlpha(pixels[i*iw+j]);
int red=255-cm.getRed(pixels[i*iw+j]);
int green=255-cm.getGreen(pixels[i*iw+j]);
int blue=255-cm.getBlue(pixels[i*iw+j]);
pixels[i*iw+j]=alpha<<24|red<<16|green<<8|blue;
}
}
ImageProducer ip=new MemoryImageSource(iw,ih,pixels,0,iw);
tmp=createImage(ip);
repaint();
}else{
JOptionPane.showMessageDialog(null,"请先打开一幅图片!",
"提示",JOptionPane.WARNING_MESSAGE);
}
}
图5.6 点击反转灰度变换后的GUI
5.5 数据库的建立
本设计实现了一个医学图像档案,即创建了一个数据库用于存放病人ID,姓名及其图像信息。可以通过病人的ID进行图像信息的查询,还可以将新的图像信息添加进此档案中。其设计流程图如图5.7所示。
图5.7 数据库设计流程图
本设计所使用的数据库为Access数据库,首先用Access创建了image.mdb,在其中创建了一个名为pic的表用于存放病人ID,姓名及其图像信息。
创建完数据库后就要对数据库进行连接,看如下代码:
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection("jdbc:odbc:image");
stmt = con.createStatement();
}
catch(Exception e){}
上述语句首先调用了Class类的forName方法,将返回一个sun.jdbc.odbc.JdbcOdbcDriver类的对象,称为加载JDBC-ODBC Bridge驱动器。然后通过调用DriverManager 类的getConnection方法,连接地址为jdbc:odbc:image的数据库,并且返回一个Connection类型的对象赋予变量con。这样便建立了与数据库image的连接。接着调用Connection类的createStatement方法,创建了一个Statement类的对象stmt,即创建了一个将SQL语句传递给数据库的Statement对象。
ResultSet rs = stmt.executeQuery("SELECT ID, 姓名,图片 FROM pic");
此句调用Statement对象的executeQuery方法执行SQL语句,将结果返回给一个ResultSet类型的变量rs,通过调用ResultSet类中的方法即可实现数据库的查询。
String s1=JOptionPane.showInputDialog(null,"请输入ID");
String s2 = JOptionPane.showInputDialog(null,"请输入姓名");
String strInc = "INSERT INTO pic(ID,姓名,图片) Values('"+s1+"','"+s2+"','"+filename+"')";
stmt.executeUpdate(strInc);
当执行插入操作时,程序首先弹出对话框要求用户输入ID及姓名,然后即可将GUI中的图像保存进数据库。详细代码参见附录C。
当用户退出本系统时,除了释放系统资源外还要关闭与数据库操作相关的链接,其代码如下:
rs.close(); //关闭记录集
stmt.close(); //关闭Statement对象
con.close(); //关闭数据库链接
6 开发工具
利用记事本和JDK开发Java程序虽然在理论上是完全可行的,但一般Java程序的开发都会借助一些工具加快开发速度。
JCreator是一个小巧灵活的Java开发工具,它可将Java的程序的编写、编译、运行和调试集成进自身的环境中直接进行开发,且无需进行环境变量的设定。我们可以直接在JCreator中编辑Java源文件,选择相应的菜单和点击对应的按钮就可以完成Java程序的编译、运行等工作,十分方便。由于JCreator集成了编辑源文件,编译,运行调试为一体,所以又被称为IDE(Integration Developer Environment,集成开发环境),其他的具有类似特点的开发工具也被称为IDE。
6.1 JCreator概述
1.JCreator的特点
JCreator是共享软件,用来开发基于Java的应用程序,安装后只有4M左右,且只需32M内存即可运行。
Java程序开发需要安装Java的开发工具包(JDK),但JCreator安装程序本身并不附带,所以需要先安装JDK,才能利用JCreator进行开发。
2.JCreator的工程(Project)和工作空间Workspace
JCreator利用工程(Project)管理相应的文件,一个工程由多个Java源文件和其他一些文件组成,JCreator中工程文件的扩展名为jcp。
JCreator的工作空间(Workspace)用来管理工程,一个工作空间中可以包含多个工程,JCreator中工作空间文件的扩展名为jcw。
JCreator规定,一个工程必须包含在一个工作空间中。所以,当我们创建一个工程时,JCreator会自动给我们创建一个工作空间已包含当前工程。JCreator在同一时刻只容许打开一个工作空间。
6.2 JCreator编辑界面的组成
JCreator的界面如图6.1所示:
图6.1 JCeator界面
1.文件视图
文件视图用来显示工程中的所有文件,并且可以显示当前的工程名称和工程所在的工作空间的名称。
一个工作空间中可以包含多个工程,但只能有一个活动工程。活动工程是指当前起作用的工程。双击工作空间中的一个工程名字将使得该工程成为活动工程,活动工程的名字显示为黑体,而非活动工程显示为普通字体。
文件视图图解
2.代码视图
代码视图用来编辑工程文件的源代码。在文件视图中双击某个文件名称,即可在代码视图中对该文件进行编辑JCreator提供了代码帮助的功能。即如果输入相应的方法或变量,代码视图可提供该方法或变量的动态提示。如果代码提示不出现,可能的原因为JDK及相关类库文件没有正确设置或书写的代码有错误。
3.类视图
类视图显示了当前显示在代码视图中Java源文件的类的层次和类中的方法,双击某一方法将直接在代码视图中定位到该方法的定义处。
4.输出视图
输出视图主要用来输出编译相关的信息。如果有错误信息出现,双击错误信息的第一行即可在源代码中定位该错误。
结 论
随着远程医疗技术的蓬勃发展,对医学图像处理提出的要求也越来越高。医学图像处理技术发展至今,各个学科的交叉渗透已是发展的必然趋势,其中还有很多亟待解决的问题。有效地提高医学图像处理技术的水平,与多学科理论的交叉融合、医务人员和理论技术人员之间的交流就显得越来越重要。多维、多参数以及多模式图像在临床诊断与治疗中将发挥更大的作用。
本设计主要是用Java语言实现对医学图像的简单处理,包括线性灰度变换、伪彩色处理、平滑处理等图像增强算法和阈值分割、边缘检测等图像分割算法。并将处理后的结果显示于Java GUI中。通过这次设计,使我对数字图像处理的几种算法理解的更加深刻,也掌握了当今流行的一门编程语言Java,对以后的工作和学习有很大的帮助。
由于时间有限,设计只做了本地处理,也就是数据库中的图像信息是保存在本地的。Java的优势实际上在于Web方面,如果在医院有一台服务器,服务器的数据库中保存着病人的信息,我们就可以通过网络访问这台服务器,从数据库中查询病人的图像信息或向数据库中添加病人的图像信息,方便管理病人的档案。
致 谢
经过半年的工作和学习,本次毕业设计已经接近尾声,作为一名本科生的毕业设计,由于经验的匮乏,难免有许多考虑不周全的地方,如果没有导师的督促指导,以及一起工作的同学们的支持,想要完成这个设计是难以想象的。
在这里首先要感谢张治老师在毕业设计期间给我技术上的支持,以及医学图像处理方面的资料。使我顺利的完成了毕业设计,同时对张老师认真负责的态度表示衷心的感谢。
其次还要感谢大学四年来所有的老师,是他们为我打下了电子信息专业知识的基础;同时还要感谢所有的同学们,正是因为有了你们的支持和鼓励。此次毕业设计才会顺利完成。
最后感谢我的母校——沈阳理工大学四年来对我的大力栽培。
参考文献
[1] 刘榴娣,刘明奇.《实用数字图像处理》.第一版.北京理工大学出版社.2003年
[2] 章梳晋.《图像处理和分析》.第一版.清华大学出版社.2006年
[3] 陈浩,李本富.《医学图像处理技术新进展》.第四军医大学学报.2004年,第5期
[4] 林信良.《Java JDK 5.0学习笔记》.清华大学出版社.2006年
[5] David Flanagan.《JAVA IN A NUTSHELL》.第三版.O’REILLY出版社.1999年
[6] 王宏.《数字图像处理—Java语言实现》.第一版.东北大学出版社.2005年
[7] Rafael C.Gonzalez,Richard E.Woods.《冈萨雷斯 数字图像处理》.阮秋琦,阮宇智.第二版.电子工业出版社.2005年