Opencv级联分类器训练自己的.xml文件

1.首先了解一点opencv前置知识点

(1)Opencv下载和导入Visual studio 2022
https://mydreamambitious.blog.csdn.net/article/details/124902276
(2)visual studo 2022中使用Opencv人脸检测
https://mydreamambitious.blog.csdn.net/article/details/124903134
(3)HAAR与LBP的人脸检测时间效率比较
https://mydreamambitious.blog.csdn.net/article/details/124912506

2.相关文件的准备

在这里插入图片描述
对上面的文件打开细看:
(1)negative文件(这里的图片是经过一定处理之后的,下面会给出程序):
在这里插入图片描述
positive文件中也是和negative一样是图片(positive的图片也是经过一定处理之后的,下面会给出程序):

(2)neg.txt文件(通过程序处理的,下面给出程序)
在这里插入图片描述
(3)两个工具的准备
下载opencv:https://www.raoyunsoft.com/opencv/opencv-3.4.2/
在这里插入图片描述
下载完之后安装会的一个opencv文件,进入:E:\opencv\build\x64\vc14\bin
这里面,看到两个文件,将这两个文件拷贝到要训练的地方
在这里插入图片描述
(4)pos.txt文件(里面是正样本的图片路径和相关信息)
在这里插入图片描述
这里关于图片正负样本的说明:
(1)正样本:包含要检测的物体,如果是人脸的话,最好只包含人脸(这样效果更好);
(2)负样本:不包含要检测的物体(只要不包含要检测的物体就行)

3.图片和图片路径的处理程序(python)

对正样本的处理

import os
import glob
import traceback
from PIL import Image

# 首先将图片转换为规定的格式
def convertPic(pic, saveDir, width=300, height=300):
    try:
        #读取图片
        img = Image.open(pic)
        #缩放图片
        new_img = img.resize((width, height), Image.ANTIALIAS)
        #保存图片
        new_img.save(os.path.join(saveDir, os.path.basename(pic)))
    except:
        print('open image fail!')
        traceback.print_exception(BaseException)

# 修改图片的名字
def Resname(pic):
    num = 1
    for filename in os.listdir(pic):
        os.rename(os.path.join(pic, filename), os.path.join(pic, str(num) + ".jpg"))
        num += 1

#将图片相关信息保存到.txt文件中
def convertDat(picDir,saveDir):
    for pic in glob.glob(picDir+'*.png'):
        text=("%s %d %d %d %d %d")%(pic,1,0,0,30,30)
        with open(saveDir,'a') as fp:
            fp.write(text+'\n')

if __name__ == '__main__':
    print('Pycharm')
    #正样本的所有图片路径
    picDir="E:\\conda_3\\PyCharm\\OpenCV\\FaceDetect\\opencv.xml\\OpencvTrain\\positive\\img\\Total\\"
    #正样本图片经过处理之后保存的位置
    saveDir="E:\\conda_3\\PyCharm\\OpenCV\\FaceDetect\\opencv.xml\\OpencvTrain\\positive\\Convert_img\\"
    #将图片相关信息保存的文件路径,这里的pos.dat改为.txt文件也可以
    saveDat="E:\\conda_3\\PyCharm\\OpenCV\\FaceDetect\\opencv.xml\\OpencvTrainCreate\\pos.dat"

    for pic in glob.glob(picDir+"*.png"):
        convertPic(pic,saveDir)
     Resname(saveDir)

    convertDat(picDir,saveDat)

负样本处理的过程也是一样的,只是因为我这里使用的图片格式不一样,所以将正负样本的处理程序写成了两个文件。

import os
import glob
import traceback
from PIL import Image

#首先将图片转换为规定的格式
def convertPic(pic,saveDir,width=300,height=300):
    try:
        #读取图片
        img=Image.open(pic)
        #缩放图片
        new_img=img.resize((width,height),Image.ANTIALIAS)
        #保存图片
        new_img.save(os.path.join(saveDir,os.path.basename(pic)))
    except:
        print('open image fail!')
        traceback.print_exception(BaseException)

#修改图片的名字
def Resname(pic):
    num=1
    for filename in os.listdir(pic):
        os.rename(os.path.join(pic,filename),os.path.join(pic,str(num)+".jpg"))
        num+=1

#将处理的图片路径存入文件saveDir
def convertDat(picDir,saveDir):
    for pic in glob.glob(picDir+'*.jpg'):
        text=("%s")%(pic)
        with open(saveDir,'a') as fp:
            fp.write(text+'\n')

if __name__ == '__main__':
    print('PyCharm')
    picDir="E:\\conda_3\\PyCharm\\OpenCV\\FaceDetect\\opencv.xml\\OpencvTrainCreate\\negative\\"
    saveDir="E:\\conda_3\\PyCharm\\OpenCV\\FaceDetect\\opencv.xml\\OpencvTrain\\negative\\convert_img\\"
    saveTxt=r"E:\conda_3\PyCharm\OpenCV\FaceDetect\opencv.xml\OpencvTrainCreate\neg.txt"

    for pic in glob.glob(picDir+"*.jpg"):
        convertPic(pic,saveDir)
    Resname(saveDir)
    convertDat(picDir,saveTxt)


# See PyCharm help at https://www.jetbrains.com/help/pycharm/


通过上面的处理之后得到所需要训练的所有文件

4.训练

(1)开始可能会遇到这个问题
在这里插入图片描述
解决方案:
在这里插入图片描述
(2)打开cmd,进入到当前训练的文件位置:
输入生成正样本文件语句:opencv_createsamples.exe -info pos.txt -vec pos.vec -bg neg.txt -numPos 25 -numNeg 72 -w 30 -h 30
参数的解释:

-data <cascade_dir_name>  用于保存训练好的文件位置,如不存在训练程序会创建它,用于存放训练好的分类器;
-vec<vec_file_name>:输出文件,其中包含用于训练的正样本;
-img<image_file_name>:输入图片文件名;
-bg<background_file_name>:背景图片的描述,文件中包含一系列图片路径,其实也就是包含负样本图片的路径的文件;
-num<number_of_samples>:生成的正样本的数目;
-bgcolor<background_color>:背景颜色(目前为灰度图);背景颜色表示透明颜色。因为图像压缩可造成颜色偏差,颜色的容差可以由 -bgthresh 指定;所有处于 bgcolor-bgthresh 和bgcolor+bgthresh 之间的像素都被设置为透明像素。
-inv:如果指定该标志的话,前景图片的颜色将翻转;
-randinv:表示颜色随机的翻转;
-maxidev<max_intensity_deviation>:前景样本里像素的亮度梯度的最大值;
-maxxangle<max_x_rotation_angle>:X轴最大旋转角度,必须以弧度为单位;
-maxyangle<max_y_rotation_angle>:Y轴最大旋转角度,必须以弧度为单位;
-maxzangle<max_z_rotation_angle>:Z轴最大旋转角度,必须以弧度为单位;
-show:如果指定该选项,每个样本都将被显示。如果按下 Esc 键,程序将继续创建样本但不再显示。
-numPos 10 :正样本的数量;
-numNeg 50 :负样本的数量(neg文件夹下有50张负样本);
-numStages 15 :样本训练的层数;
-featureType<{HAAR(default), LBP}>      特征的类型: HAAR - 类Haar特征; LBP - 局部纹理模式特征;
-w<sample_width>:输出样本的宽度(以像素为单位);
-h<sample_height>:输出样本的高度(以像素为单位)。

在这里插入图片描述
(3)训练
可能会遇到这个问题
Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file.
解决方案:
设置的 numPos 过大,由于训练时POS count 会从你设置的numPos增大,每一级都按一定的次序增大,后来可能会超过样本库中正样本的个数,就会报这个错误。

输入训练语句:opencv_traincascade.exe -data xml -vec pos.vec -bg neg.txt -numPos 25 -numNeg 72 numStages 6 -featureType LBP -w 30 -h 30

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.训练结果

在这里插入图片描述

6.对训练的.xml文件测试

关于Opencv下载和导入Visual studio 2022
https://mydreamambitious.blog.csdn.net/article/details/124902276

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//haarcascade_frontalcatface.xml
//opencv_world455d.lib
//E:\Visual studio 2019\Opencv\opencv\build\include
//E:\Visual studio 2019\Opencv\opencv\build\x64\vc15\lib
String filename = "E:\\conda_3\\PyCharm\\OpenCV\\FaceDetect\\CascadeClassifer\\haarcascade_frontalface_alt.xml";
String filename_self = "E:\\conda_3\\PyCharm\\OpenCV\\FaceDetect\\opencv.xml\\OpencvTrainCreate\\xml\\cascade.xml";
String filename_ther = "E:\\conda_3\\PyCharm\\OpenCV\\FaceDetect\\课程配套源代码\\cascade.xml";

CascadeClassifier face_classifiler;

int main() {
	if (!face_classifiler.load(filename_self)) {
		printf("The CascadeClassifier load fail!");
		return 0;
	}
	//打开摄像头实时检测
	namedWindow("face", WINDOW_AUTOSIZE);
	VideoCapture capture(0);
	Mat frame;
	Mat gray;
	while (capture.read(frame)) {
		cvtColor(frame, gray, COLOR_BGR2GRAY);
		//equalizeHist直方图均衡化,,用于提高图像的质量
		equalizeHist(gray, gray);
		vector<Rect>faces;
		//输入图像 vector<Rect>& objects 缩放比例 检测次数 检测方法 图像大小
		face_classifiler.detectMultiScale(gray, faces, 1.2, 3, 0, Size(30, 30));
		for (size_t t = 0; t < faces.size(); t++) {

			rectangle(frame, faces[static_cast<int>(t)], Scalar(255, 255, 0), 2, 8, 0);


			cv::Point locate;
			locate.x = (float)(faces[static_cast<int>(t)].x + faces[static_cast<int>(t)].width / 4);
			locate.y = (float)(faces[static_cast<int>(t)].y - 10);
			putText(frame, "Person", locate, FONT_HERSHEY_SIMPLEX,
				1.2, (0, 0, 255), 2, 8);
		}
		imshow("face", frame);
		if (waitKey(10) == 27) {
			break;
		}
	}
	capture.release();
	destroyAllWindows();

	return 0;
}


转载:https://blog.csdn.net/Keep_Trying_Go/article/details/124955149

posted @ 2022-07-09 17:10  萧海~  阅读(284)  评论(1编辑  收藏  举报