You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中基于SimpleITK读取DICOM图像的像素值转Color方法问询

将DICOM单通道像素值转换为Unity Color32的解决方案

首先,DICOM的单值像素(通常是灰度值或HU值)转成Unity的RGBA格式逻辑很清晰——因为是灰度图,我们只需要把R、G、B三个通道设为相同的归一化后的值,Alpha通道设为255(完全不透明)即可。不过要注意:DICOM原始像素值往往不是0-255的范围(比如CT的HU值范围是-1024到3071),必须先做归一化或窗宽窗位映射,否则显示会出现全黑、过曝等问题。

基础灰度转换(无窗宽窗位)

如果你的liverVoxels已经是归一化到0-1的float值,直接乘255转成byte就行:

// 假设pixel已在0-1范围内
byte grayValue = (byte)(pixel * 255f);
Color32 _col = new Color32(grayValue, grayValue, grayValue, 255);

如果liverVoxels是原始DICOM像素值(比如HU值),需要先计算全局最大最小值做归一化:

// 提前计算所有像素的最值(放在循环外,避免重复计算浪费性能)
float minPixel = liverVoxels.Min();
float maxPixel = liverVoxels.Max();

// 像素循环内的处理:
float normalizedPixel = (pixel - minPixel) / (maxPixel - minPixel);
normalizedPixel = Mathf.Clamp01(normalizedPixel); // 确保值被限制在0-1区间
byte grayValue = (byte)(normalizedPixel * 255f);
Color32 _col = new Color32(grayValue, grayValue, grayValue, 255);

专业医学图像窗宽窗位处理

对于DICOM医学图像(比如肝脏CT),通常需要用**窗宽(Window Width)和窗位(Window Level)**来调整显示,突出目标组织细节。公式如下:

// 肝脏CT常用窗位WL=50,窗宽WW=150,可根据你的图像调整
float WL = 50f;
float WW = 150f;
float lowerBound = WL - WW / 2f;
float upperBound = WL + WW / 2f;

// 将像素值映射到0-1范围
float mappedPixel = Mathf.Clamp((pixel - lowerBound) / (upperBound - lowerBound), 0f, 1f);
byte grayValue = (byte)(mappedPixel * 255f);
Color32 _col = new Color32(grayValue, grayValue, grayValue, 255);

完整修改后的代码示例

把上述逻辑整合到你的原有代码中,最终版本如下:

List<Texture2D> _imageListTexture = new List<Texture2D>();

// 提前设置归一化或窗宽窗位参数(二选一即可)
float minPixel = liverVoxels.Min();
float maxPixel = liverVoxels.Max();
// 或者启用窗宽窗位:
// float WL = 50f;
// float WW = 150f;
// float lowerBound = WL - WW / 2f;
// float upperBound = WL + WW / 2f;

for (int k = 0; k < depth; k++) {
    Texture2D _myTex = new Texture2D(width, height, TextureFormat.ARGB32, true);
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            int idx = i + width * (j + height * k);
            float pixel = liverVoxels[idx];
            
            // 选择一种映射方式
            // 方式1:全局最值归一化
            float normalizedPixel = (pixel - minPixel) / (maxPixel - minPixel);
            normalizedPixel = Mathf.Clamp01(normalizedPixel);
            
            // 方式2:窗宽窗位映射
            // float normalizedPixel = Mathf.Clamp((pixel - lowerBound) / (upperBound - lowerBound), 0f, 1f);
            
            byte gray = (byte)(normalizedPixel * 255f);
            Color32 _col = new Color32(gray, gray, gray, 255);
            
            _myTex.SetPixel(i, j, _col);
        }
    }
    _myTex.Apply();
    _imageListTexture.Add(_myTex);
}

额外优化提示

  • 把最值计算或窗宽窗位参数设置放在循环外,避免重复计算,提升处理大尺寸图像的性能。
  • 如果DICOM图像有方向信息,可能需要调整纹理的Y轴方向,避免切片显示颠倒。
  • 对于超大尺寸图像,SetPixel逐点设置效率较低,可以改用SetPixels32一次性设置整行或整纹理的像素数组,大幅提升速度。

内容的提问来源于stack exchange,提问作者vuthea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 08:37:33