未验证 提交 54b828a8 编写于 作者: XYZ_916's avatar XYZ_916 提交者: GitHub

add fight recognition docs to "deploy/pphuman/docs" (#6235)

* add fight recognition docs

* add fight recognition tool file : split_fight_train_test_dataset.py

* fight recognition quick start and develop documents

* add solution selection table for action recognition.

* add fight recognition case AI Studio link
上级 dfee2ed8
......@@ -440,6 +440,8 @@
- [基于人体关键点检测的合规检测](https://aistudio.baidu.com/aistudio/projectdetail/4061642?contributionType=1)
- [打架识别](https://aistudio.baidu.com/aistudio/projectdetail/4086987?contributionType=1)
## <img title="" src="https://user-images.githubusercontent.com/48054808/157836473-1cf451fa-f01f-4148-ba68-b6d06d5da2f9.png" alt="" width="20"> 应用案例
- [安卓健身APP](https://github.com/zhiboniu/pose_demo_android)
......
......@@ -54,6 +54,7 @@ PP-Human支持图片/单镜头视频/多镜头视频多种输入方式,功能
* [快速开始](docs/tutorials/action.md)
* 摔倒检测
* 打架识别
* [二次开发教程](../../docs/advanced_tutorials/customization/action.md)
* 方案选择
* 数据准备
......
......@@ -2,21 +2,23 @@
# PP-Human行为识别模块
行为识别在智慧社区,安防监控等方向具有广泛应用,PP-Human中集成了基于骨骼点的行为识别模块。
行为识别在智慧社区,安防监控等方向具有广泛应用,PP-Human中集成了基于骨骼点的行为识别模块、基于视频分类的打架识别模块。
## 摔倒识别
<div align="center">
<img src="../images/action.gif" width='1000'/>
<center>数据来源及版权归属:天覆科技,感谢提供并开源实际场景数据,仅限学术研究使用</center>
</div>
## 模型库
### 模型库
在这里,我们提供了检测/跟踪、关键点识别以及识别摔倒动作的预训练模型,用户可以直接下载使用。
| 任务 | 算法 | 精度 | 预测速度(ms) | 模型权重 | 预测部署模型 |
|:---------------------|:---------:|:------:|:------:| :------: |:---------------------------------------------------------------------------------: |
| 行人检测/跟踪 | PP-YOLOE | mAP: 56.3 <br> MOTA: 72.0 | 检测: 28ms <br> 跟踪:33.1ms |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.pdparams) |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip) |
| 关键点识别 | HRNet | AP: 87.1 | 单人 2.9ms |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/dark_hrnet_w32_256x192.pdparams) |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/dark_hrnet_w32_256x192.zip)|
| 行为识别 | ST-GCN | 准确率: 96.43 | 单人 2.7ms | - |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/STGCN.zip) |
| 摔倒识别 | ST-GCN | 准确率: 96.43 | 单人 2.7ms | - |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/STGCN.zip) |
注:
......@@ -25,8 +27,9 @@
3. 行为识别模型使用[NTU-RGB+D](https://rose1.ntu.edu.sg/dataset/actionRecognition/)[UR Fall Detection Dataset](http://fenix.univ.rzeszow.pl/~mkepski/ds/uf.html)和部分业务数据融合训练,精度在业务数据测试集上得到。
4. 预测速度为NVIDIA T4 机器上使用TensorRT FP16时的速度, 速度包含数据预处理、模型预测、后处理全流程。
### 配置说明
## 配置说明
[配置文件](../config/infer_cfg_pphuman.yml)中与行为识别相关的参数如下:
[配置文件](../../config/infer_cfg_pphuman.yml)中与行为识别相关的参数如下:
```
SKELETON_ACTION:
model_dir: output_inference/STGCN # 模型所在路径
......@@ -38,7 +41,7 @@ SKELETON_ACTION:
enable: False #是否开启该功能
```
## 使用方法
### 使用方法
1. 从上表链接中下载模型并解压到```./output_inference```路径下。
2. 目前行为识别模块仅支持视频输入,设置infer_cfg_pphuman.yml中`SKELETON_ACTION`的enable: True, 然后启动命令如下:
```python
......@@ -57,7 +60,7 @@ python deploy/pphuman/pipeline.py --config deploy/pphuman/config/infer_cfg_pphum
--model_dir kpt=./dark_hrnet_w32_256x192 action=./STGCN
```
## 方案说明
### 方案说明
1. 使用目标检测与多目标跟踪获取视频输入中的行人检测框及跟踪ID序号,模型方案为PP-YOLOE,详细文档参考[PP-YOLOE](../../../configs/ppyoloe/README_cn.md)
2. 通过行人检测框的坐标在输入视频的对应帧中截取每个行人,并使用[关键点识别模型](../../../configs/keypoint/hrnet/dark_hrnet_w32_256x192.yml)得到对应的17个骨骼特征点。骨骼特征点的顺序及类型与COCO一致,详见[如何准备关键点数据集](../../../docs/tutorials/PrepareKeypointDataSet_cn.md)中的`COCO数据集`部分。
3. 每个跟踪ID对应的目标行人各自累计骨骼特征点结果,组成该人物的时序关键点序列。当累计到预定帧数或跟踪丢失后,使用行为识别模型判断时序关键点序列的动作类型。当前版本模型支持摔倒行为的识别,预测得到的`class id`对应关系为:
......@@ -67,7 +70,7 @@ python deploy/pphuman/pipeline.py --config deploy/pphuman/config/infer_cfg_pphum
```
4. 行为识别模型使用了[ST-GCN](https://arxiv.org/abs/1801.07455),并基于[PaddleVideo](https://github.com/PaddlePaddle/PaddleVideo/blob/develop/docs/zh-CN/model_zoo/recognition/stgcn.md)套件完成模型训练。
## 自定义模型训练
### 自定义模型训练
我们已经提供了检测/跟踪、关键点识别以及识别摔倒动作的预训练模型,可直接下载使用。如果希望使用自定义场景数据训练,或是对模型进行优化,根据具体模型,分别参考下面的链接:
| 任务 | 算法 | 模型训练及导出文档 |
| ---- | ---- | -------- |
......@@ -75,6 +78,42 @@ python deploy/pphuman/pipeline.py --config deploy/pphuman/config/infer_cfg_pphum
| 关键点识别 | HRNet | [使用教程](../../../configs/keypoint#3训练与测试) |
| 行为识别 | ST-GCN | [使用教程](https://github.com/PaddlePaddle/PaddleVideo/tree/develop/applications/PPHuman) |
## 打架识别
随着监控摄像头部署覆盖范围越来越广,人工查看是否存在打架等异常行为耗时费力、效率低,AI+安防助理智慧安防。PP-Human中集成了打架识别模块,识别视频中是否存在打架行为。我们提供了预训练模型,用户可直接下载使用。
| 任务 | 算法 | 精度 | 预测速度(ms) | 模型权重 | 预测部署模型 |
| ---- | ---- | ---------- | ---- | ---- | ---------- |
| 打架识别 | PP-TSM | 准确率:89.06% | T4, 2s视频128ms | [下载链接](https://videotag.bj.bcebos.com/PaddleVideo-release2.3/ppTSM_fight.pdparams) | [下载链接](https://videotag.bj.bcebos.com/PaddleVideo-release2.3/ppTSM_fight.zip) |
打架识别模型基于6个公开数据集训练得到:Surveillance Camera Fight Dataset、A Dataset for Automatic Violence Detection in Videos、Hockey Fight Detection Dataset、Video Fight Detection Dataset、Real Life Violence Situations Dataset、UBI Abnormal Event Detection Dataset。
本项目关注的场景为监控摄像头下的打架行为识别。打架行为涉及多人,基于骨骼点技术的方案更适用于单人的行为识别。此外,打架行为对时序信息依赖较强,基于检测和分类的方案也不太适用。由于监控场景背景复杂,人的密集程度、光线、拍摄角度等都会对识别造成影响,本方案采用基于视频分类的方式判断视频中是否存在打架行为。针对摄像头距离人较远的情况,通过增大输入图像分辨率优化。由于训练数据有限,采用数据增强的方式提升模型的泛化性能。
### 使用方法
1. 从上表链接中下载预测部署模型并解压到`./output_inference`路径下;
2. 修改解压后`ppTSM`文件夹中的文件名称为`model.pdiparams、model.pdiparams.info和model.pdmodel`
3. 修改配置文件`deploy/pphuman/config/infer_cfg_pphuman.yml``VIDEO_ACTION`下的`enable``True`
4. 输入视频,启动命令如下:
```
python deploy/pphuman/pipeline.py --config deploy/pphuman/config/infer_cfg_pphuman.yml \
--video_file=test_video.mp4 \
--device=gpu
```
测试效果如下:
<div width="1000" align="center">
<img src="../images/fight_demo.gif"/>
</div>
数据来源及版权归属:Surveillance Camera Fight Dataset。
### 方案说明
目前打架识别模型使用的是[PP-TSM](https://github.com/PaddlePaddle/PaddleVideo/blob/develop/docs/zh-CN/model_zoo/recognition/pp-tsm.md),并在PP-TSM视频分类模型训练流程的基础上修改适配,完成模型训练。对于输入的视频或者视频流,进行等间隔抽帧,当视频帧累计到指定数目时,输入到视频分类模型中判断是否存在打架行为。
## 参考文献
```
@inproceedings{stgcn2018aaai,
......
import cv2
def cut_video(video_path, frameToStart, frametoStop, saved_video_path):
cap = cv2.VideoCapture(video_path)
FPS = cap.get(cv2.CAP_PROP_FPS)
TOTAL_FRAME = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 获取视频总帧数
size = (cap.get(cv2.CAP_PROP_FRAME_WIDTH),
cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
videoWriter = cv2.VideoWriter(
saved_video_path,
apiPreference=0,
fourcc=cv2.VideoWriter_fourcc(* 'mp4v'),
fps=FPS,
frameSize=(int(size[0]), int(size[1])))
COUNT = 0
while True:
success, frame = cap.read()
if success:
COUNT += 1
if COUNT <= frametoStop and COUNT > frameToStart: # 选取起始帧
videoWriter.write(frame)
else:
print("cap.read failed!")
break
if COUNT > frametoStop:
break
cap.release()
videoWriter.release()
print(saved_video_path)
import os
import glob
import random
import fnmatch
import re
import sys
class_id = {"nofight": 0, "fight": 1}
def get_list(path, key_func=lambda x: x[-11:], rgb_prefix='img_', level=1):
if level == 1:
frame_folders = glob.glob(os.path.join(path, '*'))
elif level == 2:
frame_folders = glob.glob(os.path.join(path, '*', '*'))
else:
raise ValueError('level can be only 1 or 2')
def count_files(directory):
lst = os.listdir(directory)
cnt = len(fnmatch.filter(lst, rgb_prefix + '*'))
return cnt
# check RGB
video_dict = {}
for f in frame_folders:
cnt = count_files(f)
k = key_func(f)
if level == 2:
k = k.split("/")[0]
video_dict[f] = str(cnt) + " " + str(class_id[k])
return video_dict
def fight_splits(video_dict, train_percent=0.8):
videos = list(video_dict.keys())
train_num = int(len(videos) * train_percent)
train_list = []
val_list = []
random.shuffle(videos)
for i in range(train_num):
train_list.append(videos[i] + " " + str(video_dict[videos[i]]))
for i in range(train_num, len(videos)):
val_list.append(videos[i] + " " + str(video_dict[videos[i]]))
print("train:", len(train_list), ",val:", len(val_list))
with open("fight_train_list.txt", "w") as f:
for item in train_list:
f.write(item + "\n")
with open("fight_val_list.txt", "w") as f:
for item in val_list:
f.write(item + "\n")
if __name__ == "__main__":
frame_dir = sys.argv[1] # "rawframes"
level = sys.argv[2] # 2
train_percent = sys.argv[3] # 0.8
if level == 2:
def key_func(x):
return '/'.join(x.split('/')[-2:])
else:
def key_func(x):
return x.split('/')[-1]
video_dict = get_list(frame_dir, key_func=key_func, level=level)
print("number:", len(video_dict))
fight_splits(video_dict, train_percent)
......@@ -2,12 +2,140 @@
## 方案选择
行为识别常用的技术有检测技术、骨骼点技术、分类技术等,不同技术方案的优劣势和适用场景如下:
| 技术方案 | 方案说明 | 方案优势 | 方案劣势 | 适用场景 |
| :--: | :--: | :--: | :--: | :--: |
| 基于人体骨骼点的行为识别 | 1. 通过目标检测技术识别出图像中的人;<br> 2. 针对每个人,基于关键点检测技术识别出关键点;<br>3. 基于关键点序列变化识别出具体行为。 | 1. 可识别出每个人的行为;<br>2. 聚焦动作本身,鲁棒性和泛化性好; | 1. 对关键点检测依赖较强,人员较密集或存在遮挡等情况效果不佳;<br>2. 无法准确识别多人交互动作;<br>3. 难以处理需要外观及场景信息的动作;<br>4. 数据收集和标注困难; | 适用于根据人体结构关键点能够区分的行为,背景简单,人数不多场景,如健身场景。 |
| 基于人体id的分类 | 1. 通过目标检测技术得到图像中的人;<br>2. 针对每个人通过图像分类技术得到具体的行为类别。 | 1.通过检测技术可以为分类剔除无关背景的干扰,提升最终识别精度;<br>2. 方案简单,易于训练;<br>3. 数据采集容易;<br>4. 可结合跳帧及结果复用逻辑,速度快; | 1. 缺少时序信息;<br>2. 精度不高; | 对时序信息要求不强的动作,且动作既可通过人也可通过人+物的方式判断,如打电话。 |
| 基于人体id的检测 | 1. 通过目标检测技术得到画面中的人;<br>2. 根据检测结果将人物从原图中抠出,再在扣得的图像中再次用目标检测技术检测与行为强相关的目标。 | 1. 方案简单,易于训练;<br> 2. 可解释性强;<br> 3. 数据采集容易;<br> 4. 可结合跳帧及结果复用逻辑,速度快; | 1. 缺少时序信息;<br>2. 分辨率较低情况下效果不佳;<br> 3. 密集场景容易发生动作误匹配 | 行为与某特定目标强相关的场景,且目标较小,需要两级检测才能准确定位,如吸烟。 |
| 基于视频分类的行为识别 | 应用视频分类技术对整个视频场景进行分类。 | 1.充分利用背景上下文和时序信息;<br>2. 可利用语音、字幕等多模态信息;<br>3. 不依赖检测及跟踪模型;<br>4. 可处理多人共同组成的动作; | 1. 无法定位到具体某个人的行为;<br>2. 场景泛化能力较弱;<br>3.真实数据采集困难; | 无需具体到人的场景的判定,即判断是否存在某种特定行为,多人或对背景依赖较强的动作,如监控画面中打架识别等场景。 |
## 数据准备
### 视频分类数据准备
视频分类任务输入的视频格式一般为`.mp4``.avi`等格式视频或者是抽帧后的视频帧序列,标签则可以是`.txt`格式存储的文件。
对于打架识别任务,具体数据准备流程如下:
#### 数据集下载
打架识别基于6个公开的打架、暴力行为相关数据集合并后的数据进行模型训练。公开数据集具体信息如下:
| 数据集 | 下载连接 | 简介 | 标注 | 数量 | 时长 |
| ---- | ---- | ---------- | ---- | ---- | ---------- |
| Surveillance Camera Fight Dataset| https://github.com/sayibet/fight-detection-surv-dataset | 裁剪视频,监控视角 | 视频级别 | 打架:150;非打架:150 | 2s |
| A Dataset for Automatic Violence Detection in Videos | https://github.com/airtlab/A-Dataset-for-Automatic-Violence-Detection-in-Videos | 裁剪视频,室内自行录制 | 视频级别 | 暴力行为:115个场景,2个机位,共230 ;非暴力行为:60个场景,2个机位,共120 | 几秒钟 |
| Hockey Fight Detection Dataset | https://www.kaggle.com/datasets/yassershrief/hockey-fight-vidoes?resource=download | 裁剪视频,非真实场景 | 视频级别 | 打架:500;非打架:500 | 2s |
| Video Fight Detection Dataset | https://www.kaggle.com/datasets/naveenk903/movies-fight-detection-dataset | 裁剪视频,非真实场景 | 视频级别 | 打架:100;非打架:101 | 2s |
| Real Life Violence Situations Dataset | https://www.kaggle.com/datasets/mohamedmustafa/real-life-violence-situations-dataset | 裁剪视频,非真实场景 | 视频级别 | 暴力行为:1000;非暴力行为:1000 | 几秒钟 |
| UBI Abnormal Event Detection Dataset| http://socia-lab.di.ubi.pt/EventDetection/ | 未裁剪视频,监控视角 | 帧级别 | 打架:216;非打架:784;裁剪后二次标注:打架1976,非打架1630 | 原视频几秒到几分钟不等,裁剪后2s |
打架(暴力行为)视频3956个,非打架(非暴力行为)视频3501个,共7457个视频,每个视频几秒钟。
#### 视频抽帧
为了加快训练速度,将视频进行抽帧。下面命令会根据视频的帧率FPS进行抽帧,如FPS=30,则每秒视频会抽取30帧图像。
```bash
cd ${PaddleVideo_root}
python data/ucf101/extract_rawframes.py dataset/ rawframes/ --level 2 --ext mp4
```
其中,视频存放在`dataset`目录下,打架(暴力)视频存放在`dataset/fight`中;非打架(非暴力)视频存放在`dataset/nofight`中。`rawframes`目录存放抽取的视频帧。
#### 训练集和验证集划分
打架识别验证集1500条,来自Surveillance Camera Fight Dataset、A Dataset for Automatic Violence Detection in Videos、UBI Abnormal Event Detection Dataset三个数据集。
也可根据下面的命令将数据按照8:2的比例划分成训练集和测试集:
```bash
python split_fight_train_test_dataset.py "rawframes" 2 0.8
```
参数说明:“rawframes”为视频帧存放的文件夹;2表示目录结构为两级,第二级表示每个行为对应的子文件夹;0.8表示训练集比例。
其中`split_fight_train_test_dataset.py`文件在`deploy/pphuman/tools`路径下。
执行完命令后会最终生成fight_train_list.txt和fight_val_list.txt两个文件。打架的标签为1,非打架的标签为0。
#### 视频裁剪
对于未裁剪的视频,需要先进行裁剪才能用于模型训练,`deploy/pphuman/tools/clip_video.py`中给出了视频裁剪的函数`cut_video`,输入为视频路径,裁剪的起始帧和结束帧以及裁剪后的视频保存路径。
## 模型优化
### 1. 摔倒--基于关键点的行为识别方案
### 2. 打架--基于视频分类的行为识别方案
#### VideoMix
[VideoMix](https://arxiv.org/abs/2012.03457)是视频数据增强的方法之一,是对图像数据增强CutMix的扩展,可以缓解模型的过拟合问题。
与Mixup将两个视频片段的每个像素点按照一定比例融合不同的是,VideoMix是每个像素点要么属于片段A要么属于片段B。输出结果是两个片段原始标签的加权和,权重是两个片段各自的比例。
在baseline的基础上加入VideoMix数据增强后,精度由87.53%提升至88.01%。
#### 更大的分辨率
由于监控摄像头角度、距离等问题,存在监控画面下人比较小的情况,小目标行为的识别较困难,尝试增大输入图像的分辨率,模型精度由88.01%提升至89.06%。
## 新增行为
### 1. 基于关键点的行为识别方案
### 2. 基于视频分类的行为识别方案
目前打架识别模型使用的是[PaddleVideo](https://github.com/PaddlePaddle/PaddleVideo)套件中[PP-TSM](https://github.com/PaddlePaddle/PaddleVideo/blob/develop/docs/zh-CN/model_zoo/recognition/pp-tsm.md),并在PP-TSM视频分类模型训练流程的基础上修改适配,完成模型训练。
请先参考[使用说明](https://github.com/PaddlePaddle/PaddleVideo/blob/develop/docs/zh-CN/usage.md)了解PaddleVideo模型库的使用。
| 任务 | 算法 | 精度 | 预测速度(ms) | 模型权重 | 预测部署模型 |
| ---- | ---- | ---------- | ---- | ---- | ---------- |
| 打架识别 | PP-TSM | 准确率:89.06% | T4, 2s视频128ms | [下载链接](https://videotag.bj.bcebos.com/PaddleVideo-release2.3/ppTSM_fight.pdparams) | [下载链接](https://videotag.bj.bcebos.com/PaddleVideo-release2.3/ppTSM_fight.zip) |
#### 模型训练
下载预训练模型:
```bash
wget https://videotag.bj.bcebos.com/PaddleVideo/PretrainModel/ResNet50_vd_ssld_v2_pretrained.pdparams
```
执行训练:
```bash
# 单卡训练
cd ${PaddleVideo_root}
python main.py --validate -c pptsm_fight_frames_dense.yaml
```
本方案针对的是视频的二分类问题,如果不是二分类,需要修改配置文件中`MODEL-->head-->num_classes`为具体的类别数目。
```bash
cd ${PaddleVideo_root}
# 多卡训练
export CUDA_VISIBLE_DEVICES=0,1,2,3
python -B -m paddle.distributed.launch --gpus=“0,1,2,3” \
--log_dir=log_pptsm_dense main.py --validate \
-c pptsm_fight_frames_dense.yaml
```
#### 模型评估
训练好的模型下载:[https://videotag.bj.bcebos.com/PaddleVideo-release2.3/ppTSM_fight.pdparams](https://videotag.bj.bcebos.com/PaddleVideo-release2.3/ppTSM_fight.pdparams)
模型评估:
```bash
cd ${PaddleVideo_root}
python main.py --test -c pptsm_fight_frames_dense.yaml \
-w ppTSM_fight_best.pdparams
```
其中`ppTSM_fight_best.pdparams`为训练好的模型。
#### 模型导出
导出inference模型:
```bash
cd ${PaddleVideo_root}
python tools/export_model.py -c pptsm_fight_frames_dense.yaml \
-p ppTSM_fight_best.pdparams \
-o inference/ppTSM
```
......@@ -23,5 +23,7 @@
- [基于PP-PicoDetv2 的路面垃圾检测](https://aistudio.baidu.com/aistudio/projectdetail/3846170?channelType=0&channel=0)
- [基于人体关键点检测的合规检测](https://aistudio.baidu.com/aistudio/projectdetail/4061642?contributionType=1)
- [打架识别](https://aistudio.baidu.com/aistudio/projectdetail/4086987?contributionType=1)
*范例将持续更新中
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册