C# 实现医学影像 DICOM 工作站(2):Dicom影像导入和工作列表

该系列文章详细介绍了如何使用C#语言开发一个医学影像DICOM工作站,涵盖了从项目介绍到影像导入、展示、处理、多平面重建、体绘制以及利用AI进行疾病分析的全过程。代码示例展示了如何处理DICOM文件,解析元数据并存储到数据库中。
摘要由CSDN通过智能技术生成

系列文章

1.C# 实现医学影像 DICOM  工作站(1):项目介绍

2.C# 实现医学影像 DICOM 工作站(2):Dicom影像导入和工作列表

3.C# 实现医学影像 DICOM 工作站(3):实现Dicom影像的展示

4.C# 实现医学影像 DICOM 工作站(4):实现Dicom影像的调窗,缩放,移动,旋转,透镜等功能

5.C# 实现医学影像 DICOM 工作站(5):实现Dicom影像序列的多平面重建(MPR)

6.C# 实现医学影像 DICOM 工作站(6):使用VTK实现影像序列的体绘制(VR)

7.C# 实现医学影像 DICOM 工作站(7):使用AI功能完成肺间质性疾病(ILD)的分析和源码下载

核心代码:

  private async void StartTask()
        {
            bool isImport = false;
            try
            {
                var fileInfos = await Task.Run(() =>
                {
                    DirectoryInfo dir = new DirectoryInfo(SelectPath);
                    var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
                    return files;
                });
                llLoading.Visibility = Visibility.Hidden;
                llLoadBar.Visibility = Visibility.Visible;
                llLoadBar.Value = 0;
                llLoadBar.Minimum = 0;
                llLoadBar.Maximum = fileInfos.Length;
                Action<string> actionBar = new Action<string>(UpdateBar);
                Action<string> actionMsg = new Action<string>(UpdateMsg);
                Dictionary<string, DcmSeries> dic = new Dictionary<string, DcmSeries>();
                await Task.Run(() =>
                {
                    foreach (var fileInfo in fileInfos)
                    {
                        try
                        {
                            this.Dispatcher.BeginInvoke(actionBar, fileInfo.FullName);
                            var suffix = fileInfo.Extension.ToLower();
                            if (suffix == ".dcm" || string.IsNullOrEmpty(suffix))
                            {
                                if (!DicomFile.HasValidHeader(fileInfo.FullName))
                                {
                                    continue;
                                }
                                var file = DicomFile.Open(fileInfo.FullName);
                                var data = file.Dataset;
                                var seriesIuid = data.GetValueOrDefault<string>(DicomTag.SeriesInstanceUID, 0, null);
                                if (string.IsNullOrEmpty(seriesIuid))
                                {
                                    continue;
                                }
                                if (!dic.ContainsKey(seriesIuid))
                                {
                                    var dcmSeries = new DcmSeries();
                                    dcmSeries.SeriesIuid = seriesIuid;
                                    dcmSeries.AccessionNo = data.GetValueOrDefault<string>(DicomTag.AccessionNumber, 0, null);
                                    dcmSeries.PatientName = data.GetValueOrDefault<string>(DicomTag.PatientName, 0, null);
                                    dcmSeries.PatientName = DicomUtil.GetPatientName(dcmSeries.PatientName);
                                    dcmSeries.Gender = data.GetValueOrDefault<string>(DicomTag.PatientSex, 0, null);
                                    dcmSeries.Modality = data.GetValueOrDefault<string>(DicomTag.Modality, 0, null);
                                    dcmSeries.PatientBrithDate = data.GetValueOrDefault<string>(DicomTag.PatientBirthDate, 0, null);
                                    dcmSeries.PatientId = data.GetValueOrDefault<string>(DicomTag.PatientID, 0, null);
                                    dcmSeries.SeriesDescription = data.GetValueOrDefault<string>(DicomTag.SeriesDescription, 0, null);
                                    dcmSeries.StudyDate = data.GetValueOrDefault<string>(DicomTag.StudyDate, 0, null);
                                    dcmSeries.StudyId = data.GetValueOrDefault<string>(DicomTag.StudyID, 0, null);
                                    dcmSeries.SeriesNumber = data.GetValueOrDefault<string>(DicomTag.SeriesNumber, 0, null);
                                    dcmSeries.Thinkness = data.GetValueOrDefault<string>(DicomTag.SliceThickness, 0, null);
                                    dcmSeries.FileCount = 0;
                                    dcmSeries.DicomFiles = new List<DcmFile>();
                                    dic.Add(seriesIuid, dcmSeries);
                                }
                                DcmSeries temSeries = dic[seriesIuid];
                                DcmFile dcmFile = new DcmFile();
                                dcmFile.InstanceNumbder = data.GetValueOrDefault<int>(DicomTag.InstanceNumber, 0, 1);
                                dcmFile.SliceLocation = data.GetSingleValue<double>(DicomTag.SliceLocation);
                                dcmFile.InstanceUid = data.GetValueOrDefault<string>(DicomTag.SOPInstanceUID, 0, null);
                                dcmFile.Path = fileInfo.FullName;
                                temSeries.DicomFiles.Add(dcmFile);
                            }
                        }
                        catch (Exception ex)
                        {


                        }

                    }
                    if (dic.Count > 0)
                    {
                        isImport = true;
                        this.Dispatcher.BeginInvoke(actionMsg, "正在进行归档.......");
                        using (DicomDBContext db = DicomDBContext.getInstance())
                        {
                            foreach (var item in dic)
                            {
                                string seriesUID = item.Key;
                                var tem = db.DcmSerieses.Where(m => m.SeriesIuid == seriesUID).ToList();
                                DcmSeries series = null;
                                if (tem.Count() > 0)
                                {
                                    series = tem.First();
                                    db.DcmSerieses.Remove(series);
                                    var temList = db.DcmFiles.Where(m => m.SeriesId == series.Id).ToList();
                                    db.DcmFiles.RemoveRange(temList);
                                    db.SaveChanges();
                                }
                                series = item.Value;
                                var listFiles = series.DicomFiles;
                                series.DicomFiles = null;
                                series.LastModified = DateTime.Now;
                                series.FileCount = listFiles.Count;
                                db.DcmSerieses.Add(series);
                                db.SaveChanges();
                                foreach (var dcmFile in listFiles)
                                {
                                    dcmFile.SeriesId = series.Id;
                                }
                                db.DcmFiles.AddRange(listFiles);
                                db.SaveChanges();


                            }
                        }
                    }

                });
            }
            catch (Exception ex)
            {
                HandyControl.Controls.MessageBox.Show(ex.Message, "错误信息", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                this.Close();
                if (isImport)
                {
                    EventBus.Instance().TriggerReloadWorkList();
                }
            }
        }

核心代码讲解:

1. 代码首先完成获取目录下包括子目录中所有的文件

2.使用Fo-Dicom对所有文件进行判断,判断是否是DICOM文件

3.对于是Dicom的文件进行解析.对于工作站,和普通的PACS终端不同,我们使用Series作为工作列表的层级,方便处理. 

        DIcom中一般存在这样的层级关系Patient->Study->Series->Instance,即一般情况下,一个病人有多个检查,一个检查存在多个序列,一个序列有可能有多个实例. 

        我们这里使用Series作为工作列表的层级.

4.在获取获取序列底下所有dicom文件的同时,获取InstanceNumbder ,后面我将用该属性对序列文件进行排序.

5.数据库入库,保存为2个表,一个是Series表,主要记录检查相关信息,一个是File表,用来记录该序列所包含的文件

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

影像熊猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值