DCMTK、ITK、VTK读取dicom信息

DCMTK、ITK、VTK读取dicom影像数据的方法

直接上代码,调用不同的医学影像库读取dicom影像信息

1. DCMTK读取影像中的pixelData
//参数  list:为输入的图像文件名列表
bool DCMTKReadDicoms(QStringList list)
{
	DJDecoderRegistration::registerCodecs();
    DJEncoderRegistration::registerCodecs();
    DcmRLEEncoderRegistration::registerCodecs();
    DcmRLEDecoderRegistration::registerCodecs();
    
    DcmFileFormat dcmff_ ;
    DcmDataset *dset = dcmff_.getDataset();  
    DcmElement *element = nullptr;
    for (int i = 0; i < list.size(); i++)
    {
        OFCondition result;
        result = dcmff_.loadFile(list.at(i).toStdString().data());    

        dset->chooseRepresentation(EXS_LittleEndianImplicit, nullptr);
        result = dset->findAndGetElement(DCM_PixelData,
                                         element);   
        DcmPixelData *dpix = NULL;
        dpix = OFstatic_cast(DcmPixelData *, element);
        /* 因为我们有压缩数据,所以必须利用DcmPixelSequence
           以便以原始格式访问,例如解压缩
           使用外部库
         */
        DcmPixelSequence *dseq = NULL;
        E_TransferSyntax xferSyntax = EXS_Unknown;
        const DcmRepresentationParameter *rep = NULL;
        // 查找访问DCMTK中数据的正确表示所需的键 
        dpix->getOriginalRepresentationKey(xferSyntax, rep);
        // 访问原始数据表示并在像素序列内获得结果
        result = dpix->getEncapsulatedRepresentation(dset->getCurrentXfer(), rep, dseq);
        if ( result == EC_Normal )    //针对压缩数据的访问遍历
        {
            DcmPixelItem *pixitem = NULL;
            // 访问第一帧(跳过偏移表)
            dseq->getItem(pixitem, 1);
            if (pixitem == NULL)
                return 1;
            Uint8 *pixData = NULL;
            // 获取此像素项的长度(即片段,即大部分时间,帧的长度)
            Uint32 length = pixitem->getLength();
            if (length == 0)
                return 1;
            // 最后,获取此像素项的压缩数据 
            result = pixitem->getUint8Array(pixData);
            // 使用pixData执行一些有用的操作。。。(下方遍历访问了这些值)
            cv::Mat dst2(512, 512, CV_8UC1, cv::Scalar::all(0));
            unsigned short *data = nullptr;
            for (int i = 0; i < 512; i++)
            {
                data = dst2.ptr<unsigned short>
                       (i);   //取得每一行的头指针 也可使用dst2.at(i, j) = ?
                for (int j = 0; j < 512; j++)
                {
                    unsigned short temp = pixData[i * 512 + j];
                    qDebug() << temp;
                }
            }
        }
        else             //针对没有压缩数据的访问遍历
        {
            Uint16 *pixData16 = NULL;
            result = element->getUint16Array(pixData16);
            int slope, intercept;
            const char *value = nullptr;
            dset->findAndGetString(DCM_RescaleIntercept, value);
            intercept = QString::fromLatin1(value).toInt();

            dset->findAndGetString(DCM_RescaleSlope, value);
            slope = QString::fromLatin1(value).toInt();

            qDebug() << "intercept" << intercept
                     << "slope" << slope;

            cv::Mat dst2(512, 512, CV_16UC1, cv::Scalar::all(0));
            unsigned short *data = nullptr;
            for (int i = 0; i < 512; i++)
            {
                data = dst2.ptr<unsigned short>
                       (i);   //取得每一行的头指针 也可使用dst2.at(i, j) = ?
                for (int j = 0; j < 512; j++)
                {
                    unsigned short temp = pixData16[i * 512 + j];
                    qDebug() << temp;
                }
            }
        }
        if (result.bad())
            return 1;
        else
            return 0;
    }
    DJDecoderRegistration::cleanup();
}
是否存在压缩影像的判别:(具体的术语还不清楚,后续补上),可根据下方的两个示意图做初步了解

压缩影像tag信息:
在这里插入图片描述
未压缩影像tag信息:
在这里插入图片描述通过影像浏览工具中的tagid(7FE0,0010),即tag描述信息为Pixel Data的value是否为空并可判断影像是否被压缩。

2.VTK读取影像信息
bool VtkReadDicoms(QStringList list)
{
    QFileInfo info(list.at(0));
    vtkSmartPointer<vtkDICOMReader> reader =
        vtkSmartPointer<vtkDICOMReader>::New();
    vtkSmartPointer<vtkImageData> sliceData = vtkSmartPointer<vtkImageData>::New();
    reader->SetFileName(list.at(0).toStdString().c_str());
    reader->Update();
    sliceData = reader->GetOutput();
    qDebug() << "显示点的Dimensions" << sliceData->GetDimensions()[0] << ","
             << sliceData->GetDimensions()[1] << "," << sliceData->GetDimensions()[2];
    qDebug() << "显示点的个数" << sliceData->GetNumberOfPoints();
    int nbOfComp = sliceData->GetNumberOfScalarComponents();
    qDebug() << "通道" << nbOfComp;
    for (int i = 0; i < 512; i++)
    {
        data = dst2.ptr<signed short>
               (i);   //取得每一行的头指针 也可使用dst2.at(i, j) = ?
        for (int j = 0; j < 512; j++)
        {
            for (int k = 0; k < 1; k++)
            {
                signed short *pixel =
                    (signed short *) (sliceData->GetScalarPointer(i, j, k));
                qDebug() << *(pixel);
            }
        }
    }
}
3.ITK读取dicom图像
bool ReadDicom(const std::string &file_name,
                               InputImageType::Pointer &image)
{
    typedef itk::ImageFileReader<InputImageType> ReaderType;
    ReaderType::Pointer reader = ReaderType::New();
    typedef itk::GDCMImageIO  ImageIOType;
    ImageIOType::Pointer gdcmImageIO = ImageIOType::New();
    reader->SetFileName(file_name);
    reader->SetImageIO( gdcmImageIO );
    try
    {
        reader->Update();
    }
    catch (itk::ExceptionObject &)
    {
        return false;
    }
    image = reader->GetOutput();
    return true;
}

你可能感兴趣的:(c++,开发语言)