基于YOLO与伺服电机的AI自动追踪摄像机DIY全流程详解
🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度
这次我们来看一个硬核的动手项目:如何用 YOLO 目标检测与追踪技术,结合伺服电机和云台,自制一个能自动识别并追踪目标的 AI 摄像机。这个项目不是简单的软件演示,而是从硬件组装、模型训练到软件控制的完整闭环。如果你对计算机视觉、嵌入式控制和 AI 应用集成感兴趣,这篇文章将带你一步步实现它。
项目的核心思路很清晰:利用 YOLO 模型实时分析摄像头画面,识别出目标(比如人、车、宠物)并计算出其在画面中的位置坐标。然后,通过一个控制程序,将这些坐标转换为云台伺服电机的控制指令,驱动摄像头转动,让目标始终保持在画面中央。整个过程完全自动化,无需人工干预。
这个 DIY 项目的价值在于,它打通了从 AI 算法到物理执行器的链路。你不仅会用到最新的 YOLO 多目标追踪技术(如 BoT-SORT、ByteTrack),还需要处理串口通信、PID 控制等硬件交互知识。无论是用于智能监控、自动跟拍,还是作为机器人视觉模块,都是一个极佳的学习和实践案例。接下来,我们将从核心能力、硬件选型、软件部署到最终联调,详细拆解整个实现过程。
1. 核心能力速览
在开始动手前,我们先快速了解这个“AI 自动追踪摄像机”项目能做什么,以及你需要准备什么。
| 能力项 | 说明 |
|---|---|
| 核心功能 | 实时视频流目标检测与追踪,并自动控制云台伺服电机使目标居中。 |
| AI 模型 | 基于 Ultralytics YOLO (v8/v11/YOLO26) 系列模型,支持 Detect、Segment、Pose 等多种任务,并集成 BoT-SORT、ByteTrack 等先进追踪器。 |
| 硬件门槛 | 中低门槛。需要一台带 GPU 的电脑(用于模型推理),一个 USB 摄像头或网络摄像头,一个二维云台(含两个舵机或步进电机),以及对应的电机驱动板(如 PCA9685)和微控制器(如 Arduino/树莓派)。CPU 也可推理,但帧率会降低。 |
| 显存/内存占用 | 取决于所选 YOLO 模型尺寸。例如,yolo26n.pt在 GPU 上推理时显存占用通常在 1-2GB 左右;yolo26s.pt或更大模型需要更多显存。CPU 推理则主要占用内存。 |
| 软件栈 | Python 3.8+, Ultralytics, OpenCV, PySerial (用于串口通信), 可选:ROS2 (用于更复杂的机器人集成)。 |
| 启动方式 | 通过 Python 脚本一键启动。脚本将同时运行:1. 摄像头视频捕获与 YOLO 推理追踪;2. 目标位置到电机控制量的计算;3. 通过串口向硬件发送控制指令。 |
| 接口/扩展能力 | 核心是一个 Python 类,提供检测结果回调函数,易于集成到其他系统。支持多线程处理多个视频流。可通过修改追踪器配置文件 (botsort.yaml,bytetrack.yaml等) 来切换和调优追踪算法。 |
| 适合场景 | 教育演示、智能监控原型、自动跟拍系统、机器人视觉伺服、互动装置。不适合对追踪精度和延迟有极端要求的工业级应用。 |
2. 适用场景与使用边界
这个项目适合谁?
- 计算机视觉学习者:想深入了解目标检测、多目标追踪 (MOT) 算法如何与硬件结合。
- 嵌入式开发爱好者:希望用 Python/Arduino 实现软硬件交互,控制电机。
- 创客/极客:热衷于打造个性化的智能硬件,如自动追踪宠物的摄像头、自动演讲跟踪器。
- 教育/研究机构:用于演示 AI 感知-决策-控制的完整流程。
它能解决什么问题?
- 动态目标持续锁定:在视频流中,即使目标短暂被遮挡或快速移动,也能保持 ID 一致并持续追踪。
- 硬件自动反馈控制:将 AI 的“感知”结果(目标坐标)实时转化为“动作”(电机转动),形成闭环。
- 低成本原型验证:用相对廉价的硬件(几百元)验证自动追踪概念,无需购买昂贵的商用云台摄像机。
不适合什么场景?
- 绝对安全关键场景:如自动驾驶、精密工业检测。本项目是原型,延迟和可靠性未经过严格认证。
- 极端光照或恶劣环境:复杂光线、雨雪天气会严重影响摄像头成像和 YOLO 检测精度。
- 需要 7x24 小时无人值守稳定运行:DIY 项目在长期运行稳定性上可能不及商业产品。
版权、隐私与安全边界
- 模型使用:YOLO 是开源模型,可用于个人学习和非商业项目。若用于商业产品,请注意 Ultralytics 的许可证协议 (AGPL-3.0)。
- 隐私保护:该系统处理视频流,切勿在未经他人同意的情况下在私人或公共空间进行录制和追踪,这涉及严重的隐私和法律问题。请在明确授权的、可控的测试环境(如自家书房、实验室)中进行。
- 硬件安全:确保云台固定牢固,电机扭矩设置合理,避免转动时拉扯线缆或造成机械损伤。调试时远离人脸和易碎品。
3. 环境准备与前置条件
开始编码前,请确保你的软硬件环境就绪。
3.1 硬件清单与组装
- 计算设备:
- 主控电脑:一台装有 Windows/Linux/macOS 的电脑。推荐使用带有 NVIDIA GPU 的电脑以获得最佳实时性能。集显或 CPU 也可运行,但帧率会受限。
- 微控制器(可选但推荐):用于生成精确的 PWM 信号控制舵机。常见选择:
- Arduino Uno/Nano:成本低,易于编程,通过 USB 串口与电脑通信。
- 树莓派 Pico:性价比高,原生支持 MicroPython/CircuitPython。
- 树莓派 4B/5:可直接运行 Python 和 OpenCV,实现“All in One”,但电机控制精度可能不如专用单片机。
- 视觉与云台:
- 摄像头:普通的 USB 网络摄像头即可,分辨率 720p 或 1080p。确保帧率在 30fps 左右。
- 二维云台:包含两个自由度(俯仰和偏航)的云台套件。通常包含两个舵机(如 SG90、MG996R)和云台支架。
- 舵机驱动板(如果使用 Arduino):如 PCA9685,这是一个 I2C 接口的 16 通道 PWM 舵机驱动板,可以精确控制多个舵机。
- 连接线:杜邦线(公对公、公对母)若干。
- 电源:为舵机单独供电(通常需要 5V-6V,2A 以上的电源),切勿直接从 Arduino 的 5V 引脚取电给大扭矩舵机,可能导致板子损坏。
- 组装步骤:
- 将摄像头固定在云台顶部的平台上。
- 将两个舵机分别安装到云台的偏航(左右转)和俯仰(上下转)轴。
- 将舵机信号线连接到 PCA9685 驱动板的 PWM 输出通道(例如 Channel 0 和 Channel 1)。
- 将 PCA9685 的 VCC、GND、SDA、SCL 连接到 Arduino 的对应引脚(5V, GND, A4/SDA, A5/SCL)。
- 为 PCA9685 和舵机连接外部电源(共地)。
- 将 Arduino 通过 USB 线连接到电脑。
- 将 USB 摄像头连接到电脑。
3.2 软件环境安装
在电脑上配置 Python 环境:
# 1. 创建并激活虚拟环境 (推荐) conda create -n ai-tracker python=3.10 conda activate ai-tracker # 或使用 venv python -m venv ai-tracker source ai-tracker/bin/activate # Linux/macOS ai-tracker\Scripts\activate # Windows # 2. 安装核心AI与视觉库 pip install ultralytics opencv-python opencv-contrib-python # 3. 安装硬件通信库 pip install pyserial # 用于与 Arduino 串口通信 # 如果需要使用 PCA9685,在电脑端通常不需要额外库,控制逻辑在 Arduino。 # 4. 安装其他可能用到的工具库 pip install numpy matplotlib验证 Ultralytics YOLO 安装:
from ultralytics import YOLO model = YOLO('yolo26n.pt') print(model.info()) # 如果能打印出模型信息,说明安装成功4. 软件部分:YOLO 追踪与云台控制逻辑
这是项目的核心代码部分。我们将分模块构建。
4.1 Arduino 端代码 (云台控制)
首先,在 Arduino IDE 中编写代码,烧录到 Arduino 板子上。这段代码负责从串口读取指令,并控制 PCA9685 驱动舵机。
#include <Wire.h> #include <Adafruit_PWMServoDriver.h> // 初始化 PCA9685 对象 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // 定义舵机通道 #define SERVO_PAN_CHANNEL 0 // 偏航舵机(左右) #define SERVO_TILT_CHANNEL 1 // 俯仰舵机(上下) // 舵机脉宽范围(微秒),根据你的舵机规格调整 #define SERVOMIN 150 #define SERVOMAX 600 // 初始化舵机角度 int panAngle = 90; // 初始居中,范围 0-180 int tiltAngle = 90; void setup() { Serial.begin(115200); // 设置串口波特率,与Python端匹配 pwm.begin(); pwm.setPWMFreq(50); // 舵机控制频率通常为50Hz // 初始位置居中 setServoAngle(SERVO_PAN_CHANNEL, panAngle); setServoAngle(SERVO_TILT_CHANNEL, tiltAngle); delay(1000); } void loop() { // 监听串口指令 if (Serial.available() > 0) { String command = Serial.readStringUntil('\n'); command.trim(); // 指令格式期望为: "P,100" 或 "T,80",分别控制 Pan 和 Tilt int commaIndex = command.indexOf(','); if (commaIndex != -1) { char axis = command.charAt(0); int targetAngle = command.substring(commaIndex + 1).toInt(); // 限制角度范围 targetAngle = constrain(targetAngle, 0, 180); if (axis == 'P') { panAngle = targetAngle; setServoAngle(SERVO_PAN_CHANNEL, panAngle); } else if (axis == 'T') { tiltAngle = targetAngle; setServoAngle(SERVO_TILT_CHANNEL, tiltAngle); } } } } // 将角度(0-180)转换为 PCA9685 可用的脉宽值 void setServoAngle(int channel, int angle) { int pulse = map(angle, 0, 180, SERVOMIN, SERVOMAX); pwm.setPWM(channel, 0, pulse); }4.2 Python 端主控程序
这是运行在电脑上的主程序,它执行 YOLO 检测追踪,并计算控制指令发送给 Arduino。
import cv2 import serial import threading import time from collections import defaultdict from ultralytics import YOLO import numpy as np class AITrackingCamera: def __init__(self, com_port='COM3', baudrate=115200, camera_id=0, model_name='yolo26n.pt', tracker='botsort.yaml'): """ 初始化 AI 追踪摄像机 :param com_port: Arduino 串口,Windows 为 'COM3',Linux/macOS 为 '/dev/ttyUSB0' 或 '/dev/ttyACM0' :param baudrate: 串口波特率,需与 Arduino 程序一致 :param camera_id: 摄像头设备ID,0 为默认摄像头 :param model_name: YOLO 模型路径或名称,如 'yolo26n.pt' :param tracker: 追踪器配置文件,如 'botsort.yaml', 'bytetrack.yaml' """ # 初始化串口连接 try: self.ser = serial.Serial(com_port, baudrate, timeout=1) time.sleep(2) # 等待串口初始化 print(f"[INFO] 已连接到串口 {com_port}") except Exception as e: print(f"[ERROR] 无法打开串口 {com_port}: {e}") self.ser = None # 初始化摄像头 self.cap = cv2.VideoCapture(camera_id) if not self.cap.isOpened(): raise IOError(f"无法打开摄像头 {camera_id}") self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 设置分辨率,可根据性能调整 self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) print(f"[INFO] 摄像头 {camera_id} 已就绪") # 加载 YOLO 模型和追踪器 self.model = YOLO(model_name) self.tracker_config = tracker print(f"[INFO] 已加载模型 {model_name} 和追踪器 {tracker}") # 追踪历史记录,用于绘制轨迹 self.track_history = defaultdict(lambda: []) # 云台控制参数 self.frame_center_x = 320 # 假设帧宽640,中心点x坐标 self.frame_center_y = 240 # 假设帧高480,中心点y坐标 self.pan_angle = 90 # 初始角度,居中 self.tilt_angle = 90 self.pid_pan = PID(kp=0.5, ki=0.01, kd=0.05) # 简单的PID控制器,参数需调试 self.pid_tilt = PID(kp=0.5, ki=0.01, kd=0.05) # 选择追踪的目标类别 (COCO数据集类别索引) self.target_class_ids = [0] # 0: 'person',可以改为其他,如 [2] 为车, [16] 为狗 # 运行标志 self.running = True def send_servo_command(self, axis, angle): """通过串口发送舵机控制指令""" if self.ser and self.ser.is_open: command = f"{axis},{angle}\n" self.ser.write(command.encode()) # print(f"[DEBUG] 发送指令: {command.strip()}") def calculate_control(self, bbox_center_x, bbox_center_y): """ 根据目标边界框中心点计算云台需要调整的角度。 使用简单的比例控制,将像素误差转换为角度调整量。 """ # 计算目标中心与画面中心的误差(像素) error_x = bbox_center_x - self.frame_center_x error_y = bbox_center_y - self.frame_center_y # 使用 PID 控制器计算角度调整量(这里简化,直接使用比例控制) # 更复杂的系统可以使用完整的 PID 或滤波算法 angle_adjust_x = self.pid_pan.update(error_x) angle_adjust_y = self.pid_tilt.update(error_y) # 更新目标角度,并限制在0-180度范围内 new_pan_angle = int(self.pan_angle - angle_adjust_x * 0.1) # 系数需要根据云台实际转动速度调整 new_tilt_angle = int(self.tilt_angle + angle_adjust_y * 0.1) # Y轴方向可能相反 new_pan_angle = max(0, min(180, new_pan_angle)) new_tilt_angle = max(0, min(180, new_tilt_angle)) # 如果角度变化超过阈值,则发送指令 if abs(new_pan_angle - self.pan_angle) > 1 or abs(new_tilt_angle - self.tilt_angle) > 1: self.pan_angle = new_pan_angle self.tilt_angle = new_tilt_angle self.send_servo_command('P', self.pan_angle) self.send_servo_command('T', self.tilt_angle) return new_pan_angle, new_tilt_angle def run_tracking(self): """主循环:捕获帧,运行YOLO追踪,计算控制指令并显示""" print("[INFO] 开始追踪,按 'q' 键退出。") while self.running: success, frame = self.cap.read() if not success: print("[WARNING] 无法从摄像头读取帧。") break # 运行 YOLO 追踪 results = self.model.track(frame, persist=True, tracker=self.tracker_config, verbose=False) # 获取追踪结果 if results[0].boxes is not None and results[0].boxes.id is not None: boxes = results[0].boxes.xyxy.cpu().numpy() # 边界框 [x1, y1, x2, y2] track_ids = results[0].boxes.id.cpu().numpy().astype(int) class_ids = results[0].boxes.cls.cpu().numpy().astype(int) confidences = results[0].boxes.conf.cpu().numpy() # 选择要追踪的目标(例如,选择置信度最高的人) target_idx = None max_conf = 0 for i, (cls_id, conf) in enumerate(zip(class_ids, confidences)): if cls_id in self.target_class_ids and conf > max_conf: max_conf = conf target_idx = i if target_idx is not None: # 获取目标边界框中心 x1, y1, x2, y2 = boxes[target_idx] bbox_center_x = int((x1 + x2) / 2) bbox_center_y = int((y1 + y2) / 2) track_id = track_ids[target_idx] # 计算并发送云台控制指令 pan_angle, tilt_angle = self.calculate_control(bbox_center_x, bbox_center_y) # 在帧上绘制信息 label = f"ID:{track_id} Pan:{pan_angle} Tilt:{tilt_angle}" cv2.circle(frame, (bbox_center_x, bbox_center_y), 5, (0, 255, 0), -1) cv2.putText(frame, label, (int(x1), int(y1)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # 更新并绘制轨迹 track = self.track_history[track_id] track.append((bbox_center_x, bbox_center_y)) if len(track) > 30: track.pop(0) points = np.array(track, dtype=np.int32).reshape((-1, 1, 2)) cv2.polylines(frame, [points], isClosed=False, color=(0, 255, 255), thickness=2) # 在画面中心画一个十字 cv2.drawMarker(frame, (self.frame_center_x, self.frame_center_y), (255, 0, 0), cv2.MARKER_CROSS, 20, 2) # 显示帧 annotated_frame = results[0].plot() # 使用 Ultralytics 内置绘图功能 cv2.imshow('AI Tracking Camera', annotated_frame) # 按键退出 if cv2.waitKey(1) & 0xFF == ord('q'): self.running = False break self.release() def release(self): """释放资源""" self.running = False if self.cap: self.cap.release() cv2.destroyAllWindows() if self.ser and self.ser.is_open: self.ser.close() print("[INFO] 资源已释放。") # 一个简单的 PID 控制器类(简化版,仅用于演示) class PID: def __init__(self, kp, ki, kd): self.kp = kp self.ki = ki self.kd = kd self.prev_error = 0 self.integral = 0 def update(self, error): self.integral += error derivative = error - self.prev_error output = self.kp * error + self.ki * self.integral + self.kd * derivative self.prev_error = error return output if __name__ == "__main__": # 配置参数:请根据你的实际设置修改! COM_PORT = 'COM3' # Windows 示例 # COM_PORT = '/dev/ttyUSB0' # Linux 示例 CAMERA_ID = 0 # 通常 0 是内置摄像头,1 是外接USB摄像头 MODEL_NAME = 'yolo26n.pt' # 也可以尝试 'yolo26s.pt' 等 TRACKER_CONFIG = 'botsort.yaml' # 可选:'bytetrack.yaml', 'ocsort.yaml' tracker_cam = AITrackingCamera(com_port=COM_PORT, camera_id=CAMERA_ID, model_name=MODEL_NAME, tracker=TRACKER_CONFIG) try: tracker_cam.run_tracking() except KeyboardInterrupt: tracker_cam.release()4.3 代码关键点解析
- 模型与追踪器加载:
YOLO(model_name)加载检测模型,.track(..., tracker=tracker_config)启用指定追踪器。追踪器负责在视频帧之间维持目标 ID。 - 目标选择策略:代码中选择了置信度最高的“人”作为追踪目标 (
target_class_ids = [0])。你可以修改为追踪车、狗等,或实现多目标中选择最近/最大的目标等更复杂的策略。 - 控制逻辑:
calculate_control函数实现了最简单的比例控制。误差是目标中心与画面中心的像素差。angle_adjust * 0.1是一个比例系数,需要根据你的云台转动速度、摄像头视野和电机响应速度进行实地调试。更优的方案是使用完整的 PID 控制器。 - 串口通信:指令格式为
P,角度值和T,角度值,以换行符\n结束,与 Arduino 代码匹配。 - 可视化:使用 OpenCV 绘制目标中心点、轨迹线和云台角度信息,便于调试。
5. 功能测试与效果验证
部署完硬件和软件后,按以下步骤进行测试。
5.1 分步测试流程
硬件独立测试:
- 烧录 Arduino 代码后,打开串口监视器(波特率 115200)。
- 手动发送
P,45和T,135等指令,观察云台是否正确转动到指定角度。确保转动平滑且范围正确(0-180度)。
YOLO 检测与追踪测试(不连接硬件):
- 暂时注释掉 Python 代码中与串口相关的行(
self.ser.write)。 - 运行主程序,确保摄像头能打开,并且 YOLO 能正确检测并追踪到人。观察画面中的边界框、ID 和轨迹线是否正常显示。
- 尝试在
AITrackingCamera初始化时更换不同的tracker参数(如bytetrack.yaml),观察不同追踪器在目标遮挡、快速移动时的表现差异。
- 暂时注释掉 Python 代码中与串口相关的行(
集成联调:
- 恢复串口代码,确保 Arduino 已连接。
- 运行完整程序。让人在摄像头前移动。
- 观察:摄像头画面中的十字中心是否试图跟随目标中心?云台是否随之转动?
- 调试控制参数:如果云台转动过于剧烈(震荡)或过于缓慢(跟不上),需要调整
PID类中的kp,ki,kd参数,以及calculate_control函数中的比例系数0.1。
5.2 预期效果与成功标准
- 成功标准 1(检测追踪):画面中人物被稳定框出,且 ID 在短时间内保持恒定,即使有短暂遮挡或交叉,ID 交换频率较低。
- 成功标准 2(云台响应):当人物横向移动时,偏航(Pan)舵机应带动云台左右转动,试图将人物保持在画面水平中央。当人物纵向移动时,俯仰(Tilt)舵机应上下转动。
- 成功标准 3(闭环稳定):系统应能形成一个稳定的负反馈闭环。目标左移 -> 云台左转 -> 目标在画面中右移(相对)-> 误差减小 -> 云台减速直至停止。整个过程应平滑,无持续振荡。
5.3 常见失败原因排查
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 摄像头无画面 | 摄像头被其他程序占用或 ID 错误。 | 检查cv2.VideoCapture(CAMERA_ID)中的 ID。尝试1,2。 | 关闭其他可能使用摄像头的软件(如微信、Zoom)。 |
| YOLO 检测不到目标 | 模型未下载、类别不匹配或环境太暗。 | 检查控制台是否有模型下载提示。确认target_class_ids设置正确。 | 确保网络通畅,首次运行会自动下载模型。增加光照或换用更大的模型(如yolo26s.pt)。 |
| 追踪 ID 频繁跳变 | 追踪器选择不当或参数不佳。 | 尝试更换追踪器,如从botsort.yaml换为bytetrack.yaml。 | 根据场景选择追踪器(见下文“追踪器选型指南”)。调整conf和iou参数。 |
| 云台不转动 | 串口未连接、波特率不匹配或指令格式错误。 | 检查 Arduino 端口号COM_PORT是否正确。检查 Arduino 串口监视器是否能收到数据。 | 确认端口号,确保 Python 和 Arduino 代码波特率一致。检查指令末尾是否有\n。 |
| 云台转动方向相反 | 舵机安装方向或控制逻辑正负号错误。 | 观察转动方向与预期是否相反。 | 在calculate_control函数中,调整angle_adjust_x或angle_adjust_y前的正负号。或物理上调整舵机安装方向。 |
| 云台振荡(来回抖) | PID 参数kp过大或系统延迟大。 | 观察云台是否在目标位置附近来回摆动。 | 大幅降低kp值,例如从 0.5 降到 0.1。增加微分项kd以抑制振荡。 |
| 云台响应迟钝 | PID 参数kp过小。 | 观察云台转动是否缓慢,总是跟不上目标。 | 适当增加kp值。检查摄像头帧率是否过低(应 >15fps)。 |
6. 追踪器选型与高级配置
根据网络搜索材料,Ultralytics YOLO 提供了多种追踪器。在云台追踪场景下,选择合适的追踪器至关重要。
6.1 如何选择追踪器?
参考官方指南,并结合云台追踪场景:
- ByteTrack:最轻量,开销最小。适合背景简单、目标运动平缓的静态摄像头场景。如果你的摄像头固定不动,只是目标在动,可以优先尝试 ByteTrack。
- BoT-SORT(默认):在 ByteTrack 基础上增加了摄像机运动补偿 (CMC)。这正好适合我们的场景!因为云台转动时,摄像头本身就在运动。BoT-SORT 能更好地处理这种全局运动,是移动云台摄像机的推荐起点。
- OC-SORT:擅长处理非线性、突然变向的运动(如体育比赛)。如果追踪目标经常做不规则运动,可以尝试。
- Deep OC-SORT / TrackTrack:在拥挤、遮挡严重的场景下表现更好,ID 交换更少。但计算开销稍大。如果追踪单个目标,前三个通常足够。
建议:在AITrackingCamera初始化时,通过tracker='botsort.yaml'参数进行切换测试。
6.2 自定义追踪器参数
你可以复制 Ultralytics 的追踪器配置文件并修改,以适应你的场景。例如,创建my_botsort.yaml:
# my_botsort.yaml tracker_type: botsort track_high_thresh: 0.25 # 高置信度检测阈值,降低可检测更模糊目标 track_low_thresh: 0.1 # 低置信度检测阈值 new_track_thresh: 0.3 # 初始化新轨迹的阈值 track_buffer: 60 # 轨迹保留帧数,应对遮挡,云台场景可适当增大 match_thresh: 0.8 # 匹配阈值 fuse_score: True gmc_method: sparseOptFlow # 摄像机运动补偿方法,对云台至关重要 proximity_thresh: 0.5 appearance_thresh: 0.25 with_reid: False # 除非追踪多人且频繁交叉,否则关闭以节省资源然后在代码中加载:
TRACKER_CONFIG = 'path/to/my_botsort.yaml'6.3 启用重识别 (ReID) 以应对严重遮挡
如果追踪的目标(如特定的人)会长时间被遮挡,可以启用 ReID。在配置文件中设置with_reid: True,并使用model: auto或指定一个 ReID 模型(如yolo26n-reid.onnx)。注意,这会增加计算量。
7. 性能优化与资源占用
- 模型选择:
yolo26n.pt(纳米) 速度最快,显存占用约 1-2GB,精度尚可。yolo26s.pt(小) 精度更高,显存占用增加。在 Jetson Nano 或树莓派 5 上,可能只能流畅运行 Nano 版本。 - 分辨率与帧率:代码中设置了
640x480。降低分辨率(如320x240)可大幅提升帧率,但会降低检测距离和精度。可以在cv2.VideoCapture后使用cv2.resize进一步缩放。 - CPU vs GPU:如果没有 GPU,Ultralytics 会自动回退到 CPU 推理。CPU 推理速度会慢很多,可能导致云台控制延迟过高。务必在性能足够的设备上运行。
- 多线程:如果未来需要处理多个摄像头,可以参考网络材料中的多线程示例,将每个摄像头的处理放在独立线程中。
8. 项目扩展与下一步
这个基础项目可以朝多个方向扩展:
- 多目标选择策略:当前是追踪置信度最高的目标。可以改为追踪画面中最大的目标、最近的目标,或者通过点击画面选择目标。
- 更先进的控制算法:用更完整的 PID 控制器,甚至引入滤波(如卡尔曼滤波)来预测目标运动,使云台运动更平滑。
- 集成到机器人系统:将本程序作为一个 ROS2 节点,发布目标位置话题,供其他导航或决策节点使用。
- 添加网络功能:使用 Flask 或 FastAPI 包裹一个 Web API,可以远程查看画面、选择追踪目标、控制云台。
- 使用树莓派作为主控:将整个 Python 程序移植到树莓派上,配合树莓派摄像头,实现真正的嵌入式独立设备。需要注意树莓派的算力可能只支持 YOLO 的 Nano 版本。
9. 总结
这个“自制 AI 自动追踪摄像机”项目成功地将前沿的 YOLO 多目标追踪算法与传统的硬件控制结合起来。你不仅学会了如何使用 Ultralytics YOLO 的多种追踪器,还掌握了通过串口控制舵机云台的方法。
最值得尝试的点:体验从 AI 感知到物理执行的完整链路。调试 PID 参数让云台平稳追踪的过程,是理解控制理论的绝佳实践。
最先应该验证的功能:确保 YOLO 检测追踪单独工作正常,再单独测试云台串口控制,最后进行集成。分步调试是成功的关键。
最容易踩的坑:
- 电源问题:舵机务必外接供电,否则 Arduino 可能重启或烧毁。
- 控制参数:PID 参数需要耐心调试,从很小的
kp开始。 - 追踪器选择:对于运动的云台,务必使用带摄像机运动补偿 (CMC) 的追踪器,如 BoT-SORT。
- 延迟:整个系统的延迟(摄像头采集、推理、计算、串口通信、电机响应)会影响追踪效果。在代码中打印帧率 (FPS),并尝试优化每一步。
这个项目代码和思路已经为你搭好了骨架,剩下的就是动手组装、调试和优化。建议收藏本文,在实践过程中随时回头查阅各个模块的配置和问题排查方法。
🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度