3. 目标检测基础
目标检测是机器人目标跟随系统的“眼睛”,其核心任务是在图像或点云数据中定位感兴趣目标的边界框(Bounding Box)和类别标签。在ROS2框架下,检测算法需要被封装为独立的组件节点,通过话题(Topic)或服务(Service)与感知、规划、控制模块解耦通信。本章将系统梳理传统视觉方法与深度学习方法的适用边界,并给出在ROS2中集成检测算法的工程化路径。
3.1 传统目标检测方法:原理与适用场景
传统方法不依赖大规模标注数据,基于手工设计的特征与浅层分类器,在计算资源受限的嵌入式平台(如树莓派、Jetson Nano)上仍具实用价值。
3.1.1 Haar Cascade 级联分类器
核心原理:Haar特征描述图像局部灰度变化(边缘、线条、中心环绕),通过积分图快速计算。Adaboost算法迭代选择最优弱分类器,级联结构逐层拒绝非目标区域,实现快速筛选。
# ROS2中加载Haar模型示例
import cv2
from cv_bridge import CvBridge
cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY)
faces = cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30,30))
适用场景:人脸检测、简单刚体目标(如固定形状的箱子)。对计算资源要求极低,但光照变化、遮挡、旋转会导致漏检率显著上升。
3.1.2 HOG + SVM
HOG(方向梯度直方图)统计局部梯度方向分布,对目标轮廓敏感。SVM(支持向量机)在特征空间寻找最大间隔超平面。行人检测是经典应用案例。
3.1.3 模板匹配
通过滑动窗口计算模板与图像子区域的相似度(如归一化相关系数NCC)。适用于目标外观固定、无尺度变化的场景(如二维码定位)。
3.2 深度学习目标检测方法
深度学习方法通过卷积神经网络自动学习特征,在复杂场景下精度远超传统方法。根据检测流程分为两阶段和单阶段两类。
3.2.1 两阶段检测器:Faster R-CNN
RPN(区域提议网络)先生成候选框,再通过ROI Pooling提取固定尺寸特征,最后进行分类和回归。精度高但推理速度慢(约5-10 FPS),适合静态场景或离线处理。
3.2.2 单阶段检测器:YOLO系列
YOLO将检测视为回归问题,一次前向传播同时输出边界框坐标和类别概率。YOLOv5/v8在工程中应用最广,支持TensorRT加速,在Jetson Orin上可达30-60 FPS。
| 模型 | 输入尺寸 | mAP@0.5 | 推理时间(ms) | 模型大小(MB) |
|---|---|---|---|---|
| YOLOv5s | 640×640 | 37.4 | 6.3 | 14.4 |
| YOLOv8s | 640×640 | 44.9 | 8.7 | 22.5 |
| YOLOv5m | 640×640 | 45.4 | 12.1 | 42.0 |
选择建议:机器人跟随场景优先选择YOLOv5s或YOLOv8s,平衡精度与实时性。若目标类别单一(如仅人),可裁剪模型输出层减少计算量。
3.2.3 轻量化模型:MobileNet-SSD
MobileNet作为骨干网络大幅减少参数量,适合CPU推理。在树莓派4上可达15 FPS,但精度较YOLO低约10个百分点。
3.3 ROS2中集成检测算法的工程架构
ROS2的组件化设计允许将检测算法封装为独立节点,通过话题通信实现模块解耦。推荐使用rclpy或rclcpp编写节点,并利用cv_bridge完成ROS图像消息与OpenCV Mat的转换。
3.3.1 节点设计与话题定义
# 自定义消息: DetectionBox.msg
std_msgs/Header header
string class_name
float32 confidence
float32 x_min
float32 y_min
float32 x_max
float32 y_max
# 目标中心在相机坐标系下的3D位置(需结合深度)
geometry_msgs/Point center_3d
典型话题流:/camera/image_raw(传感器)→ /detection/boxes(检测结果)→ /target/pose(TF变换后)→ /cmd_vel(速度指令)。
3.3.2 集成流程(以YOLOv8为例)
- 模型导出:使用
yolo export model=yolov8s.pt format=onnx导出ONNX格式,便于跨平台部署。 - 推理封装:创建
YoloDetector类,加载ONNX模型,使用ONNX Runtime或TensorRT推理。 - ROS2节点:订阅
Image消息,在回调中调用推理接口,发布DetectionBox数组。 - 性能优化:使用
rclpy的qos设置(如SensorDataQoS)减少延迟;多线程执行器处理图像回调。
class YoloNode(Node):
def __init__(self):
super().__init__('yolo_detector')
self.sub = self.create_subscription(Image, '/camera/image_raw', self.callback, 10)
self.pub = self.create_publisher(DetectionBoxArray, '/detection/boxes', 10)
self.model = YOLO('yolov8s.pt')
def callback(self, msg):
cv_img = self.bridge.imgmsg_to_cv2(msg, 'bgr8')
results = self.model(cv_img, verbose=False)
boxes = self.parse_results(results)
self.pub.publish(boxes)
3.3.3 坐标变换与目标定位
检测框仅提供像素坐标,需结合相机内参和深度信息(或假设目标在地面平面)计算3D位置。使用tf2_ros将目标坐标从camera_link变换到base_link,供控制节点使用。
camera_calibration包)。深度相机(如RealSense D435)需对齐RGB与深度图,否则3D坐标误差可达数厘米。
3.4 实战案例:基于YOLOv5的室内人员跟随
场景与约束:室内走廊环境,机器人搭载Intel RealSense D435i相机,目标为实验室成员(单人),要求检测帧率≥20 FPS,跟随距离1-3米。
初始现象:使用YOLOv5s原始模型,检测精度良好但推理延迟达45ms(约22 FPS),且深度图对齐后目标中心点抖动严重。
分析过程:
- 延迟瓶颈:ONNX Runtime在CPU上推理耗时30ms,图像预处理(缩放+归一化)耗时10ms。
- 抖动原因:深度图噪声导致中心点深度值波动±5cm,直接映射到速度指令引起机器人抖动。
优化措施:
- 将输入尺寸从640×640降至416×416,mAP下降约2%,但推理时间降至18ms。
- 使用TensorRT FP16量化,推理时间进一步降至8ms。
- 对深度值应用中值滤波(核大小5),并限制目标中心点变化速率(低通滤波α=0.6)。
- 采用PID控制器,比例系数Kp=0.8,积分Ki=0.1,微分Kd=0.2,输出限幅±0.5 m/s。
结果对比:优化后帧率稳定在30 FPS,目标中心点标准差从4.2cm降至1.1cm,机器人跟随过程无明显抖动。
复盘经验:检测算法集成需关注端到端延迟(图像采集→推理→控制),而非仅模型推理时间。深度数据滤波与控制参数需联合调优,避免“检测准但控制差”的脱节问题。
3.5 常见误区与总结
| 误区 | 后果 | 正确做法 |
|---|---|---|
| 直接使用未标定相机 | 检测框偏移,3D定位误差大 | 先标定相机内参和畸变系数 |
| 忽略QoS设置 | 图像话题丢帧,检测延迟增大 | 使用SensorDataQoS(Best Effort) |
| 模型输入尺寸过大 | 推理时间超标,无法实时 | 根据硬件能力选择合适输入尺寸 |
| 未处理深度噪声 | 目标位置抖动,控制不稳定 | 滤波+限制变化速率 |
核心要点:目标检测方法选择需权衡精度、速度、硬件约束;ROS2集成应遵循“节点解耦、话题通信、参数可调”原则;检测结果必须经过坐标变换和滤波才能用于速度控制。下一环节将深入TF坐标变换的具体实现。