OpenCV3+级联卷积神经网络训练自己的分类器

1.简介

    最近小学期的课程中,导师要求做了一个在图像中识别特定人物的任务(识别特朗普)。我最开始使用反投影直方图,但是效果极其渣,后来选用神经网络的方法做分类进行识别,但网上写的都不甚详细,于是打算自己写一个作为记录。

2.原理

    OpenCV3中使用的分类器是基于级联神经网络,其可以通过级数的增加提高分类的正确率。

3.过程

步骤一:

    首先,我们需要知道训练一个分类器我们要准备些什么:

    A.我们先建立一个空白的文件夹

    B.我们在这个空白的文件夹上建立一个名为posdata的文件夹、一个名为negdata的文件夹、一个名为xml的文件夹,这些文件夹现在为止都是空白的,我们先什么都不需要去添加进去。


    C.将下列文件目录拷贝到我们刚刚建立的那个文件夹的主目录下,就像这样



    D.在这之后,我们就需要收集我们的数据了。我们将特朗普的面颊正样本放在名为posdata的文件夹中,将负样本放在名为negdata的文件夹中,正负样本的链接在这里。

扫描二维码关注公众号,回复: 2039885 查看本文章

    正样本

    负样本

    E.在放好之后,我们需要做出有关正负样本的标签文件。我们首先打开 posdata 文件夹做正样本的标签文件。我们在 posdata中新建一个 txt 文档,在其中打上这一段代码

dir /b/s/p/w *.jpg > posdata.txt

    之后,我们将其保存为 .bat 格式,就像这样:


    这时在文档中就像这样:


    我们运行 neg.bat 就会生成一个 posdata.txt,我们使用 Ctrl+h 更换这个文档中的内容,将绝对路径改为相对路径,更改前和更改后的状态就像这样:



    在这时,我们对这个文件继续进行更改,将 jpg 更换为

jpg 1 0 0 20 20

    更改之后的文档就像这样:


    之后,我们把这个posdata的文档移动到  training 文件夹的根目录下(剪切)

    F.对正样本处理好之后,我们继续对negdata进行处理,所有处理步骤和上述一样,但是我们不需要做 jpg 更改那一个步骤,更改好的文档就像这样,之后,我们也把他移动到主目录下。


    G.在这之后,我们打开 cmd 将 cmd 的处理目录设置到我们现在这个文件夹下:


    并且输入以下命令:

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

    那个200代表着一共有200张正样本,两个20代表正样本大小为20*20,输入之后,我们会生成一个 pos.vec 文件。


    H.在这之后,我们就可以进行训练了,进行训练的口令是

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

    在这里,我推荐 -numPos 与 -numNeg 的比值在 1:3 左右,这是一个比较好的比例;-mem 代表着你能给这段程序多少内存,由你的电脑而定。

    要注意的是,训练之前我们一定要保持 xml 文件夹是一个空文件夹,否则会报错。如果训练正常,我们就会出现以下界面:


    训练好之后,我们可以在xml文件夹中找到名为 cascade.xml 的文件,这就是训练好的分类器。在这里,这篇文章对训练中的参数做出总结,我觉得很好。

    有关参数总结

    在这之后,我们就可以使用我们训练好的分类器啦,就可以识别出特朗普喽:


    有关的代码是:

// 行人识别.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <opencv2\opencv.hpp>

void main()
{
	cv::CascadeClassifier face_detector;
	face_detector.load("..\\cascade.xml");
	if (face_detector.empty())
	{
		std::cout << "分类器加载失败!!!" << std::endl;
		return;
	}
	cv::Size original_size = face_detector.getOriginalWindowSize();
	cv::Mat image = cv::imread("..\\trump3.jpg", cv::IMREAD_COLOR);
	if (image.empty())
	{
		std::cout << "图片加载失败!!!" << std::endl;
		return;
	}
	cv::Mat image_gray;
	cv::cvtColor(image, image_gray, cv::COLOR_BGR2GRAY);
	std::vector<cv::Rect> faces;
	face_detector.detectMultiScale(image_gray, faces, 1.05, 1, 0);
	for (size_t i = 0; i < faces.size(); i++)
	{
		cv::rectangle(image, faces[i], cv::Scalar(0, 0, 255), 2, 8, 0);
	}
	cv::imshow("detect result", image);
	printf("人脸数量为%d\n", faces.size());
	cv::waitKey(0);
}


猜你喜欢

转载自blog.csdn.net/Coulson_Zhao/article/details/80980408