關於醫學圖像處理中鈣化積分的計算


前言

最近在做一個醫學圖像處理的項目,項目的內容就是在拉直的血管上面找到鈣化的部分,並且計算出鈣化積分。

效果圖如下所示:  

第一章   醫學背景知識介紹

1.1 冠脈動脈鈣化以及鈣化積分定義

      冠狀動脈鈣化(CAC)的定性檢測根據病變大小超過某一面積或體積閾值、密度超過規定的CT值閾值即可區分冠狀動脈斑塊內的病變是否為鈣化。冠狀動脈鈣化積分(CACS)中傳統的積分法AS定義面積閾值為1 mm2、CT值閾值為130 Hu。Detrano等使用8.16mm3的體積作為鈣化灶大小的閾值。質量積分[10]定義面積閾值為連續的3個像素、CT值閾值為130 Hu。Nelson等[11]所使用的面積閾值為4個緊鄰的像素,CT值閾值為130 Hu。另有研究者認為[12]不應使用某一固定的CT值作為病灶的密度閾值,因為同一密度的物體在不同CT機上的CT值可能有差異,故推薦使用一個固定的含鈣濃度值(100 mg/cc)作為閾值。然而Glodny等[13]卻嘗試在CCTA圖像中將冠狀動脈上CT值大於600 Hu的像素分離出來作為鈣化灶來研究,這種方法雖有偏頗,會明顯低估鈣化斑塊負荷,但其結果卻和常規CACS有高度線性相關性,甚至認為該方法可用於替代常規CACS以避免CACS掃描導致的電離輻射,這一觀點尚待進一步的考證。

     Agatston等[2]首次使用了CACS對冠狀動脈鈣化斑塊進行了定量分析,稱之為Agatston 積分(Agatston Score, AS),
AS= Σ (CT值 × 面積 × 權重系數)。
CT值越高,權重系數越大,具體如下:130~199 Hu為1,200~299 HU為2,300~399 Hu為3,等於或大於400 Hu為4。
1998年Callister等[14]報道了CAC的容積積分(Volume Score,VS)的定量分析。VS等於所有鈣化斑塊的容積之和。VS積分法所計算的是鈣化的體積,而與鈣化灶的密度變化沒有對應關系。
2005年Nelson等[11]使用了質量積分(Mass Score,MS)進行CAC的定量測量。MS的檢測相對復雜,該方法須使用羥磷灰石鈣校准體模,此體模由數個含鈣濃度不同的模塊組成,且濃度已知。體模與受檢者須同時進行掃描。通過測量各個模塊的CT值便可確定CT值與含鈣濃度的計算關系,即:

體模CT值 = 斜率 × 體模含鈣濃度 + 截距。

測出各個模塊的CT值,可計算出斜率和截距。然后測量冠狀動脈鈣化斑塊的CT值,根據上述關系計算出鈣化斑塊的含鈣濃度,即:

鈣化斑塊的含鈣濃度 = (鈣化斑塊平均CT值-截距) ÷ 斜率。

最后通過軟件計算出冠狀動脈全部鈣化斑塊的質量積分,即:

MS = ∑(鈣化灶的含鈣濃度 × 容積)。

AS是較客觀的CAC量化分析方法,早己受到了影像界的認可,臨床應用廣泛,一直是傳統的鈣化斑塊定量分析參數,但此方法的重復性不高,使病人間的對照及隨訪觀察結果可信度下降。VS的重復性與AS相比有所改善,可用於高危人群隨訪及冠心病人治療后復查。VS主要缺點是由於受部分容積效應的影響,另一方面VS沒有考慮鈣化斑塊的CT值,而CT值的高低可能代表了斑塊的演變階段,因此可能存在一定的片面性,而且此方法的重復性仍有不足。由於每位患者的含鈣濃度均是在體模校准的基礎上獲得,不受設備、掃描協議或患者個體差異的影響,其結果具有可比性,因而MS有良好的可重復性和准確性。在掃描協議標准化后,多中心的體模研究[8]使用不同生產廠商的CT機、不同機型的CT機進行CACS測量,結果為AS、VS與MS的變異系數分別為7.9%、4.0%、2.8%, MS具有最高的重復性和准確性,這與絕大部分研究結果一致。MS是國際心臟CT標准化協會物理工作組(the Physics Task Group ofthe International Consortium on Standardization in Cardiac CT)推薦的鈣化定量分析方法[12]

1.2窗寬、窗位、CT值

      人體組織CT值的范圍為-1000到+1000共2000個分度,人眼不能分辨這樣微小灰度的差別,僅能分辨16個灰階。為了提高組織結構細節的顯示, 能分辨CT值差別小的兩種組織,操作人員可以根據診斷需要調節圖像的對比度和亮度,這種調節技術稱為窗技術-窗寬、窗位的選擇。

      窗寬是指顯示圖像時所選用的CT值范圍,在此范圍內的組織結構按其密度高低從白到黑分為16個等級(灰階)。如窗寬為160Hu,則可分辨的CT值為160/16=10Hu,即兩種組織CT值的差別在10Hu以上者即可分辨出來。 由此可見窗寬的寬窄直接影響圖像的對比度;窄窗寬顯示的CT值范圍小,每級灰階代表的CT值幅度小,因而對比度強,可分辨密度較接近的組織或結構,如檢查腦組織宜選用窄的窗寬;反之,窗寬加寬則每級灰階代表的

CT值幅度增大,對比度差,適於分辨密度差別大的結構如肺、骨質。窗位是指窗寬上、下限CT值的平均數。因為不同組織的CT值不同,欲觀察其細微結構最好選擇該組織的CT值為中心進行掃描,這個中心即為窗位。窗位的高低影響圖像的亮度:窗位低圖像亮度高呈白色;窗位高圖像亮度低呈黑色,但在實際操作中尚須兼顧其它結

構選用適當的窗位。總之,如要獲得較清晰且能滿足診斷要求的CT圖像,必須選用合適的窗寬、窗位,否則

圖像不清楚,還往往難以達到診斷要求,降低了CT掃描的診斷效能。

正常人體組織的CT值:

類別
CT值(HU)
0±10
腦脊液
3-8
血漿
3-14
水腫
7-17
腦白質
25-32
腦灰質
30-40
血液
13-32
血塊
64-84
肝臟
50-70
脾臟
50-65
胰腺
45-55
腎臟
40-50
肌肉
40-80
膽囊
10-30
脂肪
-20~-80
鈣化
80-300
空氣-200HU以上
骨骼+400以上

     窗寬,窗位,CT值之間的數量關系:通俗的說:窗位是窗寬的中位數數值,窗寬是范圍,比如窗寬250,窗位50,CT值范圍是-75~175HU,CT值的范圍的中位數必須是50,而范圍則是250。換算成公式的話如下:

 CT值的下限x = L-W/2,上限y = L+W/2;
其中,L代表窗位的數值,W代表窗寬數值。
   
 第二章  算法設計
2.1待續
 
第三章  部分代碼
3.1vtk to OpenCV
/*****************************************************/
/*
@function name:vtk2ipl
@function:vtk格式圖片轉化到opencv格式
@parameters
srcDataVtk,sliceOrder:輸入,srcDataVtk是vtkImageData格式體數據,sliceOrder是要抽取的體數據的slice編號
dstDataMat :輸出,dstDataMat 是opencv格式圖像
@result:
@Notes:
*/
/*****************************************************/


void calScore::vtk2ipl(vtkImageData *srcDataVtk,Mat &dstDataMat,int sliceOrder)
{
    vtkImageShiftScale* shiftScale = vtkImageShiftScale::New();
    shiftScale->SetInput(srcDataVtk);
    shiftScale->SetShift(-(800 - 0.5*1680));//800level,1680windows 這里
    shiftScale->SetScale(255.0/1680);
    shiftScale->SetOutputScalarTypeToUnsignedChar();
    shiftScale->ClampOverflowOn();
    shiftScale->Update();

    if (c_mode_XYZ =="XZ")//xz平面
    {
        cv::Mat image(dims[0], dims[2], CV_8UC1);

        for (int i=0; i<dims[0]; ++i) 
        {
            for (int j=0; j<dims[2]; ++j) 
            {
                image.at<unsigned char>(cv::Point(j,i)) = 
                    *static_cast<unsigned char*>(shiftScale->GetOutput()->GetScalarPointer(i,sliceOrder,j));
            }
        }
        imwrite("D:\\cvimg.bmp",image);
        image.copyTo(dstDataMat);
    }

    if (c_mode_XYZ =="YZ")//yz平面
    {
        cv::Mat image(dims[1], dims[2], CV_8UC1);

        for (int i=0; i<dims[1]; ++i) 
        {
            for (int j=0; j<dims[2]; ++j) 
            {
                image.at<unsigned char>(cv::Point(j,i)) = 
                    *static_cast<unsigned char*>(shiftScale->GetOutput()->GetScalarPointer(sliceOrder,i,j));
            }
        }
        imwrite("D:\\cvimg.bmp",image);
        image.copyTo(dstDataMat);
    }

    if (c_mode_XYZ =="XY")//xy平面
    {
        cv::Mat image(dims[0], dims[1], CV_8UC1);

        for (int i=0; i<dims[0]; ++i) 
        {
            for (int j=0; j<dims[1]; ++j) 
            {
                image.at<unsigned char>(cv::Point(j,i)) = 
                *static_cast<unsigned char*>(shiftScale->GetOutput()->GetScalarPointer(i,j,sliceOrder));
                
            }
        }
        imwrite("D:\\cvimg.bmp",image);
        image.copyTo(dstDataMat);
    }
    
    //free
    shiftScale->Delete();
}

 

 3.2 OpenCV to VTK

 

 1 /*****************************************************/
 2      /*
 3      @function name:ipl2vtk
 4      @function:opencv格式圖片轉化到vtk格式
 5      @parameters
 6      _src:輸入,-src 是OpenCV數據
 7      _dest :輸出,_dest 是vtk格式圖像
 8      @result:
 9      @Notes:
10      */
11     /*****************************************************/
12 void calScore::ipl2vtk(IplImage* _src, vtkImageData* _dest)
13 {
14     vtkImageImport *importer = vtkImageImport::New();
15     if ( _dest )
16     {
17         importer->SetOutput( _dest );
18     }
19     importer->SetDataSpacing( 1, 1, 1 );
20     importer->SetDataOrigin( 0, 0, 0 );
21     importer->SetWholeExtent(  0, _src->width-1, 0, _src->height-1, 0, _src->nChannels-1 );
22     importer->SetDataExtentToWholeExtent();
23     importer->SetDataScalarTypeToUnsignedChar();
24     importer->SetNumberOfScalarComponents( _src->nChannels );
25     importer->SetImportVoidPointer( _src->imageData );
26     importer->Update();
27 
28     //free
29     importer->Delete();
30 
31 }

 

3.3 抽取slice

 

 

/*****************************************************/
     /*
     @function name:extractSlice
     @function:抽取slice
     @parameters
     _srcvtk,sliceOrder:輸入,_srcvtk是vtkImageData格式體數據,sliceOrder是要抽取的體數據的slice編號
     @result:返回抽取的slice數據,數據格式是vtkImageData
     @Notes:
     */
    /*****************************************************/
vtkImageData *calScore::extractSlice(vtkImageData *_srcvtk,int sliceOrder)
{
    _srcvtk = vtkImageData::New();
    _srcvtk->SetDimensions(imageData->GetDimensions());
    _srcvtk->SetScalarTypeToDouble();
    _srcvtk->SetNumberOfScalarComponents(4);
    _srcvtk->AllocateScalars();
    _srcvtk->DeepCopy(imageData);
    _srcvtk->Update();
    

    vtkExtractVOI*extractVOI = vtkExtractVOI::New();
    //extractVOI->SetInput(_srcvtk);
    extractVOI->SetInput(imageData);

    if (c_mode_XYZ =="XZ")//xz平面
    {
        extractVOI->SetVOI(0,dims[0],sliceOrder,sliceOrder,0,dims[2]);
    }

    if (c_mode_XYZ =="YZ")//yz平面
    {
        extractVOI->SetVOI(sliceOrder,sliceOrder,0,dims[1],0,dims[2]);
    }

    if (c_mode_XYZ =="XY")//xy平面
    {
        extractVOI->SetVOI(0,dims[0],0,dims[1],sliceOrder,sliceOrder);
    }
    
    extractVOI->Update();

    //vtkImageData *imgData2D = vtkImageData::New();
    //imgData2D->DeepCopy(extractVOI->GetOutput());
    
    //return imgData2D;
    return extractVOI->GetOutput();
}

 

第四章 總結
4.1待續
 
 
 
 
         1.2節 http://blog.sina.com.cn/s/blog_4c88d09a0100k8b1.html   http://www.dxy.cn/bbs/thread/20979764#20979764


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM