【转】DCMTK开源库的学习笔记4:利用ini配置文件对dcm影像进行归档

转自:https://blog.csdn.net/zssureqh/article/details/8846337

背景介绍:

医学影像PACS工作站的服务端需要对大量的dcm文件进行归档,写入数据库处理。由于医学图像的特殊性,每一个患者(即所谓的Patient)每做一次检查(即Study)都至少会产生一组图像序列(即Series),而每一组图像序列下会包含大量的dcm文件(例如做一次心脏CTA的诊断,完整的一个心脏断层扫描序列大约有200幅图像)。DICOM3.0协议中对每一幅影像是按照特定的三个UID(唯一标示符)来进行标记的,分别是StudyInstanceUID、SeriesInstanceUID、SOPInstanceUID。其中StudyInstanceUID代表了唯一的一次检查(Study),SeriesInstanceUID代表了相应检查下的唯一序列(Series)、SOPInstanceUID代表了唯一检查下的唯一序列下的唯一图像。通常PACS工作站都是利用这三个UID来对dcm文件进行归档处理。

归档的设计:

1、基本的归档结构是:

第一级:StudyInstanceUID

存储同一患者的影像数据

第二级:SeriesInstanceUID

存储同一次检查下的影像数据

第三级:SOPInstanceUID

存储同一个序列下的影像数据

了解了大致的归档结构后,现在应该考虑怎样将dcm记录写入到数据库中?最直观的想法就是将每一个dcm文件都记录在数据库中,这样当需要读取指定的dcm文件时通过给定的三个UID直接在数据库中查询就能够得到。但是如此一来,数据库的容量会急剧增加,同一患者在数据库中存在着大量的冗余记录。因为患者的影像数据是按照上述的三级目录来归档的,大量的相关的影像数据存储在服务器的同一个目录下,对于同一个序列的图像可以直接在第二级目录中利用SOPInstanceUID来进行检索,而不需要进行数据库的查询。但是当二级目录下的文件数量较大时,检索文件件中的文件同样需要耗费大量的时间,那么怎样可以提高检索效率呢?答案就是:配置文件。由于在归档的时候我们已经读取过每个dcm文件的三个UID,那么可以将归档时候读取的UID信息写入到相应的INI配置文件中,并存储到相应的图像序列目录下。那么在检索图像时,通过前两级UID可以快速在数据库中查询到影像数据的归档目录,当进入到指定的归档目录后,利用归档时生成的INI文件,可以快速的检索到指定的dcm文件,另外如果归档时将一些常用的dcm文件信息一同写入到INI配置文件中(如图像的宽度、高度、患者姓名、出生年月、窗宽/窗位等),在后续的一些图像处理中同样能够节约时间,提高效率。

2、INI配置文件的生成

INI配置文件的格式就不细讲了,CSDN中已有很多详细讲解的博文,请大家自行参阅。这次详细讲解一下利用dcmtk开源库来提取相应的dcm文件信息并写入到ini配置文件中的方法。

DCMTK开源库是一个很好的医学影像开发基础库,其很好的实现了DICOM3.0标准,且类的继承体系简单明了,与DICOM3.0标准一一对应(参考博文:“dcmtk开源库的继承体系与DICOM3.0标准的对应关系”)。这里我们只用到了dcmtk中的DcmItem类,该类派生自DcmObject基础类,其含有ElementList成员变量,存储了DICOM3.0标准中规定的一系列的数据元(Data Element)基本结构如下图所示:

注:DcmItem类就是Dataset(数据集)的子类。其内部包含了数据元序列(即ElementList数据成员)。

通过阅读关于DcmItem类的源码,总结归纳了以下几种dcmtk开源库给出的操作dcm文件相应数据元的函数:findAndGet 函数、findOrCreate函数、findAndXXX函数、putAndInsert函数,以及insertXXX函数,如下图:

至此我们可以利用findAndGet函数类来提取dcm文件中的相关信息,结合WindowsAPI函数来进行INI配置文件的归档。由于INI配置文件就是文本文件,因此我们选用了DcmItem中的findAndGetString函数来提取dcm文件中的数据元,利用findAndGetString函数能够直接得到字符串格式(const char*)的数据元,另外,结合WritePrivateProfileString函数来生成INI配置文件。(注:此处findAndGetString函数正好与WritePrivateProfileString函数的格式匹配,如果采用findAndGet的其他函数,如findAndGetSin32,就需要利用itoa等函数将整型转换成const char*类型,增加了编程的复杂性)

下面给出部分代码:

        DcmTagKey THU_DCM_ELEMENTS[]={DCM_InstanceNubmber, DCM_Rows,DCM_Columns,DCM_PatientName};//定义需要写入到ini文件中的dcm数据元标签数组int num=sizeof(THU_DCM_ELEMNTS)/sizeof(DcmTagKey);OFString mImageValue;OFString mGap("|");//INI配置文件中各个数据元之间的间隔符OFString mImageModule("ImageModule\\");//配置文件的节名称OFString mSOPInstanceUID;OFString mSeriesInstanceUID;DcmDataset *pDataset=mDcmFile->getDataset();DcmMetaInfo *pMetaInfo=mDcmFile->getMetaInfo();pDataset->findAndGetOFString(DCM_SeriesInstanceUID,mSeriesInstanceUID);pDataset->findAndGetOFString(DCM_SOPInstanceUID,mSOPInstanceUID);mImageModule+=mSeriesInstanceUID;for(int i=0;i<num;++i){OFString mValueRecord;DcmElement *element;if(THU_DCM_ELEMNTS[i].getGroup()>0x0002)// to determine if the THU_DCM_ELEMENTS[i] is MetaInfo{//the element belongs to DatasetpDataset->findAndGetOFStringArray(THU_DCM_ELEMNTS[i],mValueRecord);mValueRecord+=mGap;}else{//the element belongs to MetaInfoif(THU_DCM_ELEMNTS[i].getGroup()==0x0000 && THU_DCM_ELEMNTS[i].getElement()==0x0000){mValueRecord=mGap;}else{pMetaInfo->findAndGetOFStringArray(THU_DCM_ELEMNTS[i],mValueRecord);mValueRecord+=mGap;}}mImageValue+=mValueRecord;}::WritePrivateProfileString(mImageModule.c_str(),mSOPInstanceUID.c_str(),mImageValue.c_str(),iniFileName);

3、数据库的写入:

数据库写入的方式与INI配置文件生成基本相似,只要稍微了解C++数据库编程的人员,就很容易仿照上述INI配置文件的生成过程来完成数据库写入的部分,此处就不细讲了,只给出简单的部分代码:

 

				DcmFileFormat fileformat;TCHAR FilePath[MAX_PATH];OFCondition oc = fileformat.loadFile(FilePath);DcmDataset *pDataset=fileformat.getDataset();char query[1000];memset(query,0,sizeof(char)*1000);lstrcat(query,_T("insert into patient values ("));const char *tString;pDataset->findAndGetString(DCM_InstanceNumber,tString);lstrcat(query,tString);lstrcat(query,_T(","));pDataset->findAndGetString(DCM_PatientName,tString);lstrcat(query,_T("\""));lstrcat(query,tString);lstrcat(query,_T("\""));lstrcat(query,_T(","));pDataset->findAndGetString(DCM_PatientID,tString);lstrcat(query,tString);lstrcat(query,_T(","));pDataset->findAndGetString(DCM_PatientBirthDate,tString);lstrcat(query,tString);lstrcat(query,_T(","));pDataset->findAndGetString(DCM_PatientSex,tString);lstrcat(query,"\"");lstrcat(query,tString);lstrcat(query,"\"");lstrcat(query,",");pDataset->findAndGetString(DCM_PatientAge,tString);char temp[100];memcpy(temp,tString,lstrlen(tString));temp[lstrlen(tString)]=_T('\0');for(int i=0;i<strlen(temp);++i)if(temp[i]==_T('Y'))temp[i]=_T('\0');lstrcat(query,temp);lstrcat(query,",");lstrcat(query,_T("2013)"));		//mysql数据库的写入MYSQL* con;con=mysql_init((MYSQL*)0);if(con!=NULL && mysql_real_connect(con,host,user,passwd,db,port,unix_socket,client_flag)){if(!mysql_select_db(con,db)){::printf("Selcet successfully the database!\n");con->reconnect=1;int rt=mysql_real_query(mysql,query,strlen(query));if(rt){::printf("Error making insert!!!\n");}}}

对于MYSQL的C++操作,可以参见博文: http://www.cnblogs.com/justinzhang/archive/2011/09/23/2185963.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436011.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux ( )含义,Linux的shell中$()、$[] 、${}分别是什么意思?

在bash中&#xff0c;$( )与 (反引号)都是用来作命令替换的。命令替换与变量替换差不多&#xff0c;都是用来重组命令行的&#xff0c;先完成引号里的命令行&#xff0c;然后将其结果替换出来&#xff0c;再重组成新的命令行。exp 1[rootlocalhost ~]# echo today is $(date &q…

【转】DCMTK开源库类继承结构与DICOM3.0标准元素定义的对应关系图

转自&#xff1a;https://blog.csdn.net/zssureqh/article/details/9275271 最近由于课题需要&#xff0c;拿出来一些时间阅读了下DICOM3.0标准。在处理相关的DCM医学图像时使用了DCMTK开源库&#xff0c;废话不多说&#xff0c;直接贴图&#xff1a; 图一&#xff1a;DCMTK开…

c语言中用简易暗纹来输入密码,确定夫琅和费单缝衍射明、暗纹位置的不同教学方法的讨论...

崔红玲苏向英摘要&#xff1a;夫琅和费单缝衍射的明、暗纹位置及相应光强是波动光学中的重要部分&#xff0c;用不同的方法讲解效果不同。本文比较了惠更斯-菲涅耳原理定量积分法及半波带法得到的结论&#xff0c;表明在近似情况下&#xff0c;这两种方法都可以对其进行描述。关…

【转】从零开始学图形学:10分钟看懂贝塞尔曲线

转自&#xff1a;https://zhuanlan.zhihu.com/p/344934774 引入 在画画的时候&#xff0c;你可能会遇到画曲线的情况。比如你想画一个肥宅的大肚子轮廓&#xff0c;此时你随手一画&#xff0c;发现不好看&#xff0c;感觉太鼓了&#xff0c;于是你只能重新画&#xff0c;再画一…

Flex 学习随笔 ---- 使用WebService 与数据库连接

任何一个网络工具&#xff0c; 如果不能和数据打交道&#xff0c;那它就是失败的。 还好Flex是可以的&#xff0c;由于本人刚学&#xff0c;就用asp.netc#来讲下这个简单的连接。 Flex 和数据库通讯现在只能使用Service&#xff0c;如httpservice,rpcservice,webservice等等。 …

第三方登录android代码,Android Learning:微信第三方登录(示例代码)

这两天&#xff0c;解决了微信第三方授权登录的问题&#xff0c;作为一个新手&#xff0c;想想也是一把辛酸泪。我想着&#xff0c;就把我的遇到的坑给大家分享一下&#xff0c;避免新手遇到我这样的问题能够顺利避开。步骤一 微信开发者平台我开始的解决思路是&#xff0c;去这…

对象与函数

摘自《UMLOOPC嵌入式C语言开发精讲》 11.3 对象与函数11.3.1 函数的角色经济诺贝尔奖得主H.A.Simon&#xff08;H.A.Simon&#xff0c;计算机人工智能之父&#xff09;在其1962年的文章《The Architecture of Complexity》中说道&#xff1a;“从小系统建造成庞大系统时&…

android打包工具多渠道批量打包,Android 快速渠道批量打包详解教程-美团多渠道打包方案...

今天写一篇文章来总结下android批量打渠道包美团版本。之前项目上一直用的是gradle 批量打包方式&#xff0c;那个速度啊真是令人发指&#xff0c;15个渠道得跑上半个小时&#xff0c;出去吃顿饭回来&#xff0c;还在跑。特别是赶上项目上线的话&#xff0c;如果给测试提交了正…

【转】云社区 博客 博客详情 二维异形件排版算法介绍(一)

转自&#xff1a;https://bbs.huaweicloud.com/blogs/175385 【摘要】 排样问题&#xff08;Nesting Problem&#xff09;又称为下料问题(Cutting and stock problems)或填充问题(Packing Problem)&#xff0c;其目标是在材料切割过程中寻找一个较高的材料利用率。排样问题属于…

android 微信两个服务的,微信上线两个新功能

微信又上线新功能了&#xff01;一个与你的钱包相关&#xff0c;一个与你的微信号相关&#xff0c;赶紧来看看吧微信支付分全面开放每个微信用户都拥有自己的一个分数值 &#xff0c;且每月根据综合数据更新一次。达到一定的分值门槛&#xff0c;用户即可享受超千项便捷服务。这…

【转】二维异形件排版算法介绍(二)

转自&#xff1a;https://bbs.huaweicloud.com/blogs/196289【摘要】 二维不规则异形件主要有两种策略&#xff1a;分别是基于可行解的排样策略和基于重叠移除的排样策略。所谓基于可行解的排样策略&#xff0c;是指在排样过程中零件之间始终是不重叠的&#xff0c;而基于重叠移…

【转】介绍一些免费/开源的医学影像后处理工具

转自&#xff1a;https://blog.csdn.net/liaopiankun0618/article/details/84328331 来源&#xff1a;融视影像科技 综述 医学影像的处理有两个特质。一是复杂&#xff0c;整个处理流程涉及多种算法&#xff0c;需要调整的参数较多。二是发展快&#xff0c;从采集、重建到后…

android gradle 语法,Gradle 1.语法

8种机械键盘轴体对比本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f;gradle 语法解析:gradle的语法十分简洁,以至于看起来跟像是配置文件。先看一个简单的android项目完整的gradle脚本&#xff1a;build.gradle123456789101112131415…

【转】二维异形件排版算法介绍(三)

转自&#xff1a;https://bbs.huaweicloud.com/blogs/203947 【摘要】 相比于基于可行解的排样算法&#xff0c;重叠移除算法在改变解的状态时&#xff0c;允许零件之间发生重叠&#xff0c;然后采用分离技术消除重叠&#xff0c;直到达到算法的终止条件为止。重叠移除算法的关…

【转】Dicom格式文件解析器!!!!!!!

转自&#xff1a;https://www.cnblogs.com/assassinx/archive/2013/01/09/dicomViewer.html Dicom全称是医学数字图像与通讯&#xff0c;这里讲的暂不涉及通讯的问题 只讲*.dcm 也就是diocm格式文件的读取&#xff0c;读取本身是没啥难度的 无非就是字节码数据流处理。只不过确…

【转】医学影像调窗技术!!!!

转自&#xff1a;https://www.cnblogs.com/assassinx/p/3139505.html 在年初的时候做过一个dicom格式文件解析&#xff0c;当时只是提了下。看着跟别人的显示出来也差不多 其实是我想太简单了。整理了下思路 这里提供正确的调窗代码。 医学影像 说得挺高科技的 其实在这个过程…

【转】理解字节序 大端字节序和小端字节序

转自&#xff1a;https://www.cnblogs.com/gremount/p/8830707.html 以下内容参考了 http://www.ruanyifeng.com/blog/2016/11/byte-order.html https://blog.csdn.net/yishengzhiai005/article/details/39672529 1. 计算机硬件有两种储存数据的方式&#xff1a;大端字节序…

创建windows服务,定时监控网站应用程序池

最近网站总是报"Timer_Connection"错误,导致该网站所使用的应用程序池由于错误过多停止运行,网站也就出现了service unvaliable,无法访问,在网上查了很多资料,结果很让人无奈,这个问题已经困扰我了很久,一直没有得到解决,后来同事发来一篇文章让我有了新的解决方法,虽…

【转】Qtcreator中常用快捷键和小技巧

转自&#xff1a;https://blog.csdn.net/imxiangzi/article/details/48863855 https://blog.csdn.net/jh1513/article/details/52346802 快捷键及对应含义 下载地址&#xff1a;http://download.csdn.net/detail/jh1513/9615209 快捷键 功能 Esc 切换到代码编辑状态 F1 …

【转】VS编译时自动引用Debug|Release版本的dll

转自&#xff1a;https://www.cnblogs.com/KevinYang/archive/2011/04/10/2011879.html 公司一些早期的项目&#xff0c;把所有工程都放到一个解决方案下了&#xff0c;导致整个解决方案编译很慢&#xff0c;而且也不便于类库的复用和维护。因此我们决定把工程按照功能划分到不…