16位CT DICOM数据转换为8位
CT DICOM数据常用16位有符号数据存储,可用DCMTK对其进行解析。
解析方法:

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位无符号数据

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位)
上面数据有些偏移,还不确定是什么问题。
上述方法供探讨,谢谢!
分类:
DICOM/DCMTK
标签:
CT 16位转8位 DCMTK
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!