
项目来源:第三届3D视觉创新应用竞赛 项目名称:利用深度相机实现对校园流浪动物的管理 团队/作者:魏丙正,杭州电子科技大学 相机型号:Astra Pro 支持设备:STM32、树莓派4B、xiaoche 四轮移动机器人 源代码链接:https://github.com/3DCVdeveloper/RobotV_Campus-stray-animals
1. 项目一句话
这不是一台“会拍照的小车”,而是一套面向校园流浪猫狗管理的移动式3D视觉系统:它让机器人在巡逻中发现动物、判断猫狗类别、结合深度信息估计空间位置,并为后续的追踪、投喂、建档和健康管理提供数据入口。
可以把它理解为一个会移动的“校园动物管理节点”:
识别目标 → 感知距离 → 规划路线 → 靠近观察 → 建立档案 → 持续追踪
2. 为什么校园需要这样的机器人?
校园流浪动物通常活动范围大、出现时间不固定、个体特征相似,传统人工巡查很难做到连续记录。项目背景中提到的问题主要集中在三个方面:

项目的核心价值并不是“驱赶动物”,而是把不可预测的流浪动物活动变成可记录、可识别、可干预的数据化管理过程。对校园管理者来说,它提供的是巡逻、发现、识别、追踪、投喂和健康档案的闭环能力;对动物本身来说,它也为疫苗接种、救助和绝育等工作提供更稳定的基础信息。
3. 系统总体架构:一台小车,三层智能
项目搭建了一台四轮移动机器人,硬件上采用“运动控制 + 信息处理 + 3D感知”的分层结构。

在工作时,雷达负责提供环境与障碍物信息,树莓派进行信息处理后把运动意图传递给STM32;Astra Pro深度相机则负责采集动物的外观特征和空间信息,用于识别、建档、避障和追踪。
4. 软件算法:先看懂数据怎么流,再看懂算法怎么配合
这个项目不是把几个算法简单堆在一起,而是形成了一条完整的数据链路:传感器采集环境,树莓派进行视觉和导航计算,STM32执行运动控制,最后把识别结果沉淀为动物档案。
为了便于理解,可以先把系统抽象成下面这条主线:

这条链路里,每个算法都有非常清晰的位置:
| 模块 | 输入 | 输出 | 解决的问题 |
|---|---|---|---|
| FastSLAM | 雷达观测、里程计信息 | 机器人位姿、环境地图 | 我在哪里,周围环境长什么样 |
| A* | 地图、起点、目标点 | 全局路径 | 应该从哪条路线接近目标 |
| DWA | 当前速度、障碍物、局部目标 | 线速度、角速度 | 眼前怎么走才安全 |
| YOLOv7 | RGB图像 | 类别、置信度、检测框 | 画面里有没有猫狗 |
| 深度融合 | 检测框、深度图 | 目标距离、空间位置 | 猫狗离机器人有多远 |
| MedianFlow | 初始目标框、连续视频帧 | 连续目标轨迹 | 目标移动后如何持续跟踪 |
4.1 感知层:RGB-D相机与雷达分别负责什么?
Astra Pro提供RGB图像和深度图。RGB图像适合做“看清楚是什么”,深度图适合做“判断离我多远”。雷达则更适合做环境结构感知,例如墙体、路沿、树木、行人等障碍物。
一个简化后的传感器数据结构可以这样理解:
sensor_frame:
rgb_image: "640x480 BGR/RGB image"
depth_map: "640x480 depth value in millimeters"
lidar_scan:
angle_min: -135
angle_max: 135
ranges: [1.20, 1.18, 1.25, "..."]
timestamp: "2026-06-26T10:00:00"
其中,RGB图像进入YOLOv7做目标检测;深度图和检测框结合,计算目标距离;雷达数据进入建图与避障模块。三类信息分工明确,最后在树莓派侧融合。
4.2 定位建图:FastSLAM回答“机器人在哪里”
FastSLAM用于移动机器人定位与地图构建。它可以理解为“带着不确定性的地图绘制”:机器人一边移动,一边根据雷达观测和运动估计更新自己的位姿,同时维护校园环境地图。
理解性伪代码如下:
particles = init_particles(robot_start_pose)
while robot_is_running:
odom = read_wheel_odometry()
scan = read_lidar_scan()
# 1. 根据运动模型预测机器人可能到达的位置
particles = motion_update(particles, odom)
# 2. 用雷达观测修正每个粒子的可信度
particles = measurement_update(particles, scan)
# 3. 重采样,保留更可信的位置假设
particles = resample(particles)
# 4. 输出当前最可信位姿与地图
pose, map_grid = estimate_pose_and_map(particles)
校园环境的难点在于道路、草地、食堂门口、教学楼走廊等区域结构差异大,机器人不能只依赖固定路线。FastSLAM让小车在巡逻过程中持续更新“我在哪”和“周围有什么”,为后续路径规划提供基础。
**4.3 路径规划:A*负责大路线,DWA负责小动作**
A算法负责全局路径规划。它在地图上综合考虑起点、终点和路径代价,寻找一条整体较优路线。例如机器人从食堂门口移动到草坪投喂点时,A会给出一条大方向正确的路线。
def astar_plan(grid_map, start, goal):
open_set = PriorityQueue()
open_set.put(start, priority=0)
while not open_set.empty():
current = open_set.get()
if current == goal:
return rebuild_path(current)
for next_cell in neighbors(current):
cost = path_cost(current, next_cell) + heuristic(next_cell, goal)
open_set.put(next_cell, priority=cost)
DWA动态窗口法负责局部避障。它不会重新规划整条路线,而是在机器人当前速度能力范围内,枚举多组可行速度,选择“更接近目标、离障碍物更远、运动更平滑”的那一组。
def dwa_select_velocity(current_pose, current_velocity, local_goal, obstacles):
candidates = sample_velocity_window(current_velocity)
best_score = -float("inf")
best_cmd = (0.0, 0.0)
for v, w in candidates:
trajectory = simulate_motion(current_pose, v, w)
score = (
goal_score(trajectory, local_goal)
+ clearance_score(trajectory, obstacles)
+ smoothness_score(v, w)
)
if score > best_score:
best_score = score
best_cmd = (v, w)
return best_cmd
两者的关系可以概括为:A*告诉机器人“往哪个方向走”,DWA告诉机器人“下一秒怎么安全地走”。
4.4 控制执行:树莓派给决策,STM32管动作
树莓派更适合运行视觉识别、路径规划、数据处理等计算任务;STM32更适合做稳定的底层控制,例如电机速度、转向、PWM输出、串口通信等。
树莓派发送给STM32的运动指令可以抽象成下面这种结构:
{
"cmd": "move",
"linear_velocity": 0.25,
"angular_velocity": -0.12,
"target_mode": "follow_animal",
"stop_distance_m": 1.5
}
当深度相机判断动物距离过近,或者雷达检测到前方障碍物时,上层逻辑可以把速度降为0,STM32立即执行停车或转向。
5. 识别关键:YOLOv7不只是“分类”,而是给机器人一个可行动的目标

项目目标识别部分采用YOLOv7。YOLO系列属于典型的一阶段目标检测算法,它把“目标在哪里”和“目标是什么”放在一次网络推理中完成,因此速度快,适合实时系统。
对于移动机器人来说,实时性不是锦上添花,而是基本要求。动物会移动,机器人也在移动,如果识别速度太慢,检测框对应的位置就会滞后,后续追踪和导航都会被影响。
本地代码文件中保留了完整的YOLOv7工程,包括:
• detect.py:图像、视频、摄像头目标检测入口
• video.py:面向双路画面/深度视觉场景的检测显示逻辑
• yolov7.pt、traced_model.pt:模型权重文件
• data/coco.yaml:COCO类别配置,其中包含cat、dog等动物类别
• runs/detect/:多次检测实验输出的视频与图片结果
5.1 训练数据:从“图片”变成“检测样本”
项目方案中提到训练集来自Kaggle猫狗识别数据集:下载约2000张图片进行标注,并划分出训练集与验证集。标注工具使用labelImg,将动物位置转换为目标检测所需的边界框数据。
目标检测数据和普通分类数据的差别在于:它不仅需要知道“这张图里有猫”,还要知道“猫在图中的哪个位置”。一个典型的YOLO标注行可以这样理解:
class_id center_x center_y width height
0 0.512 0.438 0.260 0.330
其中坐标是归一化后的比例值,不是原始像素值。假设0代表cat,1代表dog,那么数据配置可以抽象为:
train: datasets/cat_dog/images/train
val: datasets/cat_dog/images/val
nc: 2
names:
- cat
- dog
本地工程中的data/coco.yaml仍保留COCO 80类配置,其中已经包含cat、dog。若要进一步面向校园流浪动物定制模型,可以把类别收敛到猫、狗及少量校园相关干扰类别,从而降低误检风险。
5.2 YOLOv7结构:Input、Backbone、Head分别做什么
YOLOv7可按三个部分理解:
| 结构 | 作用 | 在本项目中的意义 |
|---|---|---|
| Input | 输入图像并进行尺寸适配、归一化等处理 | 接收Astra Pro或摄像头画面 |
| Backbone | 提取多层视觉特征 | 捕捉猫狗的轮廓、纹理、姿态等特征 |
| Head | 输出类别、置信度和检测框 | 给出“这是猫/狗”和“它在画面中的位置” |
项目方案中特别强调了ELAN和MP结构。ELAN可以增强网络的特征表达能力,让模型在多层特征之间保持更丰富的梯度路径;MP结构则用于下采样与特征聚合。对于猫狗识别来说,这类结构的意义在于:同一只猫狗可能出现侧身、趴下、遮挡、逆光、远距离等不同状态,网络需要从局部纹理和整体轮廓中同时提取可用信息。
5.3 推理流程:从摄像头画面到检测框
本地detect.py的核心逻辑可以概括为“读图 → 预处理 → 模型推理 → 非极大值抑制 → 画框/保存结果”。理解性伪代码如下:
model = load_yolov7_weights("yolov7.pt")
for rgb_frame in camera_stream:
image = resize_and_normalize(rgb_frame, size=640)
raw_pred = model(image)
detections = non_max_suppression(
raw_pred,
conf_threshold=0.25,
iou_threshold=0.45
)
for box, score, class_id in detections:
if class_id in ["cat", "dog"]:
draw_box(rgb_frame, box, label=f"{class_id} {score:.2f}")
这里的non_max_suppression很关键。模型可能对同一只猫输出多个重叠检测框,NMS会保留置信度更高、位置更合理的框,避免系统把一只动物误认为多个目标。
实际运行时,可以用类似下面的方式对图片、视频或摄像头画面进行检测:
python detect.py --weights yolov7.pt --conf 0.25 --img-size 640 --source inference/images/horses.jpg
python detect.py --weights yolov7.pt --conf 0.25 --img-size 640 --source 0
5.4 检测框为什么还不够?深度相机的价值在这里
普通RGB摄像头只能告诉机器人:画面里哪里有猫狗。
深度相机进一步告诉机器人:猫狗离我多远、在空间中的大致位置在哪里。
这就是Astra Pro这类RGB-D相机的关键价值。RGB负责识别,Depth负责空间测量。把YOLOv7的检测框与深度图对齐后,可以在检测框中心点或目标区域内采样深度值,得到目标距离估计。这样机器人才能从“看见动物”升级到“知道动物在前方几米处”。
更稳妥的做法不是只取检测框中心一个像素,而是在检测框中间区域取一小块深度值,再用中位数过滤异常点:
def estimate_target_distance(depth_map, box):
x1, y1, x2, y2 = box
cx1 = int(x1 + 0.35 * (x2 - x1))
cx2 = int(x1 + 0.65 * (x2 - x1))
cy1 = int(y1 + 0.35 * (y2 - y1))
cy2 = int(y1 + 0.65 * (y2 - y1))
roi_depth = depth_map[cy1:cy2, cx1:cx2]
valid_depth = roi_depth[(roi_depth > 200) & (roi_depth < 6000)]
if len(valid_depth) == 0:
return None
return median(valid_depth) / 1000.0 # millimeters to meters
本地video.py中已经体现了这种设计方向:脚本同时处理两路画面,并预留了根据目标框中心点计算距离的逻辑。虽然距离计算调用在当前代码中处于注释状态,但整体流程已经指向“检测框 + 深度数据”的融合方案。
6. 追踪关键:MedianFlow让识别结果从“单帧”变成“连续轨迹”
单帧识别只能回答“这一帧里有没有猫狗”。但机器人管理流浪动物时,更重要的是连续观察:它往哪里走?是否靠近危险区域?是否已经被记录过?
MedianFlow是一种经典的目标追踪算法,它通过前向和后向光流一致性判断跟踪点是否可靠。简单说,它会检查一个点从上一帧跟到下一帧后,再反向跟回上一帧是否还能回到原位置;如果偏差很大,说明这个点不可靠,需要剔除。
它和YOLOv7的配合关系可以这样理解:
YOLOv7:负责发现目标,并给出初始检测框
MedianFlow:负责在短时间连续帧里跟住这个框
YOLOv7:隔几帧重新校准,避免追踪漂移
理解性伪代码如下:
tracker = None
frame_count = 0
for frame in camera_stream:
frame_count += 1
if tracker is None or frame_count % 10 == 0:
detections = yolov7_detect(frame)
target = select_best_cat_or_dog(detections)
if target:
tracker = init_medianflow_tracker(frame, target.box)
animal_state = "detected"
else:
ok, box = tracker.update(frame)
animal_state = "tracking" if ok else "lost"
if animal_state in ["detected", "tracking"]:
update_target_trajectory(box)
这种方法适合短时间、局部连续的目标跟踪。对本项目而言,YOLOv7负责定期“重新确认目标”,MedianFlow负责在相邻帧之间保持目标连续性。这样可以减少每一帧都完全依赖检测器的压力,也能提高运动过程中的目标稳定性。
7. 从巡逻到建档:完整工作流程
一个典型任务可以拆成六步:

如果用程序流程表达,这个闭环可以写成:
while patrol_task_active:
rgb, depth = astra_pro.read()
lidar_scan = lidar.read()
pose, map_grid = fastslam.update(lidar_scan)
detections = yolov7.detect(rgb)
for det in detections:
if det.label not in ["cat", "dog"]:
continue
distance = estimate_target_distance(depth, det.box)
target_point = project_to_robot_frame(det.box, distance)
if distance is not None and distance > 1.5:
global_path = astar.plan(map_grid, pose, target_point)
cmd = dwa.control(pose, global_path, lidar_scan)
stm32.send(cmd)
else:
stm32.send({"linear_velocity": 0.0, "angular_velocity": 0.0})
save_or_update_animal_archive(det, pose, distance)
其中,1.5米可以理解为安全观察距离。实际项目中,这个距离需要根据相机视场、小车刹停距离、动物应激反应和校园人流情况调整。
7.1 动物档案应该记录什么?
档案不是简单存一张照片,而是将“某次发现”变成可持续管理的数据。一个动物档案可以设计成下面这种结构:
{
"animal_id": "CAT-HDU-0007",
"species": "cat",
"first_seen": "2026-06-26 09:35:12",
"last_seen": "2026-06-26 10:18:40",
"appearance": {
"color": "orange-white",
"body_size": "medium",
"features": ["white paws", "left ear notch"]
},
"health_record": {
"vaccinated": false,
"sterilized": "unknown",
"visible_injury": false
},
"trajectory": [
{"location": "canteen east lawn", "distance_m": 2.4},
{"location": "dormitory walkway", "distance_m": 3.1}
],
"image_refs": [
"archive/CAT-HDU-0007/20260626_093512.jpg"
]
}
这类结构能支持后续的管理动作:确认是否为已记录个体、统计出现频率、标记健康状态、安排投喂或救助。
7.2 系统状态机:机器人什么时候巡逻,什么时候停下?
为了避免逻辑混乱,移动机器人通常会用状态机管理任务:
PATROL
↓ 检测到猫狗
APPROACH
↓ 到达安全观察距离
OBSERVE
↓ 完成拍摄与识别
ARCHIVE
↓ 档案更新完成
TRACK_OR_RETURN
↓ 目标离开 / 巡逻任务继续
PATROL
对应到代码层,可以理解为:
if state == "PATROL" and animal_detected:
state = "APPROACH"
elif state == "APPROACH" and distance <= safe_distance:
state = "OBSERVE"
elif state == "OBSERVE" and image_quality_ok:
state = "ARCHIVE"
elif state == "ARCHIVE" and archive_saved:
state = "TRACK_OR_RETURN"
8. 应用场景:它能在校园里做什么?

8.1 定点巡逻:把“偶然看见”变成“持续巡查”
机器人可以在流浪动物常出现的区域巡逻,例如宿舍楼下、食堂后门、草坪、教学楼连廊附近。当检测到猫狗时,小车停下并进行识别,记录时间和位置。
8.2 自主投喂:把投喂变得可控
项目方案中提到机器人可移动到指定地点对小动物进行投喂。相比随机投喂,机器人投喂更适合与管理策略结合,例如固定地点、固定时间、固定数量,减少动物无序聚集。
8.3 档案建立:给每只动物一个可追踪编号
系统可以为小动物建立数据库档案,记录类别、照片、活动地点、出现频率、疫苗接种与健康状态。这个能力是项目最具管理意义的部分,因为它把“校园里有很多猫狗”变成了“有哪些个体、它们在哪里、状态如何”。
8.4 外来动物识别:发现变化,而不仅是发现动物
当机器人再次巡逻时,可以识别已经存在于数据库内的动物,并对新出现的外来动物进行区分。这对于疾病防控、数量评估和救助管理都很关键。
9. 测试方案:看得准,也要走得稳
项目测试分为导航测试和识别测试。
导航测试关注机器人能否在室外草地、室内食堂、教学楼等场景中到达动物附近。测试时,小车开启导航节点,根据目标位置移动并避开障碍物,以此验证导航精度和运动稳定性。
识别测试关注模型能否准确判断动物身份。测试方式是将现有动物个体数据作为输入,与测试集结果进行对比。当小车移动到动物附近后,系统处理深度相机数据,完成动物类别或身份判断,并评估识别功能是否可靠。
这两个测试必须组合起来看:如果只识别准确但无法靠近,系统不能形成管理闭环;如果能移动但识别不稳定,也无法建立可信档案。移动机器人项目的难点就在于“感知、决策、控制”必须同时成立。
10. 项目创新点与技术优势
▍创新点一:把3D相机用于校园流浪动物管理
传统摄像头只能提供二维画面,Astra Pro提供RGB-D数据,让系统同时获得外观特征和距离信息。这让机器人可以做目标识别、避障、追踪和空间定位,而不是只做静态拍摄。
▍创新点二:YOLOv7提升实时识别能力
项目在参考R-CNN、VGG16、YOLO等典型识别算法后,选择YOLOv7作为猫狗识别核心。相比两阶段检测方法,YOLOv7更适合边缘侧实时推理;相比普通分类网络,它能同时输出目标位置,更适合机器人导航和追踪。
▍创新点三:导航、识别、追踪形成闭环
FastSLAM、A*、DWA解决“到哪里去、怎么过去”的问题;YOLOv7解决“目标是谁、在哪里”的问题;MedianFlow解决“目标移动后如何持续观察”的问题。多个模块配合,使系统从单点识别扩展为完整的移动管理方案。
▍创新点四:考虑RGB-D噪声处理
项目方案中提到,RGB-D相机采集图像时可能存在较多噪声,因此采用Orbbec SDK相关滤波算法对原始图像进行处理。深度图噪声会直接影响距离估计,如果不处理,检测框中心点的深度值可能跳变,导致机器人误判距离。因此滤波不是简单的画面优化,而是影响导航与追踪可靠性的关键步骤。
11. 项目可继续深化的方向
这个项目已经完成了“移动机器人 + 3D视觉 + 猫狗识别 + 导航追踪”的基础框架。若继续迭代,可以重点增强以下能力:
• 个体重识别:在猫狗类别识别之外,进一步识别“是哪一只猫/狗”。
• 档案系统:增加后台管理界面,支持照片、位置轨迹、健康状态、疫苗记录。
• 边缘部署优化:将YOLOv7模型导出为ONNX或TensorRT,提高树莓派或边缘设备推理效率。
• 投喂策略:结合出现频率和健康状态,制定更精细的定点投喂计划。
• 校园管理联动:与保卫处、后勤、动物保护社团或校医院形成数据共享机制。
12. 结语:真正有价值的不是“识别猫狗”,而是让管理变得温和、连续、可执行
“利用深度相机实现对校园流浪动物的管理”这个项目的亮点,不只是把YOLOv7放在小车上跑起来,而是把3D视觉、机器人导航、目标追踪和动物档案管理放进同一个应用场景里。
它解决的是一个很真实的问题:校园流浪动物既需要被关注,也需要被有序管理。通过Astra Pro深度相机、树莓派4B、STM32和四轮移动底盘的组合,系统把流浪动物从“看见一次”变成“持续记录”,从“人工经验管理”推进到“数据辅助管理”。
如果说普通摄像头是校园里的眼睛,那么这套3D视觉机器人系统更像是一名会移动、会记录、会判断距离的巡查员。它让技术不只停留在演示,而是走向一个更具体、更温和、也更可落地的校园治理场景。