DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> HTML基礎知識 >> HTML5詳解 >> 基於HTML5的PACS--HTML5圖像處理
基於HTML5的PACS--HTML5圖像處理
編輯:HTML5詳解     

在此之前,此系統是結合DICOM的WADO標准,在浏覽器裡通過Javascript操作返回的JPG圖片。這種服務器端解析,客戶端展現的方式,對實現圖像的移動、縮放、旋轉、測量等圖像操作能夠實現實時的交互。但這種方式存在著幾個弊端:

1.獲取圖像上的CT值(鈣化值)信息的時候,要頻繁的和服務器進行交互。

2.調整圖像的窗寬窗位或者對圖像進行反色,也要和服務器進行頻繁的交互。

3.對圖像進行測量(長方形測量,橢圓測量等)只能獲取到面值和周長的簡單的信息,這對於醫生的診斷沒多大的用處,實際運用中需要知道所測量的區域的最大值、最小值、方差值、均值等測量信息。

 以上的缺點歸結為一點:即本地沒有處理像素信息的操作。但是Html5對於像素級處理的能力已經支持得很好,完成可以實現客戶端對像素信息的操作。所以為了解決以上問題最近對系統做了一次比較大的升級。即客戶端端直接操作DICOM的像素數據進行JS端圖像的生成以及JS端實現窗寬窗位的調整。

獲取dicom中的像素數據,可考慮以下兩種方式:

A:服務器端直接以字節流的方式返回DICOM文件,客戶端用JS來接收字節流,並負責解析DICOM中的圖像數據,這種方式不僅要根據DICOM 的傳輸語法(0002,0010)Transfer Syntax UID,還要根據  (0028,0002)Samples per pixel、(0028,0004)Photometric Interpretation,(0028,0010)Rows,(0028,0011)Columns,(0028,0100)Bits Allocated,(0028,0103)Pixel Representation等標簽來確定像素數據的結構,復雜點的可能還會用到查找表來查找((0028,0004)Photometric Interpretation的值等於==PALETTE COLOR)。對於非壓縮的顯示VR或者是隱形VR, (0028,0004)Photometric Interpretation等於MONOCHROME1或者MONOChrome2來說JS解析出像素數據確實很方便,但是DICOM文件各式各樣,要 寫出包羅給種傳輸語法以及各種像素結構的JS文件確實很費勁。還要考慮到多幀動態圖像,如果多針圖像很大整個文件下載下來解析估計浏覽器會徹底奔潰。所以 覺得這種方式不太可行。(雖然這過程中實現了顯示VR的DICOM文件的JS解析,但是中途考慮到復雜性和難度還是放棄了)。

B:從服務器端獲取DICOM文件的像素數組,既然目前基於C/S模式的PACS已經相當成熟,各式各樣的第三方開源的dicom解析工具如 DCMTK,DCM4CHE,MDCM,OPENDICOM等也相當的多,用開源的DICOM解析工具獲取到像素數據也相當的方便。所以在服務器獲取到像 素數據返回給JS端,讓JS端直接操作像素數據來生成要顯示的圖像。對於多幀圖像也可以按需按幀的從服務器下載像素數據。

言歸正傳,目前此系統是基於第二種方式來實現。需要特別注意的是:做窗寬窗位調整的時候要先做HounsfIEld 值的轉換。 

HU[i] = pixel_val[i]*rescaleSlope+ rescaleIntercept。窗寬窗位的調整使用了線性的window-leveling 算法針對CT/MR等圖像,或者是非線性的gamma算法針對DX圖像(即當windowWidth比較大的時候要考慮非線性的gamma算法,因為線性 算法中每windowWidth/255個原始密度會壓縮成一個顯示灰度,windowWidth很大的時候損失可能會很大)

//線性的window-leveling算法
min = (2*windowCenter - windowWidth)/2.0 - 0.5;  
max = (2*windowCenter + windowWidth)/2.0 - 0.5;
for (var i = 0; i != nNumPixels; i++){
    showPixelValue = (pixelHuValue[i] - min)*255.0/(double)(max - min);
} 
//非線性的gamma算法
min = (2*windowCenter - windowWidth)/2.0 - 0.5;  
max = (2*windowCenter + windowWidth)/2.0 - 0.5;
for (var i = 0; i != nNumPixels; i++){
    showPixelValue = 255.0 * Math.pow(pixelHuValue/(max-min), 1.0/gamma);
}

如下代碼展示JS端如何用後台獲取到的像素數據生成圖像。其中用到了查找表的概念。

/**
 * @author http://www.cnblogs.com/poxiao
 * pixelBuffer代表是從後台獲取到的像素信息數組,代碼只列出了單色灰度圖像的情況,
 * 如果是三色的RGB圖像自己稍微改動下代碼即可。篇幅有限不在敘述。
 **/
var pixelBuffer;
//width 代表圖像的寬度,即DICOM中的標簽(0028,0011)Columns
var width;
//height 代表圖像的高度,即DICOM中的標簽(0028,0010)Rows
var height;
/**
 * @windowCenter 代表當前要顯示的窗位
 * @windowWidth 代表當前要顯示的窗寬
 * @bitsStored (0028,0101) 根據每個像素的存儲位數生成查找表大小
 * @rescaleSlope (0028,1053)用於計算HU值
 * @rescaleIntercept  (0028,1052)用於計算HU值
 * **/
function createImageCanvas(windowCenter,windowWidth,bitsStored,rescaleSlope,rescaleIntercept){
    var lookupObject=new LookupTable();
    lookupObject.setData(windowCenter,windowWidth,bitsStored,rescaleSlope,rescaleIntercept);
    lookupObject.calculateHULookup();
    lookupObject.calculateLookup();
    
    var imageCanvas=document.createElement("canvas");
    imageCanvas.width = width;
    imageCanvas.height =height;
    imageCanvas.style.width = width;
    imageCanvas.style.height = height;
    var tmpCxt = imageCanvas.getContext("2d");
    var imageData = tmpCxt.getImageData(0,0,width,height);
    var n=0;
    for(var yPix=0; yPix<height; yPix++)
    {
        for(var xPix=0; xPix<width;xPix++)
        {
            var offset = (yPix * width + xPix) * 4;
            var pixelValue=lookupObject.lookup[pixelBuffer[n]];
            imageData.data[offset]=    pixelValue;
            imageData.data[offset+1]=pixelValue;
            imageData.data[offset+2]=pixelValue;
            imageData.data[offset+3]=255;
            n++;
        }
    }
    tmpCxt.putImageData(imageData, 0,0);
    
    return imageCanvas;
};
/**
 * 像素查找表,主要要先根據rescaleSlope和rescaleIntercept進行HounsfIEld值的轉換
 * HU[i] = pixel_val[i]*rescaleSlope+ rescaleIntercept
 */
function LookupTable()
{
    this.bitsStored;
    this.rescaleSlope;
    this.rescaleIntercept;
    this.windowCenter;
    this.windowWidth;
    
    this.huLookup;
    this.lookup;
}

LookupTable.prototype.setData=function(wc,ww,bs,rs,ri)
{    
    this.windowCenter=wc;
    this.windowWidth=ww;
    this.bitsStored=bs;
    this.rescaleSlope=rs;
    this.rescaleIntercept=ri;
};

LookupTable.prototype.setWindowingdata=function(wc,ww)
{
    this.windowCenter=wc;
    this.windowWidth=ww;
};

LookupTable.prototype.calculateHULookup=function()
{
    var size=1<<this.bitsStored;
    this.huLookup = new Array(size);
    for(var inputValue=0;inputValue<size;inputValue++)
    {
        if(this.rescaleSlope == undefined && this.rescaleIntercept == undefined) {
            this.huLookup[inputValue] = inputValue;
        } else {       
            this.huLookup[inputValue] = inputValue * this.rescaleSlope + this.rescaleIntercept;
        }
    }
};
/**
 * 窗寬窗位的調整線性的Window-leveling算法
 * 非線性的gamma算法,稍微修改下:
 *  var y=255.0 * Math.pow(this.huLookup[inputValue]/this.windowWidth, 1.0/gamma);
 * **/
LookupTable.prototype.calculateLookup=function()
{    
    var size=1<<this.bitsStored;
    var min=this.windowCenter-0.5-(this.windowWidth-1)/2;
    var max=this.windowCenter-0.5+(this.windowWidth-1)/2;
    this.lookup=new Array(size);
    for(var inputValue=0;inputValue<size;inputValue++)
    {
        if(this.huLookup[inputValue]<=min){
            this.lookup[inputValue]=0 ;
        }else if (this.huLookup[inputValue]>max){
            this.lookup[inputValue]=255;
        }else{                
            var y=((this.huLookup[inputValue]-(this.windowCenter-0.5))/(this.windowWidth-1)+0.5)*255;
            this.lookup[inputValue]= parseInt(y);
        }
    }
};

鼠標調整窗寬窗位的時候JS端生成圖像+繪制圖形的速度。

1.512 X 512大小的CT圖像調整窗寬窗位速度

 2.512 X 512大小的彩色CT圖像調整窗寬窗位速度

 3.512 x 512大小的MR圖像調整窗寬窗位速度

 4.2057 X 1347大小的CR圖像調整窗寬窗位速度

5.有了像素信息後就可以在客戶端實時的獲取到CT值了。

6:有了像素信息後測量也可以獲取到測量區域的最大值、最小值、方差值、均值等測量信息了

進測試,調整窗寬窗位時Html5上繪制圖形的時間還是很快的,總的繪制時間在10毫秒的數量級,而且發現繪制時間還可以變少,這繪制時間包括了圖 像邊角上的文字信息,但是Html5繪制文字的信息效率明顯比繪制圖像的效率要底,所以不必每次刷新都繪制文本信息,可以加以參數控制在圖像切換或者調窗 寬窗位的時候也就是文本信息變化的時候才繪制文字信息。關於圖像的生成時間,發現圖像的生成時間和圖像的寬X高成正比,圖像越大所需時間越長,對於 CT/MR等圖像時間大概在幾十個毫秒級。對於2057X1347的CR圖像時間大概在400毫秒級,對於2000X3000多的DX圖像生成圖像的時間 就有點卡頓了,要1秒-2秒左右。。。這速度還得想辦法優化有木有。。。。。還有對於DX圖像調整窗寬窗位雖然使用了gamma算法,但是出來的圖像,我 總感覺得沒有用第三方工具比如RadiAnt上看見的光滑,噪聲有點大。所以在沒得到更好的解決方案前,目前DX的圖像只能特殊化即保留原來的方式在服務 器端直接生成JPG讓客戶端直接繪制,希望會DICOM圖像算法的大神們看到此文章後能給小弟我一點關於DX調窗寬窗位的意見,是不是還要用到別的算法啥的?。先謝謝了

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved