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

本文详细解析了人脸检测项目中的数据准备工作,包括正样本和负样本的处理。正样本通过将大量人脸图片转为灰度图,统一尺寸并存储为vec文件;而负样本则收集不含人脸的图片,形成文件名列表。代码实现中,PosReader用于读取vec文件,NegReader负责管理负样本文件路径。
摘要由CSDN通过智能技术生成

        我们来看步骤(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.list
neg0\535.png
neg0\536.png
neg0\537.png
neg0\538.png
neg0\539.png
neg0\54.png
neg0\540.png
neg0\541.png
neg0\542.png
neg0\543.png
neg0\544.png
neg0\545.png
neg0\546.png
neg0\547.png
neg0\548.png
neg0\549.png
neg0\55.png
neg0\550.png
neg0\551.png
neg0\552.png
neg0\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文件,得到了正样本总数目,获取了负样本的文件列表和总数目。

 





  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值