几年前我写了一个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标准.嵌入DICOM文件时对jpeg流进行了哪些扩展/更改?
小智 6
DICOM指定使用ISO 10918,因此在DICOM图像中使用无损JPEG没有任何魔力,除了将已解码比特流的始终无符号输出重新解释为有符号(取决于像素表示)并且如Resolo描述的那样,将解码的"存储的像素值"应用于重新缩放斜率和截距为观察者可能报告的任何"值"(例如,作为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.我确实在https://sourceforge.net/projects/xmedcon/上检查了哪个编解码器XMedCon正在使用,它似乎使用了Cornell无损代码的一些副本; 所以它可能容易受到BitBank所引用的帖子中描述的相同错误(https://groups.google.com/forum/#!topic/comp.protocols.dicom/Yl5GkZ8ggOE)或其他一些错误.我没有尝试破译源代码来查看.
正如在线 dicom 查看器所说,第一个像素的值确实是 -3024:
您正确地将第一个幅度解码为 30768,但第一个像素的预测变量设置为零,因此其实际值为 32768+30768=63536。这是一个无符号值。
现在,像素表示标记表示文件值采用 b2 补码(带符号),因此当我们使用最高有效位作为符号时,该值变为 -2000。
当我们应用重新缩放斜率截距标签中的值 (-1024) 时,第一个像素的值将变为 -3024。
但是,我的编解码器在第 179 行附近没有找到任何幅度 2047,因此您的编解码器可能会以某种方式失去同步:在后续行中也可以看到同步丢失(它们都向右移动)。