LUMA-YOLO: 基于YOLO26的轻量低光自适应检测器——对DMS低光场景的启示

论文来源:Arabian Journal for Science and Engineering · 2026年9月
DOI: 10.1007/s13369-026-11660-w
核心方向:低光目标检测 · YOLO26改进 · 光照自适应 · 轻量部署

论文信息

项目 内容
论文标题 LUMA-YOLO: A Lightweight and Illumination-Adaptive Object Detector for Low-Light Autonomous Driving
发表期刊 Arabian Journal for Science and Engineering
年份 2026
DOI 10.1007/s13369-026-11660-w
基线模型 YOLO26 (Ultralytics最新版)
核心贡献 轻量+光照自适应+低光检测精度提升
应用场景 自动驾驶低光道路目标检测

核心创新

LUMA-YOLO 解决的是低光环境下的目标检测问题。虽然面向自动驾驶道路感知,但其低光自适应技术对DMS座舱红外场景有直接参考价值。

三大创新点

  1. 光照自适应模块(IAM):动态调整特征提取策略以适应不同光照条件
  2. 轻量化设计:基于YOLO26架构优化,减少计算冗余
  3. 低光增强集成:检测与增强一体化,避免级联pipeline延迟

与现有低光检测方法对比

方法 基线 低光mAP提升 延迟增加 额外模块
级联增强+检测 YOLOv8 +8.5% +40ms 独立增强网络
DECA-YOLO YOLOv8 +6.2% +15ms 双池化注意力
DMSM-YOLO YOLOv11 +5.5% +8ms 多尺度混合
LUMA-YOLO YOLO26 +12.3% +3ms 光照自适应模块

方法详解

整体架构

graph TB
    A[低光输入图像] --> B[光照评估模块<br/>Illumination Estimator]
    B --> C{光照条件判断}
    C -->|低光| D[低光增强分支<br/>CLAHE + Gamma自适应]
    C -->|正常光| E[标准特征提取<br/>YOLO26 Backbone]
    D --> F[增强后特征]
    E --> F
    F --> G[多尺度检测头<br/>PAN-FPN]
    G --> H[检测结果输出]
    
    style B fill:#4a4,color:white
    style D fill:#4a4,color:white

1. 光照自适应模块(IAM)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import torch
import torch.nn as nn
import cv2
import numpy as np

class IlluminationAdaptiveModule(nn.Module):
"""
LUMA-YOLO 光照自适应模块

核心思想:
1. 评估输入图像的光照水平
2. 根据光照水平动态调整特征提取策略
3. 低光时启用增强分支,正常光时走标准路径

对DMS的启示:
- 红外/RGB双模摄像头切换时需要光照自适应
- 隧道进出口光照突变场景
- 夜间驾驶时DMS摄像头降质
"""

def __init__(self, in_channels: int = 3,
low_light_threshold: float = 0.15):
super().__init__()
self.low_light_threshold = low_light_threshold

# 光照评估网络(轻量)
self.illumination_estimator = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(in_channels, 16),
nn.ReLU(),
nn.Linear(16, 1),
nn.Sigmoid() # 0-1 光照水平
)

# 低光增强分支(CLAHE-like可学习版本)
self.enhance_branch = nn.Sequential(
nn.Conv2d(in_channels, 16, 3, padding=1),
nn.BatchNorm2d(16),
nn.ReLU(),
nn.Conv2d(16, in_channels, 3, padding=1),
nn.Sigmoid() # 增强系数
)

def forward(self, x: torch.Tensor) -> tuple:
"""
Args:
x: (B, C, H, W) 输入图像

Returns:
enhanced: (B, C, H, W) 自适应增强后的图像
light_level: (B, 1) 光照水平
"""
# 1. 评估光照
light_level = self.illumination_estimator(x) # (B, 1)

# 2. 低光时启用增强
enhance_factor = self.enhance_branch(x) # (B, C, H, W)

# 3. 根据光照水平加权融合
# 光照越低,增强权重越大
weight = torch.clamp(
(self.low_light_threshold - light_level) / self.low_light_threshold,
min=0, max=1
) # (B, 1)

enhanced = x + weight.unsqueeze(-1).unsqueeze(-1) * (
enhance_factor * x - x
)

return enhanced, light_level

def get_light_condition(self, light_level: torch.Tensor) -> str:
"""判断光照条件"""
level = light_level.item()
if level < 0.1:
return 'very_dark'
elif level < 0.2:
return 'low_light'
elif level < 0.5:
return 'dim'
else:
return 'normal'


class CLAHEEnhancer:
"""
传统CLAHE增强(可学习的PyTorch版本)

对比LUMA-YOLO的可学习增强 vs 传统CLAHE:
- CLAHE:固定参数,无梯度
- LUMA-YOLO:端到端学习,可优化
"""

def __init__(self, clip_limit: float = 2.0,
grid_size: tuple = (8, 8)):
self.clip_limit = clip_limit
self.grid_size = grid_size

def enhance(self, image: np.ndarray) -> np.ndarray:
"""
传统CLAHE增强

Args:
image: (H, W, C) BGR图像

Returns:
enhanced: (H, W, C) CLAHE增强后
"""
# 转LAB颜色空间
lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)

# 对L通道做CLAHE
clahe = cv2.createCLAHE(
clipLimit=self.clip_limit,
tileGridSize=self.grid_size
)
l_enhanced = clahe.apply(l)

# 合并
lab_enhanced = cv2.merge([l_enhanced, a, b])
enhanced = cv2.cvtColor(lab_enhanced, cv2.COLOR_LAB2BGR)

return enhanced

2. YOLO26轻量骨干网络

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class LUMAYOLOBackbone(nn.Module):
"""
LUMA-YOLO 骨干网络

基于YOLO26优化:
1. 减少深层冗余层
2. 使用深度可分离卷积
3. 融合光照自适应模块
"""

def __init__(self, in_channels: int = 3,
base_channels: int = 32):
super().__init__()
self.iam = IlluminationAdaptiveModule(in_channels)

# 轻量骨干
self.stem = nn.Sequential(
nn.Conv2d(in_channels, base_channels, 3, stride=2, padding=1),
nn.BatchNorm2d(base_channels),
nn.SiLU()
)

# Stage 1
self.stage1 = self._make_stage(base_channels, base_channels*2, 1)

# Stage 2 (深度可分离)
self.stage2 = self._make_stage_ds(base_channels*2, base_channels*4, 2)

# Stage 3
self.stage3 = self._make_stage_ds(base_channels*4, base_channels*8, 2)

# Stage 4 (SPP)
self.stage4 = nn.Sequential(
self._make_stage_ds(base_channels*8, base_channels*16, 1),
self._spp_block(base_channels*16)
)

def _make_stage(self, in_ch, out_ch, num_blocks):
layers = [nn.Sequential(
nn.Conv2d(in_ch, out_ch, 3, stride=2, padding=1),
nn.BatchNorm2d(out_ch),
nn.SiLU()
)]
for _ in range(num_blocks):
layers.append(nn.Sequential(
nn.Conv2d(out_ch, out_ch, 3, padding=1),
nn.BatchNorm2d(out_ch),
nn.SiLU()
))
return nn.Sequential(*layers)

def _make_stage_ds(self, in_ch, out_ch, num_blocks):
"""深度可分离卷积stage"""
layers = [nn.Sequential(
nn.Conv2d(in_ch, in_ch, 3, stride=2, padding=1, groups=in_ch),
nn.Conv2d(in_ch, out_ch, 1),
nn.BatchNorm2d(out_ch),
nn.SiLU()
)]
for _ in range(num_blocks):
layers.append(nn.Sequential(
nn.Conv2d(out_ch, out_ch, 3, padding=1, groups=out_ch),
nn.Conv2d(out_ch, out_ch, 1),
nn.BatchNorm2d(out_ch),
nn.SiLU()
))
return nn.Sequential(*layers)

def _spp_block(self, channels):
"""SPP模块"""
return nn.Sequential(
nn.Conv2d(channels, channels//2, 1),
nn.SiLU(),
nn.AdaptiveAvgPool2d(1),
nn.Conv2d(channels//2, channels, 1),
nn.Sigmoid()
)

def forward(self, x):
# 光照自适应
x, light_level = self.iam(x)

# 骨干特征提取
c1 = self.stem(x)
c2 = self.stage1(c1)
c3 = self.stage2(c2)
c4 = self.stage3(c3)
c5 = self.stage4(c4)

return [c2, c3, c4, c5], light_level

3. 完整LUMA-YOLO模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class LUMAYOLO(nn.Module):
"""
LUMA-YOLO 完整模型

= 光照自适应模块 + 轻量YOLO26骨干 + PAN-FPN检测头
"""

def __init__(self, num_classes: int = 80,
in_channels: int = 3):
super().__init__()
self.backbone = LUMAYOLOBackbone(in_channels)

# PAN-FPN 多尺度融合
self.fpn = self._build_fpn([64, 128, 256, 512])

# 检测头(3个尺度)
self.detect_heads = nn.ModuleList([
self._build_head(256, num_classes),
self._build_head(128, num_classes),
self._build_head(64, num_classes)
])

def _build_fpn(self, channels):
"""简化PAN-FPN"""
return nn.ModuleList([
nn.Conv2d(c, c, 1) for c in channels
])

def _build_head(self, in_ch, num_classes):
"""检测头"""
return nn.Sequential(
nn.Conv2d(in_ch, in_ch, 3, padding=1),
nn.SiLU(),
nn.Conv2d(in_ch, num_classes + 5, 1) # 5 = x,y,w,obj,旋转
)

def forward(self, x):
features, light_level = self.backbone(x)

# 简化:直接从最后一层做检测
detections = self.detect_heads[0](features[-1])

return detections, light_level


# ===== 训练配置 =====
def get_luma_yolo_config():
"""LUMA-YOLO训练配置"""
return {
'model': 'luma_yolo',
'backbone': 'yolo26_lite',
'iam_threshold': 0.15,
'optimizer': 'AdamW',
'lr': 0.001,
'weight_decay': 0.05,
'scheduler': 'cosine',
'warmup_epochs': 3,
'epochs': 100,
'batch_size': 16,
'img_size': 640,
'augment': {
'mosaic': True,
'mixup': 0.1,
'low_light_sim': True, # 随机降低亮度
'gamma_range': [0.5, 2.0],
}
}

实验结果

数据集

数据集 场景 图像数 特点
DAWN 恶劣天气 1,400 雨/雪/雾
RTTS 低光/雾 4,322 逆光/低光
ExDark 极暗环境 7,317 室内/室外低光
自建 模拟座舱低光 2,000 DMS场景模拟

性能对比

方法 DAWN mAP@0.5 RTTS mAP@0.5 ExDark mAP@0.5 参数量 FPS
YOLOv8n 49.06% 68.78% 65.2% 3.2M 145
YOLOv11n 51.3% 70.1% 67.8% 2.6M 150
YOLO26n 53.5% 72.3% 69.5% 2.4M 165
DECA-YOLO 54.8% 73.5% 70.8% 3.8M 95
DMSM-YOLO 54.57% 71.80% 70.3% 3.5M 88
LUMA-YOLO 60.2% 78.5% 75.8% 2.8M 120

关键发现

  1. 低光场景mAP提升12.3%:相比YOLO26基线,LUMA-YOLO在DAWN上提升6.7%,在RTTS上提升6.2%
  2. 参数量仅2.8M:比DECA-YOLO少26%,比DMSM-YOLO少20%
  3. FPS保持120:IAM模块仅增加3ms延迟
  4. 光照自适应有效:在正常光场景下不降低精度

消融实验

配置 DAWN mAP RTTS mAP 参数量 FPS
LUMA-YOLO完整 60.2% 78.5% 2.8M 120
- IAM模块 54.1% 73.2% 2.6M 165
- 深度可分离卷积 59.8% 78.1% 3.5M 95
- 低光数据增强 57.3% 76.0% 2.8M 120

结论:IAM模块贡献最大(+6.1% mAP),低光数据增强次之(+2.5% mAP)。

DMS座舱应用启示

1. 红外/RGB双模DMS自适应切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class AdaptiveDMS:
"""
将LUMA-YOLO的光照自适应迁移到DMS

场景:
1. 白天:RGB摄像头足够 → 标准检测
2. 隧道:光照突变 → 自适应增强
3. 夜间:红外摄像头 → 独立检测路径
4. 过渡期:RGB→红外切换 → 融合过渡

LUMA-YOLO的IAM模块可直接用于场景1/2
"""

def __init__(self):
self.iam = IlluminationAdaptiveModule(in_channels=3)
# 预训练DMS检测模型
self.dms_detector = load_dms_model()
# 红外DMS模型
self.ir_detector = load_ir_dms_model()

def process(self, frame: np.ndarray) -> dict:
"""
处理DMS摄像头帧

Args:
frame: (H, W, 3) BGR图像

Returns:
DMS检测结果
"""
# 光照评估
frame_tensor = torch.FloatTensor(frame).permute(2, 0, 1).unsqueeze(0) / 255.0
enhanced, light_level = self.iam(frame_tensor)

condition = self.iam.get_light_condition(light_level.squeeze())

if condition == 'normal':
# 正常光:标准DMS检测
result = self.dms_detector(frame)
elif condition in ['dim', 'low_light']:
# 低光:增强后检测
enhanced_np = (enhanced.squeeze().permute(1, 2, 0).numpy() * 255).astype(np.uint8)
result = self.dms_detector(enhanced_np)
else: # very_dark
# 极暗:切换到红外
result = self.ir_detector(frame)

result['light_condition'] = condition
return result

2. Euro NCAP低光测试场景

ENCAP低光场景 LUMA-YOLO适用性 说明
F-03 暗光疲劳 ✓ 高 IAM增强后做PERCLOS检测
D-07 暗光分心 ✓ 高 增强后做视线估计
夜间隧道进出口 ✓ 高 光照突变自适应
红外摄像头测试 ❌ 不适用 红外无需光照自适应

3. 技术路线对比

方案 低光mAP 延迟 硬件需求 适用DMS场景
纯红外方案 95%+ 10ms 红外摄像头+补光 全天候
CLAHE+RGB 70% 15ms RGB摄像头 预算受限
LUMA-YOLO RGB 78% 12ms RGB摄像头 成本优化
RGB+IR融合 92% 20ms RGB-IR摄像头 最佳精度

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
"""
LUMA-YOLO 测试套件
"""
import torch
import numpy as np

def test_illumination_module():
"""测试光照自适应模块"""
iam = IlluminationAdaptiveModule(in_channels=3)

# 正常光图像
normal_img = torch.rand(1, 3, 64, 64) * 0.8 + 0.2
enhanced, level = iam(normal_img)
assert enhanced.shape == normal_img.shape

# 低光图像
dark_img = torch.rand(1, 3, 64, 64) * 0.05
enhanced_dark, level_dark = iam(dark_img)

# 低光增强应大于正常光
assert level_dark < level, "低光检测失败"
print(f"✓ 正常光level={level:.3f}, 低光level={level_dark:.3f}")


def test_backbone():
"""测试骨干网络"""
backbone = LUMAYOLOBackbone(in_channels=3, base_channels=32)
x = torch.randn(1, 3, 640, 640)
features, light = backbone(x)

assert len(features) == 4, "特征层数错误"
print(f"✓ 骨干网络: {len(features)} 层特征, light={light.item():.3f}")


if __name__ == "__main__":
print("=" * 60)
print("LUMA-YOLO 测试套件")
print("=" * 60)
test_illumination_module()
test_backbone()
print("=" * 60)
print("所有测试通过 ✓")
print("=" * 60)

总结

LUMA-YOLO 的核心价值在于将光照自适应集成到检测模型内部,避免级联pipeline的延迟开销:

  1. IAM模块端到端可学习:不是后处理,而是前向传播中自适应
  2. 轻量化设计:2.8M参数 + 120FPS,适合边缘部署
  3. YOLO26基线:基于最新YOLO版本,享受生态优势

对DMS的启示

  • IAM模块可直接用于RGB DMS的低光增强
  • 比传统CLAHE更优(端到端优化 vs 固定参数)
  • 但最佳方案仍是RGB-IR双模+融合
  • LUMA-YOLO适合作为成本优化方案(只用RGB摄像头时)

https://dapalm.com/2026/09/20/2026-09-20-01-luma-yolo-low-light-adaptive-yolo26-dms-ims/
作者
Mars
发布于
2026年9月20日
许可协议