您的位置:首页 > 其它

DCM医学影像文件的格式与读取方法分享

2014-01-10 13:25 676 查看
医学影像DCM是个类似PNG的分块格式,内涵丰富医疗信息,由于应用领域较窄,OpenCV没有提供对其加载支持,一般采用dcmtk库进行加载。

博主本着研究探索的精神写了这段代码,并分享出来,提供了解析DCM的DIB数据、宽高、窗宽窗位、像素间距的功能,支持反色DCM。

将来可以参考spec文档进行扩充,可以在大框架中加入块的处理,从而抽取更多感兴趣的信息,也可以加入压缩DCM的支持。

// 输入:文件名
// 输出:宽高 窗宽窗位 像素间距 dib
unsigned short* dcmLoadImage(char* fn, int& width, int& height, int& windowWidth, int& windowLevel, double& pixelSpacing)
{
// 读取整个文件到内存
FILE* f = fopen(fn, "rb");
fseek(f, 0, SEEK_END);
int dcmSize = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char* dcm = new unsigned char[dcmSize];
fread(dcm, dcmSize, 1, f);
fclose(f);

// 解析
width = -1;
height = -1;
windowWidth = -1;
windowLevel = -1;
pixelSpacing = 0.0;
bool invert = false;
unsigned short* dib = NULL;
int dibSize = -1;
int p = 132;
while( p<dcmSize )
{
short group = *(short*)(dcm+p);
p+=2;
short element = *(short*)(dcm+p);
p+=2;
//cout<<setfill('0')<<hex<<setw(4)<<group<<","<<setw(4)<<element<<setfill('\0')<<dec<<endl;

if(group==0x0002)
{
if(element==0x0001)// 2,1
{
p+=10;
}
else// 2,*
{
char vr[3];
vr[0] = dcm[p++];
vr[1] = dcm[p++];
vr[2] = '\0';
short size = *(short*)(dcm+p);
p+=2;
p+=size;
}
}
else// *
{
int size = *(int*)(dcm+p);
p+=4;
if(size==-1)
size=0;
if(group==0x0028&&element==0x0010)
height = *(short*)(dcm+p);
if(group==0x0028&&element==0x0030)
pixelSpacing = atof((char*)dcm+p);
if(group==0x0028&&element==0x0004)
invert = !strncmp((char*)dcm+p, "MONOCHROME1", 11);
else if(group==0x0028&&element==0x0011)
width = *(short*)(dcm+p);
else if(group==0x0028&&element==0x1050)
windowLevel = atoi((char*)dcm+p);
else if(group==0x0028&&element==0x1051)
windowWidth = atoi((char*)dcm+p);
else if(group==0x7FE0&&element==0x0010)
{
dibSize = size;
dib = new unsigned short[dibSize];
memcpy(dib, dcm+p, dibSize);
}
p+=size;
}
}
assert(p==dcmSize);
assert(width!=-1);
assert(height!=-1);
assert(windowLevel!=-1);
assert(windowWidth!=-1);
assert(dib!=NULL);
assert(dibSize==width*height*2);

// 反图做修正
if(invert)
{
for(int i=0; i<width*height; i++)
dib[i] ^= 0xFFFF;
windowLevel = 65535-windowLevel;
}

delete[] dcm;
return dib;
}

void dcmReleaseImage(unsigned short* dib)
{
delete[] dib;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: