读取Elekta(医科达)CBCT采集的HIS图像

这篇文章是放射物理相关文章。

1 放射治疗中的两个重点

在肿瘤的放射治疗中,我们最关心的两个问题中的第一个是剂量的计算准确性,另一个是照射位置的准确性。剂量的计算等我们以后说,我们先说说怎么保证照射位置的准确性。

在放射治疗的历史发展中,为了确定照射位置的准确性,医生和物理师们做出了很多贡献。1895年伦琴发现了X射线后,接下来几年,X射线就被用来治疗肿瘤了。

一开始由于射线能量比较低,只能治疗表浅肿瘤。后来居里夫人等发现了放射性核素,核素放射出来的射线能量就高了很多了,可以治疗更深的肿瘤了。一开始,对于表浅肿瘤,医生在患者的皮肤表面画好标记,然后让技师进行照射。后来随着计算机的发明,放射治疗进行了质的提升。70年代CT机的出现,更是带来了破天荒的突破。可以对肿瘤和正常组织扫面,3D重建,可以完全在CT图像中确定肿瘤的位置、大小和形状。3D适型计划系统的出现,可以准确的计算剂量,同时还可以使用CT模拟机进行精确的定位。

最早,确定肿瘤位置的方法是采用拍摄正位和侧位胶片的方法,来确定肿瘤和铅挡块的位置,从而保证照射时位置的准确。随着EPID的出现,可以使用EPID进行正侧位照片的拍摄,完全电子化,快速方便。随着Cone Beam CT在加速器上的安装,可以在治疗前对患者进行CT扫描,重建,更加准确的确定肿瘤的位置,为精准放射治疗提供可能。

2 Elekta CBCT图像的获取

医科达加速器配备的CBCT,扫描后的图像是HIS格式。扫描时,使用kV射线(80-140kV)进行旋转扫描,探测器也是EPID板(可以采集kV射线)。根据设定,每隔0.5度左右吧(根据_Frames.xml数据推算)获取一张透射图像。然后根据图像的位置信息将获取到的600+张图像进行重建(FDK算法)。

3 单张HIS图像的读取

单张HIS图像的内容是什么呢?到底是什么格式?因此本篇文章就是研究怎么读取单张HIS文件,并将它显示出来。

首先查看_Frames.xml文件

<DicomUID>1.3.12.2.1107.5.1.4.92303.30000019060503011740200000028</DicomUID>
  </Treatment>
  <Field>
    <Id>***KV-IMAGES***</Id>
    <Description></Description>
  </Field>
  <Image>
    <kV>100</kV>
    <mA>40</mA>
    <ms>40</ms>
    <AcquisitionPresetName>Head and Neck S20 CW</AcquisitionPresetName>
    <Width>512</Width>
    <Height>512</Height>
    <Depth>16</Depth>
    <ReadoutOrientation>V</ReadoutOrientation>
    <DicomUID>1.3.46.423632.337391202112324925803.1</DicomUID>
    <CTDIvol>1.0</CTDIvol>
    <CTDIPhantomType>Head Phantom (Length 15cm)</CTDIPhantomType>
    <AbsoluteTableLatPosIEC1217_MM>15.6</AbsoluteTableLatPosIEC1217_MM>
    <AbsoluteTableLongPosIEC1217_MM>234.3</AbsoluteTableLongPosIEC1217_MM>
    <AbsoluteTableVertPosIEC1217_MM>-132.1</AbsoluteTableVertPosIEC1217_MM>
  </Image>
  <Frames>
    <Frame>
      <Seq>1</Seq>
      <DeltaMs>0</DeltaMs>
      <HasPixelFactor>False</HasPixelFactor>
      <PixelFactor>0</PixelFactor>
      <GantryAngle>-175.103530884</GantryAngle>
      <Exposed>True</Exposed>
      <MVOn>False</MVOn>
      <UCentre>1.224934578</UCentre>
      <VCentre>0.268885463</VCentre>
      <Inactive>False</Inactive>
    </Frame>

我们看到了,图像的维度是512x512,16位图。

然后上C++代码,使用的文件在这里:https://download.csdn.net/download/kangdehua/16490699

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <opencv2/opencv.hpp>

using namespace std;

int main(int,char* [])
{
    string fileName="../data/test.1.his";
    // 读取文件,以二进制模式读取
    fstream input(fileName.c_str(),ios::binary|ios::in);
    char buffer[100];               // read function can only get 1 Byte every time.
    input.read(buffer,100);  // read 100 Bytes every time.
    // 因为我偷偷的知道了文件头有100个字节(哈哈)

    // use vector store the header information.
    vector<unsigned short> header;  // 因为我们已经知道文件数据是16位数据了,所以使用 16位类型保存数据

    for(int i=0;i<50;++i){
        unsigned short p=buffer[2*i+1]<<8|buffer[2*i+0];    // use the little Endian.
        header.push_back(p);
    }

    // Display the header
    for(vector<unsigned short>::iterator it=header.begin();it!=header.end();++it){
        cout<<*it<<endl;
    }

    unsigned short row,col;
    row=header[8];
    col=header[9];
    cout<<"The row and column are: "<<row<<","<<col<<endl;

    // Read the data in the his file.
    input.seekg(100,ios::beg);  // 跳过前面100个字节的文件头
    int size=512*512;    //262144    double is 524288
    unsigned short pixel[size];
    char data[size*2];
    input.read(data,size*2);   // 读取后面的所有图像像素数据
    for(int i=0;i<size;++i){
        pixel[i]=data[2*i+1]<<8|data[2*i+0];  //小端字节序
    }

    // Display the image using OpenCV
    // 借用OpenCV,方便。
    cv::Mat image=cv::Mat(col,row,CV_16UC1,pixel);
    cv::normalize(image,image,0,255,cv::NORM_MINMAX,CV_8UC1);
    cv::imshow("His Image",image);
    cv::waitKey();


    return 0;
}

这里面的关键点是字节序的读取方法,注意16位数据按照顺序读取后,需要按照小端字节序还原成原来的数据。

显示结果:

图1 Elekta CBCT单张HIS图像

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值