在nema.org DICOM文件中解码无损JPEG

6
我多年前写了一个JPEG压缩/解压程序,可以处理无损和有损的JPEG文件。它工作得很好,但并不总是正确地解码DICOM文件中的JPEG流。
我对JPEG很熟悉,但对DICOM知之甚少。DICOM中的无损JPEG不可能符合JPEG ISO标准。必须进行一些修改,无论是硬编码还是通过DICOM文件中JPEG文件流外部的某个参数进行修改。
我的代码在大多数样本DICOM文件(compsamples_jpeg.tar)上失败了,请参见: ftp://medical.nema.org/MEDICAL/Dicom/DataSets/WG04/ 这是当我解码此集合中第一个无损JPEG(IMAGES\JPLL\CT1_JPLL)时发生的情况: dicom decoded image 左侧图像由我的代码呈现,右侧图像由在线DICOM阅读器呈现: www (dot) ofoct (dot) com (slash) viewer (slash) dicom-viewer-online (dot) html
(x)MedCon是一个开源的DICOM阅读器,在像素级别上与我的代码出现了相同的问题,所以我不是唯一一个遇到这个问题的人。 xmedcon点sourceforge点net
我逐字节阅读了这个jpeg流,画出了霍夫曼树并计算了霍夫曼编码,我的代码完全按照预期运行。以下是霍夫曼编码:
0 00 4 01 3 100 5 101 1 1100 2 1101 6 1110 7 11110 8 111110 9 1111110 12 11111110 11 111111110 10 1111111110 15 11111111110
以下是SOS标记后的压缩数据:
  • ff 00 de 0c 00 (ff后的00是填充字节)
  • 11111111 11011110 00001100 00000000
  • 11111111110 si=15
  • 111100000110000 diff=30768

在线查看器显示第一个像素值为-3024。如果正确,第一个diff值应为-3024,但不是。

此后,我的代码正确解码了大约2/5的图像,但随后解码出一个极不准确的diff值:

  • d2 a1 fe ff 00 e0 (ff后的00是填充字节)
  • 1010111 10100001 11111110 11111111 11100000

  • 101 si=5

  • 01111 diff=-16
  • 01 si=4
  • 0000 diff=-15
  • 111111110 si=11 ????
  • 11111111111 diff=2047
如果您查看在线查看器解码的图像,该位置的像素强度没有根本性变化,因此si=11值不正确。
我确信我对jpeg有很好的理解,但是DICOM中的jpeg流似乎不遵循jpeg标准。嵌入DICOM文件时对jpeg流进行了哪些扩展/更改?

1
我维护着这个库,可以无问题地对其进行解码。虽然我不是JPEG专家,但也许它能帮助你找出问题所在。如果你想可视化它,该库被用于这个JS查看器中。 - martinez314
我的无损代码能够正确解码图像。根据您的图像出现的情况(错误的DC值,但仍然同步),我认为您没有正确解释长度为16的编码。这里有一个关于它的快速讨论:https://groups.google.com/forum/#!topic/comp.protocols.dicom/Yl5GkZ8ggOE - BitBank
只是一个奇怪的想法 - 这是一个非常狭窄的领域(DICOM图像中的无损JPEG)。我想知道世界上有多少程序员像我们一样重新发明了这个轮子并编写了自己的无损JPEG解码器... - BitBank
2个回答

6
DICOM规范严格按照ISO 10918的使用方式编写,因此在DICOM图像中使用无损JPEG并没有什么神奇之处,除了重新解释解码比特流的总是无符号输出为有符号(取决于像素表示)并将Rescale Slope和Intercept应用于解码后的“存储像素值”以转换为查看器可能报告的任何“值”(例如作为Hounsfield单位),正如Paolo所描述的那样。换句话说,不要依赖查看器报告的“像素值”与解码比特流的直接输出相同。

供参考,这里是DICOM中涉及10918通用使用的几个部分:

http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_8.2.html#sect_8.2.1 http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_A.4.html#sect_A.4.1

DICOM编码器可能会将单个压缩帧拆分成多个片段,就像这个示例中故意使用分段来测试解码能力一样。我希望你知道这一点,并已经注意到跨片段边界重新组装压缩的位流(即删除片段之间的固定长度Item标记):

http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_A.4.html

尽管一些编码器可能存在缺陷,但我认为在我多年前使用Stanford PVRG编解码器创建的NEMA样本数据集中,IMAGES \ JPLL \ CT1_JPLL并非如此。我的自己的解码器(虽然很简单)在http://www.dclunie.com/pixelmed/software/codec/上没有问题。源代码可用,因此如果您想重新编译它并打开一些调试消息以跟踪每个解码值、预测输入值、在每行开始时重新启动等,以与您自己的逻辑进行比较,请随意。最后,由于JPEG无损在DICOM之外很少使用,您可能会发现很难获得其他样本进行测试。一个这样的来源是USF数字化乳腺X线检查集合(医学,但不是DICOM),位于http://marathon.csee.usf.edu/Mammography/Database.html。David

PS. 我检查了https://sourceforge.net/projects/xmedcon/ XMedCon 使用的编解码器,似乎使用了康奈尔无损编码的某个副本; 因此可能会受到 BitBank 引用的帖子中描述的相同错误(https://groups.google.com/forum/#!topic/comp.protocols.dicom/Yl5GkZ8ggOE)或其他错误的影响。我没有尝试解密源代码。


2
第一个像素的值确实是-3024,就像在线dicom查看器显示的那样。您正确地将第一个幅度解码为30768,但第一个像素的预测器设置为零,因此其真实值为32768+30768=63536。这是一个无符号值。
现在,像素表示标签说明文件值采用b2补码(有符号),因此当我们使用最高位作为符号位时,该值变为-2000。
当我们应用重新缩放斜率截距标记中的值(-1024)时,第一个像素的值变为-3024。
然而,我的编解码器在179行附近没有发现任何幅度为2047的值,因此您的编解码器可能以某种方式失去同步:同步丢失也可在随后的行中看到(它们都向右移动)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接