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