翼度科技»论坛 编程开发 .net 查看内容

医学DICOM文件与PACS系统进行数据传输

2

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
最近在做一个医疗项目,其中设计到医学影像数据Dicom文件的传输,其中的一个功能是需要Dicom文件和PACS系统进行互通,就是能将本地的DICOM文件传输到PACS系统,并且本地系统能查询到PACS系统数据并下载。针对将文件上传到PACS系统。之前我们项目中都是使用的C++来处理的。C#的项目都是通过调用C++封装的接口来实现与PACS的数据传输。我这里做了实现了两种方案,都是纯C#实现,并且都已走通。
方式一:通过C#的开源库fo-dicom来实现的数据传输,直接通过NuGet安装相关的依赖包,比如我这里是NET6,搜索并下载fo-dicom.NetCore,如果是.net framework版本的,应该是搜索fo-dicom安装即可。也可以去github上下载源码笔记编译。这里直接上代码,代码中都有注释。
方式一:基于fo-dicom的开源库来实现
  1.         /// <summary>
  2.         /// 发送Dicom数据到PACS系统,C#实现方式
  3.         /// </summary>
  4.         /// <param name="dicomFilePath">Dicom文件路径</param>
  5.         /// <param name="nodeName">Dicom节点名称,我这里是根据节点来找到对应的PACS服务器信息</param>
  6.         /// <returns></returns>
  7.         public async Task SendDicomFileToPacs(string dicomFilePath, string nodeName)
  8.         {
  9.             DICOMConnectParameterWrapper connectPara = new DICOMConnectParameterWrapper();
  10.             DICOMConnectKeyWrapper connectKey = new DICOMConnectKeyWrapper();
  11.             bool isSecure = false;
  12.             if (GetConnectionParameter(nodeName, ref connectPara, ref connectKey, ref isSecure) == false)
  13.             {
  14.                 await Task.CompletedTask; //如果找不到配置的PACS服务器信息,直接返回
  15.             }
  16.             //connectPara.ServiceIP=PACS服务器IP,connectPara.ServicePort=PACS服务器端口,connectPara.ClientAETitle=客户端AETITLE,connectPara.ServiceAETitle=PACS服务器AEtitle
  17.             var client = new Dicom.Network.Client.DicomClient(connectPara.ServiceIP, Convert.ToInt32(connectPara.ServicePort), false, connectPara.ClientAETitle, connectPara.ServiceAETitle);
  18.             var file = DicomFile.Open(@dicomFilePath);
  19.             client.AssociationAccepted += (sender, args) =>
  20.             {
  21.                 Console.WriteLine("Association accepted");
  22.             };
  23.             client.AssociationRejected += (sender, args) =>
  24.             {
  25.                 Console.WriteLine("Association rejected");
  26.             };
  27.             client.RequestTimedOut += (sender, args) =>
  28.             {
  29.                 Console.WriteLine("DIMSE timeout");
  30.             };
  31.             client.StateChanged += (sender, args) =>
  32.             {
  33.                 Console.WriteLine("DIMSE progress: {0} / {1}", args.NewState.ToString(), args.OldState.ToString());
  34.             };
  35.             await client.AddRequestAsync(new Dicom.Network.DicomCStoreRequest(@dicomFilePath)
  36.             {
  37.                 OnResponseReceived = (req, res) =>
  38.                 {
  39.                     Console.WriteLine($"C-STORE response: {res.Status}");
  40.                 }
  41.             });
  42.             try
  43.             {
  44.                 await client.SendAsync();
  45.             }
  46.             catch(Exception ex)
  47.             {
  48.                 Console.WriteLine("An error occurred while sending the DICOM file: {0}", ex.Message);
  49.             }
  50.             
  51.         }
复制代码
在方式一中,这里封装的是针对简单的传输。是在PACS系统不需要认证等前提下,就是说数据传输不需要加密认证等。 当然,实际使用时,PACS系统有些会有安全和认证机制,我们需要根据实际情况处理。我这里的方法GetConnectionParameter是封装的根据PACS节点名来找到对应的PACS的配置,比如PACS的服务器IP,Port,是否加密,证书,等等。如果有加密或认证什么的,还需要进一步处理,我这里会涉及到多个PACS服务器系统,我是在系统中做了配置,通过nodeName来找到对一个的PACS系统的信息。
GetConnectionParameter获取PACS服务器信息
  1.         private bool GetConnectionParameter(string nodeName, ref DICOMConnectParameterWrapper connectPara, ref DICOMConnectKeyWrapper connectKey, ref bool isSecure)
  2.         {
  3.             if (!DicomPeerDictionary.ContainsKey(nodeName))
  4.             {
  5.                 return false;
  6.             }
  7.             DicomNodeBase node = DicomPeerDictionary[nodeName];
  8.             connectPara.ClientAETitle = ConfigInfo.DicomNode_ClientAETitle; //客户端AETitle
  9.             connectPara.ClientIP = CommonHelper.GetAddressIP(); //客户端IP地址
  10.             connectPara.ClientPort = ConfigInfo.DicomNode_ClientPort; //客户端端口
  11.             connectPara.ServiceAETitle = node.AETitle; //PACS服务器AETitle
  12.             connectPara.ServiceIP = node.IP; //PACS服务器IP
  13.             connectPara.ServicePort = node.Port; //PACS服务器端口
  14.             connectKey.PrivateKey = node.PrivateKeyPath; //秘钥
  15.             connectKey.CACertificateFile = node.CACertificatePath; //CA证书文件
  16.             connectKey.CertificateFile = node.CertificatePath; //证书
  17.             isSecure = node.IsEncryptionChecked; //是否加密
  18.             return true;
  19.         }
复制代码
使用的时候就简单了,直接调用SendDicomFileToPacs方法,传入Dicom文件的全路径,以及PACS配置的NodeName即可。另外,我这里用的fo-dicom的库是fo-dicom.netcore的4.0.8版本的,每个版本的可能会有些差别。这里还有涉及到从PACS查询数据,下载数据的功能,这个在fo-dicom库中可以使用类Dicom.Network.DicomCFindRequest来进行操作,其中封装了好几个查询的方法:CreateStudyQuery,CreateSeriesQuery,CreatePatientQuery,CreateImageQuery,CreateWorklistQuery,然后询请求的响应通过类中的OnResponseReceived事件处理,可以获取到查询结果的数据集。我们可以将查询结果的数据集直接转换成一个DICOM文件保存到本地,这样就可以实现下载功能。
方式二:传输数据到PACS的实现方式
这种方式我是针对Orthanc的PACS系统的实现方式,,Orthanc本身有提供API接口,只需要调用其接口实现数据传输即可。使用的时候传入Dicom文件路径和PACS服务器URL即可。这里代码如下。
发送数据到Orthanc的PACS系统
  1.         /// <summary>
  2.         /// 发送数据到Orthanc的PACS系统,C#实现方式,直接调用Orthanc的API来实现
  3.         /// </summary>
  4.         /// <param name="dicomFilePath">Dicom文件路径</param>
  5.         /// <param name="orthancUrl">PACS系统的URL,类似 http://localhost:8042</param>
  6.         public void UploadDicomToOrthanc(string dicomFilePath, string orthancUrl)
  7.         {
  8.             using (var client = new HttpClient())
  9.             {
  10.                 using (var content = new MultipartFormDataContent())
  11.                 {
  12.                     // 添加文件内容
  13.                     var fileStream = File.OpenRead(dicomFilePath);
  14.                     var streamContent = new StreamContent(fileStream);
  15.                     content.Add(streamContent, "file", Path.GetFileName(dicomFilePath));
  16.                     // 发送POST请求到Orthanc服务器
  17.                     var response =  client.PostAsync($"{orthancUrl}/instances", content).Result;
  18.                     if (response.IsSuccessStatusCode)
  19.                     {
  20.                         Console.WriteLine("DICOM文件上传成功。");
  21.                     }
  22.                     else
  23.                     {
  24.                         Console.WriteLine("上传失败,HTTP状态码:" + response.StatusCode);
  25.                     }
  26.                 }
  27.             }
  28.         }
复制代码
来源:https://www.cnblogs.com/huangqian/p/18413651
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具