当前位置: 首页 > news >正文

YOLO目标追踪代码示例:「进出双向人流统计」和「越界报警」

本文博主再给你一个可直接落地的增强版脚本:在原有「区域人流统计」基础上,新增:

进出双向计数(进+1,出-1)
越界报警(非法闯入/离开触发)
轨迹方向判断(基于中心点穿越区域边界)
报警弹窗 + 日志保存

实现思路是:用 TrackZone 做区域过滤 + 自己维护每个ID的历史中心点 → 判断穿越方向


一、实现原理(先看这个,代码更好懂)

  1. TrackZone负责:

    • 只在指定多边形区域内追踪目标
    • 返回track_ids+boxes
  2. 方向判断逻辑

    • 记录每个track_id上一帧的中心点(x1, y1)
    • 当前帧中心点(x2, y2)
    • 判断线段是否穿过区域某条边
    • 根据穿越边的法向量判断是「进入」还是「离开」
  3. 越界报警

    • 进入/离开时触发
    • 画面红色高亮 + 控制台打印 + 日志文件

二、完整代码:进出双向统计 + 越界报警

✅ 依赖:ultralytics,opencv-python,numpy

fromultralyticsimportYOLO,solutionsimportcv2importnumpyasnpfromdatetimeimportdatetime# ======================# 1. 基础配置# ======================MODEL_PATH="yolo26n.pt"VIDEO_PATH="video.mp4"# 0=摄像头OUTPUT_PATH="output_people_counting.mp4"# 监控区域(多边形,顺时针)region_points=np.array([(200,200),(1000,200),(1000,600),(200,600)],dtype=np.int32)# ======================# 2. 全局状态# ======================id_history={}# track_id -> 上一帧中心点enter_count=0exit_count=0ALARM_LOG="alarm.log"# ======================# 3. 工具函数# ======================defpoint_in_polygon(pt,polygon):"""判断点是否在多边形内"""returncv2.pointPolygonTest(polygon,pt,False)>=0defsegment_intersects_polygon(p1,p2,polygon):""" 判断线段p1->p2是否穿过polygon任意边 返回 True + 边的法向量方向 """foriinrange(len(polygon)):a=tuple(polygon[i])b=tuple(polygon[(i+1)%len(polygon)])# 线段ab(边)与线段p1p2相交ifcv2.clipLine(a,b,p1,p2)[0]:edge_vec=np.array(b)-np.array(a)normal=np.array([-edge_vec[1],edge_vec[0]])# 法向量returnTrue,normalreturnFalse,Nonedeflog_alarm(event,track_id):timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")line=f"[{timestamp}] ALARM:{event}| TrackID={track_id}\n"print(line.strip())withopen(ALARM_LOG,"a",encoding="utf-8")asf:f.write(line)# ======================# 4. 初始化 TrackZone# ======================trackzone=solutions.TrackZone(model=MODEL_PATH,region=region_points.tolist(),classes=[0],# 只统计人tracker="bytetrack.yaml",show=False,persist=True)# ======================# 5. 视频IO# ======================cap=cv2.VideoCapture(VIDEO_PATH)fps=int(cap.get(cv2.CAP_PROP_FPS))w=int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))h=int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))out=cv2.VideoWriter(OUTPUT_PATH,cv2.VideoWriter_fourcc(*"mp4v"),fps,(w,h))# ======================# 6. 主循环# ======================whilecap.isOpened():success,frame=cap.read()ifnotsuccess:breakresults=trackzone(frame)# TrackZone返回的boxes和idsboxes=results.boxes.xyxy.cpu().numpy()ids=results.boxes.id.cpu().numpy().astype(int)forbox,tidinzip(boxes,ids):x1,y1,x2,y2=map(int,box)cx,cy=(x1+x2)//2,(y1+y2)//2pt=(cx,cy)# 首次出现iftidnotinid_history:id_history[tid]=ptcontinueprev_pt=id_history[tid]id_history[tid]=pt# 判断是否穿越区域边界intersect,normal=segment_intersects_polygon(prev_pt,pt,region_points)ifintersectandnormalisnotNone:move_vec=np.array(pt)-np.array(prev_pt)direction=np.dot(move_vec,normal)ifdirection>0:enter_count+=1event="ENTER"else:exit_count-=1event="EXIT"log_alarm(event,tid)# 越界报警:红框高亮cv2.rectangle(frame,(x1,y1),(x2,y2),(0,0,255),3)cv2.putText(frame,f"ALARM:{event}",(x1,y1-10),cv2.FONT_HERSHEY_SIMPLEX,0.8,(0,0,255),2)else:# 正常追踪框cv2.rectangle(frame,(x1,y1),(x2,y2),(0,255,0),2)cv2.putText(frame,f"ID:{tid}",(x1,y1-10),cv2.FONT_HERSHEY_SIMPLEX,0.6,(0,255,0),2)# 绘制区域cv2.polylines(frame,[region_points],True,(255,0,0),2)# 统计信息cv2.putText(frame,f"In:{enter_count}Out:{exit_count}Total:{enter_count+exit_count}",(20,40),cv2.FONT_HERSHEY_SIMPLEX,1.2,(0,255,255),2)out.write(frame)cv2.imshow("People Counting & Intrusion Alarm",frame)ifcv2.waitKey(1)&0xFF==ord("q"):break# ======================# 7. 清理# ======================cap.release()out.release()cv2.destroyAllWindows()print("✅ 处理完成")print(f"进入人数:{enter_count}")print(f"离开人数:{abs(exit_count)}")print(f"当前在场人数:{enter_count+exit_count}")print(f"报警日志:{ALARM_LOG}")

三、运行效果说明

功能表现
进入区域绿色框 +In +1
离开区域绿色框 +Out -1
越界瞬间红色高亮框 + ALARM提示
日志alarm.log自动记录
输出视频带统计面板 + 报警标记

四、常见优化建议

场景优化
斜向进出误判改用射线法 + 方向角度阈值
多人密集提高track_buffer,降低match_thresh
夜间误报加亮度判断 / 红外摄像头
只想统计“进入”删除 EXIT 分支即可
http://www.cnnetsun.cn/news/3396192.html

相关文章:

  • 智能跨编辑器同步架构:Switch2IDEA实现毫秒级上下文切换的技术方案
  • 数字电路设计:从锁存器到触发器的避坑指南
  • 从帧结构到应用场景:深入解析CAN FD如何重塑车载网络通信
  • 终极免费方案:RDP Wrapper 解锁 Windows 家庭版远程桌面完整指南
  • OBS多平台直播插件:一键实现多平台同步直播的完整指南
  • C++实现自动驾驶优化算法:从梯度下降到LM法的工程实践
  • C++进制转换实战:从原理到性能优化与避坑指南
  • 车载SerDes解串器DS90UH948-Q1核心功能配置与调试实战
  • KLayout完整入门指南:三步掌握版图设计与验证核心技术
  • 终极指南:嵌入式Rust on Espressif std-training - 从零开始掌握ESP32-C3开发
  • 【爱马仕智能体】Hermes 文件自动化处理工具部署教学,零基础落地操作文档(含安装包)
  • 5个技巧掌握招聘时间:Boss Show Time插件精准提升求职成功率
  • GTA5线上小助手:从零开始掌握开源游戏辅助工具的全方位实战指南
  • 5分钟掌握图表数据提取:WebPlotDigitizer完全免费解决方案
  • REFramework专业开发指南:从零到一的RE引擎游戏Mod开发实战
  • 开关稳压器测试实战:核心挑战与解决方案
  • 游戏在左,战争在右:当你转身捕捉宝可梦时,谁在盯着你的摄像头?
  • RE引擎游戏Mod开发深度解析:REFramework架构设计与技术实现
  • 快速入门:5步搭建ESP32-C3 Rust开发环境 - std-training实战教程
  • 一文看懂人工智能专业:从学习路径到高薪就业全解析
  • 弹性工作者的时间管理与工具链整合实战指南
  • 5分钟快速上手VMagicMirror:零设备驱动虚拟形象的终极指南
  • Flutter Clean Architecture 导航管理:如何在四层架构中实现路由
  • Claude Sonnet 4在GitHub Copilot Pro中不可见?身份对齐全解析
  • SolidWorks 2026安装指南:云原生许可与系统环境深度适配
  • CSS will-change用得溜,页面滚动不卡顿!
  • SWIFT大模型训练框架:3步快速上手600+模型微调的终极指南
  • 松下伺服驱动器与PLC的脉冲控制接线实战指南
  • 如何30秒看透B站评论区真实身份:开源成分检测器完全指南
  • hyperglass支持的网络设备平台全解析:从Arista到VyOS的完整指南