基于YOLO与伺服电机的AI自动追踪摄像机DIY全流程详解

基于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 感知-决策-控制的完整流程。

它能解决什么问题?

  1. 动态目标持续锁定:在视频流中,即使目标短暂被遮挡或快速移动,也能保持 ID 一致并持续追踪。
  2. 硬件自动反馈控制:将 AI 的“感知”结果(目标坐标)实时转化为“动作”(电机转动),形成闭环。
  3. 低成本原型验证:用相对廉价的硬件(几百元)验证自动追踪概念,无需购买昂贵的商用云台摄像机。

不适合什么场景?

  1. 绝对安全关键场景:如自动驾驶、精密工业检测。本项目是原型,延迟和可靠性未经过严格认证。
  2. 极端光照或恶劣环境:复杂光线、雨雪天气会严重影响摄像头成像和 YOLO 检测精度。
  3. 需要 7x24 小时无人值守稳定运行:DIY 项目在长期运行稳定性上可能不及商业产品。

版权、隐私与安全边界

  • 模型使用:YOLO 是开源模型,可用于个人学习和非商业项目。若用于商业产品,请注意 Ultralytics 的许可证协议 (AGPL-3.0)。
  • 隐私保护:该系统处理视频流,切勿在未经他人同意的情况下在私人或公共空间进行录制和追踪,这涉及严重的隐私和法律问题。请在明确授权的、可控的测试环境(如自家书房、实验室)中进行。
  • 硬件安全:确保云台固定牢固,电机扭矩设置合理,避免转动时拉扯线缆或造成机械损伤。调试时远离人脸和易碎品。

3. 环境准备与前置条件

开始编码前,请确保你的软硬件环境就绪。

3.1 硬件清单与组装

  1. 计算设备
    • 主控电脑:一台装有 Windows/Linux/macOS 的电脑。推荐使用带有 NVIDIA GPU 的电脑以获得最佳实时性能。集显或 CPU 也可运行,但帧率会受限。
    • 微控制器(可选但推荐):用于生成精确的 PWM 信号控制舵机。常见选择:
      • Arduino Uno/Nano:成本低,易于编程,通过 USB 串口与电脑通信。
      • 树莓派 Pico:性价比高,原生支持 MicroPython/CircuitPython。
      • 树莓派 4B/5:可直接运行 Python 和 OpenCV,实现“All in One”,但电机控制精度可能不如专用单片机。
  2. 视觉与云台
    • 摄像头:普通的 USB 网络摄像头即可,分辨率 720p 或 1080p。确保帧率在 30fps 左右。
    • 二维云台:包含两个自由度(俯仰和偏航)的云台套件。通常包含两个舵机(如 SG90、MG996R)和云台支架。
    • 舵机驱动板(如果使用 Arduino):如 PCA9685,这是一个 I2C 接口的 16 通道 PWM 舵机驱动板,可以精确控制多个舵机。
    • 连接线:杜邦线(公对公、公对母)若干。
    • 电源:为舵机单独供电(通常需要 5V-6V,2A 以上的电源),切勿直接从 Arduino 的 5V 引脚取电给大扭矩舵机,可能导致板子损坏。
  3. 组装步骤
    1. 将摄像头固定在云台顶部的平台上。
    2. 将两个舵机分别安装到云台的偏航(左右转)和俯仰(上下转)轴。
    3. 将舵机信号线连接到 PCA9685 驱动板的 PWM 输出通道(例如 Channel 0 和 Channel 1)。
    4. 将 PCA9685 的 VCC、GND、SDA、SCL 连接到 Arduino 的对应引脚(5V, GND, A4/SDA, A5/SCL)。
    5. 为 PCA9685 和舵机连接外部电源(共地)。
    6. 将 Arduino 通过 USB 线连接到电脑。
    7. 将 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 代码关键点解析

  1. 模型与追踪器加载YOLO(model_name)加载检测模型,.track(..., tracker=tracker_config)启用指定追踪器。追踪器负责在视频帧之间维持目标 ID。
  2. 目标选择策略:代码中选择了置信度最高的“人”作为追踪目标 (target_class_ids = [0])。你可以修改为追踪车、狗等,或实现多目标中选择最近/最大的目标等更复杂的策略。
  3. 控制逻辑calculate_control函数实现了最简单的比例控制。误差是目标中心与画面中心的像素差。angle_adjust * 0.1是一个比例系数,需要根据你的云台转动速度、摄像头视野和电机响应速度进行实地调试。更优的方案是使用完整的 PID 控制器。
  4. 串口通信:指令格式为P,角度值T,角度值,以换行符\n结束,与 Arduino 代码匹配。
  5. 可视化:使用 OpenCV 绘制目标中心点、轨迹线和云台角度信息,便于调试。

5. 功能测试与效果验证

部署完硬件和软件后,按以下步骤进行测试。

5.1 分步测试流程

  1. 硬件独立测试

    • 烧录 Arduino 代码后,打开串口监视器(波特率 115200)。
    • 手动发送P,45T,135等指令,观察云台是否正确转动到指定角度。确保转动平滑且范围正确(0-180度)。
  2. YOLO 检测与追踪测试(不连接硬件)

    • 暂时注释掉 Python 代码中与串口相关的行(self.ser.write)。
    • 运行主程序,确保摄像头能打开,并且 YOLO 能正确检测并追踪到人。观察画面中的边界框、ID 和轨迹线是否正常显示。
    • 尝试在AITrackingCamera初始化时更换不同的tracker参数(如bytetrack.yaml),观察不同追踪器在目标遮挡、快速移动时的表现差异。
  3. 集成联调

    • 恢复串口代码,确保 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根据场景选择追踪器(见下文“追踪器选型指南”)。调整confiou参数。
云台不转动串口未连接、波特率不匹配或指令格式错误。检查 Arduino 端口号COM_PORT是否正确。检查 Arduino 串口监视器是否能收到数据。确认端口号,确保 Python 和 Arduino 代码波特率一致。检查指令末尾是否有\n
云台转动方向相反舵机安装方向或控制逻辑正负号错误。观察转动方向与预期是否相反。calculate_control函数中,调整angle_adjust_xangle_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. 项目扩展与下一步

这个基础项目可以朝多个方向扩展:

  1. 多目标选择策略:当前是追踪置信度最高的目标。可以改为追踪画面中最大的目标、最近的目标,或者通过点击画面选择目标。
  2. 更先进的控制算法:用更完整的 PID 控制器,甚至引入滤波(如卡尔曼滤波)来预测目标运动,使云台运动更平滑。
  3. 集成到机器人系统:将本程序作为一个 ROS2 节点,发布目标位置话题,供其他导航或决策节点使用。
  4. 添加网络功能:使用 Flask 或 FastAPI 包裹一个 Web API,可以远程查看画面、选择追踪目标、控制云台。
  5. 使用树莓派作为主控:将整个 Python 程序移植到树莓派上,配合树莓派摄像头,实现真正的嵌入式独立设备。需要注意树莓派的算力可能只支持 YOLO 的 Nano 版本。

9. 总结

这个“自制 AI 自动追踪摄像机”项目成功地将前沿的 YOLO 多目标追踪算法与传统的硬件控制结合起来。你不仅学会了如何使用 Ultralytics YOLO 的多种追踪器,还掌握了通过串口控制舵机云台的方法。

最值得尝试的点:体验从 AI 感知到物理执行的完整链路。调试 PID 参数让云台平稳追踪的过程,是理解控制理论的绝佳实践。

最先应该验证的功能:确保 YOLO 检测追踪单独工作正常,再单独测试云台串口控制,最后进行集成。分步调试是成功的关键。

最容易踩的坑

  1. 电源问题:舵机务必外接供电,否则 Arduino 可能重启或烧毁。
  2. 控制参数:PID 参数需要耐心调试,从很小的kp开始。
  3. 追踪器选择:对于运动的云台,务必使用带摄像机运动补偿 (CMC) 的追踪器,如 BoT-SORT。
  4. 延迟:整个系统的延迟(摄像头采集、推理、计算、串口通信、电机响应)会影响追踪效果。在代码中打印帧率 (FPS),并尝试优化每一步。

这个项目代码和思路已经为你搭好了骨架,剩下的就是动手组装、调试和优化。建议收藏本文,在实践过程中随时回头查阅各个模块的配置和问题排查方法。

🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度