简介:面向人工智能项目实践者,这份资源将YOLOv5人体检测与OpenPose姿态估计结合,用于实现高效摔倒检测。压缩包内共183个文件,涵盖Python脚本、YOLO与OpenPose模型文件(openpose.jit、action.jit)、训练配置yaml以及大量示例图片,整体约40MB,便于快速搭建与二次开发。运行runOpenpose.py可提取人体关键点图,并可通过pose.py中draw方法控制保存位置,为后续模型训练准备数据;运行detect.py则先执行YOLO定位人体,再裁剪人体区域交给OpenPose分析姿态,其中宽高比判断与关键点限制均可按需修改。若需检测其他姿势,资源提供了完整扩展流程:采集图片生成关键点图、按类别整理至data/train与data/test、执行action_detect/train.py训练新模型,具备良好的通用性。附带的Dockerfile与yaml配置可帮助快速部署环境,减少踩坑。已有1063人学习使用,适合具备Python基础、希望深入目标检测与姿态识别结合的开发者。
1. 为什么摔倒检测要用 yolov5 加 openpose:先想清楚再动手
yolov5人体检测+openpose姿态检测实现摔倒检测,这个方案拆开就是一套串行管道:先用yolov5把人从画面里找出来,再用openpose估计头、颈、髋、膝等关键点,最后按关键点的高度和角度判定是否摔倒。早期我试过只靠yolov5人体检测:连续几帧检测框中心点突然下移就报摔倒,结果工人蹲下捡东西被误报成摔倒。只靠目标框很难区分蹲、坐、躺,而姿态估计能把判断从“框的位置”升级成“骨骼的姿势”,误报率能降一截。这个项目适合正在学目标检测、想往姿态估计走一步的从业者,也适合做养老院、工地等场景的安防落地。下面按环境—联动—判定—排查—部署的顺序讲,代码可直接抄去改。
2. 环境与模型选型:把 yolov5 和 openpose 装进同一个推理管线
2.1 conda 环境配置:先解决版本冲突,再谈检测效果
做这个项目,最容易翻车的地方不是算法,而是环境。yolov5依赖pytorch,openpose官方仓库依赖caffe、cudnn和一堆编译工具,两个装进同一个环境,经常因为protobuf或opencv版本打架。我踩过一次:yolov5要opencv-python>=4.1,openpose的python API又需要opencv-contrib-python,两个包互相覆盖,最后图像显示都是花的。后来我不再碰官方openpose仓库,改用OpenCV DNN模块加载openpose的caffemodel。这样姿态估计不再需要额外编译C++代码,一个opencv-python就搞定,和yolov5只共享python环境,省掉很多玄学问题。
# 用conda创建独立环境,避免污染base环境 conda create -n fall python=3.8 -y conda activate fall # 安装pytorch,先按你机器的cuda版本选命令,CPU版直接跑也没有问题 conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch -y # yolov5需要的依赖,可以进入yolov5源码目录后装requirements pip install -r requirements.txt # 这里单独装opencv-python和opencv-contrib-python,dnn模块在contrib包里更全 pip install opencv-python opencv-contrib-python numpy先说python和pytorch:conda create指定python=3.8,是因为不少历史版本的yolov5和openpose模型脚本对3.9以上支持的坑比较多,没必要在这个地方赌运气。cudatoolkit版本不用追新,只要和你的显卡驱动匹配。如果只是CPU调试,把cuda那行去掉,后面推理会慢一些但能跑通。再强调一下opencv:dnn模块读caffe模型在opencv-python里也有,但contribute包里额外包含了文本检测、跟踪等模块,后文有些辅助函数会用到,所以两个都装上不会被覆盖。
yolov5源码建议从官方仓库clone下来,因为后面要训练自己的数据集和导出torchscript,都需要源码里的export.py和train.py。别用纯pip install yolov5这种方式,你很难看着源码改后处理。clone下来之后,进入目录pip install -r requirements.txt最稳。这个细节算是我做yolov5基础笔记时最常提醒人的一点:依赖清单在官方requirements.txt里已经写死,自己逐个pip装很容易漏掉pyyaml、matplotlib、tensorboard这些辅助包。
2.2 模型权重与训练策略:用官方权重还是自己训练 yolov5
环境装好后,第一件事是把yolov5s.pt跑起来。官方权重对coco 80类都有检出能力,其中person类对应的类别id是0。摔倒检测场景里通常不需要检测其他东西,可以强制让模型只输出person类。如果场景是固定的室内摄像头,视野变化小、人的大小范围稳定,官方权重够用;如果场景是俯视、夜间、或者人经常被遮挡,官方权重就很容易漏检,这时候才需要考虑用自己场景的数据微调yolov5。常见做法是先收集500到1000张标注了person的图片,用yolov5的detect.py做一次验证,看看哪些场景漏检,再去sample数据训练。yolov5超参数里最需要调的三个是batch、epochs和imgsz。我的习惯是先用batch=8、epochs=50、imgsz=640跑一遍,确认loss能降下来,再把epochs加到100。不要一上来就训练300轮,v5训练很快,但调一次数据集和标签要花很多时间。
OpenPose部分用OpenCV DNN的话,需要准备两件东西:一个caffemodel权重文件,一个prototxt网络结构文件。prototxt我一般直接用官方BODY_25的版本,它输出25个关键点,比coco的18点多了髋部和脚部细节,摔倒判定时多了几个可靠的参考点。加载代码很短:
import cv2 # 官方BODY_25的caffe模型文件放到models/openpose目录 net = cv2.dnn.readNetFromCaffe( "models/openpose/pose_deploy_linevec.prototxt", "models/openpose/pose_iter_440000.caffemodel" ) # 直接用CPU也能跑,但会慢;有GPU时优先用CUDA net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)这里要说明两点。第一,模型文件是openpose官方发布的,很多博客里都能看到对应文件名,但注意prototxt和caffemodel必须配套,用coco的prototxt配BODY_25的caffemodel,会直接报维度不匹配的错误。第二,setPreferableBackend和setPreferableTarget这两行,如果你的机器没有CUDA,就不要调用,否则dnn模块会启动失败。CPU跑openpose不是不行,而是输入分辨率必须降下来,我们后面第3章会讲怎么用yolov5的框来缩小openpose的输入图,避免全图推理。
YOLOv5的模型大小也要选对。yolov5s是速度和精度平衡点,做实时摔倒检测首选。如果想更轻,用yolov5n,把imgsz降到320,但检测小目标能力会变差;如果想更准,用yolov5m或l,但CPU上代价很大。如果目标是“树莓派5上部署自己训练的yolov5模型”,我会建议yolov5s加ONNXRuntime甚至TensorRT,而不是直接跑原版pytorch,原版pytorch在树莓派5上跑yolov5s很难到实时,加上openpose就更难了。
如果你决定训练自己的数据集,yaml文件要按yolo格式写:
# 在yolov5源码目录下执行,fall.yaml里指向你标注好的数据集 python train.py --data fall.yaml --weights yolov5s.pt \ --epochs 50 --batch-size 8 --img-size 640fall.yaml的关键内容只有三行:path写数据集根目录,train写训练图片文件夹,names写成["person"],nc自动推断为1。这样训练出来的就是单类别检测器,后处理时不需要再按class过滤。这个配置在yolov5训练自己的数据集时非常常见,比直接用coco.yaml省显存也省推理时间。
3. 人体检测与姿态估计的联动:让两套模型在一根管线里配合
3.1 yolov5人体检测:后处理为什么要做类别过滤与置信度过滤
yolov5输出是三维tensor,shape是[1, 25200, 85],85里前4个坐标,第5个objectness,剩下80个分类概率。直接拿这个输出做摔倒判定是不可能的:25200个候选框里大部分是背景,而且坐标是在640x640输入图下的像素坐标,不是原图坐标。所以后处理至少要做三件事:阈值过滤、NMS、坐标缩放。如果你用torch.hub方式加载模型,这些后处理yolov5已经封装好了,返回的results对象里可以直接拿pandas()。自己用源码的detect.py时,最后的detect层也做了nms。但摔倒检测里有个细节:不要用默认的conf=0.25,最好调到0.45到0.5。为什么?因为openpose比较慢,我们只会对置信度高的框去做姿态估计,如果一个低置信度的框混进来,openpose算出的关键点大概率是乱的,反而把摔倒判定带偏。
import torch # 加载yolov5官方预训练模型;离线部署时改成加载本地的yolov5s.pt model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True) model.conf = 0.45 # 提高置信度,滤掉低质量的预测框 model.iou = 0.5 # NMS的IoU阈值,框重叠严重时调高到0.6 model.classes = [0] # 只保留person类,coco里0是person model.max_det = 20 # 画面中最多保留20个人,人多时防止后处理卡顿 # frame是摄像头读进来的BGR图;results里带缩放和nms信息 results = model(frame) boxes = results.pandas().xyxy[0] # 每一行是 x1 y1 x2 y2 confidence class参数说明:conf、iou、classes这三个属性是yolov5推理时直接读的,比你在detect层外面再做一次过滤省事。max_det限制最大检测人数,主要不是为了速度,是为了防止某帧画面出现大量误检框时,后面的姿态估计被无意义目标占满。boxes里拿到的坐标是原图坐标,因为torch.hub返回的results对象内部已经把letterbox的padding和缩放映射回去了。我自己写落地方案时不会用torch.hub,因为每次启动都要检查网络;正确做法是用export.py把yolov5s.pt导出成torchscript或onnx,然后用torch.jit.load或onnxruntime加载。torch.hub只适合开发调试,部署时它需要联网或提前缓存权重。
3.2 openpose姿态关键点:从人体框裁剪还是全图推理,映射关系必须写对
OpenPose网络输入固定是368x368或656x368,如果直接把整帧1080p塞进去,下采样严重,人小一点关键点就是糊的。更稳的做法是用yolov5给的人体框把人抠出来,只对这个框做姿态估计。这个框会动态变化,所以还要动态计算缩放和偏移。
def estimate_pose(net, frame, box): x1, y1, x2, y2 = [int(v) for v in box[:4]] # 框向外扩展20%,给关键点留出边缘余量 h, w = frame.shape[:2] pad_x, pad_y = int((x2 - x1) * 0.2), int((y2 - y1) * 0.2) x1 = max(0, x1 - pad_x) y1 = max(0, y1 - pad_y) x2 = min(w, x2 + pad_x) y2 = min(h, y2 + pad_y) person = frame[y1:y2, x1:x2] blob = cv2.dnn.blobFromImage(person, 1.0 / 255, (368, 368), (127.5, 127.5, 127.5), swapRB=False) net.setInput(blob) heatmaps = net.forward()[0] # shape: (57, 46, 46),BODY_25前25个通道是关键点热图 # 找出每个关键点的最大响应位置,并映射回原图 keypoints = [] for i in range(25): heat = heatmaps[i] _, conf, _, point = cv2.minMaxLoc(heat) if conf < 0.2: keypoints.append((0, 0, conf)) continue # 热图尺寸是46x46,先映射到裁剪图尺寸,再加回左上角偏移 px = int(point[0] * person.shape[1] / heat.shape[1]) + x1 py = int(point[1] * person.shape[0] / heat.shape[0]) + y1 keypoints.append((px, py, conf)) return keypoints注意:blobFromImage 的 mean 值必须从 prototxt 的 mean_value 字段读取,手填会和模型训练配置不一致。
这段代码最关键的坑是坐标映射。net.forward输出的热图尺寸不是368x368,而是输入尺寸除以8,也就是46x46。很多人直接把热图坐标当成原图坐标,结果关键点全部挤在人物的左上角。这里用point[0]乘person.shape[1]/heat.shape[1]得到裁剪图内坐标,再加x1偏移。扩展20%是人脸遮挡、手部摆动时最常见的调优手段:不扩展的话,人体稍微侧身,手肘关键点就会被切出去。blobFromImage的mean值是127.5,这个必须和caffe模型的训练配置一致,改成ImageNet的mean会让人体关键点全部漂移。你要是不确定,直接查prototxt文件里的mean_value字段。
再讲一下为什么不在全图上跑openpose。除了慢,还有一个稳定性问题:全图里如果有两个人,openpose输出的关键点分组依赖PAF部分,很容易把两个人的肩膀互相连错。你只在单个人体框里跑,天然避开了不同人关键点匹配的纠葛。这也是这个组合方案相比纯openpose的一大优势:检测和姿态各司其职。yolov5负责把人分开,openpose只负责单人的骨骼细节。
4. 摔倒判定算法:不靠玄学,靠几何特征和阈值
4.1 关键点特征:中心点高度、躯干角度、速度突变
有了25个关键点,怎么判断摔倒?最直接的特征有三个:关键点平均高度、躯干倾角、关键点垂直方向速度。摔倒过程通常发生在0.5到1.5秒之间,表现是人体高度快速下降,同时躯干从接近垂直变成接近水平。如果只用高度下降,蹲下和坐下也会触发误报;如果只用角度,躺下休息或侧卧也会误报。所以落地系统一般把三个特征组合,再加一个时间窗确认。
有些人会问,为什么不用目标检测框的宽高比变化来判断?因为宽高比在弯腰捡东西、从床上坐起时同样会剧烈变化,而且远近距离也会影响宽高比。姿态关键点能更直接地描述人体是否保持竖直,这也是这套方案比纯目标检测更容易过验收的原因。
先定义特征计算。BODY_25的关键点编号中,0是鼻子,1是颈部,8是髋部中点,12是右髋,13是左髋。躯干倾角可以用颈部和髋部中点连成的线段与垂直轴的夹角,但要注意:坐着的夹角可能也有40度,要配合高度。我用的是归一化高度,也就是关键点平均高度除以当前人的身高估计值。这个身高估计值取“头到脚踝”的竖直方向距离,会比用坐标绝对像素稳定。
import numpy as np def fall_features(keypoints): # keypoints: list of (x, y, conf),数量25 kp = np.array(keypoints, dtype=np.float32) kp[kp[:, 2] < 0.2, :2] = 0 # 低置信度的点不参与计算 nose = kp[0, :2] neck = kp[1, :2] mid_hip = kp[8, :2] right_ankle = kp[15, :2] left_ankle = kp[16, :2] # 关键点平均高度:用鼻子、颈部、髋部的高度做平均 avg_y = (nose[1] + neck[1] + mid_hip[1]) / 3 # 躯干倾角:颈-髋向量与垂直轴(0, -1)的夹角 trunk_vec = mid_hip - neck if np.linalg.norm(trunk_vec) < 1: angle = 0.0 else: # 夹角公式,注意图像坐标系y向下,垂直方向是(0, -1) cos_angle = abs(trunk_vec[1]) / np.linalg.norm(trunk_vec) angle = np.degrees(np.arccos(np.clip(cos_angle, -1, 1))) # 参考高度:用颈到踝的竖直距离,作为衡量高度下降的标尺 ankle_y = (left_ankle[1] + right_ankle[1]) / 2 ref_height = max(1, abs(ankle_y - neck[1])) # 归一化平均高度:0表示人平躺,1表示站立 norm_height = max(0.0, min(1.0, (ankle_y - avg_y) / ref_height)) return norm_height, angle这里我把norm_height定义成一个0到1的值。站立时鼻、颈、髋的平均位置接近颈部,ankle_y减去avg_y基本等于ref_height,所以归一化高度接近1。平躺时三个关键点的y都接近地面,ankle_y减去avg_y接近0,norm_height接近0。为什么要用“踝关节在地面”作参照而不是直接用绝对像素高度?因为摄像头远近和分辨率会让绝对高度在不同距离下差很多,归一化后跨距离可比。角度部分要小心图像坐标系:y轴向下,trunk_vec[1]是负数时表示髋在下、颈在上,cos_angle取绝对值后对站和躺都一样能算。这个特征描述的是躯干偏离垂直的程度,不是倒地方向,所以前后倒都行。
4.2 判定逻辑与参数设定:把阈值写成可调的超参数,别写死在代码里
有了每帧的norm_height和angle,还不能单帧判断。摔倒有一个关键特征:短时间内的突发变化。坐下和蹲下也是高度下降,但速度比摔倒慢,且躯干角度未必超过60度。所以我的判定逻辑是滑动窗口内同时满足三个条件:norm_height从高点快速下降到低于阈值,angle超过阈值,变化发生在1秒内。
class FallDetector: def __init__(self, height_thresh=0.3, angle_thresh=45, speed_thresh=0.4, win_size=10): self.height_thresh = height_thresh self.angle_thresh = angle_thresh self.speed_thresh = speed_thresh self.win_size = win_size self.history = [] # 存 (norm_height, angle) def update(self, norm_height, angle): self.history.append((norm_height, angle)) if len(self.history) > self.win_size: self.history.pop(0) if len(self.history) < self.win_size: return False # 用窗口内最高点和最低点的差异衡量速度 heights = [h for h, _ in self.history] drop = max(heights) - min(heights) # 用窗口最后两帧的平均角度看是否接近水平 avg_angle = sum(a for _, a in self.history[-3:]) / 3 if drop >= self.speed_thresh and min(heights) <= self.height_thresh and avg_angle >= self.angle_thresh: return True return False fall = FallDetector()参数说明:height_thresh是归一化高度阈值,我常用0.3,意思是人体中心高度掉到站立的30%以下。如果你只监控躺着休息的床位区,这个阈值要调低,否则人正常躺下会被判摔倒。angle_thresh用45度,是因为坐姿的躯干倾角通常在30度以下,摔倒时一般会超过45度。speed_thresh用0.4,表示在10帧窗口内高度变化超过40%,这能过滤掉慢慢坐下的情况。win_size要根据帧率设:视频是15fps,10帧是0.67秒;视频是30fps,win_size应该调到16到20,保证窗口覆盖1秒的时间跨度。这些阈值就和yolov5超参数一样,是需要对你实际场景样本反复调的,没有一套全局最优值。
如果窗口内先下降、又站起来,history会丢失最高点,导致drop被低估。所以更稳的写法是维护一个“最近1秒内最大高度”的记忆,不随窗口滑动丢掉。这个我在实际项目里加过,确实减少了扶老人起身时的误报。另外,检测到摔倒后应该再等3到5帧确认,不要立刻触发报警,因为摄像头抖动和人体自然晃动都可能造成一帧虚假特征。
还有一点和yolov5的送检逻辑相关:多人画面里每个人都要单独维护一个FallDetector实例,不能把两个人的关键点混在一组特征里。最简单的方法是用IoU把连续帧的人体框关联起来,再按检测框的id去更新历史。没有人框时,先不更新窗口,避免把空白帧也计入高度变化。跟踪闭环后,摔倒判定自然会从单帧报警变成时间序列报警。
5. 踩坑与排查:环境、模型、映射、阈值,五个最容易翻车的地方
5.1 openpose 在 CPU 上慢到没法实时,怎么救?
现象是视频画面卡到1秒只出两三帧,CPU风扇狂转,GPU显存却没用上。原因是OpenCV DNN默认用CPU,而BODY_25的caffemodel本身是VGG风格的大网络,如果还按368x368全图推理,时间全耗在卷积上。解决时我一般分三步:先用yolov5的框裁剪后再输入openpose,避开全图;再把输入分辨率从368x368降到288x288,大骨架点基本不受影响;然后启用GPU,把后端换成DNN_BACKEND_CUDA。以上都不满足时,就隔帧跑openpose,用检测框的连续变化先粗筛,确认高度突然下降后再触发一次单帧姿态估计,这个先粗筛后精检的思路在部署部分会再续。
5.2 yolov5 检测不到人,或把椅背、海报当成人
现象是摄像头对着走廊,空旷场景经常漏检;对着办公室,椅背频繁误检成person。原因是官方yolov5s的coco训练集以自然场景为主,监控视角、夜间红外、画面压缩都会导致分布偏移。高背椅的轮廓和站立的人体下半身相似,所以误检。解决时先拿现场样本批量跑detect.py,把漏检和误检截图留下来,挑几百张做微调。如果暂时不想训练,就调model.conf:误检多提高到0.5到0.6,漏检多降到0.3。但要清楚,conf降得越低,后面openpose处理的无意义框就越多。从部署角度,我倾向训练自己的数据集,一次投入长期受益。
5.3 坐下、蹲下被误判成摔倒,关键是时间窗口
现象是测试视频里人慢慢坐到沙发上,系统报了摔倒。原因是单帧特征满足了高度和角度阈值,但坐下的速度远低于摔倒,FallDetector的speed_thresh没拦住。解决时把判断从单帧改成滑动窗口,用窗口内最大高度和最小高度的差作为速度度量,然后调高speed_thresh;同时注意坐着时norm_height通常不会降到0.3以下,所以height_thresh可以结合“需持续0.5秒”的条件。窗口不要设太长,否则真摔倒后1秒才报警,失去了预警价值。
5.4 关键点映射错位:底座在跑,骨架画在墙上
现象是yolov5框定位准确,但openpose画出的骨架和人体错位,越靠近画面边缘越严重。原因是热图坐标没有按网络下采样倍率换算,或者忘了加裁剪框偏移;另一个常见原因是blobFromImage的mean参数和prototxt不一致,导致热图整体漂移。解决时按第3.2节的代码走,用heat.shape映射比例而不是硬编码尺寸;把mean_value写成从prototxt读取,避免手填。如果发现只有下边界错位,多半是yolov5的框在裁剪时越界,记得先做min/max clip。开发阶段建议把关键点实时画出来看,别等报警才看图。
5.5 摄像头斜装,角度和高度全部失真
现象是摄像头装在墙角斜着俯拍,人躺下时躯干角度只有20度,摔倒不报警。原因是单目相机无法还原三维姿态,斜装时图像上的“垂直”不等于实际重力方向。解决时优先把摄像头正对活动区域,高度不超过2米,俯角不超过30度;如果必须装在高处,就做相机标定,把图像坐标映射到地面坐标系再算角度。实在不行,把高度下降作为主判据,角度只做辅助,因为倒地后关键点的y坐标接近地面,站姿的y坐标在图像上仍然较高。卫生间这种必须高装的位置,纯2D方案的误报率会明显偏高,需要接受误报或换带人形框的雷达。
6. 最后一步:把摔倒检测做成能实时运行的部署方案
6.1 用 frame skipping 和检测结果缓存把帧率提上来
整套管线最贵的就是openpose。我的习惯是设计一个两级调度:yolov5每帧都跑,因为它相对快;openpose只在“人框高度变化异常”的帧才跑。实现时用一个简单的粗筛,输入先用yolov5人框底部坐标的变化,高度快速下降就触发一次openpose细判。日常不触发时完全不做姿态估计,CPU占用立刻降下来。如果你要在树莓派5上部署自己训练的yolov5模型,这个策略几乎是必须的:yolov5可以导出成ONNX用ONNXRuntime跑,openpose只在报警前瞬间启动。
下面是主循环的简化版:
cap = cv2.VideoCapture("fall.mp4") fall = FallDetector() # 假设yolo_model和openpose_net已经加载 while True: ret, frame = cap.read() if not ret: break results = yolo_model(frame) boxes = results.pandas().xyxy[0] person = boxes[boxes["class"] == 0].head(1) if not person.empty: box = person.iloc[0][["x1", "y1", "x2", "y2"]].values keypoints = estimate_pose(openpose_net, frame, box) norm_h, angle = fall_features(keypoints) is_fall = fall.update(norm_h, angle) if is_fall: cv2.putText(frame, "FALL", (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3) cv2.imshow("fall", frame) if cv2.waitKey(1) == 27: break这个代码把openpose放在每帧里跑,实际部署时要把estimate_pose调用包在一个条件判断里:只有最近3帧人框底部y坐标变化超过阈值,才去做姿态估计。这样做的原因是摔倒通常伴随人体框底部快速下落,如果这个粗筛没通过,大概率不是摔倒,就不必为它付openpose的算力账。用head(1)只处理画面里最靠前的人,避免多人同时触发;要处理多人场景,就把这一步改成循环并对每个人维护一个FallDetector实例。
6.2 验证方法:用正负样本视频逼出阈值问题
别拿一段躺下的视频测一遍就宣布完工。我习惯准备三份素材:摔倒视频、坐下/蹲下视频、正常行走视频,各5到10段。对每段统计系统输出结果,计算召回率和误报率。调参时先定height_thresh,再用angle_thresh调误报,最后用speed_thresh调“慢慢倒下”的漏报。每次调整都在三份素材上全部重跑,因为阈值互相影响。这也是我踩坑最多的地方:原来只在一段视频上调参,换场景后误报率翻倍,后来固定用三份素材回归才算稳定。
至于这个方向值不值得做,我的答案是值得,但要看清楚自己手里有什么数据。如果你只有CPU,先按上面的两级调度把流程跑通,再用GPU加速;如果要商业落地,一定要做摔倒后的连续确认和报警延后,避免误报消耗安保人力。我自己的习惯是把判决阈值放在服务端配置文件里,而不是写死在代码中,这样现场部署时不用改代码重新编译,只需调参数重启服务。这个习惯救过我不少次,希望帮到你。
本文还有配套的精品资源,点击获取