Dicom 计算位图的窗口宽度和窗口中心

Dicom 计算位图的窗口宽度和窗口中心,dicom,fo-dicom,Dicom,Fo Dicom,我正在尝试实现dicom查看器。对于dicom文件,我可以通过设置窗口宽度和窗口中心。但有时我需要设置位图的参数。我已经找到了方法,但它不正确 private Bitmap setWinWidthAndCenter(Bitmap bmp) { int center = (int)vsWindowCenter.Value; int width = (int)vsWindowWidth.Value; var wyMin = center - 0.5 - (width -


我正在尝试实现dicom查看器。对于dicom文件,我可以通过设置窗口宽度和窗口中心。但有时我需要设置位图的参数。我已经找到了方法,但它不正确

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;
}
私有位图集WinWidthandCenter(位图bmp)
{ 
int center=(int)vsWindowCenter.Value;
int width=(int)vsWindowWidth.Value;
var wyMin=中心-0.5-(宽度-1)/2;
var wMax=中心-0.5+(宽度-1)/2;
系统、绘图、颜色;
对于(int i=0;i
也许任何人都知道什么是错的

编辑1:
左侧图像是通过fo dicom库接收到的预期结果。右图像是通过my函数处理后的结果。

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

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

我认为您的线条

var val=(int)((color.R-(中心-0.5))/(宽度-1)+0.5)*255)

这不太正确。我想你想要

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

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

我找到了这个问题的解决办法。
算法是正确的,但有一点:位图有窗口宽度和中心的初始值,有窗口中心: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);
}
公共位图设置WinWidth和CenterforBitmap(位图bmp、双默认中心、双默认宽度、双当前中心、双当前宽度)
{
双difCenter=当前中心-默认中心;
双difWidth=当前宽度-默认宽度;
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;
系统、绘图、颜色;
对于(int i=0;i
你能更具体地说明出了什么问题吗?@WilfRosenbaum,结果比预期的要光明。在这个项目之前,我从来没有做过图像处理,有些事情我不懂。谢谢你的回答。如果我理解正确,位图和原始数据需要不同的参数值才能得到相同的结果。使用原始数据比使用位图更容易操作。对。DICOM头中的数据将引用原始数据值,而不是重建的位图。。。因为我是从一组dicom图像中制作图像的,比如“Onis”程序中的MPR模式。还有一个问题,当用户改变窗口宽度或中心时,我需要用新参数重新渲染整套图像。我认为不是直接重新渲染,而是直接重新渲染部分图像。当使用公式时,有时结果值大于255。如果该值替换为255,不幸的是,这不是预期的结果。我认为@cneller是对的。位图需要不同的值才能得到与原始数据相同的结果。哎呀,我想你的公式还有一个错误。应该是var val=(int)((color.R-wyMin)/(width-1))*255;但是,如果像素值的范围已从原始DICOM文件更改为输入位图,则在将其应用于位图之前,也必须更改窗口中心和宽度。如果原始DICOM图像包含重缩放坡度和截距属性(如CT图像)然后在将窗口中心和宽度应用于图像时也必须考虑这一点;返回与我的公式var val=(int)(((color.R-(center-0.5))/(width-1)+0.5)*255)相同的结果;。无论如何,非常感谢你的帮助,如果我能成功,我会写在这篇文章里。