CT DICOM数据常用16位有符号数据存储,可用DCMTK对其进行解析。
解析方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
DcmFileFormat dfile; OFCondition status1; DcmMetaInfo *metainfo1; status1 = dfile.loadFile("F:\imageData\CT\CTA\DD0215\A3932225"); status1 = dfile.loadFile("F:\imageData\CT\CTA\bianfengying\bianfengying009.dcm"); status1 = dfile.loadFile("F:\imageData\CT\CTA\55\1.2.392.200036.9116.2.1220972159.1407127612.8906.1.26.dcm"); status1 = dfile.loadFile("F:\imageData\CT\12390000\06379867"); metainfo1 = dfile.getMetaInfo(); DcmDataset *data = dfile.getDataset(); DcmElement* element = NULL; data->findAndGetElement(DCM_PixelData, element); DcmElement* Redelementcolor = NULL; data->findAndGetElement(DCM_RedPaletteColorLookupTableData, Redelementcolor); DcmElement* Greenelementcolor = NULL; data->findAndGetElement(DCM_GreenPaletteColorLookupTableData, Greenelementcolor); DcmElement* Blueelementcolor = NULL; data->findAndGetElement(DCM_BluePaletteColorLookupTableData, Blueelementcolor); unsigned short row(0); data->findAndGetUint16(DCM_Rows, row); unsigned short column(0); data->findAndGetUint16(DCM_Columns, column); OFString frame; data->findAndGetOFString(DCM_NumberOfFrames, frame); OFString windowCenter; data->findAndGetOFString(DCM_WindowCenter, windowCenter); OFString windowWidth; data->findAndGetOFString(DCM_WindowWidth, windowWidth); int window_center = 100; int window_width = 700; window_center = atoi(windowCenter.c_str()); window_width = atoi(windowWidth.c_str()); //Uint8* uint8pixdata = nullptr; //element->getUint8Array(uint8pixdata); long count = row*column;// *atoi(frame.c_str()); int m_bytecount = count * sizeof(Uint16); Uint16* uint16pixdata = nullptr; element->getUint16Array(uint16pixdata);
可看到,通过 element->getUint16Array(uint16pixdata),获取得到16位无符号的raw数据。如果需要将其处理成8位数据,还需要进一步处理。
我的处理方式(不一定准确,供探讨)
1.将获取得到的无符号16位数据,转换为有符号16位数据
2.通过窗宽窗位算法,对数据进行压缩,得到处理后的16位有符号数据。(可参考https://blog.csdn.net/wu_uuww/article/details/6286048)
3.通过最大最小值算法,将16位数据压缩成8位无符号数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Sint16 *Sint16PixData = new Sint16[count]; for (int i = 0; i < count; i++) { if (uint16pixdata[i] > 20000) { Sint16PixData[i] = uint16pixdata[i] - 65536; } else { Sint16PixData[i] = uint16pixdata[i]; } } int min2 = 0; int max = 0; min2 = (2 * window_center - window_width) / 2.0 + 0.5; max = (2 * window_center + window_width) / 2.0 + 0.5; Sint16 * sint16PixData2 = new Sint16[count]; unsigned char * uint8PixData = new unsigned char[count]; for (int i = 0; i < count; i++) { Sint16PixData[i] = Sint16PixData[i]; Sint16 temp = (Sint16PixData[i] - min2) * 255 / (max - min2) ; sint16PixData2[i] = temp; } int int16max = getMaxValue(sint16PixData2, count); int int16min = getMinValue(sint16PixData2, count); for (int i = 0; i < count; i++) { int temp = (sint16PixData2[i] - int16min) * 255 / (int16max - int16min); uint8PixData[i] = temp; }
处理前(16位)
处理后(8位)
上面数据有些偏移,还不确定是什么问题。
上述方法供探讨,谢谢!