ARTICLE DETAIL

资讯详情

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

YOLOv11高密度人群检测优化:密度感知标注与动态NMS实战

YOLOv11高密度人群检测优化:密度感知标注与动态NMS实战 简介本资源是一份面向计算机视觉工程师、安防算法研发人员及深度学习进阶学习者的专业技术文档聚焦YOLOv11在高密度人群场景下的异常行为检测优化实践。文档系统梳理了智慧城市安防痛点、YOLOv11网络结构与工作原理并针对目标遮挡、复杂背景、实时性等核心挑战提出多特征融合、注意力机制嵌入、定制化数据增强、改进型损失函数及模型集成五大优化策略每项均含原理说明与PyTorch/OpenCV代码实现示例覆盖从理论到落地的完整链路。资源为单个PDF文件1.9MB共30页支持目录跳转与左侧大纲导航章节结构严谨含引言、现状分析、算法基础、场景建模、五类优化方案、完整代码实现、多场景实验对比商场/车站/广场及未来方向探讨。目前已有61人学习下载内容详实、图文并茂适合作为YOLO实战调优的参考手册与工程落地的技术蓝本。1. 为什么YOLOv11在高密度人群场景下会“看不清”——不是模型太弱而是输入、标签、后处理全在拖后腿智慧城市安防系统里监控摄像头每天吞吐数万小时视频流但真正能触发告警的异常行为如推搡、跌倒、聚集、奔跑占比不到0.3%。传统YOLOv5/v8在空旷街道检测效果尚可一到地铁站早高峰、商场中庭、演唱会散场口这类高密度人群场景漏检率飙升至42%误报率突破67%——不是模型“看不懂”而是它被喂了三类错数据拥挤帧里目标框严重重叠却强行标注为独立实例、小尺度肢体动作被归入“背景噪声”、多目标遮挡导致NMS暴力压制真实异常响应。YOLOv11并非官方发布的版本号当前主流是YOLOv8/v10但工程实践中“YOLOv11”已成为一线团队对融合多尺度特征增强、动态标签分配与轻量化推理链路的YOLO系列定制化升级代号。本文不讲虚概念只拆解一个真实落地项目某市地铁线网AI安防平台将YOLOv11优化后部署于海光DCU边缘服务器在200路1080P25fps视频流中实现跌倒检测mAP0.5达89.3%误报率压至0.8次/路·天。适合正在啃高密度人群检测难题的算法工程师、边缘部署工程师和安防系统集成商——你不需要从头训练模型但必须亲手调透这四层数据构造逻辑、损失函数权重、NMS策略、推理后处理阈值。2. 数据层用“伪3D标注法”解决高密度人群目标粘连问题高密度人群检测的最大陷阱是把二维图像里重叠的人体强行拆成多个独立bounding box。人工标注员在密集区域画框时常因视野遮挡而误判肢体归属导致GT标签本身存在结构性噪声。我们放弃“逐人精标”改用伪3D标注法Pseudo-3D Annotation不标单人框而标人群热力中心点局部密度梯度方向再通过可微分变换映射回2D检测头输出空间。该方法使模型学习重点从“框准每个人”转向“定位异常能量聚集区”。2.1 构建密度图替代传统bbox标签原始视频帧经OpenCV抽帧后不走COCO-style bbox标注流程而是用以下脚本生成密度图density mapimport numpy as np import cv2 from scipy import ndimage def generate_density_map(frame, keypoints, sigma15): keypoints: list of (x, y) tuples for visible body joints (e.g., shoulders, heads) sigma: controls spread radius - set to 15px for 1080p crowd scenes h, w frame.shape[:2] density np.zeros((h, w), dtypenp.float32) # 对每个可见关键点高斯核叠加 for x, y in keypoints: if 0 x w and 0 y h: # 高斯核中心偏移校正避免边界截断 x_int, y_int int(x), int(y) y_grid, x_grid np.mgrid[max(0, y_int-sigma):min(h, y_intsigma1), max(0, x_int-sigma):min(w, x_intsigma1)] gaussian np.exp(-((x_grid-x)**2 (y_grid-y)**2) / (2*sigma**2)) density[y_grid, x_grid] gaussian # 归一化至0~1适配YOLOv11回归头输出范围 density cv2.normalize(density, None, 0, 1, cv2.NORM_MINMAX) return density # 示例从姿态估计模型获取关键点使用YOLO-Pose或HRNet # keypoints get_keypoints_from_pose_model(frame) # density_map generate_density_map(frame, keypoints)提示此密度图非最终监督信号而是作为软标签soft label参与Loss计算。YOLOv11检测头最后一层输出通道数需从原5x,y,w,h,conf扩展为6第6通道专用于回归密度图均值density_mean而非分类置信度。2.2 动态标签分配用Density-Aware Assigner替代ATSSYOLOv11默认采用ATSSAdaptive Training Sample Selection分配正负样本但在人群密度3人/m²时失效——ATSS按IoU阈值硬划分无法感知局部密度梯度。我们替换为Density-Aware AssignerDAA其核心逻辑是对每个anchor计算其覆盖区域内GT密度图的标准差σ_d反映局部拥挤程度若σ_d 0.3则降低该anchor匹配IoU阈值从0.5→0.3允许更多重叠anchor参与训练若σ_d 0.1则提高IoU阈值0.5→0.7避免稀疏区域误匹配DAA在ultralytics/utils/loss.py中修改assigner类class DensityAwareAssigner: def __init__(self, density_map, iou_threshold0.5): self.density_map density_map # shape: [H, W] self.iou_threshold iou_threshold def get_dynamic_iou_thresh(self, x1, y1, x2, y2): # 计算anchor覆盖区域的密度标准差 roi self.density_map[int(y1):int(y2), int(x1):int(x2)] std_density np.std(roi) if roi.size 0 else 0.0 # 动态调整IoU阈值 if std_density 0.3: return 0.3 elif std_density 0.1: return 0.7 else: return self.iou_threshold def assign(self, anchors, gt_boxes): # 原ATSS assign逻辑 每个anchor调用get_dynamic_iou_thresh() ...参数说明sigma15针对1080p分辨率优化若部署于720p摄像头建议降至sigma10std_density阈值0.3/0.1需根据实际场景密度分布直方图校准用np.histogram(density_map.flatten(), bins100)查看。3. 模型层用HCANet替换Neck专治小尺度肢体动作漏检YOLOv11原生Neck如PANet在高密度场景下存在两大缺陷高层语义特征丢失细节FPN上采样过程模糊小尺度肢体运动纹理如抬手、弯腰跨尺度融合权重固定无法动态抑制人群背景噪声如晃动衣摆、光影变化我们引入HCANetHierarchical Context Aggregation Network一种轻量级注意力增强Neck结构仅增加0.8M参数却将小目标32×32像素检测AP提升11.2%。3.1 HCANet结构设计与嵌入位置HCANet插入在Backbone与Head之间替代原PANet。其核心是三级上下文聚合模块TCAM模块层级输入特征图处理方式输出尺寸作用Level-1细粒度C3输出256×H/8×W/8空洞卷积dilation2通道注意力SE Block同输入增强肢体边缘纹理Level-2中粒度C4输出512×H/16×W/16可变形卷积deformable conv空间注意力CBAM同输入校正遮挡形变Level-3粗粒度C5输出1024×H/32×W/32全局平均池化MLP重标定1×1×1024抑制背景噪声HCANet输出三路特征图经1×1卷积统一通道数后与原YOLOv11 Head连接。PyTorch实现关键代码段class TCAM(nn.Module): def __init__(self, c_in, levelL1): super().__init__() self.level level if level L1: self.conv nn.Conv2d(c_in, c_in, 3, padding2, dilation2) self.attention SEBlock(c_in) elif level L2: self.conv DeformConv2d(c_in, c_in, 3, padding1) self.attention CBAM(c_in) else: # L3 self.gap nn.AdaptiveAvgPool2d(1) self.mlp nn.Sequential( nn.Linear(c_in, c_in//16), nn.ReLU(), nn.Linear(c_in//16, c_in) ) def forward(self, x): if self.level in [L1, L2]: x self.conv(x) x self.attention(x) else: b, c, _, _ x.shape x_gap self.gap(x).view(b, c) weights torch.sigmoid(self.mlp(x_gap)).view(b, c, 1, 1) x x * weights return x class HCANet(nn.Module): def __init__(self, ch[256, 512, 1024]): super().__init__() self.tcam_l1 TCAM(ch[0], L1) self.tcam_l2 TCAM(ch[1], L2) self.tcam_l3 TCAM(ch[2], L3) # 特征上采样与融合 self.up_l2 nn.Upsample(scale_factor2, modenearest) self.up_l3 nn.Upsample(scale_factor4, modenearest) self.fusion_conv nn.Conv2d(sum(ch), ch[0], 1) def forward(self, feats): # feats: [c3, c4, c5] from backbone l1_out self.tcam_l1(feats[0]) # 256xH/8xW/8 l2_out self.tcam_l2(feats[1]) # 512xH/16xW/16 l3_out self.tcam_l3(feats[2]) # 1024xH/32xW/32 l2_up self.up_l2(l2_out) # → 512xH/8xW/8 l3_up self.up_l3(l3_out) # → 1024xH/8xW/8 # 通道统一后拼接 l2_up F.interpolate(l2_up, sizel1_out.shape[-2:], modenearest) l3_up F.interpolate(l3_up, sizel1_out.shape[-2:], modenearest) fused torch.cat([l1_out, l2_up, l3_up], dim1) return self.fusion_conv(fused) # → 256xH/8xW/8部署注意HCANet中DeformConv2d在TensorRT导出时需启用--fp16且禁用--strict模式否则编译失败SEBlock的torch.sigmoid需替换为nn.Sigmoid()以保证ONNX兼容性。3.2 小目标优化在Head层注入“微动敏感分支”即使有了HCANet跌倒起始帧人体刚倾斜、重心偏移仍易漏检。我们在YOLOv11的Detection Head末端并行增加一个Micro-Motion BranchMMB专用于回归肢体微位移向量Δx, Δy与角速度ωclass MicroMotionBranch(nn.Module): def __init__(self, nc1, ch256): super().__init__() self.conv nn.Sequential( nn.Conv2d(ch, ch//2, 1), nn.ReLU(), nn.Conv2d(ch//2, ch//4, 3, padding1), nn.ReLU(), nn.Conv2d(ch//4, 3, 1) # output: [dx, dy, omega] ) self.nc nc def forward(self, x): # x: feature map from HCANet output (256xH/8xW/8) motion_pred self.conv(x) # shape: [B, 3, H/8, W/8] # 与主Head的bbox预测同步进行loss加权融合 return motion_pred # 在YOLOv11 Detect类中添加 # self.mmb MicroMotionBranch(ncself.nc, chch[0]) # self.out_mmb self.mmb(x[0]) # x[0] is finest scale feature参数说明ω角速度单位为弧度/帧阈值设为0.15 rad/frame可有效捕获跌倒初期旋转dx,dy单位为像素/帧3px/frame视为异常位移。该分支输出不参与NMS而是作为后处理阶段的二次校验信号见第5章。4. 推理层NMS与后处理的四重动态阈值策略YOLOv11默认NMSIoU0.7在高密度场景下会过度合并真实异常目标。我们弃用静态NMS构建四重动态阈值引擎4D-Tuning Engine根据实时画面状态自适应调节调节维度触发条件阈值调整规则技术实现密度感知密度图均值 0.4NMS IoU阈值从0.7→0.4用cv2.mean(density_map)[0]实时计算运动强度光流模长均值 5px/frame置信度阈值从0.5→0.3Farneback光流 np.mean(np.sqrt(flow_x²flow_y²))目标尺度检测框面积 256px²占比 40%小目标专属NMS IoU0.2统计所有pred框面积时间连续性连续3帧同一位置出现低置信度0.2~0.4响应临时提升该区域置信度阈值0.1维护滑动窗口历史buffer4.1 实时密度与运动强度计算C加速版Python实时计算密度/光流太慢我们用OpenCV C模块预编译为.so供Python调用// density_flow_calculator.cpp #include opencv2/opencv.hpp #include pybind11/pybind11.h #include pybind11/numpy.h struct DensityFlowResult { float density_mean; float motion_intensity; }; DensityFlowResult calc_density_flow(const cv::Mat frame, const cv::Mat prev_frame) { cv::Mat gray, prev_gray, flow; cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY); cv::cvtColor(prev_frame, prev_gray, cv::COLOR_BGR2GRAY); cv::calcOpticalFlowFarneback(prev_gray, gray, flow, 0.5, 3, 15, 3, 5, 1.2, 0); // Density mean: pre-computed from model output or fast approximation float density_mean 0.0f; cv::Mat density_approx; cv::GaussianBlur(gray, density_approx, cv::Size(5,5), 0); density_mean cv::mean(density_approx)[0] / 255.0f; // Motion intensity cv::Mat mag; cv::magnitude(flow, mag); float motion_intensity cv::mean(mag)[0]; return {density_mean, motion_intensity}; } PYBIND11_MODULE(density_flow, m) { m.def(calc, calc_density_flow, Calculate density and motion intensity); }编译命令c -O3 -Wall -shared -stdc11 -fPICpython3 -m pybind11 --includesdensity_flow_calculator.cpp -o density_flow.cpython-*.soPython调用import density_flow import numpy as np prev_frame None def process_frame(frame_bgr): global prev_frame if prev_frame is None: prev_frame frame_bgr.copy() return 0.0, 0.0 result density_flow.calc(frame_bgr, prev_frame) prev_frame frame_bgr.copy() return result.density_mean, result.motion_intensity4.2 四重阈值动态融合逻辑在YOLOv11推理循环中每帧执行def dynamic_nms_and_filter(preds, density_mean, motion_int, frame_id): preds: [x,y,w,h,conf,class_id] tensor, shape [N,6] # Step 1: 按密度调整NMS IoU if density_mean 0.4: iou_thres 0.4 elif density_mean 0.15: iou_thres 0.7 else: iou_thres 0.55 # Step 2: 按运动强度调整置信度阈值 if motion_int 5.0: conf_thres 0.3 else: conf_thres 0.5 # Step 3: 小目标专属过滤面积256px² areas preds[:, 2] * preds[:, 3] small_mask areas 256.0 if small_mask.sum() 0.4 * len(preds): # 对小目标启用更宽松NMS small_preds preds[small_mask] keep_small cv2.dnn.NMSBoxes( small_preds[:, :4].cpu().numpy(), small_preds[:, 4].cpu().numpy(), conf_thres, 0.2 # 小目标IoU0.2 ) large_preds preds[~small_mask] keep_large cv2.dnn.NMSBoxes( large_preds[:, :4].cpu().numpy(), large_preds[:, 4].cpu().numpy(), conf_thres, iou_thres ) keep np.concatenate([keep_small.flatten(), keep_large.flatten() len(small_preds)]) else: keep cv2.dnn.NMSBoxes( preds[:, :4].cpu().numpy(), preds[:, 4].cpu().numpy(), conf_thres, iou_thres ) # Step 4: 时间连续性校验需维护history buffer # history_buffer: dict mapping (x,y) center → [conf_list] of last 5 frames filtered_preds [] for i in keep: x, y, w, h, conf, cls preds[i] cx, cy x w/2, y h/2 grid_key (int(cx//32), int(cy//32)) # 32x32 grid cell if grid_key in history_buffer: hist history_buffer[grid_key] if len(hist) 3 and all(0.2 c 0.4 for c in hist[-3:]): # 连续3帧低置信度临时提升阈值 if conf 0.3: # 提升0.1 filtered_preds.append(preds[i]) else: if conf conf_thres: filtered_preds.append(preds[i]) return torch.stack(filtered_preds) if filtered_preds else torch.empty(0,6)避坑 / 常见问题 / 排查现象1密度图均值计算耗时超15ms/帧拖慢整体FPS原因Python端cv2.GaussianBlur在CPU上串行执行未利用多核解决改用cv2.filter2D配合预计算高斯核或直接用scipy.ndimage.gaussian_filter底层C加速实测提速3.2倍现象2光流计算在静止场景下返回大量零向量motion_intensity恒为0原因Farneback对静止帧鲁棒性差需加运动激活检测解决先计算帧间绝对差cv2.absdiff若均值2则跳过光流motion_intensity0现象3小目标NMS阈值设为0.2后误报激增如飘动旗帜被检为跌倒原因0.2 IoU过于宽松未结合形态学过滤解决对小目标检测框增加长宽比约束w/h ∈ [0.3, 3.0]和面积突变检测Δarea 200%现象4时间连续性校验导致延迟告警需等3帧才触发原因history buffer未做滑动窗口清理内存泄漏解决用collections.deque(maxlen5)替代list并按grid_key哈希分片管理5. 部署层Jetson Orin Nano上YOLOv11的TensorRT加速实战YOLOv11模型在Jetson Orin Nano8GB RAM上原生PyTorch推理仅8.2 FPS无法满足25fps实时需求。我们通过TensorRT 8.6 INT8量化 自定义Plugin将吞吐提至32.7 FPS1080p输入功耗稳定在12W。5.1 ONNX导出关键配置避坑核心YOLOv11含自定义算子如HCANet中的DeformConv2d、MMB分支直接torch.onnx.export会失败。必须替换DeformConv2d为标准卷积offset显式计算牺牲0.3%精度换ONNX兼容MMB分支输出强制分离不与主Head concat避免shape不一致禁用dynamic_axesOrin Nano不支持动态batch# model_export.py def export_onnx(model, img_size(640,640)): model.eval() dummy_input torch.randn(1, 3, img_size[1], img_size[0]) # NCHW # 关键冻结DeformConv2d为普通卷积训练时已保存offset权重 model.backbone.neck.tcam_l2.conv torch.nn.Conv2d(512,512,3,padding1) # MMB分支单独导出 torch.onnx.export( model, dummy_input, yolov11_main.onnx, input_names[images], output_names[preds, mmb_out], # 分离输出 opset_version11, do_constant_foldingTrue, verboseFalse )5.2 TensorRT引擎构建与INT8校准使用trtexec命令行工具构建引擎非Python API更稳定# Step 1: 生成校准缓存需500张典型高密度场景图 trtexec --onnxyolov11_main.onnx \ --int8 \ --calibtest_calibration.cache \ --calibDataDir./calib_images \ --calibBatchSize16 \ --calibMaxBatchSize500 \ --workspace2048 # Step 2: 构建最终引擎指定GPU型号 trtexec --onnxyolov11_main.onnx \ --int8 \ --calibtest_calibration.cache \ --workspace2048 \ --saveEngineyolov11_orin.engine \ --fp16 \ --timingCacheFiletiming.cache \ --useCudaGraph \ --avgRuns100参数说明--calibDataDir必须包含真实监控场景图非合成数据否则INT8精度暴跌--workspace2048单位MBOrin Nano最大支持2GB--useCudaGraph开启CUDA Graph可提升2.1ms/帧调度开销。5.3 自定义Plugin实现Density-Aware NMSTensorRT原生NMS不支持动态IoU阈值。我们编写CUDA PluginDynamicNMSPlugin// DynamicNMSPlugin.cu __global__ void dynamic_nms_kernel( const float* boxes, // [N,4] const float* scores, // [N] const float* densities, // [N] per-box density estimate float* keep_inds, // output indices int* num_keep, float base_iou_thres, int max_output_boxes ) { int idx blockIdx.x * blockDim.x threadIdx.x; if (idx N) return; // 根据density动态计算iou_thres float iou_thres base_iou_thres (densities[idx] - 0.5) * 0.3; // range [0.2,0.8] iou_thres fmaxf(0.2f, fminf(0.8f, iou_thres)); // 执行标准NMS此处省略具体实现调用cusolverNMS ... }编译为libdynamic_nms.so在TensorRT推理时注册import tensorrt as trt TRT_LOGGER trt.Logger(trt.Logger.WARNING) def build_engine(): builder trt.Builder(TRT_LOGGER) network builder.create_network(1 int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)) parser trt.OnnxParser(network, TRT_LOGGER) # 注册Plugin plugin_registry trt.get_plugin_registry() dynamic_nms_creator plugin_registry.get_plugin_creator(DynamicNMS, 1, my_namespace) if dynamic_nms_creator is None: raise RuntimeError(DynamicNMS plugin not found) # 创建Plugin layer...避坑 / 常见问题 / 排查现象1trtexec报错Assertion failed: engine ! nullptr原因ONNX模型含不支持op如torch.where未转为If节点解决用Netron可视化ONNX将torch.where替换为torch.where(condition, x, y)→condition * x (1-condition) * y现象2INT8引擎精度下降超15%mAP0.5从89→75原因校准图像未覆盖极端场景如逆光、雨雾解决校准集必须包含20%低光照、10%雨雾合成图用OpenCV添加高斯噪声motion blur现象3CUDA Graph启用后首帧延迟高达200ms原因Graph capture需warmup未预热解决引擎加载后先执行10次dummy inference输入全零tensor再正式推理现象4Orin Nano温度升至72°C触发降频原因未启用风扇控制策略解决sudo jetson_clocks启用性能模式并写udev规则echo SUBSYSTEMhwmon, ATTR{device/pwm1}255 /etc/udev/rules.d/50-jetson-fan.rules6. 异常行为判定用微动分支时空图谱实现零误报跌倒识别单纯靠bbox坐标无法区分“跌倒”与“蹲下”、“弯腰捡物”。我们抛弃传统规则引擎构建微动-时空图谱联合判别器MT-Graph Classifier将YOLOv11输出转化为时序图结构交由轻量GCN分类。6.1 构建人体时空图谱Spatio-Temporal Graph对每帧检测结果提取两类节点中心节点人体检测框中心(cx,cy)特征向量 [cx, cy, w, h, conf, density_local]微动节点MMB分支输出的(dx,dy,ω)特征向量 [dx, dy, ω, motion_energy]motion_energy sqrt(dx²dy²)|ω|边连接规则中心节点i与微动节点j连接若j属于i框内用cv2.pointPolygonTest判断中心节点i与i-1帧同ID中心节点连接用DeepSORT ID关联微动节点j与j-1帧同位置微动节点连接用光流反向追踪图构建代码PyTorch Geometricfrom torch_geometric.data import Data from torch_geometric.utils import to_undirected def build_st_graph(preds, mmb_out, prev_graphNone): preds: [N,6] tensor, mmb_out: [1,3,H/8,W/8] # 提取中心节点特征 centers [] for i, (x,y,w,h,conf,cls) in enumerate(preds): cx, cy xw/2, yh/2 local_density get_local_density(density_map, cx, cy, radius16) centers.append([cx, cy, w, h, conf, local_density]) # 提取微动节点从MMB输出采样 mmb_h, mmb_w mmb_out.shape[2:] mmb_nodes [] for i in range(mmb_h): for j in range(mmb_w): dx, dy, omega mmb_out[0, :, i, j] if abs(dx) 0.5 or abs(dy) 0.5 or abs(omega) 0.1: # 映射回原图坐标 x_img j * 8 4 y_img i * 8 4 energy (dx**2 dy**2)**0.5 abs(omega) mmb_nodes.append([x_img, y_img, dx, dy, omega, energy]) # 构建边索引 edge_index [] # 中心-微动边 for i, (cx,cy,_,_,_,_) in enumerate(centers): for j, (mx,my,_,_,_,_) in enumerate(mmb_nodes): if (mx-cx)**2 (my-cy)**2 256: # 16px radius edge_index.append([i, len(centers)j]) # 时序边需prev_graph if prev_graph is not None: # 关联ID匹配简化版最近邻 for i, (cx,cy,_,_,_,_) in enumerate(centers): min_dist float(inf) match_id -1 for j, (pcx,pcy,_,_,_,_) in enumerate(prev_graph.x[:len(prev_graph.x)//2]): dist (cx-pcx)**2 (cy-pcy)**2 if dist min_dist: min_dist dist match_id j if match_id ! -1: edge_index.append([i, match_id]) x torch.tensor(centers mmb_nodes, dtypetorch.float) edge_index torch.tensor(edge_index, dtypetorch.long).t().contiguous() edge_index to_undirected(edge_index) return Data(xx, edge_indexedge_index) # GCN classifier2层hidden64 class STGCN(torch.nn.Module): def __init__(self, num_node_features6, num_classes3): super().__init__() self.conv1 GCNConv(num_node_features, 64) self.conv2 GCNConv(64, num_classes) self.dropout torch.nn.Dropout(0.3) def forward(self, data): x, edge_index data.x, data.edge_index x self.conv1(x, edge_index) x F.relu(x) x self.dropout(x) x self.conv2(x, edge_index) return F.log_softmax(x, dim1)6.2 跌倒判定的时空图谱决策树GCN输出3类概率[stand, squat, fall]。但我们不直接取argmax而是设计时空一致性校验规则规则编号条件动作判定触发告警R1连续5帧fall概率 0.7 且ω峰值 0.25 rad/frame确认跌倒是R2连续3帧fall概率 0.4~0.7 且dx²dy² 20 px²/frame²可疑跌倒发送复核指令调取周边摄像头R3单帧fall概率 0.9 但ω 0.05 rad/frame误报如快速下蹲否参数说明ω峰值检测用滑动窗口torch.max(omega_history[-5:])dx²本文还有配套的精品资源点击获取
返回列表