用opencv训练分类器比较有用的两个辅助工具。
项目主页:http://note.sonots.com/SciSoftware/haartraining.html#v6f077ba
项目主页上有编译好的exe文件,但没有linux下面编译好的二进制文件。
mergevec用于合并多个vec文件。
用法:
mergevec
<collection_file_of_vecs> #类似于创建样本和训练的描述文件,一个存有要合并的vec文件路径列表的文件,可用find命令查找并重定向生成
<output_vec_filename> #输出vec文件名
[-show] #与创建样本时的show参数一样,
[-w <sample_width = 24>] #不解释
[-h <sample_height = 24>] #不解释
vec2img用于从vec文件中释放图像文件
用法:
vec2img
<input_vec_filename> #指定vec文件
<output_filename_format> #指定输出文件格式,是一个含有%d格式的文件名字串,扩展名决定图像文件的输出格式,如test_%04d.png
[-w <sample_width = 24>] #不解释
[-h <sample_height = 24>] #不解释
编译:
下载两个文件的源码,因为都是单个文件,这里我贴出来:
mergevec.cpp
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "cvhaartraining.h"
#include "_cvhaartraining.h" // Load CvVecFile
// Write a vec header into the vec file (located at cvsamples.cpp)
void icvWriteVecHeader( FILE* file, int count, int width, int height );
// Write a sample image into file in the vec format (located at cvsamples.cpp)
void icvWriteVecSample( FILE* file, CvArr* sample );
// Append the body of the input vec to the ouput vec
void icvAppendVec( CvVecFile &in, CvVecFile &out, int *showsamples, int winwidth, int winheight );
// Merge vec files
void icvMergeVecs( char* infoname, const char* outvecname, int showsamples, int width, int height );
// Append the body of the input vec to the ouput vec
void icvAppendVec( CvVecFile &in, CvVecFile &out, int *showsamples, int winwidth, int winheight )
{
CvMat* sample;
if( *showsamples )
{
cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE );
}
if( !feof( in.input ) )
{
in.last = 0;
in.vector = (short*) cvAlloc( sizeof( *in.vector ) * in.vecsize );
if ( *showsamples )
{
if ( in.vecsize != winheight * winwidth )
{
fprintf( stderr, "ERROR: -show: the size of images inside of vec files does not match with %d x %d, but %d\n", winheight, winwidth, in.vecsize );
exit(1);
}
sample = cvCreateMat( winheight, winwidth, CV_8UC1 );
}
else
{
sample = cvCreateMat( in.vecsize, 1, CV_8UC1 );
}
for( int i = 0; i < in.count; i++ )
{
icvGetHaarTraininDataFromVecCallback( sample, &in );
icvWriteVecSample ( out.input, sample );
if( *showsamples )
{
cvShowImage( "Sample", sample );
if( cvWaitKey( 0 ) == 27 )
{
*showsamples = 0;
}
}
}
cvReleaseMat( &sample );
cvFree( (void**) &in.vector );
}
}
void icvMergeVecs( char* infoname, const char* outvecname, int showsamples, int width, int height )
{
char onevecname[PATH_MAX];
int i = 0;
int filenum = 0;
short tmp;
FILE *info;
CvVecFile outvec;
CvVecFile invec;
int prev_vecsize;
// fopen input and output file
info = fopen( infoname, "r" );
if ( info == NULL )
{
fprintf( stderr, "ERROR: Input file %s does not exist or not readable.\n", infoname );
exit(1);
}
outvec.input = fopen( outvecname, "wb" );
if ( outvec.input == NULL )
{
fprintf( stderr, "ERROR: Output file %s is not writable.\n", outvecname );
exit(1);
}
// Header
rewind( info );
outvec.count = 0;
for ( filenum = 0; ; filenum++ )
{
if ( fscanf( info, "%s", onevecname ) == EOF )
{
break;
}
invec.input = fopen( onevecname, "rb" );
if ( invec.input == NULL )
{
fprintf( stderr, "ERROR: Input file %s does not exist or not readable.\n", onevecname );
exit(1);
}
fread( &invec.count, sizeof( invec.count ) , 1, invec.input );
fread( &invec.vecsize, sizeof( invec.vecsize ), 1, invec.input );
fread( &tmp, sizeof( tmp ), 1, invec.input );
fread( &tmp, sizeof( tmp ), 1, invec.input );
outvec.count += invec.count;
if( i > 0 && invec.vecsize != prev_vecsize )
{
fprintf( stderr, "ERROR: The size of images in %s(%d) is different with the previous vec file(%d).\n", onevecname, invec.vecsize, prev_vecsize );
exit(1);
}
prev_vecsize = invec.vecsize;
fclose( invec.input );
}
outvec.vecsize = invec.vecsize;
icvWriteVecHeader( outvec.input, outvec.count, outvec.vecsize, 1);
// Contents
rewind( info );
outvec.count = 0;
for ( i = 0; i < filenum ; i++ )
{
if (fscanf( info, "%s", onevecname ) == EOF) {
break;
}
invec.input = fopen( onevecname, "rb" );
fread( &invec.count, sizeof( invec.count ) , 1, invec.input );
fread( &invec.vecsize, sizeof( invec.vecsize ), 1, invec.input );
fread( &tmp, sizeof( tmp ), 1, invec.input );
fread( &tmp, sizeof( tmp ), 1, invec.input );
icvAppendVec( invec, outvec, &showsamples, width, height );
fclose( invec.input );
}
fclose( outvec.input );
}
int main( int argc, char **argv )
{
int i;
char *infoname = NULL;
char *outvecname = NULL;
int showsamples = 0;
int width = 24;
int height = 24;
if( argc == 1 )
{
printf( "Usage: %s\n <collection_file_of_vecs>\n"
" <output_vec_filename>\n"
" [-show] [-w <sample_width = %d>] [-h <sample_height = %d>]\n",
argv[0], width, height );
return 0;
}
for( i = 1; i < argc; ++i )
{
if( !strcmp( argv[i], "-show" ) )
{
showsamples = 1;
// width = atoi( argv[++i] ); // obsolete -show width height
// height = atoi( argv[++i] );
}
else if( !strcmp( argv[i], "-w" ) )
{
width = atoi( argv[++i] );
}
else if( !strcmp( argv[i], "-h" ) )
{
height = atoi( argv[++i] );
}
else if( argv[i][0] == '-' )
{
fprintf( stderr, "ERROR: The option %s does not exist. n", argv[i] );
exit(1);
}
else if( infoname == NULL )
{
infoname = argv[i];
}
else if( outvecname == NULL )
{
outvecname = argv[i];
}
}
if( infoname == NULL )
{
fprintf( stderr, "ERROR: No input file\n" );
exit(1);
}
if( outvecname == NULL )
{
fprintf( stderr, "ERROR: No output file\n" );
exit(1);
}
icvMergeVecs( infoname, outvecname, showsamples, width, height );
return 0;
}
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "cvhaartraining.h"
#include "_cvhaartraining.h" // Load CvVecFile
void icvVec2Img( const char* vecname, const char* outformat, int width, int height );
// Extract images from a vec file
void icvVec2Img( const char* vecname, const char* outformat, int width, int height )
{
CvVecFile vec;
CvMat* sample;
char outfilename[PATH_MAX];
short tmp;
vec.input = fopen( vecname, "rb" );
if ( vec.input == NULL )
{
fprintf( stderr, "ERROR: Input file %s does not exist or not readable.\n", vecname);
exit(1);
}
fread( &vec.count, sizeof( vec.count ), 1, vec.input );
fread( &vec.vecsize, sizeof( vec.vecsize ), 1, vec.input );
fread( &tmp, sizeof( tmp ), 1, vec.input );
fread( &tmp, sizeof( tmp ), 1, vec.input );
if( !feof( vec.input ) )
{
vec.last = 0;
vec.vector = (short*) cvAlloc( sizeof( *vec.vector ) * vec.vecsize );
if( vec.vecsize != width * height )
{
fprintf( stderr, "ERROR: The size of images inside of vec files does not match with %d x %d, but %d. \n", height, width, vec.vecsize );
exit(1);
}
sample = cvCreateMat( height, width, CV_8UC1 );
//cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE );
for( int i = 0; i < vec.count; i++ )
{
icvGetHaarTraininDataFromVecCallback( sample, &vec );
sprintf( outfilename, outformat, i + 1 );
printf( "%s\n", outfilename );
cvSaveImage( outfilename, sample );
//cvShowImage( "Sample", sample ); cvWaitKey( 0 );
}
cvReleaseMat( &sample );
cvFree( (void**) &vec.vector );
}
fclose( vec.input );
}
int main(int argc, char **argv){
char *vecname = NULL;
char *outformat = NULL;
int width = 24;
int height = 24;
int i = 0;
if( argc == 1 )
{
printf( "Usage: %s\n <input_vec_filename>\n"
" <output_filename_format>\n"
" [-w <sample_width = %d>] [-h <sample_height = %d>]\n",
argv[0], width, height );
printf( "The output filename format is a string having one %%d such as 'samples%%04d.png'.\n"
"The image file format is automatically determined by the extension.\n" );
return 0;
}
for( i = 1; i < argc; ++i )
{
if( !strcmp( argv[i], "-w" ) )
{
width = atoi( argv[++i] );
}
else if( !strcmp( argv[i], "-h" ) )
{
height = atoi( argv[++i] );
}
else if( vecname == NULL )
{
vecname = argv[i];
}
else if( outformat == NULL )
{
outformat = argv[i];
}
}
if ( vecname == NULL )
{
fprintf( stderr, "ERROR: No input vec file. \n" );
exit(1);
}
if ( outformat == NULL )
{
fprintf( stderr, "ERROR: Not output filename format. \n" );
exit(1);
}
icvVec2Img( vecname, outformat, width, height );
return 0;
}
编译的话,将两个文件复制到opencv源码中的apps/haartraining/路径下
编译前,代码需要调整一下,将头文件
#include <cvhaartraining.h>
#include <_cvhaartraining.h> // Load CvVecFile
中的<>换成“”,让其在当前路径中寻找头文件,上面我贴出来的代码是已经调整过的。
编译命令:
mergevec.cpp
$ g++ `pkg-config --cflags --libs opencv` -o mergevec mergevec.cpp cvboost.cpp cvcommon.cpp cvsamples.cpp cvhaarclassifier.cpp cvhaartraining.cpp
vec2img.cpp
$ g++ `pkg-config --cflags --libs opencv` -o vec2img vec2img.cpp cvboost.cpp cvcommon.cpp cvsamples.cpp cvhaarclassifier.cpp cvhaartraining.cpp