手把手教你用YOLO-v8.3:快速实现无人机自动避障(附完整代码)

1. 为什么选择YOLO-v8.3做无人机避障?

想象一下,你的无人机正在空中飞行,前方突然出现一棵树或者一个行人。传统避障方案,比如超声波传感器,探测距离有限,而且容易受环境影响。激光雷达效果好,但价格贵、重量大,装在小型无人机上不现实。

这时候,基于摄像头的视觉方案就成了最佳选择。它成本低、重量轻,而且能“看懂”周围环境。在众多视觉算法里,YOLO(You Only Look Once)系列模型脱颖而出,因为它够快、够准。

YOLO-v8.3是Ultralytics公司维护的最新稳定版本之一。它最大的特点就是“快”和“小”。一个最小的YOLOv8n模型,只有几兆大小,在像树莓派、Jetson Nano这样的嵌入式设备上,也能跑出几十帧每秒的速度,完全能满足无人机实时避障的需求。

简单来说,用YOLO-v8.3做避障,就是用无人机的“眼睛”(摄像头)拍下前方画面,让模型快速识别出画面里的障碍物(比如人、车、树),然后告诉飞控系统:“前面有东西,快绕开!”

本文将带你从零开始,一步步搭建一个基于YOLO-v8.3的无人机避障视觉系统。我们会使用CSDN星图平台提供的“YOLO-V8”预置镜像,省去繁琐的环境配置,直接上手写代码、看效果。

2. 准备工作:快速搭建开发环境

自己从零搭建深度学习环境,光是安装各种依赖和配置CUDA就能劝退很多人。好在CSDN星图提供了开箱即用的“YOLO-V8”镜像,里面什么都装好了。

2.1 镜像里有什么?

这个镜像可以理解为一个已经配置好的“软件包”,你一键启动,就获得了一个完整的开发环境:

  • 操作系统:Ubuntu 20.04,稳定且兼容性好。
  • 深度学习框架:PyTorch 1.13 + CUDA 11.7,GPU加速必备。
  • 核心工具包
    • ultralytics==8.3.0:这是YOLO-v8的官方Python库,我们写代码全靠它。
    • opencv-python:处理图像和视频的核心工具。
    • numpy, matplotlib:科学计算和画图常用。
  • 开发工具:预装了JupyterLab和SSH服务,方便你用不同方式写代码。
  • 工作目录:镜像启动后,默认就在项目目录 /root/ultralytics 下,里面已经有了一些示例。

2.2 两种方式开始编程

镜像提供了两种交互方式,你可以选自己喜欢的。

方式一:用JupyterLab(推荐给新手)

这种方式就像在用网页版的Python笔记本,可以边写代码边看结果,特别适合调试和可视化。

  1. 启动镜像后,在浏览器里打开JupyterLab的地址(通常是 http://你的服务器IP:8888)。
  2. 新建一个Python笔记本(Notebook)。
  3. 直接在里面写代码、运行,图像结果可以直接显示在网页上。

方式二:用SSH终端(适合自动化部署)

如果你习惯用命令行,或者想写一个脚本让无人机一直跑,可以用SSH。

  1. 用SSH工具(比如Xshell、MobaXterm或者系统自带的终端)连接到你的服务器。
  2. 登录后,输入 cd /root/ultralytics 进入工作目录。
  3. 然后用 python your_script.py 这样的命令来运行你的Python脚本。

3. 核心代码实战:让无人机“看见”障碍物

理论说再多,不如一行代码。下面我们就来写一个最核心的避障检测模块。这个模块的任务就是:读取摄像头画面,用YOLO-v8.3找出里面的障碍物,并判断是否需要避障。

3.1 第一步:加载模型与初始化

首先,我们创建一个Python脚本,比如叫 drone_obstacle_detection.py

# drone_obstacle_detection.py
from ultralytics import YOLO
import cv2
import torch

# 1. 自动选择运行设备(有GPU就用GPU,没有就用CPU)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"使用设备: {device}")

# 2. 加载预训练的YOLOv8模型
# 这里我们使用最小的'nano'版本(yolov8n.pt),速度最快,适合无人机。
# 模型会自动从网上下载(如果本地没有的话)。
model = YOLO("yolov8n.pt").to(device)

# 3. 定义我们需要避开的障碍物类别
# YOLO默认能识别80类COCO数据集物体,我们只关心其中几类。
OBSTACLE_CLASSES = ['person', 'bicycle', 'car', 'motorcycle', 'bus', 'truck', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe']
# 注意:这个列表可以根据你的实际飞行环境增减。比如在公园飞,就要加上‘tree’。

def is_obstacle(class_name):
    """判断检测到的物体是否属于需要避开的障碍物"""
    return class_name in OBSTACLE_CLASSES

代码解释

  • YOLO("yolov8n.pt"):这行代码创建了一个YOLO模型对象。yolov8n.pt 是预训练好的权重文件,n代表nano(最小),还有 s(small), m(medium), l(large), x(xlarge) 等更大更准但更慢的版本。
  • .to(device):把模型放到GPU或CPU上运行。
  • OBSTACLE_CLASSES:这是我们自己定义的列表。YOLO能认很多物体,但无人机不需要避开所有东西(比如天空、云朵)。这里我们只把可能撞上的、有危险的物体算作障碍物。

3.2 第二步:编写核心检测与告警函数

接下来,我们写一个函数,它接收一帧图像,返回标注好的图像和是否有障碍物的判断。

def detect_and_alert(frame):
    """
    对输入的一帧图像进行障碍物检测和告警判断。
    参数:
        frame: 摄像头捕捉到的一帧图像(numpy数组)
    返回:
        annotated_frame: 画上了检测框和标签的图像
        need_avoidance: 布尔值,True表示需要执行避障动作
    """
    # 使用模型进行推理
    # conf=0.5: 只相信置信度高于50%的检测结果,减少误报。
    # imgsz=640: 将图像缩放至640x640大小输入模型,这是速度和精度的平衡点。
    results = model(frame, conf=0.5, imgsz=640)

    # 获取第一个(也是唯一一个)结果的检测框信息
    detections = results[0].boxes
    need_avoidance = False
    # 使用ultralytics内置方法,快速画出带标签的检测结果图
    annotated_frame = results[0].plot()

    # 如果没有检测到任何东西,直接返回
    if detections is None:
        return annotated_frame, need_avoidance

    # 遍历所有检测到的物体
    for box in detections:
        # 获取物体类别ID和名称
        cls_id = int(box.cls.cpu().numpy())
        cls_name = model.names[cls_id]

        # 判断它是不是我们需要避开的障碍物
        if is_obstacle(cls_name):
            confidence = float(box.conf.cpu().numpy())  # 检测置信度
            # 获取物体边界框的坐标 (x1, y1, x2, y2)
            x1, y1, x2, y2 = box.xyxy[0].cpu().numpy()

            # 关键判断:障碍物是否在飞行路径的“危险区域”?
            # 我们假设无人机摄像头朝前,画面中心是飞行方向。
            frame_center_x = frame.shape[1] / 2  # 图像宽度的一半
            obstacle_center_x = (x1 + x2) / 2

            # 定义“危险区域”:画面中心左右各30%的宽度范围
            danger_zone_width = frame.shape[1] * 0.3
            if abs(obstacle_center_x - frame_center_x) < danger_zone_width:
                # 障碍物在危险区域内,触发避障告警
                need_avoidance = True
                print(f"[警告] 检测到障碍物: {cls_name}, 置信度: {confidence:.2f}, 位置: X中心={obstacle_center_x:.0f}")
                # 在实际系统中,这里可以加上更复杂的逻辑,比如根据物体大小和距离判断紧急程度。

    return annotated_frame, need_avoidance

代码解释

  • model(frame, conf=0.5, imgsz=640):这是执行推理的核心。传入图像、置信度阈值和输入尺寸。
  • results[0].plot():一个非常方便的函数,它自动把检测框、类别标签和置信度画在图像上,省去我们手动用OpenCV画图的麻烦。
  • 危险区域判断:这是避障逻辑的关键。我们只关心出现在画面正前方的障碍物。侧方的物体,即使检测到了,也暂时不处理,因为无人机可能只是从旁边飞过。这个 30% 的阈值可以根据无人机视野和飞行速度调整。

3.3 第三步:连接视频源并运行主循环

最后,我们需要一个循环,不断地从摄像头获取画面,调用上面的函数,并显示结果。

# 主程序开始
if __name__ == "__main__":
    # 设置视频源
    # 方案1: 使用测试视频文件
    # video_source = "test_flight.mp4"
    # 方案2: 使用USB摄像头(通常为0)
    # video_source = 0
    # 方案3: 使用无人机的RTSP视频流(需要替换为你的无人机IP)
    video_source = "rtsp://192.168.1.100:554/stream"  # 示例地址,请替换

    cap = cv2.VideoCapture(video_source)

    if not cap.isOpened():
        print("错误:无法打开视频源!")
        exit()

    print("开始检测,按 'q' 键退出...")

    while cap.isOpened():
        # 读取一帧
        ret, frame = cap.read()
        if not ret:
            print("视频流结束或读取失败。")
            break

        # 执行障碍物检测
        result_frame, need_avoid = detect_and_alert(frame)

        # 如果需要避障,这里可以触发飞控指令
        if need_avoid:
            # 这里是和飞控通信的接口,需要根据你的飞控协议(如MAVLink)实现
            # send_avoidance_command("HOVER_OR_TURN") # 伪代码
            # 为了演示,我们在画面上显示一个红色的警告文字
            cv2.putText(result_frame, "OBSTACLE AHEAD! AVOIDING...", (50, 50),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

        # 显示结果
        cv2.imshow('Drone Obstacle Detection', result_frame)

        # 按'q'键退出循环
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    # 释放资源
    cap.release()
    cv2.destroyAllWindows()
    print("程序结束。")

运行与测试

  1. 将上面的三段代码整合到一个 .py 文件中。
  2. 在JupyterLab里新建一个单元格粘贴全部代码运行,或者通过SSH在终端执行 python drone_obstacle_detection.py
  3. 首次运行时会自动下载 yolov8n.pt 模型文件。
  4. 确保 video_source 变量设置正确。你可以先用一个本地视频文件(如 test_flight.mp4)或USB摄像头(0)测试。
  5. 如果一切正常,你会看到一个窗口,实时显示摄像头画面,并用框标出检测到的障碍物。当障碍物出现在画面中心区域时,控制台会打印警告,画面上也可能出现提示文字。

4. 从演示到真机:关键优化与注意事项

上面的代码是一个完整的演示原型。但要真正用到无人机上,还需要考虑更多工程问题。

4.1 性能优化:让检测更快

无人机的算力有限,我们必须榨干每一分性能。

  • 模型量化:把模型从浮点数(FP32)转换成整数(INT8)格式,速度能提升2-3倍,精度损失很小。YOLO-v8.3支持导出为TensorRT引擎,这是NVIDIA设备上最快的运行方式。
    # 在代码中导出为TensorRT引擎(需要提前安装TensorRT)
    model.export(format='engine', half=True) # half=True使用FP16精度,更快
    # 然后加载导出的 .engine 文件进行推理
    model = YOLO('yolov8n.engine')
    
  • 降低输入分辨率:代码里我们用的 imgsz=640。如果飞行环境简单,障碍物较大,可以尝试降到 320,速度会快很多,但小物体可能就看不到了。
  • 跳帧处理:如果帧率要求不是极高,可以每2帧或3帧处理一帧,用中间帧的检测结果来插值,能显著降低计算负载。

4.2 提升检测效果:让小物体和特殊环境更清晰

  • 针对训练:用无人机在自己典型飞行环境(如园区、农田)拍摄的数据,对YOLO-v8.3进行微调(Fine-tuning),让它更熟悉你要避开的物体(比如特定的树木、电线)。
  • 应对小物体:高空飞行时,远处的障碍物在图像上可能只有几十个像素。可以尝试使用更大的输入分辨率(如 imgsz=1280),或者选用YOLO-v8中带有“P2”或“P3”层的模型变体,它们对小目标更敏感。
  • 应对光线天气:模型在夜间、雾天可能失效。可以考虑加装红外摄像头,或者训练时多加入不同天气、时段的数据。

4.3 系统集成:与飞控通信

代码中的 send_avoidance_command 是伪代码。真实集成需要:

  1. 选择通信协议:最常用的是MAVLink协议,它是无人机领域的通用语言。
  2. 定义指令:根据检测结果,生成具体的飞控指令。例如:
    • need_avoidance == True:发送 MAV_CMD_NAV_GUIDED_ENABLE 指令,让飞控进入“引导模式”,并给出一个偏航或爬升的设定点。
    • 更高级的,可以根据障碍物的位置和大小,计算出一个安全的绕行路径点。
  3. 注意延迟:从检测到发出指令,整个流程的延迟要尽可能低(最好<100ms)。使用高效的通信库(如 pymavlink)和优化代码逻辑至关重要。

5. 总结

通过本文,你已经掌握了使用YOLO-v8.3为无人机搭建视觉避障系统的核心流程:

  1. 环境准备:利用CSDN星图“YOLO-V8”镜像,秒搭开发环境。
  2. 核心开发:用不到100行Python代码,实现了视频流的实时障碍物检测与告警。
  3. 逻辑设计:学会了如何定义“障碍物”并判断其是否位于飞行路径的“危险区域”。
  4. 优化方向:了解了模型量化、分辨率调整等提升性能的方法,以及真机集成需要考虑的通信和延迟问题。

YOLO-v8.3的强大之处在于它平衡了速度、精度和易用性,让复杂的视觉感知任务变得触手可及。你可以基于本文的代码框架,进一步探索:

  • 结合光流或双目视觉估算障碍物距离。
  • 集成更高级的路径规划算法(如A*、D*)。
  • 部署到真实的Jetson Nano或Orin NX等嵌入式AI设备上。

希望这篇手把手教程能成为你探索无人机智能视觉的起点。动手跑通代码,看着屏幕里的框随着障碍物移动,你会感受到AI赋予机器的“视觉”魅力。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐