compute scales pyramid
authormarina.kolpakova <marina.kolpakova@itseez.com>
Tue, 4 Sep 2012 15:08:52 +0000 (19:08 +0400)
committermarina.kolpakova <marina.kolpakova@itseez.com>
Tue, 6 Nov 2012 23:19:04 +0000 (03:19 +0400)
modules/objdetect/src/softcascade.cpp

index dae352c..065fb0d 100644 (file)
@@ -75,27 +75,93 @@ namespace {
         {printf("   stage: %f %f\n",threshold, weight);}
     };
 
+    // according to R. Benenson, M. Mathias, R. Timofte and L. Van Gool paper
+    struct CascadeIntrinsics
+    {
+        static const float lambda = 1.099f, a = 0.89f;
+        static const float intrinsics[10][4];
+
+        static float getFor(int channel, float scaling)
+        {
+            CV_Assert(channel < 10);
+
+            if ((scaling - 1.f) < FLT_EPSILON)
+                return 1.f;
+
+            int ud = (int)(scaling < 1.f);
+            return intrinsics[channel][(ud << 1)] * pow(scaling, intrinsics[channel][(ud << 1) + 1]);
+        }
+
+    };
+
+    const float CascadeIntrinsics::intrinsics[10][4] =
+        {   //da, db, ua, ub
+            // hog-like orientation bins
+            {a, lambda / log(2), 1, 2},
+            {a, lambda / log(2), 1, 2},
+            {a, lambda / log(2), 1, 2},
+            {a, lambda / log(2), 1, 2},
+            {a, lambda / log(2), 1, 2},
+            {a, lambda / log(2), 1, 2},
+            // gradient magnitude
+            {a, lambda / log(2), 1, 2},
+            // luv color channels
+            {1, 2,      1, 2},
+            {1, 2,      1, 2},
+            {1, 2,      1, 2}
+        };
+
     static const char *SC_F_THRESHOLD      = "threshold";
     static const char *SC_F_DIRECTION      = "direction";
-    static const char *SC_F_CHANNEL        = "chennel";
+    static const char *SC_F_CHANNEL        = "channel";
     static const char *SC_F_RECT           = "rect";
 
     struct Feature
     {
         float threshold;
         int direction;
-        int chennel;
+        int channel;
         cv::Rect rect;
 
         Feature() {}
         Feature(const cv::FileNode& fn)
         : threshold((float)fn[SC_F_THRESHOLD]), direction((int)fn[SC_F_DIRECTION]),
-          chennel((int)fn[SC_F_CHANNEL])
+          channel((int)fn[SC_F_CHANNEL])
         {
             cv::FileNode rn = fn[SC_F_RECT];
             cv::FileNodeIterator r_it = rn.begin();
             rect = cv::Rect(*(r_it++), *(r_it++), *(r_it++), *(r_it++));
-            printf("       feature: %f %d %d [%d %d %d %d]\n",threshold, direction, chennel, rect.x, rect.y, rect.width, rect.height);}
+            printf("       feature: %f %d %d [%d %d %d %d]\n",threshold, direction, channel, rect.x, rect.y, rect.width, rect.height);}
+
+        Feature rescale(float relScale)
+        {
+            Feature res(*this);
+            res.rect = cv::Rect (cvRound(rect.x * relScale), cvRound(rect.y * relScale),
+                                 cvRound(rect.width * relScale), cvRound(rect.height * relScale));
+            res.threshold = threshold * CascadeIntrinsics::getFor(channel, relScale);
+            return res;
+        }
+    };
+
+    struct Level
+    {
+        int index;
+        float factor;
+        float logFactor;
+        int width;
+        int height;
+        float octave;
+        cv::Size objSize;
+
+        Level(int i,float f, float lf, int w, int h): index(i), factor(f), logFactor(lf), width(w), height(h), octave(0.f) {}
+
+        void assign(float o, int detW, int detH)
+        {
+            octave = o;
+            objSize = cv::Size(cv::saturate_cast<int>(detW * o), cv::saturate_cast<int>(detH * o));
+        }
+
+        float relScale() {return (factor / octave); }
     };
 }
 
@@ -112,6 +178,43 @@ struct cv::SoftCascade::Filds
     std::vector<Octave>  octaves;
     std::vector<Stage>   stages;
     std::vector<Feature> features;
+    std::vector<Level>   levels;
+
+    // compute levels of full pyramid
+    void calcLevels(int frameW, int frameH, int scales)
+    {
+        CV_Assert(scales > 1);
+        levels.clear();
+        float logFactor = (log(maxScale) - log(minScale)) / (scales -1);
+
+        float scale = minScale;
+        for (int sc = 0; sc < scales; ++sc)
+        {
+            Level level(sc, scale, log(scale) + logFactor,
+                std::max(0.0f, frameW - (origObjWidth * scale)), std::max(0.0f, frameH - (origObjHeight * scale)));
+            if (!level.width || !level.height)
+                break;
+            else
+                levels.push_back(level);
+
+            if (fabs(scale - maxScale) < FLT_EPSILON) break;
+            scale = std::min(maxScale, expf(log(scale) + logFactor));
+        }
+
+        for (std::vector<Level>::iterator level = levels.begin(); level < levels.end(); ++level)
+        {
+            float minAbsLog = FLT_MAX;
+            for (std::vector<Octave>::iterator oct = octaves.begin(); oct < octaves.end(); ++oct)
+            {
+                const Octave& octave =*oct;
+                float logOctave = log(octave.scale);
+                float logAbsScale = fabs((*level).logFactor - logOctave);
+
+                if(logAbsScale < minAbsLog)
+                    (*level).assign(octave.scale, ORIG_OBJECT_WIDTH, ORIG_OBJECT_HEIGHT);
+            }
+        }
+    }
 
     bool fill(const FileNode &root, const float mins, const float maxs)
     {
@@ -193,110 +296,6 @@ struct cv::SoftCascade::Filds
     }
 };
 
-// namespace {
-
-// struct Cascade {
-//     int logOctave;
-//     float octave;
-//     cv::Size objSize;
-// };
-
-// struct Level {
-//     int index;
-//     float factor;
-//     float logFactor;
-//     int width;
-//     int height;
-//     float octave;
-//     cv::Size objSize;
-
-//     Level(int i,float f, float lf, int w, int h) : index(i), factor(f), logFactor(lf), width(w), height(h), octave(0.f) {}
-
-//     void assign(float o, int detW, int detH)
-//     {
-//         octave = o;
-//         objSize = cv::Size(cv::saturate_cast<int>(detW * o), cv::saturate_cast<int>(detH * o));
-//     }
-
-//     float relScale() {return (factor / octave); }
-// };
-//     // compute levels of full pyramid
-//     void pyrLevels(int frameW, int frameH, int detW, int detH, int scales, float minScale, float maxScale, std::vector<Level> levels)
-//     {
-//         CV_Assert(scales > 1);
-//         levels.clear();
-//         float logFactor = (log(maxScale) - log(minScale)) / (scales -1);
-
-//         float scale = minScale;
-//         for (int sc = 0; sc < scales; ++sc)
-//         {
-//             Level level(sc, scale, log(scale) + logFactor, std::max(0.0f, frameW - (detW * scale)), std::max(0.0f, frameH - (detH * scale)));
-//             if (!level.width || !level.height)
-//                 break;
-//             else
-//                 levels.push_back(level);
-
-//             if (fabs(scale - maxScale) < FLT_EPSILON) break;
-//             scale = std::min(maxScale, expf(log(scale) + logFactor));
-//         }
-
-//     }
-
-//     // according to R. Benenson, M. Mathias, R. Timofte and L. Van Gool paper
-//     struct CascadeIntrinsics {
-//         static const float lambda = 1.099f, a = 0.89f;
-//         static const float intrinsics[10][4];
-
-//         static float getFor(int chennel, float scaling)
-//         {
-//             CV_Assert(chennel < 10);
-
-//             if ((scaling - 1.f) < FLT_EPSILON)
-//                 return 1.f;
-
-//             int ud = (int)(scaling < 1.f);
-//             return intrinsics[chennel][(ud << 1)] * pow(scaling, intrinsics[chennel][(ud << 1) + 1]);
-//         }
-
-//     };
-
-//     const float CascadeIntrinsics::intrinsics[10][4] =
-//         {   //da, db, ua, ub
-//             // hog-like orientation bins
-//             {a, lambda / log(2), 1, 2},
-//             {a, lambda / log(2), 1, 2},
-//             {a, lambda / log(2), 1, 2},
-//             {a, lambda / log(2), 1, 2},
-//             {a, lambda / log(2), 1, 2},
-//             {a, lambda / log(2), 1, 2},
-//             // gradient magnitude
-//             {a, lambda / log(2), 1, 2},
-//             // luv -color chennels
-//             {1, 2,      1, 2},
-//             {1, 2,      1, 2},
-//             {1, 2,      1, 2}
-//         };
-
-//     struct Feature
-//     {
-//         cv::Rect rect;
-//         int channel;
-//         float threshold;
-
-//         Feature(int x, int y, int w, int h, int c, float t) : rect(cv::Rect(x, y, w, h)), channel(c), threshold(t) {}
-//         Feature(cv::Rect r, int c, float t) : rect(r), channel(c), threshold(t) {}
-
-//         Feature rescale(float relScale)
-//         {
-//             cv::Rect r(cvRound(rect.x * relScale), cvRound(rect.y * relScale), cvRound(rect.width * relScale), cvRound(rect.height * relScale));
-//             return Feature( r, channel, threshold * CascadeIntrinsics::getFor(channel, relScale));
-//         }
-//     };
-// }
-
-
-
-
 cv::SoftCascade::SoftCascade() : filds(0) {}
 
 cv::SoftCascade::SoftCascade( const string& filename, const float minScale, const float maxScale)
@@ -318,38 +317,9 @@ bool cv::SoftCascade::load( const string& filename, const float minScale, const
     if (!fs.isOpened()) return false;
 
     filds = new Filds;
-    if (!(*filds).fill(fs.getFirstTopLevelNode(), minScale, maxScale)) return false;
-
-    // ////////////////
-    // // temp fixture
-    // Filds& flds = *filds;
-    // flds.octaves.push_back(0.5f);
-    // flds.octaves.push_back(1.0f);
-    // flds.octaves.push_back(2.0f);
-    // flds.octaves.push_back(4.0f);
-    // flds.octaves.push_back(8.0f);
-
-    // // scales calculations
-    // std::vector<Level> levels;
-
-    // pyrLevels(FRAME_WIDTH, FRAME_HEIGHT, ORIG_OBJECT_WIDTH, ORIG_OBJECT_HEIGHT, TOTAL_SCALES, minScale, maxScale, levels);
-
-    // for (std::vector<Level>::iterator level = levels.begin(); level < levels.end(); ++level)
-    // {
-    //     float minAbsLog = FLT_MAX;
-    //     for (std::vector<float>::iterator oct = flds.octaves.begin(); oct < flds.octaves.end(); ++oct)
-    //     {
-    //         float logOctave = log(*oct);
-    //         float logAbsScale = fabs((*level).logFactor - logOctave);
-
-    //         if(logAbsScale < minAbsLog)
-    //             (*level).assign(*oct, ORIG_OBJECT_WIDTH, ORIG_OBJECT_HEIGHT);
-
-    //     }
-    // }
-
-    // load cascade from xml
-    // read(const FileNode &root)
+    Filds& flds = *filds;
+    if (!flds.fill(fs.getFirstTopLevelNode(), minScale, maxScale)) return false;
+    // flds.calcLevels(FRAME_WIDTH, FRAME_HEIGHT, TOTAL_SCALES);
 
     return true;
 }