基于OpenCV训练口罩检测数据集并测试
以下内容是利用opencv自带的训练器opencv_traincascade.exe与opencv_createsamples.exe,来对口罩数据集进行训练。内容是自己操作过程中的笔记,可能会有些杂乱,其他的可以查看一下参考资料。
文章目录
- 0. 检测器初体验
- 1. 数据的准备
- 2. 创建正样本vec文件
- 3. 训练获得xml文件
- 4. 利用训练出来的cascade.xml来验证
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:breakcap.release()
cv2.destroyAllWindows()
这里体验了一下opencv自带的xml来构建人脸检测器,但是,检测得过程不是特别的稳定。关于opencv自带的检测器其实还有关于其他方面的,如下所示,具体的可以自行体验。
1. 数据的准备
正样本:仅包含被检测物体的样本,并且距离边界尽量要小,图片尺寸大小一致,附件需要有路径还需要添加重复吃属于目标图片的矩形框。
eg:E:\学习\机器学习\数据集\mask2\positive\100000.jpg 1 0 0 20 20
ps:这里1表示当前图片重复出现的次数是1, 0 0 50 50表示目标图片大小是矩形框从(0,0)到(50,50)
负样本:不包含被检测物体的样本,图片尺寸大小无要求,路径存放没有要求。
eg:E:\学习\机器学习\数据集\mask2\negative\100000.jpg
这里口罩的数据集中的正样本数为: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
输入完了之后就会生成对应的file,里面存储的是当前文件夹下全部后缀名为md的文件名。
2. 创建正样本vec文件
opencv_createsamples.exe -vec pos.vec -info posdata.txt -num 352 -w 20 -h 20
成功获得pos.vec文件
- 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
参数列表如下所示:
- data <cascade_dir_name>:应存储经过训练的分类器的位置。此文件夹应事先手动创建。
- vec <vec_file_name>: 带有正样本的 vec 文件(由 opencv_createsamples 实用程序创建)。
- bg <background_file_name>: 背景描述文件。这是包含负样本图像的文件。
- numPos <number_of_positive_samples>:每个分类器阶段训练中使用的正样本数。
- numNeg <number_of_negative_samples>:每个分类器阶段训练中使用的负样本数。
- numStages <number_of_stages>:要训练的级联阶段数。
- precalcValBufSize <precalculated_vals_buffer_size_in_Mb>:预先计算的特征值的缓冲区大小(以 Mb 为单位)。您分配的内存越多,训练过程就越快,但请记住,两者的-precalcValBufSize总和-precalcIdxBufSize不应超过您可用的系统内存。
- precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb>:预先计算的特征索引的缓冲区大小(以 Mb 为单位)。您分配的内存越多,训练过程就越快,但请记住,两者的-precalcValBufSize总和-precalcIdxBufSize不应超过您可用的系统内存。
- baseFormatSave: 这个论点在 Haar-like 特征的情况下是真实的。如果指定,级联将以旧格式保存。这只适用于向后兼容的原因,并允许用户坚持使用旧的已弃用界面,至少可以使用较新的界面训练模型。
- numThreads <max_number_of_threads>:训练期间使用的最大线程数。请注意,实际使用的线程数可能会更少,具体取决于您的机器和编译选项。默认情况下,如果您使用 TBB 支持构建 OpenCV,则会选择最大可用线程,这是优化所必需的。
- acceptanceRatioBreakValue <break_value>:此参数用于确定您的模型应该保持学习的精确程度以及何时停止。一个好的指导原则是训练不超过 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文件
ps:这个xml的文件夹需要自己创建
整个bin的目录文件如下所示:
在训练过程中会出现了以下的问题:
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.
这不是一个错误。鉴于所提供的样本设置,级联已达到其预期的潜力。需要添加更多的数据或者设置更苛刻条件。
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提供的工具训练不是很稳定。
有机会下次使用深度学习的方法来做一些口罩检测的项目。
参考资料:
- 一些训练过程中可能出现的错误:https://www.cnblogs.com/hyacinthwyd/p/8885003.html
- 使用opencv的级联分类器训练样本获得xml数据的方法:https://blog.csdn.net/qq_43475606/article/details/110054791
- 基于Opencv的口罩佩戴识别系统:https://blog.csdn.net/cj151525/article/details/104984897
基于OpenCV训练口罩检测数据集并测试相关推荐
- 实战CenterNet,训练猫脸关键点检测数据集并测试
实战CenterNet,训练猫脸关键点检测数据集并测试 一.本机配置 二.环境搭建 三.数据准备 四.开始训练 五.测试 六.references 这里主要记录一下,调试CenterNet用来训练猫脸 ...
- 一分钟教会您使用Yolov5训练自己的数据集并测试
1. 下载YOLO项目代码 点击这里下载并解压YOLO的官方代码:https://github.com/ultralytics/yolov5/tree/v5.0 2. 环境安装 cd进入到下载的YOL ...
- Mxnet训练自己的数据集并测试
使用Mxnet训练图片分类类器 1.准备数据: (1)建立一个根目录然后,再为每一个类别的图片建立一个子文件夹,把每一类图片放入对应的子文件夹即可. --root: ----class1 ----cl ...
- Python口罩识别检测全网最全OpenCV训练分类器具体步骤(以训练口罩检测分类器为例)附分类器和数据集下载地址
声明 本文仅在CSDN发布,其他均为盗版.请支持正版! 正版链接: https://blog.csdn.net/meenr/article/details/115825671 OpenCV训练口罩检测 ...
- 使用opencv训练目标检测模型基于cascade模型
使用opencv训练目标检测模型基于cascade模型 基于Haar特征的cascade分类器(classifiers) 是Paul Viola和 Michael Jone在2001年,论文" ...
- Ultralytics公司YOLOv8来了(训练自己的数据集并基于NVIDIA TensorRT和华为昇腾端到端模型加速)--跟不上“卷“的节奏
Official YOLOv8 训练自己的数据集并基于NVIDIA TensorRT和华为昇腾端到端模型加速 说明: 本项目支持YOLOv8的对应的package的版本是:ultralytics-8. ...
- 基于openMV的口罩检测
基于openMV的口罩检测 什么是openmv openmv可以做什么 学习过程 好久没有更新了,这学期过得有点狼狈,暑假留校做一辆stm32智能小车,会不时更新一些我学习到的东西,今天分享一下我这两 ...
- 基于opencv的人脸检测与识别(python)(1)
基于opencv的人脸检测与识别(python语言)(1) 人脸检测和识别技术就目前而言,已经相对成熟,各类算法层出不穷,这都归功于各位奋斗在一线的大佬的努力(站在巨人的肩膀上的感觉就是爽).本文是参 ...
- 基于opencv实现人脸检测
基于opencv实现人脸检测 opencv简述 opencv是一个开源的计算机视觉库,它有着C++,Python,Java等接口,支持Windows,Linux,Mac OS,IOS 和 Androi ...
最新文章
- 请编写出一个html页面 令其输出,javaweb程序设计案例教程_课后习题1.pdf
- crontab添加定时任务
- hprof文件中导出图片
- 割平面法只能求解纯整数规划吗_【DMC第四讲】整数规划
- 数组tostring方法_数组toString()方法以及JavaScript中的示例
- 利用WindowsAPI创建窗体(c++)
- [Ubuntu] zsh
- 浅谈 voip 未來企業通信
- 《狂人C》阅读笔记(1)
- 类中不写成员函数易犯错误模型
- android 极光推送测试,Android 极光推送基本步骤
- Sumifs函数多条件求和的9个实例
- 计算机储位分配,仓库储位分配的基本思路与原则
- React高级(五)
- PTA 7-154 置点不动产——认真学习,努力工作买买房子吧
- 怎么去开发一款软件?
- python拟合sir模型_SI,SIS,SIR模型的正确实现(python)
- 【20保研】北京大学信息工程学院关于举办 “2019年全国优秀大学生夏令营”的通知...
- Javascript迭代、递推、穷举、递归常用算法实例讲解
- 词根:lun = moon, 表示“月亮”
热门文章
- 游戏服务器引擎的设计(二)开发游戏服务器底层 及libuv使用
- access数据库窗体设计实验报告_大学Access数据库实验报告
- PHP实现量化交易,量化交易干货丨如何使用DolphinDB计算K线
- dede织梦data目录正确迁移及引起的问题解决方法【转】
- esp32-pico-d4开发环境配置
- 高并发情况处理(乐观锁悲观锁)
- Linux操作系统下查询NVMe盘符、Slot ID和Bus ID的对应关系
- 奶块服务器正在维护是什么意思,奶块例行维护什么意思 | 手游网游页游攻略大全...
- MTK Android 13平台开关机动画铃声客制化
- Whisper.cpp 编译使用