基于OpenCV训练口罩检测数据集并测试

简介: 基于OpenCV训练口罩检测数据集并测试

0. 检测器初体验


由于这里需要opencv自带的xml文件,这里我用的是conda的虚拟环境,所以xml文件处于E:\anacanda\envs\pytorch\Lib\site-packages\cv2\data中,这里使用了一个关于人脸检测的xml文件。


import cv2
#识别人脸的xml文件,构建人脸检测器
facexml_path = "E:/anacanda/envs/pytorch/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml"
detector= cv2.CascadeClassifier(facexml_path)
#获取0号摄像头的实例
cap = cv2.VideoCapture(0)
while True:
    # 就是从摄像头获取到图像,这个函数返回了两个变量,第一个为布尔值表示成功与否,以及第二个是图像。
    ret, img = cap.read()
    assert ret is True,"Cramae Capture Nothing"
    # 转为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    #获取人脸坐标
    faces = detector.detectMultiScale(gray, 1.1, 3)
    for (x, y, w, h) in faces:
        #参数分别为 图片、左上角坐标,右下角坐标,颜色,厚度
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
    cv2.imshow('Test Detection', img)
    # 在10ms内等待按键,否则显示下一帧,也就是10ms内按Esc退出循环
    if cv2.waitKey(10) == 27:
        break
cap.release()
cv2.destroyAllWindows()


这里体验了一下opencv自带的xml来构建人脸检测器,但是,检测得过程不是特别的稳定。关于opencv自带的检测器其实还有关于其他方面的,如下所示,具体的可以自行体验。

image.png


1. 数据的准备


  • 正样本:仅包含被检测物体的样本,并且距离边界尽量要小,图片尺寸大小一致,附件需要有路径还需要添加重复吃属于目标图片的矩形框。

eg:E:\学习\机器学习\数据集\mask2\positive\100000.jpg 1 0 0 20 20

ps:这里1表示当前图片重复出现的次数是1, 0 0 50 50表示目标图片大小是矩形框从(0,0)到(50,50)

image.png


  • 负样本:不包含被检测物体的样本,图片尺寸大小无要求,路径存放没有要求。

eg:E:\学习\机器学习\数据集\mask2\negative\100000.jpg

image.png

这里口罩的数据集中的正样本数为:352,负样本数为:1053


  • 正样本名字处理脚本

这里对正样本进行名字的添加处理我写了一个脚本来实现,具体变现为:E:\学习\机器学习\数据集\mask2\positive\100000.jpg -> E:\学习\机器学习\数据集\mask2\positive\100000.jpg 1 0 0 20 20


import os
# 读取文件所有数据
rf = open(r"E:/学习/机器学习/数据集/mask2/positive/posdata.txt", "r")
rdata = rf.readlines()
# 改写数据并保存
wdata = []
for data in rdata:
    oneline = data[:-1] + " 1 0 0 20 20\n"
    wdata.append(oneline)
# 写入数据
wf = open(r"E:/学习/机器学习/数据集/mask2/positive/posdata2.txt", "w")
wf.writelines(wdata)
# 关闭文件描述符
rf.close()
wf.close()


  • 保存图片文件名处理脚本

把图片文件名保存在一个文件中,构建成一个函数使用.

不过这个操作可以通过使用cmd打开对应的文件夹,输入:dir /b/s/p/w *.jpg > your_filename.txt 来实现,简洁版本是:dir /b *.jpg > your_filename.txt


import os
# dir:图片文件夹的路径
# filename:保存文件名称
def SaveImageName(dir, filename):
    imgnames = os.listdir(dir)
    imglists = []
    for imgname in imgnames:
        imgname = dir + '/' + imgname + '\n'
        imglists.append(imgname)
    wf = open(os.path.join(dir, filename), "w")
    wf.writelines(imglists)
    wf.close()
# 测试函数
imgdir = "E:/学习/机器学习/数据集/mask2/negative"
filename = "negative.txt"
SaveImageName(imgdir, filename)


ps:dir /b *.jpg > your_filename.txt

image.png

输入完了之后就会生成对应的file,里面存储的是当前文件夹下全部后缀名为md的文件名。


2. 创建正样本vec文件


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

image.png

成功获得pos.vec文件

image.png

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

详细参数见官方资料:https://docs.opencv.org/3.4.1/dc/d88/tutorial_traincascade.html


3. 训练获得xml文件


最后运行成功的代码:


opencv_traincascade.exe -data xml -vec pos.vec -bg negdata.txt -numPos 100 -numNeg 300 -numStages 20 -w 20 -h 20 -mode ALL

image.png


参数列表如下所示:


  • data :应存储经过训练的分类器的位置。此文件夹应事先手动创建。
  • vec : 带有正样本的 vec 文件(由 opencv_createsamples 实用程序创建)。
  • bg : 背景描述文件。这是包含负样本图像的文件。
  • numPos :每个分类器阶段训练中使用的正样本数。
  • numNeg :每个分类器阶段训练中使用的负样本数。
  • numStages :要训练的级联阶段数。
  • precalcValBufSize :预先计算的特征值的缓冲区大小(以 Mb 为单位)。您分配的内存越多,训练过程就越快,但请记住,两者的-precalcValBufSize总和-precalcIdxBufSize不应超过您可用的系统内存。
  • precalcIdxBufSize :预先计算的特征索引的缓冲区大小(以 Mb 为单位)。您分配的内存越多,训练过程就越快,但请记住,两者的-precalcValBufSize总和-precalcIdxBufSize不应超过您可用的系统内存。
  • baseFormatSave: 这个论点在 Haar-like 特征的情况下是真实的。如果指定,级联将以旧格式保存。这只适用于向后兼容的原因,并允许用户坚持使用旧的已弃用界面,至少可以使用较新的界面训练模型。
  • numThreads :训练期间使用的最大线程数。请注意,实际使用的线程数可能会更少,具体取决于您的机器和编译选项。默认情况下,如果您使用 TBB 支持构建 OpenCV,则会选择最大可用线程,这是优化所必需的。
  • acceptanceRatioBreakValue :此参数用于确定您的模型应该保持学习的精确程度以及何时停止。一个好的指导原则是训练不超过 10e-5,以确保模型不会过度训练您的训练数据。默认情况下,此值设置为 -1 以禁用此功能。

详细参数见官方资料:https://docs.opencv.org/3.4.1/dc/d88/tutorial_traincascade.html


ps:这里需要小心调整numPos与numNeg的大小,这里指的每个分类器阶段训练中使用样本数,设置得过大可能会引起错误。设置的numPos过大,由于训练时pos count 会从你设置的numPos增大,每一级都按一定的次序增大,后来可能会超过样本库中正样本的个数,就会报这个错误。


Error: Bad argument (Can not get new positive sample. The most

possible reason is insufficient count of samples in given vec-file.


根据参考资料3,这里设置调整的值一般满足关系为:


  • numneg (负样本)数设置为总数的一半,或者其他值,
  • numpos (正样本)数设置为负样本数的3分1

训练完成后,得到最后的casce.xml文件

image.png


ps:这个xml的文件夹需要自己创建


整个bin的目录文件如下所示:

image.png


在训练过程中会出现了以下的问题:


1)Error: Bad argument (Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file


opencv_traincascade.exe -data xml -vec pos.vec -bg negdata.txt -numPos 500 -numNeg 656 -numStages 20 -w 20 -h 20 -mode ALL


出现问题:


Error: Bad argument (Can not get new positive sample. The most

possible reason is insufficient count of samples in given vec-file

opencv_traincascade.exe -data xml -vec pos.vec -bg negdata.txt -numPos 352 -numNeg 1053 -numStages 20 -w 20 -h 20 -mode ALL


出现问题:


Error: Bad argument (Can not get new positive sample. The most

possible reason is insufficient count of samples in given vec-file.


问题原因:设置的numPos过大,由于训练时pos count 会从你设置的numPos增大,每一级都按一定的次序增大,后来可能会超过样本库中正样本的个数,就会报这个错误。


2)Required leaf false alarm rate achieved. Branch training terminated.

image.png

这不是一个错误。鉴于所提供的样本设置,级联已达到其预期的潜力。需要添加更多的数据或者设置更苛刻条件。


4. 利用训练出来的cascade.xml来验证


下面是调用摄像头,利用刚刚训练出来的xml文件来构建口罩的检测器来对每一帧图像进行检测


import cv2
# 构建两个检测器
facexml_path = "E:/anacanda/envs/pytorch/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml"
maskxml_path = "E:/project/Opencv_Project/dataset/bin/xml/cascade.xml"
face_detector = cv2.CascadeClassifier(facexml_path)
mask_detector = cv2.CascadeClassifier(maskxml_path)
# 获取摄像头的实例
cap = cv2.VideoCapture(0)
# 不断对每一帧进行处理
while True:
    # 返回的第一个参数是成功与否,第二个参数的一帧图像
    ret, img = cap.read()  
    assert ret is True,"Capture Noting"   # 如果ret为空则报错
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    #获取人脸坐标
    faces = face_detector.detectMultiScale(gray, 1.1, 3)
    # 依次遍历人脸对象
    for (x, y, w, h) in faces:
        #参数分别为 图片、左上角坐标,右下角坐标,颜色,厚度
        cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
        face=img[y:y+h,x:x+w]  # 裁剪坐标为[y0:y1, x0:x1]
        mask_face=mask_detector.detectMultiScale(face, 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 Detection', img)
    # 在10ms内等待按键,否则显示下一帧,也就是10ms内按Esc退出循环
    if cv2.waitKey(10) == 27:
        break
# 释放缓存,清理窗口
cap.release()
cv2.destroyAllWindows()


实验结果:


这里我该了两次参数训练了两个cascade.xml文件,但是效果好像都不好;另外我私下问了参考资料[3]的博主,拿了其提供的cascade.xml文件(这里表示感谢!!有需要的可以关注他的公众号:矩阵科学),好像效果还是不太好,甚至没有检测出口罩,一方面可能是我电脑摄像头不好,另一方面可能使用opencv提供的工具训练不是很稳定。


有机会下次使用深度学习的方法来做一些口罩检测的项目。


参考资料:

  1. 一些训练过程中可能出现的错误:https://www.cnblogs.com/hyacinthwyd/p/8885003.html
  2. 使用opencv的级联分类器训练样本获得xml数据的方法:https://blog.csdn.net/qq_43475606/article/details/110054791
  3. 基于Opencv的口罩佩戴识别系统:https://blog.csdn.net/cj151525/article/details/104984897


目录
相关文章
|
1月前
|
机器学习/深度学习 编解码 监控
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章详细介绍了如何使用YOLOv8进行目标检测任务,包括环境搭建、数据准备、模型训练、验证测试以及模型转换等完整流程。
1392 1
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 监控 计算机视觉
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
本文介绍了如何使用YOLOv7进行目标检测,包括环境搭建、数据集准备、模型训练、验证、测试以及常见错误的解决方法。YOLOv7以其高效性能和准确率在目标检测领域受到关注,适用于自动驾驶、安防监控等场景。文中提供了源码和论文链接,以及详细的步骤说明,适合深度学习实践者参考。
343 0
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 并行计算 数据可视化
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用PaddleClas框架完成多标签分类任务,包括数据准备、环境搭建、模型训练、预测、评估等完整流程。
98 0
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 JSON 算法
语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)
本文介绍了DeepLab V3在语义分割中的应用,包括数据集准备、模型训练、测试和评估,提供了代码和资源链接。
198 0
语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)
|
1月前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
52 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 XML 并行计算
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用YOLOX完成图像目标检测任务的完整流程,包括数据准备、模型训练、验证和测试。
173 0
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
11天前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
43 3
|
1月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
64 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
2月前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
245 7
Jmeter实现WebSocket协议的接口测试方法
|
2月前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
254 3
快速上手|HTTP 接口功能自动化测试
下一篇
无影云桌面