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
相关产品推荐
相关产品推荐

