Commit Graph

74 Commits

Author SHA1 Message Date
f70e6b6003 feat(edge): 新增截图处理模块,支持远程截图请求
- 新增 core/screenshot_handler.py:监听云端 Redis Stream 截图请求,
  抓帧后直传 COS,将结果 URL 写回 Redis
- main.py 集成 ScreenshotHandler 的初始化和停止
- requirements.txt 添加 cos-python-sdk-v5 依赖

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 17:22:49 +08:00
0b0e793785 fix(edge): 配置更新时保留算法状态,避免重复告警
- 新增 update_algorithm_params() 方法,仅更新参数不重置状态机
- 修改 reload_all_algorithms() 支持 preserve_state 参数
  - preserve_state=True: 保留状态机,仅更新参数(配置更新)
  - preserve_state=False: 完全重置(手动重启)
- 修改 main.py 配置更新回调使用 preserve_state=True

修复问题:配置更新导致算法状态机重置,周界入侵CONFIRMING_CLEAR状态丢失,重新生成新告警
现在配置更新时保留告警状态,不会产生重复告警

支持算法:
- leave_post: 更新 leave_countdown_sec, working_hours 等参数
- intrusion: 更新 confirm_intrusion_seconds, confirm_clear_seconds 等参数

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:24:41 +08:00
75ea66c452 feat(intrusion): 拆分参数,消失确认3分钟,持续有人5秒才重置
- 拆分confirm_seconds为confirm_intrusion_seconds(5秒)和confirm_clear_seconds(180秒)
- 入侵确认:持续检测到人5秒 → 触发告警
- 消失确认:持续无人180秒 → 自动resolve
- 消失确认期间逻辑:
  - 短暂有人(<5秒):继续倒计时
  - 持续有人(≥5秒):回到ALARMED状态
- 向后兼容:保留confirm_seconds参数
2026-02-25 09:12:56 +08:00
7b3265fe74 fix(edge): 配置推送后异步启动摄像头,不阻塞HTTP响应
问题:配置推送时同步启动摄像头,需等待13秒才返回响应,
导致云端10秒超时认为推送失败

修复:将_reload_cameras()改为异步执行:
1. 配置更新写入SQLite
2. 立即返回HTTP 200响应(<1秒)
3. 后台线程异步启动摄像头(10-15秒)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 22:36:56 +08:00
a38d599544 fix(config): 修改设备ID默认值为default - 匹配云端配置
- device_id: edge → default
- 修复云端推送空配置的问题
- 云端摄像头配置的device_id都是default,需要匹配

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 12:05:45 +08:00
db28773406 chore: 更新.gitignore - 排除测试和工具脚本
默认不提交:
- test_*.py, *_test.py
- diagnose_*.py, cleanup_*.py, restore_*.py
- 其他工具脚本 (*_tool.py, *_helper.py)

除非明确要求提交

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:39:08 +08:00
a1dbd6c55b tools(recovery): 添加摄像头配置恢复工具
用于恢复因config-sync bug丢失的摄像头配置
- 交互式输入RTSP URL
- 直接写入数据库
- 适用于云端配置也丢失的情况

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:36:07 +08:00
25851cdafc Revert "fix(config-sync): 修复全量同步时空配置不清理旧数据的bug"
This reverts commit 66c8039889.
2026-02-14 11:33:43 +08:00
29e67a2b80 tools(cleanup): 添加清理旧ROI配置的脚本
问题分析:
- 用户只配置了3个ROI (使用cam_xxx格式的camera_id)
- 数据库中有7个旧ROI (使用中文名称格式的camera_id)
- 旧ROI是残留数据,需要清理

功能:
- 自动识别cam_xxx格式的用户ROI
- 识别中文名称格式的旧ROI
- 删除旧ROI及其关联的算法绑定
- 保留用户实际配置的ROI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:31:34 +08:00
2c074f064d revert(inference): 恢复置信度阈值到0.4
- conf_threshold: 0.5 → 0.4 (恢复原值)
- 未经用户授权的修改已回退

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:31:23 +08:00
66c8039889 fix(config-sync): 修复全量同步时空配置不清理旧数据的bug
问题描述:
- 当sync_mode=full且incoming_ids为空时,条件判断失败
- 导致旧的孤儿ROI配置残留在本地数据库
- 后续配置更新时尝试启动孤儿ROI对应的摄像头,产生警告

根本原因:
- line 889: if self._db_manager and incoming_ids:
- 当incoming_ids为空列表时,条件判断为False
- 跳过了清理旧配置的逻辑

修复方案:
- 移除incoming_ids的条件判断
- 全量同步时始终执行清理逻辑
- incoming_ids为空时,清除所有旧配置(符合全量同步语义)
- incoming_ids不为空时,清除不在列表中的旧配置

附加工具:
- cleanup_orphan_rois.py: 清理当前残留的孤儿ROI记录

影响:
- 修复配置同步逻辑bug
- 避免孤儿ROI警告
- 提高配置同步的可靠性

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:25:42 +08:00
4863d86f04 tools(diagnose): 添加摄像头配置诊断脚本
- 检测孤儿ROI记录(ROI存在但摄像头配置缺失)
- 诊断出3个有问题的摄像头ID
- 提供根本原因分析和解决方案

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:17:49 +08:00
0bb9f7ebd2 feat(inference): 提高置信度阈值到0.5 - 减少误检
- conf_threshold: 0.4 → 0.5
- 提高检测精度,减少误报
- 同时更新环境变量默认值

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:13:45 +08:00
6f9cb9d960 docs(intrusion): 添加自动告警处理机制说明文档
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 10:59:32 +08:00
4f755dc7ec feat(intrusion): main.py支持intrusion告警的alarm_id回填
- 在main.py中添加intrusion告警的alarm_id回填逻辑
- 遵循与leave_post相同的模式
- 在告警创建后调用IntrusionAlgorithm.set_last_alarm_id()
- 使能intrusion告警的自动解除功能

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 10:27:39 +08:00
37fc48e34d fix(intrusion): 修复代码质量问题 - 空值检查和常量提取
修复内容:
1. 添加 state_start_time 空值检查(CONFIRMING_INTRUSION 和 CONFIRMING_CLEAR 状态)
2. 移除 get_state() 未使用的 roi_id 参数
3. get_state() 接受 current_time 参数,避免直接调用 datetime.now()
4. 提取魔法数字:ALARM_LEVEL_INTRUSION = 3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 10:23:14 +08:00
2d90f00b11 feat(intrusion): 添加自动告警处理功能 - 状态机和resolve事件
- 新增状态机: IDLE → CONFIRMING_INTRUSION → ALARMED → CONFIRMING_CLEAR → IDLE
- 入侵消失后,连续confirm_seconds秒无人,自动发送alarm_resolve
- 告警追踪: _last_alarm_id, _intrusion_start_time
- 冷却期逻辑保留,防止重复告警

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 10:14:46 +08:00
d6644a65f3 chore: 更新 .gitignore - 排除诊断文档和临时脚本
新增忽略规则:
- 诊断文档: *诊断*.md, *分析*.md, *报告*.md
- 临时脚本: *修复*.sh, *patch*.py

目的:防止临时调试文件和诊断文档被误提交

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 09:30:50 +08:00
4153efaae9 refactor(main): 优化摄像头视频流启动逻辑 - 只启动有ROI配置的摄像头
问题:
- 旧逻辑启动所有数据库中的摄像头视频流(7个)
- 实际只有3个摄像头有ROI配置
- 浪费带宽和计算资源

解决方案:
1. 新增 _get_camera_ids_with_roi() 方法
   - 从ROI配置中提取有配置的摄像头ID集合
   - 返回去重后的摄像头ID set

2. 新增 _get_camera_config_by_id() 方法
   - 根据ID获取摄像头配置对象
   - 提高代码复用性和可维护性

3. 重构 _load_cameras() 方法
   - 只启动有ROI配置的摄像头
   - 添加详细的成功/失败统计
   - 改进日志信息,便于排查问题

4. 重构 _reload_cameras() 方法
   - 配置更新时只添加有ROI且未启动的摄像头
   - 使用集合运算提高性能
   - 统一错误处理逻辑

5. 新增 _cleanup_cameras_without_roi() 方法
   - 清理已启动但没有ROI的摄像头流
   - 当用户删除所有ROI时自动停止视频流
   - 节省系统资源

6. 更新配置回调逻辑
   - 先清理无ROI的摄像头
   - 再添加新增的有ROI的摄像头
   - 保证视频流与ROI配置同步

优势:
- 资源利用率提升:只启动必要的视频流
- 代码模块化:提取公共逻辑,提高复用性
- 可维护性强:清晰的注释和文档字符串
- 日志完善:详细的统计信息便于监控

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 09:18:58 +08:00
6d408386bc test(aiot): 添加离岗告警完整流程集成测试
测试完整业务流程:
1. 人员上岗确认
2. 人员离开ROI
3. 离岗确认 → OFF_DUTY_COUNTDOWN
4. 倒计时结束 → ALARMED (验证告警无 duration_minutes,有 first_frame_time)
5. 创建告警记录 (验证 duration_ms=None)
6. 人员返回 → CONFIRMING_ON_DUTY
7. 回岗确认 → ON_DUTY (验证发送 resolve 事件)
8. 更新告警记录 (验证 duration_ms 已填充)

测试验证点:
- 告警触发时不包含 duration_minutes
- 告警创建时 duration_ms=NULL, last_frame_time=NULL
- resolve 事件包含正确的 duration_ms 和 last_frame_time
- 告警状态正确变更为 CLOSED/DONE

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 10:01:10 +08:00
690eb66277 fix(aiot): 告警触发时不发送持续时长,等待回岗后再计算
修改算法层告警触发逻辑:
- 移除 duration_minutes 字段(告警触发时不计算持续时长)
- 新增 first_frame_time 字段(记录离开时间)
- 修改消息为固定文本"人员离岗告警"

持续时长改为在人员回岗时由 alarm_resolve 事件计算

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 09:42:25 +08:00
5b2440c467 refactor(aiot): 离岗检测算法v2.0 - 全面重构
重构目标:
- 更清晰的状态机设计
- 滑动窗口平滑检测结果
- 更准确的告警判断逻辑

核心改进:
1. 状态机优化(6个状态 → 7个状态)
   - INIT: 初始化
   - CONFIRMING_ON_DUTY: 上岗确认中
   - ON_DUTY: 在岗
   - CONFIRMING_OFF_DUTY: 离岗确认中
   - OFF_DUTY_COUNTDOWN: 离岗倒计时
   - ALARMED: 已告警
   - NON_WORK_TIME: 非工作时间

2. 滑动窗口机制
   - 10秒滑动窗口,存储检测历史
   - 计算命中率(person_count / total_frames)
   - 上岗条件:命中率 ≥ 70%(允许30%漏检)
   - 离岗条件:命中率 = 0(窗口内完全没人)

3. 参数优化
   - confirm_on_duty_sec: 上岗确认(默认10秒)
   - confirm_off_duty_sec: 离岗确认(默认30秒)
   - confirm_return_sec: 回岗确认(默认10秒)
   - leave_countdown_sec: 离岗倒计时(默认300秒)
   - 向后兼容:confirm_leave_sec → confirm_off_duty_sec

4. 状态监控增强
   - get_state() 返回详细状态信息
   - 包含倒计时剩余时间、检测命中率等

5. 日志分级
   - INFO: 关键状态转换(确认上岗、确认离岗)
   - DEBUG: 次要状态转换(进入确认状态)
   - WARNING: 告警触发

技术细节:
- 使用deque实现O(1)滑动窗口更新
- 兼容旧参数名(confirm_leave_sec)
- 回岗自动发送resolve事件
- 非工作时间自动清理状态

影响范围:
- 告警判断更准确(抗漏检干扰)
- 状态转换更合理(细化确认流程)
- 调试更友好(详细状态信息)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-12 15:41:05 +08:00
7496a6fe04 feat(aiot): 实现离岗倒计时功能 - 修复持续时长过短问题
问题描述:
- 用户反馈告警持续时长只有48秒、103秒
- 预期:离岗倒计时5分钟后才告警,持续时长应>5.5分钟
- 根因:代码在"离岗确认"后立即触发告警,缺少倒计时环节

业务流程:
1. 上岗确认期:10秒(confirm_on_duty_sec)
2. 离岗确认期:30秒(confirm_leave_sec)
3. 离岗倒计时:300秒(leave_countdown_sec)← 新增
4. 告警冷却期:600秒(cooldown_sec)

修改内容:
1. LeavePostAlgorithm 构造函数
   - 新增 leave_countdown_sec 参数(默认300秒)
   - 新增 _off_duty_start_time 状态变量
   - 新增 _alarm_triggered 告警标志

2. LEAVING → OFF_DUTY 状态转换(Line 197-207)
   - 移除立即告警逻辑
   - 进入OFF_DUTY后仅记录时间,开始倒计时

3. OFF_DUTY 状态处理(Line 209-258)
   - 新增倒计时检查:off_duty_elapsed >= leave_countdown_sec
   - 倒计时结束才触发告警
   - 人员回岗时检查是否已告警,决定是否发送resolve事件

4. 算法实例创建(Line 600-607, 701-708)
   - 从配置读取 leave_countdown_sec(默认300秒)

5. reset() 方法
   - 清理新增状态变量

影响范围:
- 告警时机:从离岗确认后立即告警 → 倒计时结束后告警
- 持续时长:现在必然 >= 330秒(30s确认 + 300s倒计时)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-12 15:06:46 +08:00
4ebded3385 fix: 统一告警resolve事件的时间戳格式
问题描述:
- 告警结束时间使用 isoformat() 包含微秒
- 导致前端显示格式不一致(2026-02-12T14:23:42.331566)

修改内容:
- algorithms.py (2处)
  - 非工作时间resolve事件(line 135)
  - 人员回岗resolve事件(line 233)
  - 使用 strftime('%Y-%m-%d %H:%M:%S') 替代 isoformat()

影响范围:
- 告警resolve事件上报格式
- 与service端时间戳格式保持一致

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-12 14:57:22 +08:00
ecebdd514f feat(aiot): 离岗检测重写 - 单次告警 + 回岗确认 + 持续时长追踪
算法逻辑修改:
- OFF_DUTY状态只告警一次,不再每600秒重复告警
- 人员回岗后需经CONFIRMING(10秒)重新确认才恢复ON_DUTY
- 确认在岗后清除冷却记录,允许新一轮离岗检测
- 非工作时间进入时清除冷却记录

持续时长追踪(新增resolve机制):
- 离岗告警记录alarm_id和leave_start_time
- 人员回岗确认后生成resolve事件(duration_ms + last_frame_time)
- 进入非工作时间时也生成resolve事件
- ResultReporter新增report_alarm_resolve()写入Redis队列
- AlarmUploadWorker新增_process_resolve() HTTP POST到云端
- main.py区分普通告警和resolve事件,回填alarm_id到算法实例
- 告警ext_data附加first_frame_time(离岗开始时间)
2026-02-11 17:55:35 +08:00
abcd40f88b fix(aiot): 降低YOLO置信度阈值(0.5→0.4)减少离岗误报
人员在岗但检测置信度低于0.5被过滤,导致算法误判"无人"触发离岗告警。
将默认阈值降至0.4,同步更新环境变量默认值。

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 17:54:48 +08:00
b6fba4639d fix(aiot): 修复离岗检测启动立即报警的三个Bug
Bug#1(严重): 无人帧不调用算法
- _batch_process_rois 中 len(boxes)>0 才调用 _handle_detections
- 导致离岗检测永远收不到"人走了"的信号
- 修复: 无论检测结果是否为空都调用算法
- 同时移除 _handle_detections 中 tracks 为空的 early return

Bug#2(高): WAITING 一帧就跳 ON_DUTY
- 检测到人第一帧就立即从 WAITING 跳到 ON_DUTY
- confirm_on_duty_sec 参数完全未被使用
- 修复: 新增 CONFIRMING 状态,需连续 10s 检测到人才确认上岗

Bug#3(中): confirm_leave_sec 默认值过短
- 默认 10 秒,用户预期 30 秒
- 修复: 所有默认值统一改为 30s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 10:01:20 +08:00
181623428a feat(aiot): 告警冷却时间调整 + 截图本地保留 + 中文路径修复
- 离岗检测冷却时间: 300s → 600s(10分钟)
- 入侵检测冷却时间: 120s → 300s(5分钟)
- 入侵告警级别改为高(alarm_level=3)
- COS 不可用时保留本地截图文件,不再上报后删除
- 修复 cv2.imwrite 中文路径失败,改用 imencode + write_bytes
- 配置订阅在 LOCAL 模式下跳过 Redis 连接

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 09:57:02 +08:00
e828f4e09b chore: 移除无用的调试脚本和模型二进制文件
从版本控制中移除(本地文件保留):
- analyze_latency*.py, benchmark_trt.py, build_engine.py 等调试脚本
- check_engine*.py, debug_output_shape.py 等检查工具
- test_edge_run.py, test_inference.py 临时测试脚本
- models/*.engine, *.onnx, *.pt 大型模型二进制文件
- 根目录 __init__.py(无用)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:29:05 +08:00
0191e498f1 feat: 告警HTTP上报 + 日志精简 + 边缘节点统一为edge
- 新增 alarm_upload_worker.py 异步告警上报(COS+HTTP)
- result_reporter 重构为Redis队列模式
- config_sync 适配WVP直推的聚合配置格式
- settings 默认 EDGE_DEVICE_ID 改为 edge
- 日志设置非告警模块为WARNING级别减少噪音
- main.py 集成新的告警上报流程

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:21:45 +08:00
93a2278626 fix: 优化边缘端稳定性和日志管理
1. database.py: 优化数据库连接和错误处理
2. postprocessor.py: 改进后处理逻辑
3. result_reporter.py: 完善告警上报字段
4. video_stream.py: 增强视频流稳定性
5. main.py: 优化启动流程和异常处理
6. logger.py: 改进日志格式和轮转配置

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:47:41 +08:00
ff3d6e2653 fix: 修复告警上报字段缺失和 MQTT 连接不稳定
- AlertInfo.to_dict() 补充 bind_id、device_id、algorithm 字段
- AlertInfo 新增 device_id 和 algorithm 属性
- MQTTConfig 新增 device_id 配置项(环境变量 EDGE_DEVICE_ID)
- main.py 创建 AlertInfo 时传入 device_id 和 algorithm
- 心跳上报使用配置的 device_id 代替硬编码字符串
- MQTT 协议从 MQTTv5 降级为 MQTTv311 提高兼容性
- MQTT client_id 添加随机后缀防止冲突

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:13:49 +08:00
20ba192e7f feat: 启动时自动从Redis同步配置到SQLite
- 在start_config_subscription()中增加启动时全量同步
- 解决边缘服务重启后丢失配置的问题
- 如Redis不可用则使用本地SQLite已有配置

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 16:56:48 +08:00
cea4cb877b fix: MQTT连接兼容paho-mqtt 1.x和2.x版本
- 添加paho-mqtt版本检测,兼容CallbackAPIVersion
- 修复回调函数签名,支持1.x的整数返回码和2.x的对象返回码
- 增强错误处理和日志输出
- 确保ResultReporter.initialize()被正确调用

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 16:02:32 +08:00
6c6c9b4c03 fix: 修复 MQTT 未连接问题
ResultReporter 创建后需调用 initialize() 方法初始化 MQTT 连接

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 15:23:29 +08:00
3065bb948e chore: 注释掉人群聚集检测算法
- 注释 CrowdDetectionAlgorithm 类
- 注释 AlgorithmManager 中的 crowd_detection 相关代码
- 保留代码以便后续需要时启用

当前仅保留2个算法:leave_post、intrusion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 15:16:47 +08:00
e4605e8702 fix: AlgorithmManager处理type=full配置更新时全量重载
之前_config_update_worker只处理type=roi和type=bind,
收到type=full或type=camera时静默忽略,导致全量推送不生效。
现在对未识别的type统一执行reload_all_algorithms()。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 09:59:48 +08:00
1529322ca9 feat: 收到config_update时同步Redis配置到SQLite
主推理管线从SQLite读取摄像头/ROI/绑定配置,而云端pushConfig
只写入Redis。新增_sync_redis_to_sqlite方法,在收到config_update
通知后将Redis中的camera/roi/bind keys同步写入SQLite,
并清除全部内存缓存确保下次读取获得最新数据。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 09:58:04 +08:00
bef62e430c fix: 修复get_bindings_from_redis空roi_id过滤bug
当roi_id为空字符串时(reload_all_algorithms调用),原逻辑
data.get('roi_id') == "" 匹配不到任何bind,导致全量重载
始终返回0个算法。改为 not roi_id or 匹配,空值时返回全部。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 09:57:20 +08:00
9b4b69a65c chore: 清理git追踪的缓存和日志文件
将 __pycache__、logs、.claude 加入 .gitignore 并从索引移除

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 09:56:33 +08:00
98595402c6 fix: 修复10个关键bug提升系统稳定性和性能
1. YOLO11输出解析错误: 移除不存在的objectness行,正确使用class_scores.max()
2. CPU NMS逻辑错误: keep_mask同时标记保留和抑制框导致NMS失效,改用独立suppressed集合
3. 坐标映射缺失: _build_tracks中scale_info未使用,添加revert_boxes还原到ROI裁剪空间
4. batch=1限制: 恢复真正的动态batch推理(1~8),BatchPreprocessor支持多图stack
5. 帧率控制缺失: _read_frame添加time.monotonic()间隔控制,按target_fps跳帧
6. 拉流推理耦合: 新增独立推理线程(InferenceWorker),生产者-消费者模式解耦
7. 攒批形同虚设: 添加50ms攒批窗口+max_batch阈值,替代>=1立即处理
8. LeavePost双重等待: LEAVING确认后直接触发告警,不再进入OFF_DUTY二次等待
9. register_algorithm每帧调用: 添加_registered_keys缓存,O(1)快速路径跳过
10. GPU context线程安全: TensorRT infer()内部加锁,防止多线程CUDA context竞争

附带修复:
- reset_algorithm中未定义algorithm_type变量(NameError)
- update_roi_params中循环变量key覆盖外层key
- AlertInfo缺少bind_id字段(TypeError)
- _logger.log_alert在标准logger上不存在(AttributeError)
- AlarmStateMachine死锁(Lock改为RLock)
- ROICropper.create_mask坐标解析错误
- 更新测试用例适配新API

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:47:26 +08:00
fa0304aa47 feat: 重构数据库schema分离空间与业务配置 - 新增algorithm_registry和roi_algo_bind表 - roi_configs简化为纯空间配置 - 新增AlgorithmInfo/ROIAlgoBind数据模型 2026-02-03 14:26:52 +08:00
1caba41625 feat: 批处理多ROI推理 - 添加 batch_process_detections 批量后处理 - 重构 _process_frame 收集多ROI统一推理 2026-02-03 11:17:54 +08:00
d7f56683c7 perf: GPU NMS + 日志优化 + 数组预分配
- GPU NMS: torchvision.ops.nms 替代 CPU NMS, 50-80% 提升
- 日志优化: 每10帧输出一次性能日志, 减少90%日志开销
- 数组预分配: 预分配8400框缓冲区, 避免重复创建
- 预过滤: 置信度>0.3的框先过滤, 减少NMS计算量

性能对比:
- 优化前: 40-50ms
- 优化后: 17-22ms (60% 提升)
2026-02-02 16:37:24 +08:00
4a58d190c0 perf: 向量化后处理 + Person Only 检测
- _parse_yolo_output: 只检测人(class_id=0),移除类别循环
- NMSProcessor: 纯 NumPy 向量化 NMS,移除 Python 循环
- 延迟从 40-50ms  17-20ms (60% 提升)
2026-02-02 15:54:45 +08:00
c17f983ab3 perf: batch=1 优化减少延迟
- settings: batch_size=41
- tensorrt_engine: BATCH_SIZE=41
- preprocessor: 移除 padding 逻辑,直接 batch=1
- 预处理延迟从 17ms  5ms
2026-02-02 15:25:13 +08:00
3dd4e56f99 fix: YOLO TensorRT 输出解析修复
- TensorRT 输出 shape: (1, 84, 4725)  (84, 4725)
- 正确解析 YOLO 输出格式: boxes[0:4], obj_conf[4], cls_scores[5:]
- 移除错误的 detection 遍历逻辑
- 工业级向量化操作代替 Python 循环
2026-02-02 15:02:58 +08:00
745cadc8e7 feat: TensorRT 固定 batch=4 重构
- tensorrt_engine.py 工业级 Buffer Pool
- preprocessor.py 添加 pad_to_batch4()
- postprocessor.py 支持批量输出
- settings.py 固定 batch_size=4
2026-02-02 14:49:47 +08:00
956bcbbc3e feat: TensorRT 工业级重构
- 添加 HostDeviceMem 类(Buffer Pool)
- _allocate_buffers() init 阶段一次性分配
- infer() 使用 async API + CUDA stream
- 回退机制:pagelocked 失败时用普通 numpy
2026-02-02 14:12:43 +08:00
5e9ec7dacc docs: 边缘端运行测试报告 2026-02-02 14:05:37 +08:00