Merge pull request #2181 from asmorkalov:ocv_packaging
[profile/ivi/opencv.git] / apps / traincascade / imagestorage.cpp
1 #include "opencv2/core/core.hpp"
2 #include "opencv2/core/internal.hpp"
3
4 #include "cv.h"
5 #include "imagestorage.h"
6 #include <stdio.h>
7 #include <iostream>
8 #include <fstream>
9
10 using namespace std;
11 using namespace cv;
12
13 bool CvCascadeImageReader::create( const string _posFilename, const string _negFilename, Size _winSize )
14 {
15     return posReader.create(_posFilename) && negReader.create(_negFilename, _winSize);
16 }
17
18 CvCascadeImageReader::NegReader::NegReader()
19 {
20     src.create( 0, 0 , CV_8UC1 );
21     img.create( 0, 0, CV_8UC1 );
22     point = offset = Point( 0, 0 );
23     scale       = 1.0F;
24     scaleFactor = 1.4142135623730950488016887242097F;
25     stepFactor  = 0.5F;
26 }
27
28 bool CvCascadeImageReader::NegReader::create( const string _filename, Size _winSize )
29 {
30     string dirname, str;
31     std::ifstream file(_filename.c_str());
32     if ( !file.is_open() )
33         return false;
34
35     size_t pos = _filename.rfind('\\');
36     char dlmrt = '\\';
37     if (pos == string::npos)
38     {
39         pos = _filename.rfind('/');
40         dlmrt = '/';
41     }
42     dirname = pos == string::npos ? "" : _filename.substr(0, pos) + dlmrt;
43     while( !file.eof() )
44     {
45         std::getline(file, str);
46         if (str.empty()) break;
47         if (str.at(0) == '#' ) continue; /* comment */
48         imgFilenames.push_back(dirname + str);
49     }
50     file.close();
51
52     winSize = _winSize;
53     last = round = 0;
54     return true;
55 }
56
57 bool CvCascadeImageReader::NegReader::nextImg()
58 {
59     Point _offset = Point(0,0);
60     size_t count = imgFilenames.size();
61     for( size_t i = 0; i < count; i++ )
62     {
63         src = imread( imgFilenames[last++], 0 );
64         if( src.empty() )
65             continue;
66         round += last / count;
67         round = round % (winSize.width * winSize.height);
68         last %= count;
69
70         _offset.x = std::min( (int)round % winSize.width, src.cols - winSize.width );
71         _offset.y = std::min( (int)round / winSize.width, src.rows - winSize.height );
72         if( !src.empty() && src.type() == CV_8UC1
73                 && _offset.x >= 0 && _offset.y >= 0 )
74             break;
75     }
76
77     if( src.empty() )
78         return false; // no appropriate image
79     point = offset = _offset;
80     scale = max( ((float)winSize.width + point.x) / ((float)src.cols),
81                  ((float)winSize.height + point.y) / ((float)src.rows) );
82
83     Size sz( (int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F) );
84     resize( src, img, sz );
85     return true;
86 }
87
88 bool CvCascadeImageReader::NegReader::get( Mat& _img )
89 {
90     CV_Assert( !_img.empty() );
91     CV_Assert( _img.type() == CV_8UC1 );
92     CV_Assert( _img.cols == winSize.width );
93     CV_Assert( _img.rows == winSize.height );
94
95     if( img.empty() )
96         if ( !nextImg() )
97             return false;
98
99     Mat mat( winSize.height, winSize.width, CV_8UC1,
100         (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step );
101     mat.copyTo(_img);
102
103     if( (int)( point.x + (1.0F + stepFactor ) * winSize.width ) < img.cols )
104         point.x += (int)(stepFactor * winSize.width);
105     else
106     {
107         point.x = offset.x;
108         if( (int)( point.y + (1.0F + stepFactor ) * winSize.height ) < img.rows )
109             point.y += (int)(stepFactor * winSize.height);
110         else
111         {
112             point.y = offset.y;
113             scale *= scaleFactor;
114             if( scale <= 1.0F )
115                 resize( src, img, Size( (int)(scale*src.cols), (int)(scale*src.rows) ) );
116             else
117             {
118                 if ( !nextImg() )
119                     return false;
120             }
121         }
122     }
123     return true;
124 }
125
126 CvCascadeImageReader::PosReader::PosReader()
127 {
128     file = 0;
129     vec = 0;
130 }
131
132 bool CvCascadeImageReader::PosReader::create( const string _filename )
133 {
134     if ( file )
135         fclose( file );
136     file = fopen( _filename.c_str(), "rb" );
137
138     if( !file )
139         return false;
140     short tmp = 0;
141     if( fread( &count, sizeof( count ), 1, file ) != 1 ||
142         fread( &vecSize, sizeof( vecSize ), 1, file ) != 1 ||
143         fread( &tmp, sizeof( tmp ), 1, file ) != 1 ||
144         fread( &tmp, sizeof( tmp ), 1, file ) != 1 )
145         CV_Error_( CV_StsParseError, ("wrong file format for %s\n", _filename.c_str()) );
146     base = sizeof( count ) + sizeof( vecSize ) + 2*sizeof( tmp );
147     if( feof( file ) )
148         return false;
149     last = 0;
150     vec = (short*) cvAlloc( sizeof( *vec ) * vecSize );
151     CV_Assert( vec );
152     return true;
153 }
154
155 bool CvCascadeImageReader::PosReader::get( Mat &_img )
156 {
157     CV_Assert( _img.rows * _img.cols == vecSize );
158     uchar tmp = 0;
159     size_t elements_read = fread( &tmp, sizeof( tmp ), 1, file );
160     if( elements_read != 1 )
161         CV_Error( CV_StsBadArg, "Can not get new positive sample. The most possible reason is "
162                                 "insufficient count of samples in given vec-file.\n");
163     elements_read = fread( vec, sizeof( vec[0] ), vecSize, file );
164     if( elements_read != (size_t)(vecSize) )
165         CV_Error( CV_StsBadArg, "Can not get new positive sample. Seems that vec-file has incorrect structure.\n");
166
167     if( feof( file ) || last++ >= count )
168         CV_Error( CV_StsBadArg, "Can not get new positive sample. vec-file is over.\n");
169
170     for( int r = 0; r < _img.rows; r++ )
171     {
172         for( int c = 0; c < _img.cols; c++ )
173             _img.ptr(r)[c] = (uchar)vec[r * _img.cols + c];
174     }
175     return true;
176 }
177
178 void CvCascadeImageReader::PosReader::restart()
179 {
180     CV_Assert( file );
181     last = 0;
182     fseek( file, base, SEEK_SET );
183 }
184
185 CvCascadeImageReader::PosReader::~PosReader()
186 {
187     if (file)
188         fclose( file );
189     cvFree( &vec );
190 }