ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

香橙派5 RK3588部署YOLOv5s:RTSP取流计时与X11远程回显实战

香橙派5 RK3588部署YOLOv5s:RTSP取流计时与X11远程回显实战 1. 这集的目标取流循环计时 X11 回显画面写这一集的时候我已经默认你前面几集把香橙派5上的RK3588系统、YOLOv5s模型、NPU推理这些基础工作都整理过关了。上一集我们把RTSP取流跑通了画面能一帧一帧读进来也能经过模型推理输出框。但很多刚上车的朋友试完发现推理有没有用画面准不准光看终端打日志完全没感觉尤其当你想把香橙派上的实时检测结果给旁边的同事展示一下总不能让人围着一块开发板看串口输出吧。这一集解决两个实际问题一是给取流循环加计时二是用X11把画面弹回电脑。前者是工程化的地基后者是展示和调试的窗口。先说计时。很多教程跑YOLOv5s就是对着视频一顿 “摄像头打开、循环读取、推理、画框、显示”最后报一个fps数字但这个数字到底测的是什么是从开门到关门的全过程平均还是只有推理部分的耗时你是想调模型推理速度还是想调取流线程还是想评估端到端延迟这些事情不分开测量后面一旦出问题你根本不知道瓶颈卡在哪。所以这集我要讲的是怎么把时间戳埋进循环的每个关键节点把“总耗时”“抓帧耗时”“推理耗时”“显示耗时”拆开看。再说X11。香橙派接个HDMI显示器当然能看画面但很多时候开发板放在机柜里、支架上根本没接屏幕。你用电脑SSH上去跑程序如果想直接把OpenCV的imshow窗口“弹”到你电脑桌面上靠的就是X11转发。配置好了以后香橙派上的窗口会直接出现在你电脑屏幕上延迟低、操作简单比什么截图回传、串口打印坐标靠谱得多。这一集的内容适合三种人正在追这个系列、急着给项目交付做验证的人被取流和推理耗时搅在一起、分不清哪慢的人以及想脱离HDMI、纯远程调试YOLO部署环境的人。我不讲玄学只讲我这套香橙派5上实际跑过的流程和踩过的坑。2. 给取流循环加计时先分清时间都花在哪2.1 梳理取流循环里可以被计时的四个节点很多人在RK3588上写YOLOv5s推理循环代码大概长这样import cv2 from ultralytics import YOLO cap cv2.VideoCapture(rtsp://192.168.1.64:554/live) model YOLO(yolov5s.pt) while True: ret, frame cap.read() results model(frame) annotated results[0].plot() cv2.imshow(yolo, annotated) if cv2.waitKey(1) 0xFF ord(q): break这段代码能跑但你问它“瓶颈在哪”它回答不了你。因为它只有一个外层的循环次数除以总时间得到的结果是“整个循环平均每秒跑几帧”。这有一点用但没有定位能力。我在工程上习惯把取流循环拆成四个节点按时间顺序是抓帧、预处理、推理、后处理与显示。在RK3588这种异构平台上抓帧是ISP/解码器的事推理是NPU的事显示是GPU的事这几个硬件单元之间是并行接力关系。如果你只测总耗时你连瓶颈到底在硬件链路哪一环都看不出来。所以我一般会在代码里埋四个时间戳t0表示这一轮循环开始t1是cap.read()返回之后代表取帧完成t2是模型推理调用之前代表预处理完成t3是推理返回之后t4是画框和显示完成之后。这样每一轮循环我就有四个差值t1-t0是抓帧耗时t2-t1是预处理耗时t3-t2是推理耗时t4-t3是后处理与显示耗时t4-t0是整轮端到端耗时。把这些值累加起来算平均值比单纯算fps有信息量得多。2.2 时间戳埋点与FPS统计的代码实现下面这段代码是我在香橙派5上实跑过的版本用Python的time.perf_counter()来计时不用time.time()。为什么不用time.time()因为time.time()的精度和系统时钟调整都会影响结果perf_counter走的是单调时钟精度高且不受闰秒、NTP校准影响测短时间间隔更可靠。import time import cv2 from ultralytics import YOLO RTSP_URL rtsp://192.168.1.64:554/live cap cv2.VideoCapture(RTSP_URL, cv2.CAP_FFMPEG) model YOLO(yolov5s.pt) # 提前准备好计时器和统计容器 frame_count 0 time_capture 0.0 time_preprocess 0.0 time_infer 0.0 time_postprocess 0.0 time_total 0.0 while True: t0 time.perf_counter() ret, frame cap.read() if not ret: print(抓帧失败等待重连...) time.sleep(1) cap.open(RTSP_URL) continue t1 time.perf_counter() # 这里可以做letterbox缩放、归一化我简单起见直接用模型自带预处理 t2 time.perf_counter() results model(frame, verboseFalse) t3 time.perf_counter() annotated results[0].plot() cv2.imshow(yolo-rk3588, annotated) cv2.waitKey(1) t4 time.perf_counter() # 累加各类耗时 frame_count 1 time_capture t1 - t0 time_preprocess t2 - t1 time_infer t3 - t2 time_postprocess t4 - t3 time_total t4 - t0 if frame_count % 30 0: avg_capture time_capture / frame_count avg_preprocess time_preprocess / frame_count avg_infer time_infer / frame_count avg_postprocess time_postprocess / frame_count avg_total time_total / frame_count print(f帧数: {frame_count}, f取流: {avg_capture * 1000:.2f}ms, f预处理: {avg_preprocess * 1000:.2f}ms, f推理: {avg_infer * 1000:.2f}ms, f后处理显示: {avg_postprocess * 1000:.2f}ms, f总耗时: {avg_total * 1000:.2f}ms, f端到端FPS: {1.0 / avg_total:.2f}) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()实跑下来在香橙派5上如果模型是yolov5s、输入分辨率640x640、视频源是1080p RTSP大概能看到推理耗时在30ms上下取流耗时在10ms到20ms之间波动后处理加显示可能也要十几毫秒总耗时轻松到60ms左右也就是说端到端也就16FPS上下。这个数字单独看“推理能跑30ms”会觉得很快但端到端只有16FPS问题就出在后面的加计时统计上你会立刻意识到瓶颈不只是NPU。2.3 三处容易让计时失真的细节第一处是cap.read()阻塞问题。RTSP取流用的是FFmpeg后端网络抖动会导致read()阻塞比较久。如果你把这段阻塞时间算进抓帧耗时里它确实是端到端的一部分但没有必要抱怨RK3588慢因为这是网络链路问题。实测下来有线连接比Wi-Fi稳定得多Wi-Fi下取流耗时能冲到100ms以上有线基本稳定在20ms内。所以我建议做性能压测时一定用有线网络或者本地视频文件先把网络变量排除掉。第二处是cv2.waitKey()的显示耗时。很多人把这行代码不当回事但imshow加waitKey实际上会把图像数据从内存推到显示系统在X11转发场景下这个操作还会经过网络传输耗时能被拉到几十毫秒。我后面会专门讲X11配置你先记住如果你只想测推理性能可以把显示部分注释掉单独跑推理测npu时间如果测完整链路就必须把显示时间算进去。第三处是预热问题。模型刚加载完的前几帧RK3588的NPU驱动、内存分配、FFmpeg解码器都还没进入稳定状态前10帧测出来的时间往往偏大。我在脚本里特意用每30帧打印一次平均值而不是从头到尾只打印一个平均值就是为了观察稳定后的数据。常规做法是先跑30帧预热再把统计清零重新累积。3. X11转发配置把香橙派画面弹到电脑桌面上3.1 开启服务端X11转发香橙派这边跑的是Ubuntu 20.04OpenSSH服务一般是装好的。要支持X11转发需要确认/etc/ssh/sshd_config里有下面这几行X11Forwarding yes X11DisplayOffset 10 X11UseLocalhost yes改完之后执行sudo systemctl restart sshd。X11Forwarding必须打开否则客户端连上来时就算带-X参数也没用。X11DisplayOffset设成10意思是X显示的编号从10开始分配避免和本地图形界面冲突。X11UseLocalhost设置成yes表示转发通道只绑定在回环地址上更安全也能防止局域网内其他人直接连到你的X Server。检查一下香橙派上有没有安装x11-apps。很多精简的Ubuntu镜像没带你可以先跑一句sudo apt update sudo apt install -y x11-apps然后用xclock或xeyes做测试。注意测试必须从你的电脑终端SSH进香橙派再执行不是在香橙派本地终端执行。3.2 客户端配置VcXsrv与WindTerm的搭配电脑端这边我用的组合是WindTerm加VcXsrv。WindTerm作为SSH客户端配置项里有一项“X11转发”勾上就能把远程的X11请求转发到本地。VcXsrv则是一个跑在Windows上的X Server负责在电脑桌面上开一个X窗口环境接收并显示远程传过来的GUI内容。如果你是按照热词里常见的“windterm x11转发配置”搜到的资料操作路径大概是这样电脑装VcXsrv启动XLaunch选“Multiple windows”Display number设成0下一步默认完成。跑起来之后桌面右下角会多一个X图标。WindTerm里创建香橙派会话连接设置中勾选X11转发。连接后运行echo $DISPLAY正常会显示localhost:10.0说明X11通道已经建立。跑xeyes测试如果能弹出两个眼睛窗口说明整条通道是通的。如果你用的不是WindTerm而是Windows Terminal加原生OpenSSH就在连接命令里加-X参数ssh -X orangepi192.168.1.100Linux电脑上直接SSH加-X即可macOS也一样。整条链路理解了换什么客户端本质都一样本地X Server接收远程应用的窗口绘制请求SSH负责承载X11协议流量。这一步很多人踩的坑是顺序问题先启动SSH后启动VcXsrv或者VcXsrv的防火墙拦截了回环流量。Windows防火墙默认会弹窗问是否允许VcXsrv访问网络一定要勾选允许否则X11流量过不去表现就是SSH连接正常但任何图形程序都输出cannot open display。3.3 踩坑实录XTest.h编译错误与Wayland干扰热词里有“complie xdottool: x11/extensions/xtest.h:no such file or directory”这条我顺便说一下。这个错误我见过不止一次在Ubuntu 20.04上源码编译xdotool、或者某些需要模拟键鼠输入的自动化工具时经常会报找不到XTest.h。原因很简单系统里没有安装X11开发库的扩展部分。解决办法sudo apt install -y libxtst-dev libx11-dev装了libxtst-dev之后/usr/include/X11/extensions/XTest.h就会出现编译器也就不会再报这个错。这里不展开讲xdotool但这个报错和X11环境是一条线的顺手记一笔免得你用到的时候卡住。另外一个坑是Wayland和X11的冲突。热词里有一句“虚拟机怎么从wayland切换至x11”这说明很多人已经碰到过这个问题。如果你电脑上跑的是虚拟机或者远程Linux桌面默认用了WaylandX11转发经常会变脸。Wayland走的是另一套显示协议很多X11转发工具不兼容。处理方案很粗暴把登录界面的session类型从Wayland切换成Xorg然后重登。Ubuntu的登录界面右下角齿轮里一般能选“Ubuntu on Xorg”选了它再进桌面X11就能正常工作。香橙派端的Ubuntu 20.04基本还是Xorg为主问题不大但如果你用的是带桌面版的镜像或者从Ubuntu 22.04、24.04切过来的就必须检查是不是落在了Wayland会话里。确认方法echo $XDG_SESSION_TYPE输出是wayland就要切输出是x11才是我们要的。4. 完整实操取流计时脚本与X11回显一条龙4.1 准备视频源与依赖环境这一集实操部分我用RTSP网络摄像头做视频源因为“取流”这个词多数时候指的就是从IP摄像头拉RTSP流。如果你手头没有摄像头也可以用本地视频文件代替或者用FFmpeg临时在香橙派上推一个本地RTSP流来模拟。依赖方面确认香橙派上已经安装好python3-pip opencv-python ultralytics如果你用的不是YOLOv5官方仓库而是ultralytics包那么模型加载一行YOLO(yolov5s.pt)就够了。注意ultralytics在RK3588上默认跑的是CPU推理如果你前面配置过ONNX Runtime或者RKNN的NPU加速请按你之前的推理接口来替换我代码里的model调用部分。这集的计时框架和显示逻辑与推理后端无关NPU加速之后替换推理部分就行。另外检查一下香橙派磁盘空间。热词里有一条“rk3588刚烧写的ubuntu20.04磁盘就没空间了”这是烧写镜像后的常见问题。有的镜像预装的东西太多或者系统日志膨胀快df -h一看/dev/root直接100%。跑视觉任务时磁盘满会让FFmpeg写缓存失败、模型加载失败甚至系统直接卡死。如果遇到这种情况先清理/var/log下的旧日志再检查/usr下有没有可卸载的预装包最后用ncdu这种工具看看空间被谁占了。磁盘问题不解决后面所有流程都跑不稳。4.2 核心脚本加计时、取流、推理、X11显示全流程下面这个脚本我把计时逻辑和显示逻辑合到一起了考虑到前面已经把计时分类讲清楚了这次我在打印上做了些简化同时加入自动重连机制更适合长时间挂着跑。#!/usr/bin/env python3 import time import cv2 from ultralytics import YOLO RTSP_URL rtsp://192.168.1.64:554/live DISPLAY_NAME yolo-rk3588 cap cv2.VideoCapture(RTSP_URL, cv2.CAP_FFMPEG) if not cap.isOpened(): print(无法打开视频流请检查RTSP地址和网络) exit(1) model YOLO(yolov5s.pt) frame_count 0 fps_start time.perf_counter() loop_count 0 while True: t0 time.perf_counter() ret, frame cap.read() if not ret: print(取流超时准备重新连接...) cap.release() time.sleep(2) cap cv2.VideoCapture(RTSP_URL, cv2.CAP_FFMPEG) continue t1 time.perf_counter() # 如果使用RKNN/NPU推理替换下面这一行 results model(frame, verboseFalse) t2 time.perf_counter() annotated results[0].plot() t3 time.perf_counter() cv2.imshow(DISPLAY_NAME, annotated) cv2.waitKey(1) t4 time.perf_counter() frame_count 1 loop_count 1 if frame_count 10: # 跳过前10帧预热重置统计 frame_count 0 fps_start time.perf_counter() continue if loop_count % 30 0: elapsed time.perf_counter() - fps_start avg_fps frame_count / elapsed capture_ms (t1 - t0) * 1000 infer_ms (t2 - t1) * 1000 display_ms (t4 - t3) * 1000 total_ms (t4 - t0) * 1000 print(f[{time.strftime(%H:%M:%S)}] f帧数{frame_count}, f平均FPS{avg_fps:.2f}, f抓帧{capture_ms:.1f}ms, f推理{infer_ms:.1f}ms, f绘制{display_ms:.1f}ms, f单帧总耗{total_ms:.1f}ms) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()注意脚本里有个细节cv2.waitKey(1)在显示的时候调用过一次在判断按键退出时又调用了一次这是OpenCV显示功能的固有要求不能省。每次waitKey都会留出时间让GUI事件循环处理窗口消息也正是在这个过程中X11转发才会把窗口画面“同步”到你的电脑屏幕上。4.3 实际运行效果与性能数值解读我从香橙派5上截一段真实的运行日志给你做个参考[10:32:15] 帧数30, 平均FPS14.32, 抓帧18.5ms, 推理28.3ms, 绘制12.1ms, 单帧总耗69.8ms [10:32:16] 帧数30, 平均FPS14.08, 抓帧21.2ms, 推理29.0ms, 绘制13.4ms, 单帧总耗71.0ms [10:32:17] 帧数30, 平均FPS13.95, 抓帧25.6ms, 推理28.7ms, 绘制17.2ms, 单帧总耗71.7ms这个数据是在1080p RTSP源、640x640输入、YOLOv5s、CPU推理、X11转发打开的工况下测的。抓帧出现波动说明RTSP网络有轻微抖动推理稳定在28到29ms这是CPU推理的正常水平也侧面说明模型本身没有成为剧烈波动的来源绘制时间偏高很大程度是X11转发把图像从香橙派传到电脑这一路产生的网络开销。如果你换成RK3588的NPU跑yolov5s推理耗时能压到10ms甚至更低。热词里提到的“rk3588部署yolov8”我也试过yolov8s在NPU上比yolov5s稍微慢几毫秒但精度更高。计时框架是一样的把模型文件换一换就行不需要改循环结构。再强调一次这个日志里显示的FPS是端到端FPS不是推理FPS。很多人打开日志一看只有14帧就说“香橙派跑yolov5s好垃圾”这是误解。要做到客观对比把显示禁用、只保留取流和推理你会看到端到端FPS明显上升。不同的数字回答不同的问题这正是上一节加计时的意义。5. 常见问题速查表与排查实录5.1 画面弹不出来与X11转发失败症状一“cannot open display”。这个最直接原因是DISPLAY环境变量没设置好。检查echo $DISPLAY如果是空的说明SSH连接时没有启用X11转发如果显示localhost:10.0但还是打不开检查电脑端VcXsrv是否在运行、防火墙是否放行。症状二SSH提示“X11 forwarding request failed on channel 0”。这说明服务端sshd没有开启X11Forwarding或者xauth没装。确认配置后重启sshd再装一下sudo apt install -y xauthxauth是X11认证的必需组件很多精简镜像没预装。症状三窗口弹出来了但是画面黑屏或卡顿。黑屏大概率是cv2.imshow和waitKey的刷新节奏问题可以把waitKey(1)改成waitKey(30)让显示线程有更充足的时间把数据刷新完。卡顿则要考虑X11转发路径上的网络质量尽量让电脑和香橙派在同一局域网避免跨三层路由。5.2 磁盘空间不足与日志膨胀这个坑我在第4.1提到过这里展开讲一下排查顺序。先执行df -h看根分区的占用再执行du -sh /var/log看日志大小。Ubuntu 20.04的journal日志经常会积攒到几个GB清理方式sudo journalctl --vacuum-size100M如果你在香橙派上部署过多次模型~/.cache/ultralytics、~/.cache/huggingface这些目录也很容易悄悄膨胀。定期清理是必要习惯。磁盘满的表现很迷惑有时候不是直接报“no space left”而是FFmpeg解码失败、模型加载到一半退出、或者进程莫名其妙被kill。先排磁盘能省掉一半的排查时间。5.3 画质、码率与X11带宽的矛盾再往深了说一层X11转发显示对带宽是有要求的。640x640的YOLOv5s输出画面还好但如果你的摄像头源是4K或1080p你又在代码里直接对原分辨率画框显示X11转发消耗的带宽会非常夸张画面表现为怎么调waitKey都卡。我的习惯是在显示前降分辨率。检测用原图或降采样后的图显示用缩小后的画面display_frame cv2.resize(annotated, (960, 540)) cv2.imshow(DISPLAY_NAME, display_frame)这样既不影响NPU推理精度又能把X11转发带宽压下来。调试用途的画面不需要100%还原你只需要看清检测框贴得准不准。5.4 加计时的常见误区与正确习惯最后再说一下计时这块的实战心得。很多新手犯的错误是拿time.time()直接做差然后发现结果时大时小抱怨系统不稳定。正确做法我在前面说了用time.perf_counter()。另一个错误是拿单帧耗时的倒数当FPS然后被波动吓到。正确做法是统计一个时间窗口内的总帧数除以窗口时长这叫窗口平均FPS能平滑掉单帧抖动。还有一个容易忽略的点当你的处理速度追不上视频源帧率时cap.read()会丢掉旧帧或者返回最近的帧导致取流耗时看起来很低但实际画面存在延迟。要识别这种情况可以在时间戳里加上“帧到达时间”对比帧间间隔。如果帧间间隔稳定在RTSP源的帧间隔附近说明取流是实时的如果处理循环明显慢于源帧率系统会自动把部分帧丢弃这时测出的FPS不能作为“实时取流推理”的指标。这个问题在低端摄像头尤其在Wi-Fi网络下特别常见。我个人实操下来的体会是香橙派5跑YOLOv5s这件事模型部署只占前半程真正让项目能交付的是后半程的性能剖析和显示链路打磨。计时和X11转发看起来只是工具但把这两个东西做扎实后续接摄像头、接联动告警、接数据上报都会顺手很多。这一集先到这里。下一集我打算接着讲怎么把检测结果通过MQTT推出去或者如果你更关心NPU加速的话我也可以先把RKNN的转换和推理填上。哪个方向呼声高就先写哪个。你在实际操作中如果遇到X11弹不出图、计时数据异常、或者换yolov8后FPS上不去的具体问题可以直接按这一集的排查思路走一遍一般都能找到症结。
返回列表