关于DCMTK中像素存储以及getoutdata()函数的使用

来源:互联网 发布:数据修炼系统顶点 编辑:程序博客网 时间:2024/06/05 16:13

当你看这个帖子的时候,假设你在因为这个问题而困惑。

  在使用这个函数的时候纠结了很久,各种google、百度都没查到,测试了好多次,并计算了许多二进制像素值,才终于搞明白,getoutdata()里的参数到底应该怎么写;
  首先弄清楚dicom文件中单个像素值是怎么存的,说下一般的情况,以16位二进制方式存储,分析需要通过pixel模块的,bitstored, bitsallocated, highbit, pixel representation这四个值。

  • pixel representation
    pixel representation的值有0和1两种,0代表无符号,1代表有符号,比如二进制1001如果是无符号存储,表示9,如果是有符号(第一位代表符号位)的话就是-1;二进制0001不管是有符号还是无符号都代表1。
  • bitsallocated
    bitsallocated表示用多少位来储存,通俗来说就是开辟多少空间来存一个像素值,bitsallocated的存在是为了凑整,8或16或32,方便二进制计算.
  • bitstored
    在CT中一般bitsallocated=16位,因为16位所占空间很大,肯定是用不完的,所以又有bitstored这个值来表示用bitsallocated中的多少位来存像素值,剩余几位全部置0就行了。
  • highbit
    因为像素值可能是有符号或无符号,highbit这个值的存在是为了确定符号位。

下面举几个例子:

  • 例1:pixel representation=0, bitsallocated=16, bitsstored=12, highbit=11,假设像素值为100,按照标准存储如下:
    |0000|0000|0110|0100|
  • 例2:pixel representation=1, bitsallocated=16, bitsstored=12, highbit=11,假设像素值为100,按照标准存储如下:
    |0000|1000|0110|0100|
  • 例3:pixel representation=1, bitsallocated=16, bitsstored=16, highbit=15,假设像素值为100,按照标准存储如下:
    |1000|0000|0110|0100|

特别注意

其实上面例2、例3都是错的,没看出来么?

  上面的储存方式是我们人脑所方便理解的,但对于计算机而言,负数如果是这么存储的话,计算机处理时候需要先做个判断,第一位是不是1,然后再计算,这显然对于傻瓜的只能处理0、1的计算机而言是个沉重的负担,所以负数的存储用了补码(想深入理解原码、反码、补码推荐博客),对于正数而言补码还是其本身,对于负数而言补码是撇除符号位后进行反码运算后+1。
所以:

  • 例2的真实存储情况是|0000|1111|1001|1100|
    其实例2这种情况只是我臆想的,真是应该是不存在的,一般按照例1或例3这种比较规律的方式,当然,储存情况是厂家订制的,鬼知道他们会怎么干。
  • 例3的真实存储情况是|1111|1111|1001|1100|

考虑大端小端后

前面都是没有考虑大小端情况,对于不同系统存储方式有大端、小端的区别(大端、小端知识可以参考博文),所以是打断的情况不用变化,如果是小端,则结果为:

  • 例1的存储情况是|0100|0110|0000|0000|
  • 例2的存储情况是|1100|1001|1111|0000|
  • 例3的存储情况是|1100|1001|1111|1111|

关于getoutdata()

  DicomImage类中getoutdata()函数的使用与上述储存情况息息相关,函数参数作用是取bitsstored的后面多少位,函数参数设为bitsstored的值,然后读出的来的值为实际像素值(自己对有符号无符号进行转换)

DicomImage *image = new DicomImage("test.dcm");Uint16* a= (Uint16*)image->getOutputData(12);vector<Uint16> PixelData;for (int i = 0; i < 512 * 512; i++){    PixelData.push_back(*(a + i));}
阅读全文
0 0