add factory method for Fields structure
authormarina.kolpakova <marina.kolpakova@itseez.com>
Thu, 11 Oct 2012 15:11:39 +0000 (19:11 +0400)
committermarina.kolpakova <marina.kolpakova@itseez.com>
Sat, 10 Nov 2012 01:10:42 +0000 (05:10 +0400)
modules/gpu/src/softcascade.cpp

index f25c5a3..fc7114b 100644 (file)
@@ -78,77 +78,255 @@ namespace imgproc
 
 struct cv::gpu::SoftCascade::Filds
 {
+    struct CascadeIntrinsics
+    {
+        static const float lambda = 1.099f, a = 0.89f;
+
+        static float getFor(int channel, float scaling)
+        {
+            CV_Assert(channel < 10);
+
+            if (fabs(scaling - 1.f) < FLT_EPSILON)
+                return 1.f;
+
+            // according to R. Benenson, M. Mathias, R. Timofte and L. Van Gool's and Dallal's papers
+            static const float A[2][2] =
+            {   //channel <= 6, otherwise
+                {        0.89f, 1.f}, // down
+                {        1.00f, 1.f}  // up
+            };
+
+            static const float B[2][2] =
+            {   //channel <= 6,  otherwise
+                { 1.099f / ::log(2), 2.f}, // down
+                {             0.f, 2.f}  // up
+            };
 
-    Filds()
+            float a = A[(int)(scaling >= 1)][(int)(channel > 6)];
+            float b = B[(int)(scaling >= 1)][(int)(channel > 6)];
+
+            // printf("!!! scaling: %f %f %f -> %f\n", scaling, a, b, a * pow(scaling, b));
+            return a * ::pow(scaling, b);
+        }
+    };
+
+    static Filds* parseCascade(const FileNode &root, const float mins, const float maxs)
     {
-        plane.create(FRAME_HEIGHT * (HOG_LUV_BINS + 1), FRAME_WIDTH, CV_8UC1);
-        fplane.create(FRAME_HEIGHT * 6, FRAME_WIDTH, CV_32FC1);
-        luv.create(FRAME_HEIGHT, FRAME_WIDTH, CV_8UC3);
-        shrunk.create(FRAME_HEIGHT / 4 * HOG_LUV_BINS, FRAME_WIDTH / 4, CV_8UC1);
-        integralBuffer.create(1 , (shrunk.rows + 1) * HOG_LUV_BINS * (shrunk.cols + 1), CV_32SC1);
-        hogluv.create((FRAME_HEIGHT / 4 + 1) * HOG_LUV_BINS, FRAME_WIDTH / 4 + 64, CV_32SC1);
-        detCounter.create(1,1, CV_32SC1);
-    }
+        static const char *const SC_STAGE_TYPE          = "stageType";
+        static const char *const SC_BOOST               = "BOOST";
 
-    // scales range
-    float minScale;
-    float maxScale;
+        static const char *const SC_FEATURE_TYPE        = "featureType";
+        static const char *const SC_ICF                 = "ICF";
 
-    int origObjWidth;
-    int origObjHeight;
+        // only Ada Boost supported
+        std::string stageTypeStr = (string)root[SC_STAGE_TYPE];
+        CV_Assert(stageTypeStr == SC_BOOST);
 
-    int downscales;
+        // only HOG-like integral channel features cupported
+        string featureTypeStr = (string)root[SC_FEATURE_TYPE];
+        CV_Assert(featureTypeStr == SC_ICF);
 
-    GpuMat octaves;
-    GpuMat stages;
-    GpuMat nodes;
-    GpuMat leaves;
-    GpuMat levels;
+        static const char *const SC_ORIG_W              = "width";
+        static const char *const SC_ORIG_H              = "height";
 
-    GpuMat detCounter;
+        int origWidth = (int)root[SC_ORIG_W];
+        CV_Assert(origWidth  == ORIG_OBJECT_WIDTH);
 
-    // preallocated buffer 640x480x10 for hogluv + 640x480 got gray
-    GpuMat plane;
+        int origHeight = (int)root[SC_ORIG_H];
+        CV_Assert(origHeight == ORIG_OBJECT_HEIGHT);
 
-    // preallocated buffer for floating point operations
-    GpuMat fplane;
+        static const char *const SC_OCTAVES             = "octaves";
+        static const char *const SC_STAGES              = "stages";
+        static const char *const SC_FEATURES            = "features";
 
-    // temporial mat for cvtColor
-    GpuMat luv;
+        static const char *const SC_WEEK                = "weakClassifiers";
+        static const char *const SC_INTERNAL            = "internalNodes";
+        static const char *const SC_LEAF                = "leafValues";
 
-    // 160x120x10
-    GpuMat shrunk;
+        static const char *const SC_OCT_SCALE           = "scale";
+        static const char *const SC_OCT_STAGES          = "stageNum";
+        static const char *const SC_OCT_SHRINKAGE       = "shrinkingFactor";
 
-    // temporial mat for integrall
-    GpuMat integralBuffer;
+        static const char *const SC_STAGE_THRESHOLD     = "stageThreshold";
 
-    // 161x121x10
-    GpuMat hogluv;
+        static const char * const SC_F_CHANNEL          = "channel";
+        static const char * const SC_F_RECT             = "rect";
 
-    std::vector<float> scales;
 
-    device::icf::CascadeInvoker<device::icf::CascadePolicy> invoker;
+        FileNode fn = root[SC_OCTAVES];
+            if (fn.empty()) return false;
 
-    static const int shrinkage = 4;
+        using namespace device::icf;
 
-    enum { BOOST = 0 };
-    enum
+        std::vector<Octave>  voctaves;
+        std::vector<float>   vstages;
+        std::vector<Node>    vnodes;
+        std::vector<float>   vleaves;
+
+        FileNodeIterator it = fn.begin(), it_end = fn.end();
+        int feature_offset = 0;
+        ushort octIndex = 0;
+        ushort shrinkage = 1;
+
+        for (; it != it_end; ++it)
+        {
+            FileNode fns = *it;
+            float scale = (float)fns[SC_OCT_SCALE];
+
+            bool isUPOctave = scale >= 1;
+
+            ushort nstages = saturate_cast<ushort>((int)fns[SC_OCT_STAGES]);
+            ushort2 size;
+            size.x = cvRound(ORIG_OBJECT_WIDTH * scale);
+            size.y = cvRound(ORIG_OBJECT_HEIGHT * scale);
+            shrinkage = saturate_cast<ushort>((int)fns[SC_OCT_SHRINKAGE]);
+
+            Octave octave(octIndex, nstages, shrinkage, size, scale);
+            CV_Assert(octave.stages > 0);
+            voctaves.push_back(octave);
+
+            FileNode ffs = fns[SC_FEATURES];
+            if (ffs.empty()) return false;
+
+            FileNodeIterator ftrs = ffs.begin();
+
+            fns = fns[SC_STAGES];
+            if (fn.empty()) return false;
+
+            // for each stage (~ decision tree with H = 2)
+            FileNodeIterator st = fns.begin(), st_end = fns.end();
+            for (; st != st_end; ++st )
+            {
+                fns = *st;
+                vstages.push_back((float)fns[SC_STAGE_THRESHOLD]);
+
+                fns = fns[SC_WEEK];
+                FileNodeIterator ftr = fns.begin(), ft_end = fns.end();
+                for (; ftr != ft_end; ++ftr)
+                {
+                    fns = (*ftr)[SC_INTERNAL];
+                    FileNodeIterator inIt = fns.begin(), inIt_end = fns.end();
+                    for (; inIt != inIt_end;)
+                    {
+                        // int feature = (int)(*(inIt +=2)) + feature_offset;
+                        inIt +=3;
+                        // extract feature, Todo:check it
+                        uint th = saturate_cast<uint>((float)(*(inIt++)));
+                        cv::FileNode ftn = (*ftrs)[SC_F_RECT];
+                        cv::FileNodeIterator r_it = ftn.begin();
+                        uchar4 rect;
+                        rect.x = saturate_cast<uchar>((int)*(r_it++));
+                        rect.y = saturate_cast<uchar>((int)*(r_it++));
+                        rect.z = saturate_cast<uchar>((int)*(r_it++));
+                        rect.w = saturate_cast<uchar>((int)*(r_it++));
+
+                        if (isUPOctave)
+                        {
+                            rect.z -= rect.x;
+                            rect.w -= rect.y;
+                        }
+
+                        uint channel = saturate_cast<uint>((int)(*ftrs)[SC_F_CHANNEL]);
+                        vnodes.push_back(Node(rect, channel, th));
+                        ++ftrs;
+                    }
+
+                    fns = (*ftr)[SC_LEAF];
+                    inIt = fns.begin(), inIt_end = fns.end();
+                    for (; inIt != inIt_end; ++inIt)
+                        vleaves.push_back((float)(*inIt));
+                }
+            }
+
+            feature_offset += octave.stages * 3;
+            ++octIndex;
+        }
+
+        cv::Mat hoctaves(1, voctaves.size() * sizeof(Octave), CV_8UC1, (uchar*)&(voctaves[0]));
+        CV_Assert(!hoctaves.empty());
+
+        cv::Mat hstages(cv::Mat(vstages).reshape(1,1));
+        CV_Assert(!hstages.empty());
+
+        cv::Mat hnodes(1, vnodes.size() * sizeof(Node), CV_8UC1, (uchar*)&(vnodes[0]) );
+        CV_Assert(!hnodes.empty());
+
+        cv::Mat hleaves(cv::Mat(vleaves).reshape(1,1));
+        CV_Assert(!hleaves.empty());
+
+        std::vector<Level> vlevels;
+        float logFactor = (::log(maxs) - ::log(mins)) / (TOTAL_SCALES -1);
+
+        float scale = mins;
+        int downscales = 0;
+        for (int sc = 0; sc < TOTAL_SCALES; ++sc)
+        {
+            int width  = ::std::max(0.0f, FRAME_WIDTH - (origWidth  * scale));
+            int height = ::std::max(0.0f, FRAME_HEIGHT - (origHeight * scale));
+
+            float logScale = ::log(scale);
+            int fit = fitOctave(voctaves, logScale);
+
+            Level level(fit, voctaves[fit], scale, width, height);
+            level.scaling[0] = CascadeIntrinsics::getFor(0, level.relScale);
+            level.scaling[1] = CascadeIntrinsics::getFor(9, level.relScale);
+
+            if (!width || !height)
+                break;
+            else
+            {
+                vlevels.push_back(level);
+                if (voctaves[fit].scale < 1) ++downscales;
+            }
+
+            if (::fabs(scale - maxs) < FLT_EPSILON) break;
+            scale = ::std::min(maxs, ::expf(::log(scale) + logFactor));
+
+            // std::cout << "level " << sc
+            //           << " octeve "
+            //           << vlevels[sc].octave
+            //           << " relScale "
+            //           << vlevels[sc].relScale
+            //           << " " << vlevels[sc].shrScale
+            //           << " [" << (int)vlevels[sc].objSize.x
+            //           << " " <<  (int)vlevels[sc].objSize.y << "] ["
+            // <<  (int)vlevels[sc].workRect.x << " " <<  (int)vlevels[sc].workRect.y << "]" << std::endl;
+        }
+
+        cv::Mat hlevels(1, vlevels.size() * sizeof(Level), CV_8UC1, (uchar*)&(vlevels[0]) );
+        CV_Assert(!hlevels.empty());
+
+        Filds* filds = new Filds(mins, maxs, origWidth, origHeight, shrinkage, downscales,
+            hoctaves, hstages, hnodes, hleaves, hlevels);
+
+        return filds;
+    }
+
+    Filds( const float mins, const float maxs, const int ow, const int oh, const int shr, const int ds,
+        cv::Mat hoctaves, cv::Mat hstages, cv::Mat hnodes, cv::Mat hleaves, cv::Mat hlevels)
+    : minScale(mins), maxScale(maxs), origObjWidth(ow), origObjHeight(oh), shrinkage(shr), downscales(ds)
     {
-        FRAME_WIDTH        = 640,
-        FRAME_HEIGHT       = 480,
-        TOTAL_SCALES       = 55,
-        ORIG_OBJECT_WIDTH  = 64,
-        ORIG_OBJECT_HEIGHT = 128,
-        HOG_BINS           = 6,
-        LUV_BINS           = 3,
-        HOG_LUV_BINS       = 10
-    };
+        plane.create(FRAME_HEIGHT * (HOG_LUV_BINS + 1), FRAME_WIDTH, CV_8UC1);
+        fplane.create(FRAME_HEIGHT * 6, FRAME_WIDTH, CV_32FC1);
+        luv.create(FRAME_HEIGHT, FRAME_WIDTH, CV_8UC3);
+        shrunk.create(FRAME_HEIGHT / shr * HOG_LUV_BINS, FRAME_WIDTH / shr, CV_8UC1);
+        integralBuffer.create(1 , (shrunk.rows + 1) * HOG_LUV_BINS * (shrunk.cols + 1), CV_32SC1);
+        hogluv.create((FRAME_HEIGHT / shr + 1) * HOG_LUV_BINS, FRAME_WIDTH / shr + 64, CV_32SC1);
+        detCounter.create(1,1, CV_32SC1);
+
+        octaves.upload(hoctaves);
+        stages.upload(hstages);
+        nodes.upload(hnodes);
+        leaves.upload(hleaves);
+        levels.upload(hlevels);
+
+        invoker = device::icf::CascadeInvoker<device::icf::CascadePolicy>(levels, octaves, stages, nodes, leaves);
+
+    }
 
-    bool fill(const FileNode &root, const float mins, const float maxs);
     void detect(int scale, const cv::gpu::GpuMat& roi, cv::gpu::GpuMat& objects, cudaStream_t stream) const
     {
         cudaMemset(detCounter.data, 0, detCounter.step * detCounter.rows * sizeof(int));
-        // device::icf::CascadeInvoker<device::icf::CascadePolicy> invoker(levels, octaves, stages, nodes, leaves);
         invoker(roi, hogluv, objects, detCounter, downscales, scale);
     }
 
@@ -169,11 +347,9 @@ struct cv::gpu::SoftCascade::Filds
     }
 
 private:
-    void calcLevels(const std::vector<device::icf::Octave>& octs,
-                                                    int frameW, int frameH, int nscales);
 
     typedef std::vector<device::icf::Octave>::const_iterator  octIt_t;
-    int fitOctave(const std::vector<device::icf::Octave>& octs, const float& logFactor) const
+    static int fitOctave(const std::vector<device::icf::Octave>& octs, const float& logFactor)
     {
         float minAbsLog = FLT_MAX;
         int res =  0;
@@ -257,247 +433,61 @@ private:
             cv::gpu::integralBuffered(channel, sum, integralBuffer);
         }
     }
-};
-
-bool cv::gpu::SoftCascade::Filds::fill(const FileNode &root, const float mins, const float maxs)
-{
-    using namespace device::icf;
-    minScale = mins;
-    maxScale = maxs;
-
-    // cascade properties
-    static const char *const SC_STAGE_TYPE          = "stageType";
-    static const char *const SC_BOOST               = "BOOST";
-
-    static const char *const SC_FEATURE_TYPE        = "featureType";
-    static const char *const SC_ICF                 = "ICF";
-
-    static const char *const SC_ORIG_W              = "width";
-    static const char *const SC_ORIG_H              = "height";
-
-    static const char *const SC_OCTAVES             = "octaves";
-    static const char *const SC_STAGES              = "stages";
-    static const char *const SC_FEATURES            = "features";
-
-    static const char *const SC_WEEK                = "weakClassifiers";
-    static const char *const SC_INTERNAL            = "internalNodes";
-    static const char *const SC_LEAF                = "leafValues";
-
-    static const char *const SC_OCT_SCALE           = "scale";
-    static const char *const SC_OCT_STAGES          = "stageNum";
-    static const char *const SC_OCT_SHRINKAGE       = "shrinkingFactor";
-
-    static const char *const SC_STAGE_THRESHOLD     = "stageThreshold";
-
-    static const char * const SC_F_CHANNEL          = "channel";
-    static const char * const SC_F_RECT             = "rect";
-
-    // only Ada Boost supported
-    std::string stageTypeStr = (string)root[SC_STAGE_TYPE];
-    CV_Assert(stageTypeStr == SC_BOOST);
-
-    // only HOG-like integral channel features cupported
-    string featureTypeStr = (string)root[SC_FEATURE_TYPE];
-    CV_Assert(featureTypeStr == SC_ICF);
 
-    origObjWidth = (int)root[SC_ORIG_W];
-    CV_Assert(origObjWidth  == ORIG_OBJECT_WIDTH);
+public:
 
-    origObjHeight = (int)root[SC_ORIG_H];
-    CV_Assert(origObjHeight == ORIG_OBJECT_HEIGHT);
-
-    FileNode fn = root[SC_OCTAVES];
-        if (fn.empty()) return false;
-
-    std::vector<Octave>  voctaves;
-    std::vector<float>   vstages;
-    std::vector<Node>    vnodes;
-    std::vector<float>   vleaves;
-    scales.clear();
-
-    FileNodeIterator it = fn.begin(), it_end = fn.end();
-    int feature_offset = 0;
-    ushort octIndex = 0;
-    ushort shrinkage = 1;
-
-    for (; it != it_end; ++it)
-    {
-        FileNode fns = *it;
-        float scale = (float)fns[SC_OCT_SCALE];
-
-        bool isUPOctave = scale >= 1;
-
-        scales.push_back(scale);
-        ushort nstages = saturate_cast<ushort>((int)fns[SC_OCT_STAGES]);
-        ushort2 size;
-        size.x = cvRound(ORIG_OBJECT_WIDTH * scale);
-        size.y = cvRound(ORIG_OBJECT_HEIGHT * scale);
-        shrinkage = saturate_cast<ushort>((int)fns[SC_OCT_SHRINKAGE]);
-
-        Octave octave(octIndex, nstages, shrinkage, size, scale);
-        CV_Assert(octave.stages > 0);
-        voctaves.push_back(octave);
-
-        FileNode ffs = fns[SC_FEATURES];
-        if (ffs.empty()) return false;
-
-        FileNodeIterator ftrs = ffs.begin();
-
-        fns = fns[SC_STAGES];
-        if (fn.empty()) return false;
-
-        // for each stage (~ decision tree with H = 2)
-        FileNodeIterator st = fns.begin(), st_end = fns.end();
-        for (; st != st_end; ++st )
-        {
-            fns = *st;
-            vstages.push_back((float)fns[SC_STAGE_THRESHOLD]);
+    // scales range
+    float minScale;
+    float maxScale;
 
-            fns = fns[SC_WEEK];
-            FileNodeIterator ftr = fns.begin(), ft_end = fns.end();
-            for (; ftr != ft_end; ++ftr)
-            {
-                fns = (*ftr)[SC_INTERNAL];
-                FileNodeIterator inIt = fns.begin(), inIt_end = fns.end();
-                for (; inIt != inIt_end;)
-                {
-                    // int feature = (int)(*(inIt +=2)) + feature_offset;
-                    inIt +=3;
-                    // extract feature, Todo:check it
-                    uint th = saturate_cast<uint>((float)(*(inIt++)));
-                    cv::FileNode ftn = (*ftrs)[SC_F_RECT];
-                    cv::FileNodeIterator r_it = ftn.begin();
-                    uchar4 rect;
-                    rect.x = saturate_cast<uchar>((int)*(r_it++));
-                    rect.y = saturate_cast<uchar>((int)*(r_it++));
-                    rect.z = saturate_cast<uchar>((int)*(r_it++));
-                    rect.w = saturate_cast<uchar>((int)*(r_it++));
-
-                    if (isUPOctave)
-                    {
-                        rect.z -= rect.x;
-                        rect.w -= rect.y;
-                    }
+    int origObjWidth;
+    int origObjHeight;
 
-                    uint channel = saturate_cast<uint>((int)(*ftrs)[SC_F_CHANNEL]);
-                    vnodes.push_back(Node(rect, channel, th));
-                    ++ftrs;
-                }
+    const int shrinkage;
+    int downscales;
 
-                fns = (*ftr)[SC_LEAF];
-                inIt = fns.begin(), inIt_end = fns.end();
-                for (; inIt != inIt_end; ++inIt)
-                    vleaves.push_back((float)(*inIt));
-            }
-        }
+    // preallocated buffer 640x480x10 for hogluv + 640x480 got gray
+    GpuMat plane;
 
-        feature_offset += octave.stages * 3;
-        ++octIndex;
-    }
+    // preallocated buffer for floating point operations
+    GpuMat fplane;
 
-    // upload in gpu memory
-    octaves.upload(cv::Mat(1, voctaves.size() * sizeof(Octave), CV_8UC1, (uchar*)&(voctaves[0]) ));
-    CV_Assert(!octaves.empty());
+    // temporial mat for cvtColor
+    GpuMat luv;
 
-    stages.upload(cv::Mat(vstages).reshape(1,1));
-    CV_Assert(!stages.empty());
+    // 160x120x10
+    GpuMat shrunk;
 
-    nodes.upload(cv::Mat(1, vnodes.size() * sizeof(Node), CV_8UC1, (uchar*)&(vnodes[0]) ));
-    CV_Assert(!nodes.empty());
+    // temporial mat for integrall
+    GpuMat integralBuffer;
 
-    leaves.upload(cv::Mat(vleaves).reshape(1,1));
-    CV_Assert(!leaves.empty());
+    // 161x121x10
+    GpuMat hogluv;
 
-    // compute levels
-    calcLevels(voctaves, FRAME_WIDTH, FRAME_HEIGHT, TOTAL_SCALES);
-    CV_Assert(!levels.empty());
+    GpuMat detCounter;
 
-    invoker = device::icf::CascadeInvoker<device::icf::CascadePolicy>(levels, octaves, stages, nodes, leaves);
+    // Cascade from xml
+    GpuMat octaves;
+    GpuMat stages;
+    GpuMat nodes;
+    GpuMat leaves;
+    GpuMat levels;
 
-    return true;
-}
+    device::icf::CascadeInvoker<device::icf::CascadePolicy> invoker;
 
-namespace {
-    struct CascadeIntrinsics
+    enum { BOOST = 0 };
+    enum
     {
-        static const float lambda = 1.099f, a = 0.89f;
-
-        static float getFor(int channel, float scaling)
-        {
-            CV_Assert(channel < 10);
-
-            if (fabs(scaling - 1.f) < FLT_EPSILON)
-                return 1.f;
-
-            // according to R. Benenson, M. Mathias, R. Timofte and L. Van Gool's and Dallal's papers
-            static const float A[2][2] =
-            {   //channel <= 6, otherwise
-                {        0.89f, 1.f}, // down
-                {        1.00f, 1.f}  // up
-            };
-
-            static const float B[2][2] =
-            {   //channel <= 6,  otherwise
-                { 1.099f / log(2), 2.f}, // down
-                {             0.f, 2.f}  // up
-            };
-
-            float a = A[(int)(scaling >= 1)][(int)(channel > 6)];
-            float b = B[(int)(scaling >= 1)][(int)(channel > 6)];
-
-            // printf("!!! scaling: %f %f %f -> %f\n", scaling, a, b, a * pow(scaling, b));
-            return a * pow(scaling, b);
-        }
+        FRAME_WIDTH        = 640,
+        FRAME_HEIGHT       = 480,
+        TOTAL_SCALES       = 55,
+        ORIG_OBJECT_WIDTH  = 64,
+        ORIG_OBJECT_HEIGHT = 128,
+        HOG_BINS           = 6,
+        LUV_BINS           = 3,
+        HOG_LUV_BINS       = 10
     };
-}
-
-inline void cv::gpu::SoftCascade::Filds::calcLevels(const std::vector<device::icf::Octave>& octs,
-                                                    int frameW, int frameH, int nscales)
-{
-    CV_Assert(nscales > 1);
-    using device::icf::Level;
-
-    std::vector<Level> vlevels;
-    float logFactor = (::log(maxScale) - ::log(minScale)) / (nscales -1);
-
-    float scale = minScale;
-    downscales = 0;
-    for (int sc = 0; sc < nscales; ++sc)
-    {
-        int width  = ::std::max(0.0f, frameW - (origObjWidth  * scale));
-        int height = ::std::max(0.0f, frameH - (origObjHeight * scale));
-
-        float logScale = ::log(scale);
-        int fit = fitOctave(octs, logScale);
-
-        Level level(fit, octs[fit], scale, width, height);
-        level.scaling[0] = CascadeIntrinsics::getFor(0, level.relScale);
-        level.scaling[1] = CascadeIntrinsics::getFor(9, level.relScale);
-
-        if (!width || !height)
-            break;
-        else
-        {
-            vlevels.push_back(level);
-            if (octs[fit].scale < 1) ++downscales;
-        }
-
-        if (::fabs(scale - maxScale) < FLT_EPSILON) break;
-        scale = ::std::min(maxScale, ::expf(::log(scale) + logFactor));
-
-        // std::cout << "level " << sc
-        //           << " octeve "
-        //           << vlevels[sc].octave
-        //           << " relScale "
-        //           << vlevels[sc].relScale
-        //           << " " << vlevels[sc].shrScale
-        //           << " [" << (int)vlevels[sc].objSize.x
-        //           << " " <<  (int)vlevels[sc].objSize.y << "] ["
-        // <<  (int)vlevels[sc].workRect.x << " " <<  (int)vlevels[sc].workRect.y << "]" << std::endl;
-    }
-
-    levels.upload(cv::Mat(1, vlevels.size() * sizeof(Level), CV_8UC1, (uchar*)&(vlevels[0]) ));
-}
+};
 
 cv::gpu::SoftCascade::SoftCascade() : filds(0) {}
 
@@ -513,21 +503,15 @@ cv::gpu::SoftCascade::~SoftCascade()
 
 bool cv::gpu::SoftCascade::load( const string& filename, const float minScale, const float maxScale)
 {
-    if (filds)
-        delete filds;
-    filds = 0;
+    if (filds) delete filds;
 
     cv::FileStorage fs(filename, FileStorage::READ);
     if (!fs.isOpened()) return false;
 
-    filds = new Filds;
-    Filds& flds = *filds;
-    if (!flds.fill(fs.getFirstTopLevelNode(), minScale, maxScale)) return false;
-    return true;
+    filds = Filds::parseCascade(fs.getFirstTopLevelNode(), minScale, maxScale);
+    return filds != 0;
 }
 
-//================================== synchronous version ============================================================//
-
 void cv::gpu::SoftCascade::detectMultiScale(const GpuMat& colored, const GpuMat& rois,
                                 GpuMat& objects, const int /*rejectfactor*/, int specificScale) const
 {
@@ -562,7 +546,7 @@ void cv::gpu::SoftCascade::detectMultiScale(const GpuMat&, const GpuMat&, GpuMat
 
 cv::Size cv::gpu::SoftCascade::getRoiSize() const
 {
-    return cv::Size(Filds::FRAME_WIDTH / 4, Filds::FRAME_HEIGHT / 4);
+    return cv::Size(Filds::FRAME_WIDTH / (*filds).shrinkage, Filds::FRAME_HEIGHT / (*filds).shrinkage);
 }
 
 #endif
\ No newline at end of file