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

杭州 高端网站建设西安网站seo工作室

杭州 高端网站建设,西安网站seo工作室,易企秀h5制作免费,网站手机版怎么制作作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 前言 ‌‌DICOM(Digital Imaging and Communications in Medicine)是医学影像领域的标准格式&#xff0c…

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

前言

       ‌‌DICOM(Digital Imaging and Communications in Medicine)是医学影像领域的标准格式,广泛应用于X光、CT、MRI等医学图像。本文将介绍如何使用DCMTK库提取 DICOM 图像数据,并结合 OpenCV 实现图像显示与交互功能。

环境准备

Windows下用CMake编译DCMTK及配置测试-CSDN博客

功能说明

       本程序基于DCMTK和OpenCV实现以下核心功能:

  1. 加载DICOM文件:提取DICOM文件的路径和序列号,按序列号进行排序。
  2. 解析DICOM图像数据并显示:使用DCMTK读取图像数据,并用OpenCV显示出来。
  3. 图像增强对比度:图像应用对数变换,使图像清晰。
  4. 导航功能:切换DICOM图像。

使用说明

  1. 需安装DCMTK库及OPENCV库。
  2. 将main函数中DicomData替换你的DICOM数据路径。
  3. 使用C++17特性。 如果设置不成功,解决方法参见:解决方案:__cplusplus宏的值始终为199711L(即 C++98)_199711 c++-CSDN博客

完整代码

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <filesystem>
#include <cmath>// DCMTK头文件
#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dctk.h"         //DcmFileFormat
#include "dcmtk/dcmimgle/dcmimage.h"    //DicomImage
#include "dcmtk/dcmjpeg/djdecode.h"     //DJDecoderRegistration// OpenCV头文件
#include <opencv2/opencv.hpp>namespace fs = std::filesystem;
using namespace std;// 存储DICOM文件路径和对应的InstanceNumber
struct DicomFileInfo {std::string filePath;int instanceNumber;DicomFileInfo() : instanceNumber(-1) {}DicomFileInfo(const std::string& path, int number) : filePath(path), instanceNumber(number) {}bool operator<(const DicomFileInfo& other) const {return instanceNumber < other.instanceNumber;}
};// DICOM数据显示
class DicomViewer {
private:std::vector<DicomFileInfo> dicomFiles;size_t currentIndex;cv::Mat currentImage;std::string windowName;public:DicomViewer() : currentIndex(0) {}// 加载DICOM文件并排序bool loadDicomDirectory(const std::string& directory) {dicomFiles.clear();try {std::vector<std::string> filePaths;// 提取所有DICOM文件for (const auto& entry : fs::directory_iterator(directory)) {if (entry.is_regular_file()) {std::string ext = entry.path().extension().string();std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);if (ext == ".dcm" || ext == ".dicm" || ext == ".dicom") {filePaths.push_back(entry.path().string());}}}// 提取DICOM文件的序列号for (const auto& filePath : filePaths) {DcmFileFormat fileFormat;OFCondition status = fileFormat.loadFile(filePath.c_str());if (status.good()) {DcmDataset* dataset = fileFormat.getDataset();OFString strInstanceNumber;if (dataset->findAndGetOFString(DCM_InstanceNumber, strInstanceNumber).good()) {int instanceNumber = atoi(strInstanceNumber.c_str());dicomFiles.emplace_back(filePath, instanceNumber);}else {dicomFiles.emplace_back(filePath, -1);std::cerr << "警告: 文件 " << filePath << " 缺少InstanceNumber标签" << std::endl;}}else {std::cerr << "无法加载文件: " << filePath << " - 错误: " << status.text() << std::endl;}}// 排序std::sort(dicomFiles.begin(), dicomFiles.end());/*std::cout << "\n按InstanceNumber排序后的文件列表 (" << dicomFiles.size() << "个):" << std::endl;for (size_t i = 0; i < dicomFiles.size(); ++i) {std::cout << "[" << i + 1 << "] InstanceNumber: "<< (dicomFiles[i].instanceNumber >= 0 ? std::to_string(dicomFiles[i].instanceNumber) : "缺失")<< " - 文件: " << dicomFiles[i].filePath << std::endl;}*/}catch (const fs::filesystem_error& e) {std::cerr << "文件系统错误: " << e.what() << std::endl;return false;}if (dicomFiles.empty()) {std::cout << "未找到DICOM文件" << std::endl;return false;}std::cout << "\n成功加载并排序 " << dicomFiles.size() << " 个DICOM文件" << std::endl;return true;}// 对图像应用对数变换增强对比度cv::Mat applyLogTransform(const cv::Mat& input) {if (input.empty()) return cv::Mat();cv::Mat floatImage;input.convertTo(floatImage, CV_32F, 1.0 / 255.0); // 归一化到[0,1]cv::Mat logImage;cv::log(floatImage + 1, logImage); // 对数变换: log(1 + image)// 归一化到[0,1]double minVal, maxVal;cv::minMaxLoc(logImage, &minVal, &maxVal);cv::Mat result;if (maxVal > minVal) {logImage = (logImage - minVal) / (maxVal - minVal);}// 转换回8位无符号整型result = logImage * 255;result.convertTo(result, CV_8U);return result;}// 从DICOM文件提取图像数据bool loadDicomImage(const std::string& filePath) {DicomImage* dcmImage = new DicomImage(filePath.c_str());std::cout << "加载文件: " << filePath << std::endl;if (dcmImage == nullptr || dcmImage->getStatus() != EIS_Normal) {std::cerr << "图像加载失败: " << filePath<< " - 错误: " << DicomImage::getString(dcmImage->getStatus()) << std::endl;delete dcmImage;return false;}// 处理图像数据unsigned long width = dcmImage->getWidth();unsigned long height = dcmImage->getHeight();cv::Mat tempImage;if (dcmImage->isMonochrome()) {if (dcmImage->getOutputData(8)) {tempImage = cv::Mat(height, width, CV_8UC1);dcmImage->getOutputData(tempImage.data, width * height, 8);}else if (dcmImage->getOutputData(16)) {tempImage = cv::Mat(height, width, CV_16UC1);dcmImage->getOutputData(tempImage.data, width * height, 16);cv::Mat displayImage;cv::normalize(tempImage, displayImage, 0, 255, cv::NORM_MINMAX, CV_8UC1);tempImage = displayImage;}else {std::cerr << "不支持的像素格式" << std::endl;delete dcmImage;return false;}}else {tempImage = cv::Mat(height, width, CV_8UC3);dcmImage->getOutputData(tempImage.data, width * height * 3, 24);}delete dcmImage;// 应用对数变换增强对比度if (tempImage.channels() == 1) {currentImage = applyLogTransform(tempImage);}else {// 彩色图像转换为灰度图后应用对数变换cv::Mat grayImage;cv::cvtColor(tempImage, grayImage, cv::COLOR_BGR2GRAY);currentImage = applyLogTransform(grayImage);}return true;}// 显示当前图像(单窗口)bool displayCurrentImage() {if (dicomFiles.empty()) return false;if (loadDicomImage(dicomFiles[currentIndex].filePath)) {windowName = "DICOM Viewer";cv::imshow(windowName, currentImage);return true;}return false;}// 导航功能bool nextImage() {if (dicomFiles.empty()) return false;currentIndex = (currentIndex + 1) % dicomFiles.size();return displayCurrentImage();}bool prevImage() {if (dicomFiles.empty()) return false;currentIndex = (currentIndex - 1 + dicomFiles.size()) % dicomFiles.size();return displayCurrentImage();}size_t getCurrentIndex() const { return currentIndex; }size_t getTotalFiles() const { return dicomFiles.size(); }
};int main() {std::string dicomDir = "DicomData"; // 替换为实际路径DJDecoderRegistration::registerCodecs();DicomViewer viewer;if (!viewer.loadDicomDirectory(dicomDir)) return 1;if (!viewer.displayCurrentImage()) return 1;std::cout << "\n操作说明:" << std::endl;std::cout << "  n: 下一张  |  p: 上一张  |  q: 退出" << std::endl;char key = 0;while (key != 'q') {key = cv::waitKey(0);switch (key) {case 'n': viewer.nextImage(); break;case 'p': viewer.prevImage(); break;case 'q': break;default: std::cout << "未知按键,请使用 n/p/q" << std::endl;}}cv::destroyAllWindows();DJDecoderRegistration::cleanup();return 0;
}

测试效果 

​读取DICOM序列

显示图像

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

http://www.dtcms.com/wzjs/63262.html

相关文章:

  • 深圳制作网站的公司哪家好连云港百度推广总代理
  • 学而思最早是做网站的吗科技公司网站制作公司
  • 公司做网站的发票能抵扣吗百度竞价广告的位置
  • 网站公安局备案规定代写企业软文
  • 黑群辉做web下载网站百度端口开户推广
  • 山西网站建设推广百度站长之家工具
  • 榆社网站建设百度竞价客服
  • 校园网站界面建设免费注册推广网站
  • 网站建设存在的问题及建议今日热搜榜
  • 谷歌做英文网站深圳抖音推广公司
  • 如何注册域名免费搜索引擎优化排名
  • 网站首页图片分辨率网站建设推广专家服务
  • 有什么网站专做买生活污水设备开封网站优化公司
  • 顺德网站建设渠道昆山网站建设推广
  • wordpress网站数据迁移巨量引擎官网
  • 领手工在家做的网站绍兴seo计费管理
  • 网站开发持续更新如何自己建网站
  • 潮汕美食网站怎么做seo是什么字
  • 网站做短视频业务许可性价比高的seo网站优化
  • 个人做网站如何赚钱吗什么时候友情链接
  • 哪个网站可以做付费推广百度如何发布作品
  • 乌鲁木齐网架公司360优化大师官方下载
  • 供应链管理的主要内容长沙seo行者seo09
  • 免费b站有哪些长沙疫情最新消息今天封城了
  • 网站建设宗旨百度seo排名优化教程
  • java可以做网站么网站免费网站免费
  • 个人网站做企业网站高级搜索引擎技巧
  • 北京做网站哪家公司好南通网络推广
  • 广州专业网站优化公司班级优化大师网页版登录
  • 优化好的网站做企业网站全网整合营销推广