人脸检测源码解析——3、准备数据

来源:互联网 发布:vim c语言 ide 编辑:程序博客网 时间:2024/05/29 18:09

        我们来看步骤(1)创建图片读取器中完成了哪些工作。

 

// (1)创建图片读取器,设置正样本vec文件路径,从中读取正样本图片;负样本图片的文件名列表;样本图像的size,宽高像素值    if( !imgReader.create( _posFilename, _negFilename, _cascadeParams.winSize ) )

        调用PosReader和NegReader的create函数

bool CvCascadeImageReader::create( conststring _posFilename, const string _negFilename, Size _winSize ){   return posReader.create(_posFilename) &&negReader.create(_negFilename, _winSize);}

正样本

        先来看一下正样本长什么样,这在前面的原理部分已经讲过。我们会收集大量的人脸图片,然后转成0-255的灰度图片,缩放到同样的尺寸比如24*24。opencv中提供工具可以把这些小图像以vec文件的格式存到一个大文件中,以加快读取的速度并方便训练程序处理。


        例如下面是已经用工具制作好的24*24大小的vec文件,里面包含了大量上述人脸小图像。

        在来看代码如何处理该文件获得正样本。

        PosReader::create函数,打开vec文件,读取样本个数count,图片的像素数目vecSize。

 boolCvCascadeImageReader::PosReader::create( const string _filename ){   if ( file )       fclose( file );    //file 文件指针,打开文件   file = fopen( _filename.c_str(), "rb" );    if( !file )       return false;   short tmp = 0;    //读取vec文件头    //int count    --  vec中样本的个数    //int vecSize  --  图片像素数目 w*h ,样本图像保存为short类型    //short tmp[2] --  两个short,没用到   if( fread( &count, sizeof( count ), 1, file ) != 1 ||       fread( &vecSize, sizeof( vecSize ), 1, file ) != 1 ||       fread( &tmp, sizeof( tmp ), 1, file ) != 1 ||       fread( &tmp, sizeof( tmp ), 1, file ) != 1 )       CV_Error_( CV_StsParseError, ("wrong file format for %s\n",_filename.c_str()) );   // base为实际图片数据开始的位置,字节数    base= sizeof( count ) + sizeof( vecSize ) + 2*sizeof( tmp );   if( feof( file ) )       return false;   last = 0;    //short vec[vecSize] 用于缓存一个样本的图像数据   vec = (short*) cvAlloc( sizeof( *vec ) * vecSize );   CV_Assert( vec );   return true;} 


负样本

        负样本只要不包含人脸就可以,因此没必要像正样本那样精挑细选,收集大量不包含人脸的图片即可。

        我们需要告诉训练程序使用哪些文件作为负样本,因此会制作一个文件名列表,作为负样本数据输入给程序,示例如下:

neg.listneg0\535.pngneg0\536.pngneg0\537.pngneg0\538.pngneg0\539.pngneg0\54.pngneg0\540.pngneg0\541.pngneg0\542.pngneg0\543.pngneg0\544.pngneg0\545.pngneg0\546.pngneg0\547.pngneg0\548.pngneg0\549.pngneg0\55.pngneg0\550.pngneg0\551.pngneg0\552.pngneg0\553.png

 

        负样本列表文件每行存放一个文件名,create函数打开该文件,读取所有文件路径到内部变量imgFilenames中。

bool CvCascadeImageReader::NegReader::create( const string _filename, Size _winSize){   string dirname, str;   std::ifstream file(_filename.c_str());   if ( !file.is_open() )       return false;    size_t pos = _filename.rfind('\\');   char dlmrt = '\\';   if (pos == string::npos)    {       pos = _filename.rfind('/');       dlmrt = '/';    }   dirname = pos == string::npos ? "" : _filename.substr(0, pos)+ dlmrt;    //负样本列表文件,每行记录一个图片文件路径    //#开头的行为注释,忽略    //读取所有文件名到列表imgFilenames 中   while( !file.eof() )    {       std::getline(file, str);       if (str.empty()) break;       if (str.at(0) == '#' ) continue; /* comment */       imgFilenames.push_back(dirname + str);    }   file.close();    //保存窗口尺寸   winSize = _winSize;   last = round = 0;   return true;}


        总结一下,我们已经打开了正样本vec文件,得到了正样本总数目,获取了负样本的文件列表和总数目。

 





0 0