几年前我写了一个jpeg压缩器/解压缩器,可以处理无损和有损的jpeg文件。它运行良好,但并不总是正确解码DICOM文件中的jpeg流。
我很了解jpeg,但我对DICOM知之甚少。 DICOM中的无损jpeg不可能符合jpeg ISO标准。必须进行一些修改,硬编码或由jpeg文件流之外的DICOM文件中的某个参数修改。
我的代码在大多数示例DICOM文件(compsamples_jpeg.tar)处失败: ftp://medical.nema.org/MEDICAL/Dicom/DataSets/WG04/
这是我解码此套装中的第一个无损jpeg(IMAGES \ JPLL \ CT1_JPLL)时会发生什么:
左图像是从我的代码渲染的,右边是由在线DICOM阅读器呈现的: www(点)ofoct(点)com(斜杠)查看器(斜杠)dicom-viewer-online(点)html
(x)MedCon是一个开源的DICOM读取器,它与我的代码完全相同,所以我不是唯一一个有这个问题的人。 xmedcon dot sourceforge dot net
我已逐字节读取了这个jpeg流,绘制了霍夫曼树并用铅笔和纸计算了霍夫曼代码,我的代码完全按照它应该做的去做。以下是霍夫曼代码:
以下是SOS标记后的压缩数据:
在线观看者说第一个像素值是-3024。如果这是正确的,那么第一个diff值应该是-3024,但它不是。
在此之后,我的代码正确地解码了大约2/5的图像,但随后解码了一个非常不准确的diff值:
1010111 10100001 11111110 11111111 11100000
101 si = 5
如果您查看在线查看器解码的图像,此位置的像素强度没有根本变化,因此si = 11值不正确。
我确信我对jpeg有很好的理解,但DICOM中的jpeg流似乎不遵循jpeg标准。当jpeg流嵌入DICOM文件时,对它们进行了哪些扩展/更改?
答案 0 :(得分:5)
DICOM指定使用ISO 10918,因此在DICOM图像中使用无损JPEG没有任何魔力,除了将已解码比特流的始终无符号输出重新解释为有符号(取决于像素表示)并将重新缩放斜率和截距应用于解码的"存储的像素值"进入任何"价值观"如Paolo所描述的,观众可以报告(例如,作为Hounsfield单位)。换句话说,不要依赖"像素值"观察者报告与解码比特流的直接输出相同。
作为参考,以下是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
虽然有些编码器可能有问题,但我不认为NEMA样本数据集中的IMAGES \ JPLL \ CT1_JPLL就是这种情况,这是我多年前使用Stanford PVRG编解码器创建的。
http://www.dclunie.com/pixelmed/software/codec/我自己的解码器(最小)与它没有任何问题。源是可用的,所以如果你想重新编译它,打开一些调试消息来跟踪每个解码值,预测器输入值,每行开头重启等,与你自己的逻辑进行比较,随意
最后,由于JPEG无损在DICOM之外很少使用,您可能会发现很难获得其他要测试的样本。我想到的一个问题是USF数字化乳房X线照相术集(医学,但不是DICOM),http://marathon.csee.usf.edu/Mammography/Database.html。
大卫
PS。我确实检查了XMedCon在https://sourceforge.net/projects/xmedcon/使用的编解码器,它似乎使用了Cornell无损代码的一些副本;所以它可能容易受到BitBank所引用的帖子(https://groups.google.com/forum/#!topic/comp.protocols.dicom/Yl5GkZ8ggOE)中描述的相同错误或其他一些错误的影响。我没有尝试破译源代码来查看。
答案 1 :(得分:1)
第一个像素的值确实是-3024,因为在线dicom查看器说:
您正确地将第一个幅度解码为30768,但第一个像素的预测值设置为零,因此其实际值为32768 + 30768 = 63536。这是一个无符号值。
现在,像素表示标签表示文件值是b2补码(有符号),因此当我们使用最高有效位作为符号时,该值变为-2000。
当我们在rescale斜率截取标记(-1024)中应用该值时,第一个像素的值变为-3024。
但是,我的编解码器在第179行附近找不到任何幅度2047,所以也许你的编解码器会以某种方式失去同步:在后续行中也会看到同步丢失(它们都向右移动)