【问题标题】:How to read DICOM string value with backslash (VR=LO, Value="0.4323\0.2325")?如何读取带反斜杠的 DICOM 字符串值(VR=LO,Value="0.4323\0.2325")?
【发布时间】:2020-07-30 13:59:54
【问题描述】:

我们的 C++ 软件使用 ITK 来编写 DICOM 文件。在其中,我们有一个私有标签,其中LO(长字符串)为VR,2 个十进制值作为0.3234\0.34223 之类的值。

LO 选项是 ITK 固有的。

在其他 java 应用程序中,我使用 dcm4che3 来读取/写入它们。由于它尊重 DICOM 协议,因此禁止使用反斜杠,dcm4che 将值解释为"0.3234",并且永远不会达到第二个值。

我使用的所有 DICOM 查看器应用程序都可以显示此值。

所以我的问题是:尽管存在反斜杠,但在 dcm4che 中是否有将这个完整值读取为字符串 "0.3234\0.34223" 的技巧?

下面是我使用的代码:

     public DicomInfo uploadFile(MultipartFile file) throws IOException, ParseException {

       DicomInfo infos = new DicomInfo();

       Attributes attrs = readDicomAttributes(file);
       infos.setTags(toAttributesObject(attrs).toString());
    }

    private static JsonObject toAttributesObject(Attributes targetSeriesAttrs) 
    {
       StringWriter strWriter = new StringWriter();
       JsonGenerator gen = Json.createGenerator(strWriter);
       JSONWriter writer = new JSONWriter(gen);
       writer.write(targetSeriesAttrs);
       gen.flush();
       gen.close();
       return Json.createReader(new 
          StringReader(strWriter.toString())).readObject();
  }
  
  public Attributes readDicomAttributes(MultipartFile file) throws IOException 
  {
    DicomInputStream dis = new DicomInputStream(file.getInputStream());
    Attributes dataSet = dis.readDataset(-1, Tag.PixelData);
    Attributes fmi = dis.readFileMetaInformation();
    dis.close();

    fmi.addAll(dataSet);

    return fmi;
  }

在我为这个标签得到的 JSON 中:

\"00110013\":{\"vr\":\"LO\",\"Value\":[\"0.4323\"]},

如您所见,它是 LO,第二部分已经丢失。

我获取具体属性的方法:

attr.getStrings(0x00110013)

发回一个只有一个值的表格,0.4323。

问题发生在 readDataSet 函数期间。

当我用免费的dicom viewer之类的软件打开标签时,我有完整的数据,所以数据就在这里。


好的,我找到了问题的根源......它是addAllfmi.addAll(dataSet);

在数据集中,getStrings 完美运行。在fmiaddAll之后,属性丢失了第二个值。

所以我的问题是现在解决这个addAll 问题:dcm4che3 java lib: Attributes.addAll method seems to lost multiple LO values

【问题讨论】:

  • 反斜杠不是被禁止的,我猜你必须以某种方式告诉 dcm4che 你的私有属性的值多重性为 2。我不知道该怎么做,但通常会提到这个配置作为“私人词典”
  • in LO 反斜杠不应使用,请参阅文档,因此即使 getStringS 也不起作用。而且我无法修改 VR。
  • 我认为唯一的解决方案是忘记 dcm4che 并在 java 中使用 ITK impl ...
  • 我没有使用过 dcm4che,但快速浏览一下资料表明StringValueType.getStrings() 做了正确的事情,例如通过 '\' 分隔符拆分标签内容并返回字符串。你能展示你用来读取标签内容的代码吗?
  • 我只是编辑以放置我的代码和结果

标签: java dicom dcm4che


【解决方案1】:

请参阅 Paolo 的回答,请相信我们反斜杠不违反 VR。正如他所说,该属性是二维,即它有VR LO 的两个值,由反斜杠分隔

我对 dcm4che 项目及其背后的人有所了解,我几乎无法想象它通常无法处理这个问题。

我强烈怀疑您的问题与您的属性是 private 的事实有关。也就是说,如果没有任何关于标签及其值的附加信息,dcm4che(和任何其他产品)永远不会知道该属性的值被编码为 VR LO(长字符串)。

DICOM 中的默认传输语法是 Implicit Little Endian。这意味着,数据集不传达关于数据集中属性的 VR 的显式信息。该信息由属性的Tag隐式编码,必须使用数据字典(DICOM Part 6)查找标签并获取对应的VR。很明显,这仅适用于标准中定义的知名 DICOM 标签,而对于私有标签则无效。

因此,一种选择是尝试以显式小端序对数据集进行编码,这意味着 VR 是数据集中属性编码的一部分。我希望这已经足够了。

成熟的工具包(如 dcm4che)允许通过配置扩展数据字典,也就是说,您可以使用自定义标签定义来扩展 takeit 使用的“官方”数据字典 - 包括 VR .因此,在数据集本身没有明确给出 VR 的情况下,可以查找标签。

再次重申,我不是 dcm4che 的专家,但在 google 上快速搜索“dcm4che private dictionary”会得到this promising link

我非常有信心您可以在 dcm4che 中解决问题,并且您不必迁移到其他工具包。

【讨论】:

  • 据我了解,在显式小端序中编码数据集应该可以完成这项工作;不幸的是,OP没有明确提到它或评论他们是否尝试过这个。希望他们尝试一下并提出输出。
  • @AmitJoshi - 我实际上假设他们确实将其编码为 Explicit Little Endian,否则他们将不知道 VR - 但你是对的,这可能正是问题所在。否则完全同意 kritzel_sw。
【解决方案2】:

这个问题的解决方法是写

dataSet.addAll(fmi);
return dataSet;

而不是

fmi.AddAll(dataSet);
return fmi;

由于 addAll 方法丢失了多个私有 LO 值

【讨论】:

    【解决方案3】:

    LO 可以有多个值,用反斜杠分隔。

    DICOM 标准规定,在 VR“LO”中,反斜杠不能用于值中,因为它用于分隔不同的元素。

    在不允许多个元素的 VR 中,可以在值中使用反斜杠。

    所以这里 dcm4che 是错误的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      相关资源
      最近更新 更多