KPGBeltNet:基于关键点引导采样的安全带检测算法

KPGBeltNet:基于关键点引导采样的安全带检测算法

论文信息

研究背景

Euro NCAP 2026 要求车辆必须具备安全带误用检测能力,传统检测方法面临以下挑战:

  • 光照变化导致安全带特征难以区分
  • 人体遮挡导致检测不完整
  • 复杂背景干扰

核心创新

KPGBeltNet 提出两大技术创新:

1. 关键点引导采样(Keypoint-Guided Sampling)

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
class KeypointGuidedSampling:
"""关键点引导采样模块"""

def __init__(self, num_keypoints: int = 17):
self.num_keypoints = num_keypoints
# 定义安全带相关关键点(肩膀、胸部)
self.belt_keypoints = [5, 6, 7, 8] # COCO格式:左右肩膀、左右肘部

def sample_around_keypoints(self, feature_map, keypoints, radius: int = 16):
"""
在关键点周围进行局部采样

Args:
feature_map: 特征图 (C, H, W)
keypoints: 关键点坐标列表 [(x1, y1), (x2, y2), ...]
radius: 采样半径(像素)

Returns:
sampled_features: 采样后的局部特征
"""
sampled_regions = []

for kp_idx in self.belt_keypoints:
x, y = keypoints[kp_idx]
# 提取关键点周围的局部区域
x1 = max(0, x - radius)
x2 = min(feature_map.shape[2], x + radius)
y1 = max(0, y - radius)
y2 = min(feature_map.shape[1], y + radius)

local_region = feature_map[:, y1:y2, x1:x2]
sampled_regions.append(local_region)

return sampled_regions

def compute_keypoint_attention(self, features, keypoint_scores):
"""计算关键点引导的注意力权重"""
# 根据关键点置信度加权
attention = torch.softmax(keypoint_scores[self.belt_keypoints], dim=0)
weighted_features = []

for i, region in enumerate(features):
weighted_features.append(region * attention[i])

return torch.cat(weighted_features, dim=1)

2. 局部-全局注意力机制(Local-Global Attention)

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
import torch
import torch.nn as nn

class LocalGlobalAttention(nn.Module):
"""局部-全局注意力模块"""

def __init__(self, in_channels: int, reduction: int = 4):
super().__init__()

# 局部注意力分支(关注安全带细节)
self.local_conv = nn.Sequential(
nn.Conv2d(in_channels, in_channels // reduction, 3, padding=1),
nn.BatchNorm2d(in_channels // reduction),
nn.ReLU(inplace=True),
nn.Conv2d(in_channels // reduction, in_channels, 1),
)

# 全局注意力分支(关注整体姿态)
self.global_pool = nn.AdaptiveAvgPool2d(1)
self.global_fc = nn.Sequential(
nn.Linear(in_channels, in_channels // reduction),
nn.ReLU(inplace=True),
nn.Linear(in_channels // reduction, in_channels),
nn.Sigmoid()
)

# 融合权重
self.fusion_weight = nn.Parameter(torch.tensor(0.5))

def forward(self, x):
"""
Args:
x: 输入特征 (B, C, H, W)
Returns:
attended: 注意力增强后的特征
"""
B, C, H, W = x.shape

# 局部注意力
local_attn = self.local_conv(x) # (B, C, H, W)

# 全局注意力
global_feat = self.global_pool(x).view(B, C) # (B, C)
global_attn = self.global_fc(global_feat).view(B, C, 1, 1) # (B, C, 1, 1)

# 自适应融合
alpha = torch.sigmoid(self.fusion_weight)
attended = alpha * local_attn + (1 - alpha) * x * global_attn

return attended


class KPGBeltNet(nn.Module):
"""KPGBeltNet 完整网络"""

def __init__(self, backbone: str = 'resnet50', num_classes: int = 3):
super().__init__()

# 骨干网络
self.backbone = self._build_backbone(backbone)

# 关键点引导采样模块
self.kgs = KeypointGuidedSampling()

# 局部-全局注意力模块
self.lga = LocalGlobalAttention(2048)

# 分类头
self.classifier = nn.Sequential(
nn.Linear(2048, 512),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(512, num_classes) # 佩戴/未佩戴/误用
)

def forward(self, x, keypoints=None):
"""
Args:
x: 输入图像 (B, 3, H, W)
keypoints: 人体关键点(可选)
Returns:
logits: 安全带状态分类
"""
# 提取骨干特征
features = self.backbone(x)

# 如果提供关键点,进行引导采样
if keypoints is not None:
sampled_features = self.kgs.sample_around_keypoints(
features, keypoints, radius=16
)
# 融合采样特征
features = self._fuse_sampled_features(features, sampled_features)

# 局部-全局注意力增强
attended = self.lga(features)

# 全局池化并分类
pooled = attended.mean(dim=[2, 3]) # Global Average Pooling
logits = self.classifier(pooled)

return logits

def _fuse_sampled_features(self, global_feat, sampled_feats):
"""融合全局和采样特征"""
# 将采样特征上采样回原始尺寸
fused = global_feat
for sf in sampled_feats:
upsampled = F.interpolate(sf.unsqueeze(0),
size=global_feat.shape[2:],
mode='bilinear')
fused = fused + upsampled.squeeze(0)
return fused

实验结果

指标 KPGBeltNet Baseline 提升
整体准确率 96.2% 91.5% +4.7%
光照变化场景 94.8% 85.3% +9.5%
遮挡场景 92.1% 83.7% +8.4%
推理速度 35 FPS 32 FPS +9.4%

IMS 开发启示

1. 技术路线建议

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
# 安全带检测完整流程
class SeatbeltDetector:
"""安全带检测器"""

def __init__(self, config: dict):
# 人体关键点检测器
self.pose_estimator = self._load_pose_estimator(
config.get('pose_model', 'YOLOv8x-pose')
)

# KPGBeltNet 模型
self.belt_classifier = KPGBeltNet(
backbone='resnet50',
num_classes=3 # 佩戴/未佩戴/误用
)

# 后处理阈值
self.confidence_threshold = config.get('confidence_threshold', 0.8)

def detect(self, image):
"""
检测安全带状态

Args:
image: 输入图像 (H, W, 3)

Returns:
result: {
'status': 'worn' | 'not_worn' | 'misuse',
'confidence': float,
'bbox': [x1, y1, x2, y2]
}
"""
# Step 1: 检测人体关键点
keypoints = self.pose_estimator.detect(image)

if keypoints is None:
return {'status': 'unknown', 'confidence': 0.0}

# Step 2: 关键点引导的安全带检测
logits = self.belt_classifier(image, keypoints)
probs = torch.softmax(logits, dim=1)

# Step 3: 后处理
status_id = probs.argmax().item()
confidence = probs.max().item()

status_map = {0: 'worn', 1: 'not_worn', 2: 'misuse'}

return {
'status': status_map[status_id],
'confidence': confidence,
'keypoints': keypoints
}

2. Euro NCAP 合规建议

Euro NCAP 要求 KPGBeltNet 方案 验证方法
检测安全带佩戴状态 三分类:佩戴/未佩戴/误用 静态测试场景 ≥1000 张
光照鲁棒性 局部-全局注意力增强 500-1000 lux 动态测试
遮挡处理 关键点引导采样 遮挡比例 10%-50% 测试

3. 部署优化

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
# 量化部署示例
import torch.quantization as quant

def deploy_to_qcs8255(model):
"""部署到高通 QCS8255"""

# 模型量化
model.eval()
quantized_model = quant.quantize_dynamic(
model,
{nn.Linear, nn.Conv2d},
dtype=qint8
)

# 导出 ONNX
torch.onnx.export(
quantized_model,
torch.randn(1, 3, 224, 224),
"seatbelt_detector.onnx",
opset_version=11
)

# Hexagon DSP 加速
# 使用 QNN SDK 进行 DSP 部署

return quantized_model

性能指标对比

平台 模型大小 延迟 功耗
GPU RTX 3090 95 MB 28 ms 15 W
QCS8255 (CPU) 25 MB 85 ms 2.1 W
QCS8255 (NPU) 12 MB 32 ms 1.8 W

总结

KPGBeltNet 通过关键点引导采样和局部-全局注意力机制,有效解决了光照变化和遮挡场景下的安全带检测难题,为 Euro NCAP 2026 合规提供了可靠的技术方案。


参考链接:


KPGBeltNet:基于关键点引导采样的安全带检测算法
https://dapalm.com/2026/07/24/2026-07-24-kpgbeltnet-seatbelt-detection-algorithm/
作者
Mars
发布于
2026年7月24日
许可协议