├── Note ├── other │ ├── 异常行为检测.md │ └── 行人检测算法.md ├── pic │ ├── 3.png │ ├── HOG.jpg │ ├── Haar.png │ ├── IDT.png │ ├── 人脸异常行为检测.png │ ├── 光流法.png │ ├── 帧差法.png │ ├── 级联分类器.jpg │ ├── 背景差分法.png │ ├── 行为识别.png │ ├── 行为识别01.png │ ├── 行为识别02.png │ ├── 行为识别03.png │ └── 运动目标检测比较.jpg ├── 目标检测.md ├── 行为识别.md ├── 视频行为识别.md └── 运动目标检测.md ├── Paper ├── 基于ATM机的用户异常行为识别的研究_宋丙菊.caj └── 基于深度学习的人体行为识别技术的研究与应用_刘潇.caj ├── README.md └── Src ├── videoFrameDifference.py ├── videoFrameDifferenceCopy.py └── videoOpencv.py /Note/other/异常行为检测.md: -------------------------------------------------------------------------------- 1 | 一般需求四个环节: 2 | * 目标检测 特征提取 行为识别 异常判断 3 | 4 | 5 | 图像预处理: 有噪声 6 | 7 | 颜色空间转换 图像滤波 形态学算子 8 | 9 | 10 | 目标提取 : 11 | 12 | 侦差法 光流法 混合多高斯背景建模算法 ViBe算法 13 | 14 | ATM内背景不随时间变化,主要因素是光照: 背景差分法 15 | 16 | 17 | ATM: 嵌入式系统 18 | 19 | 20 | 21 | 22 | 深度学习 23 | 24 | 2D-CNN 行为识别 25 | 26 | 3D卷积神经网络: 视频人行为变化具有连续性 27 | 28 | 29 | 30 | 目标检测 目标跟踪 目标分类 目标行为识别 31 | 32 | 33 | 视频运动目提取: 34 | 侦差法 光流法 混合多高斯背景建模算法 ViBe算法 35 | 36 | 视频运动目标跟踪 37 | 基于区域 基于特征 基于模型 基于活动轮廓 38 | 39 | 算法实时性 ATM单个人体出现遮挡可能性较小 改进Hu特征提取 采用Mean-shift 跟踪算法 40 | 41 | 异常行为识别 42 | 隐马尔科夫模型 43 | 44 | 人脸: 蒙面 遮挡 45 | 预先定义异常行为语义 46 | 获取: 全局监控摄像头 47 | 48 | 整体: 手拿异物 跑 下蹲 49 | 训练测试各个样本 判断异常行为 50 | 获取: ATM机正对人脸的摄像头 51 | 52 | 53 | 54 | 55 | 56 | ## 目标检测 57 | 58 | ### 人脸对象: 59 | 颜色空间: 目的: 获取颜色信息 60 | 方法: RGB(三种分量混杂一起 不利于肤色分割) 61 | HSV (表达形式复杂,实时性) 62 | YCbCr(肤色聚类性比较好) 63 | 64 | 二值图像处理: 目的: 去噪 65 | 方法: 数学形态学 66 | 67 | 人脸检测肤色模型选择: 基于椭圆肤色模型: 实时性好点 68 | 基于高斯模型 : 计算量大 实时性差 69 | 70 | 71 | 72 | 人脸检测的方法: 基于先验知识的肤色检测方法 基于模板的方法 基于统计的学习方法 73 | 肤色提取的优点: 速度快 姿态不变性 74 | 75 | 76 | ### 人体对象 77 | 光流法: 主要采用了运动目标随时间变化的光流特性 78 | 缺点: 受噪声 多光源 遮挡影响 计算复杂 抗燥性差 79 | 80 | 侦差法: 81 | 计算简单 实时性比较好 对背景光照变化不敏感 适应性强 82 | 83 | 背景差分法: 主流方法 84 | 实现简单 实时性好 相对于侦差法能够得到较完整的目标特征 适用于摄像机静止的情况 85 | 缺点: 随着时间推移 会出现许多伪目标点 86 | 87 | 88 | 自适应高斯背景模型 89 | 利用静止摄像机采集的背景图像 会随着时间推移发生变化 90 | 因此 采用背景差分 需要建立背景模型 不断更新背景图像 适应这种背景变化 91 | 92 | 93 | 94 | 95 | ## 目标跟踪 96 | 97 | ### 特征选择与提取 98 | Hu矩特征: 在提取人体行为特征时具有很好的平移 缩放 旋转不变性和抗干扰性 99 | 改进Hu矩: 中心距越大 越反应的细节越多 对噪声就会越敏感 100 | 101 | ### 目标跟踪方法 102 | 粒子滤波跟踪: 计算过程复杂 实时性差 103 | Mean-shift: 实时性好 对遮挡 目标变形鲁棒性好 104 | 105 | 106 | 107 | ## 异常行为识别 108 | 行为识别方法: 109 | 基于模板匹配的静态识别方法: 110 | 计算简单 但缺乏动态特性 对于噪声和运动时间间隔变化敏感 111 | 112 | 基于概率统计的动态识别法: 隐马尔可夫模型HMM 支持向量机SVM 动态贝叶斯网络 神经网络等 113 | 114 | 115 | 116 |
117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /Note/other/行人检测算法.md: -------------------------------------------------------------------------------- 1 | 行人检测要解决的主要难题是: 2 | * 外观差异大。包括视角,姿态,服饰和附着物,光照,成像距离等。从不同的角度看过去,行人的外观是很不一样的。处于不同姿态的行人,外观差异也很大。由于人穿的衣服不同,以及打伞、戴帽子、戴围巾、提行李等附着物的影响,外观差异也非常大。光照的差异也导致了一些困难。远距离的人体和近距离的人体,在外观上差别也非常大。 3 | * 遮挡问题。在很多应用场景中,行人非常密集,存在严重的遮挡,我们只能看到人体的一部分,这对检测算法带来了严重的挑战。 4 | * 背景复杂。无论是室内还是室外,行人检测一般面临的背景都非常复杂,有些物体的外观和形状、颜色、纹理很像人体,导致算法无法准确的区分。 5 | * 检测速度。行人检测一般采用了复杂的模型,运算量相当大,要达到实时非常困难,一般需要大量的优化。 6 | 7 | 8 | ## 基于运动检测的算法 9 | 10 | 如果摄像机静止不动,则可以利用背景建模算法提取出运动的前景目标,然后利用分类器对运动目标进行分类,判断是否包含行人。常用的背景建模算法有: 11 | 12 | * 高斯混合模型,Mixture of Gaussian model[1] 13 | * ViBe算法[2] 14 | * 帧差分算法 15 | * SACON,样本一致性建模算法[3] 16 | * PBAS算法[4] 17 | 18 | 这些背景建模算法的思路是通过前面的帧学习得到一个背景模型,然后用当前帧与背景帧进行比较,得到运动的目标,即图像中变化的区域 19 | 20 | 背景建模算法实现简单,速度快,但存在下列问题: 21 | 22 | * 只能检测运动的目标,对于静止的目标无法处理 23 | * 受光照变化、阴影的影响很大 24 | * 如果目标的颜色和背景很接近,会造成漏检和断裂 25 | * 容易受到恶劣天气如雨雪,以及树叶晃动等干扰物的影响 26 | * 如果多个目标粘连,重叠,则无法处理 27 | 28 | ## 基于机器学习的方法 29 | 30 | **介绍人工特征+分类器的方案** 31 | 32 | 人体有自身的外观特征,我们可以手工设计出特征,然后用这种特征来训练分类器用于区分行人和背景。这些特征包括颜色,边缘,纹理等机器学习中常用的特征 33 | 34 | 采用的分类器有神经网络,SVM,AdaBoost,随机森林等计算机视觉领域常用的算法。由于是检测问题,因此一般采用滑动窗口的技术 35 | 36 | ### HOG+SVM 37 | 38 | 梯度方向直方图(HOG)是一种`边缘特征`,它利用了边缘的朝向和强度信息,后来被广泛应用于车辆检测,车牌检测等视觉目标检测问题。 39 | 40 | *HOG的做法是固定大小的图像先计算梯度,然后进行网格划分,计算每个点处的梯度朝向和强度,然后形成网格内的所有像素的梯度方向分分布直方图,最后汇总起来,形成整个直方图特征* 41 | 42 |
43 | 44 | 得到候选区域的HOG特征后,需要利用分类器对该区域进行分类,确定是行人还是背景区域 45 | 46 | 在实现时,使用了线性支持向量机,这是因为采用非线性核的支持向量机在预测时的计算量太大,与支持向量的个数成正比(SVM) 47 | 48 | 目前OpenCV中的行人检测算法支持HOG+SVM以及HOG+Cascade两种,二者都采用了滑动窗口技术,用固定大小的窗口扫描整个图像,然后对每一个窗口进行前景和背景的二分类。为了检测不同大小的行人,还需要对图像进行缩放。 49 | 50 | 51 | 52 | ### HOG+AdaBoost 53 | 由于HOG + SVM的方案计算量太大,为了提高速度,后面有研究者参考了VJ[6]在人脸检测中的分类器设计思路 将AdaBoost分类器级联的策略应用到了人体检测中,只是将Haar特征替换成HOG特征,因为Haar特征过于简单,无法描述人体这种复杂形状的目标。 54 | 55 |
56 | 57 | 相同条件下的预测时间只有基于SVM方法的十分之一。 58 | 59 | 60 | ### ICF+AdaBoost 61 | 62 | HOG特征只关注了物体的边缘和形状信息,对目标的表观信息并没有有效记录,所以很难处理遮挡问题,而且由于梯度的性质,该特征对噪点敏感。 63 | 64 | 针对这些问题后面有人提出了积分通道特征(ICF)[7],积分通道特征包括10个通道: 65 | 66 | * 6 个方向的梯度直方图,3 个LUV 颜色通道和1 梯度幅值, 67 | 68 | 为了检测不同大小的行人,作者并没有进行图像缩放然后用固定大小的分类器扫描,而是训练了几个典型尺度大小的分类器,对于其他尺度大小的行人,采用这些典型尺度分类器的预测结果进行插值来逼近,这样就不用对图像进行缩放。 69 | 70 | 71 | ### DPM+ latent SVM 72 | 73 | 行人检测中的一大难题是遮挡问题,为了解决这一问题,出现了采用部件检测的方法,把人体分为头肩,躯干,四肢等部分,对这些部分分别进行检测,然后将结果组合起来,使用的典型特征依然是HOG,采用的分类器有SVM和AdaBoost。 74 | 75 | 76 | DPM(Deformable Parts Models)是一种基于组件的检测算法,DPM检测中使用的特征是HOG,针对目标物不同部位的组建进行独立建模。 77 | 78 | DPM中根模型和部分模型的作用, 79 | * 根模型(Root-Filter)主要是对物体潜在区域进行定位,获取可能存在物体的位置,但是是否真的存在我们期望的物体,还需要结合组件模型(Part-Filter)进行计算后进一步确认 80 | 81 | DPM算法在人体检测中取得取得了很好的效果,主要得益于以下几个原因: 82 | * 基于方向梯度直方图(HOG)的低级特征(具有较强的描述能力) 83 | * 基于可变形组件模型的高效匹配算法 84 | * 采用了鉴别能力很强的latent-SVM分类器 85 | 86 | DPM算法同时存在明显的局限性 87 | * DPM特征计算复杂,计算速度慢 88 | * 人工特征对于旋转、拉伸、视角变化的物体检测效果差 89 | 90 | `这些弊端很大程度上限制了算法的应用场景,这一点也是基于人工特征+分类器的通病。` 91 | 92 | 93 | 采用经典机器学习的算法虽然取得了不错的成绩,但依然存在下面的问题: 94 | * 对于外观,视角,姿态各异的行人检测精度还是不高 95 | * 提取的特征在特征空间中的分布不够紧凑 96 | * 分类器的性能受训练样本的影响较大 97 | * 离线训练时的负样本无法涵盖所有真实应用场景的情况 98 | 99 | 100 | ## 基于深度学习的算法 101 | 102 | 基于深度学习的通用目标检测框架,如Faster-RCNN、SSD、FPN、YOLO等,这些方法都可以直接应用到行人检测的任务中 103 | 104 | 105 | 106 | * 行人检测主要的方法是 1 使用人工特征+分类器的方案 2 深度学习 107 | 108 | * 使用的分类器 1有线性支持向量机, 2 AdaBoost, 3 随机森林。 109 | 110 | 111 | ### Cascade CNN 112 | 113 | 如果直接用卷积网络进行滑动窗口检测,将面临计算量太大的问题,因此必须采用优化策略 114 | 115 | 所以提出了一种用`级联的卷积网络`进行行人检测的方案这借鉴了AdaBoost分类器级联的思想。 116 | 117 | * 前面的卷积网络简单,可以快速排除掉大部分背景区域: 118 | * 后面的卷积网络更复杂,用于精确的判断一个候选窗口是否为行人 119 | 120 | 这种做法和人脸检测中的Cascade CNN类似。 121 | 122 | 123 | ### JointDeep 124 | 125 | 作者使用了一种混合的策略,以Caltech行人数据库训练一个卷积神经网络的行人分类器。 126 | 127 | 该分类器是作用在行人检测的最后的一级,即对最终的候选区域做最后一关的筛选,因为这个过程的效率不足以支撑滑动窗口这样的穷举遍历检测。 128 | 129 | ### SA-FastRCNN 130 | 131 | 作者分析了Caltech行人检测数据库中的数据分布,提出了以下两个问题: 132 | * 才行人尺度问题是待解决的一个问题 133 | * 行人检测中有许多的小尺度物体, 与大尺度物体实例在外观特点上非常不同 134 | 135 | 由于大尺寸和小尺寸行人提取的特征显示出显着差异,作者分别针对大尺寸和小尺寸行人设计了2个子网络分别进行检测。 136 | 137 | 138 | ### Faster R-CNN 139 | 140 | Faster R-CNN中的RPN网络对提取行人候选区域是相当有效的,而下游的检测网络表现的不好。 141 | 142 | 作者指出了其中的两个原因: 143 | * 对于小目标,卷积层给出的特征图像太小了,无法有效的描述目标; 144 | * 另外,也缺乏难分的负样本挖掘机制。 145 | 146 | 作者在这里采用了一种混合的策略,用RPN提取出候选区域,然后用随机森林对候选区域进行分类。这一结构如下图所示: 147 | 148 | 149 | ### DeepParts 150 | 151 | 提出了一种基于部件的检测方案,称为DeepParts,致力于解决遮挡问题。这种方案将人体划分成多个部位,分别进行检测,然后将结果组合起来。 152 | 153 | 154 | ### RepLoss 155 | 156 | RepLoss[14]由face++提出,主要目标是解决遮挡问题。 157 | 158 | ### HyperLearner 159 | 160 | 提出了一种称为HyperLearner的行人检测算法,改进自Faster R-CNN 161 | 162 | 163 | -------------------------------------------------------------------------------- /Note/pic/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/3.png -------------------------------------------------------------------------------- /Note/pic/HOG.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/HOG.jpg -------------------------------------------------------------------------------- /Note/pic/Haar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/Haar.png -------------------------------------------------------------------------------- /Note/pic/IDT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/IDT.png -------------------------------------------------------------------------------- /Note/pic/人脸异常行为检测.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/人脸异常行为检测.png -------------------------------------------------------------------------------- /Note/pic/光流法.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/光流法.png -------------------------------------------------------------------------------- /Note/pic/帧差法.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/帧差法.png -------------------------------------------------------------------------------- /Note/pic/级联分类器.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/级联分类器.jpg -------------------------------------------------------------------------------- /Note/pic/背景差分法.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/背景差分法.png -------------------------------------------------------------------------------- /Note/pic/行为识别.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/行为识别.png -------------------------------------------------------------------------------- /Note/pic/行为识别01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/行为识别01.png -------------------------------------------------------------------------------- /Note/pic/行为识别02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/行为识别02.png -------------------------------------------------------------------------------- /Note/pic/行为识别03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/行为识别03.png -------------------------------------------------------------------------------- /Note/pic/运动目标检测比较.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Note/pic/运动目标检测比较.jpg -------------------------------------------------------------------------------- /Note/目标检测.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | 如何理解一张图片?根据后续任务的需要,有三个主要的层次。 4 | * 一是分类(Classification) 5 | * 二是检测(Detection ) 6 | * 三是分割(Segmentation):分割包括语义分割(semantic segmentation)和实例分割(instance segmentation), 7 | 8 | ## [传统方法](https://www.zhihu.com/question/53438706) 9 | 10 | 传统算法最经典的莫过于Harr+adaboost 的检测算法和hog+Svm以及DPM算法了 11 | 12 | ### Haar+Adaboost 13 | 14 | 其他级联分类器框架如:**Haar/LBP/积分HOG/ACF feature+Adaboost** 15 | 16 | 其实这就是boosting由简单弱分类拼装强分类器的过程,这个算法第一次使目标检测成为现实 17 | 18 |
19 | 20 | OpenCV有对级联分类器的经典实现 21 | 22 | ### HoG+SVM 23 | 24 | 之后又有人魔改出LoG/DoG/RoG等一系列特征,没啥意思就不多说了。 25 | 26 | 值得一提的是,有人把SVM中的HoG改为Integral HoG 用于级联分类器。这也就是目前OpenCV级联分类器的积分HOG的原型: 27 | 28 | 29 | 30 | 31 | 32 | ## [深度学习](https://zhuanlan.zhihu.com/p/34142321) 33 | 34 | ### 两阶段(2-stage)检测模型: 准 35 | 36 | **`基于region proposal(two stage):R-CNN家族,包括Faster R-CNN/Mask R-CNN/RFCN`** 37 | 38 | * 顾名思义,两刀解决问题: 39 | * 1、生成可能区域(Region Proposal) & CNN 提取特征 40 | * 2、放入分类器分类并修正位置 41 | 42 | * 这一流派的算法都离不开 Region Proposal ,即是优点也是缺点,主要代表人物就是 R-CNN 系。 43 | 44 | #### R-CNN: R-CNN系列 45 | 从图像分类任务的经验来看,CNN网络自动习得的特征取得的效果已经超出了手工设计(如SIFT, HOG)的特征。 46 | 47 | CNN的想法直接明了,即将检测任务转化为区域上的分类任务 48 | 49 | 模型本身存在的问题也很多,如需要训练三个不同的模型(proposal, classification, regression)、重复计算过多导致的性能问题等。 50 | 51 | 52 | #### Fast R-CNN: 共享卷积运算 53 | 54 | R-CNN耗时的原因是CNN是在每一个Proposal上单独进行的,没有共享计算,便提出将基础网络在图片整体上运行完毕后,再传入R-CNN子网络,共享了大部分计算,故有Fast之名 55 | 56 | 57 | #### Faster R-CNN: 两阶段模型的深度化 58 | 59 | 本文的主要贡献是提出Regional Proposal Networks,替代之前的SS算法。RPN网络将Proposal这一任务建模为二分类(是否为物体)的问题。 60 | 61 | 62 | 63 | ### 单阶段(1-stage)检测模型: 快 64 | 65 | 66 | **`基于回归(one-shot):YOLO/YOLO2/SSD/DSSD`** 67 | 68 | * 一刀流回归的思想 69 | - 一刀流最核心的还是利用了分类器优秀的分类效果,首先给出一个大致的范围(最开始就是全图)进行分类,然后不断迭代这个范围直到一个精细的位置,如上图从蓝色的框框到红色的框框 70 | * 这样做的优点就是快,但是会有许多漏检 71 | 72 | #### YOLO 73 | 74 | 它将检测任务表述成一个统一的、端到端的回归问题,并且以只处理一次图片同时得到位置和分类而得名。 75 | 76 | * 主要优点: 77 | - 快 实时 78 | - 全局处理使得背景错误相对少,相比基于局部(区域)的方法, 如Fast RCNN。 79 | - 泛化性能好,在艺术作品上做检测时,YOLO表现比Fast R-CNN好。 80 | 81 | * 存在一些问题 82 | - 划分网格较为粗糙 限制了对小尺度物体和相近物体的检测。 83 | 84 | 85 | #### SSD: Single Shot Multibox Detector 86 | 87 | * SSD相比YOLO有以下突出的特点 88 | - 多尺度的feature map:这一点试图提升小物体的检测精度。 89 | - 更多的anchor box, 90 | 91 | 92 | 轮子: [常用的检测算法](https://github.com/tensorflow/models/tree/master/research/object_detection) 93 | 94 | 95 | -------------------------------------------------------------------------------- /Note/行为识别.md: -------------------------------------------------------------------------------- 1 | # 行为分类 2 | 3 | ## 任务概述 4 | 5 | ### 任务特点 6 | 行为识别和图像分类其实很相似,图像分类是按照图像中的目标进行软分类,行为识别也类似。 7 | 最开始的时候类似于UCF数据集,都是采用的单标签,也就是一段视频只对应一个标签。 8 | 现在CPVR举办的Activitynet(Kinetics 数据集)每段视频中包含多个标签。相比于图像分类, 9 | `视频多了一个时序维度,而这个问题恰恰是目前计算机领域令人头疼的问题。` 10 | 11 | ### 研究难点 12 | 13 | * 行为识别处理的是视频,所以相对于图像分类来说多了一个需要处理的时序维度 14 | * 行为识别还有一个痛点是视频段长度不一,而且开放环境下视频中存在多尺度、多目标、摄像机移动等众多的问题。 15 | 16 | 17 | ## 传统方法 18 | 19 | 在深度学习出现之前,表现最好的算法是iDT 20 | * IDT的思路是利用光流场来获得视频序列中的一些轨迹,再沿着轨迹提取HOF,HOG,MBH,trajectory4中特征, 21 | * 其中HOF基于灰度图计算,另外几个均基于dense optical flow(密集光流计算)。 22 | * 最后利用FV(Fisher Vector)方法对特征进行编码,再基于编码训练结果训练SVM分类器 23 | 24 | iDT算法框架主要包含:密集采样特征点,特征轨迹跟踪和基于轨迹的特征提取三个部分。 25 | 26 |
27 | 28 | 29 | ## TWO STREAM方法 30 | 31 | Two-Stream CNN网络顾名思义分为两个部分,一部分处理RGB图像,一部分处理光流图像。最终联合训练,并分类。 32 | 33 | 光流栈(Optical flow Stacking): 34 | * 简单的来说就是计算每两帧之间的光流,然后简单的stacking。 35 | 36 | 缺点: 37 | * two-stream的方法很大的一个弊端就是不能对长时间的视频进行建模 38 | 39 | TSN网络提出了一个很有用的方法,先将视频分成K个部分,然后从每个部分中随机的选出一个短的片段,然后对这个片段应用上述的two-stream方法,最后对于多个片段上提取到的特征做一个融合 40 | 41 | ## C3D方法 42 | 43 | 目前来看C3D的方法得到的效果普遍比Two-Stream方法低好几个百分点。但是C3D任然是目前研究的热点,主要原因是该方法比Two-Stream方法快很多,而且基本上都是端到端的训练,网络结构更加简洁。 44 | 45 | C3D的意思是:用三维的卷积核处理视频。 46 | 47 | ## RNN方法 48 | 49 | 视频除了空间维度外,最大的痛点是时间序列问题。 RNN网络非常适合处理序列。 50 | 51 | RPAN网络框架可以分为三个大的部分。 (RPAN中引入了姿态监督的机制) 52 | * 特征生成部分:用Two-Stream的方法生成 53 | * 姿态注意机制 54 | * LSTM时序处理网络 55 | 56 | 57 | # 行为检测 58 | 59 | 相比于行为分类,行为检测难度更高,不仅需要定位视频中可能存在行为动作的视频段,还需要将其分类。 60 | 61 | ## 研究难点 62 | 63 | * 时序信息。与行为识别/分类一样,视频理解的通用难点就是时序信息的处理。所以针对这一点目前的主要方法基本上都是使用RNN读入CNN提取的特征,或者直接使用C3D一样的时序卷积。 64 | * 边界不明确。不同于行为识别的是,行为检测要求做精确的动作区间检测,而生活中一个动作的产生往往边界不是十分确定的,所以这也是导致目前行为检测mAP偏低的原因。 65 | * 时间跨度大。在生活中,一个行为动作往往跨度非常大,短的动作几秒左右,比如挥手。长的动作有的持续数十分钟,比如攀岩、骑行等等。这使得我们在提取Proposal的时候变得异常的艰难。 66 | 67 | ## CDC网络 68 | 69 | CDC网络[13]是在C3D网络基础上,借鉴了FCN的思想。在C3D网络的后面增加了时间维度的上采样操作,做到了帧预测(frame level labeling)。 70 | 71 | ## R-C3D网络 72 | 73 | 基于Faster R-CNN和C3D网络思想。对于任意的输入视频L,先进行Proposal,然后用3D-pooling,最后进行分类和回归操作。 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Note/视频行为识别.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | # 0-概述 6 | 7 | ## 行为检测 8 | 9 | ``` 10 | 但在现实应用中更容易遇到的情况是序列尚未在时域分割(Untrimmed), 11 | 因此需要同时对行为动作进行时域定位(分割)和类型判定,这类任务一般称为行为检测。 12 | 传统 DTW 动态时间规整 分割视频 13 | 现在 利用RNN网络对未分割序列进行行为检测(行为动作的起止点的定位 和 行为动作类型的判定) 14 | 15 | Action Detection 16 | 17 | 目的:不仅要知道一个动作在视频中是否发生,还需要知道动作发生在视频的哪段时间 18 | 19 | 特点:需要处理较长的,未分割的视频。且视频通常有较多干扰,目标动作一般只占视频的一小部分。 20 | 21 | 分类:根据待检测视频是一整段读入的还是逐次读入的,分为online和offline两种 22 | 23 | Offline action detection: 24 | 特点:一次读入一整段视频,然后在这一整段视频中定位动作发生的时间 25 | 26 | Online action detection: 27 | 特点:不断读入新的帧,在读入帧的过程中需要尽可能早的发现动作的发生(在动作尚未结束时就检测到)。 28 | 同时online action detection 还需要满足实时性要求,这点非常重要。 29 | 这导致online action detection不能采用计算复杂度过大的方法(在现有的计算能力下) 30 | 31 | 现有方法: 32 | 逐帧检测法: 33 | 即在视频序列的每帧上独立判断动作的类型,可以用CNN等方法,仅用上了spatial的信息 34 | 滑窗法: 即设置一个固定的滑窗大小,在视频序列上进行滑窗,然后对滑窗得到的视频小片断利用action recognition的方法进行分类。 35 | 36 | 现状:由于此问题难度比action recognition高很多,所以现在还没有效果较好的方法 37 | 38 | ``` 39 | ## 行为识别 40 | 41 | 42 | 43 | ### 1.任务特点 44 | ``` 45 | 目的 46 | 给一个视频片段进行分类,类别通常是各类人的动作 47 | 48 | 特点 49 | 简化了问题,一般使用的数据库都先将动作分割好了,一个视频片断中包含一段明确的动作, 50 | 时间较短(几秒钟)且有唯一确定的label。 51 | 所以也可以看作是输入为视频,输出为动作标签的多分类问题。 52 | 此外,动作识别数据库中的动作一般都比较明确,周围的干扰也相对较少(不那么real-world)。 53 | 有点像图像分析中的Image Classification任务。 54 | 55 | 难点/关键点 56 | 强有力的特征: 57 | 即如何在视频中提取出能更好的描述视频判断的特征。 58 | 特征越强,模型的效果通常较好。 59 | 特征的编码(encode)/融合(fusion): 60 | 这一部分包括两个方面, 61 | 第一个方面是非时序的,在使用多种特征的时候如何编码/融合这些特征以获得更好的效果; 62 | 另外一个方面是时序上的,由于视频很重要的一个特性就是其时序信息, 63 | 一些动作看单帧的图像是无法判断的,只能通过时序上的变化判断, 64 | 所以需要将时序上的特征进行编码或者融合,获得对于视频整体的描述。 65 | 算法速度: 66 | 虽然在发论文刷数据库的时候算法的速度并不是第一位的。 67 | 但高效的算法更有可能应用到实际场景中去. 68 | ``` 69 | 70 | ### 2 人体行为识别 71 | ``` 72 | 73 | 人体行为识别的目标是从一个未知的视频或者是图像序列中自动分析其中正在进行的行为。 74 | 75 | 简单的行为识别即动作分类,给定一段视频,只需将其正确分类到已知的几个动作类别, 76 | 77 | 复杂点的识别是视频中不仅仅只包含一个动作类别,而是有多个, 78 | 系统需自动的识别出动作的类别以及动作的起始时刻。 79 | 行为识别的最终目标是分析视频中 80 | 哪些人 who 81 | 在什么时刻 when 82 | 什么地方, where 83 | 干什么事情, what 84 | 即所谓的“W4系统” 85 | 86 | 人体行为识别应用背景很广泛,主要集中在智能视频监控, 87 | 病人监护系统,人机交互,虚拟现实,智能家居,智能安防, 88 | 运动员辅助训练,另外基于内容的视频检索和智能图像压缩等 89 | 有着广阔的应用前景和潜在的经济价值和社会价值, 90 | 其中也用到了不少行为识别的方法。 91 | 92 | ``` 93 | 94 | 95 | 96 | # 1-传统方法 97 | 98 | 传统方法的具体流程 99 |
100 | 101 | 102 | 103 | 104 | # 2-深度学习方法 105 | 106 | 深度学习方法具体流程 107 |
108 | 109 | ## 2.1 two-stream(双流)方法 110 | 111 | [two-stream](https://blog.csdn.net/liuxiao214/article/details/78377791) 112 | ``` 113 | Two Stream方法最初在这篇文章中被提出: 114 | 在空间部分,以单个帧上的外观形式,携带了视频描绘的场景和目标信息。 115 | 其自身静态外表是一个很有用的线索,因为一些动作很明显地与特定的目标有联系。 116 | 在时间部分,以多帧上的运动形式,表达了观察者(摄像机)和目标者的运动。 117 | 118 | 基本原理为: 119 | 1. 对视频序列中每两帧计算密集光流,得到密集光流的序列(即temporal信息)。 120 | 2. 然后对于视频图像(spatial)和密集光流(temporal)分别训练CNN模型, 121 | 两个分支的网络分别对动作的类别进行判断, 122 | 3. 最后直接对两个网络的class score进行fusion(包括直接平均和svm两种方法),得到最终的分类结果。 123 | ``` 124 | 125 | 126 | ## 2.2 C3D 127 | 128 | ``` 129 | C3D是facebook的一个工作,采用3D卷积和3D Pooling构建了网络。 130 | 通过3D卷积,C3D可以直接处理视频(或者说是视频帧的volume) 131 | 实验效果:UCF101-85.2% 可以看出其在UCF101上的效果距离two stream方法还有不小差距。 132 | 我认为这主要是网络结构造成的,C3D中的网络结构为自己设计的简单结构,如下图所示。 133 | 134 | 速度: 135 | C3D的最大优势在于其速度,在文章中其速度为314fps。而实际上这是基于两年前的显卡了。 136 | 用Nvidia 1080显卡可以达到600fps以上。 137 | 138 | 139 | ``` 140 | 141 | 142 | ## 2.3 CNN-LSTM 143 | ``` 144 | 人体骨架怎么获得呢? 145 | 146 | 主要有两个途径: 147 | 通过RGB图像进行关节点估计(Pose Estimation openpose工具箱)获得, 148 | 或是通过深度摄像机直接获得(例如Kinect)。 149 | 150 | 每一时刻(帧)骨架对应人体的K个关节点所在的坐标位置信息,一个时间序列由若干帧组成。 151 | 152 | 153 | 思路: 154 | 在视频上先对每一帧做姿态估计(Kinetics 数据集上文章用的是OpenPose),然后可以构建出一个空间上的骨架时序图。 155 | 然后应用ST-GCN网络提取高层特征 156 | 最后用softmax分类器进行分类 157 | 158 | 159 | ``` 160 | -------------------------------------------------------------------------------- /Note/运动目标检测.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 概述 4 | 5 | ## 静态背景下的目标检测 6 | 7 | 运动目标计算机视觉检测有以下基本方法:帧差法、光流法和背景减法,此外还有特征匹配法、KNN及这些方法的变种(三帧差分、五帧差分) 8 | 9 | *
10 | 11 | ### 1 帧间差分法 12 | 该方法利用图像序列中相邻帧的像素值之间的相关性,先将图像序列中相邻两帧进行相减,然后对得到差值图像进行阈值判断,进而提取动态前景 13 | *
14 | 15 | * 优缺点 16 | - 动态性强,能够适应动态背景下的运动目标检测 17 | - 但是,这类算法检测出的目标轮廓非常不理想,在目标内部会留有许多空洞,在目标运动较快时目标的轮廓会被扩大,在目标运动较慢时甚至有可能无法得到目标的边界。 18 | 19 | 20 | ### 2 [背景差分法](https://www.cnblogs.com/xrwang/archive/2010/02/21/ForegroundDetection.html) 21 | 获取背景模型的最简单方法是直接捕获一副不包含任何移动物体的“干净”的背景图像。然而,在实际环境中,这样“干净”的背景是很难被捕捉到的 22 | 23 | *
24 | 25 | * 优缺点 26 | * 速度快 准确 容易实现 27 | * 缺点是由于通常需要缓冲若干帧频来学习背景,因此往往需要消耗大量的内存, 28 | 29 | [各种背景差分除的方法](http://code.google.com/p/bgslibrary/) 30 | 31 | 32 | ### 3 光流法 33 | 通常,视频序列中背景的光流是一致,与运动目标的光流不同,因此,根据光流的不同就可以提取运动目标和背景区域。 34 | 35 | *
36 | 37 | * 特点 38 | * 在摄像机运动、背景变化时,光流法也能检测出运动目标,并且它能同时完成运动目标检测和跟踪 39 | * 计算复杂度高 很难做到实时检测 非常容易受到噪声干扰 40 | 41 | 42 | ### 4 码本(codebook) 43 | 算法为图像中每一个像素点建立一个码本,每个码本可以包括多个码元(对应阈值范围) 44 | 45 | * 在学习阶段,对当前像素点进行匹配, 46 | - 如果该像素值在某个码元的学习阈值内,也就是说与之前出现过的某种历史情况偏离不大,则认为该像素点符合背景特征,需要更新对应点的学习阈值和检测阈值 47 | - 如果新来的像素值与每个码元都不匹配,则可能是由于动态背景导致,这种情况下,我们需要为其建立一个新的码元。每个像素点通过对应多个码元,来适应复杂的动态背景。 48 | 49 | * 在应用时,每隔一段时间选择K帧通过更新算法建立CodeBook背景模型,并且删除超过一段时间未使用的码元。 50 | 51 | ### 5 混合高斯模型(GMM) 52 | 53 | 混合高斯建模GMM(Gaussian Mixture Model)作为单核高斯背景建模的扩展,是目前使用最广泛的一种方法。 54 | 55 | GMM将背景模型描述为多个分布(能够满足背景的切换,比如树叶晃动),符合其中一个分布模型(有树叶、无树叶)的像素即为背景像素 56 | 57 | 第一,效果不错,噪声可以很快消除,第二,opencv包含了GMM算法 58 | 59 | 60 | 61 | GMM针对复杂背景有很好的适应性,其表现也更接近实际应用 62 | * 特点 63 | 64 | * 而能够适应像素层面上的背景扰动问题,并能通过对背景的不断更新,使系统能对背景的变化自适应。 65 | * 但是,高斯混合模型对于全局光照变化、阴影非常敏感,对于缓慢的运动目标检测效果也不理想。 66 | 67 | ### 6 ViBe方法 68 | 69 | 该算法使用概率统计方法对背景建模并采用随机策略来更新背景模型,这和GMM有很大不同(像素的变化存在不确定性很难用一个固定的模型来表征) 70 | 71 | * 速度快,效果好,但无法适应光照变化,会出现阴影与空洞。 72 | -------------------------------------------------------------------------------- /Paper/基于ATM机的用户异常行为识别的研究_宋丙菊.caj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Paper/基于ATM机的用户异常行为识别的研究_宋丙菊.caj -------------------------------------------------------------------------------- /Paper/基于深度学习的人体行为识别技术的研究与应用_刘潇.caj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShixianGuo/Abnormal-behavior-detection/2650294939c17ac32afa6520344e4524a26a4749/Paper/基于深度学习的人体行为识别技术的研究与应用_刘潇.caj -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Abnormal-behavior-detection 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Src/videoFrameDifference.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import time 3 | import imutils 4 | import cv2 5 | 6 | # 创建参数解析器并解析参数 7 | ap = argparse.ArgumentParser() 8 | ap.add_argument("-v", "--video", help="path of the video") 9 | # 待检测目标的最小面积,该值需根据实际应用情况进行调整(原文为500) 10 | ap.add_argument("-a", "--min-area", type=int, default=2000, help="minimum area size") 11 | args = vars(ap.parse_args()) #@ 12 | 13 | # 如果video参数为空,则从自带摄像头获取数据 14 | if args.get("video") == None: 15 | camera = cv2.VideoCapture(0) 16 | # 否则读取指定的视频 17 | else: 18 | camera = cv2.VideoCapture(args["video"]) 19 | 20 | 21 | # 开始之前先暂停一下,以便跑路(离开本本摄像头拍摄区域^_^) 22 | print("Ready?") 23 | time.sleep(1) 24 | print("Action!") 25 | 26 | # 初始化视频第一帧 27 | firstRet, firstFrame = camera.read() 28 | if not firstRet: 29 | print("Load video error!") 30 | exit(0) 31 | 32 | # 对第一帧进行预处理 33 | firstFrame = imutils.resize(firstFrame, width=500) # 尺寸缩放,width=500 34 | gray_firstFrame = cv2.cvtColor(firstFrame, cv2.COLOR_BGR2GRAY) # 灰度化 35 | firstFrame = cv2.GaussianBlur(gray_firstFrame, (21, 21), 0) #高斯模糊,用于去噪 36 | 37 | # 遍历视频的每一帧 38 | while True: 39 | (ret, frame) = camera.read() 40 | 41 | # 如果没有获取到数据,则结束循环 42 | if not ret: 43 | break 44 | 45 | # 对获取到的数据进行预处理 46 | frame = imutils.resize(frame, width=500) 47 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 48 | gray_frame = cv2.GaussianBlur(gray_frame, (21, 21), 0) 49 | 50 | # cv2.imshow('video', firstFrame) 51 | # 计算第一帧和其他帧的差别 52 | frameDiff = cv2.absdiff(firstFrame, gray_frame) 53 | # 忽略较小的差别 54 | retVal, thresh = cv2.threshold(frameDiff, 25, 255, cv2.THRESH_BINARY) 55 | 56 | # 对阈值图像进行填充补洞 57 | thresh = cv2.dilate(thresh, None, iterations=2) 58 | image, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 59 | 60 | text = "Unoccupied" 61 | # 遍历轮廓 62 | for contour in contours: 63 | # if contour is too small, just ignore it 64 | if cv2.contourArea(contour) < args["min_area"]: 65 | continue 66 | 67 | # 计算最小外接矩形(非旋转) 68 | (x, y, w, h) = cv2.boundingRect(contour) 69 | cv2.rectangle(frame, (x, y), (x+w, y+h), (0,255,0), 2) 70 | text = "Occupied!" 71 | 72 | v2.putText(frame, "Room Status: {}".format(text), (10,20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 2) 73 | 74 | cv2.imshow('frame', frame) 75 | # cv2.imshow('thresh', thresh) 76 | # cv2.imshow('frameDiff', frameDiff) 77 | 78 | # 处理按键效果 79 | key = cv2.waitKey(60) & 0xff 80 | if key == 27: # 按下ESC时,退出 81 | break 82 | elif key == ord(' '): # 按下空格键时,暂停 83 | cv2.waitKey(0) 84 | 85 | # 释放资源并关闭所有窗口 86 | camera.release() 87 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Src/videoFrameDifferenceCopy.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import time 3 | import datetime 4 | import os 5 | 6 | # 选取摄像头,0为笔记本内置的摄像头,1,2···为外接的摄像头 7 | camera=cv2.VideoCapture(0) 8 | 9 | time.sleep(5)#延迟5s执行 10 | background = None#初始化背景 11 | def nothing(x): 12 | pass 13 | 14 | cv2.namedWindow("fps") #新建一个窗口 15 | cv2.createTrackbar('level','fps',21,255,nothing) #新建阈值滑动条 16 | shot_idx = 0 17 | 18 | while True: 19 | text = "No Target" 20 | flat=0 21 | # 滑动条赋值 22 | kerne = cv2.getTrackbarPos('level', 'fps') 23 | if kerne%2==0 : 24 | kerne=kerne+1#解决滑动条赋值到高斯滤波器是偶数异常抛出 25 | (grabbed, frame) = camera.read() 26 | # 对帧进行预处理,先转灰度图,再进行高斯滤波。 27 | # 用高斯滤波对图像处理,避免亮度、震动等参数微小变化影响效果 28 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 29 | gray = cv2.GaussianBlur(gray, (kerne, kerne), 0) 30 | # 将第一帧设置为整个输入的背景 31 | if background is None: 32 | background = gray 33 | continue 34 | # 当前帧和第一帧的不同它可以把两幅图的差的绝对值输出到另一幅图上面来 35 | frameDelta = cv2.absdiff(background, gray) 36 | # 二值化 37 | thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1] 38 | # 腐蚀膨胀 39 | thresh = cv2.dilate(thresh, None, iterations=2) 40 | #取轮廓 41 | cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, 42 | cv2.CHAIN_APPROX_SIMPLE)[-2] 43 | # 遍历轮廓 44 | for c in cnts: 45 | if cv2.contourArea(c) < 1800: # 对于较小矩形区域,选择忽略 46 | continue 47 | flat=1#设置一个标签,当有运动的时候为1 48 | # 计算轮廓的边界框,在当前帧中画出该框 49 | (x, y, w, h) = cv2.boundingRect(c) 50 | cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2) 51 | text = "Find Target! save as D:\CCTVlook" 52 | print("Find Target!") 53 | # cv2.putText(frame, text, (10, 20), 54 | # cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) 55 | # cv2.putText(frame, datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"), 56 | # (10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1) 57 | #cv2.imshow("Frame Delta", frameDelta) 58 | 59 | cv2.imshow("fps", frame) 60 | #cv2.imshow("Thresh", thresh) 61 | 62 | key = cv2.waitKey(1) & 0xFF 63 | 64 | # 如果q键被按下,跳出循环 65 | ch = cv2.waitKey(1) 66 | if key == ord("q"): 67 | break 68 | elif key == ord(' '): # 按下空格键时,暂停 69 | cv2.waitKey(0) 70 | 71 | camera.release() 72 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Src/videoOpencv.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | import cv2 3 | 4 | def is_inside(o, i): 5 | ox, oy, ow, oh = o 6 | ix, iy, iw, ih = i 7 | # 如果符合条件,返回True,否则返回False 8 | return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih 9 | 10 | def draw_person(img, person): 11 | x, y, w, h = person 12 | cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 255), 2) 13 | 14 | 15 | 16 | # 图片识别方法 17 | def discern(img): 18 | # 定义HOG特征+SVM分类器 19 | hog = cv2.HOGDescriptor() 20 | hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) 21 | found, w = hog.detectMultiScale(img, winStride=(8, 8), scale=1.05) 22 | 23 | # 判断坐标位置是否有重叠 24 | found_filtered = [] 25 | for ri, r in enumerate(found): 26 | for qi, q in enumerate(found): 27 | a = is_inside(r, q) 28 | if ri != qi and a: 29 | break 30 | else: 31 | found_filtered.append(r) 32 | 33 | # 勾画筛选后的坐标位置 34 | for person in found_filtered: 35 | draw_person(img, person) 36 | 37 | 38 | #人脸检测 39 | grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 40 | # OpenCV人脸识别分类器 41 | classifier = cv2.CascadeClassifier( 42 | "C:\Program Files\Python36\Lib\site-packages\opencv-master\data\haarcascades\haarcascade_frontalface_default.xml" 43 | ) 44 | color = (0, 255, 0) # 定义绘制颜色 45 | # 调用识别人脸 46 | faceRects = classifier.detectMultiScale( 47 | grayImg, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32)) 48 | if len(faceRects): # 大于0则检测到人脸 49 | for faceRect in faceRects: # 单独框出每一张人脸 50 | x, y, w, h = faceRect 51 | # 框出人脸 52 | cv2.rectangle(img, (x, y), (x + h, y + w), color, 2) 53 | 54 | cv2.imshow("image", img) # 显示图像 55 | 56 | 57 | def main(): 58 | cap = cv2.VideoCapture(0) 59 | 60 | while (1): 61 | ret, frame = cap.read() 62 | discern(frame) 63 | if cv2.waitKey(1) & 0xFF == ord('q'): 64 | break 65 | 66 | cap.release() 67 | cv2.destroyAllWindows() 68 | 69 | if __name__ == '__main__': 70 | main() 71 | --------------------------------------------------------------------------------