点云强度如何增强显示

4 阅读4分钟

点云强度如何增强显示

核心思想:把强度值(0-255)映射成不同颜色,让斑马线和道路在视觉上区分开。

算法原理(3 步)

第 1 步:归一化

强度值 80-180 → 变成 0-1 之间的 t 值

    t = (当前强度 - 最小值) / (最大值 - 最小值)
    
    举例:范围 [80, 180]
    - 强度 80  → t = 0.0
    - 强度 130 → t = 0.5
    - 强度 180 → t = 1.0

第 2 步:根据 t 值分配颜色

    t = 0.0        → 蓝色   (0, 0, 1)
    t = 0.33       → 青色   (0, 1, 1)
    t = 0.66       → 黄色   (1, 1, 0)
    t = 1.0        → 红色   (1, 0, 0)

第 3 步:中间值线性过渡

    t 在 0 到 0.33 之间:R 从 0→0, G 从 0→1, B=1
    t 在 0.33 到 0.66 之间:R 从 0→1, G=1, B 从 10
    t 在 0.66 到 1 之间:R=1, G 从 10, B=0

可视化

强度值:  0 ────── 85 ────── 170 ────── 255
t 值:    0 ────── 0.33 ──── 0.66 ────── 1
颜色:    蓝 ────→ 青 ────→ 黄 ────→ 红
         ████    ████    ████    ████
为什么能区分斑马线和道路?
斑马线和道路的反射强度不同:

道路(沥青):强度低 → 显示蓝色/青色 斑马线(白色涂料):强度高 → 显示黄色/红色 滑块的作用:调整minI和maxI,让斑马线的强度刚好落在黄色/红色区域,道路落在蓝色区域,这样颜色对比就出来了!

代码对应

// 第 1 步:归一化
const clipped = Math.max(minI, Math.min(maxI, intensity))
let t = (clipped - minI) / (maxI - minI)

// 第 2-3 步:分段赋值 RGB
if (t < 0.33) {      // 蓝→青段
    r = 0; g = t*3; b = 1
} else if (t < 0.66) { // 青→黄段
    r = (t-0.33)*3; g = 1; b = 1-(t-0.33)*3
} else {             // 黄→红段
    r = 1; g = 1-(t-0.66)*3; b = 0
}

拖动 GUI 中的两个滑块来区分不同物体:

  • 强度中心:决定哪个强度值显示为黄色(中间色)
  • 强度范围:控制对比度,范围越小颜色分界越明显

滑块实现原理

强度中心

GUI 控制(第 193-195 行):

this.gui.add(params, 'intensityCenter', 0, 255, 1)
  .name('强度中心')
  .onChange((value) => {
    this.updateColorRange(value, params.intensityRange)
  })

更新逻辑(第 222-227 行):

updateColorRange(center, range) {
  const min = Math.max(0, center - range / 2)   // 最小值 = 中心 - 范围/2
  const max = Math.min(255, center + range / 2) // 最大值 = 中心 + 范围/2
  this.colorRange = [min, max]
  this.applyIntensityColorMap()
}

为什么 center 决定黄色对应的强度值?

归一化公式:t = (intensity - min) / (max - min)

intensity = center 时:

t = (center - (center - range/2)) / ((center + range/2) - (center - range/2))
  = (range/2) / range
  = 0.5

结论:无论 range 是多少,只要 intensity == center,结果永远是 t = 0.5,对应黄色区域(青→黄段)。

举例

  • center = 128, range = 100min=78, max=178 → 强度 128 的点 t = 50/100 = 0.5 → 黄色
  • center = 150, range = 60min=120, max=180 → 强度 150 的点 t = 30/60 = 0.5 → 黄色

强度范围

GUI 控制(第 198-200 行):

this.gui.add(params, 'intensityRange', 10, 255, 5)
  .name('强度范围')
  .onChange((value) => {
    this.updateColorRange(params.intensityCenter, value)
  })

原理:范围决定归一化公式的分母

t = (intensity - minI) / (maxI - minI)
                   ↑
                 范围 = range
范围大小效果
范围大(如 200)分母大,同样的强度差ΔI 产生的Δt 更小 → 颜色过渡平缓
范围小(如 30)分母小,同样的强度差ΔI 产生的Δt 更大 → 颜色对比强烈

建议操作

  • 先点"自动调整范围"获取基准
  • 调小"强度范围"(如 30-80)增强对比
  • 移动"强度中心"直到斑马线和道路颜色差异最大

伽马值(Gamma)

作用

调整中间调亮度,让斑马线和道路的顏色对比更明显,而不影响最暗和最亮部分。

原理

在归一化得到 t 值后,应用伽马校正:

// gamma > 1:提亮中间调
// gamma < 1:压暗中间调
if (enableGamma.value) {
  t = Math.pow(t, 1 / gammaValue.value)
}

伽马变换公式t_out = t_in ^ (1/γ)

伽马值效果适用场景
γ = 1.0无变化,线性映射原始对比
γ > 1.0(如 1.5-2.5)提亮中间调,低强度值变化小,高强度值变化大道路和斑马线强度差异小,需要拉开中间色调
γ < 1.0(如 0.5-0.9)压暗中间调,高强度值变化小,低强度值变化大高光区域过曝,需要压缩

为什么有效?

伽马校正改变的是 t 值的分布密度:

  • γ > 1:更多 t 值被推向 1,中间调和高光区域的颜色变化更细腻
  • γ < 1:更多 t 值被推向 0,暗部区域的颜色变化更细腻

举例(γ = 1.5):

原 t 值 → 伽马校正后
t = 0.10.1^(1/1.5) = 0.21  (轻微提升)
t = 0.50.5^(1/1.5) = 0.63  (明显提升)
t = 0.90.9^(1/1.5) = 0.93  (变化很小)

使用顺序

完整的颜色映射流程:

1. 强度值 → 裁剪到 [minI, maxI]
2. 归一化 → t = (clipped - minI) / (maxI - minI)
3. 伽马校正 → t = t ^ (1/γ)  ← 这一步调整中间调
4. 分段配色 → 根据校正后的 t 分配 RGB

GUI 控制

// 伽马值滑块 (0.5-2.5)
gui.add(params, 'gammaValue', 0.5, 2.5, 0.1)
  .name('亮度值')

// 开关
gui.add(params, 'enableGamma')
  .name('亮度调节')

操作建议

  1. 先用"强度中心"和"强度范围"确定基本的颜色分界
  2. 调节"亮度值"滑块(推荐从 1.0 开始,逐渐增大到 1.5-2.0)
  3. 观察斑马线和道路的对比度,找到最清晰的平衡点