基于官方資料包例程完成圖片或攝像頭目標(biāo)檢測(cè)、結(jié)果顯示和 FPS記錄。
1.實(shí)驗(yàn)?zāi)康?/p>
?驗(yàn)證 YOLOv8官方例程能在 ELF-RV1126B上正確啟動(dòng)并調(diào)用 NPU推理。
?驗(yàn)證攝像頭節(jié)點(diǎn)、模型路徑和例程關(guān)鍵參數(shù)配置是否正確。
?記錄目標(biāo)檢測(cè)效果和平均 FPS,形成可歸檔的 AI部署驗(yàn)收結(jié)果。
2.前置條件與目錄要求
1)板端準(zhǔn)備以下內(nèi)容:main_camera_fps_v8.py、rknnpool 目錄、func 目錄、rknnModel/best.rknn。(注意所有文件夾創(chuàng)建在/dev/mmcblk0p8分區(qū)的/userdata下,默認(rèn)安裝路徑是在/dev/root分區(qū)的home/elf下,會(huì)導(dǎo)致/dev/root的空間滿了)

在大分區(qū)創(chuàng)建緩存目錄
mkdir -p /userdata/.cache/pip
創(chuàng)建軟鏈接,讓系統(tǒng)以為它還在原位,其實(shí)存在了 49G的分區(qū)里
ln -s /userdata/.cache/pip ~/.cache/pip
2)若使用攝像頭,請(qǐng)先確認(rèn)攝像頭已經(jīng)被系統(tǒng)識(shí)別:這里使用的是HIKVISION的USB攝像頭。
| 無攝像頭時(shí)的處理:如果暫時(shí)沒有接攝像頭,可以先把官方例程改為讀取靜態(tài)圖片或視頻文件,先驗(yàn)證“模型加載 +前后處理 +推理輸出”鏈路;但正式驗(yàn)收時(shí),仍建議補(bǔ)做攝像頭路徑測(cè)試。 |
步驟 2.1 激活 Python 環(huán)境并安裝 OpenCV(接上一個(gè)實(shí)驗(yàn))
|
cd /userdata/rknn_test python3 -m venv venv source venv/bin/activate pip install rknn-toolkit-lite2==2.3.2 -i https://pypi.tuna.tsinghua.edu.cn/simple pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple ![]() |
步驟 2.2 檢查當(dāng)前攝像頭節(jié)點(diǎn)
|
v4l2-ctl --list-devices v4l2-ctl --list-formats-ext -d /dev/video52 ![]() ![]() |
說明:請(qǐng)把 /dev/videoXX替換為你的實(shí)際攝像頭節(jié)點(diǎn),這是video52。若是 UVC攝像頭,節(jié)點(diǎn)往往位于較靠后的 /dev/video號(hào);若是 OV13855,則可參考官方手冊(cè)中的攝像頭測(cè)試章節(jié)確認(rèn)節(jié)點(diǎn)(這里使用的是HIKVISION的USB攝像頭,1080p USB)。
3. 關(guān)鍵目錄與參數(shù)檢查
| 檢查項(xiàng) | 建議內(nèi)容 | 備注 |
|---|---|---|
| 主程序 | main_camera_fps_v8.py | 建議直接使用官方資料包版本 |
| 模型目錄 | ./rknnModel/best.rknn | 模型路徑要與腳本一致 |
| 依賴目錄 | rknnpool / func | 保持與主程序在同一工程目錄下 |
| 攝像頭節(jié)點(diǎn) | /dev/videoXX | 必須按實(shí)際節(jié)點(diǎn)修改 |
| 線程 | TPEs = 1~2初測(cè),穩(wěn)定后再提高 | 先求穩(wěn)定,再追求 FPS |
步驟 3.1 官方例程中的關(guān)鍵參數(shù)示例(按需修改,這里用X11轉(zhuǎn)發(fā)至Mobaxterm進(jìn)行顯示)
|
import os #抑制 Qt字體警告 os.environ["QT_LOGGING_RULES"] = "qt.qpa.fonts.warning=false" import cv2 import time from rknnpool.rknnpool_ld import rknnPoolExecutor from func.func_yolov8_optimize import myFunc # ---------------性能采集工具函數(shù) --------------- def get_npu_load(): """讀取 RV1126B NPU負(fù)載百分比,返回字符串如 '45%'或 'N/A'""" paths = [ "/sys/kernel/debug/rknpu/load", "/sys/class/devfreq/ffbc0000.npu/load", ] for p in paths: try: with open(p, "r") as f: text = f.read().strip() #取第一行 first_line = text.split("n")[0].strip() #格式可能是 "NPU load: 4%"或 "45%"或 "45 / 100" if "%" in first_line: #提取百分比數(shù)字,如 "NPU load: 4%" -> "4%" import re m = re.search(r'(d+)s*%', first_line) if m: return f"{m.group(1)}%" return first_line parts = first_line.replace("/", " ").split() if len(parts) >= 2: return f"{int(int(parts[0]) * 100 / int(parts[1]))}%" return first_line except (FileNotFoundError, PermissionError, ValueError): continue return "N/A" def get_cpu_usage(prev_stat): """ 通過 /proc/stat兩次采樣差值計(jì)算 CPU使用率。 prev_stat:上次采樣的 (idle, total)元組,首次傳 None。 返回 (cpu_percent_str, current_stat) """ try: with open("/proc/stat", "r") as f: line = f.readline() #第一行 "cpu ..." parts = [int(x) for x in line.split()[1:]] idle = parts[3] total = sum(parts) if prev_stat is None: return ("--", (idle, total)) d_idle = idle - prev_stat[0] d_total = total - prev_stat[1] if d_total == 0: return ("0.0%", (idle, total)) usage = (1.0 - d_idle / d_total) * 100 return (f"{usage:.1f}%", (idle, total)) except (FileNotFoundError, PermissionError, ValueError): return ("N/A", prev_stat) def draw_osd(frame, fps_str, cpu_str, npu_str): """在幀左上角繪制半透明黑底 +性能信息""" lines = [ f"FPS : {fps_str}", f"CPU : {cpu_str}", f"NPU : {npu_str}", ] font = cv2.FONT_HERSHEY_SIMPLEX scale, thickness = 0.7, 2 y0, dy = 25, 30 #半透明背景 overlay = frame.copy() cv2.rectangle(overlay, (5, 5), (220, y0 + dy * len(lines) - 10), (0, 0, 0), -1) cv2.addWeighted(overlay, 0.5, frame, 0.5, 0, frame) for i, text in enumerate(lines): cv2.putText(frame, text, (10, y0 + i * dy), font, scale, (0, 255, 0), thickness) return frame # --------------- X11顯示檢測(cè) --------------- #修復(fù) sudo下 X11授權(quán)丟失問題: # sudo會(huì)切換到 root,但 root沒有原用戶的 .Xauthority令牌 sudo_user = os.environ.get("SUDO_USER") if sudo_user: #從原用戶的 home目錄繼承 .Xauthority sudo_home = os.path.expanduser(f"~{sudo_user}") xauth_file = os.path.join(sudo_home, ".Xauthority") if os.path.exists(xauth_file) and "XAUTHORITY" not in os.environ: os.environ["XAUTHORITY"] = xauth_file print(f"已設(shè)置 XAUTHORITY={xauth_file} (來自用戶 {sudo_user})") if "DISPLAY" not in os.environ: print("警告:未檢測(cè)到 DISPLAY環(huán)境變量") print("請(qǐng)確保 MobaXterm已開啟 X11轉(zhuǎn)發(fā) (ssh -X / -Y)") print("嘗試設(shè)置 DISPLAY=localhost:10.0繼續(xù)...") os.environ["DISPLAY"] = "localhost:10.0" # ---------------初始化 --------------- cap = cv2.VideoCapture("/dev/video52") modelPath = "./rknnModel/best.rknn" TPEs = 8 os.makedirs("output", exist_ok=True) if not cap.isOpened(): print("錯(cuò)誤:無法打開攝像頭 /dev/video52") os.system("ls -l /dev/video*") exit(-1) print(f"攝像頭已打開,分辨率: {int(cap.get(3))}x{int(cap.get(4))}") pool = rknnPoolExecutor( rknnModel=modelPath, TPEs=TPEs, func=myFunc ) #預(yù)填充推理流水線 if cap.isOpened(): for i in range(TPEs + 1): ret, frame = cap.read() if not ret: print(f"錯(cuò)誤:第 {i}幀讀取失敗") cap.release() pool.release() exit(-1) pool.put(frame) # --------------- X11窗口 (帶降級(jí)) --------------- WINDOW_NAME = "YOLOv8 - RV1126B" use_x11 = False try: cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL) cv2.resizeWindow(WINDOW_NAME, 640, 480) use_x11 = True print("X11顯示窗口已創(chuàng)建") except cv2.error as e: print(f"警告: X11窗口創(chuàng)建失敗 ({e})") print("將以無頭模式運(yùn)行 (僅保存圖片到 output/)") print("提示:請(qǐng)嘗試以下命令解決 X11問題:") print(f" 1.用普通用戶運(yùn)行: python3 {os.path.basename(__file__)}") print(f" (先執(zhí)行: sudo chmod 666 /dev/video52)") print(f" 2.或傳遞 X11授權(quán): sudo -E XAUTHORITY=$HOME/.Xauthority ./venv/bin/python3 {os.path.basename(__file__)}") print(f" 3.或允許 root訪問 X11: xhost +local:root") # ---------------推理主循環(huán) --------------- # X11轉(zhuǎn)發(fā)帶寬有限,跳幀顯示以避免拖慢推理幀率 #每 X11_SKIP幀才做一次 imshow,其余幀只推理不顯示 X11_SKIP = 10 print("開始推理循環(huán),按 'q'或 Ctrl+C停止...") frames, loopTime, initTime = 0, time.time(), time.time() fps_display = "..." #預(yù)采樣 CPU一次,使首次輸出不是 "--" cpu_display, cpu_stat = get_cpu_usage(None) npu_display = get_npu_load() last_good_frame = None try: while cap.isOpened(): ret, frame = cap.read() if not ret: print(f"第 {frames + 1}幀讀取失敗,退出") break pool.put(frame) frame, flag = pool.get() if not flag: print(f"第 {frames + 1}幀推理失敗,退出") break frames += 1 last_good_frame = frame #每30幀更新性能數(shù)據(jù) if frames % 30 == 0: elapsed = time.time() - loopTime fps_val = 30 / elapsed if elapsed > 0 else 0 fps_display = f"{fps_val:.1f}" npu_display = get_npu_load() cpu_display, cpu_stat = get_cpu_usage(cpu_stat) loopTime = time.time() #保存圖片 save_path = f"output/result_{frames}.jpg" cv2.imwrite(save_path, frame) print(f"FPS: {fps_display} CPU: {cpu_display} NPU: {npu_display} | 已保存: {save_path}") # OSD疊加 draw_osd(frame, fps_display, cpu_display, npu_display) #通過 X11顯示 (跳幀以減少 X11轉(zhuǎn)發(fā)開銷) if use_x11 and frames % X11_SKIP == 0: cv2.imshow(WINDOW_NAME, frame) if cv2.waitKey(1) & 0xFF == ord('q'): print("按 'q'退出") break except KeyboardInterrupt: print("n手動(dòng)停止") finally: if last_good_frame is not None: cv2.imwrite("output/result_latest.jpg", last_good_frame) print(f"最后一幀已保存: output/result_latest.jpg") if frames > 0: total_time = time.time() - initTime print(f"總幀數(shù): {frames} 總平均幀率: {frames / total_time:.2f}") else: print("未處理任何幀") cap.release() pool.release() if use_x11: cv2.destroyAllWindows() |
步驟 3.2 運(yùn)行 YOLOv8 官方例程
|
sudo ./venv/bin/python3 main_camera_fps_v8.py 可以設(shè)置跳幀X11_SKIP =15(X11轉(zhuǎn)發(fā)是瓶頸) ![]() |
4. 預(yù)期結(jié)果與判定標(biāo)準(zhǔn)
| 檢查項(xiàng) | 成功標(biāo)志 | 判定 |
|---|---|---|
| 程序啟動(dòng) | 無 import錯(cuò)誤、無模型路徑錯(cuò)誤 | 通過 / 不通過 |
| 攝像頭打開 | 可正常讀取畫面或至少確認(rèn)節(jié)點(diǎn)可用 | 通過 / 不通過 |
| 目標(biāo)檢測(cè) | 畫面中能看到檢測(cè)框 /類別結(jié)果 | 通過 / 不通過 |
| 性能記錄 | 能夠記錄平均 FPS或等效性能指標(biāo) | 通過 / 不通過 |
5. 常見問題與排查
?程序啟動(dòng)失敗:先檢查 main_camera_fps_v8.py、rknnpool、func 和 rknnModel 目錄是否完整。
?畫面不出圖:優(yōu)先檢查 /dev/videoXX是否寫對(duì),攝像頭是否被 v4l2-ctl正確識(shí)別。
?SSH下無窗口:這通常是顯示環(huán)境問題,不一定是模型推理失敗;建議接本地顯示器,或改為保存圖片/日志方式驗(yàn)證。
?FPS偏低:先把 TPEs調(diào)到 1~2保證穩(wěn)定,再逐步提升;同時(shí)避免在高分辨率顯示輸出下直接判斷模型性能。
?檢測(cè)結(jié)果為空:檢查 best.rknn是否與當(dāng)前前處理 /后處理函數(shù)匹配,避免腳本模型版本不對(duì)應(yīng)。
-
AI
+關(guān)注
關(guān)注
91文章
40579瀏覽量
302259 -
目標(biāo)檢測(cè)
+關(guān)注
關(guān)注
0文章
234瀏覽量
16529
發(fā)布評(píng)論請(qǐng)先 登錄
【NPU實(shí)戰(zhàn)】在迅為RK3588上玩轉(zhuǎn)YOLOv8:目標(biāo)檢測(cè)與語(yǔ)義分割一站式部署指南
【飛凌嵌入式RV1126B開發(fā)板試用體驗(yàn)】+ 5. YOLOv8目標(biāo)識(shí)別部署
使用YOLOv8做目標(biāo)檢測(cè)和實(shí)例分割的演示
在AI愛克斯開發(fā)板上用OpenVINO?加速YOLOv8目標(biāo)檢測(cè)模型
YOLOv8版本升級(jí)支持小目標(biāo)檢測(cè)與高分辨率圖像輸入
AI愛克斯開發(fā)板上使用OpenVINO加速YOLOv8目標(biāo)檢測(cè)模型
三種主流模型部署框架YOLOv8推理演示
RV1126 yolov8訓(xùn)練部署教程
RV1126 yolov8訓(xùn)練部署教程
使用ROCm?優(yōu)化并部署YOLOv8模型
飛凌嵌入式旗下教育品牌推出RV1126B\RK3506B\RK3576新品開發(fā)板
ElfBoard新品發(fā)布|【RV1126B】ELF-RV1126B開發(fā)板正式發(fā)布
ELF-RV1126B+VScode測(cè)試-1
ELF-RV1126B NPU 驅(qū)動(dòng)與 RKNN 運(yùn)行環(huán)境
ELF-RV1126B YOLOv8官方例程目標(biāo)檢測(cè)部署驗(yàn)證




評(píng)論