使用FDDB人脸样本检测库,测试自己的人脸检测算法性能并生成ROC曲线。
Posted 晴堂
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用FDDB人脸样本检测库,测试自己的人脸检测算法性能并生成ROC曲线。相关的知识,希望对你有一定的参考价值。
一,说明及环境
网上有关FDDB人脸检测库的使用以及ROC文件生成的文章太少,并且都无法检测opencv中自带的人脸检测算法。最近
工作的原因,需要用到FDDB库检测我们自己的人脸检测算法性能。所以认真研究了FDDB库的使用,并生成了ROC文件。
所有代码在Win10,VS2013,opencv2411下亲测可用。
二,过程及代码
1,下载FDDB图片库,注解文件以及生成ROC文件的源代码。官网地址:http://vis-www.cs.umass.edu/fddb/
所有需要的资料以及代码,我已经上传,在评论里留下邮箱,我会尽快发到你邮箱。
2,编译FDDB源代码,直接导入到win32控制台项目中即可,源代码中已经写好了main方法。
3,根据自己的人脸检测算法生成FDDB必须的表述自己算法结果的txt文件。
FDDB官网中的readme.txt文件已经说明了自己生成的txt文件的内容格式,如下:
<image name i>///写入自己检测的图片名称,
<number of faces in this image =im>///检测到的人脸个数
<face i1> ///检测到的人脸矩形或椭圆信息以及信心值也可说是准确率detection_score
<face i2>
...
<face im>
...
where the representation of a face depends on the specifics
of the shape of the hypothesized image region. The evaluation
code supports the following shapes:
4 a. Rectangular regions
Each face region is represented as:
<left_x top_y width height detection_score>
4 b. Elliptical regions
Each face region is represented as:
<major_axis_radius minor_axis_radius angle center_x center_y detection_score>.
Also, the order of images in the output file is expected to be
the same as the order in the file annotatedList.txt.
我们必须对FDDB库中提供的图片,使用我们自己的算法对图片进行人脸检测,将每一张的检测结果信息按照如上
格式写入到txt文件,图片的读入顺序按照下载的annotatedList.txt文件中列举的图片路径以及名称顺序,内容如下:
2002/08/11/big/img_591
2002/08/26/big/img_265
2002/07/19/big/img_423
2002/08/24/big/img_490
2002/08/31/big/img_17676
.........
2002/08/07/big/img_1453
2002/08/02/big/img_760
生成opencv中人脸检测算法的结果文件,代码如下:
// evaluation.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <cctype>
#include <iostream>
#include<fstream>
#include <iterator>
#include <stdio.h>
using namespace std;
using namespace cv;
bool isOverlap(Rect r1,Rect r2);
//实现识别并绘制出面部矩形框,参数依次是图片,人脸检测分类器,允许的缩小比,检测出人脸准确分值,
//返回检测出的人脸矩形
vector<Rect> detectAndDraw( Mat& img, CascadeClassifier& cascade,double scale,int * score);
//人脸模型文件,为xml文件结构记录了一个标准的人脸模特数据;
string cascadeName = "haarcascade_frontalface_alt.xml";
int main( int argc, const char** argv )
Mat frame, frameCopy, image;//OpenCV中存储数据的通用类型,较旧的版本中为
string inputName;
string dir;
bool tryflip = false;
CascadeClassifier cascade;
double scale = 1;
cascade.load( cascadeName );
ifstream in_txt("FDDB-fold-01.txt");//文件直接放在程序当前目录下,自己根据情况修改
ofstream out_txt1("output.txt");//生成的算法检测结果文件
out_txt1.close();
while(!in_txt.eof())
getline(in_txt,inputName);//读取图片路径
dir=dir1+inputName;
dir+=".jpg";
image = imread(dir,CV_LOAD_IMAGE_COLOR);
if( !image.empty() )
ofstream out_txt("output.txt",ios::app);
int scoreBuffer[50];
vector<Rect> faces=detectAndDraw( image, cascade,scale,scoreBuffer);
out_txt<<inputName<<endl<<faces.size()<<endl;
out_txt.close();
for(int i=0;i<faces.size();i++)
ofstream out_txt1("output.txt",ios::app);
//写入结果文件
out_txt1<<faces[i].x<<" "<<faces[i].y<<" "<<faces[i].width<<" "<<faces[i].height<<" "<<scoreBuffer[i]<<endl;
out_txt1.close();
faces.clear();
waitKey(0);
return 0;
vector<Rect> detectAndDraw( Mat& img, CascadeClassifier& cascade,
double scale,int * scoreBuffer)
vector<Rect> faces, faces2;
Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
cvtColor( img, gray, CV_BGR2GRAY );
resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
equalizeHist( smallImg, smallImg );
//检测出人脸位置
cascade.detectMultiScale( smallImg, faces,1.05,0, 0|CV_HAAR_SCALE_IMAGE,Size(20, 20));
//获取opencv检测人脸过程中,所有的匹配框,因为opencv每检测出一张脸都要检测出若干个子矩形框,
//最终进行合并成一个矩形框,所以子矩形框越多,准确路越高。
cascade.detectMultiScale( smallImg, faces2,1.05,2, 0|CV_HAAR_SCALE_IMAGE,Size(20, 20));
int i=0;
for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); r++,i++)
//计算每张脸的准确率分值,
int score=0;
for( vector<Rect>::const_iterator s = faces.begin(); s != faces.end(); s++)
if(isOverlap(*r,*s))//如果重复就说明这个子矩形框是正确的,可以加分
score++;
scoreBuffer[i]=score;
cout<<score<<endl;
return faces2;
bool isOverlap(Rect r1,Rect r2)//判断矩形是否重叠
int x0=r1.x>r2.x?r1.x:r2.x;
int y0=r1.y>r2.y?r1.y:r2.y;
int x1=r1.x+r1.width;
int y1=r1.y+r1.height;
int x2=r2.x+r2.width;
int y2=r2.y+r2.height;
int x3=x1<x2?x1:x2;
int y3=y1<y2?y1:y2;
if(x3<x0||y3<y0)
return false;
else
return true;
代码运行结束,就会生成描述算法结果的txt文件。
4,使用FDDB的源代码程序,读入自己算法的结果程序,以及对应自己结果程序的FDDB注解文件,这个注解文件其实
存储了每张图片人脸的正确位置,FDDB的源代码程序会按照顺序和我们自己的算法程序结果进行比对。需要注意的是,
我们自己的算法结果文件中,信心值也可说是准确率detection_score有多少个不同的值,最终生成的ROC文件就会有多
少组数据。FDDB代码的使用方法如下:
只需要修改带有main方法的.CPP文件,将其中定义读入文件路径的代码修改为:
//存放FDDB图片的根文件夹,为当前文件夹
string baseDir = "";
//存储读取图片顺序的txt
string listFile = "FDDB-fold-01.txt";
//自己算法生成的结果文件
string detFile = "output.txt";
//记录了每张图片的人脸检测答案
string annotFile = "FDDB-fold-01-ellipseList.txt";
我的项目文件目录截图如下:
程序运行结束,会在程序当前目录下生成tempContROC.txt和tempDiscROC.txt分别是非离散和离散的ROC曲线文件。
至于怎么显示ROC曲线,在matlab里使用plot函数即可。
以上是关于使用FDDB人脸样本检测库,测试自己的人脸检测算法性能并生成ROC曲线。的主要内容,如果未能解决你的问题,请参考以下文章