当前位置: 首页 > news >正文

在Windows系统中使用C++与Orthanc交互:基于DICOMweb的医学影像应用开发

在这里插入图片描述

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用,熟悉DICOM医学影像及DICOM协议,业余时间自学JavaScript,Vue,qt,python等,具备多种混合语言开发能力。撰写博客分享知识,致力于帮助编程爱好者共同进步。欢迎关注、交流及合作,提供技术支持与解决方案。
技术合作请加本人wx(注明来自csdn):xt20160813

在Windows系统中使用C++与Orthanc交互:基于DICOMweb的医学影像应用开发

在之前的文章中,我们详细探讨了Orthanc作为轻量级PACS服务器的核心功能、DICOMweb支持以及Python实现的示例代码。为了进一步扩展Orthanc的应用场景,本文将聚焦于在Windows系统中,使用**C++**开发与Orthanc交互的应用程序,重点展示如何通过DICOMweb接口实现医学影像的查询、检索和上传功能。文章将提供完整的C++示例代码,包含关键注释,并介绍Windows环境下的开发配置和注意事项。


一、为何选择C++与Orthanc交互

C++是一种高性能、跨平台的编程语言,广泛应用于医疗影像处理和PACS系统开发。结合Orthanc的DICOMweb接口,使用C++开发具有以下优势:

  • 高性能:C++的低级控制和内存管理适合处理大型DICOM数据集。
  • 跨平台兼容性:C++代码可轻松移植到Linux或其他系统。
  • 与DICOM库集成:C++与DCMTK、GDCM等DICOM库无缝集成,增强影像处理能力。
  • Windows生态支持:Windows是许多医院和开发环境的首选平台,C++在Windows下有成熟的开发工具链。

本文将使用C++通过HTTP请求与Orthanc的DICOMweb接口交互,展示如何实现QIDO-RS(查询)、WADO-RS(检索)和STOW-RS(上传)功能。


二、开发环境准备

1. 安装Orthanc

在Windows系统中,推荐使用Docker或直接下载预编译的Windows二进制包运行Orthanc:

  • Docker方式
    docker pull orthanc/orthanc
    docker run -p 8042:8042 -p 4242:4242 orthanc/orthanc
    
  • Windows二进制包
    从Orthanc官网(https://www.orthanc-server.com/download.php)下载Windows版本,解压后运行Orthanc.exe

默认配置下,Orthanc的REST API和DICOMweb接口运行在http://localhost:8042

2. C++开发工具

  • 编译器:Visual Studio 2022(社区版免费),支持C++17及以上。
  • HTTP客户端库:使用cpp-httplib,一个轻量级的C++ HTTP客户端库,适合与RESTful接口交互。
  • JSON解析库:使用nlohmann/json,便于处理DICOMweb返回的JSON数据。
  • DICOM处理库(可选):如DCMTK或GDCM,用于解析DICOM文件。

3. 安装依赖库

使用vcpkg(Visual Studio的包管理器)安装cpp-httplibnlohmann/json

# 安装vcpkg(如果尚未安装)
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg integrate install# 安装cpp-httplib和nlohmann/json
.\vcpkg install cpp-httplib
.\vcpkg install nlohmann-json

4. Visual Studio项目配置

  1. 创建一个新的C++空项目。
  2. 在项目属性中:
    • 添加vcpkg的头文件路径:vcpkg\installed\x64-windows\include
    • 添加vcpkg的库路径:vcpkg\installed\x64-windows\lib
    • 链接cpp-httplib.libnlohmann_json.lib(根据需要)。

三、C++实现DICOMweb功能

以下展示如何使用C++与Orthanc的DICOMweb接口交互,实现以下功能:

  1. QIDO-RS:查询DICOM研究。
  2. WADO-RS:检索DICOM元数据。
  3. STOW-RS:上传DICOM文件。

1. 前置代码:HTTP客户端封装

我们创建一个简单的HTTP客户端类,封装cpp-httplib的请求功能,并使用nlohmann/json解析响应。

#include <httplib.h>
#include <nlohmann/json.hpp>
#include <string>
#include <iostream>
#include <fstream>using json = nlohmann::json;// HTTP客户端类,封装与Orthanc的交互
class OrthancClient {
private:httplib::Client client;std::string dicomWebRoot;public:OrthancClient(const std::string& host, int port, const std::string& root = "/dicom-web"): client(host, port), dicomWebRoot(root) {client.set_connection_timeout(10); // 设置连接超时为10秒client.set_read_timeout(30);       // 设置读取超时为30秒}// 发送GET请求并返回JSON响应json get(const std::string& endpoint, const httplib::Params& params = {}) {auto res = client.Get((dicomWebRoot + endpoint).c_str(), params);if (res && res->status == 200) {return json::parse(res->body);}throw std::runtime_error("GET request failed: " + std::to_string(res ? res->status : -1));}// 发送POST请求上传DICOM文件bool postDicomFile(const std::string& endpoint, const std::string& filePath) {std::ifstream file(filePath, std::ios::binary);if (!file.is_open()) {throw std::runtime_error("Cannot open file: " + filePath);}// 读取文件内容std::vector<char> fileData((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());httplib::MultipartFormDataItems items = {{ "file", std::string(fileData.begin(), fileData.end()), std::filesystem::path(filePath).filename().string(), "application/dicom" }};auto res = client.Post((dicomWebRoot + endpoint).c_str(), items);return res && res->status == 200;}
};

代码注释

  • OrthancClient:封装HTTP客户端,初始化时指定Orthanc服务器的地址、端口和DICOMweb根路径。
  • get:发送GET请求,解析并返回JSON响应。
  • postDicomFile:发送POST请求,上传DICOM文件。

2. QIDO-RS:查询DICOM研究

以下代码展示如何查询患者ID为"12345"的DICOM研究。

void queryStudies(OrthancClient& client) {try {// 设置查询参数httplib::Params params = {{ "PatientID", "12345" },{ "00100020", "12345" } // 患者ID的DICOM标签};// 发送QIDO-RS请求json studies = client.get("/studies", params);// 解析并打印结果for (const auto& study : studies) {std::string studyUID = study["0020000D"]["Value"][0].get<std::string>();std::cout << "Study Instance UID: " << studyUID << std::endl;}} catch (const std::exception& e) {std::cerr << "Error in QIDO-RS: " << e.what() << std::endl;}
}

代码注释

  • params:设置查询条件,支持DICOM标签或标准字段。
  • client.get:发送GET请求到/dicom-web/studies端点。
  • 响应为JSON数组,包含匹配的研究信息。

3. WADO-RS:检索DICOM元数据

以下代码展示如何检索特定研究的元数据。

void retrieveMetadata(OrthancClient& client, const std::string& studyUID) {try {// 发送WADO-RS请求json metadata = client.get("/studies/" + studyUID + "/metadata");// 打印元数据(示例:Study Description)if (metadata.contains("00081030")) {std::string studyDesc = metadata["00081030"]["Value"][0].get<std::string>();std::cout << "Study Description: " << studyDesc << std::endl;}} catch (const std::exception& e) {std::cerr << "Error in WADO-RS: " << e.what() << std::endl;}
}

代码注释

  • /studies/{studyUID}/metadata:WADO-RS端点,返回研究的元数据。
  • metadata:JSON对象,包含DICOM标签及其值。

4. STOW-RS:上传DICOM文件

以下代码展示如何上传DICOM文件到Orthanc。

void uploadDicomFile(OrthancClient& client, const std::string& filePath) {try {// 发送STOW-RS请求bool success = client.postDicomFile("/studies", filePath);if (success) {std::cout << "DICOM file uploaded successfully: " << filePath << std::endl;} else {std::cerr << "Failed to upload DICOM file" << std::endl;}} catch (const std::exception& e) {std::cerr << "Error in STOW-RS: " << e.what() << std::endl;}
}

代码注释

  • postDicomFile:以multipart/form-data格式上传DICOM文件。
  • 成功上传后,Orthanc会解析并存储DICOM文件。

5. 主程序

以下是完整的程序入口,整合上述功能。

int main() {try {// 初始化Orthanc客户端OrthancClient client("localhost", 8042);// 查询研究std::cout << "Querying studies..." << std::endl;queryStudies(client);// 检索元数据std::string studyUID = "1.2.840.113619.2.55.3.60467153.1234.1234567890";std::cout << "\nRetrieving metadata for study: " << studyUID << std::endl;retrieveMetadata(client, studyUID);// 上传DICOM文件std::string dicomFile = "path/to/sample.dcm";std::cout << "\nUploading DICOM file: " << dicomFile << std::endl;uploadDicomFile(client, dicomFile);} catch (const std::exception& e) {std::cerr << "Main error: " << e.what() << std::endl;return 1;}return 0;
}

代码注释

  • 主程序初始化OrthancClient,依次调用查询、检索和上传功能。
  • 异常处理确保程序健壮性。

四、Windows系统下的注意事项

  1. 防火墙配置

    • 确保Orthanc的端口(默认8042和4242)未被Windows防火墙阻止。
    • 在Windows PowerShell中运行以下命令开放端口:
      netsh advfirewall firewall add rule name="Orthanc" dir=in action=allow protocol=TCP localport=8042,4242
      
  2. 文件路径

    • Windows使用反斜杠(\)作为路径分隔符,但在C++字符串中需转义为\\,或使用原始字符串(如R"(path\to\file)")。
    • 示例:"C:\\Users\\Username\\sample.dcm"
  3. 依赖库的DLL

    • 确保cpp-httplibnlohmann/json的动态链接库(.dll)在可执行文件的目录下,或已添加到系统PATH。
    • vcpkg会自动将DLL放置在vcpkg\installed\x64-windows\bin
  4. 字符编码

    • Orthanc的DICOMweb接口使用UTF-8编码,确保C++程序的字符串处理兼容UTF-8。
    • 在Visual Studio中,设置项目属性为“使用Unicode字符集”。
  5. 性能优化

    • 对于大规模DICOM文件上传,建议使用异步I/O或多线程以提高性能。
    • 调整cpp-httplib的超时参数,适应网络环境。

五、扩展:与DCMTK集成

若需解析或生成DICOM文件,可集成DCMTK库。以下是使用DCMTK读取DICOM文件并上传到Orthanc的示例:

1. 安装DCMTK

通过vcpkg安装DCMTK:

.\vcpkg install dcmtk

2. 示例代码:读取DICOM文件并上传

#include <dcmtk/dcmdata/dctk.h>void uploadDicomWithDCMTK(OrthancClient& client, const std::string& filePath) {try {// 使用DCMTK加载DICOM文件DcmFileFormat fileFormat;OFCondition status = fileFormat.loadFile(filePath.c_str());if (status.bad()) {throw std::runtime_error("Failed to load DICOM file: " + status.text());}// 验证DICOM文件有效性DcmDataset* dataset = fileFormat.getDataset();if (!dataset) {throw std::runtime_error("Invalid DICOM file");}// 上传文件client.postDicomFile("/studies", filePath);std::cout << "DICOM file validated and uploaded: " << filePath << std::endl;} catch (const std::exception& e) {std::cerr << "Error in DCMTK upload: " << e.what() << std::endl;}
}

代码注释

  • DcmFileFormat:加载DICOM文件并验证其格式。
  • 在上传前,DCMTK可用于提取元数据或进行预处理(如匿名化)。

六、实际应用场景

  1. 医院影像工作站

    • 开发Windows桌面应用,通过DICOMweb从Orthanc检索影像并显示。
    • 使用C++结合OpenGL或VTK实现影像渲染。
  2. 自动化影像处理

    • 开发批量上传DICOM文件的工具,结合DCMTK进行元数据验证。
    • 实现影像匿名化后上传到Orthanc。
  3. 远程诊断系统

    • 开发C++服务端程序,通过DICOMweb实时查询和传输影像到远程客户端。

七、总结

通过C++在Windows系统中与Orthanc的DICOMweb接口交互,开发者可以构建高性能、可靠的医学影像应用。本文提供的示例代码展示了查询、检索和上传DICOM文件的核心功能,并通过DCMTK扩展了DICOM文件处理能力。结合Windows的开发工具链和Orthanc的轻量级特性,C++开发者能够快速实现从桌面应用到服务器端服务的多种场景。

对于更复杂的应用,建议进一步探索Orthanc的插件系统或与其他影像处理库(如ITK、VTK)集成。

参考资源

  • Orthanc官方文档:https://book.orthanc-server.com/
  • cpp-httplib GitHub:https://github.com/yhirose/cpp-httplib
  • nlohmann/json GitHub:https://github.com/nlohmann/json
  • DCMTK官方文档:https://dicom.offis.de/

相关文章:

  • Cribl 中 Parser 扮演着重要的角色 + 例子
  • 【Auto-dl ssh隧道,TensorBoard】
  • FreeRTOS学习笔记【11】-----任务列表
  • 打卡day31
  • 计算机网络基础概念
  • Gas优化利器:Merkle 树如何助力链上数据效率革命
  • ubuntu下docker安装mongodb-支持单副本集
  • 磁盘空间不足,迁移Docker 数据目录
  • 基于自然语言转SQL的BI准确率如何?
  • 《算法笔记》11.8小节——动态规划专题->总结 问题 D: Coincidence
  • linux下jenkins部署安装使用
  • 【图像大模型】Stable Video Diffusion:基于时空扩散模型的视频生成技术深度解析
  • 【HTML-2】HTML 标题标签:构建网页结构的基础
  • 设计模式之备忘录模式
  • 如何使用通义灵码玩转Python - AI编程助手提升效率
  • windows安装WS,实测可行
  • Prompt Tuning:轻量级大模型微调全攻略
  • Python | 库存覆盖天数【待续】
  • 理解阿里云的MQTT
  • Python类的力量:第六篇:设计模式——Python面向对象编程的“架构蓝图”
  • 携程:今年第一季度营业收入约138亿元,入境旅游预订同比增长超100%
  • 凤阳县鼓楼四周连夜搭起围挡,安徽省文物局已介入调查
  • 河北6人在河道倒污泥被控污染环境案撤诉后,已拿到国赔决定书
  • 出生于1991年,石秀清拟提名为铜陵市辖县(区)政府副县(区)长人选
  • 重庆一男大学生掉进化粪池死亡,重庆对外经贸学院:以学校通报为准
  • 昆明一小区火灾调查报告:七旬夫妇身亡,生前拾荒存放大量可燃物