createsamples.cpp中生成vec文件的实现及详细注释、图解——人脸识别的尝试系列(三)
生活随笔
收集整理的這篇文章主要介紹了
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文件的,下面是具體的實現代碼以及根據我個人理解加上的詳細注釋
為方便大家理解,代碼中插入了兩張圖片,分別展示了相應區域代碼的執行結果
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; }
總結
以上是生活随笔為你收集整理的createsamples.cpp中生成vec文件的实现及详细注释、图解——人脸识别的尝试系列(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: loadrunner 录制java_Lo
- 下一篇: 砥志研思SVM(一) 最优间隔分类器问