cascade自己训练级联分类器(人脸检测)

Odetta ·
更新时间:2024-09-20
· 701 次阅读

cascade训练简介

后面有详细解释,和步骤代码的实现,可能需要简单修改,建议代码自己先写着试试

训练步骤

下载文件包opencv。这里的opencv是指编译好的.exe文件,不是需要编译的source源码文件。建议下载3.4版本的,最新版可能训练步骤不同,这里我没有做仔细学习,毕竟新手,等以后熟练了再做解释。
windows版本:官网下载
iOS版本:官网下载
Android版本:官网下载
官网地址:https://opencv.org/releases/
但是有一点,官网嘛,外网比较慢,我下载了一晚上,也可以去csdn下载,就是需要金币,不太值。

样本收集
样本收集是个费时费力的活,当时在朋友圈喊了一声,同学把淘宝弄来的给我了,实际上符合条件的还是不够用的,所以大家可以找找其他图片。
样本分为正负样本集。
**正样本:**人脸图像,数量在一般在2k以上
**负样本:**非人脸任何图像,数量一般在5k以上
正负样本越多越好,当然,负样本要远大于正样本数量。

准备文件夹
这一步好说,让准备文件夹,主要是命令和文件夹有关,所以这一步要求大家和我准备一样的文件夹,如果你熟悉命令可以另说。

cascade文件夹:这是整个环境的文件夹,下面的文件夹和文件除非特殊特殊声明,都存放在这个文件夹下 neg文件夹:用于存放负样本集 pos文件夹:用于存放正样本集 opencv_world341.dll:该文件存放在步骤1下载好的文件夹中:G:\opencv\build\x64\vc15\bin,把它复制粘贴到cascade文件夹下 opencv_creaesamples.exe:该文件存放路径同上 opencv_traincascade.exe:该文件存放路径同上 xml文件夹:用于存放训练好的.xml文件 人脸图像一张:用于后期测试 修改正负样本照片 正样本: 修改成灰度图 大小:Haar特征2020;LBP特征2424 数量:2000以上 负样本: 修改成灰度图 大小:60*60 数量:5000以上 若样本直接修改可能会造成图片扭曲,因为图片不一定是n*n,可能是n*m的。 分别在pos文件夹neg文件夹下添加.txt文件pos.txtneg.txt。然后,八仙过海,各显神通,将文件填充如下:
neg.txt:文件路径+图像名写入文件中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VNVbZOEQ-1586010263149)(leanote://file/getImage?fileId=5e8886718540084b17000000)]
pos.txt:将图像名和1 0 0 20 20写入文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bixo0MGl-1586010263150)(leanote://file/getImage?fileId=5e8886ce8540084b17000001)]
上述可以直接用重定向符号输入,再使用文本的替代功能即可

dir/b > pos.txt

注意:将文件末尾的多余字符neg.txt和pos.txt删掉

开始生成pos.vec文件,进入cascade文件夹中,输入命令:

opencv_createsamples.exe -info pos\pos.txt -vec pos.vec -bg neg\neg.txt -num 2000 -w 20 -h 20

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-19M8Un7G-1586010263150)(leanote://file/getImage?fileId=5e888aac8540084b17000002)]

开始训练:

opencv_traincascade.exe -data xml -vec pos.vec -bg neg\neg.txt -numPos 2000 -numNeg 5000 -numStages 20 -featureType HAAR -w 20 -h 20

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4WqVbf45-1586010263150)(leanote://file/getImage?fileId=5e888b4c8540084b17000003)]
我电脑没有显卡,不知道这个训练吃显卡还是cpu,但是训练够慢的。

命令解释 opencv_createsamples.exe -info pos\pos.txt -vec pos.vec -bg neg\neg.txt -num 2000 -w 20 -h 20 -info 输入正样本描述文件,默认NULL -img 输入图像文件名,默认NULL -bg 负样本描述文件,文件中包含一系列的被随机选作物体背景的图像文件名,默认NULL -num 生成正样本的数目,默认1000 -bgcolor 背景颜色,表示透明颜色,默认0 -bgthresh 颜色容差,所有处于bgcolor-bgthresh和bgcolor+bgthresh之间的像素被置为透明像 素,也就是将白噪声加到前景图像上,默认80 -inv 前景图像颜色翻转标志,如果指定颜色翻转,默认0(不翻转) -randinv 如果指定颜色将随机翻转,默认0 -maxidev 前景图像中像素的亮度梯度最大值,默认40 -maxxangle X轴最大旋转角度,以弧度为单位,默认1.1 -maxyangle Y轴最大旋转角度,以弧度为单位,默认1.1 -maxzangle Z轴最大旋转角度,以弧度为单位,默认0.5
输入图像沿着三个轴进行旋转,旋转角度由上述3个值限定。 -num 训练的正样本图片数 -show 如果指定,每个样本都将被显示,按下Esc键,程序将继续创建样本而不在显示,默认为0(不显示) -scale 显示图像的缩放比例,默认4.0 -w 输出样本宽度,默认24 -h 输出样本高度,默认24 -vec 输出用于训练的.vec文件,默认NULL

我们也看到了,许多命令都是默认的

opencv_traincascade.exe -data xml -vec pos.vec -bg neg\neg.txt -numPos 2000 -numNeg 5000 -numStages 20 -featureType HAAR -w 20 -h 20 -data 目录名xml,存放训练好的分类器,如果不存在训练程序自行创建 -vec pos.vec文件,由opencv_createsamples生成 -bg 负样本描述文件, neg\neg.txt -numPos 每级分类器训练时所用到的正样本数目 -numNeg 每级分类器训练时所用到的负样本数目,可以大于-bg指定的图片数目 -numStages 训练分类器的级数,默认20级,一般在14-25层之间均可。 如果层数过多,分类器的fals alarm就更小,但是产生级联分类器的时间更长,分类器的hitrate就更小,检测速度就慢。如果正负样本较少,层数没必要设置很多。 -precalcValBufSize 缓存大小,用于存储预先计算的特征值,单位MB -precalcIdxBufSize 缓存大小,用于存储预先计算的特征索引,单位M币 -baseFormatSave 仅在使用Haar特征时有效,如果指定,级联分类器将以老格式存储 -stageType 级联类型,staticconst char* stageTypes[] = { CC_BOOST }; -featureType 特征类型,staticconst char* featureTypes[] = { CC_HAAR, CC_LBP, CC_HOG }; -w -h 训练样本的尺寸,必须跟使用opencv_createsamples创建的训练样本尺寸保持一致 -bt Boosted分类器类型 DAB-discrete Adaboost, RAB-RealAdaboost, LB-LogiBoost, GAB-Gentle Adaboost -minHitRate 分类器的每一级希望得到的最小检测率,总的最大检测率大约为min_hit_rate^number_of_stages -maxFalseAlarmRate 分类器的每一级希望得到的最大误检率,总的误检率大约为max_false_rate^number_of_stages -weightTrimRate Specifies whether trimming should beused and its weight. 一个还不错的数值是0.95 -maxDepth 弱分类器的最大深度,一个不错数值是1,二叉树 -maxWeightCount 每一级中弱分类器的最大数目

更多内容请搜索:opencv_createsamples源码剖析

python代码-图像裁剪 import cv2 import os dir_path = os.path.dirname("G:\\face_regconition\\opencv_5\\self_trian_cascade\\neg\\") neg_imgs = os.listdir("G:\\face_regconition\\opencv_5\\self_trian_cascade\\neg") i = 0 for i in neg_imgs: absolute_path = os.path.join(dir_path, i) img = cv2.imread(absolute_path) dst = cv2.resize(img, (60,60), 0, 0, cv2.INTER_LINEAR) #修改图片大小 a = cv2.imwrite(absolute_path, dst) if a == True: print(i) i += 1 print("over")

可以修改路径和参数改变图像信息

python代码-图片转灰度图 import cv2 import numpy as np import os neg_dir_path = os.path.dirname("G:\\face_regconition\\opencv_5\\self_trian_cascade\\neg\\") neg_imgs = os.listdir("G:\\face_regconition\\opencv_5\\self_trian_cascade\\neg") pos_dir_path = os.path.dirname("G:\\face_regconition\\opencv_5\\self_trian_cascade\\pos\\") pos_imgs = os.listdir("G:\\face_regconition\\opencv_5\\self_trian_cascade\\pos") def bgr2gray(imgs, dir_path): i = 1 for img in imgs: absolute_path = os.path.join(dir_path, img) img_bgr = cv2.imread(absolute_path) img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_RGB2GRAY) judge = cv2.imwrite("G:\\face_regconition\\opencv_5\\self_trian_cascade\\new"+ "\\" + str(i) + ".jpg", img_gray) if judge == 1: i += 1 os.remove(absolute_path) def bgr2gray_recurse(imgs, dir_path): i = 0 for dirs in imgs: new_dir = dir_path + "\\" +dirs if os.path.isdir(new_dir): imgs_name = os.listdir(dir_path + "\\" + dirs) for img in imgs_name: absolute_path = os.path.join(new_dir +"\\"+ img) if "Thumbs.db" not in absolute_path: img_bgr = cv2.imread(absolute_path) img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_RGB2GRAY) judge = cv2.imwrite(dir_path + "\\" + str(i) + ".jpg", img_gray) if judge == 1: i += 1 os.remove(absolute_path) bgr2gray(neg_imgs, neg_dir_path) bgr2gray_recurse(pos_imgs, pos_dir_path)

上面的代码也需要做稍许修改。上面的函数是对图片直接修改成灰度,下面是对树形目录修改的代码。

python代码-测试 import cv2 # 实例化人脸分类器 face_cascade = cv2.CascadeClassifier('G:\\face_regconition\\haarshare\\haarcascade_frontalface_default.xml') # 读取测试图片 img = cv2.imread('G:\\face_regconition\\opencv_5\\self_trian_cascade\\123.jpg', cv2.IMREAD_COLOR) # 将原彩色图转换成灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 开始在灰度图上检测人脸,输出是人脸区域的外接矩形框 faces = face_cascade.detectMultiScale(gray, 1.2, 8) # 遍历人脸检测结果 for (x, y, w, h) in faces: # 在原彩色图上画人脸矩形框 cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # 获取该人脸矩形框的感兴趣区域RoI, 浅复制 roi_gray = gray[y:y + h, x:x + w] roi_color = img[y:y + h, x:x + w] # 显示画好矩形框的图片 cv2.namedWindow('faces', 0) cv2.imshow('faces', img) # 等待退出键 cv2.waitKey(0) # 销毁显示窗口 cv2.destroyAllWindows()

由于写总结的时候这篇文章还没写完,所以用的.xml文件是opencv自己训练好的。等训练好,用xml文件夹下的非stages文件即可。

其他

还有类似修改文件名的代码:

os.rename(oldname, newname)

剩下的,就是数据了。数据我放在csdn的网站上,请依情况自行参考。开源,不要金币。
文件下载下来之后,把xml文件夹里面的文件删掉,neg.txtpos.txt中的内容按照自己的存放地址替换一下,删掉最后的一行不一样的文字。

参考:
https://blog.csdn.net/lql0716/article/details/72566839

https://blog.csdn.net/weixin_41799483/article/details/80567909


作者:那我就换个名字吧



人脸检测 CASCADE 训练 分类 分类器 级联

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章