DICOM(Digital Imaging and Communications in Medicine)是一种用于在医学成像设备和其他相关系统之间传输和存储医疗图像和信息的标准。DICOM标准定义了一组服务,这些服务通过网络或介质传输来进行通信。这些服务中,SCU(Service Class User)和SCP(Service Class Provider)是两个关键角色,分别代表服务的用户和提供者。
DICOM通信通过这些操作(C-ECHO、C-STORE、C-FIND、C-MOVE)来实现医疗图像和信息在不同设备和系统之间的传输和存储。每个操作都有明确的流程和角色定义,确保数据能够可靠地传输和存储,同时支持设备之间的互操作性。
文章后面有涉及到AE Title的管理,scu端实现,scp端的实现;worklist的查询服务实现;dicom文件的解析;dicom文件传输交互等等。
以下是DICOM影像通信中常用的一些操作及其详细介绍:
1. C-ECHO(验证服务)
C-ECHO 服务用于验证两台DICOM设备之间的通信连接。
- SCU:发送C-ECHO请求以验证连接。
- SCP:接收请求并返回C-ECHO响应。
示例场景:
- SCU:发送一个C-ECHO请求到SCP。
- SCP:接收请求并返回一个成功或失败的响应。
SCU -- C-ECHO-RQ --> SCP
SCU <-- C-ECHO-RSP -- SCP
2. C-STORE(存储服务)
C-STORE 服务用于将DICOM图像或其他数据对象从SCU传输到SCP进行存储。
- SCU:发送C-STORE请求以存储图像。
- SCP:接收图像并存储,然后返回C-STORE响应。
示例场景:
- SCU:从扫描仪获取图像,并发送C-STORE请求到PACS系统。
- SCP:接收图像并存储到数据库,返回存储成功或失败的响应。
SCU -- C-STORE-RQ --> SCP
SCU <-- C-STORE-RSP -- SCP
3. C-FIND(查询服务)
C-FIND 服务用于在DICOM数据库中查询匹配特定条件的DICOM对象。
- SCU:发送C-FIND请求以查询数据。
- SCP:接收请求,执行查询,并返回匹配的结果。
示例场景:
- SCU:发送C-FIND请求以查找特定患者的所有图像。
- SCP:在数据库中执行查询,返回匹配的图像信息。
SCU -- C-FIND-RQ --> SCP
SCU <-- C-FIND-RSP -- SCP
4. C-MOVE(移动服务)
C-MOVE 服务用于在不同DICOM设备之间移动DICOM对象。
- SCU:发送C-MOVE请求以将数据从一个设备移动到另一个设备。
- SCP:接收请求,找到数据并将其发送到目标设备。
示例场景:
- SCU:发送C-MOVE请求以将图像从PACS系统移动到工作站。
- SCP:从存储中检索图像,并发送到指定的目标设备(例如工作站)。
SCU -- C-MOVE-RQ --> SCP
SCP -- C-STORE-RQ --> 目标设备
目标设备 -- C-STORE-RSP --> SCP
SCU <-- C-MOVE-RSP -- SCP
详细操作步骤
C-ECHO:
- SCU发送C-ECHO请求到SCP。
- SCP接收请求并返回C-ECHO响应,指示连接是否成功。
C-STORE:
- SCU获取要存储的DICOM图像。
- SCU发送C-STORE请求和图像数据到SCP。
- SCP接收图像并存储。
- SCP返回C-STORE响应,指示存储是否成功。
C-FIND:
- SCU构建查询条件并发送C-FIND请求到SCP。
- SCP接收请求并在数据库中执行查询。
- SCP逐个返回匹配的结果。
- SCU接收查询结果。
C-MOVE:
- SCU发送C-MOVE请求到SCP,指定目标设备。
- SCP接收请求并检索匹配的数据。
- SCP通过C-STORE将数据发送到目标设备。
- 目标设备接收并存储数据,返回C-STORE响应到SCP。
- SCP返回C-MOVE响应到SCU,指示移动操作是否成功。
代码实现
(1)c-echo
(2)c-store
(3)c-find
(4)c-move
示例代码:
public IEnumerable<DicomCFindResponse> OnCFindRequest(DicomCFindRequest request)
{
request.Dataset.WriteToConsole();
DicomStatus status = DicomStatus.Success;
List<DicomCFindResponse> list = new List<DicomCFindResponse>();
try
{
if (UserCustomCFindRequestHandle != null)
{
IList<DicomDataset> data = UserCustomCFindRequestHandle(request);
if (data != null)
{
foreach (var one in data)
{
DicomCFindResponse rsp = new DicomCFindResponse(request, DicomStatus.Pending);
rsp.Dataset = one;
list.Add(rsp);
}
}
else
{
status = DicomStatus.QueryRetrieveOutOfResources;
}
}
}
catch (Exception ex)
{
logger.Instance.Error(ex.ToString());
list.Clear();
status = DicomStatus.ProcessingFailure;
}
list.Add(new DicomCFindResponse(request, status));
return list;
}