
手头有一台 Mavic 3T,我想做一件很直接的事:把无人机摄像头的画面送到电脑上,再交给 YOLO系列,比如YOLO11(YOLOv8或YOLO26都一样)做目标检测。
一开始想到的是 HDMI。遥控器有接口,笔记本也有接口,用线接起来,能不能直接把画面当成模型的输入?查过之后才发现,最先要解决的并不是 detect.py 怎么写,而是电脑到底从哪里接收视频。
沿着这个问题往下梳理,会遇到三个环节:遥控器怎样输出画面,电脑怎样收到画面,以及模型怎样持续处理画面。本文以 Mavic 3T、DJI RC Pro 行业版、DJI Pilot 2 和 Windows 电脑为例,重点整理没有采集卡时的 RTMP 接入方法,同时保留 HDMI 采集卡作为另一条路线。
一、HDMI 接上了,为什么电脑不一定有画面?
HDMI 接口有方向。笔记本自带的 HDMI 通常是输出口,用途是把电脑画面送到显示器;遥控器的 HDMI 也是往外输出。把两个输出口接在一起,不会让系统多出一个摄像头。只有设备明确提供 HDMI 输入能力时,才另当别论。
DJI RC Pro 行业版配有 Mini-HDMI 接口,线材应按实际接口选用,不要和 Micro-HDMI 混淆。DJI 官方规格
要通过这条线把视频送进电脑,需要一个中间设备:HDMI 采集卡。
遥控器 Mini-HDMI 输出 ↓ HDMI 线采集卡 HDMI IN ↓ USB电脑识别为视频采集设备 ↓YOLO11 读取设备画面这里的 HDMI IN 就是采集卡上负责接收画面的接口。对支持 UVC 的采集卡来说,接入电脑后的使用方式接近普通 USB 摄像头。
但我目前首先考虑的是:没有采集卡,能不能先利用现有网络把视频送过来? 这就引出了 RTMP。
二、先选一条接入路线
| 方案 | 画面怎样进入电脑 | 前提 | 主要取舍 |
|---|---|---|---|
| HDMI 采集卡 | HDMI 转 USB 视频设备 | 有采集卡和匹配的线材 | 减少网络因素,但仍有采集、缓冲与推理开销 |
| RTMP | 遥控器推流,电脑服务接收 | 遥控器能访问电脑的流媒体服务 | 不必增加采集卡,需处理网络与视频缓冲 |
| 截屏或虚拟摄像头 | 读取电脑上已有的图传窗口 | 已经有可用的投屏或播放画面 | 容易混入界面元素,还会增加处理环节 |
截屏不是独立的图传接入方法:如果电脑上还看不到无人机画面,运行截屏命令也不会凭空获得视频。
下面先写 RTMP。目标是依次确认三个结果:服务器收到流、播放器看到画面、YOLO 显示检测结果。
三、RTMP:让遥控器把画面推到电脑
RTMP 的全称是 Real-Time Messaging Protocol。放在这个项目里,不必先研究协议报文,只需要分清三个角色:
- 推流端:遥控器,将视频发送到指定地址。
- 流媒体服务:运行在电脑上,接收视频并提供给客户端读取。
- 拉流端:播放器或 YOLO 程序,从服务中读取视频。
Mavic 3T → 遥控器图传 → Pilot 2 推流 ↓ 局域网 电脑上的 RTMP 服务 ↓ 解码 → YOLO11 → 显示DJI 的 Mavic 3 行业系列手册包含 RTMP、RTSP 直播服务的说明。实际入口、可选画质和视频源以所用 Pilot 2 与固件版本为准。DJI 用户手册
1. 先把电脑和遥控器放到能互通的网络里
最容易排查的方式,是让两者连接同一个普通路由器。没有路由器时,也可以尝试手机热点,或在电脑支持的情况下开启 Windows 移动热点。
这里不依赖遥控器自己开热点:让遥控器作为 Wi-Fi 客户端接入网络即可。手机热点和访客 Wi-Fi 可能隔离客户端,Windows 移动热点也受网卡、驱动与系统设置影响,因此“都连上了 Wi-Fi”还不等于彼此能访问。
在电脑的 PowerShell 中运行:
ipconfig找到与遥控器处在同一网络的网卡,记录它的 IPv4 地址。假设是 192.168.1.20,后续遥控器就往这个地址推流。不要误用 VPN、Docker 或其他虚拟网卡的地址。
2. 在电脑启动一个明确可用的收流服务
本文采用 SRS 的 Docker 方式。需要先安装并启动 Docker Desktop,使用 Linux 容器;下面的命令在 Windows PowerShell 中执行。
docker run --rm -it --name mavic-rtmp -p 1935:1935 ossrs/srs:5这条命令只映射本例所需的 RTMP 端口 1935。保持这个终端运行;按 Ctrl+C 停止后,临时容器会被删除。SRS 官方入门文档给出了这一镜像系列的启动方式和 RTMP 推拉流示例。SRS Docker 入门
另开一个终端可以查看运行状态和日志:
docker ps --filter name=mavic-rtmpdocker logs --tail 50 mavic-rtmp如果 docker 命令不可用或提示无法连接 Docker 服务,应先解决 Docker 环境问题。若提示容器名称或端口已占用,检查已有服务,不要同时启动两套占用 1935 的程序。
在 Windows 防火墙中,为这次实验所用的可信网络配置入站 TCP 1935 规则,限定到本地子网。不要用关闭整个防火墙代替端口配置。这个最小服务没有配置推拉流鉴权,应只用于受控局域网,不直接映射到公网。
3. 分清遥控器地址与电脑本机地址
本例约定使用应用名 live 和流名 yolo:
| 使用位置 | 地址 |
|---|---|
| 遥控器推流 | rtmp://192.168.1.20:1935/live/yolo |
| 同一台电脑上的播放器或 YOLO | rtmp://127.0.0.1:1935/live/yolo |
两条地址访问的是同一个服务。192.168.1.20 是示例值,需要替换为实际电脑 IP;127.0.0.1 则表示“当前这台设备自己”。
4. 在 Pilot 2 中开始直播
确认遥控器已经显示飞机图传,再找到直播设置,选择自定义 RTMP,填写上面的推流地址。不同版本的菜单位置可能变化,按实际界面操作。
若界面使用一个地址输入框,就填完整 URL;若拆成服务器和流密钥,则对应为:
| 字段 | 示例 |
|---|---|
| 服务器 | rtmp://192.168.1.20:1935/live |
| 流密钥 | yolo |
开始推流后,查看电脑上的 SRS 日志,确认有发布连接。这里的流名只是本例的路径标识,不代表服务已经启用身份验证。
5. 先用播放器验收,不急着启动模型
在电脑上用 VLC 的“打开网络串流”功能,输入:
rtmp://127.0.0.1:1935/live/yolo能持续播放之后,再进入下一步。同时看清楚收到的是什么画面:可见光、红外、分屏,还是带有叠加信息的视频。不要仅凭遥控器当前界面推断输出内容。
如果 VLC 也没有画面,先检查推流状态、电脑 IP、防火墙和流路径,此时还没有必要调整 YOLO 参数。
四、先用一条命令接入 YOLO11
在单独的工作目录建立 Python 环境。下面直接调用虚拟环境中的程序,省去 PowerShell 激活脚本的步骤:
python -m venv .venv.\.venv\Scripts\python.exe -m pip install --upgrade pip.\.venv\Scripts\python.exe -m pip install ultralytics opencv-python确认播放器能收到流后运行:
.\.venv\Scripts\yolo.exe predict model=yolo11n.pt source="rtmp://127.0.0.1:1935/live/yolo" imgsz=640 conf=0.3 show=True save=False stream_buffer=False这里先用较小的 yolo11n.pt 验证输入链路。Ultralytics 提供 YOLO11 的 CLI 和 Python 调用方式;本地没有权重时,首次加载可能需要联网下载。YOLO11 官方文档
show=True 需要有桌面显示环境,save=False 则避免初次调试同时写入检测视频。有 NVIDIA 显卡时,能否使用 GPU 还取决于驱动和 PyTorch 安装,可先查看:
.\.venv\Scripts\python.exe -c "import torch; print(torch.cuda.is_available())"返回 True 后可以尝试在推理命令后加上 device=0;使用 CPU 则指定 device=cpu。具体速度留到设备接通后测量。
五、需要处理检测结果时,再写 Python 脚本
以前接触 YOLOv5 时,经常会从仓库里的 detect.py 开始。本文使用的是 Ultralytics 的 YOLO11 API,下面是自行编写的入口脚本,保存为 mavic_yolo.py 即可;把它命名成 detect.py 也可以,但它不是官方仓库中的同名文件。
脚本支持采集设备编号、RTMP 地址和本地视频文件。先复用 Ultralytics 的取流逻辑,只有需要特别指定采集后端、裁切输入或管理重连时,再单独封装 OpenCV 读取过程。
import argparse
from ultralytics import YOLO
def main(): parser = argparse.ArgumentParser(description="Mavic 3T video + YOLO11") parser.add_argument("--source", required=True) parser.add_argument("--model", default="yolo11n.pt") parser.add_argument("--conf", type=float, default=0.3) parser.add_argument("--imgsz", type=int, default=640) parser.add_argument("--device", default=None) parser.add_argument("--classes", type=int, nargs="+", default=None) args = parser.parse_args()
source = int(args.source) if args.source.isdecimal() else args.source model = YOLO(args.model) results = model.predict( source=source, stream=True, stream_buffer=False, imgsz=args.imgsz, conf=args.conf, device=args.device, classes=args.classes, show=True, save=False, verbose=False, )
try: for index, result in enumerate(results, start=1): # 在这里读取 result.boxes,按需要处理坐标、类别和置信度。 if index % 30 == 0: count = 0 if result.boxes is None else len(result.boxes) print(f"Processed frames: {index}, detections: {count}") except KeyboardInterrupt: print("Stopped.") finally: results.close()
if __name__ == "__main__": main()接入 RTMP:
.\.venv\Scripts\python.exe mavic_yolo.py --source "rtmp://127.0.0.1:1935/live/yolo"如果暂时还没接通无人机,可以先用一段本地视频确认 Python 环境和模型能够运行:
.\.venv\Scripts\python.exe mavic_yolo.py --source "test.mp4"结束时在终端按 Ctrl+C。这是一份用于验证链路的入口脚本,断流恢复仍需后续单独实现;出错时先根据终端信息恢复视频源,再重新启动。
这里有两个容易混淆的参数:
stream=True:返回结果生成器,需要通过for迭代触发并持续消费结果,避免把长视频的结果全部保存在列表中。stream_buffer=False:允许取流器丢弃旧帧,优先处理较新的画面。它不能清除遥控器、服务端或解码器里已经存在的延迟。
这两个参数分别处理结果返回方式和视频帧排队策略,不能互相替代。Ultralytics 推理文档
六、有了采集卡以后,怎样接入同一套程序?
接好“遥控器 → 采集卡 → USB → 电脑”后,先用系统相机应用或 OBS 预览,确认采集卡确实有画面,再关闭占用设备的预览程序。
Pilot 2 的 HDMI 输出设置可从相机界面右上角菜单进入 HD/图传设置,查看视频输出类型。根据当前版本选择适合检测的画面输出,并确认电脑收到的图像是否包含菜单或 OSD。DJI HDMI 输出设置说明
然后把输入改成对应设备号:
.\.venv\Scripts\python.exe mavic_yolo.py --source 00 只是设备索引,不一定是采集卡,也可能是笔记本内置摄像头。需要根据实际情况尝试 1、2 等编号,编号也可能随设备插拔变化。
画面异常时,检查采集卡声明支持的采集规格,而不是只看包装上的 HDMI 输入或环出规格。例如“支持 4K 输入”并不等于电脑能以 4K 帧率采集。分辨率、帧率和像素格式应从双方共同支持的组合开始尝试。
七、能出框之后,还要看两件事
1. 检测速度与端到端延迟是两项指标
模型一秒能处理多少帧,只描述处理能力。画面从相机进入系统,到电脑显示检测框,中间还要经过图传、输出、传输、解码、排队和绘制。
即使模型推理很快,持续处理积压的旧帧,窗口仍然可能明显落后于现场。因此本文不直接套用“RTMP 固定延迟几秒”或“采集卡固定几十毫秒”的结论。
可以做一个简单的观察实验:让相机拍摄不断变化的计时器,再用另一台设备同时拍到计时器和电脑上的检测窗口,比较同一照片中两处时间读数。重复多次,并记录画质、网络、模型和运行设备。这种方式估计的是整条链路的显示延迟,精度受计时器刷新和拍摄过程影响。
若延迟随运行时间增长,优先检查是否持续积压旧帧;若画面本身就不流畅,先确认播放器里的表现,再区分取流问题和推理性能问题。
2. 接通热成像,不等于模型适应了热成像
收到哪一路视频,应以电脑实际解码的画面为准。切换镜头、直播视频源或分屏模式后,都应重新确认输入,不能默认 HDMI 与 RTMP 永远和遥控器屏幕完全一致。
即便同样检测人和车辆,航拍中的目标尺度、俯视角度,以及红外画面的外观都可能与预训练数据不同。有画面但检不出来,和根本没收到视频,是两类问题。
后续应使用实际场景样本检查漏检、误检和小目标表现,再决定是否需要调整输入尺寸或训练专用模型。普通视频流里的红外伪彩图也不能直接当作逐像素温度数据使用。
八、按链路顺序排查问题
| 现象 | 优先检查 |
|---|---|
| HDMI 直连笔记本没有输入 | 笔记本是否真的有 HDMI IN;否则需要采集设备 |
| RTMP 服务启动失败 | Docker 是否运行、容器名称是否重复、1935 是否被占用 |
| 遥控器推不上流 | 电脑 IP、服务状态、端口映射、防火墙和网络客户端隔离 |
| 有发布连接,播放器却没有图 | 推拉路径是否一致、发布是否仍在持续、视频编码是否能解码 |
| VLC 有画面,YOLO 打不开 | YOLO 实际使用的地址、Python 环境、OpenCV 后端和报错信息 |
| 采集卡能打开但黑屏或花屏 | 遥控器输出、线材、USB 连接、像素格式及分辨率组合 |
| 检测窗口越来越落后 | 排队策略、推理负载、解码与显示缓冲 |
| 画面正常,但漏检或误检严重 | 视频源、目标大小、画质、类别设置与模型适配情况 |
ping 可以辅助判断网络,但它失败不代表 TCP 1935 一定不通。若有另一台 Windows 设备位于同一网络,可以从那台设备测试:
Test-NetConnection 192.168.1.20 -Port 1935这一步能帮助确认从网络外部能否连接电脑服务,但仍不能代替真实推流测试。
OpenCV 相关问题也不要一律归结为“没有安装 FFmpeg”。可以先检查当前 Python 环境的构建信息:
.\.venv\Scripts\python.exe -c "import cv2; print(cv2.getBuildInformation())"查看 Video I/O 中的 FFmpeg 支持情况。单独安装一个 ffmpeg.exe,不会自动改变已安装 OpenCV 的编译能力;同样,设置 CAP_PROP_BUFFERSIZE 也不保证所有采集后端都会接受。具体能力取决于后端与设备。OpenCV 视频 I/O 文档
九、下一步:补上这套设备自己的实验记录
这次整理之后,我更明确了第一轮实验的顺序:先让播放器稳定收到视频,再接 YOLO,最后记录延迟和检测表现。需要补充的现场材料包括遥控器与 Pilot 2 版本、推流设置、电脑配置、实际视频规格,以及一张可见检测结果的截图。
跑通后也应记录软件版本,便于以后复现:
.\.venv\Scripts\python.exe -m pip freeze > requirements-tested.txtdocker image inspect ossrs/srs:5 --format '{{json .RepoDigests}}'如果以后需要更深入地处理相机数据或遥控器应用,再评估 DJI Mobile SDK;官方支持列表包含 Mavic 3 行业系列。DJI Mobile SDK
Payload SDK 则要进一步核对机型、SDK 版本与具体功能。支持某款飞机的载荷开发,不等于所有视频接口都能使用,也不能据此承诺取流延迟。DJI Payload SDK 版本说明
对眼下这个项目,我准备先从本地 RTMP 链路开始。等输入画面稳定了,再用同一段场景比较不同模型和接入方式,判断真正需要优化的是网络、解码、推理,还是模型本身。
分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
最后更新于 ,距今已过 30 天
部分内容可能已过时
评论