本文禁止转载、抄袭,请尊重作者权利。
使用特征脸方法的基于Opencv的猫脸检测实现
摘要
目前,在计算机视觉和模式识别领域,脸识别技术是一个很活跃的课题,人脸识别的方法已经十分丰富,而对于日常生活中的宠物脸识别的技术还在发展中,因此对猫脸的识别越来越受到人们的关注。
本文针对提出猫的脸部识别所需要的面部特征并分析其有效性,建立猫的脸部模型和利用脸部模型提出猫的自动识别系统三个问题进行了建模和算法设计。本文将基于目前比较热门的特征脸算法来研究猫脸的面部特征,再利用这些特征量建立猫的面部模型,最后得到猫的机器自动识别装置。
问题一,提出猫的面部特征。我们通过观察对比100张猫的图片,决定提取猫的眼睛、鼻子和嘴巴作为此次研究的三个面部特征。这里采用Haar-like特征的方法来研究。由边缘特征、线性特征、中心特征和对角线特征,组合成特征模板。特征模板内有白色和黑色两种矩形,并定义该模板的特征值为白色矩形像素和减去黑色矩形像素和。Haar特征值反映了图像的灰度变化情况。通过改变特征模板的大小和位置,可在图像子窗口中穷举出大量的特征。将图像从起点开始到各个点所形成的矩形区域像素之和作为一个数组的元素保存在内存中,并计算所有子窗口的特征值。由此可以得到眼睛、鼻子、嘴巴的特征向量。
问题二,建立猫的面部模型。这里我们采用主成分分析(PCA)的方法建立的猫的面部特征模型。利用matlab读取样本(选10张猫脸图片),继而得到灰度图,统一图片尺寸(这里我们采用128*128像素),然后把每张图转换成128*128维的列向量,把所有列向量放到一个集合中。然后计算平均值,得到平均图像(平均脸),计算每张图与平均图像的差值,再计算出它的协方差矩阵,将其对角化,由此得到各个特征向量,也就得到了各个特征脸图像。而在这组特征解系下的解便是属于猫的脸,也就完成了猫脸的模型。
问题三,提出猫的机器自动识别系统。针对猫脸的检测识别有别于人脸,由于猫的品种较多且属猫科的动物较多都对检测识别造成干扰,这样的工作通常比人脸识别更具难度,特征脸技术可用于猫脸检测识别。首先把一批猫脸图像转换成一个特征向量集,称为“Eigenfaces”,即“特征脸”,它们是最初训练图像集的基本组件。识别的过程是把一副新的图像投影到特征脸子空间,并通过它的投影点在子空间的位置以及投影线的长度来进行判定和识别。猫脸检测识别系统的建立可以利用特征脸方法,通过建立简单分类器并级联,进而利用Opencv工具加载分类器进行猫脸检测识别。但限于算法设计和某些遮挡特征的因素存在,对于强干扰因素条件下的图片中猫脸的检测识别还存有一定局限性。综合统计,这种系统的识别正确率可以达到75%以上。
【关键词】特征脸 Haar-like 主成分分析(PCA) 分类器
目录
一、 提出猫的面部特征并分析有效性 ……………………………3
1、 图像的归一化…………………………………………………………3
2、 Haar-like特征………………………………………………………4
3、 有效性分析……………………………………………………………4
二、 建立猫的脸部模型 ……………………………………………5
1、采集样本………………………………………………………………5
2、主成分分析(PCA) …………………………………………………5
3、测试对比………………………………………………………………7
三、 提出猫的机器自动识别系统 …………………………………9
1、构建猫脸数据库,训练分类器………………………………………9
2、使用Opencv进行图像处理 …………………………………………11
3、猫脸检测识别系统效果………………………………………………11
一、提出猫的面部特征并分析有效性
1、图像归一化
为了统一需要读取的图片的尺寸并提高计算的精度,我们需要先对图像进行归一化处理。
归一化的主要过程是:
(1) 坐标中心化
(2) X-shearing归一化
(3) 放缩归一化
(4) 旋转归一化
具体过程用矩阵表示为:
区域f(x,y)对应的p+q矩是:
我们定义的其中心矩为:
定义图像的协方差矩阵M为
我们可以得到:
(其中x‘’‘和y’‘’是变化后的位置,而x,y是初始的位置)
而这个变换过程从右到左就是我们上述的四步骤:坐标中心化,
x,y方向的拉伸,缩放变化,旋转变化。
通过归一化,可以保持仿射变换的不变性,能够消除其他变换对
图像的影响。
在Matlab中我们使用简单的归一化函数[y,ps] =mapminmax(x,ymin,ymax)来实现图像的归一化处理。
完成归一化处理之后我们就可以开始对图像进行特征分析了。
2、Haar-like特征
Haar-like特征最早是由Papageorgiou等应用于人脸表示,这里可以用来分析猫脸。Haar特征分为三类:边缘特征、线性特征、中心特征和对角线特征,组合成特征模板。特征模板内有白色和黑色两种矩形,并定义该模板的特征值为白色矩形像素和减去黑色矩形像素和。Haar特征值反映了图像的灰度变化情况。猫的脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颜色要深,鼻子比它周边的颜色要深,嘴巴与它周围的颜色也不同。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述特定走向(水平、垂直、对角)的结构。
原理简介:对于图中的A, B和D这类特征,特征数值计算公式为:v=Sum白-Sum黑,而对于C来说,计算公式如下:v=Sum白-2*Sum黑;之所以将黑色区域像素和乘以2,是为了使两种矩形区域中像素数目一致。
通过改变特征模板的大小和位置,可在图像子窗口中穷举出大量的特征。上图的特征模板称为“特征原型”;特征原型在图像子窗口中扩展(平移伸缩)得到的特征称为“矩形特征”;矩形特征的值称为“特征值”。
矩形特征可位于图像任意位置,大小也可以任意改变,所以矩形特征值是矩形模版类别、矩形位置和矩形大小这三个因素的函数。故类别、大小和位置的变化,使得很小的检测窗口含有非常多的矩形特征。
由这个原理,我们可以构造一种分类器,来区分猫脸的不同部位。下面以眼睛为例,展示分类的效果。
如:
可以看出,通过使用Haar-like特征方法,利用眼睛与其周围颜色的差别,可以清楚的区分出猫的眼睛的位置。那么同样的,我们可以利用特征向量来区分猫的鼻子和耳朵的位置。
3、有效性分析
从上面的实验结果我们可以看出计算机在区分眼睛的同时也框出了猫的整个脸,这是因为猫脸与其周边的颜色也有差别,说明这种特征法在实际运用中存在一定的误差,容易受背景、光线等的干扰。
二、建立猫的面部模型
1、采集样本
我们从所给的100张猫的图片中随机选取20张,截出猫脸的位置,并保存成jpg图片,构成样本总体。
利用Matlab分别读取上述20张图片的灰度值,存储为灰度矩阵,并统一化矩阵的大小(这里为128*128),然后其转换成128*128维的列向量。由此一共得到了20个列向量,用于下面的猫脸模型的构建。具体代码:
%sample
clear;
clc;
train_path='C:\Users\asus\Desktop\2016modeling\a\sample\';
phi=zeros(128*128,20);
for i=1:20
path=strcat(train_path,num2str(i),'.jpg');
image=rgb2gray(imread(path));
image=imresize(image,[128,128]);
phi(:,i)=double(reshape(image,1,[])');
end;
附20张裁剪后的猫脸:
2、主成分分析(PCA)
主成分分析法PCA(Principal Component Analysis)是一种常用的数据分析方法。PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降维。
1)我们将上述20个列向量放在一个矩阵phi中,即
phi={image1,image2,……,image20}
2)计算phi矩阵的自均值,从而可以得到平均脸,并保存图片。具体代码:
%mean
mean_phi=mean(phi,2);
mean_face=reshape(mean_phi,128,128);
image_mean=mat2gray(mean_face);
imwrite(image_mean,'C:\Users\asus\Desktop\2016modeling\a\','jpg');
实验结果显示:
()
3)将phi的每一列进行零均值化,即减去这一列的均值,然后求出协方差矩阵,从而求出协方差矩阵的特征值以及对应的特征向量。这样便可以得到每一个特征脸的灰度图像。具体代码:
for i=1:19
x(:,i)=phi(:,i)-mean_phi;
end
Lx=x'*x;
tic;
[eigenvector,eigenvalue]=eigs(Lx,19);
toc;
%normalization
for i=1:19
%K-Lchange
UL(:,i)=x*eigenvector(:,i)/sqrt(eigenvalue(i,i));
end
%display Eigenface
for i=1:19
Eigenface=reshape(UL(:,i),[128,128]);
figure(i);
imshow(mat2gray(Eigenface));
end
实验得到的各个特征脸为:
()
4)我们可以知道所有猫脸都可以由这组猫的特征脸所代表的特征向量线性标出,因此这就构建了猫的面部模型。当然,样本越多得到的结果越精确,即得到的特征向量越多。
3、测试对比
我们任意选择四张图片来进行猫脸模型的测试,并通过对比所给图的特征量与我们构建的猫脸模型的特征量的差值来分析误差大小。选择的四张图片如下:
使用Matlab求解,具体代码:
%test
clc;
test_path='C:\Users\asus\Desktop\2016modeling\a\test\';
error=zeros([1,4]);
for i=1:4
path=strcat(test_path,num2str(i),'.jpg');
image=rgb2gray(imread(path));
image=double(imresize(image,[128,128]));
phi_test=zeros(128*128,1);
phi_test(:,1)=double(reshape(image,1,[]'));
x_test=phi_test-mean_phi;
y_test=UL'*x_test;
x_test_re=UL*y_test;
face_re=x_test_re+mean_phi;
%calculateerror rate
e=face_re-phi_test;
%displayfigure
face_re_2=reshape(face_re(:,1),[128,128]);
figure(i);
imshow(mat2gray(image));
title('Original');
figure(10+i);
imshow(mat2gray(face_re_2));
title('Reconstruct');
error(1,i)=norm(e);
%displayerror rate
error_rate=error(1,i);
display(error_rate);
end
从而得到:
对应的误差值为:
可见由20张样本构建的猫脸模型效果还可以,误差在e+4附近,但这类误差可以由训练更多的样本来控制。
三、提出猫的机器自动检测识别系统
利用上述建立猫的脸部模型,本文提出关于猫脸的自动检测系统。
系统平台由C++语言编程实现,基于最新的OpenCV3.0 C++开发,可以实现在PC、android\IOS平台上进行猫脸自动检测识别。
以下以PC平台为例,说明猫脸系统的建立过程。
一、构建猫脸数据库,训练分类器。
概述:首先,利用所给100份样本进行筛选后按照本文前述模型特征进行分类器训练,每个所需面部特征训练得到一个简单分类器,而后将数个简单分类器级联成最终的猫脸分类器。在实际检测图片中,检测窗口依次通过每一级分类器,全部通过每一级分类器检测的区域即为目标区域,该区域即为检测识别出的猫脸。
1. 创建样本:
用给出的猫脸图片作为训练样本,训练样本分为正例样本和反例样本,其中正例样本使用单纯猫脸,反例样本使用其它不包含猫脸特征的图片,所有的样本图片做尺寸归一化处理。
正样本通过C++程序opencv_createsamples.exe创建,建立过程参数设定不再冗述。样本创建程序代码在论文附录中给出。
负样本通过建立文档描述。描述文档是一个文本文件,每一行基于描述文件的相对路径包含了一个负样本图片的文件名。
本系统负样本建立目录如下:
../images
…
|
文档的内容为:
img/
img/
…
建立批处理对负样本进行处理。
<span style="font-family: Arial, Helvetica, sans-serif;"> </span>cd d:\catfaces\create
createsamples -vec d:\catfaces\create\
-info d:\catfaces\
-bg d:\catfaces\
-num 5
-show
-w 24
-h 28
生成的正样本文件在d:\catfaces\create目录下,至此,样本创建完毕。
2. 利用OpenCV3.0 Boost工具训练分类器:
样本创建后进行分类器训练,训练过程是由程序来实现。训练原理已在本文前述中给出,训练程序代码在论文附录中给出。
3. 级联简单分类器,形成最终的可用分类器:
建立批处理文件形成最终的分类器原型。
cd d:\catfaces\create
haartraining -data e:\catfaces\classifier
-vec e:\catfaces\
-bg e:\catfaces\
-npos 5
-nneg 2
-w 24
-h 28
训练结束后,会在目录classifier下生成文件,即为训练完成的分类器,以XML文件的形式存在。
二、使用Opencv进行图像处理
1. 加载分类器和需要检测识别猫脸的目标图片:
-
String xmlPath = "..\";//分类器路径
-
CascadeClassifier ccf; //创建分类器对象
-
Mat img = imread("..\"); //目标图片路径
-
ccf.load(xmlPath); //加载分类器
2. 创建容器:
vector<Rect> faces; //创建一个容器保存检测出来的脸
3. 原图图片灰度化处理:
-
Mat gray;
-
cvtColor(img, gray, CV_BGR2GRAY); //灰度图转化,用于提取haar特征
4. 直方图均衡:
equalizeHist(gray, gray); //直方图均衡
5. 使用分类器检测识别猫脸:
ccf.detectMultiScale(gray, faces, 1.1, 3, 0, Size(100, 100), gray.size()); //检测猫脸,Size的参数检测时需做调整
6. 将目标猫脸标识矩形边框:
-
for (vector<Rect>::const_iterator iter= faces.begin();iter != faces.end();iter++)
-
{
-
rectangle(img, *iter, Scalar(0, 0, 255), 2, 8); //画出脸部矩形
-
}
7. 还原原图并显示检测识别结果:
imshow("Cat Faces", img);
上述以图片为例进行检测,如建立动态视频形式的猫脸检测识别系统,则仅需对摄像视频进行时间间隔采样成图片进行分析即可。
详细系统建立的代码在论文附录中给出。
三、猫脸检测识别系统效果
a.简单猫脸的目标图片,结果:正确识别。
b.非仅有猫脸的目标图片,结果:正确识别。
c.有明显干扰因素的目标图片,结果:大部分正确识别,结果显示有干扰的图片也包含了正确识别。
d.简单人脸目标图片,结果:未出现错误识别。
e.有很强干扰因素的目标图片,结果:可能存在错误识别的情况,以下截取在强干扰下错误识别的情况。
错误情况分析:
1.样本训练数量不足,导致分类器的识别能力不适应强干扰情况。
2.算法先天不足,如猫的近亲老虎、豹子等情况或图片某处遮挡特征提取的关键部位出现。
3.系统偶然性。
系统实现结论:
本文提出的猫脸的识别系统通过对100份样本猫脸样本的检测识别进行统计,利用程序参数微调其检测识别完全正确率可以达到75%左右;还有大约15%的图片可以识别,但会出现其他额外识别的不准确情况;有10%的图片不能够正确识别,大多由于图片背景杂乱或猫脸过小隐藏于遮挡物后导致系统错误标识;另外,针对无猫脸的负样本检测识别,系统不会标识矩形框,结果基本准确。
附录
(代码以C++语言给出,遵守C99标准)
A.opencv_createsamples.exe源代码(部分)
-
#include <cstdio>
-
#include <cstring>
-
#include <cstdlib>
-
#include <cmath>
-
#include <ctime>
-
-
using namespace std;
-
-
#include ""
-
-
int main( int argc, char*argv[] )
-
{
-
int i = 0;
-
char* nullname = (char*)"(NULL)";
-
char* vecname = NULL; /* .vec file name */
-
char* infoname = NULL; /* file name with marked up image descriptions */
-
char* imagename = NULL; /* single sample image */
-
char* bgfilename = NULL; /* background */
-
int num = 1000;
-
int bgcolor = 0;
-
int bgthreshold = 80;
-
int invert = 0;
-
int maxintensitydev = 40;
-
double maxxangle = 1.1;
-
double maxyangle = 1.1;
-
double maxzangle = 0.5;
-
int showsamples = 0;
-
/* the samples are adjusted to this scale in the sample preview window */
-
double scale = 4.0;
-
int width = 24;
-
int height = 24;
-
-
srand((unsigned int)time(0));
-
-
if( argc == 1 )
-
{
-
printf( "Usage: %s\n [-info <collection_file_name>]\n"
-
" [-img <image_file_name>]\n"
-
" [-vec <vec_file_name>]\n"
-
" [-bg <background_file_name>]\n [-num <number_of_samples = %d>]\n"
-
" [-bgcolor <background_color = %d>]\n"
-
" [-inv] [-randinv] [-bgthresh <background_color_threshold = %d>]\n"
-
" [-maxidev <max_intensity_deviation = %d>]\n"
-
" [-maxxangle <max_x_rotation_angle = %f>]\n"
-
" [-maxyangle <max_y_rotation_angle = %f>]\n"
-
" [-maxzangle <max_z_rotation_angle = %f>]\n"
-
" [-show [<scale = %f>]]\n"
-
" [-w <sample_width = %d>]\n [-h <sample_height = %d>]\n",
-
argv[0], num, bgcolor, bgthreshold, maxintensitydev,
-
maxxangle, maxyangle, maxzangle, scale, width, height );
-
-
return 0;
-
}
-
-
for( i = 1; i < argc; ++i )
-
{
-
if( !strcmp( argv[i], "-info" ) )
-
{
-
infoname = argv[++i];
-
}
-
else if( !strcmp( argv[i], "-img" ) )
-
{
-
imagename = argv[++i];
-
}
-
else if( !strcmp( argv[i], "-vec" ) )
-
{
-
vecname = argv[++i];
-
}
-
else if( !strcmp( argv[i], "-bg" ) )
-
{
-
bgfilename = argv[++i];
-
}
-
else if( !strcmp( argv[i], "-num" ) )
-
{
-
num = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-bgcolor" ) )
-
{
-
bgcolor = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-bgthresh" ) )
-
{
-
bgthreshold = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-inv" ) )
-
{
-
invert = 1;
-
}
-
else if( !strcmp( argv[i], "-randinv" ) )
-
{
-
invert = CV_RANDOM_INVERT;
-
}
-
else if( !strcmp( argv[i], "-maxidev" ) )
-
{
-
maxintensitydev = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-maxxangle" ) )
-
{
-
maxxangle = atof( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-maxyangle" ) )
-
{
-
maxyangle = atof( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-maxzangle" ) )
-
{
-
maxzangle = atof( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-show" ) )
-
{
-
showsamples = 1;
-
if( i+1 < argc && strlen( argv[i+1] ) > 0 && argv[i+1][0] != '-' )
-
{
-
double d;
-
d = strtod( argv[i+1], 0 );
-
if( d != -HUGE_VAL && d !=HUGE_VAL && d > 0 ) scale = d;
-
++i;
-
}
-
}
-
else if( !strcmp( argv[i], "-w" ) )
-
{
-
width = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-h" ) )
-
{
-
height = atoi( argv[++i] );
-
}
-
}
-
-
printf( "Info file name: %s\n", ((infoname ==NULL) ? nullname : infoname ) );
-
printf( "Img file name: %s\n", ((imagename ==NULL) ? nullname : imagename ) );
-
printf( "Vec file name: %s\n", ((vecname ==NULL) ? nullname : vecname ) );
-
printf( "BG file name: %s\n", ((bgfilename ==NULL) ? nullname : bgfilename ) );
-
printf( "Num: %d\n", num );
-
printf( "BG color: %d\n", bgcolor );
-
printf( "BG threshold: %d\n", bgthreshold );
-
printf( "Invert: %s\n", (invert ==CV_RANDOM_INVERT) ? "RANDOM"
-
: ( (invert) ? "TRUE" : "FALSE" ) );
-
printf( "Max intensity deviation: %d\n", maxintensitydev );
-
printf( "Max x angle: %g\n", maxxangle );
-
printf( "Max y angle: %g\n", maxyangle );
-
printf( "Max z angle: %g\n", maxzangle );
-
printf( "Show samples: %s\n", (showsamples) ?"TRUE" : "FALSE" );
-
if( showsamples )
-
{
-
printf( "Scale: %g\n", scale );
-
}
-
printf( "Width: %d\n", width );
-
printf( "Height: %d\n", height );
-
-
/* determine action */
-
if( imagename && vecname )
-
{
-
printf( "Create training samples from single image applying distortions...\n" );
-
-
cvCreateTrainingSamples( vecname, imagename, bgcolor, bgthreshold, bgfilename,
-
num, invert, maxintensitydev,
-
maxxangle, maxyangle, maxzangle,
-
showsamples, width, height );
-
-
printf( "Done\n" );
-
}
-
else if( imagename && bgfilename && infoname )
-
{
-
printf( "Create test samples from single image applying distortions...\n" );
-
-
cvCreateTestSamples( infoname, imagename, bgcolor, bgthreshold, bgfilename, num,
-
invert, maxintensitydev,
-
maxxangle, maxyangle, maxzangle, showsamples, width, height );
-
-
printf( "Done\n" );
-
}
-
else if( infoname && vecname )
-
{
-
int total;
-
-
printf( "Create training samples from images collection...\n" );
-
-
total = cvCreateTrainingSamplesFromInfo( infoname, vecname, num, showsamples,
-
width, height );
-
-
printf( "Done. Created %d samples\n", total );
-
}
-
else if( vecname )
-
{
-
printf( "View samples from vec file (press ESC to exit)...\n" );
-
-
cvShowVecSamples( vecname, width, height, scale );
-
-
printf( "Done\n" );
-
}
-
else
-
{
-
printf( "Nothing to do\n" );
-
}
-
-
return 0;
-
}
B.源代码(部分)
-
#include "opencv2/"
-
#include ""
-
-
using namespace std;
-
using namespace cv;
-
-
int main( int argc, char*argv[] )
-
{
-
CvCascadeClassifier classifier;
-
string cascadeDirName, vecName, bgName;
-
int numPos = 2000;
-
int numNeg = 1000;
-
int numStages = 20;
-
int numThreads = getNumThreads();
-
int precalcValBufSize = 1024,
-
precalcIdxBufSize = 1024;
-
bool baseFormatSave = false;
-
double acceptanceRatioBreakValue = -1.0;
-
-
CvCascadeParams cascadeParams;
-
CvCascadeBoostParams stageParams;
-
Ptr<CvFeatureParams> featureParams[] = { makePtr<CvHaarFeatureParams>(),
-
makePtr<CvLBPFeatureParams>(),
-
makePtr<CvHOGFeatureParams>()
-
};
-
int fc = sizeof(featureParams)/sizeof(featureParams[0]);
-
if( argc == 1 )
-
{
-
cout << "Usage: " << argv[0]<< endl;
-
cout << " -data <cascade_dir_name>" << endl;
-
cout << " -vec <vec_file_name>" << endl;
-
cout << " -bg <background_file_name>" << endl;
-
cout << " [-numPos <number_of_positive_samples = " << numPos<< ">]"<< endl;
-
cout << " [-numNeg <number_of_negative_samples = " << numNeg<< ">]"<< endl;
-
cout << " [-numStages <number_of_stages = " << numStages<< ">]"<< endl;
-
cout << " [-precalcValBufSize <precalculated_vals_buffer_size_in_Mb = " << precalcValBufSize << ">]" << endl;
-
cout << " [-precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb = " << precalcIdxBufSize << ">]" << endl;
-
cout << " [-baseFormatSave]" << endl;
-
cout << " [-numThreads <max_number_of_threads = " << numThreads<< ">]"<< endl;
-
cout << " [-acceptanceRatioBreakValue <value> = " << acceptanceRatioBreakValue<< ">]"<< endl;
-
cascadeParams.printDefaults();
-
stageParams.printDefaults();
-
for( int fi = 0; fi < fc; fi++ )
-
featureParams[fi]->printDefaults();
-
return 0;
-
}
-
-
for( int i = 1; i < argc; i++ )
-
{
-
bool set = false;
-
if( !strcmp( argv[i], "-data" ) )
-
{
-
cascadeDirName = argv[++i];
-
}
-
else if( !strcmp( argv[i], "-vec" ) )
-
{
-
vecName = argv[++i];
-
}
-
else if( !strcmp( argv[i], "-bg" ) )
-
{
-
bgName = argv[++i];
-
}
-
else if( !strcmp( argv[i], "-numPos" ) )
-
{
-
numPos = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-numNeg" ) )
-
{
-
numNeg = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-numStages" ) )
-
{
-
numStages = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-precalcValBufSize" ) )
-
{
-
precalcValBufSize = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-precalcIdxBufSize" ) )
-
{
-
precalcIdxBufSize = atoi( argv[++i] );
-
}
-
else if( !strcmp( argv[i], "-baseFormatSave" ) )
-
{
-
baseFormatSave = true;
-
}
-
else if( !strcmp( argv[i], "-numThreads" ) )
-
{
-
numThreads = atoi(argv[++i]);
-
}
-
else if( !strcmp( argv[i], "-acceptanceRatioBreakValue" ) )
-
{
-
acceptanceRatioBreakValue = atof(argv[++i]);
-
}
-
else if ( cascadeParams.scanAttr( argv[i], argv[i+1] ) ) { i++; }
-
else if ( stageParams.scanAttr( argv[i], argv[i+1] ) ) { i++; }
-
else if ( !set )
-
{
-
for( int fi = 0; fi < fc; fi++ )
-
{
-
set = featureParams[fi]->scanAttr(argv[i],argv[i+1]);
-
if ( !set )
-
{
-
i++;
-
break;
-
}
-
}
-
}
-
}
-
-
setNumThreads( numThreads );
-
classifier.train( cascadeDirName,
-
vecName,
-
bgName,
-
numPos, numNeg,
-
precalcValBufSize, precalcIdxBufSize,
-
numStages,
-
cascadeParams,
-
*featureParams[],
-
stageParams,
-
baseFormatSave,
-
acceptanceRatioBreakValue );
-
return 0;
-
}
C.猫脸检测识别系统 检测识别过程源代码
-
#include "opencv2\"
-
#include <iostream>
-
using namespace std;
-
using namespace cv;
-
-
int main()
-
{
-
string xmlPath = "../cat_detection.xml";
-
CascadeClassifier ccf; //创建分类器对象
-
Mat img = imread("../");//目标检测图片
-
if (!ccf.load(xmlPath)) //加载训练文件
-
{
-
cout << "Can not load the xml file." << endl;
-
return 0;
-
}
-
vector<Rect> faces; //创建一个容器保存检测出来的脸
-
Mat gray;
-
cvtColor(img, gray, CV_BGR2GRAY);//灰度图转化,提取Haar特征
-
equalizeHist(gray, gray); //直方图均衡
-
//resize(gray, gray, Size(128, 128), 0, 0, CV_INTER_LINEAR);
-
ccf.detectMultiScale(gray, faces, 1.1, 3, 0, Size(125, 125), gray.size()); //检测脸,此处的Size(x,y)参数x,y检测前需调整到合适数值
-
for (vector<Rect>::const_iterator iter = faces.begin();iter!= faces.end();iter++)
-
{
-
rectangle(img, *iter, Scalar(0, 0, 255), 2, 8); //画出脸部矩形
-
}
-
imshow("Cat Faces", img);
-
waitKey(0);
-
return 0;
-
}
-------------------------------------------------------------------------------------------
感谢联合作者Cao Dongnan先生,并共同享有本文所有权利。
文章属本科生水平,班门弄斧,仅作参考,内有不当之处还请见谅。
-------------------------------------------------------------------------------------------
原始文档与程序可在我的个人主页 上得到(如果打不开只能抱歉,说明又中毒了),仅作参考。
-------------------------------------------------------------------------------------------
本文禁止转载、抄袭,请尊重作者权利。
End 2016/07/19