用opencv训练LBP特征分类器生成xml文件

需要工具:opencv_createsamples.exe 、opencv_traincascade.exe 、opencv_world3414.dll 和 opencv_world3414d.dll (这些都在下载的opencv中的,我的opencv版本为opencv-3.4.14-vc14_vc15地址是F:\document\pycharm1\opencv\build\x64\vc15\bin)
如果不想进行下载这些个训练工具,我已经准备好放到百度网盘里了,有需要的自取。(链接:https://pan.baidu.com/s/158m6bpkiVWF29S7rbuIfWg
提取码:pluo )

一、准备工作
1.正负样本的准备:
(1)如果你找的正负样本不多,可进行正负样本的旋转和镜像操作。(在进行旋转、镜像等操作前建议先调整照片的像素大小)

推荐使用软件ACDSee官方免费版,安装打开后找到样本所在文件夹,进行Ctrl+A全选,右击找到批量,就可以进行旋转、调大小、转格式等操作了。

我们进行的是对安全帽模型的训练,在进行安全帽正样本的获取时,先进行爬取了2000张佩戴安全帽的人或场景,但是对于正样本的要求是尽可能少的杂质,我们也找了获取感兴趣区域的一些文章,各种方法,但是我们认为效果不一定好,索性我们自己进行照片的剪裁(我们有7个人)。之后就对正样本进行了调大小(LBP一般格式是24x24、HAAR一般使用格式是20x20),调好之后进行旋转、镜像等获取更多的正样本,再之后把所有的正样本放到一个文件夹里进行统一重命名,在之后进行对正样本转换格式(jpg转bmp)再之后进行灰度的转换。
灰度的转换我用的是python代码,既简单有快捷。代码如下:

import cv2
import os

input_dir = 'F:\document\dachuang\\2\\000'
out_dir = 'F:\document\dachuang\\2\hui'
a = os.listdir(input_dir)
for i in a:
    img = cv2.imread(input_dir+'/'+i)
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    cv2.imencode('.bmp', gray)[1].tofile(out_dir+'/'+i)

之后再对负样本进行相似的操作(样本大小可以不一致,但必须比正样本尺寸大)

部分正样本:

OpenCV级联分类器训练与使用 opencv训练分类器生成xml_python


部分负样本:

OpenCV级联分类器训练与使用 opencv训练分类器生成xml_xml_02


二、创建正负样本描述性文件

在某个盘里进行创建文件夹TrainTest,把训练工具(opencv_createsamples.exe 、opencv_traincascade.exe 、opencv_world3414.dll 和 opencv_world3414d.dll)放在这个文件夹里。

在TrainTest里创建三个文件夹,分别为pos、neg、xml。pos文件夹中存放准备好的正样本图片,neg文件夹中存放准备好的负样本图片,xml文件夹中存放训练好的xml文件。

为正样本创建描述文件格式文件pos.txt,具体做法如下:

打开cmd,cd 到pos文件夹所在位置,输入代码dir /b > pos.txt 为负样本创建描述文件格式文件neg.txt:

cd到neg文件夹所在位置,输入代码

dir /b > neg.txt生成后还需要一定的修改:

打开pos.txt, 使用替换功能,把所有的bmp 换成 bmp 1 0 0 24 24,将所有的图片前都加上文件夹所在的绝对路径

然后在pos.txt文件里将最后一行的空格和pos.txt删掉,保存。

修改完以后是这样的:

OpenCV级联分类器训练与使用 opencv训练分类器生成xml_opencv_03


打开neg.txt,使用替换功能将所有的图片前都加上文件夹所在的绝对路径

然后在neg.txt文件里将最后一行的空格和neg.txt删掉,保存。

修改完以后是这样的:

OpenCV级联分类器训练与使用 opencv训练分类器生成xml_opencv_04

然后要把修改好的pos.txt和neg.txt放到pos和neg文件夹的同级目录下,到这里就可以进行训练了。

三、训练模型

1.使用opencv_createsamples.exe创建样本:

在cmd里cd到TrainTest文件夹下,执行指令:

opencv_createsamples.exe -info pos.txt -vec detect_number.vec -bg neg.txt -num 6256 -w 24 -h 24参数解释:

-info:就是pos.txt的位置,可以直接使用绝对地址避免出错

-vec 是你生成vec文件的位置和名称

-bg 就是neg.txt的位置,同样也可以直接使用绝对地址

-num 正样本的数量,有多少正样本就写多少

-w -h 正样本的宽高

执行后结果如下:

OpenCV级联分类器训练与使用 opencv训练分类器生成xml_opencv_05

必须要出现你正样本数目的samples。(如果没出现,要检查一下前面的步骤)

2.使用opencv_traincascade.exe开始训练:
输入命令:opencv_traincascade.exe -data xml -vec detect_number.vec -bg neg.txt -numPos 5400 -numNeg 10846 -numStages 20 -featureType LBP -w 24 -h 24

参数解释:

-data 就是你存放训练好的xml文件的文件夹,这个一定要事先创建好
 -vec 是之前生成vec文件
 -bg 就是neg.txt的位置
 -numPos 正样本的数量,这里填的比正样本数量稍微少一点(一般比正样本的0.8倍或0.9倍少),避免出错
 -numNeg 负样本的数量,有多少填多少
 -numStages 训练步数
 -featureType ,就是特征类型
 -w -h 是正样本的宽高

部分训练图如下:

OpenCV级联分类器训练与使用 opencv训练分类器生成xml_opencv_06


OpenCV级联分类器训练与使用 opencv训练分类器生成xml_xml_07


OpenCV级联分类器训练与使用 opencv训练分类器生成xml_OpenCV级联分类器训练与使用_08


OpenCV级联分类器训练与使用 opencv训练分类器生成xml_计算机视觉_09


这里我之前出错了一次,然后第二张图的步骤是从步骤1开始的。(一般出错都是numPos的正样本数目写的不合理,防止出错就写成少于正样本数目的0.8倍)

训练完成后在xml文件夹里会生成一系列xml文件,最后能用的文件是cascade.xml

测试生成的xml模型:

import cv2
detector = cv2.CascadeClassifier('F:\\document\\dachuang\\TrainTest\\xml\\cascade.xml')
cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = detector.detectMultiScale(gray,1.1,3,0,(100,100))
    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
        cv2.imshow('frame', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
cap.release()
cv2.destroyAllWindows()

ok,大功告成!