简体   繁体   English

DCMTK 库在 dcmdump 显示标签时说未找到标签

[英]DCMTK library says tag not found while dcmdump displays it

My program, for a Ubuntu 20 system using DCMTK 3.6.4-2, reads a dicom file (series) and gets the scale slopes from the corresponding tags, testing first whether they exist:我的程序,对于使用 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() ) ) );
}

In the file I use, dcmdump does not return anything for the DCM_RescaleSlope tag, but it does for the DCM_RealWorldValueSlope tag:在我使用的文件中,dcmdump 不为DCM_RescaleSlope标记返回任何内容,但它为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

When I use当我使用

std::cout << getItemString ( tmpdata, DCM_RescaleSlope )        << std::endl; 
std::cout << getItemString ( tmpdata, DCM_RealWorldValueSlope ) << std::endl;
std::cout << getItemString ( tmpdata, DCM_Modality )            << std::endl;

(where getItemString is a function for convenience) and use the debugger to look what happens in the second line, then: (其中getItemString是 function 为方便起见)并使用调试器查看第二行中发生的情况,然后:

  1. the tag is converted to g = 64 , e = 37413标签转换为g = 64 , e = 37413
  2. the line OFStatus s = theCondition.theStatus;OFStatus s = theCondition.theStatus; is set to false (that's all there is, apart from theText = "Tag not found" )设置为 false (这就是全部,除了theText = "Tag not found"

which I don't understand because (i) the value of the tag is known by the program -- otherwise it wouldn't compile, (ii) the tag is in the image as shown by dcmdump and (iii) other tags are processed OK: DCM_Modality is printed as MR .我不明白,因为(i)标签的值是程序已知的——否则它不会编译,(ii)标签在图像中,如dcmdump所示,(iii)其他标签被处理OK: DCM_Modality打印为MR

Am I doing something wrong, or do these special tags need special treatment?是我做错了什么,还是这些特殊标签需要特殊处理?

EDIT编辑

I tried one suggestion from the comments: using findAndGetFloat64 instead of findAndGetOFString , in a test我从评论中尝试了一个建议:在测试中使用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;

which resulted in这导致

A0
B0
C297.6

and the error in theStatus during the line for reading B is still the same: theText = "Tag not found"并且读取B行期间theStatus中的错误仍然相同: theText = "Tag not found"

(I had been using strings because most of the double-valued tags so far had been DS , thanks for making me aware of the difference!) (我一直在使用字符串,因为到目前为止大多数双值标签都是DS ,感谢您让我意识到其中的区别!)

The tag you are looking for is inside a sequence ( RealWorldValueMappingSequence ).您要查找的标签位于序列 ( RealWorldValueMappingSequence ) 内。 To get to the tag, you first have to get the sequence, something like this:要获取标签,您首先必须获取序列,如下所示:

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);
  ...
}

Note that this is out of my head, so it may not be accurate, but this is basically what you need to do to get the tags inside of sequence items.请注意,这不是我的想法,所以它可能不准确,但这基本上是您需要做的才能获得序列项目内的标签。 All findAndGet... methods by default only work on the current item, which may be the root dataset, but may also be a sequence item - you have to check in the DICOM standard where actually to find the tags.默认情况下,所有findAndGet...方法仅适用于当前项目,它可能是根数据集,但也可能是序列项目 - 您必须在 DICOM 标准中检查实际在哪里找到标签。

UPDATE:更新:
Having written that, I just realized that I forgot about the searchIntoSub parameter, so probably it would be sufficient to do:写完之后,我才意识到我忘记了searchIntoSub参数,所以这样做可能就足够了:

  result = tmpData->findAndGetFloat64(DCM_RealWorldValueSlope, value, 0, OFTrue);

where searchIntoSub=OfTrue means, that contained sequences are also searched.其中searchIntoSub=OfTrue表示包含的序列也被搜索。 I leave the above anyway, as it may also be needed by someone else if searching for tags in specific sequences.无论如何我都会保留上面的内容,因为如果以特定顺序搜索标签,其他人也可能需要它。

Side note:边注:
Your first approach to use findAndGetOFString should also work, if you use this parameter.如果您使用此参数,您使用findAndGetOFString的第一种方法也应该有效。 It does not make sense in your case, as you need the actual double value, but it can be used if you need only the string representation of the tag values.在您的情况下它没有意义,因为您需要实际的双精度值,但如果您只需要标记值的字符串表示形式,则可以使用它。 From the documentation for 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适用于以下VR: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、美国、UT、UV

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM