# 无人机智慧巡检_后端 **Repository Path**: yuankunn/ai_detection ## Basic Information - **Project Name**: 无人机智慧巡检_后端 - **Description**: 无人机智慧巡检后端,基于若依框架搭建而成,实现无人机画面的实时视频流检测报警,报表数据查看,大屏展示 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 94 - **Forks**: 49 - **Created**: 2023-10-26 - **Last Updated**: 2026-05-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: 若依, Java, JWT, mybatis-plus, WebSocket ## README # AiDetection 基于 **YOLO + ZLMediaKit + SpringBoot +Vue** 的 AI 智能巡检平台。 ``` RTSP 源 ──▶ Python Analyzer (PyAV+YOLO) ──▶ ZLMediaKit ──▶ 浏览器 │ ├─▶ FLV / HLS / RTSP └─▶ WebRTC (低延迟) ``` --- ## 目录结构 | 路径 | 说明 | | ---- | ---- | | `analyzer/` | Python 拉流 + YOLO 推理 + 推流(PyAV) | | `ruoyi-vue-service/` | Java 后端(Spring Boot + RuoYi) | | `ruoyi-vue-web/` | Vue 2 前端(Element-UI) | | `ZLMediaKit/` | 流媒体服务器(带 WebRTC)| | `ffmpeg-master-latest-win64-gpl-shared/` | FFmpeg Windows 二进制 | | `models/` | YOLO ONNX / TensorRT 模型 | | `config.json` | 平台总配置(端口、模型路径、密钥等) | --- ## Python 视频分析器(`analyzer/`) 本目录是原 **Analyzer** C++ 工程(BXC_VideoAnalyzer v3)的 **Python 3.9 重构实现**:对外 HTTP 路径、请求体、响应体与字段名与 C++ 版一致。 **能力概览**:推理侧用 `ultralytics`,自动识别 `.onnx` / `.engine`(TensorRT)/ `_openvino_model`;视频侧用 `PyAV` 做 RTSP 拉流、RTSP 推流与 MP4 告警落盘;服务框架为 **FastAPI + uvicorn**;多边形 IoU 使用 **shapely**;上报告警等 HTTP 调用使用 **requests**。 ### 包内目录(与 C++ 工程对应关系) ``` analyzer/ ├── main.py # 入口(对应 main.cpp) ├── requirements.txt ├── __init__.py ├── core/ │ ├── config.py # ← Core/Config.{h,cpp} │ ├── control.py # ← Core/Control.h │ ├── frame.py # ← Core/Frame.{h,cpp} │ ├── algorithm.py # ← Core/Algorithm.{h,cpp}(统一封装) │ ├── algorithm_proxy.py # ← GPU 后端的子进程 sidecar 代理 │ ├── pull_stream.py # ← Core/AvPullStream.{h,cpp} │ ├── push_stream.py # ← Core/AvPushStream.{h,cpp} │ ├── analyzer.py # ← Core/Analyzer.{h,cpp} │ ├── worker.py # ← Core/Worker.{h,cpp} │ ├── generate_alarm_video.py # ← Core/GenerateAlarmVideo.{h,cpp} │ ├── scheduler.py # ← Core/Scheduler.{h,cpp} │ └── server.py # ← Core/Server.{h,cpp} └── utils/ ├── log.py # ← Utils/Log.h ├── common.py # ← Utils/Common.h ├── calcu_iou.py # ← Utils/CalcuIOU.{h,cpp} ├── request.py # ← Utils/Request.{h,cpp} ├── transport.py # 离线把 .onnx 转 TensorRT .engine └── version.py # ← Utils/Version.h ``` 模型文件(`*.onnx` / `*.engine` / `*_openvino_model`)放在仓库根目录的 `models/`,由根目录 `config.json` 用相对路径(如 `./models/xxx`)引用即可。 ### 环境、依赖与配置 - **环境**:推荐 Python 3.9(与原需求一致),3.10+ 一般也可;Windows 10/11 或 Linux;可选 NVIDIA GPU + CUDA,用于 GPU 推理或 TensorRT `.engine`。 - **安装依赖**(在仓库根目录执行): ```bash pip install -r analyzer/requirements.txt ``` `ultralytics` 首次运行可能下载权重;若仅使用本地模型,请提前放入 `models/` 并在 `config.json` 写明路径。PyAV 依赖系统 FFmpeg 能力,pip 安装的 `av` 通常自带预编译二进制。 - **配置文件**:编辑项目根目录 [`config.json`](config.json),与 `ruoyi-vue-service` 共用同一份。 | 字段 | 说明 | | ---- | ---- | | `host` | 本机对外 IP | | `adminPort` | 管理端 HTTP 端口(上报告警) | | `analyzerPort` | 本分析服务监听端口(默认 9002) | | `mediaHttpPort` / `mediaRtspPort` | 流媒体服务端口(浏览器 / RTSP 回放) | | `uploadDir` | 本地告警视频/图片根目录 | | `onnxRuntime` / `openVINO` / `tensorRt` | 启动期兜底模型路径;布控时也可按下发的 `modelPath` 懒加载;可写绝对路径或**相对于本 config.json** 的相对路径 | | `algorithmApiUrl` | `modelCode=API` 时转发的外部推理服务 | | `algorithmOnnxRuntimeDetectDevice` | 如 `CUDAExecutionProvider`、`CPUExecutionProvider` | | `algorithmOpenVINODetectDevice` | 如 `CPU`、`GPU` | ### 启动方式 推荐在**仓库根目录**以模块方式启动(默认读取根目录 `./config.json`): ```bash python -m analyzer.main python -m analyzer.main -f config.json # 显式指定配置文件 ``` 也可直接执行脚本:`python analyzer/main.py`。若使用虚拟环境,将 `python` 换为 venv 下的解释器即可(Windows 示例:`.\analyzer\.venv\Scripts\python.exe -m analyzer.main`)。 启动成功时可见类似日志:`启动视频分析器服务:http://0.0.0.0:9002`,以及 `Start Success`。 ### HTTP API | 方法 | 路径 | 作用 | | ---- | ---- | ---- | | GET | `/` | 接口索引 | | POST | `/api/health` | 健康检查 | | POST | `/api/controls` | 当前正在分析的任务列表 | | POST | `/api/control` | 指定 `code` 的任务信息 | | POST | `/api/control/add` | 创建任务 | | POST | `/api/control/cancel` | 取消任务 | **`POST /api/control/add`** 请求体示例: ```json { "code": "test001", "streamUrl": "rtsp://admin:pwd@192.168.1.64:554/Streaming/Channels/101", "pushStream": true, "pushStreamUrl": "rtsp://192.168.1.4:554/live/test001", "algorithmCode": "人形检测", "objects": "0,person,1,2,car,0", "yoloVersion": "yolov8", "inferenceFramework": "tensorrt", "modelPath": "/abs/path/to/yolov8n.engine", "llmConfigId": 1, "llmEnabled": true, "llmBaseUrl": "https://api.openai.com/v1/chat/completions", "llmModelName": "gpt-4o-mini", "llmTemperature": 0.2, "llmMaxTokens": 256, "llmTimeoutMs": 3000, "llmSystemPrompt": "你是视觉告警复核助手。", "llmUserPromptTemplate": "请判断该告警是否误报,返回 decision/reason JSON。", "recognitionRegion": "0.1,0.1,0.9,0.1,0.9,0.9,0.1,0.9", "minInterval": "180" } ``` 要点: - `yoloVersion` 必填:`yolov8` / `yolov11` - `inferenceFramework` 必填:`tensorrt` / `onnx` / `pytorch`(`.pt`);当前仅 `(yolov8|yolov11) + tensorrt` 组合会正常放行,其余组合可能返回非 1000 错误 - `modelPath` 由业务后端布控下发,分析器按后缀选后端 - `objects`:新协议为 `classId,name,grade` 三元组;兼容旧协议 `name,grade` - `recognitionRegion`:相对图像宽高的归一化多边形顶点 - `minInterval`:告警最小间隔(秒),内部上限 180 - `llm*` 字段可选:启用后会在 YOLO 初判命中后调用远程 OpenAI 兼容接口进行二次过滤 - 旧字段 `modelCode`:仍可传 `API` / `CNNLSTM` / `DLIB_FACE` 走远程/旧分支;本地 YOLO 请用 `yoloVersion` + `inferenceFramework` 成功示例:`{"msg": "add success", "code": 1000}`。 **`POST /api/control/cancel`**:`{"code": "test001"}` → 成功时 `code: 1000`。 ### C++ 与 Python 文件对照 | C++ | Python | | --- | ------ | | `main.cpp` | `main.py` | | `Core/Config.{h,cpp}` | `analyzer/core/config.py` | | `Core/Control.h` | `analyzer/core/control.py` | | `Core/Frame.{h,cpp}` | `analyzer/core/frame.py` | | `Core/Algorithm.{h,cpp}` 及各后端 | `analyzer/core/algorithm.py`(`ultralytics` 统一封装) | | `Core/AvPullStream.{h,cpp}` | `analyzer/core/pull_stream.py` | | `Core/AvPushStream.{h,cpp}` | `analyzer/core/push_stream.py` | | `Core/Analyzer.{h,cpp}` | `analyzer/core/analyzer.py` | | `Core/Worker.{h,cpp}` | `analyzer/core/worker.py` | | `Core/GenerateAlarmVideo.{h,cpp}` | `analyzer/core/generate_alarm_video.py` | | `Core/Scheduler.{h,cpp}` | `analyzer/core/scheduler.py` | | `Core/Server.{h,cpp}`(libevent) | `analyzer/core/server.py`(FastAPI + uvicorn) | | `Utils/Log.h` | `analyzer/utils/log.py` | | `Utils/Common.h` | `analyzer/utils/common.py` | | `Utils/CalcuIOU.{h,cpp}` | `analyzer/utils/calcu_iou.py` | | `Utils/Request.{h,cpp}` | `analyzer/utils/request.py` | | `Utils/Version.h` | `analyzer/utils/version.py` | ### 自测建议 1. 启动后访问 `http://127.0.0.1:9002/` 应返回接口索引 JSON。 2. 用 Postman / curl 调用 `/api/control/add` 创建 RTSP 任务,再调 `/api/controls` 应能看到任务。 3. 命中目标时,`uploadDir/alarm//<时间戳_随机数>/` 下会生成 `main.mp4`、`main.jpg`,并向 `http://host:adminPort/service/business/alarm/add` 上报告警(需管理端已启动)。 4. 若 `pushStream=true`,可用 VLC / ffplay 拉 `pushStreamUrl` 查看画框画面。 ### YOLO 二次过滤(大模型) 本项目已支持“YOLO 命中后调用大模型二次过滤”,用于降低误报。整体流程如下: 1. 在业务系统新增 `大模型配置`(OpenAI 兼容接口:`baseUrl/apiKey/modelName/temperature/maxTokens/timeoutMs` 等)。 2. 在 `布控管理` 的新增/修改页面选择大模型配置(可不选,不选则保持原 YOLO 流程)。 3. 加入识别时,Java 后端把配置下发给 analyzer。 4. analyzer 在 `_run_yolo` 判定命中后调用大模型,读取 `decision + reason`: - `reject/drop/false_positive`:判定为误报,抑制本次告警; - 其它结论:保留告警并继续原链路。 5. 若大模型超时、网络异常或解析异常,系统自动降级为“保留原 YOLO 结果”,保证实时检测不中断。 返回约定建议(OpenAI 兼容 `chat/completions`): ```json { "decision": "keep", "reason": "目标轮廓清晰且在关注区域内" } ``` 其中 `decision` 推荐值:`keep` / `reject`。 ### 其它说明 - `DLIB_FACE` 与 C++ v3.40+ 行为一致:仅返回错误信息,不做人脸识别。 - `openvino_yolo8_face` 在 C++ 原版中已注释禁用;Python 版保留占位,可在 `analyzer/core/analyzer.py` 扩展。 - `CNNLSTM` 依赖外部推理服务与约定数据目录(如 `cnnlstmdata`),由脚本按需创建。 许可与根仓库一致,见根目录 `LICENSE`。 --- ## 一、子项目 README 汇总(统一放在顶层) 除上文 **Python 视频分析器** 外,其余子模块的要点汇总如下;需要原文时可打开对应路径。 ### 1. `ruoyi-vue-service/`(Java 后端服务) - 原 README:[`ruoyi-vue-service/readme.md`](ruoyi-vue-service/readme.md) - 主要职责:设备/任务管理、告警管理、流地址下发、与分析器进行接口协同 - 技术栈:`Spring Boot 2.5.x`、`MySQL`、`Redis`、`MyBatis-Plus`、`WebSocket`、`MQTT` - 默认账号:`admin / admin123`(以该子项目 README 为准) - 启动方式: ```bash cd ruoyi-vue-service mvn -pl ruoyi-admin spring-boot:run ``` ### 2. `ruoyi-vue-web/`(Vue 前端展示) - 原 README:[`ruoyi-vue-web/README.md`](ruoyi-vue-web/README.md) - 主要职责:巡检大屏、视频播放、布控管理、告警展示 - 技术栈:`Vue 2`、`Element-UI`、`EasyPlayerPro`(当前默认 WebRTC,失败自动降级 FLV) - 启动方式: ```bash cd ruoyi-vue-web npm install npm run dev ``` ### 3. `ZLMediaKit/`(流媒体服务) - 本仓库内置了可直接运行的 Windows 构建产物(含 WebRTC) - 详细配置、端口、WHEP 地址、自测方式见下文“ZLMediaKit(带 WebRTC)”章节 --- ## 二、ZLMediaKit(带 WebRTC) > 项目根目录已经预置了一份带 **WebRTC 编译开关** 的 ZLMediaKit Windows 构建产物, > 解压后目录为 [ZLMediaKit/](ZLMediaKit/)。无需额外编译,开箱即用。 ### 1. 下载来源 官方仓库 [ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit) 的 GitHub Actions 每日构建产物(自动开启了 `ENABLE_WEBRTC=true`),通过 [nightly.link](https://nightly.link/) 免登录直链下载: - 最新构建跳转页: - 本仓库使用的版本(2026-04-18 master): (约 82 MB,解压后约 290 MB) > 如果需要更新,直接下载最新 zip,把里面 `windows/Release/` 下所有内容 > 放到本地 [ZLMediaKit/bin/](ZLMediaKit/bin/) 即可(注意保留 `bin/config.ini` 不要被覆盖)。 ### 2. 目录结构 ``` ZLMediaKit/ ├── bin/ # MediaServer.exe 工作目录 │ ├── MediaServer.exe # 主程序(已内置 WebRTC) │ ├── config.ini # 配置文件(与项目业务保持一致,勿改) │ ├── default.pem # 内置 SSL 证书 │ ├── mk_api.dll # C SDK 动态库 │ ├── webrtc.lib # WebRTC 静态库(已链接进 exe) │ └── *.lib test_*.exe # 二次开发用静态库与示例程序 ├── www/ # HTTP 静态根目录(被 config.ini 中 rootPath=../www 引用) │ ├── webrtc/ # 官方自带 WebRTC 推拉流测试页(index.html) │ ├── webassist/ # 官方流管理后台 │ ├── swagger/ # REST API 在线文档 │ ├── ZLMRTCClient.js # 前端 WebRTC 客户端 SDK │ └── logo.png ├── start.bat # Windows 一键启动(cmd) └── start.ps1 # Windows 一键启动(PowerShell) ``` ### 3. 启动 ```bat :: 方式一:双击 start.bat 或在终端运行 ZLMediaKit\start.bat :: 方式二:手动 cd ZLMediaKit\bin MediaServer.exe -l 1 ``` 启动成功后日志会出现如下关键行(说明 WebRTC 已加载): ``` WebRtcTransport.cpp ... Load webrtc plugin:push WebRtcTransport.cpp ... Load webrtc plugin:play WebRtcTransport.cpp ... Load webrtc plugin:talk ``` ### 4. 端口与协议 | 协议 | 端口 | 说明 | | ---- | ---- | ---- | | HTTP | **9003** | REST API / HTTP-FLV / HLS / WebRTC 信令(WHEP/WHIP) | | HTTPS | 443 | — | | RTSP | **9554** | RTSP 推/拉(项目 analyzer 推流端口) | | RTSPS | 332 | — | | RTMP | 1935 | RTMP 推/拉 | | RTMPS | 19350 | — | | RTP Proxy | 10000 | GB28181 接入 | | Shell | 9000 | telnet 调试 | | **WebRTC UDP** | **8000** | 媒体传输(默认值,未在 `config.ini` 中显式声明,由 ZLM 内部默认提供) | | **WebRTC TCP** | **8000** | UDP 不通时的回退通道 | | **STUN/TURN** | **3478** | NAT 穿透 | | TURN 端口池 | 49152-65535 | TURN 服务分配端口 | > **重要**:内网部署时请放行 UDP 8000 / TCP 8000 / UDP 3478; > 公网或跨 NAT 部署时还需要在 `config.ini` 的 `[rtc]` 段补一个 > `externIP=<公网IP>`,并放行 `49152-65535/udp` 端口段。 ### 5. WebRTC 拉流地址(WHEP) ZLMediaKit 的 WebRTC 信令复用 HTTP 端口(9003),URL 范式如下: ``` http://:9003/index/api/webrtc?app=&stream=&type=play ``` 或者标准 WHEP 形式: ``` http://:9003/rtc/whep?app=&stream= ``` 例如本项目 analyzer 推流到 `rtsp://127.0.0.1:9554/analyzer/cam01` 后, WebRTC 拉流地址即为: ``` http://127.0.0.1:9003/index/api/webrtc?app=analyzer&stream=cam01&type=play ``` ### 6. 浏览器自测 直接打开内置测试页: ``` http://127.0.0.1:9003/webrtc/ ``` 填入 `http://127.0.0.1:9003/index/api/webrtc?app=analyzer&stream=cam01&type=play` 即可在 H5 上低延迟拉流。 --- ## 三、配置说明 `ZLMediaKit/bin/config.ini` 与项目其他模块严格对齐: | 字段 | 值 | 一致性说明 | | ---- | ---- | ---- | | `[api] secret` | `aqxY9ps21fyhyKNRyYpGvJCTp1JBeGOM` | 与根目录 [config.json](config.json) 的 `mediaSecret` 一致 | | `[http] port` | 9003 | 对应 `config.json` 中 `mediaHttpPort` | | `[rtsp] port` | 9554 | 对应 `config.json` 中 `mediaRtspPort` | | `[general] mediaServerId` | `bqi4DlRSYANBHBNy` | analyzer 推流分组依据 | | `[ffmpeg] bin` | `ffmpeg.exe` | 启动前请确保 `ZLMediaKit/bin/` 下能找到 `ffmpeg.exe`,或将 [ffmpeg-master-latest-win64-gpl-shared/bin](ffmpeg-master-latest-win64-gpl-shared/bin) 加入 PATH | | `[http] rootPath` | `../www` | 因此可执行文件必须在 `ZLMediaKit/bin/` 下启动 | > **请勿修改**上述字段,否则 analyzer 推流和 RuoYi 后端获取流列表都会失败。 > 如需扩展 WebRTC 行为,仅在文件末尾追加 `[rtc]` 段即可(默认值已能正常工作)。 --- ## 四、前端播放器(EasyPlayerPro + WebRTC) 前端 [ruoyi-vue-web/src/views/business/player/index.vue](ruoyi-vue-web/src/views/business/player/index.vue) 已经从 `flv-extend` 切换为 **EasyPlayerPro**,默认使用 **WebRTC** 低延迟拉流, WebRTC 失败时自动回退到 HTTP-FLV。 ### 1. 资源位置 EasyPlayerPro(含 WASM 解码器)已随仓库提供,位于: ``` ruoyi-vue-web/public/EasyPlayer/ ├── EasyPlayer-pro.js # 主库(~3.6 MB) ├── EasyPlayer-pro.wasm # 解码 WASM ├── EasyPlayer-snap.wasm # 截图 WASM ├── EasyPlayer-decode.js └── EasyPlayer-lib.js ``` 来源:(main 分支 `js/` 目录)。 通过 [ruoyi-vue-web/public/index.html](ruoyi-vue-web/public/index.html) 全局注入: ```html ``` ### 2. 调用流程 ``` 浏览器 ──GET──▶ /business/stream/webrtcurl?app=&name= │ 后端 AvStreamController │ ZLMediaKit.getWebRtcPlayerUrl(app,name) │ 返回 webrtc://host:9003/app/stream ▼ EasyPlayerPro.play(webrtcUrl) │ 内部转换为 WHEP HTTP POST ▼ ZLMediaKit ─── ICE/DTLS/SRTP ───▶ 播放 ``` 后端接口: | 接口 | 说明 | | ---- | ---- | | `GET /business/stream/webrtcurl?app=&name=` | 同时返回 `webrtcUrl`(WHEP)、`webrtcPlayerUrl`(webrtc://) 和 `flvUrl` | | `GET /business/stream/flvurl?app=&name=` | 兼容旧调用,同时附带上述全部字段 | ### 3. 自动降级 播放器组件按以下顺序尝试: 1. **WebRTC**:`webrtc://127.0.0.1:9003//`(首选,约 200~500ms 延迟) 2. **HTTP-FLV**:`http://127.0.0.1:9003//.live.flv`(兜底,约 1~3s 延迟) 界面右上角的 LIVE 标签会显示当前正在使用的协议(`WEBRTC` / `FLV`), 便于排查。 ### 4. 延迟实测 在本地同机环境(ZLMediaKit + Analyzer + 前端)下,`WEBRTC` 模式端到端延迟通常稳定在600ms,明显低于 `FLV` 兜底链路,适合实时巡检场景。 ![WebRTC 延迟实测截图](images/image.png) ### 5. 备选方案 如果你想用 ZLMediaKit 自带的客户端取代 EasyPlayerPro: - 路径:`http://127.0.0.1:9003/ZLMRTCClient.js` - 优点:开源、轻量、与 ZLM 完美兼容;缺点:UI 需自己写 - 文档示例:(ZLMediaKit 自带测试页) --- ## 五、整体启动顺序 1. 启动 ZLMediaKit ``` ZLMediaKit\start.bat ``` 2. 启动 Python Analyzer(在仓库根目录,推荐模块方式;详见上文「Python 视频分析器」) ``` python -m analyzer.main ``` Windows 若使用虚拟环境,也可:`.\analyzer\.venv\Scripts\python.exe -m analyzer.main` 或 `cd analyzer` 后执行 `.\.venv\Scripts\python.exe .\main.py`。 3. 启动 Java 后端 ``` cd ruoyi-vue-service mvn -pl ruoyi-admin spring-boot:run ``` 4. 启动前端 ``` cd ruoyi-vue-web npm run dev ``` --- ## 六、常见问题 - **MediaServer 一启动就退出,错误码 -1** 通常是工作目录不对。必须在 `ZLMediaKit/bin/` 目录下启动(`config.ini` 里 `rootPath=../www` 是相对路径),直接双击 `ZLMediaKit\start.bat` 不会有此问题。 - **WebRTC 拉流卡在握手阶段(ICE failed)** - 浏览器与服务器不在同一台机器:在 `[rtc]` 段加 `externIP=<可被浏览器访问到的 IP>`。 - 防火墙:放行 UDP 8000、TCP 8000、UDP 3478,必要时放行 `49152-65535/udp`。 - **要更换 ZLMediaKit 版本** 到 下载新 zip, 解压后用 `windows/Release/` 下的可执行文件覆盖 `ZLMediaKit/bin/`, **保留** `bin/config.ini` 不要替换。 - **SQL文件** 在目录`ruoyi-vue-service\sql`下