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

打印 上一主题 下一主题

主题 677|帖子 677|积分 2031

近来在做一个医疗项目,此中设计到医学影像数据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.         }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表