Update to 2.0.0 tree from current Fremantle build
[opencv] / apps / traincascade / imagestorage.cpp
diff --git a/apps/traincascade/imagestorage.cpp b/apps/traincascade/imagestorage.cpp
new file mode 100755 (executable)
index 0000000..c792b0c
--- /dev/null
@@ -0,0 +1,178 @@
+#include "cv.h"
+#include "imagestorage.h"
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+
+bool CvCascadeImageReader::create( const String _posFilename, const String _negFilename, Size _winSize )
+{
+    return posReader.create(_posFilename) && negReader.create(_negFilename, _winSize);
+}
+
+CvCascadeImageReader::NegReader::NegReader()
+{
+    src.create( 0, 0 , CV_8UC1 );
+    img.create( 0, 0, CV_8UC1 );
+    point = offset = Point( 0, 0 );
+    scale       = 1.0F;
+    scaleFactor = 1.4142135623730950488016887242097F;
+    stepFactor  = 0.5F;
+}
+
+bool CvCascadeImageReader::NegReader::create( const String _filename, Size _winSize )
+{
+    String dirname, str;
+    std::ifstream file(_filename.c_str());
+    if ( !file.is_open() )
+        return false;
+
+    size_t pos = _filename.rfind('\\');
+    char dlmrt = '\\';
+    if (pos == String::npos)
+    {
+        pos = _filename.rfind('/');
+        dlmrt = '/';
+    }
+    dirname = _filename.substr(0, pos) + dlmrt;
+    while( !file.eof() )
+    {
+        std::getline(file, str);
+        if (str.empty()) break;
+        if (str.at(0) == '#' ) continue; /* comment */
+        imgFilenames.push_back(dirname + str);
+    }
+    file.close();
+
+    winSize = _winSize;
+    last = round = 0;
+    return true;
+}
+
+bool CvCascadeImageReader::NegReader::nextImg()
+{
+    Point _offset = Point(0,0);
+    size_t count = imgFilenames.size();
+    for( size_t i = 0; i < count; i++ )
+    {
+        src = imread( imgFilenames[last++], 0 );
+        if( src.empty() ) 
+            continue;
+        round += last / count;
+        round = round % (winSize.width * winSize.height);
+        last %= count;
+
+        _offset.x = min( (int)round % winSize.width, src.cols - winSize.width );
+        _offset.y = min( (int)round / winSize.width, src.rows - winSize.height );
+        if( !src.empty() && src.type() == CV_8UC1 
+                && offset.x >= 0 && offset.y >= 0 )
+            break;
+    }
+
+    if( src.empty() )
+        return false; // no appropriate image
+    point = offset = _offset;
+    scale = max( ((float)winSize.width + point.x) / ((float)src.cols),
+                 ((float)winSize.height + point.y) / ((float)src.rows) );
+    
+    Size sz( (int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F) );
+    resize( src, img, sz );
+    return true;
+}
+
+bool CvCascadeImageReader::NegReader::get( Mat& _img )
+{
+    CV_Assert( !_img.empty() );
+    CV_Assert( _img.type() == CV_8UC1 );
+    CV_Assert( _img.cols == winSize.width );
+    CV_Assert( _img.rows == winSize.height );
+
+    if( img.empty() )
+        if ( !nextImg() ) 
+            return false;
+
+    Mat mat( winSize.height, winSize.width, CV_8UC1,
+        (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step );
+    mat.copyTo(_img);
+
+    if( (int)( point.x + (1.0F + stepFactor ) * winSize.width ) < img.cols )
+        point.x += (int)(stepFactor * winSize.width);
+    else
+    {
+        point.x = offset.x;
+        if( (int)( point.y + (1.0F + stepFactor ) * winSize.height ) < img.rows )
+            point.y += (int)(stepFactor * winSize.height);
+        else
+        {
+            point.y = offset.y;
+            scale *= scaleFactor;
+            if( scale <= 1.0F )
+                resize( src, img, Size( (int)(scale*src.cols), (int)(scale*src.rows) ) );
+            else
+            {
+                if ( !nextImg() ) 
+                    return false;
+            }
+        }
+    }
+    return true;
+}
+
+CvCascadeImageReader::PosReader::PosReader()
+{
+    file = 0;
+    vec = 0;
+}
+
+bool CvCascadeImageReader::PosReader::create( const String _filename )
+{
+    if ( file )
+        fclose( file );
+    file = fopen( _filename.c_str(), "rb" );
+
+    if( !file )
+        return false;
+    short tmp = 0;  
+    fread( &count, sizeof( count ), 1, file );
+    fread( &vecSize, sizeof( vecSize ), 1, file );
+    fread( &tmp, sizeof( tmp ), 1, file );
+    fread( &tmp, sizeof( tmp ), 1, file );
+    base = sizeof( count ) + sizeof( vecSize ) + 2*sizeof( tmp );
+    if( feof( file ) )
+        return false;
+    last = 0;
+    vec = (short*) cvAlloc( sizeof( *vec ) * vecSize );
+    CV_Assert( vec );
+    return true;
+}
+
+bool CvCascadeImageReader::PosReader::get( Mat &_img )
+{
+    CV_Assert( _img.rows * _img.cols == vecSize );
+    uchar tmp = 0;
+    fread( &tmp, sizeof( tmp ), 1, file );
+    fread( vec, sizeof( vec[0] ), vecSize, file );
+
+    if( feof( file ) || last++ >= count )
+        return false;
+
+    for( int r = 0; r < _img.rows; r++ )
+    {
+        for( int c = 0; c < _img.cols; c++ )
+            _img.ptr(r)[c] = (uchar)vec[r * _img.cols + c];
+    }
+    return true;
+}
+
+void CvCascadeImageReader::PosReader::restart()
+{
+    CV_Assert( file );
+    last = 0;
+    fseek( file, base, SEEK_SET );
+}
+
+CvCascadeImageReader::PosReader::~PosReader()
+{
+    if (file)
+        fclose( file );
+    cvFree( &vec );
+}