视频教程:一种简单的Dicom图像显示和保存的方法(利用dcmtk库和opencv库)
Git: https://github.com/JasonLiThirty/Dicom
opencv的下载
- 官网:https://opencv.org/releases/,下载最新版本4.3.0
- 安装即解压:
Dicom_Module工程配置opencv库
- 配置系统的环境变量Path:把之前解压(安装)好的opencv路径下的x64的bin路径添加到Path系统环境变量中,重启。
- 在Dicom_Module工程配置中加入opencv的include路径和lib路径。
- 在工程配置的linker->input里加入opencv的依赖lib,Debug配置opencv_world430d.lib,Relase配置opencv_world430.lib,这两个lib文件在opencv\build\x64\vc14\lib下。
- 将opencv\build\x64\vc14\bin目录下的opencv_world430.dll和opencv_world430d.dll拷贝到工程的输出目录下。
Dicom_Module工程配置dcmimgle和dcmimage库
- 在工程配置的linker->input里加入dcmimgle和dcmimage的依赖lib
-
将最先编译出的DCMTK类包中bin目录下的dcmimgle.dll和dcmimage.dll拷贝到工程的输出目录下。
Dicom_Module工程里编写所需类和函数
接口类DicomIF
- 新增显示图像和保存图像为BMP的接口
class __declspec(dllexport) IDicom
{
public:
...
virtual bool ShowImage(std::string filePath, Image_Pattern pattern = ImagePattern_Normal, signed int degree = 0) = 0;
virtual bool SavetoBMP(std::string filePath, Image_Pattern pattern = ImagePattern_Normal, signed int degree = 0) = 0;
...
}
实现类DicomProcessor
- 新增显示图像和保存图像为BMP的实现(头文件包含dcmimage.h)
#include "dcmtk/dcmimgle/dcmimage.h"
bool ShowImage(std::string filePath, Image_Pattern pattern = ImagePattern_Normal, signed int degree = 0);
bool SavetoBMP(std::string filePath, Image_Pattern pattern = ImagePattern_Normal, signed int degree = 0);
bool DicomProcessor::ShowImage(std::string filePath, Image_Pattern pattern, signed int degree)
{
if (!Read(filePath))
{
std::cout << "Read Dicom File Failed: " << filePath.c_str() << std::endl;
return false;
}
E_TransferSyntax tfs = m_fileformat.getDataset()->getOriginalXfer();
DicomImage *pImage = new DicomImage(&m_fileformat, tfs);
pImage->setWindow(m_image->WindowCenter, m_image->WindowWidth);
PatternConversion(pImage, pattern, degree);
Uint16 *pixelData = (Uint16*)(pImage->getOutputData(m_image->BitsAllocated));
if (pixelData == NULL)
{
std::cout << "Get Image Data Failed: " << filePath.c_str() << std::endl;
return false;
}
cv::Mat dst(pImage->getWidth(), pImage->getHeight(), CV_16U, pixelData);
cv::imshow(m_patient->PatientsName, dst);
cv::waitKey(0);
return true;
}
bool DicomProcessor::SavetoBMP(std::string filePath, Image_Pattern pattern, signed int degree)
{
if (!Read(filePath))
{
std::cout << "Read Dicom File Failed: " << filePath.c_str() << std::endl;
return false;
}
E_TransferSyntax tfs = m_fileformat.getDataset()->getOriginalXfer();
DicomImage *pImage = new DicomImage(&m_fileformat, tfs);
pImage->setWindow(m_image->WindowCenter, m_image->WindowWidth);
PatternConversion(pImage, pattern, degree);
if (!pImage->writeBMP(GenerateImageName(filePath, pattern).c_str(), 8))
{
std::cout << "Read Dicom File Failed: " << filePath.c_str() << std::endl;
return false;
}
return true;
}
- 新增图像变换函数
void PatternConversion(DicomImage* &image, Image_Pattern pattern, signed int degree = 0);
void DicomProcessor::PatternConversion(DicomImage* &image, Image_Pattern pattern, signed int degree)
{
switch (pattern)
{
case ImagePattern_Normal:
break;
case ImagePattern_Flip:
image->flipImage();
break;
case ImagePattern_Rotate:
image->rotateImage(degree);
break;
case ImagePattern_Polarity:
image->setPolarity(EPP_Reverse);
break;
default:
break;
}
}
DicomInfo:加入图像变换类型定义
enum Image_Pattern
{
ImagePattern_Normal = 1,
ImagePattern_Flip,
ImagePattern_Rotate,
ImagePattern_Polarity
};
DicomUtils:加入生成BMP文件名的函数
__declspec(dllexport) std::string GenerateImageName(std::string name, Image_Pattern pattern);
std::string GenerateImageName(std::string name, Image_Pattern pattern)
{
std::string prefix = "";
switch (pattern)
{
case ImagePattern_Normal:
break;
case ImagePattern_Flip:
prefix = "_flip";
break;
case ImagePattern_Rotate:
prefix = "_rotate";
break;
case ImagePattern_Polarity:
prefix = "_polarity";
break;
default:
break;
}
auto last_pos = name.find_last_of(".");
std::string srcName = name.substr(0, last_pos);
std::cout << srcName << std::endl;
std::string fileName = srcName + prefix + ".bmp";
return fileName;
}
Dicom_Sample加入调用代码
int main()
{
CreateDicomProcessor();
std::string readFile = "E:\\Learning\\DICOM\\Module_Sample\\MRBRAIN.dcm";
//if (!GetDicomProcessor()->ShowImage(readFile, ImagePattern_Flip))
//if (!GetDicomProcessor()->ShowImage(readFile, ImagePattern_Rotate, 90));
//if (!GetDicomProcessor()->ShowImage(readFile, ImagePattern_Polarity))
if (!GetDicomProcessor()->ShowImage(readFile))
{
std::cout << "Read Dicom Image Failed: " << readFile.c_str() << std::endl;
return -1;
}
if (!GetDicomProcessor()->SavetoBMP(readFile))
//if (!GetDicomProcessor()->SavetoBMP(readFile, ImagePattern_Flip))
//if (!GetDicomProcessor()->SavetoBMP(readFile, ImagePattern_Rotate, 90))
//if (!GetDicomProcessor()->SavetoBMP(readFile, ImagePattern_Polarity))
{
std::cout << "Read Dicom Image Failed: " << readFile.c_str() << std::endl;
return -1;
}
DeleteDicomProcessor();
return 0;
}