3


我正在尝试实现一个 dicom 查看器。对于 dicom 文件,我可以通过fo-dicom framework设置窗口宽度和窗口中心。但有时我需要为位图设置参数。我已经找到了如何做到这一点,但它不能正常工作。

private Bitmap setWinWidthAndCenter(Bitmap bmp)
{ 
    int center = (int)vsWindowCenter.Value; 
    int width = (int)vsWindowWidth.Value;
    var wyMin = center - 0.5 - (width - 1) / 2;
    var wMax = center - 0.5 + (width - 1) / 2;
    System.Drawing.Color color;
    for (int i = 0; i < bmp.Width; i++)
    {
        for (int j = 0; j < bmp.Height; j++)
        {
            color = bmp.GetPixel(i, j);
            if (color.R <= wyMin)
                color = System.Drawing.Color.FromArgb(0, 0, 0);
            else if (color.R > wMax)
                color = System.Drawing.Color.FromArgb(255, 255, 255);
            else
            {
                var val = (int)(((color.R - (center - 0.5)) / (width - 1) + 0.5) * 255);
                color = System.Drawing.Color.FromArgb(val, val, val);
            }
            bmp.SetPixel(i, j, color);
        }
    }
    return bmp;
}

可能有人知道出了什么问题。

编辑 1:
左图是通过 fo-dicom 库收到的预期结果。正确的图像是通过我的函数处理后的结果。
在此处输入图像描述 在此处输入图像描述

4

3 回答 3

4

查看您的中心和宽度值。它们可能特定于 12 位或 16 位单色图像。这将使它们与您使用的限制性 0-255 RGB 位图有很大不同。

您要么必须正确缩放中心和宽度值,要么使用原始单色数据。

于 2015-10-09T15:14:35.583 回答
2

我觉得你的台词

var val = (int)(((color.R - (center - 0.5)) / (width - 1) + 0.5) * 255);

不太正确。我想你想要

var val = (int)(( (color.R - wyMin) / (width - 1) + 0.5) * 255);

您正在尝试设置分段线性变换,将小于 wyMin 的 x 值映射到 0,将大于 wMax 的值映射到 255,并将中间 x 值映射到 0 到 255 之间的中间值。

于 2015-10-09T23:58:59.667 回答
0

我找到了解决问题的方法。
该算法是正确的,但有一点:位图具有窗口宽度和中心的初始值,窗口中心:127 和窗口宽度 255。
我们需要做的就是计算 dicom 文件中初始值之间的差异和我们想要设置的值。然后我们可以将获得的值添加到初始位图值。
正确的代码如下所示。

public Bitmap setWinWidthAndCenterForBitmap(Bitmap bmp, double defaultCenter, double defaultWidth, double currentCenter, double currentWidth)
{
    double difCenter = currentCenter - defaultCenter;
    double difWidth = currentWidth - defaultWidth;
    int WinCenter = 127 + (int)difCenter;
    int WinWidth = 255 + (int)difWidth;
    var wMin = WinCenter - 0.5 - (WinWidth - 1) / 2;
    var wMax = WinCenter - 0.5 + (WinWidth - 1) / 2;
    System.Drawing.Color color;
    for (int i = 0; i < bmp.Width; i++)
    {
        for (int j = 0; j < bmp.Height; j++)
        {
            color = bmp.GetPixel(i, j);
            color = System.Drawing.Color.FromArgb(
                calculateColor(color.R, wMin, wMax, WinCenter, WinWidth),
                calculateColor(color.G, wMin, wMax, WinCenter, WinWidth),
                calculateColor(color.B, wMin, wMax, WinCenter, WinWidth));
            bmp.SetPixel(i, j, color);
        }
    }
    return bmp;
}
private byte calculateColor(byte c, double wMin, double wMax, double WinCenter, double WinWidth)
{
    if (c <= wMin)
        return 0;
    else if (c > wMax)
        return 255;
    else
        return (byte)(((c - (WinCenter - 0.5)) / (WinWidth - 1) + 0.5) * 255);
}
于 2016-02-25T09:58:36.343 回答