createsamples.cpp中生成vec文件的实现及详细注释、图解——人脸识别的尝试系列(三)

在我们开始训练我们的Haar分类器之前,首先要对样本进行处理。

人脸识别的尝试系列(一)中:http://blog.csdn.net/u011583927/article/details/44627493

我们已经提到了如何准备我们的样本,在如下图准备好样本之后


需要在cmd窗口中调用类似如下的命令生成vec文件

opencv_createsamples.exe–vec pos.vec –info pos_image.txt –bg neg_image.txt –w 24 –h 24 –num 400

那么具体是如何生成的vec文件的,下面是具体的实现代码以及根据我个人理解加上的详细注释

为方便大家理解,代码中插入了两张图片,分别展示了相应区域代码的执行结果


/** createsamples.cpp 生成vec文件的可执行程序的具体实现** Create test/training samples        利用描述正样本和负样本的txt文件创建vec文件* 命令行示例:
opencv_createsamples.exe –vec pos.vec –info pos_image.txt –bg neg_image.txt –w 24 –h 24 –num 400
*需要先将命令行的地址调到当前文件夹下*/#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <memory>using namespace std;#include "cvhaartraining.h"
#include "ioutput.h"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;// max_intensity_deviationdouble maxxangle = 1.1;double maxyangle = 1.1;double maxzangle = 0.5;bool showsamples = false;/* the samples are adjusted to this scale in the sample preview window */double scale = 4.0;int width  = 24;int height = 24;bool pngoutput = false; /* whether to make the samples in png or in jpg*/srand((unsigned int)time(0));//如果只输入opencv_createsamples.exe 相当于查看命令行参数使用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""  [-pngoutput]",argv[0], num, bgcolor, bgthreshold, maxintensitydev,maxxangle, maxyangle, maxzangle, scale, width, height );return 0;}

 for( i = 1; i < argc; ++i )
{//strcmp(str1,str2)函数:比较两个字符串。
//相等返回0;str1>str2返回正数;str1<str2返回负数if( !strcmp( argv[i], "-info" ) ){//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" ) ){//atoi 把一个字符串转化成整形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" ) ){//输入含-inv指令invert = 1;}else if( !strcmp( argv[i], "-randinv" ) ){//输入含-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 = true;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] );}else if( !strcmp( argv[i], "-pngoutput" ) ){pngoutput = true;}}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 applied to display : %g\n", scale );}if( !pngoutput){printf( "Original image will be scaled to:\n");printf( "\tWidth: $backgroundWidth / %d\n", width );printf( "\tHeight: $backgroundHeight / %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 data set from single image applying distortions...\n""Output format: %s\n",(( pngoutput ) ? "PNG" : "JPG") );std::auto_ptr<DatasetGenerator> creator;if( pngoutput ){creator = std::auto_ptr<DatasetGenerator>( new PngDatasetGenerator( infoname ) );}else{creator = std::auto_ptr<DatasetGenerator>( new JpgDatasetGenerator( infoname ) );}creator->create( imagename, bgcolor, bgthreshold, bgfilename, num,invert, maxintensitydev, maxxangle, maxyangle, maxzangle,showsamples, width, height );printf( "Done\n" );}else if( infoname && vecname )
{//生成vec文件,我们使用的这种命令//命令包括正样本描述文件的文件名,准备生成的vec文件的文件名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 )
{//查看vec文件//命令不包含正样本文件,背景样本文件,单个正样本图像,只包含vec文件路径

 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;
}cvCreateTrainingSamplesFromInfo函数的具体实现
为方便理解,对应于上面我们输入的命令来进行解释
-infoname    pos_image.txt 正样本描述文件文件名
-vecfilename pos.vec 这个参数相当于指定创建的vec文件的名字,函数执行前这个vec文件并不存在
-num         400 正样本总数 
-showsamples false 是否显示样本
-width
-height
int cvCreateTrainingSamplesFromInfo( const char* infoname, const char* vecfilename,int num,int showsamples,int winwidth, int winheight )
{char fullname[PATH_MAX];char* filename;FILE* info;FILE* vec;IplImage* src=0;IplImage* sample;int line;int error;int i;int x, y, width, height;int total;/*
#include <assert.h>
void assert( int expression );
assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。*/assert( infoname != NULL );assert( vecfilename != NULL );total = 0;if( !icvMkDir( vecfilename ) )
{// icvMkDir() 
//个人理解:判断文件名vecfilename是否只包含文件名,不包含路径//例如:pos.veg返回1  D:\\pos.veg返回0//若只包含文件名,返回1,否则返回0#if CV_VERBOSEfprintf( stderr, "Unable to create directory hierarchy: %s\n", vecfilename );
#endif /* CV_VERBOSE */return total;}info = fopen( infoname, "r" );//以只读方式打开文件infoname,若文件不存在不创建该文件(即返回null)if( info == NULL ){#if CV_VERBOSEfprintf( stderr, "Unable to open file: %s\n", infoname );
#endif /* CV_VERBOSE */return total;}vec = fopen( vecfilename, "wb" );// 以二进制写方式打开文件,若文件不存在则创建该文件if( vec == NULL ){#if CV_VERBOSEfprintf( stderr, "Unable to open file: %s\n", vecfilename );
#endif /* CV_VERBOSE */fclose( info );return total;}//创建一个单通道byte图像sample = cvCreateImage( cvSize( winwidth, winheight ), IPL_DEPTH_8U, 1 );//写vec文件头icvWriteVecHeader( vec, num, sample->width, sample->height );if( showsamples ){cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE );}strcpy( fullname, infoname );/*strrchr() 函数查找字符在指定字符串中从后面开始的第一次出现的位置,如果成功,则返回从该位置到字符串结尾的所有字符,如果失败,则返回 false。与之相对应的是strchr()函数,它查找字符串中首次出现指定字符的位置。*/filename = strrchr( fullname, '\\' );//获取正样本描述文件的文件名,剔除路径if( filename == NULL ){filename = strrchr( fullname, '/' );}if( filename == NULL ){filename = fullname;}else
{//正常情况,将指针指向‘\’后面的第一个字符filename++;}//遍历每张正样本图片,将其信息写入vec文件for( line = 1, error = 0, total = 0; total < num ;line++ ){int count;/* 
fscanf功能: 从一个流中执行格式化输入,fscanf遇到空格和换行时结束,注意空格时也结束。
intfscanf(FILE*stream,constchar*format,[argument...]);
FILE *stream:文件指针;
char *format:格式字符串;
[argument...]:输入列表。
返回值:整型,成功读入的参数的个数
*/error = ( fscanf( info, "%s %d", filename, &count ) != 2 ); 
//info——正样本描述文件的文件流   
// 正样本描述文件每一行的格式  pos_image/0.bmp 1 0 0 24 24
//注意!filename是指向fullname的指针。所以这里以filename作为读入数据的参数,实际上修改的是fullname的内容。读入信息后fullname表示某一个正样本图片的地址(相对路径)
//count 表示文件的个数if( !error )//说明读取是正确的,获取样本图片{src = cvLoadImage( fullname, 0 );//读取一副正样本图像(强制转化为灰度图像)error = ( src == NULL );if( error ){#if CV_VERBOSEfprintf( stderr, "Unable to open image: %s\n", fullname );
#endif /* CV_VERBOSE */}}//遍历当前样本图片中的所有子窗口样本。//一般情况下的使用方法是只有一个子窗口也就是整幅样本图片,
即count=1,且x=0 y=0 width height就是样本的宽和高 for( i = 0; (i < count) && (total < num); i++, total++ ){error = ( fscanf( info, "%d %d %d %d", &x, &y, &width, &height ) != 4 );//读取当前图像的顶点坐标以及长宽if( error ) break;// cvSetImageROI 基于给定的矩形设置图像的ROI(感兴趣区域)cvSetImageROI( src, cvRect( x, y, width, height ) );void cvResize( const CvArr* src, CvArr* dst, int interpolation=CV_INTER_LINEAR );函数cvResize()功能: 重新调整图像src(或它的ROI),使它精确匹配目标dst(或其ROI)。这里需要说明的是,cvResize可以用来调整3通道图像(如RGB图像)和单通道图像的大小。src 源图像;  dst 目标图像cvResize( src, sample, width >= sample->width &&height >= sample->height ? CV_INTER_AREA : CV_INTER_LINEAR );if( showsamples ){cvShowImage( "Sample", sample );if( cvWaitKey( 0 ) == 27 ){showsamples = 0;}}//将当前这幅样本图片信息写入vec文件中icvWriteVecSample( vec, sample );}//释放当前的图片占用的内存if( src ){cvReleaseImage( &src );}if( error ){#if CV_VERBOSEfprintf( stderr, "%s(%d) : parse error", infoname, line );
#endif /* CV_VERBOSE */break;}}if( sample ){cvReleaseImage( &sample );}fclose( vec );fclose( info );return total;
}




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设置同时上内外网+文件共享

最近做了这样一个小项目&#xff0c;逻辑是这样的。 需要在某个办公人员的电脑上装个软件&#xff0c;从局域网中的另一台电脑中读取access数据库&#xff0c;然后用apn接入某个系统的内网传输数据。 同时还要保证这个工作人员能够正常的浏览因特网。 这就涉及到了两个内容。…

浅析haartraining方法进行人脸检测

上个月用了两周的时间&#xff0c;学习了用于人脸检测的haartraining算法&#xff0c;今天打算做一总结 首先先为和我一样的初学者推荐几篇博客 http://blog.csdn.net/zouxy09/article/details/7922923真的很感谢写这篇文章的博主&#xff0c;讲解深入浅出。本文中的主要逻辑…

haartraining训练分类器方法cvCreateTreeCascadeClassifier()详解——人脸识别的尝试系列(四)

本文将介绍opencv_haartraining.exe中训练分类器的核心方法cvCreateTreeCascadeClassifier&#xff08;&#xff09;中参数的具体含义&#xff0c;以及具体实现代码附加详细的注释。最后给出运行截图以作代码阅读的参考 我们还是从具体的例子出发&#xff0c;以一些实际的参数帮…

常用知识总结——模板Template

1. 模板的概念。 我们已经学过重载(Overloading)&#xff0c;对重载函数而言,C的检查机制能通过函数参数的不同及所属类的不同。正确的调用重载函数。例如&#xff0c;为求两个数的最大值&#xff0c;我们定义MAX()函数需要对不同的数据类型分别定义不同重载(Overload)版本。 /…

opencv视频读写和视频等间隔采样

今天学习了opencv的HighGUI的内容 总结了两个视频读写demo以备以后进行视频处理和识别用 demo1 视频的读取和写入 按顺序读取视频的每一帧。对于读取的每一帧图像&#xff0c;显示在窗口中&#xff0c;然后转化为灰度图像输出到指定的文件中。 运行期间可以按ESC键退出。 还…

Socket通用TCP通信协议设计及实现(防止粘包,可移植,可靠)

Socket通用TCP通信协议设计及实现&#xff08;防止粘包&#xff0c;可移植&#xff0c;可靠&#xff09; 引文 我们接收Socket字节流数据一般都会定义一个数据包协议。我们每次开发一个软件的通信模块时&#xff0c;尽管具体的数据内容是不尽相同的&#xff0c;但是大体上的框…

浅谈 Adaboost 算法

注&#xff1a;本文全文引用自http://blog.csdn.net/carson2005/article/details/41444289 当然作者也是转载的&#xff0c;原文是http://blog.csdn.net/haidao2009/article/details/7514787 写的很好所以转载过来以便之后再次翻阅。 一 Boosting 算法的起源 boost 算法系列的起…

如何理解离散傅里叶变换(一)实数形式傅里叶变换

如何理解离散傅里叶变换&#xff08;一&#xff09; ——实数形式傅里叶变换 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 本文…

快速傅里叶变换(FFT)

快速傅里叶变换&#xff08;FFT&#xff09; ------------------------------------------------------------------------------------------------------------------- 作者&#xff1a;随煜而安 时间&#xff1a;2015/7/21 注&#xff1a;本文为作者原创文章&#xff0c…

风机桨叶故障诊断(一) 样本的获取

风机桨叶故障诊断&#xff08;一&#xff09; 样本的获取今天团队接了个新项目&#xff0c;做一个风机桨叶故障诊断系统。虽然马上就是准备考研的关键期了&#xff0c;可是一想到这是我学习了机器学习后遇到的第一个实际项目&#xff0c;我觉得参与进来&#xff0c;也帮导师分担…

风机桨叶故障诊断(二) 获取图像几何主方向

风机桨叶故障诊断&#xff08;二&#xff09; 获取图像几何主方向 昨天&#xff0c;我将视频资源按帧抽取并筛选得到了可以用来提取样本的图像库。今天还是进行项目的准备工作。当我们拿到一张图片&#xff0c;我们的软件要做的大致可以分为三个步骤&#xff1a;从原图中识别桨…

风机桨叶故障诊断(三) 识别桨叶——初步构建BP神经网络

风机桨叶故障诊断&#xff08;三&#xff09; 识别桨叶——初步构建BP神经网络 新的一天&#xff0c;希望有好的运气。今天开始着手系统的第一个模块&#xff0c;从一幅图像中寻找到桨叶所在的位置。第一直觉我们的识别任务属于难度比较大&#xff0c;干扰因素多的了&#xff…

风机桨叶故障诊断(五) 修改隐含层神经元个数的尝试

风机桨叶故障诊断&#xff08;五&#xff09; 修改隐含层神经元个数的尝试 我们已经为训练一个更为稳健的神经网络做好了样本的准备工作&#xff0c;那么我们开始下一步的工作吧&#xff01; 我们已经有了样本集&#xff0c;目前我筛选出来了247个正样本&#xff0c;652个负样本…

风机桨叶故障诊断(六) 利用自编码器进行特征学习

风机桨叶故障诊断&#xff08;六&#xff09; 利用自编码器进行特征学习 在之前的工作中&#xff0c;我已经初步构建了三层的BP神经网络&#xff0c;并已经从样本集的选取&#xff0c;模型的选择&#xff08;隐含层神经元个数&#xff09;&#xff0c;和输出层神经元阈值选择这…

风机桨叶故障诊断(七) 滑动窗与非极大值抑制NMS

风机桨叶故障诊断&#xff08;七&#xff09;滑动窗与非极大值一直NMS 到目前为止&#xff0c;我已经利用自编码神经网络提取特征后训练得到了BP神经网络&#xff08;参见&#xff1a;点击打开链接&#xff09;&#xff0c;且在测试样本集上表现不错。下面我们就要应用到实际中…