OpenCV 口罩佩戴检测

基于OpenCV的口罩佩戴检测

一、前期准备

配置环境

整个环境是在 windows10 + OpenCV 3.4.15 + python 3.6.8
配置环境的话:可以按照这篇文章来

python需要安装 pandas库。

相关软件

样本预处理软件:格式工厂图片工厂(二选一)
在这里插入图片描述
主要使用其批处理功能,处理样本时会很轻松。

python IDE: Visual Studio Code, PyCharm都可以。

二、样本准备

样本数据集下载

我自己在网上搜罗了大概 6G 的数据集 ,有带口罩的,也有没带口罩的,包括知名数据集WIDER FACE数据集。
链接:百度网盘直达
提取码:YYDS

如果想直接跑训练,跳过样本预处理,可以下载我另外一份处理好的样本。
直达链接:opencv口罩人脸识别数据集+xml

机器都是笨笨的,举个例子:数据集下载下来就像是刚做好的饭,可是机器是婴儿,必须要把做好的饭先捣得稀碎他才好吃下去。
因此必须要先对数据集进行预处理(捣碎)。

刚下载下来的数据集是这样的:
在这里插入图片描述

样本的预处理(提取)

原始的数据集内的图片干扰因素很多,需要先进行第一次的筛选。比如要把带口罩的人脸之外的部分剔除掉。
在这里插入图片描述
这里取了一个巧,用OpenCV自带的分类器(其实是不能分类口罩的)先对所有数据集处理一遍,里面也会出现一些戴口罩的结果,就从这些处理后的结果中选择有口罩的作为正样本,没有口罩的作为负样本。
提取出来之后,还要将一些不符合正样本和负样本的错误的样本剔除掉。
最终的结果就像上面的一样。

接下来是详细的操作:
1.将所有照片的命名统计到Excel表格,这样便于循环遍历读取处理每一张照片。操作方法是:打开cmd,使用cd 指令进所有照片的上级目录,然后敲下面的命令:

dir /b/s/p/w *.jpg > pos.txt

这条命令会在文件夹下生成一个pos.txt文件

2.将txt文件里的内容,新建一个Excel文件,并复制进去,并在第一列第一行写names。

在这里插入图片描述

然后用python处理
!!!这里注意,python处理Excel文件需要xlrd库,而新版的xlrd库是不支持.xlsx文件的,只支持.xls文件,因此这里需要安装老版本的xlrd库

pip uninstall xlrd
pip install xlrd==1.2.0

3.用python批量处理:
这里需要先在OpenCV目录下把分类器文件(haarcascade_frontalface_default.xml)拷到需要处理的图片文件夹下,方便操作。
在这里插入图片描述

在需要处理的文件夹下,新建一个1.py(名字随便起,取1.py方便找)文件,
目录需要自己修改,按照自己的目录结构
最好单独新建一个文件夹,来保存处理后的样本

文件夹内容如下:
在这里插入图片描述
代码如下:

import pandas as pd
import cv2
names=pd.read_excel('data\\imgName.xlsx')['names']# 读取所有照片名字,这里填入自己新建的Excel文件目录和名字
i=100000 #用于重新命名 
for imagepath in names:
    #读取图片
    img = cv2.imread(imagepath)
    #转成灰度
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    #人脸识别器
    detector = cv2.CascadeClassifier('haarcascades\\haarcascade_frontalface_default.xml')#这里是分类器的文件路径和名字
    #获取人脸位置
    faces = detector.detectMultiScale(gray, 1.1, 5)
    for (x, y, w, h) in faces:
        #裁减图片
        gray = gray[y:y+h,x:x+w]  # 裁剪坐标为[y0:y1, x0:x1]
        #如果人脸不为空
        try:
            # 保存裁减后的灰度图
            cv2.imwrite('C:\\aaa\\mask\\gray1\\'+str(i)+'.jpg', gray)#输出处理后图片的文件夹位置
            # cv2.waitKey(3000)
            i += 1
        except:
            print()

在IDE中运行一下 就可以得到输出的图片了。
在这里插入图片描述
然后再去你的输出目录看,就能发现经过一次筛选的图片了。
在这里插入图片描述
!!注意,这里面会有一些分类器错误识别的图片(比如把卡通人物识别成人),把这些图片剔除后。
再在这些图片中把戴口罩的和没带口罩的分开,分别新建neg(负样本,没带口罩)和pos(戴口罩)的文件夹里。

然后调整正样本的分辨率:OpenCV官方推荐的正样本是20X20的分辨率。同样用python来实现,和上面很相似,代码如下:

import pandas as pd
import cv2
 
for n in range(1,1000):#正样本的数量1000张就是1,1000
    path='\\图片路径\\'+str(n)+'.jpg' #正样本的路径
    # 读取图片
    img = cv2.imread(path)
    img=cv2.resize(img,(50,50))
    cv2.imwrite('\\输出路径\\' + str(n) + '.jpg', img) #输出路径
    n += 1

在执行这一句之前,推荐用图片工厂统一重命名,从1开始,方便程序进行。
在这里插入图片描述
在这里插入图片描述
最终的结果:
在这里插入图片描述
负样本不用管,也可以处理成50X50的,反正要比正样本的分辨率高,这样不容易出错(不然可能会遇到奇奇怪怪的报错)。

数据集的处理完全看个人,想要效果好一点的话,可以多处理一些样本,比如对称扩充旋转扩充。最终大概准备正样本:负样本=1:3 即可。

三、训练

然后去OpenCV的目录下,把opencv_createsamples.exeopencv_traincascade.exeopencv_world3415.dllopencv_world3415d.dll都拷贝到一个单独的文件夹下,后面两个可能由于OpenCV版本不同而名字不同
在这里插入图片描述
再把刚才处理好的neg文件夹和pos文件夹也拷贝过来。然后新建一个xml文件夹(放训练器中途的临时文件和最后的分类器文件)。

然后按照上面一样的步骤,利用dir /b/s/p/w *.jpg > pos.txt命令,在pos文件夹里的图片名字都保存到pos.txtneg文件夹同理。

然后统一在pos.txt的每一行后面加上1 0 0 20 20 ,前三个数字不管,20 20是分辨率。neg.txt文件不用加!!!加了要报错!!! 报错参考:traincascade报错

最后结果像这样:
(这一步可以用word里的替换,把jpg替换成jpg 1 0 0 20 20)
在这里插入图片描述
然后用cmd,在这个文件夹里运行

opencv_createsamples.exe -vec pos.vec -info pos.txt -num 700 -w 20 -h 20

-info,指样本说明文件
-vec,样本描述文件的名字及路径
-num,总共几个样本,要注意,这里的样本数是指标定后的20x20的样本数,而不是大图的数目,其实就是样本说明文件第2列的所有数字累加
-w -h指明想让样本缩放到什么尺寸。

最后一步:创建一个traincascade.bat文件,右键编辑,内容如下:
在这里插入图片描述

opencv_traincascade.exe -data xml -vec pos.vec -bg neg.txt -numPos 600 -numNeg 1000 -numStages 20 -w 20 -h 20 -mode ALL

pause

-data:指定保存训练结果的文件夹;
-vec:指定正样本集;
-bg:指定负样本的描述文件夹;
-numPos:指定每一级参与训练的正样本的数目要 小于正样本总数
-numNeg:指定每一级参与训练的负样本的数目 可以大于负样本图片的总数
-numStage:训练的级数,一般是 13-20级,越大越久,效果越好
-w:正样本的宽;
-h:正样本的高;
-minHitRate:每一级需要达到的命中率(一般取值0.95-0.995);
-maxFalseAlarmRate:每一级所允许的最大误检率,越小训练得越久,效果越好,默认0.5;
-mode:使用Haar-like特征时使用,可选BASIC、CORE或者ALL,默认ALL;

双击运行,就开始训练了。关于训练的其他问题可以参考这篇文章
在这里插入图片描述

四、测试

训练完成之后,会在xml文件夹中看到cascade.xml文件,这就是我们需要的分类器文件了。

测试代码:

import cv2
detector= cv2.CascadeClassifier('C:\\Users\\asus\\AppData\\Local\\Programs\\Python\\Python35\\Lib\\site-packages\\cv2\\data\\haarcascade_frontalface_default.xml')#人脸识别分类器
mask_detector=cv2.CascadeClassifier('D:\\facemask\\mask\\xml\\cascade.xml')#口罩识别分类器
cap = cv2.VideoCapture(0)
while True:
    ret, img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = detector.detectMultiScale(gray, 1.1, 3)
    for (x, y, w, h) in faces:
        face=img[y:y+h,x:x+w]
        mask_face=mask_detector.detectMultiScale(gray, 1.1, 5)
        for (x2,y2,w2,h2) in mask_face:
            cv2.rectangle(img, (x2, y2), (x2 + w2, y2 + h2), (0, 0, 255), 2)
    cv2.imshow('Mask Detector', img)
    cv2.waitKey(3)
cap.release()
cv2.destroyAllWindows()

有口罩
在这里插入图片描述
没口罩
请添加图片描述

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值