DCMTK 库说在 dcmdump 显示时找不到标签
DCMTK library says tag not found while dcmdump displays it
我的程序,对于使用 DCMTK 3.6.4-2 的 Ubuntu 20 系统,读取一个 dicom 文件(系列)并从相应的标签中获取比例斜率,首先测试它们是否存在:
tmpfile.loadFile ( filename );
tmpdata = tmpfile.getDataset();
tmpdata -> findAndGetOFString ( DCM_RescaleSlope, tmpstring );
if ( !tmpstring.empty() ) {
mydcm.scl_slope = static_cast <float> ( stof ( std::string ( tmpstring.c_str() ) ) );
tmpdata -> findAndGetOFString ( DCM_RescaleIntercept, tmpstring );
mydcm.scl_inter = static_cast <float> ( stof ( std::string ( tmpstring.c_str() ) ) );
} else {
tmpdata -> findAndGetOFString ( DCM_RealWorldValueSlope, tmpstring );
mydcm.scl_slope = static_cast <float> ( stof ( std::string ( tmpstring.c_str() ) ) );
tmpdata -> findAndGetOFString ( DCM_RealWorldValueIntercept, tmpstring );
mydcm.scl_inter = static_cast <float> ( stof ( std::string ( tmpstring.c_str() ) ) );
}
在我使用的文件中,dcmdump 对 DCM_RescaleSlope
标签没有 return 任何东西,但它对 DCM_RealWorldValueSlope
标签有任何作用:
dcmdump filename | grep RealWorld
(0040,9096) SQ (Sequence with undefined length #=1) # u/l, 1 RealWorldValueMappingSequence
(0040,9224) FD 0 # 8, 1 RealWorldValueIntercept
(0040,9225) FD 4.1318681318681323 # 8, 1 RealWorldValueSlope
当我使用
std::cout << getItemString ( tmpdata, DCM_RescaleSlope ) << std::endl;
std::cout << getItemString ( tmpdata, DCM_RealWorldValueSlope ) << std::endl;
std::cout << getItemString ( tmpdata, DCM_Modality ) << std::endl;
(其中 getItemString
是方便的函数)并使用调试器查看第二行发生了什么,然后:
- 标签转换为
g = 64
、e = 37413
- 第
OFStatus s = theCondition.theStatus;
行设置为false
(仅此而已,除了 theText = "Tag not found"
)
我不明白,因为 (i) 标签的值是程序已知的——否则它不会编译,(ii) 标签在图像中,如 dcmdump
和 (iii) 其他标签处理正常:DCM_Modality
打印为 MR
.
是我做错了什么,还是这些特殊标签需要特殊处理?
编辑
我尝试了评论中的一个建议:在测试中使用 findAndGetFloat64
而不是 findAndGetOFString
double tmpdbl;
tmpdata -> findAndGetFloat64 ( DCM_RescaleSlope, tmpdbl );
std::cout << "A" << tmpdbl << std::endl;
tmpdata -> findAndGetFloat64 ( DCM_RealWorldValueSlope, tmpdbl );
std::cout << "B" << tmpdbl << std::endl;
tmpdata -> findAndGetFloat64 ( DCM_AcquisitionDuration, tmpdbl );
std::cout << "C" << tmpdbl << std::endl;
这导致
A0
B0
C297.6
并且在读取 B
的行中 theStatus
中的错误仍然是相同的:theText = "Tag not found"
(我一直在使用字符串,因为到目前为止大多数双值标签都是 DS
,感谢您让我意识到其中的区别!)
您要查找的标签在一个序列中 (RealWorldValueMappingSequence
)。要获取标签,您首先必须获取序列,如下所示:
DcmSequenceOfItems* sequence;
OFResult result = tmpData->findAndGetSequence(DCM_RealWorldValueMappingSequence, sequence);
if (result.good() && sequence && !sequence->isEmpty())
{
DcmItem* item = sequence->getItem(0); // you may have to iterate over the items instead
double value;
result = item->findAndGetFloat64(DCM_RealWorldValueSlope, value);
...
}
请注意,这是我的想法,所以它可能不准确,但这基本上是您获取序列项内的标签所需要做的。默认情况下,所有 findAndGet...
方法仅适用于当前项目,它可能是根数据集,但也可能是序列项目 - 您必须在 DICOM 标准中检查实际找到标签的位置。
更新:
写完之后,我才意识到我忘记了 searchIntoSub
参数,所以可能这样做就足够了:
result = tmpData->findAndGetFloat64(DCM_RealWorldValueSlope, value, 0, OFTrue);
其中 searchIntoSub=OfTrue
意味着,包含的序列也被搜索。
无论如何,我保留上面的内容,因为如果按特定顺序搜索标签,其他人可能也需要它。
旁注:
如果您使用此参数,您使用 findAndGetOFString
的第一种方法也应该有效。它在您的情况下没有意义,因为您需要实际的双精度值,但如果您只需要标记值的字符串表示形式,则可以使用它。来自 findAndGetOFString
的文档:
Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV
我的程序,对于使用 DCMTK 3.6.4-2 的 Ubuntu 20 系统,读取一个 dicom 文件(系列)并从相应的标签中获取比例斜率,首先测试它们是否存在:
tmpfile.loadFile ( filename );
tmpdata = tmpfile.getDataset();
tmpdata -> findAndGetOFString ( DCM_RescaleSlope, tmpstring );
if ( !tmpstring.empty() ) {
mydcm.scl_slope = static_cast <float> ( stof ( std::string ( tmpstring.c_str() ) ) );
tmpdata -> findAndGetOFString ( DCM_RescaleIntercept, tmpstring );
mydcm.scl_inter = static_cast <float> ( stof ( std::string ( tmpstring.c_str() ) ) );
} else {
tmpdata -> findAndGetOFString ( DCM_RealWorldValueSlope, tmpstring );
mydcm.scl_slope = static_cast <float> ( stof ( std::string ( tmpstring.c_str() ) ) );
tmpdata -> findAndGetOFString ( DCM_RealWorldValueIntercept, tmpstring );
mydcm.scl_inter = static_cast <float> ( stof ( std::string ( tmpstring.c_str() ) ) );
}
在我使用的文件中,dcmdump 对 DCM_RescaleSlope
标签没有 return 任何东西,但它对 DCM_RealWorldValueSlope
标签有任何作用:
dcmdump filename | grep RealWorld
(0040,9096) SQ (Sequence with undefined length #=1) # u/l, 1 RealWorldValueMappingSequence
(0040,9224) FD 0 # 8, 1 RealWorldValueIntercept
(0040,9225) FD 4.1318681318681323 # 8, 1 RealWorldValueSlope
当我使用
std::cout << getItemString ( tmpdata, DCM_RescaleSlope ) << std::endl;
std::cout << getItemString ( tmpdata, DCM_RealWorldValueSlope ) << std::endl;
std::cout << getItemString ( tmpdata, DCM_Modality ) << std::endl;
(其中 getItemString
是方便的函数)并使用调试器查看第二行发生了什么,然后:
- 标签转换为
g = 64
、e = 37413
- 第
OFStatus s = theCondition.theStatus;
行设置为false (仅此而已,除了theText = "Tag not found"
)
我不明白,因为 (i) 标签的值是程序已知的——否则它不会编译,(ii) 标签在图像中,如 dcmdump
和 (iii) 其他标签处理正常:DCM_Modality
打印为 MR
.
是我做错了什么,还是这些特殊标签需要特殊处理?
编辑
我尝试了评论中的一个建议:在测试中使用 findAndGetFloat64
而不是 findAndGetOFString
double tmpdbl;
tmpdata -> findAndGetFloat64 ( DCM_RescaleSlope, tmpdbl );
std::cout << "A" << tmpdbl << std::endl;
tmpdata -> findAndGetFloat64 ( DCM_RealWorldValueSlope, tmpdbl );
std::cout << "B" << tmpdbl << std::endl;
tmpdata -> findAndGetFloat64 ( DCM_AcquisitionDuration, tmpdbl );
std::cout << "C" << tmpdbl << std::endl;
这导致
A0
B0
C297.6
并且在读取 B
的行中 theStatus
中的错误仍然是相同的:theText = "Tag not found"
(我一直在使用字符串,因为到目前为止大多数双值标签都是 DS
,感谢您让我意识到其中的区别!)
您要查找的标签在一个序列中 (RealWorldValueMappingSequence
)。要获取标签,您首先必须获取序列,如下所示:
DcmSequenceOfItems* sequence;
OFResult result = tmpData->findAndGetSequence(DCM_RealWorldValueMappingSequence, sequence);
if (result.good() && sequence && !sequence->isEmpty())
{
DcmItem* item = sequence->getItem(0); // you may have to iterate over the items instead
double value;
result = item->findAndGetFloat64(DCM_RealWorldValueSlope, value);
...
}
请注意,这是我的想法,所以它可能不准确,但这基本上是您获取序列项内的标签所需要做的。默认情况下,所有 findAndGet...
方法仅适用于当前项目,它可能是根数据集,但也可能是序列项目 - 您必须在 DICOM 标准中检查实际找到标签的位置。
更新:
写完之后,我才意识到我忘记了 searchIntoSub
参数,所以可能这样做就足够了:
result = tmpData->findAndGetFloat64(DCM_RealWorldValueSlope, value, 0, OFTrue);
其中 searchIntoSub=OfTrue
意味着,包含的序列也被搜索。
无论如何,我保留上面的内容,因为如果按特定顺序搜索标签,其他人可能也需要它。
旁注:
如果您使用此参数,您使用 findAndGetOFString
的第一种方法也应该有效。它在您的情况下没有意义,因为您需要实际的双精度值,但如果您只需要标记值的字符串表示形式,则可以使用它。来自 findAndGetOFString
的文档:
Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV