簡體   English   中英

Fo-Dicom Window 變化緩慢

[英]Fo-Dicom Window Change is slow

我正在使用以下渲染代碼。 這是一個稍微修改過的代碼,因為在實際代碼中,我從 FTP 服務器獲取所有文件。 CurrentWindowCenter 和 CurrentWindowWidth 保存 WL 和 WW 的當前值。 可以從 UI 更改此值。 我使用 canvas 中的圖像組件直接向用戶顯示渲染的 WritableBitmap。但是圖像的渲染速度非常慢。 特別是對於 X 射線等文件較大的圖像。 所以,WW 和 WL 的變化也很慢,因為它也使用渲染 function。我對此不是很了解。 但是有沒有辦法讓渲染或者WW/WL變化的更快呢? 有沒有辦法在每次 WW/WL 發生變化時跳過圖像的渲染? 對正確方向的任何建議表示贊賞。 提前致謝。

// assume filePath holds an actual file location. 
 var filePath = "";
 var dicomFile = new DicomFile.Open(filePath);
 var dicomImage = new DicomImage(dicomFile.DataSet);
 if (CurrentWindowCenter.HasValue && CurrentWindowWidth.HasValue)
 {
     dicomImage.WindowCenter = Convert.ToDouble(CurrentWindowCenter.Value);
     dicomImage.WindowWidth = Convert.ToDouble(CurrentWindowWidth.Value);
 }
 dicomImage.RenderImage().AsWriteableBitmap();

環境

  • Fo-Dicom (4.0.8)
  • .NET 框架 4.8
  • WPF

我的猜測是 fo-dicom 並不是真正為高性能而設計的,更多的是為了兼容性。 為了獲得最佳性能,您應該通過 DirectX、OpenCL 或類似工具使用 GPU。 第二好的應該是一些緊密優化的 SIMD 代碼,可能使用 c++。

但僅使用 c# 可能會有一些改進。從外觀上看,fo-dicom 創建了一個新圖像,將像素復制到該圖像,然后創建一個 writeableBitmap 並執行另一個副本。 這些步驟將花費一些額外的時間。

我復制像素和應用 lut/transfer function 的代碼如下所示:

public static unsafe void Mono16ToMono8(
    byte* source,
    byte* target,
    int sourceStride,
    int targetStride,
    int width,
    int height,
    byte[] lut)
{
    Parallel.For(0, height, y =>
    {
        var ySource = source + y * sourceStride;
        var yTarget = target + y * targetStride;
        var srcUshort = (ushort*)ySource;
        for (int x = 0; x < width; x++)
        {
            var sample = srcUshort[x];
            yTarget[x] = lut[sample];
        }
    });
}

以及對可寫 bitmap 進行實際更新的代碼:

public static unsafe void Update(
    this WriteableBitmap self,
    IImage source,
    byte[] lut)
{
    self.Lock();
    try
    {
        var targetPtr = (byte*)self.BackBuffer;
        fixed (byte* sourcePtr = source.Data)
        {
            if (source.PixelFormat == PixelType.Mono16)
            {
                Mono16ToMono8(
                    sourcePtr,
                    targetPtr,
                    source.Stride,
                    self.BackBufferStride,
                    source.Width,
                    source.Height,
                    lut);
            }
        }
        self.AddDirtyRect(new Int32Rect(0, 0, (int)self.Width, (int)self.Height));
    }
    finally
    {
        self.Unlock();
    }
}

這使用內部 IImage 格式,其中source.DataReadOnlySpan<byte> ,但也可以是byte[] 我希望大多數其他屬性都是不言自明的。 我希望這段代碼會更快一些,因為它避免了分配和一些復制步驟。

所有這些都假設圖像是 16 位無符號格式,這在 dicom 中很常見,但不是唯一的格式。 它還假設您實際上可以獲得指向實際像素緩沖區的指針,以及將每個可能的像素值映射到一個字節的 lut 數組。 它還假定具有正確大小和顏色空間的可寫位圖。

如前所述,如果您既想要高性能,又想要處理所有可能的圖像格式,您可能需要投入時間來構建自己的圖像渲染管道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM