转自: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

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

  1. 【转】DCMTK开源库的学习笔记3:dcmtk文件中数据元的修改

    转自:https://blog.csdn.net/zssureqh/article/details/8804736 dcm文件是医学领域DICOM3.0标准所对应的主要的文件格式.前两篇学习笔记中,学 ...

  2. 【转】DCMTK开源库的学习笔记1:将DCM文件保存成BMP文件或数据流(即数组)

    转自:https://blog.csdn.net/zssureqh/article/details/8784980 DCMTK开源库介绍: DCMTK是目前最全面实现DICOM3.0标准的开源库,通过 ...

  3. 【转】DCMTK 开源库的学习笔记2:直接操作dcm文件中像素数据的尝试

    转自:https://blog.csdn.net/zssureqh/article/details/8785132 DCMTK官网给出了JPEG格式压缩的DCM文件解压缩的方法(http://supp ...

  4. C++跨平台开源库POCO学习笔记

    原文链接:http://grow.sinaapp.com/?p=1271 POCO(pocoproject.org)看起来是很不错的C++跨平台开源库,包含网络(HTTP.FTP等).正则.XML.Z ...

  5. mysql学习笔记整理——my.ini配置文件

    前言 数据库的本质还是将数据以文件的形式存储在磁盘上,不过通过数据库服务进行管理,mysql就是这样的一个工具,言归正传,前面只是对我以前一直以来的疑惑进行了复述. my.ini配置文件可以对数据库一 ...

  6. 【Python-pywt】 小波变化库—Pywavelets 学习笔记

    (转载) [Python ]小波变化库--Pywavelets 学习笔记_nanbei2463776506的博客-CSDN博客 https://blog.csdn.net/nanbei24637765 ...

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

    转自:https://blog.csdn.net/zssureqh/article/details/9275271 最近由于课题需要,拿出来一些时间阅读了下DICOM3.0标准.在处理相关的DCM医学 ...

  8. 《C++标准库》学习笔记 — STL —流

    <C++标准库>学习笔记 - STL -流 一.操控器 1.原理 2.自定义操控器 3.控制输入的宽度 二.自定义 I/O 操作符 1.重载输出操作符 2.输入操作符 三.自定义格式化标志 ...

  9. Lib库使用学习笔记

    Lib库使用学习笔记 转自:http://blog.csdn.net/macky0668/article/details/6044867 技术前沿 2008-03-31 14:21:10 阅读177  ...

最新文章

  1. 邮件服务器 Postfix+ Cyrus-SASL+cyrus-IMAPD+日常维护
  2. 计算机一级考可以用计算器吗,全国计算机一级考试题(判断题),你对电脑知识了解多少?...
  3. Python编程基础:第四十节 类变量Class Variables
  4. 设置 Nuget 本地源、在线私有源、自动构建打包
  5. IC设计前端几本经典书籍
  6. StringMVC 中如何做数据校验
  7. 工作325:uni-日期小于10补0
  8. datatype未定义是什么意思_vue.js一直提示未定义
  9. 求AOE图的 拓扑排序 及关键路径长度(java实现)
  10. Mysql ==》 单表查询
  11. 中油C语言第一次在线作业,中石油华东《程序设计(C语言)》2020年春季学期在线作业(二)...
  12. 互联网的大厂就那么几家,所以很多员工跳槽后都是互相流动的
  13. 硬盘安装 Ubuntu 9.04 与 XP 双系统 (含 Grub 不写入 MBR 的方法)
  14. C语言判断一个数是否为素数
  15. ReactJS快速入门
  16. 【业务安全01】业务安全基础及测试流程
  17. 【安信可IDE 1.5模板专题2】安信可windows一体化环境IDE V1.5 ESP8266 SDK二次开发直连阿里云飞燕平台,天猫精灵语音控制;
  18. 开源大阅兵:盘点那些走向世界的中国项目
  19. 类似捕鱼达人的金币效果
  20. Ae 效果快速参考:抠像

热门文章

  1. 【Git、GitHub、GitLab】九 工作中非常重要的一些git用法
  2. 【软件开发底层知识修炼】十九 GDB调试从入门到熟练掌握超级详细实战教程学习目录
  3. 【数据结构学习之完全从零实现所有数据结构的代码编写之二】智能指针
  4. 你的心事我全知晓——心情日记小程序丨实战
  5. Vim中根据正则对选中文本对齐(比如ini文件的=号对齐)
  6. swift 第四课 随意 设置button 图片和文字 位置
  7. 【HDU1325】Is It A Tree?(并查集基础题)
  8. ConfigurationManager.AppSettings[] ConfigurationManager智能显示不出来
  9. 美国团购网站Groupon的盈利模式
  10. 【小技巧】【Java】 创建指定数目m的Set数组