CvHaarClassifierCascade初步使用

最近了解了一下CvHaarClassifierCascade用于人脸检测的流程

然后发现:比我想象的简单多了!!!!!!!!!!!

首先,所有的训练集都能在opencv\sources\data\haarcascades目录下找的到,

其次,只需要一个cvLoad()加载训练集和cvHaarDetectObjects()获得检测轮廓

/*
*image:一般使用单通道灰度图,可以加快检测时间
*cascade:通过cvLoad加载的分类器模型
*storage:findcontour经常用到的内存空间
*scale_factor :搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%
*min_neighbors:构成检测目标的相邻矩形的最小个数(默认为3个)
*flags :默认参数CV_HAAR_DO_CANNY_PRUNING
*min_size :最小人脸尺寸
*max_size:最大人脸尺寸 
*/
CVAPI(CvSeq*) cvHaarDetectObjects(
	const CvArr* image,
	CvHaarClassifierCascade* cascade,
	CvMemStorage* storage,
	double scale_factor CV_DEFAULT(1.1),
	int min_neighbors CV_DEFAULT(3),
	int flags CV_DEFAULT(0),
	CvSize min_size CV_DEFAULT(cvSize(0,0)),
	CvSize max_size CV_DEFAULT(cvSize(0,0))
)

关于人脸识别的方法,采用了最简单的直方图匹配cvCompareHist(),求得的结果越接近1代表,两张图像越相识

话不多说直接贴整个工程的源码了

// Demo.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <math.h>
#include "cv.h"  
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\objdetect\objdetect.hpp>
#include <string>
#include <fstream>
using namespace std;

//定义路径
const char *faceCascadeFilename = "haarcascade_frontalface_alt_tree.xml";
const char *NamePath = "../face/face.txt";
//
double CompareHist_Face(IplImage *Src,IplImage *bImage)
{
	double bScore = 0.0;
	if (Src->nChannels != 1||bImage->nChannels!=1) {
		printf("Error:0x001\n");
		return -1;
	}
	int HistogramBins = 256;
	float HistogramRange1[2] = { 0, 255 };
	float *HistogramRange[1] = { &HistogramRange1[0] };

	CvHistogram *Histogram1 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY, HistogramRange);
	CvHistogram *Histogram2 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY, HistogramRange);

	cvCalcHist(&Src, Histogram1);
	cvCalcHist(&bImage, Histogram2);

	cvNormalizeHist(Histogram1, 1);
	cvNormalizeHist(Histogram2, 1);

	bScore=cvCompareHist(Histogram1, Histogram2, CV_COMP_INTERSECT);

	cvReleaseHist(&Histogram1);
	cvReleaseHist(&Histogram2);

	return bScore;
}

int FaceDetection(IplImage *src,CvRect *bRect)
{
	int num = -1;
	CvHaarClassifierCascade* face_Classifier = (CvHaarClassifierCascade*)cvLoad(faceCascadeFilename, 0, 0, 0);
	if (src->nChannels != 3)
	{
		return num;
	}
	IplImage *cvtImage = cvCreateImage(cvSize(src->width, src->height), 8, 1);
	cvCvtColor(src, cvtImage, CV_BGR2GRAY);

	//整张脸
	CvMemStorage *pStorage = cvCreateMemStorage(0);
	const double scale_factore = 1.1f;
	const int flag = CV_HAAR_DO_CANNY_PRUNING;
	CvSeq *pSeq = cvHaarDetectObjects(cvtImage, face_Classifier, pStorage, scale_factore, 3, flag, cvSize(20, 20));
	num = pSeq->total;
	for (int i = 0; i < (pSeq->total); i++)
	{
		bRect[i] = *(CvRect *)cvGetSeqElem(pSeq, i);
		//cvRectangle(src, cvPoint(bRect[i].x, bRect[i].y), cvPoint(bRect[i].x + bRect[i].width - 1, bRect[i].y + bRect[i].height - 1), cvScalar(0, 255, 0), 1, 8, 0);
	}

	cvReleaseImage(&cvtImage);
	cvReleaseMemStorage(&pStorage);
	return num;
}
void FaceDetected(const char *path, IplImage *src,bool save)
{
	if (path == nullptr)
	{
		printf("ERROR:0x002\n");
	}
	CvHaarClassifierCascade* face_Classifier = (CvHaarClassifierCascade*)cvLoad(path, 0, 0, 0);
	if (src->nChannels != 3)
	{
		printf("Error:0x003\n");
	}
	IplImage *cvtImage = cvCreateImage(cvSize(src->width, src->height), 8, 1);
	cvCvtColor(src, cvtImage, CV_BGR2GRAY);
	//整张脸
	CvMemStorage *pStorage = cvCreateMemStorage(0);
	const double scale_factore = 1.1f;
	const int flag = CV_HAAR_DO_CANNY_PRUNING;
	CvSeq *pSeq = cvHaarDetectObjects(cvtImage, face_Classifier, pStorage, scale_factore, 3, flag, cvSize(20, 20));
	for (int i = 0; i < (pSeq->total); i++)
	{
		CvRect bRect = *(CvRect *)cvGetSeqElem(pSeq, i);
		cvSetImageROI(src,bRect);
		string bName = "../face/P" + std::to_string(i) + ".jpg";
		cvSaveImage(bName.c_str(), src);
		cvResetImageROI(src);

	}
	cvReleaseImage(&cvtImage);
}

int main(int argc, _TCHAR* argv[])
{
	
	//获取txt里面的图片全称
	ifstream bfile(NamePath);
	if (!bfile.is_open())
	{
		return 0;
	}
	vector<string> bName;
	bName.clear();
	string name;
	while (getline(bfile, name))
	{
		bName.push_back(name);
	}
	//加载原图像
	IplImage *SrcImage = cvLoadImage("1.jpg");//标准图片
	IplImage *CvtSrc = cvCreateImage(cvSize(SrcImage->width, SrcImage->height), 8, 1);
	cvCvtColor(SrcImage, CvtSrc, CV_BGR2GRAY);
	CvRect bFaceRect[20];
	//原图像找全部人脸
	int num=FaceDetection(SrcImage,bFaceRect);
	//创建人脸ROI图像用于检测
	IplImage **roiFace = new IplImage*[num];
	for (int i = 0; i < num;i++)
	{
		roiFace[i] = cvCreateImage(cvSize(bFaceRect[i].width, bFaceRect[i].height), 8, 1);
		cvSetImageROI(CvtSrc, bFaceRect[i]);
		cvCopy(CvtSrc, roiFace[i]);
		cvResetImageROI(CvtSrc);
	}
	//循环对比
	for (int x = 0; x < bName.size();x++)
	{
		string bpath = "../face/" + bName.at(x);
		IplImage *face = cvLoadImage(bpath.c_str(),0);
		for (int y = 0; y < num;y++)
		{
			double socre=CompareHist_Face(face, roiFace[y]);
			if (socre>0.87)//找最低分
			{
				CvFont font;
				double hScale = 0.6;
				double vScale = 0.6;
				int line_width = 1;
				cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, hScale, vScale, 0, line_width, 8);
				//人脸区域
				cvRectangle(SrcImage, cvPoint(bFaceRect[y].x, bFaceRect[y].y), cvPoint(bFaceRect[y].x + bFaceRect[y].width, bFaceRect[y].y + bFaceRect[y].height),cvScalar(255,0,0));
				string s = std::to_string(socre);
				s = s.substr(0, 4);//保留两位
				string stt = "P"+std::to_string(x)+":"+s;
				const char * pName = stt.c_str();	//名称:分数		
				cvPutText(SrcImage, pName, cvPoint(bFaceRect[y].x, bFaceRect[y].y), &font, cvScalar(0, 255, 0));
				cvReleaseImage(&face);
				break;
			}
		}
		
	}
	cvShowImage("test", SrcImage);
	cvWaitKey(0);

	//释放
	for (int i = 0; i < num;i++)
	{
		cvReleaseImage(&roiFace[i]);
	}
	cvReleaseImage(&SrcImage);
	cvReleaseImage(&CvtSrc);
	return 0;
}

具体执行效果如下,(PS:图片随便找的,侵权请联系我删除)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值