彩虹编码的核心是将灰度值(0-255)映射到彩虹色谱(红→橙→黄→绿→蓝→靛→紫)的RGB值。下面提供两种语言的完整实现代码,并附上详细说明。
🌈 彩虹编码原理
- 彩虹色谱:将7种颜色(红、橙、黄、绿、蓝、靛、紫)作为关键点
- 映射方式:将灰度值0-255线性映射到彩虹的6个区间
- 插值:在相邻颜色点之间进行线性插值
C# 实现代码(WPF/WinForms可用)
cs
using System;
using System.Windows.Media;
public static class RainbowColorMapper
{
// 彩虹色谱的关键颜色点(归一化RGB值,0-1范围)
private static readonly (float R, float G, float B)[] RainbowColors = new[]
{
(1.0f, 0.0f, 0.0f), // 红
(1.0f, 0.5f, 0.0f), // 橙
(1.0f, 1.0f, 0.0f), // 黄
(0.0f, 1.0f, 0.0f), // 绿
(0.0f, 0.0f, 1.0f), // 蓝
(0.3f, 0.0f, 0.5f), // 靛
(0.6f, 0.0f, 0.8f) // 紫
};
/// <summary>
/// 将灰度值(0-255)转换为彩虹色
/// </summary>
public static Color GetRainbowColor(int grayValue)
{
// 确保灰度值在0-255范围内
grayValue = Math.Max(0, Math.Min(255, grayValue));
// 归一化到0-1范围
float normalized = grayValue / 255.0f;
// 映射到彩虹的6个区间 (0-6)
float position = normalized * 6.0f;
// 找到两个相邻的颜色点
int index = (int)Math.Floor(position);
float fraction = position - index;
// 确保索引在有效范围内
index = Math.Max(0, Math.Min(5, index));
// 获取两个颜色点
var color1 = RainbowColors[index];
var color2 = RainbowColors[index + 1];
// 线性插值
float r = color1.R + fraction * (color2.R - color1.R);
float g = color1.G + fraction * (color2.G - color1.G);
float b = color1.B + fraction * (color2.B - color1.B);
// 转换为0-255的整数值
return Color.FromRgb(
(byte)Math.Round(r * 255),
(byte)Math.Round(g * 255),
(byte)Math.Round(b * 255)
);
}
// 用法示例
public static void ExampleUsage()
{
// 将灰度值128转换为彩虹色
Color color = GetRainbowColor(128);
// 在WPF中使用
// var brush = new SolidColorBrush(color);
}
}
C++ 实现代码(使用SDL2或类似库)
cpp
#include <vector>
#include <cstdint>
#include <algorithm>
// 预计算彩虹颜色表(256个值)
std::vector<std::vector<uint8_t>> PrecomputeRainbowTable() {
// 彩虹色谱的关键颜色点(归一化RGB值,0-1范围)
const float rainbowColors[7][3] = {
{1.0f, 0.0f, 0.0f}, // 红
{1.0f, 0.5f, 0.0f}, // 橙
{1.0f, 1.0f, 0.0f}, // 黄
{0.0f, 1.0f, 0.0f}, // 绿
{0.0f, 0.0f, 1.0f}, // 蓝
{0.3f, 0.0f, 0.5f}, // 靛
{0.6f, 0.0f, 0.8f} // 紫
};
std::vector<std::vector<uint8_t>> table(256, std::vector<uint8_t>(3));
for (int i = 0; i < 256; ++i) {
float normalized = i / 255.0f;
float position = normalized * 6.0f;
int index = static_cast<int>(std::floor(position));
float fraction = position - index;
index = std::max(0, std::min(5, index));
float r1 = rainbowColors[index][0];
float g1 = rainbowColors[index][1];
float b1 = rainbowColors[index][2];
float r2 = rainbowColors[index + 1][0];
float g2 = rainbowColors[index + 1][1];
float b2 = rainbowColors[index + 1][2];
float r = r1 + fraction * (r2 - r1);
float g = g1 + fraction * (g2 - g1);
float b = b1 + fraction * (b2 - b1);
table[i][0] = static_cast<uint8_t>(std::round(r * 255));
table[i][1] = static_cast<uint8_t>(std::round(g * 255));
table[i][2] = static_cast<uint8_t>(std::round(b * 255));
}
return table;
}
// 使用预计算表进行快速转换
void ConvertToRainbow(const uint8_t* grayData, uint8_t* rainbowData,
int width, int height,
const std::vector<std::vector<uint8_t>>& rainbowTable) {
int totalPixels = width * height;
for (int i = 0; i < totalPixels; ++i) {
uint8_t grayValue = grayData[i];
rainbowData[i * 3 + 0] = rainbowTable[grayValue][0];
rainbowData[i * 3 + 1] = rainbowTable[grayValue][1];
rainbowData[i * 3 + 2] = rainbowTable[grayValue][2];
}
}
代码工作原理详解
-
彩虹色谱定义:
- 7种颜色作为关键点(红→紫)
- 每种颜色用归一化RGB值表示(0.0-1.0)
-
映射过程:
- 将灰度值(0-255)归一化为0.0-1.0
- 乘以6.0,得到0-6的区间值
- 例如:128 → 0.5 → 0.5*6=3.0
-
区间划分:
区间 颜色 说明 0.0-1.0 红→橙 0.0=红, 1.0=橙 1.0-2.0 橙→黄 1.0=橙, 2.0=黄 2.0-3.0 黄→绿 2.0=黄, 3.0=绿 3.0-4.0 绿→蓝 3.0=绿, 4.0=蓝 4.0-5.0 蓝→靛 4.0=蓝, 5.0=靛 5.0-6.0 靛→紫 5.0=靛, 6.0=紫 -
插值计算:
- 例如:灰度值128 → 0.5 → 3.0 → 区间3.0(绿→蓝的边界)
- 但实际计算:0.5*6=3.0 → index=3, fraction=0.0
- 所以是绿色(0.0, 1.0, 0.0)
📊 彩虹编码测试示例
| 灰度值 | 位置 | 区间 | 颜色 | 实际RGB |
|---|---|---|---|---|
| 0 | 0.0 | 0.0 | 红 | (255, 0, 0) |
| 64 | 0.25 | 1.5 | 橙→黄 | (255, 128, 0) |
| 128 | 0.5 | 3.0 | 绿 | (0, 255, 0) |
| 192 | 0.75 | 4.5 | 蓝→靛 | (38, 0, 130) |
| 255 | 1.0 | 6.0 | 紫 | (153, 0, 204) |
💡 实际应用建议
- 医学影像中:通常使用从蓝到红的彩虹编码(冷色→暖色),可以调整颜色点顺序
- 性能优化:在实时系统中,可以预先计算好256个颜色值,存储在数组中
- 自定义 :根据需要修改
rainbowColors数组,实现不同风格的彩虹编码
重要提示 :在医学影像中,彩虹编码的目的是增强人眼辨识度,而不是"覆盖"图像。选择哪种编码方式应基于临床需求,如知识库[5]所述:"在实际应用中,主要根据人眼辨色能力和能否突出显示研究目标来选择合适的3原色组合。"