背景:

上篇博文为引子,介绍了一款神奇的开源PACS系统——Orthanc。本篇开始解读官方Cookbook中的相关内容,对于简单的浏览、访问和上传请阅读前篇博文。在常规的PACS系统中还未出现对于DCM图像的修改和匿名化操作,因此此次重点介绍Orthanc利用REST API实现对DCM医学图像的修改(modification)和匿名化(anonymization)。对于官方Cookbook中的实例进行示范和调试,通过Orthanc源码分析确保示例在本机良好运行。注意:官方Cookbook中的示例在Windows下会有错误,详情见博文。

Orthanc介绍:

取名为Orthanc源自于J.R.R. Tolkien’s(托尔金)的小说。Orthanc是艾辛格(Isengard)要塞中的黑塔,初建于第二世纪,用于储存收纳南方王国的真知晶石——palantíri,一种圆形且能够看见远方的石头,透过palantíri可以跟远方使用palantíri的人进行交流。Orthanc Server正是取palantíri的此层含义,设计出一种可在整个医院DICOM拓扑网络中便捷、透明以及可编程访问医学图像的系统(可参照wiki百科的介绍:http://en.wikipedia.org/wiki/Isengard)。

另外,Orthanc中同时包含了“RTH“,即Radiotherapy。其实Orthanc本身源自于法国de Liège大学中心医院(Centre Hospitalier Universitaire)对于放射治疗服务的研究。

Orthanc之Modification & Anonymization

Anonymization:

Orthanc从0.5.0版本之后引入了对DICOM资源的匿名化操作,可对患者(patients)、检查(studies)、序列(series)和图像(instances)多个级别进行匿名化处理。为了方便示范,此处以instances级别为例进行介绍:

1)按照上篇博文上传两幅测试图像到Orthanc Server,如下图所示:

2)利用curl命令行查看一下上述两个instances,获取ID号,结果如下:

curl http://localhost:8042/instances

此处获取的instance ID号为:c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c

3)按照Orthanc官方Cookbook的说明,进行匿名化操作

输入指令:curl http://localhost:8042/instances/c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c/anonymize -X POST -d '{}' > c:\orthanc-anonymize.dcm

但是并未获得如期结果,打开c盘发现orthanc-anonymization.dcm文件大小为0KB。开启curl的verbose模式,

curl –v http://localhost:8042/instances/c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c/anonymize -X POST -d '{}' > c:\orthanc-anonymize.dcm

查看输出信息如下:

发现Orthanc Server中HTTP 服务返回值为404

通过自己查看官方Cookbook给出的指令,除了对应instance的UID不同外,并未找到问题,暂且跳过,尝试一下Modification。

Modification:

1)上传DCM文件到Orthanc Server,同Anonymization中相同;

2)利用curl http://localhost:8042/instances获取指定instance的ID号;

3)参照官方Cookbook进行Modification处理

输入如下指令,此次为了方便,直接使用curl的verbose模式:

curl –v http://localhost:8042/instances/c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c/modify –X POST –d ‘{"Replace”:{"PatientName”:"hello”,"PatientID”:"world”}}' >c:\orthanc-modify.dcm

输出结果如下:

目前为止,参照Orthanc官方的Cookbook说明,给出的两个示例都在本机无法顺利完成。因此猜测官网中给出的代码有可能是Linux系统的,在Windows系统下应该做出适当的调整,但是该怎样调整呢?该调整哪一部分呢?请继续往下看……

调试Orthanc官方Cookbook示例:

0)Orthanc REST API资料查询:

在调试之前,我们先要搞清楚出现问题的大致原因,排除一些常见的错误,比如软件版本错误、指令拼写错误等等。上面介绍的Anonymization和Modification都是利用了Orthanc的REST API功能,那么Orthanc各版本对于REST API的支持程度如何呢?我们查看一下官方的说明,如下图所示:

从上图可以看出,Orthanc从0.5.0版本之后就支持多级别的修改和匿名化操作,如上一篇博文所述,我本机安装的是最新的0.8.5版本。因此可以确保软件版本无误,另外在上述示例仿真过程中我们也对比排查了指令拼写错误。

接下来使出我们的杀手锏吧:“启动C:\Orthanc-0.8.5\Orthanc.sln工程,进入调试模式,查看Orthanc的源码”。打开Orthanc.sln解决方案,右键Orthanc工程开启调试模式,在关于REST API的几个核心类中插入断点,初次尝试插入的断点如下:

1)Anonymization源码调试:

重新按照上一节中的步骤,首先利用Orthanc Explorer向调试模式下的Orthanc Server添加DICOM文件,此时直接按F5跳过调试,因为图像加载过程中我们并未遇到问题。(此步操作必须重新添加,因为调试模式下数据的存储目录是C:\Orthanc-0.8.5\OrthancStorage,与二进制安装包默认的C:\OrthancStorage不同,上一节中我们添加的图像在调试状态下是看不到的

输入指令查看ID:

curl http://localhost:8042/instances

开始输入上一节的Anonymization指令:

curl -v http://localhost:8042/instances/c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c/anonymize -X POST -d '{}' > c:\orthanc-anonymize.dcm

Orthanc工程首次停在了断点RestApi.cpp中的Visit函数内,如下图所示:

利用F11单步调试,随后进入到解析Anonymization请求操作的函数ParseAnonymizationRequest内部,可以看到在该函数内给出了一个示例与我们输入的格式相同

继续单步调试,最后发现在解析Json格式的AnonymizationRequest指令,即我们输入的'{}’,json_reader.cpp中的readToken返回值为tokenError

至此想必我们找到了Anonymization指令出错的原因的:输入的Json格式不正确,虽然我们是按照Orthanc官方的Cookbook来进行的。为了确定Json格式是否有误,在在线Json格式检查网站(http://www.bejson.com/)测试一下,结果为:

按照提示,去掉指令中Json部分的单引号,输入:

curl -v http://localhost:8042/instances/c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c/anonymize -X POST -d {} > c:\orthanc-anonymize.dcm

curl调试输出的结果为:

利用DICOM看图软件,打开可以发现orthanc-anonymize.dcm文件中的患者姓名已经被隐藏掉了。

【总结】:正确的指令应该是外边不添加单引号,如下所示:

curl -v http://localhost:8042/instances/c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c/anonymize -X POST -d {} > c:\orthanc-anonymize.dcm

2)Modification源码调试:

既然已经找到了Anonymization中代码出错的问题,让我们去掉Modification中的单引号,尝试一下输入如下指令:

curl -v http://localhost:8042/instances/c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c/modify -X POST -d {"Replace":{"PatientName":"hello","PatientID":"world"}} >c:\orthanc-modify.dcm

令我们失望的是依然看到了HTTP Server返回的404错误

由于Modification指令中单引号内部还存在着更多的双引号。根据上次的经验,有可能还是Json格式输入输入错误。让我们只保留json_reader.cpp中的readToken断点,直接查看一下解析结果是否是tokenError?重新输入指令,进入到readToken内部,发现函数依然返回tokenError,结果如下图所示:

利用VS自带的查看工具,我们可以看到readToken函数解析的字符串current_,其真实内容是:{Replace:{PatientName:hello,PatientID:world}},其中并未看到我们输入的双引号,将{Replace:{PatientName:hello,PatientID:world}}输入到http://www.bejson.com/中,也得到了错误的结果提示:

这说明我们在命令行中输入的Json指令中的双引号,在被VS读入过程中被忽略了。那么我们利用转义字符将双引号传递进入,输入指令:

curl -v http://localhost:8042/instances/c77324ec-f5e76fc5-c96846bf-2ed4097d-86f9e79c/modify -X POST -d {\"Replace\":{\"PatientName\":\"hello\",\"PatientID\":\"world\"}} >c:\orthanc-modify.dcm

查看结果:

最终运行输出为,

在DCM看图软件中打开orthanc-modify.dcm,可以看到PatientID和PatientName已经修改。

至此,关于Orthanc Modification和Anonymization的调试已经顺利完成,可以松一口气啦,还是调试源代码给力啊^_^。

知识点补充:

Orthanc作为开源项目,获取其源码自然是轻而易举。虽然号称轻型Server系统,但是代码量还是足以吓退大多数人的。初次面对海量的代码无从下手进行调试,下面以上述调试Orthanc官方Cookbook中的Anonymization和Modification示例过程为例,讲解一下如何开始调试Orthanc。

1)如何调试Orthanc中的Http Server

之所以上一节最开始将断点设置在了RestXXX.cpp文件中,是因为本博文中的介绍的Modification和Anonymization使用的是Orthanc提供的REST API服务,因此首先推测错误应该出现在REST API的相关实现函数中。这种方法可以顺利的解决我们上面遇到的问题,并且如你所见我们已经实现了问题的排查。

但是既然调试进入了Orthanc的源码内,就顺道儿搞清楚Orthanc中Http Server的整体流程,也顺便找找究竟是在哪一个地方将curl指令中的双引号忽略的。 再一次输入指令,进入调试状态。断点第一次停在RestApi.cpp中的Visit函数处,在前一节中我们利用“单步调试”顺利的逐步进入到了JSON的解析函数readToken内,“单步调试”是向前追溯的最佳手段,也是VS提供给我们的最直观最有利的错误排查工具。但是为了要了解整个流程,我们此处需要“回溯”,那么VS提供给我们逆流而上的工具是什么呢?那就是“查找所有引用”,如下图所示:

我们可以由RestApi.cpp 转到上一级,即RestApiHierarchy.cpp中的LookupResource函数,如此迭代下去相信可以回溯到整个流程的最顶端。这种方法虽然笨拙了一些,但是比较实用。想必在Windows编程环境下大家还是更喜欢“可视化”的直观操作,即所见即所得。那么单击菜单栏中的“调试”,选择“窗口”中的“调用堆栈”,可以直观的看到在RestApi.cpp中的Visit函数之前的各种函数调用顺序,如下图所示:

至此我们可以看到整个Http Server服务的起始端是mongoose.cpp中的worker_thread函数(在“调用堆栈”中相关函数右键选择“转到源码”可以查看函数的具体位置)。由上图中“调用堆栈”的顺序我们已经可以清晰的看到Orthanc Http Server的整个调用流程。那么我们在worker_thread函数中插入断点,重新输入curl指令,查看一下在整个流程的起始状态下,Orthanc Http Server接收到的数据体是什么格式?如下图所示:

在process_new_connection函数内部读取curl发出的POST请求指令时,连接缓存buf的内容中已经不存在双引号了,因此可以确定curl的-d参数在发送JSON格式数据到Orthanc的Http Server时忽略了双引号。后续可以研究一下curl在windows环境下的使用,尤其是-d参数的设置

2)如何调试Orthanc中的DICOM Server

由于DICOM Server比较熟悉,先验知识比较多,因此调试起来比HTTP Server容易。在Orthanc的main函数中我们可以看到httpServer.Start()和dicomServer.Start(),dicomServer.Start()就是DICOM Server的入口点,由于Orthanc是基于DCMTK开发的,因此后续的流程应该是交由DCMTK来完成的,更详细的细节可参考本专栏前面的DCMTK网络系列文章。预告一下下篇博文会详细介绍利用fo-dicom开源库打造一个简单的DICOM Server服务端,那时再详细的对比分析Orthanc中的DICOM Server,本篇暂且到此为止。

参考资料:

https://code.google.com/p/orthanc/wiki/OrthancCookbook,Cookbook官网链接

https://code.google.com/p/orthanc/wiki/Anonymization,Orthanc的Modification和Anonymization介绍

https://docs.google.com/spreadsheet/pub?key=0Ao5aRMxCX2hldEJadzVUaWFmNW5QTWhrYTI3UHMzdXc&single=true&gid=8&output=html,REST API支持图谱

https://docs.google.com/spreadsheet/pub?key=0Ao5aRMxCX2hldEJadzVUaWFmNW5QTWhrYTI3UHMzdXc&single=true&gid=0&output=html,REST API支持图谱

http://curl.haxx.se/docs/manpage.html,curl中参数介绍

后续专栏博文预告:

fo-dicom搭建简单的DICOM Server



作者:zssure@163.com

时间:2014-11-29

DICOM医学图像处理:Deconstructed PACS之Orthanc,Modification Anonymization相关推荐

  1. DICOM医学图像处理:二零一四▪DICOM专栏一览

    题记 二零一四刚过,新年伊始就发生了"外滩踩踏"恶性事件,告诫我们要珍爱生命,为自己更为家人-- 回顾去年,有些许收获.有些许感慨-- 曾经听过一个段子说两个在公司工作多年的老员工 ...

  2. 【转】DICOM医学图像处理:DICOM网络传输

    背景: 专栏取名为DICOM医学图像处理原因是:博主是从医学图像处理算法研究时开始接触DICOM协议的.当初认识有局限性,认为DICOM只是一个简单的文件格式约定,简而言之,我当时认为DICOM协议就 ...

  3. DICOM医学图像处理:Dcmtk与fo-dicom保存文件的不同设计模式之“同步VS异步”+“单线程VS多线程”...

    2019独角兽企业重金招聘Python工程师标准>>> 一.背景: 最近一直在做DCM相关的编程工作,以前项目使用C++居多,所以使用DCMTK开源库,而目前团队使用C#居多,所以需 ...

  4. DICOM医学图像处理:DICOM存储操作之“多幅BMP图像数据存入DCM文件”

    背景: 本专栏"DICOM医学图像处理"受众较窄,起初只想作为自己学习积累和工作经验的简单整理.前几天无聊浏览了一下,发现阅读量两极化严重,主要集中在"关于BMP(JPG ...

  5. DICOM医学图像处理:DICOM存储操作之 “多幅JPG图像数据存入DCM文件”

    背景: 续上篇,继续介绍如何将多幅JPG图像数据存入DCM文件.即将有损压缩数据直接写入DCM文件,存储为Multi-frame形式. 多幅JPG图像数据存入DCM文件: 为了避免引起歧义,这里着重说 ...

  6. [转]DICOM医学图像处理:Deconstructed PACS之Orthanc

    转载:http://blog.csdn.net/zssureqh/article/details/41424027 背景: 此篇博文介绍一个开源的.基于WEB的DICOM Server软件.该开源软件 ...

  7. 【转】DICOM医学图像处理:开源库mDCM与DCMTK的比較分析(一),JPEG无损压缩DCM图像

    转自:https://www.cnblogs.com/mfrbuaa/p/4004114.html 有修订 背景介绍: 近期项目需求,需要使用C#进行最新的UI和相关DICOM3.0医学图像模块的开发 ...

  8. 【转】DICOM医学图像处理:浅析SWF、MWL、SPS、MPPS

    转自:https://blog.csdn.net/zssureqh/article/details/40151107 背景: 最近重新花时间阅读了DICOM标准,顺带着看了一下HL7标准和IHE,对标 ...

  9. DICOM医学图像处理:浅析SWF、WML、SPS、MPPS

    版权声明:本文为zssure原创文章,转载请注明出处,未经允许不得转载. 目录(?)[+] 背景: 最近重新花时间阅读了DICOM标准,顺带着看了一下HL7标准和IHE,对标题中提到的SWF.WML. ...

最新文章

  1. 洛谷P2766-最长递增子序列问题
  2. JeecgBoot 单体升级微服务快速方案(十分钟搞定)
  3. 技巧:让Eclipse或Flex Builder 支持自动换行。(转)
  4. 疑似Bug:简书安卓10.7首页搜索关键字屏蔽敏感词不彻底
  5. (十)Hibernate的一对一关联关系
  6. Towards Fully 8-bit Integer Inference for the Transformer Model
  7. 四十三 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理...
  8. 【用行动说话】第一篇博客
  9. 【ybt金牌导航1-4-3】【luogu P2627】修剪草坪 / Mowing the Lawn G
  10. Facebook账户 “ 解封、防封、养号 ” 知识要点,已收藏!
  11. TCP三次握手中SYN,ACK,seq ack的含义
  12. 论文的可复现性,能否量化分析?
  13. CDMA与OFDMA的比较
  14. 薛兆丰经济学思维研究:权利在真实生活中的硬度
  15. C#项目:未找到引用错误解决方案
  16. JSP cookie详解
  17. 向用户发送短信验证码
  18. C语言2进制与10进制转换
  19. 计算机几何学,计算机搞定44年几何难题:原来这2个人25年前猜对了
  20. 永磁同步电机三相等效电路图_永磁同步电动机的原理与结构详解

热门文章

  1. python怎么加字幕_python字幕处理工具
  2. 批量删除某种类型Pod,如Evict、NodeAffinity
  3. Java sleep和wait的区别
  4. 【Cyber RT】Apollo Cyber RT安装
  5. keil5安装芯片包及重装软件心得
  6. c语言劝学,《劝学》知识点集锦
  7. 2019最受欢迎开源免费CMS建站系统排行榜
  8. Python+Vue计算机毕业设计医院碳排放管理平台r392w(源码+程序+LW+部署)
  9. swoole(进程,线程)
  10. 遇到的一些bug合集