【转】DELPHI 对DICOM中的窗宽、窗位调整
在寫這篇文章前72小時,我的多窗顯示組件對于個別大W/C值的16位影像顯示還是個問題,也發了帖子到PACS站詢問過,更是在Google上貓刨了很久,終歸一無所獲,今天靜下心來,用了2小時反復查看程序處理過程,對比數據,居然就這么搞定了,原來如此簡單,哎,困惑了3天,把答案公布了,也算是助人為樂(中國地大物博,人心應寬廣無量)
對16位的影像,要判斷DICOM中最大像素值(0028,0107)大于65534,是則將16位影像數據的像素值大于等于0的全部減去65535,小于0的全部加上65535,然后在window-level的方法中將pixel_val按word取值(word是無符號類型,相當于取絕對值)進行判斷,然后賦值即可(CT影像不能用word類型取值和賦值),就這么簡單,以下是關鍵代碼,祝你愉快!!!
?
procedure DCM_GetWidAndCenBySmallint(var DICOMDATA: TDICOMDATA; var Buffer: SMallIntp0);
var
? Value, Size, i: integer;
? min16, max16: integer;
begin
? Size := DICOMDATA.ImageColumns * DICOMDATA.ImageRows;
? Value := Buffer[0];
? max16 := Value;
? min16 := Value;
? i := 0;
? while i < Size do begin
??? Value := Buffer;
??? if Value < min16 then min16 := Value;
??? if Value > max16 then max16 := Value;
??? i := i + 1;
? end;
? if DICOMDATA.MaxIntensity = 0 then DICOMDATA.MaxIntensity := max16;
? if (DICOMDATA.MaxIntensity > 65534) then begin//這里對高CT值的數據進行處理
??? i := 0;
??? while i < (Size) do begin
????? if Buffer >= 0 then
??????? Buffer := Buffer - 65535
????? else
??????? Buffer := 65535 + Buffer;
????? i := i + 1;
??? end;
? end;
? DICOMDATA.WinCen := round(DICOMDATA.WindowCenter);
? DICOMDATA.WinWid := round(DICOMDATA.WindowWidth);
? DICOMDATA.ImgMin := min16;
? DICOMDATA.ImgMax := max16;
? DICOMDATA.ImgWid := DICOMDATA.ImgMax - DICOMDATA.ImgMin;
? DICOMDATA.ImgCen := DICOMDATA.ImgMin + ((DICOMDATA.ImgWid) shr 1);
? if DICOMDATA.WindowWidth <= 0 then begin
??? DICOMDATA.WinCen := DICOMDATA.ImgCen;
??? DICOMDATA.WinWid := DICOMDATA.ImgWid;
??? DICOMDATA.WindowCenter := DICOMDATA.ImgCen;
??? DICOMDATA.WindowWidth := DICOMDATA.ImgWid;
? end;
end;
procedure DCM_Scale16to8bit(var DICOMDATA: TDICOMDATA; var Buffer: SMallIntp0; var lOutBuff: pByteArray; DataLen: integer);
var
? Value, i, lScaleShl10, Size, lWid, lcen: integer;
? min16, max16: integer;
? PixelVal: integer;
? Modality_CT: boolean;
begin
? if Buffer = nil then exit;
? //影像是否是CT
? if (DICOMDATA.TransferSyntax = '1.2.840.10008.5.1.4.1.1.2') or (trim(DICOMDATA.Modality) = 'CT') then
??? Modality_CT := true
? else
??? Modality_CT := false;
? DICOMDATA.WinCen := round(DICOMDATA.WindowCenter);
? DICOMDATA.WinWid := round(DICOMDATA.WindowWidth);
? Size := DICOMDATA.ImageColumns * DICOMDATA.ImageRows;
? lcen := round((round(DICOMDATA.WindowCenter) - DICOMDATA.IntenIntercept) / DICOMDATA.IntenScale); // 截距/斜率
? lWid := (trunc((round(DICOMDATA.WindowWidth) / DICOMDATA.IntenScale) / 2));
? min16 := lcen - lWid; //15za
? max16 := lcen + lWid; //15za
? getmem(lOutBuff, Size);
? Size := Size - 1;
? Value := (max16 - min16);
? if (Value = 0) or (trunc((1024 / Value) * 255) = 0) then begin
??? if DICOMDATA.WinWid > 1024 then begin
????? for i := 0 to Size do
??????? lOutBuff := 128;
??? end else begin
????? for i := 0 to Size do
??????? if Buffer < DICOMDATA.WinCen then
????????? lOutBuff := 0
??????? else
????????? lOutBuff := 255;
??? end;
? end else begin
??? if Value = 0 then Value := 1;
??? lScaleShl10 := trunc((1024 / Value) * 255); //value = range,Scale = 255/range
??? for i := 0 to Size do begin
????? //除CT外,其余的全部取正值
????? if Modality_CT then begin
??????? if (Buffer) < min16 then
????????? lOutBuff := 0
??????? else if (Buffer) > max16 then
????????? lOutBuff := 255
??????? else
????????? lOutBuff := (((Buffer) - min16) * lScaleShl10) shr 10;
????? end else begin //非CT
??????? if word(Buffer) < min16 then
????????? lOutBuff := 0
??????? else if word(Buffer) > max16 then
????????? lOutBuff := 255
??????? else
????????? lOutBuff := ((word(Buffer) - min16) * lScaleShl10) shr 10;
????? end;?
??? end;
? end;
? DICOMDATA.BitsStored := 8; //轉換為8位
end;
?
總結
以上是生活随笔為你收集整理的【转】DELPHI 对DICOM中的窗宽、窗位调整的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 兴业PASS信用卡:网上支付笔笔有积分
- 下一篇: earthdata数据的.nc4如何使用