Commit e69f6ae399efcec931cc7b217d05b66a881117c0
1 parent
07420612
refactored CascadeTransform to support ROC confidence values
Showing
1 changed file
with
48 additions
and
10 deletions
openbr/plugins/cascade.cpp
| ... | ... | @@ -49,19 +49,20 @@ private: |
| 49 | 49 | } |
| 50 | 50 | }; |
| 51 | 51 | |
| 52 | - | |
| 53 | 52 | /*! |
| 54 | 53 | * \ingroup transforms |
| 55 | 54 | * \brief Wraps OpenCV cascade classifier |
| 56 | 55 | * \author Josh Klontz \cite jklontz |
| 57 | 56 | */ |
| 58 | -class CascadeTransform : public UntrainableTransform | |
| 57 | +class CascadeTransform : public UntrainableMetaTransform | |
| 59 | 58 | { |
| 60 | 59 | Q_OBJECT |
| 61 | 60 | Q_PROPERTY(QString model READ get_model WRITE set_model RESET reset_model STORED false) |
| 62 | 61 | Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false) |
| 62 | + Q_PROPERTY(bool ROCMode READ get_ROCMode WRITE set_ROCMode RESET reset_ROCMode STORED false) | |
| 63 | 63 | BR_PROPERTY(QString, model, "FrontalFace") |
| 64 | 64 | BR_PROPERTY(int, minSize, 64) |
| 65 | + BR_PROPERTY(bool, ROCMode, false) | |
| 65 | 66 | |
| 66 | 67 | Resource<CascadeClassifier> cascadeResource; |
| 67 | 68 | |
| ... | ... | @@ -72,18 +73,55 @@ class CascadeTransform : public UntrainableTransform |
| 72 | 73 | |
| 73 | 74 | void project(const Template &src, Template &dst) const |
| 74 | 75 | { |
| 76 | + TemplateList temp; | |
| 77 | + project(TemplateList() << src, temp); | |
| 78 | + if (!temp.isEmpty()) dst = temp.first(); | |
| 79 | + } | |
| 80 | + | |
| 81 | + void project(const TemplateList &src, TemplateList &dst) const | |
| 82 | + { | |
| 83 | + static const int rejectLevelWeight = 1000.0; | |
| 84 | + static const int stageSumWeight = 1.0; | |
| 85 | + | |
| 75 | 86 | CascadeClassifier *cascade = cascadeResource.acquire(); |
| 76 | - vector<Rect> rects; | |
| 77 | - cascade->detectMultiScale(src, rects, 1.2, 5, src.file.get<bool>("enrollAll", false) ? 0 : CV_HAAR_FIND_BIGGEST_OBJECT, Size(minSize, minSize)); | |
| 87 | + | |
| 88 | + foreach (const Template &t, src) { | |
| 89 | + const bool enrollAll = t.file.getBool("enrollAll"); | |
| 90 | + | |
| 91 | + for (int i=0; i<t.size(); i++) { | |
| 92 | + const Mat &m = t[i]; | |
| 93 | + vector<Rect> rects; | |
| 94 | + vector<int> rejectLevels; | |
| 95 | + vector<double> levelWeights; | |
| 96 | + if (ROCMode) cascade->detectMultiScale(m, rects, rejectLevels, levelWeights, 1.2, 5, (enrollAll ? 0 : CV_HAAR_FIND_BIGGEST_OBJECT) | CV_HAAR_SCALE_IMAGE, Size(minSize, minSize), Size(), true); | |
| 97 | + else cascade->detectMultiScale(m, rects, 1.2, 5, enrollAll ? 0 : CV_HAAR_FIND_BIGGEST_OBJECT, Size(minSize, minSize)); | |
| 98 | + | |
| 99 | + if (!enrollAll && rects.empty()) | |
| 100 | + rects.push_back(Rect(0, 0, m.cols, m.rows)); | |
| 101 | + | |
| 102 | + for (size_t j=0; j<rects.size(); j++) { | |
| 103 | + dst.append(Template(t.file, m)); | |
| 104 | + if (rejectLevels.size() > j) | |
| 105 | + dst.last().file.set("Confidence", rejectLevels[j]*rejectLevelWeight + levelWeights[j]*stageSumWeight); | |
| 106 | + dst.last().file.appendRect(OpenCVUtils::fromRect(rects[j])); | |
| 107 | + } | |
| 108 | + } | |
| 109 | + } | |
| 110 | + | |
| 78 | 111 | cascadeResource.release(cascade); |
| 112 | + } | |
| 79 | 113 | |
| 80 | - if (!src.file.get<bool>("enrollAll", false) && rects.empty()) | |
| 81 | - rects.push_back(Rect(0, 0, src.m().cols, src.m().rows)); | |
| 114 | + // TODO: Remove this code when ready to break binary compatibility | |
| 115 | + void store(QDataStream &stream) const | |
| 116 | + { | |
| 117 | + int size = 1; | |
| 118 | + stream << size; | |
| 119 | + } | |
| 82 | 120 | |
| 83 | - foreach (const Rect &rect, rects) { | |
| 84 | - dst += src; | |
| 85 | - dst.file.appendRect(OpenCVUtils::fromRect(rect)); | |
| 86 | - } | |
| 121 | + void load(QDataStream &stream) | |
| 122 | + { | |
| 123 | + int size; | |
| 124 | + stream >> size; | |
| 87 | 125 | } |
| 88 | 126 | }; |
| 89 | 127 | ... | ... |