Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV createsamples example

Tags:

opencv

I am trying to run the createsamples example from the OpenCV library. I can load in one image at a time and it seems to work fine. However, when I try to load in a collection of images I get a parse error. I am not sure if it is something in my collection file that is invalid or if I am missing something elsewhere. Below is the exact format of my text document.

Text document details:

Target1.JPG 1 0 0 1296 1152
Target2.jpg 1 0 0 1890 709

Command line call:

-info "C:\Users\seb\Desktop\Learning Samples\Target\Target.txt" -num 10 -vec "C:\Users\seb\Desktop\Learning Samples\Target\Target.vec" -maxxangle 0.6 -maxyangle 0 -maxzangle 0.3 -maxidev 100 -bgcolor 0 -bgthresh 0 -w 20 -h 20

Any help is greatly appreciated.

like image 263
Seb Avatar asked Feb 02 '23 16:02

Seb


2 Answers

The parse error is because when you do not specify the number of pos image samples you want to generate, the createsamples will use the default value which is 1000. But if your annotation text document contains less than 1000 bounding boxes of objects, you will get the parse error. You can still use the .vec file for training cascade. The only problem is that the information of number is incorrect. There are two ways to fix it.

  1. You manually count the number of object bounding boxes in the text document. And specify the value less or equal to the number for the option "-num" e.g. createsamples -info xxxxx.txt -vec pos.vec -num [value]

  2. You can revise the OPENCV_ROOT_DIR/modules/haartraining/createsamples.cpp. When the -num is not specified, set the number of pos samples as the number of object bounding boxes in the text document

code snippet: In createsamples.cpp int num = 0;

In cvsamples.cpp

void icvWriteVecHeader( FILE* file, int count, int width, int height )
{
    int vecsize;
    short tmp;

    fseek ( file , 0 , SEEK_SET );

    /* number of samples */
    fwrite( &count, sizeof( count ), 1, file );
    /* vector size */
    vecsize = width * height;
    fwrite( &vecsize, sizeof( vecsize ), 1, file );
    /* min/max values */
    tmp = 0;
    fwrite( &tmp, sizeof( tmp ), 1, file );
    fwrite( &tmp, sizeof( tmp ), 1, file );

    fseek ( file , 0 , SEEK_END );
}

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;

    assert( infoname != NULL );
    assert( vecfilename != NULL );

    total = 0;
    if( !icvMkDir( vecfilename ) )
    {

#if CV_VERBOSE
        fprintf( stderr, "Unable to create directory hierarchy: %s\n", vecfilename );
#endif /* CV_VERBOSE */

        return total;
    }

    info = fopen( infoname, "r" );
    if( info == NULL )
    {

#if CV_VERBOSE
        fprintf( stderr, "Unable to open file: %s\n", infoname );
#endif /* CV_VERBOSE */

        return total;
    }

    vec = fopen( vecfilename, "wb" );
    if( vec == NULL )
    {

#if CV_VERBOSE
        fprintf( stderr, "Unable to open file: %s\n", vecfilename );
#endif /* CV_VERBOSE */

        fclose( info );

        return total;
    }

    sample = cvCreateImage( cvSize( winwidth, winheight ), IPL_DEPTH_8U, 1 );

    icvWriteVecHeader( vec, num, sample->width, sample->height );

    if( showsamples )
    {
        cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE );
    }

    strcpy( fullname, infoname );
    filename = strrchr( fullname, '\\' );
    if( filename == NULL )
    {
        filename = strrchr( fullname, '/' );
    }
    if( filename == NULL )
    {
        filename = fullname;
    }
    else
    {
        filename++;
    }

    while ( num<=0 || total<num )
    {
        int count;

        error = ( fscanf( info, "%s %d", filename, &count ) != 2 );
        if( !error )
        {
            src = cvLoadImage( fullname, 0 );
            error = ( src == NULL );
            if( error )
            {

#if CV_VERBOSE
                fprintf( stderr, "Unable to open image: %s\n", fullname );
#endif /* CV_VERBOSE */
            }
        }
        else
            if ( num <= 0 ) break;

        for( i = 0; i < count; i++, total++ )
        {
            error = ( fscanf( info, "%d %d %d %d", &x, &y, &width, &height ) != 4 );
            if( error ) break;
            cvSetImageROI( src, cvRect( x, y, width, height ) );
            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;
                }
            }
            icvWriteVecSample( vec, sample );

                        if ( num > 0 && total >= num ) break;
        }

        if ( num<=0 )
            icvWriteVecHeader( vec, total, sample->width, sample->height );

        if( src )
        {
            cvReleaseImage( &src );
        }

        if( error )
        {

#if CV_VERBOSE
            fprintf( stderr, "%s(%d) : parse error", infoname, line );
#endif /* CV_VERBOSE */

            break;
        }

        }

    if( sample )
    {
        cvReleaseImage( &sample );
    }

    fclose( vec );
    fclose( info );

    return total;
}
like image 161
Yiqun Hu Avatar answered Feb 27 '23 18:02

Yiqun Hu


I struggled to get opencv_createsamples to work on my windows machine, and it just worked successfully. I thought I would post the details to help someone else. I am using opencv 2.4.8 on Windows 7.

First, I found I needed to use the opencv_createsamples.exe file in the directory that is listed in my path variable as OPENCV_DIR. I could not copy the exe file to some more convenient place.

I set up a sub directory text_classifier in this directory for my images and my text files. I used this command on the command line:

F:\Apps\opencv\build\x64\vc10\bin>opencv_createsamples.exe -vec text_classifier\text_binary_desc -info text_classifier\positive_examples.txt -num 146 -w 1350 -h 900 -bg text_classifier\negative_samples.txt

Notice that I had to list the number of selected areas in the images (-num 146). I also listed the width and height of the positive samples.

Inside the file positive_examples.txt, I needed to have the files listed so:

text_positives_clean\1839_Boettiger_001.JPG 1 708 35 471 793

In other words, the files had to be listed relative to the file positive_examples.txt, and not relative to the exe file (opencv_createsamples.exe). When I tried listing the files relative to the exe, such as:

text_classifier\text_positives_clean\1839_Boettiger_001.JPG 1 708 35 471 793

then I got the error: Unable to open image: text_classifier\text_classifier\text_positives_clean\1839_Boettiger_001.JPG

Then I noticed that my special automated system of creating this file somehow had missed loading some files into the directory, so there were files listed in positive_examples.txt that were not in the directory. The exe simply fell over if it found something listed in positive_examples.txt that was not in the directory. I filled the gaps in the image directory.

Then I got a strange error: Unable to open image: 129

I discovered that I had made this mistake:

text_positives_clean\1862_Streckfuss_0006.JPG 1 813 502 382 353 129 46 526 798 682 780 117 67

Do you notice that the number of selected areas stated here is 1 (the number just following 'JPG'), while the number of selected areas is really 3? So opencv_createsamples.exe tried to open the next thing it found as an image, i.e. '129', after getting the single selected area. And it fell over again.

So I changed the 1 to a 3. Then I got a parse error that actually gave me a line number in my positive_examples.txt file. I went to that line, and found that one of my entries did not have a space between the selected areas, such as:

949 315 157 67131 30 513 806

I fixed this, adding the space, and finally the exe did all my 146 samples. Yoohoo!

Hope this helps someone. :-)

like image 40
excyberlabber Avatar answered Feb 27 '23 18:02

excyberlabber