分析经过j2k压缩的dicom文件经验分享

最近碰到一个问题,在网上搜到是用JPEG 2000压缩的DICOM文件

JPEG 2000对应的transfer syntax UID为

1.2.840.10008.1.2.4.91

参考:https://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_8.7.3.html

该文件是用专业德国老牌开发库DCMTK生成的

(0002,0013) SH [OFFIS_DCMTK_364]                        #  16, 1 ImplementationVersionName

怎么看的?很简单,直接用dcmtk的工具包命令dcmdump查下

dcmdump <filename>

就能dump类似如下结果

(0002,0000) UL 230                                      #   4, 1 FileMetaInformationGroupLength
(0002,0001) OB 00\01                                    #   2, 1 FileMetaInformationVersion
(0002,0002) UI =CTImageStorage                          #  26, 1 MediaStorageSOPClassUID
(0002,0003) UI [1.2.826.0.1.3680043.8.1055.1.20111102150758591.03296050.69180943] #  64, 1 MediaStorageSOPInstanceUID
(0002,0010) UI =JPEG2000                                #  22, 1 TransferSyntaxUID
(0002,0012) UI [1.2.276.0.7230010.3.0.3.6.4]            #  28, 1 ImplementationClassUID
(0002,0013) SH [OFFIS_DCMTK_364]                        #  16, 1 ImplementationVersionName
(0002,0016) AE [DICOMLIBRARY]                           #  12, 1 SourceApplicationEntityTitle

# Dicom-Data-Set
# Used TransferSyntax: JPEG 2000 (Lossless or Lossy)
(0008,0005) CS [ISO_IR 100]                             #  10, 1 SpecificCharacterSet
(0008,0008) CS [ORIGINAL\PRIMARY\AXIAL\HELIX]           #  28, 4 ImageType

......

......

(0040,0254) LO [CT1 abdomen]                           #  12, 1 PerformedProcedureStepDescription
(0040,1001) SH [A10026177757]                           #  12, 1 RequestedProcedureID
(7fe0,0010) OB (PixelSequence #=2)                      # u/l, 1 PixelData
  (fffe,e000) pi 00\00\00\00                              #   4, 1 Item
  (fffe,e000) pi ff\4f\ff\51\00\29\00\00\00\00\02\00\00\00\02\00\00\00\00\00\00\00... # 89124, 1 Item
(fffe,e0dd) na (SequenceDelimitationItem)               #   0, 0 SequenceDelimitationItem

出现一个有意思的事情

      我用dcmtk的storescu命令将其发送给用另一个开源库实现的DICOM 服务,接受后存储为新的文件。新的文件用一个免费的DICOM Viewer (Micro DICOM Viewer)查看时提示无法打开,而用Micro DICOM Viewer直接打开原文件是正常的, 但如果用一个开源的cornerstonejs去打开这个新文件又能显示出来。

为了弄清楚原因,我开始着手调研

     首先先将新文件转成未压缩的DICOM文件看看能不能让Micro DICOM Viewer打开,发现dcmtk支持j2k转换的工具是要商业授权的

Two of the DICOM JPEG 2000 transfer syntaxes are supported ("JPEG 2000 Image Compression (Lossless Only)" and "JPEG 2000 Image Compression").

Further details can be found in the online documentation for the tools DCMCJP2K and DCMDJP2K.

DCMJP2K is based on the OFFIS DICOM toolkit DCMTK and is available in different versions: There is a binary version as well as a source code variant. DCMJP2K supports several Unix dialects (e. g. Linux, Solaris and Mac OS X) as well as Windows.

This module is not freely available and must be licensed separately.

来源:https://dcmtk.org/en/dcmtk-expansion-modules/dcmjp2k/

于是我一顿操作猛如虎,找到免费平替

gdcmconv --raw file-in file-out

gdcmconv: Tool to convert dicom to dicom.

这个工具是grassroot dicom社区开发,在sourceforge有代码地址,开源有点历史了。

https://sourceforge.net/projects/gdcm/

于是对Micro DICOM Viewer打不开的压缩文件,用gdcmconv转成未压缩文件后,发现可以用micro dicom viewer打开,说明图像本身没有问题。

于是我反向操作,再压缩回J2K

 gdcmconv --j2k --lossy file-in file-out

这个时候发现压缩回的文件,micro dicom viewer能够打开。这就说明那个开源DICOM服务保存后的压缩图像格式可能与原图及gdcmconv的处理不一致。

于是我对比下两个文件的区别

dcmdump工具再次出手,经过对比发现新文件的pixel data和原文件的pixel data有一点差异:

原文件

(7fe0,0010) OB (PixelSequence #=2)                      # u/l, 1 PixelData
  (fffe,e000) pi 00\00\00\00                              #   4, 1 Item
  (fffe,e000) pi ff\4f\ff\51\00\29\00\00\00\00\02\00\00\00\02\00\00\00\00\00\00\00... # 89124, 1 Item
(fffe,e0dd) na (SequenceDelimitationItem)               #   0, 0 SequenceDelimitationItem

新文件 

(7fe0,0010) OB (PixelSequence #=6)                      # u/l, 1 PixelData
  (fffe,e000) pi 00\00\00\00                              #   4, 1 Item
  (fffe,e000) pi ff\4f\ff\51\00\29\00\00\00\00\02\00\00\00\02\00\00\00\00\00\00\00... # 20480, 1 Item
  (fffe,e000) pi 5b\51\b7\69\ef\8b\ea\28\44\43\39\1c\67\a0\70\eb\2f\73\bf\91\ea\c0... # 20480, 1 Item
  (fffe,e000) pi 82\1c\7c\94\74\3e\c0\63\a0\81\2d\ee\d2\85\d1\30\02\a1\86\6f\2d\f1... # 20480, 1 Item
  (fffe,e000) pi 74\08\37\dd\88\7b\bd\9d\98\9e\2f\6f\19\1f\40\00\ca\26\7f\17\59\68... # 20480, 1 Item
  (fffe,e000) pi f5\0c\47\98\ba\8f\08\63\8d\e4\a3\31\10\2d\bc\7d\4f\4d\e7\0a\7b\11... # 7204, 1 Item
(fffe,e0dd) na (SequenceDelimitationItem)               #   0, 0 SequenceDelimitationItem
 

 原文件只有两段pixel sequence,新文件有6段pixel sequence, 第一个段的内容4个字节都是0可以忽略。新文件把老文件的第二段共89124个字节的内容拆成了5段。

为了验证是否该差异导致,决定二进制修改Pixel Data(自我感觉很牛逼啊)

用vscode装个hex editor插件

用hex editor打开新文件,如下图

点击Ctrl+F打开文件内搜索,选中那个0101的图标表示按二进制内容搜索,

在输入框输入  e07f1000搜到pixel data所在的位置

 解释下为什么是搜素 e07f1000

pixel data的tag是 (7fe0,0010), 因为文件用的是little endian explicit, 需要把高低字节换过来进行搜索, 即7fe0 --> e07f, 0010 --> 1000

上面截图分析可以看到 TAG后面跟上的是VR(OB), 这是OB的官方定义

参考:https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html#table_6.2-1 

 关于Explicit VR的编码格式定义如下:

 参考https://dicom.nema.org/medical/dicom/current/output/html/part05.html#chapter_7

VR后面跟着4个字节的Value Length, 从截图可以看到是4个FF, 这个表示未知长度,需要靠sequence delimitation item去定义, 就是说用分割符号来判断。

刚才所说的分割符号其实就是指SQ(sequence),  (fffe,00e0)也就是SQ的开头标记,如上截图标记,后面跟着4字节长度,第一段是4个字节,跟着4个00, 第二段是20480个字节,如此类推。

那我要做的就是把第二段的长度:20480改成89124,也就是原文件的第二段的长度,然后再把第三段到第六段的(fffe,00e0)标记及其长度4个字节全部删除掉。这样就做到了和原文件一样的两个SQ段。按照这个思路改完保存后,果不其然,micro dicom viewer能正常打开了。

总结

    原始文件的pixel data是两段SQ,第一段4个字节的00我没搞懂有什么意义,但第二段的内容是完整的JPEG 2000压缩图像。而开源DICOM服务将第二段这个完整的JPEG 2000图像切成了5个SQ来保存,也不能说不符合DICOM标准,你看人家gdcmconv能够正常解压转换,cornerstonejs也能打开显示。

    因此可能还是micro dicom viewer兼容性不够,不能支持到这种将完整jpeg2000图像大卸八块的搞法,作为DICOM服务这端在保存文件时还是应尽量不去改变原文件的格局,都放在一个SQ里保存会具有更好的兼容性。

    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/563454.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

虚拟机VMware安装与Ubuntu

1.虚拟机安装 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;2fr6 CG54H-D8D0H-H8DHY-C6X7X-N2KG6 2.Ubuntu下载 Download Ubuntu Desktop | Ubuntu 3.设置 如后续要下一些软件越大越好

Diffusion Model原理剖析

目录 前言1. DDPM演算法初览2. 图像生成模型共同目标3. VAE: Lower bound of l o g P ( x ) logP(x) logP(x)4. Diffusion Model背后的数学原理5. 为什么需要Sample?6. Diffusion Model的应用7. Diffusion Model成功的关键总结参考 前言 接着上篇文章 图像生成模型浅析&#…

15.C++常用的算法_拷贝和替换算法

文章目录 遍历算法1. copy()代码工程运行结果 2. replace()代码工程运行结果 3. replace_if()代码工程运行结果 4. swap()代码工程运行结果 遍历算法 1. copy() 代码工程 copy()函数不要因为使用而使用#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include&l…

dremio支持设置

Dremio 支持提供可用于诊断目的的设置。这些设置通过 Dremio UI&#xff1a;设置>支持启用&#xff08;或禁用&#xff09; 使用 Client Tools 可以配置当用户查看数据集中的数据时&#xff0c;Dremio 项目的工具栏上显示哪些客户端应用程序按钮。用户可以通过单击相应的工具…

免费ssl泛域名/泛解析证书获取教程

泛域名SSL证书&#xff0c;也称为通配符证书&#xff0c;它可以保护一个主域名下的所有子域名。这意味着&#xff0c;无论你有多少个子域名&#xff0c;只要安装了一个泛域名SSL证书&#xff0c;就可以实现全部子域名的安全保护。这种证书非常适合大型企业或有大量子域名的网站…

数电复习(五)半导体存储电路

半导体存储电路 5.1 概述5.2 SR锁存器5.3 触发器5.3.1电平触发的触发器5.3.2 边沿触发器5.3.3 脉冲触发(主从) 触发器5.3.4 触发器逻辑功能的转换 5.4 寄存器5.4.1 数码寄存器5.4.2 移位寄存器 5.5 存储器5.5.1 ROM5.5.2 随机存储器RAM5.5.3 存储器容量的扩展5.5.4 用存储器实现…

怎么申请免费SSL证书,如何安装

什么是SSL证书&#xff0c;SSL&#xff0c;即Secure Sockets Layer&#xff08;安全套接层&#xff09;&#xff0c;它是一种安全协议&#xff0c;用于在互联网通信中为数据提供加密保护&#xff0c;从而防止数据被窃听或篡改。而SSL证书则是由权威的数字证书认证机构&#xff…

数据结构面试常见问题:什么是哈希表?它的工作原理是什么?

哈希表的基本概念 在我们的日常生活中&#xff0c;我们经常需要存储和查找各种信息&#xff0c;这些信息可能是电话号码&#xff0c;地址&#xff0c;或者是商品的价格等等。这些信息的存储和查找&#xff0c;就像是我们在一个巨大的仓库中存放和寻找物品。这个仓库就是数据结…

机器学习中的过拟合问题及应对策略:深入剖析与实战指南

在机器学习的领域中&#xff0c;过拟合是一个普遍而又棘手的问题。过拟合指的是模型在训练数据上表现优秀&#xff0c;但在未知或测试数据上表现不佳的现象。这通常是因为模型过于复杂&#xff0c;以至于“记住”了训练数据的噪声和细节&#xff0c;而非学习其内在规律和结构。…

立创·实战派ESP32-C3开发板 with lv_micropython

一、lv_micropython对驱动芯片的支持 ESP32-C3开发板的Display drivers:ST7789&#xff0c;Input drivers:FT6336&#xff0c;从LVGL的官方文档了解到lv_micropython包含了这两颗IC的驱动。 参考文档&#xff1a; lv_micropython already contains these drivers: 链接:Micro…

使用Python进行容器编排Docker Compose与Kubernetes的比较

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 随着容器化技术的普及&#xff0c;容器编排成为了管理和部署容器化应用程序的重要环节。在容…

jBPM的介绍

一、简介 jBPM&#xff08;Java Business Process Management&#xff09;是一个开源的业务流程管理框架&#xff0c;用于管理和执行业务流程。它提供了一个可视化的流程设计器&#xff0c;可以创建、模拟和部署业务流程&#xff0c;并提供了灵活的流程执行引擎。 jBPM可以帮…

【Go语言快速上手(三)】数组, 切片与映射

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Go语言专栏⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Go语言知识   &#x1f51d;&#x1f51d; GO快速上手 1. 前言2. 数组详解3. 切…

中栈内联(THE MID-STACK INLINER)优化

THE MID-STACK INLINER 直译为“中栈内联”&#xff0c;属于一种更为新进的内联策略。内联&#xff08;InLining&#xff09;的工作原理是将对一个函数的调用展开为函数本身的代码&#xff0c;通过内联减少函数调用的开销&#xff0c;也给编译器带来进一步优化代码的机会。那么…

AI大模型探索之路-实战篇3:基于私有模型GLM-企业级知识库开发实战

文章目录 前言概述一、本地知识库核心架构回顾&#xff08;RAG&#xff09;1. 知识数据向量化2. 知识数据检索返回 二、大模型选择1. 模型选择标准2. ChatGLM3-6B 三、Embedding模型选择四、改造后的技术选型五、资源准备1. 安装git-lfs2. 下载GLM模型3. 下载Embeding模型 六、…

Android Studio超级详细讲解下载、安装配置教程(建议收藏)

博主介绍&#xff1a;✌专注于前后端、机器学习、人工智能应用领域开发的优质创作者、秉着互联网精神开源贡献精神&#xff0c;答疑解惑、坚持优质作品共享。本人是掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战&#xff0c;深受全网粉丝喜爱与支持✌有…

c语言利用控制台实现贪吃蛇

使用控制台实现贪吃蛇需要的技能加点&#xff1a; 控制台设置&#xff08;包含于stdlib.h&#xff09;&#xff1a; 定义命令行窗口高/宽&#xff1a; system("mode con cols100 lines30"); system() 函数是一个C标准库函数&#xff0c;它允许程序执行操作系统命令…

深度学习Day-14:RNN实现心脏病预测

&#x1f368; 本文为&#xff1a;[&#x1f517;365天深度学习训练营] 中的学习记录博客 &#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制] 要求&#xff1a; 本地读取并加载数据&#xff1b;了解循环神经网络RNN的构建过程&#xff1b;测试集accuracy达到87%…

Linux--Linux常用命令

Linux常用命令 前言Linux命令格式命令讲解1、ls:查看当前目录下所有的内容语法:ls[-al][dir]2、pwd: 查看当前所在目录3、cd : 切换目录4、touch[文件名] : 如果文件不存在新建文件5、mkdir: 创建目录6、rm: 删除指定文件7、rmdir: 删除空目录8、cat:用于显示文件内容9、m…

MySQL8.0.36-社区版:二进制日志(4)

什么是二进制日志&#xff08;binlog&#xff09;&#xff1a;记录了所有的ddl和dml语句&#xff0c;但是不包括查询类的 二进制日志的作用&#xff1a;1.灾难恢复&#xff0c;2.mysql主从复制 查看二进制日志状态 show variables like %log_bin%; 在mysql8中默认是开启的 | l…