系列文章
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 actionBar = new Action(UpdateBar);
Action actionMsg = new Action(UpdateMsg);
Dictionary dic = new Dictionary();
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(DicomTag.SeriesInstanceUID, 0, null);
if (string.IsNullOrEmpty(seriesIuid))
{
continue;
}
if (!dic.ContainsKey(seriesIuid))
{
var dcmSeries = new DcmSeries();
dcmSeries.SeriesIuid = seriesIuid;
dcmSeries.AccessionNo = data.GetValueOrDefault(DicomTag.AccessionNumber, 0, null);
dcmSeries.PatientName = data.GetValueOrDefault(DicomTag.PatientName, 0, null);
dcmSeries.PatientName = DicomUtil.GetPatientName(dcmSeries.PatientName);
dcmSeries.Gender = data.GetValueOrDefault(DicomTag.PatientSex, 0, null);
dcmSeries.Modality = data.GetValueOrDefault(DicomTag.Modality, 0, null);
dcmSeries.PatientBrithDate = data.GetValueOrDefault(DicomTag.PatientBirthDate, 0, null);
dcmSeries.PatientId = data.GetValueOrDefault(DicomTag.PatientID, 0, null);
dcmSeries.SeriesDescription = data.GetValueOrDefault(DicomTag.SeriesDescription, 0, null);
dcmSeries.StudyDate = data.GetValueOrDefault(DicomTag.StudyDate, 0, null);
dcmSeries.StudyId = data.GetValueOrDefault(DicomTag.StudyID, 0, null);
dcmSeries.SeriesNumber = data.GetValueOrDefault(DicomTag.SeriesNumber, 0, null);
dcmSeries.Thinkness = data.GetValueOrDefault(DicomTag.SliceThickness, 0, null);
dcmSeries.FileCount = 0;
dcmSeries.DicomFiles = new List();
dic.Add(seriesIuid, dcmSeries);
}
DcmSeries temSeries = dic[seriesIuid];
DcmFile dcmFile = new DcmFile();
dcmFile.InstanceNumbder = data.GetValueOrDefault(DicomTag.InstanceNumber, 0, 1);
dcmFile.SliceLocation = data.GetSingleValue(DicomTag.SliceLocation);
dcmFile.InstanceUid = data.GetValueOrDefault(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表,用来记录该序列所包含的文件