你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
使用 C# 和 DICOMweb 标准 API
本文介绍如何通过使用 C# 和示例 .dcm DICOM® 文件来使用 DICOMweb 服务。
使用以下示例文件:
- blue-circle.dcm
- dicom-metadata.csv
- green-square.dcm
- red-triangle.dcm
示例 DICOM 文件的文件名、studyUID、seriesUID 和 instanceUID 为:
文件 | StudyUID | SeriesUID | InstanceUID |
---|---|---|---|
green-square.dcm | 1.2.826.0.1.3680043.8.498.13230779778012324449356534479549187420 | 1.2.826.0.1.3680043.8.498.45787841905473114233124723359129632652 | 1.2.826.0.1.3680043.8.498.12714725698140337137334606354172323212 |
red-triangle.dcm | 1.2.826.0.1.3680043.8.498.13230779778012324449356534479549187420 | 1.2.826.0.1.3680043.8.498.45787841905473114233124723359129632652 | 1.2.826.0.1.3680043.8.498.47359123102728459884412887463296905395 |
blue-circle.dcm | 1.2.826.0.1.3680043.8.498.13230779778012324449356534479549187420 | 1.2.826.0.1.3680043.8.498.77033797676425927098669402985243398207 | 1.2.826.0.1.3680043.8.498.13273713909719068980354078852867170114 |
注意
这些文件中的每一个都代表一个实例,并且是同一研究的一部分。 此外,绿色正方形和红色三角形属于同一系列,而蓝色圆形属于单独的系列。
先决条件
若要使用 DICOMweb 标准 API,需要部署 DICOM 服务实例。 有关详细信息,请参阅使用 Azure 门户部署 DICOM 服务。
部署 DICOM 服务实例后,检索应用服务的 URL:
- 登录 Azure 门户。
- 搜索“最近的资源”并选择你的 DICOM 服务实例。
- 复制 DICOM 服务的服务 URL。 在发出请求时,请确保将版本指定为 URL 的一部分。 有关详细信息,请参阅 DICOM 服务的 API 版本控制。
在应用程序中,安装 NuGet 包:
创建 DicomWebClient
部署 DICOM 服务后,创建 DicomWebClient。 运行代码片段以创建 DicomWebClient,在本教程的其余部分中会用到它。 确保已安装两个 NuGet 包。 有关详细信息,请参阅使用 Azure CLI 获取用于 DICOM 服务的访问令牌。
string webServerUrl ="{Your DicomWeb Server URL}"
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(webServerUrl);
IDicomWebClient client = new DicomWebClient(httpClient);
client.HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", “{Your token value}”);
使用 DicomWebClient,我们现在可以执行存储、检索、搜索和删除操作。
存储 DICOM 实例 (STOW)
通过使用 DicomWebClient,我们现在可以存储 DICOM 文件。
存储单个实例
“存储单个实例”演示如何上传单个 DICOM 文件。
详细信息:
- POST /studies
DicomFile dicomFile = await DicomFile.OpenAsync(@"{Path To blue-circle.dcm}");
DicomWebResponse response = await client.StoreAsync(new[] { dicomFile });
存储特定研究的实例
“存储特定研究的实例”演示如何将 DICOM 文件上传到指定的研究。
详细信息:
- POST /studies/{study}
DicomFile dicomFile = await DicomFile.OpenAsync(@"{Path To red-triangle.dcm}");
DicomWebResponse response = await client.StoreAsync(new[] { dicomFile }, "1.2.826.0.1.3680043.8.498.13230779778012324449356534479549187420");
在继续学习本教程的下一部分之前,请使用上述任一方法上传 green-square.dcm
文件。
检索 DICOM 实例 (WADO)
代码片段演示如何使用之前创建的 DicomWebClient 执行每个检索查询。
其余示例中会使用这些变量。
string studyInstanceUid = "1.2.826.0.1.3680043.8.498.13230779778012324449356534479549187420"; //StudyInstanceUID for all 3 examples
string seriesInstanceUid = "1.2.826.0.1.3680043.8.498.45787841905473114233124723359129632652"; //SeriesInstanceUID for green-square and red-triangle
string sopInstanceUid = "1.2.826.0.1.3680043.8.498.47359123102728459884412887463296905395"; //SOPInstanceUID for red-triangle
检索研究中的所有实例
详细信息:
- GET /studies/{study}
DicomWebResponse response = await client.RetrieveStudyAsync(studyInstanceUid);
之前上传的全部三个 dcm 文件都是同一研究的一部分,因此响应应返回全部三个实例。 验证响应的状态代码是否为 OK,以及是否返回了全部三个实例。
使用检索的实例
以下代码片段演示如何访问检索的实例。 它还演示了如何访问实例的某些字段,以及如何将其另存为 dcm 文件。
DicomWebAsyncEnumerableResponse<DicomFile> response = await client.RetrieveStudyAsync(studyInstanceUid);
await foreach (DicomFile file in response)
{
string patientName = file.Dataset.GetString(DicomTag.PatientName);
string studyId = file.Dataset.GetString(DicomTag.StudyID);
string seriesNumber = file.Dataset.GetString(DicomTag.SeriesNumber);
string instanceNumber = file.Dataset.GetString(DicomTag.InstanceNumber);
file.Save($"<path_to_save>\\{patientName}{studyId}{seriesNumber}{instanceNumber}.dcm");
}
检索研究中所有实例的元数据
此响应检索单个研究中所有实例的元数据。
详细信息:
- GET /studies/{study}/metadata
DicomWebResponse response = await client.RetrieveStudyMetadataAsync(studyInstanceUid);
之前上传的全部三个 dcm 文件都是同一研究的一部分,因此响应应返回全部三个实例的元数据。 验证响应的状态代码是否为 OK,以及是否返回了所有元数据。
检索系列中的所有实例
此响应检索单个系列中的所有实例。
详细信息:
- GET /studies/{study}/series/{series}
DicomWebResponse response = await client.RetrieveSeriesAsync(studyInstanceUid, seriesInstanceUid);
此系列有两个实例(绿色正方形和红色三角形),因此响应应返回这两个实例。 验证响应的状态代码是否为 OK,以及是否返回了这两个实例。
检索系列中所有实例的元数据
此响应检索单个研究中所有实例的元数据。
详细信息:
- GET /studies/{study}/series/{series}/metadata
DicomWebResponse response = await client.RetrieveSeriesMetadataAsync(studyInstanceUid, seriesInstanceUid);
该系列有两个实例(绿色正方形和红色三角形),因此响应应返回这两个实例的元数据。 验证响应的状态代码是否为 OK,以及是否返回了这两个实例的元数据。
检索一系列研究中的单个实例
此请求检索单个实例。
详细信息:
- GET /studies/{study}/series{series}/instances/{instance}
DicomWebResponse response = await client.RetrieveInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid);
该响应应仅返回红色三角形实例。 验证响应的状态代码是否为 OK,以及是否返回了该实例。
检索一系列研究中的单个实例的元数据
此请求检索单个研究和系列中单个实例的元数据。
详细信息:
- GET /studies/{study}/series/{series}/instances/{instance}/metadata
DicomWebResponse response = await client.RetrieveInstanceMetadataAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid);
该响应应仅返回红色三角形实例的元数据。 验证响应的状态代码是否为 OK,以及是否返回了元数据。
从单个实例中检索一个或多个帧
此请求从单个实例中检索一个或多个帧。
详细信息:
- GET /studies/{study}/series/{series}/instances/{instance}/frames/{frames}
DicomWebResponse response = await client.RetrieveFramesAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, frames: new[] { 1 });
该响应应返回红色三角形中的唯一帧。 验证响应的状态代码是否为 OK,以及是否返回了该帧。
查询 DICOM (QIDO)
注意
有关支持的 DICOM 属性,请参阅 DICOM 一致性声明。
搜索检查
此请求按 DICOM 属性搜索一个或多个研究。
详细信息:
- GET /studies?StudyInstanceUID={study}
string query = $"/studies?StudyInstanceUID={studyInstanceUid}";
DicomWebResponse response = await client.QueryStudyAsync(query);
验证响应是否包含一个研究,以及响应代码是否正常。
搜索序列
此请求按 DICOM 属性搜索一个或多个系列。
详细信息:
- GET /series?SeriesInstanceUID={series}
string query = $"/series?SeriesInstanceUID={seriesInstanceUid}";
DicomWebResponse response = await client.QuerySeriesAsync(query);
验证响应是否包含一个系列,以及响应代码是否正常。
搜索研究中的系列
此请求按 DICOM 属性搜索单个研究中的一个或多个系列。
详细信息:
- GET /studies/{study}/series?SeriesInstanceUID={series}
string query = $"/studies/{studyInstanceUid}/series?SeriesInstanceUID={seriesInstanceUid}";
DicomWebResponse response = await client.QueryStudySeriesAsync(studyInstanceUid, query);
验证响应是否包含一个系列,以及响应代码是否正常。
搜索实例
此请求按 DICOM 属性搜索一个或多个实例。
详细信息:
- GET /instances?SOPInstanceUID={instance}
string query = $"/instances?SOPInstanceUID={sopInstanceUid}";
DicomWebResponse response = await client.QueryInstancesAsync(query);
验证响应是否包含一个实例,以及响应代码是否正常。
搜索研究中的实例
此请求按 DICOM 属性搜索单个研究中的一个或多个实例。
详细信息:
- GET /studies/{study}/instances?SOPInstanceUID={instance}
string query = $"/studies/{studyInstanceUid}/instances?SOPInstanceUID={sopInstanceUid}";
DicomWebResponse response = await client.QueryStudyInstanceAsync(studyInstanceUid, query);
验证响应是否包含一个实例,以及响应代码是否正常。
搜索研究和系列中的实例
此请求按 DICOM 属性搜索单个研究和单个系列中的一个或多个实例。
详细信息:
- GET /studies/{study}/series/{series}/instances?SOPInstanceUID={instance}
string query = $"/studies/{studyInstanceUid}/series/{seriesInstanceUid}/instances?SOPInstanceUID={sopInstanceUid}";
DicomWebResponse response = await client.QueryStudySeriesInstanceAsync(studyInstanceUid, seriesInstanceUid, query);
验证响应是否包含一个实例,以及响应代码是否正常。
删除 DICOM
注意
删除并不是 DICOM 标准的一部分,只是为了方便起见才添加的。
删除研究和系列中的特定实例
此请求删除单个研究和单个系列中单个实例。
详细信息:
- DELETE /studies/{study}/series/{series}/instances/{instance}
string sopInstanceUidRed = "1.2.826.0.1.3680043.8.498.47359123102728459884412887463296905395";
DicomWebResponse response = await client.DeleteInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUidRed);
此响应从服务器中删除红色三角形实例。 如果成功,响应状态代码不包含任何内容。
删除研究中的特定系列
此请求删除单个研究中的单个系列(以及所有子实例)。
详细信息:
- DELETE /studies/{study}/series/{series}
DicomWebResponse response = await client.DeleteSeriesAsync(studyInstanceUid, seriesInstanceUid);
该响应从服务器中删除绿色正方形实例(它是系列中唯一留下的元素)。 如果成功,响应状态代码不包含任何内容。
删除特定研究
此请求删除单个研究(以及所有子系列和实例)。
详细信息:
- DELETE /studies/{study}
DicomWebResponse response = await client.DeleteStudyAsync(studyInstanceUid);
该响应从服务器中删除蓝色圆圈实例(它是系列中唯一留下的元素)。 如果成功,响应状态代码不包含任何内容。
注意
DICOM® 是美国电气制造商协会的注册商标,适用于其有关医疗信息数字通信的标准出版物。