Commit 7a2db13ce795e7cca4c993c57d3ed3ca0b46c0df
1 parent
98249fb4
No regression. Steps towards I/O.
Showing
7 changed files
with
89 additions
and
390 deletions
openbr/core/boost.cpp
| ... | ... | @@ -806,38 +806,6 @@ CvDTreeNode* CascadeBoostTree::predict( int sampleIdx ) const |
| 806 | 806 | return node; |
| 807 | 807 | } |
| 808 | 808 | |
| 809 | -<<<<<<< HEAD | |
| 810 | - | |
| 811 | -static void writeRecursive(FileStorage &fs, CvDTreeNode *node, int maxCatCount) | |
| 812 | -{ | |
| 813 | - bool hasChildren = node->left ? true : false; | |
| 814 | - fs << "hasChildren" << hasChildren; | |
| 815 | - | |
| 816 | - if (!hasChildren) // Write the leaf value | |
| 817 | - fs << "value" << node->value; // value of the node. Only relevant for leaf nodes | |
| 818 | - else { // Write the splitting information and then the children | |
| 819 | - if (maxCatCount > 1) { | |
| 820 | - fs << "subset" << "[:"; | |
| 821 | - for (int i = 0; i < ((maxCatCount + 31) / 32); i++) | |
| 822 | - fs << node->split->subset[i]; // subset to split on (categorical features) | |
| 823 | - fs << "]"; | |
| 824 | - } else { | |
| 825 | - fs << "threshold" << node->split->ord.c; // threshold to split on (ordered features) | |
| 826 | - } | |
| 827 | - | |
| 828 | - fs << "feature_idx" << node->split->var_idx; // feature idx of node | |
| 829 | - | |
| 830 | - fs << "left" << "{"; writeRecursive(fs, node->left, maxCatCount); fs << "}"; // write left child | |
| 831 | - fs << "right" << "{"; writeRecursive(fs, node->right, maxCatCount); fs << "}"; // write right child | |
| 832 | - } | |
| 833 | -} | |
| 834 | - | |
| 835 | -void CascadeBoostTree::write(FileStorage &fs) | |
| 836 | -{ | |
| 837 | - fs << "{"; | |
| 838 | - writeRecursive(fs, root, ((CascadeBoostTrainData*)data)->featureEvaluator->getMaxCatCount()); | |
| 839 | - fs << "}"; | |
| 840 | -} | |
| 841 | 809 | /* |
| 842 | 810 | static void readRecursive(const FileNode &fn, CvDTreeNode *node, CvDTreeTrainData *data) |
| 843 | 811 | { |
| ... | ... | @@ -881,8 +849,6 @@ void CascadeBoostTree::read(const FileNode &fn, CvBoost* _ensemble, CvDTreeTrain |
| 881 | 849 | } |
| 882 | 850 | */ |
| 883 | 851 | |
| 884 | -======= | |
| 885 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 886 | 852 | void CascadeBoostTree::split_node_data( CvDTreeNode* node ) |
| 887 | 853 | { |
| 888 | 854 | int n = node->sample_count, nl, nr, scount = data->sample_count; |
| ... | ... | @@ -1138,11 +1104,7 @@ bool CascadeBoost::train( const FeatureEvaluator* _featureEvaluator, |
| 1138 | 1104 | break; |
| 1139 | 1105 | } |
| 1140 | 1106 | |
| 1141 | -<<<<<<< HEAD | |
| 1142 | 1107 | classifiers.append(tree); |
| 1143 | -======= | |
| 1144 | - trees.append(tree); | |
| 1145 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 1146 | 1108 | cvSeqPush( weak, &tree ); |
| 1147 | 1109 | update_weights( tree ); |
| 1148 | 1110 | trim_weights(); |
| ... | ... | @@ -1470,7 +1432,3 @@ bool CascadeBoost::isErrDesired() |
| 1470 | 1432 | |
| 1471 | 1433 | return falseAlarm <= maxFalseAlarm; |
| 1472 | 1434 | } |
| 1473 | -<<<<<<< HEAD | |
| 1474 | - | |
| 1475 | -======= | |
| 1476 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | ... | ... |
openbr/core/boost.h
| ... | ... | @@ -4,43 +4,6 @@ |
| 4 | 4 | #include "ml.h" |
| 5 | 5 | #include <openbr/openbr_plugin.h> |
| 6 | 6 | |
| 7 | -#define CC_CASCADE_FILENAME "cascade.xml" | |
| 8 | -#define CC_PARAMS_FILENAME "params.xml" | |
| 9 | - | |
| 10 | -#define CC_CASCADE_PARAMS "cascadeParams" | |
| 11 | -#define CC_STAGE_TYPE "stageType" | |
| 12 | -#define CC_FEATURE_TYPE "featureType" | |
| 13 | -#define CC_HEIGHT "height" | |
| 14 | -#define CC_WIDTH "width" | |
| 15 | - | |
| 16 | -#define CC_STAGE_NUM "stageNum" | |
| 17 | -#define CC_STAGES "stages" | |
| 18 | -#define CC_STAGE_PARAMS "stageParams" | |
| 19 | - | |
| 20 | -#define CC_BOOST "BOOST" | |
| 21 | -#define CC_BOOST_TYPE "boostType" | |
| 22 | -#define CC_DISCRETE_BOOST "DAB" | |
| 23 | -#define CC_REAL_BOOST "RAB" | |
| 24 | -#define CC_LOGIT_BOOST "LB" | |
| 25 | -#define CC_GENTLE_BOOST "GAB" | |
| 26 | -#define CC_MINHITRATE "minHitRate" | |
| 27 | -#define CC_MAXFALSEALARM "maxFalseAlarm" | |
| 28 | -#define CC_TRIM_RATE "weightTrimRate" | |
| 29 | -#define CC_MAX_DEPTH "maxDeptrh" | |
| 30 | -#define CC_WEAK_COUNT "maxWeakCount" | |
| 31 | -#define CC_STAGE_THRESHOLD "stageThreshold" | |
| 32 | -#define CC_WEAK_CLASSIFIERS "weakClassifiers" | |
| 33 | -#define CC_INTERNAL_NODES "internalNodes" | |
| 34 | -#define CC_LEAF_VALUES "leafValues" | |
| 35 | - | |
| 36 | -#define CC_FEATURES "features" | |
| 37 | -#define CC_FEATURE_PARAMS "featureParams" | |
| 38 | -#define CC_MAX_CAT_COUNT "maxCatCount" | |
| 39 | -#define CC_FEATURE_SIZE "featSize" | |
| 40 | - | |
| 41 | -#define CC_LBP "LBP" | |
| 42 | -#define CC_RECT "rect" | |
| 43 | - | |
| 44 | 7 | #ifdef _WIN32 |
| 45 | 8 | #define TIME( arg ) (((double) clock()) / CLOCKS_PER_SEC) |
| 46 | 9 | #else |
| ... | ... | @@ -125,22 +88,14 @@ public: |
| 125 | 88 | virtual float predict( int sampleIdx, bool returnSum = false ) const; |
| 126 | 89 | |
| 127 | 90 | float getThreshold() const { return threshold; } |
| 128 | -<<<<<<< HEAD | |
| 129 | - QList<CvBoostTree*> getClassifiers() const { return classifiers; } | |
| 130 | -======= | |
| 131 | - const QList<CvBoostTree*> getTrees() const { return trees; } | |
| 132 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 91 | + QList<CvBoostTree *> getClassifers() const { return classifiers; } | |
| 133 | 92 | |
| 134 | 93 | protected: |
| 135 | 94 | virtual bool set_params(const CvBoostParams& _params); |
| 136 | 95 | virtual void update_weights(CvBoostTree* tree); |
| 137 | 96 | virtual bool isErrDesired(); |
| 138 | 97 | |
| 139 | -<<<<<<< HEAD | |
| 140 | - QList<CvBoostTree*> classifiers; | |
| 141 | -======= | |
| 142 | - QList<CvBoostTree*> trees; | |
| 143 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 98 | + QList<CvBoostTree *> classifiers; | |
| 144 | 99 | |
| 145 | 100 | float threshold; |
| 146 | 101 | float minHitRate, maxFalseAlarm; | ... | ... |
openbr/core/cascade.cpp
| ... | ... | @@ -124,9 +124,10 @@ void br::groupRectangles(vector<Rect>& rectList, vector<int>& rejectLevels, vect |
| 124 | 124 | static void loadRecursive(const FileNode &fn, _CascadeClassifier::Node *node, int maxCatCount) |
| 125 | 125 | { |
| 126 | 126 | bool hasChildren = (int)fn["hasChildren"]; |
| 127 | - | |
| 128 | - if (hasChildren) { | |
| 129 | - if (maxCatCount > 1) { | |
| 127 | + if (!hasChildren) | |
| 128 | + node->value = (float)fn["value"]; | |
| 129 | + else { | |
| 130 | + if (maxCatCount > 0) { | |
| 130 | 131 | FileNode subset_fn = fn["subset"]; |
| 131 | 132 | for (FileNodeIterator subset_it = subset_fn.begin(); subset_it != subset_fn.end(); ++subset_it) |
| 132 | 133 | node->subset.append((int)*subset_it); |
| ... | ... | @@ -134,14 +135,11 @@ static void loadRecursive(const FileNode &fn, _CascadeClassifier::Node *node, in |
| 134 | 135 | node->threshold = (float)fn["threshold"]; |
| 135 | 136 | } |
| 136 | 137 | |
| 137 | - node->featureIdx = (int)fn["feature_idx"]; | |
| 138 | + node->featureIdx = (int)fn["featureIdx"]; | |
| 138 | 139 | |
| 139 | - node->left = new _CascadeClassifier::Node; | |
| 140 | + node->left = new _CascadeClassifier::Node; node->right = new _CascadeClassifier::Node; | |
| 140 | 141 | loadRecursive(fn["left"], node->left, maxCatCount); |
| 141 | - node->right = new _CascadeClassifier::Node; | |
| 142 | 142 | loadRecursive(fn["right"], node->right, maxCatCount); |
| 143 | - } else { | |
| 144 | - node->value = (float)fn["value"]; | |
| 145 | 143 | } |
| 146 | 144 | } |
| 147 | 145 | |
| ... | ... | @@ -159,7 +157,6 @@ bool _CascadeClassifier::load(const string& filename) |
| 159 | 157 | |
| 160 | 158 | // load stages |
| 161 | 159 | FileNode stages_fn = root["stages"]; |
| 162 | - | |
| 163 | 160 | if( stages_fn.empty() ) |
| 164 | 161 | return false; |
| 165 | 162 | |
| ... | ... | @@ -170,7 +167,6 @@ bool _CascadeClassifier::load(const string& filename) |
| 170 | 167 | stage.threshold = (float)stage_fn["stageThreshold"] - THRESHOLD_EPS; |
| 171 | 168 | |
| 172 | 169 | FileNode nodes_fn = stage_fn["weakClassifiers"]; |
| 173 | - | |
| 174 | 170 | if(nodes_fn.empty()) |
| 175 | 171 | return false; |
| 176 | 172 | ... | ... |
openbr/plugins/classification/boostedforest.cpp
| 1 | 1 | #include <openbr/plugins/openbr_internal.h> |
| 2 | 2 | #include <openbr/core/boost.h> |
| 3 | 3 | |
| 4 | +#define THRESHOLD_EPS 1e-5 | |
| 5 | + | |
| 4 | 6 | using namespace cv; |
| 5 | 7 | |
| 6 | 8 | namespace br |
| ... | ... | @@ -8,63 +10,33 @@ namespace br |
| 8 | 10 | |
| 9 | 11 | struct Node |
| 10 | 12 | { |
| 11 | - Node() : left(NULL), right(NULL) {} | |
| 12 | - | |
| 13 | -<<<<<<< HEAD | |
| 14 | - float value; | |
| 13 | + float value; // for leaf nodes | |
| 15 | 14 | |
| 16 | - float threshold; // For ordered features | |
| 17 | - QList<int> subset; // For categorical features | |
| 15 | + float threshold; // for ordered features | |
| 16 | + QList<int> subset; // for categorical features | |
| 18 | 17 | int featureIdx; |
| 19 | 18 | |
| 20 | -======= | |
| 21 | - int featureIdx; | |
| 22 | - float threshold; // for ordered features only | |
| 23 | - QList<int> subset; // for categorical features only | |
| 24 | - float value; // for leaf nodes only | |
| 25 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 26 | - Node *left; | |
| 27 | - Node *right; | |
| 19 | + Node *left, *right; | |
| 28 | 20 | }; |
| 29 | 21 | |
| 30 | -<<<<<<< HEAD | |
| 31 | 22 | static void buildTreeRecursive(Node *node, const CvDTreeNode *cv_node, int maxCatCount) |
| 32 | 23 | { |
| 33 | - if (!cv_node->left) // Write the leaf value | |
| 34 | - node->value = cv_node->value; // value of the node. Only relevant for leaf nodes | |
| 35 | - else { // Write the splitting information and then the children | |
| 36 | - if (maxCatCount > 1) | |
| 37 | - for (int i = 0; i < ((maxCatCount + 31) / 32); i++) | |
| 38 | - node->subset.append(cv_node->split->subset[i]); // subset to split on (categorical features) | |
| 24 | + if (!cv_node->left) { | |
| 25 | + node->value = cv_node->value; | |
| 26 | + | |
| 27 | + node->left = node->right = NULL; | |
| 28 | + } else { | |
| 29 | + if (maxCatCount > 0) | |
| 30 | + for (int i = 0; i < (maxCatCount + 31)/32; i++) | |
| 31 | + node->subset.append(cv_node->split->subset[i]); | |
| 39 | 32 | else |
| 40 | - node->threshold = cv_node->split->ord.c; // threshold to split on (ordered features) | |
| 33 | + node->threshold = cv_node->split->ord.c; | |
| 41 | 34 | |
| 42 | - node->featureIdx = cv_node->split->var_idx; // feature idx of node | |
| 35 | + node->featureIdx = cv_node->split->var_idx; | |
| 43 | 36 | |
| 44 | - node->left = new Node; | |
| 37 | + node->left = new Node; node->right = new Node; | |
| 45 | 38 | buildTreeRecursive(node->left, cv_node->left, maxCatCount); |
| 46 | - node->right = new Node; | |
| 47 | 39 | buildTreeRecursive(node->right, cv_node->right, maxCatCount); |
| 48 | -======= | |
| 49 | -static void buildTreeRecursive(Node *node, const CvDTreeNode *tree_node, int maxCatCount) | |
| 50 | -{ | |
| 51 | - if (tree_node->left) { | |
| 52 | - if (maxCatCount > 1) { | |
| 53 | - for (int i = 0; i < (maxCatCount + 31)/32; i++) | |
| 54 | - node->subset.append(tree_node->split->subset[i]); | |
| 55 | - } else { | |
| 56 | - node->threshold = tree_node->split->ord.c; | |
| 57 | - } | |
| 58 | - | |
| 59 | - node->featureIdx = tree_node->split->var_idx; | |
| 60 | - | |
| 61 | - node->left = new Node; | |
| 62 | - buildTreeRecursive(node->left, tree_node->left, maxCatCount); | |
| 63 | - node->right = new Node; | |
| 64 | - buildTreeRecursive(node->right, tree_node->right, maxCatCount); | |
| 65 | - } else { | |
| 66 | - node->value = tree_node->value; | |
| 67 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 68 | 40 | } |
| 69 | 41 | } |
| 70 | 42 | |
| ... | ... | @@ -73,58 +45,25 @@ static void writeRecursive(FileStorage &fs, const Node *node, int maxCatCount) |
| 73 | 45 | bool hasChildren = node->left ? true : false; |
| 74 | 46 | fs << "hasChildren" << hasChildren; |
| 75 | 47 | |
| 76 | - if (!hasChildren) // Write the leaf value | |
| 77 | -<<<<<<< HEAD | |
| 78 | - fs << "value" << node->value; // value of the node. Only relevant for leaf nodes | |
| 79 | - else { // Write the splitting information and then the children | |
| 80 | - if (maxCatCount > 1) { | |
| 81 | - fs << "subset" << "[:"; | |
| 82 | -======= | |
| 83 | - fs << "value" << node->value; // value of the node. | |
| 84 | - else { // Write the splitting information and then the children | |
| 85 | - if (maxCatCount > 1) { | |
| 48 | + if (!hasChildren) | |
| 49 | + fs << "value" << node->value; | |
| 50 | + else { | |
| 51 | + if (maxCatCount > 0) { | |
| 86 | 52 | fs << "subset" << "["; |
| 87 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 88 | - for (int i = 0; i < ((maxCatCount + 31) / 32); i++) | |
| 89 | - fs << node->subset[i]; // subset to split on (categorical features) | |
| 53 | + for (int i = 0; i < (maxCatCount + 31)/32; i++) | |
| 54 | + fs << node->subset[i]; | |
| 90 | 55 | fs << "]"; |
| 91 | 56 | } else { |
| 92 | - fs << "threshold" << node->threshold; // threshold to split on (ordered features) | |
| 93 | - } | |
| 94 | - | |
| 95 | - fs << "feature_idx" << node->featureIdx; // feature idx of node | |
| 96 | - | |
| 97 | - fs << "left" << "{"; writeRecursive(fs, node->left, maxCatCount); fs << "}"; // write left child | |
| 98 | - fs << "right" << "{"; writeRecursive(fs, node->right, maxCatCount); fs << "}"; // write right child | |
| 99 | - } | |
| 100 | -} | |
| 101 | - | |
| 102 | -<<<<<<< HEAD | |
| 103 | -======= | |
| 104 | -static void readRecursive(const FileNode &fn, Node *node, int maxCatCount) | |
| 105 | -{ | |
| 106 | - bool hasChildren = (int)fn["hasChildren"]; | |
| 107 | - if (!hasChildren) { | |
| 108 | - node->value = (float)fn["value"]; | |
| 109 | - } else { | |
| 110 | - if (maxCatCount > 1) { | |
| 111 | - FileNode subset_fn = fn["subset"]; | |
| 112 | - for (FileNodeIterator subset_it = subset_fn.begin(); subset_it != subset_fn.end(); ++subset_it) | |
| 113 | - node->subset.append((int)*subset_it); | |
| 114 | - } else { | |
| 115 | - node->threshold = (float)fn["threshold"]; | |
| 57 | + fs << "threshold" << node->threshold; | |
| 116 | 58 | } |
| 117 | 59 | |
| 118 | - node->featureIdx = (int)fn["feature_idx"]; | |
| 60 | + fs << "featureIdx" << node->featureIdx; | |
| 119 | 61 | |
| 120 | - node->left = new Node; | |
| 121 | - readRecursive(fn["left"], node->left, maxCatCount); | |
| 122 | - node->right = new Node; | |
| 123 | - readRecursive(fn["right"], node->right, maxCatCount); | |
| 62 | + fs << "left" << "{"; writeRecursive(fs, node->left, maxCatCount); fs << "}"; | |
| 63 | + fs << "right" << "{"; writeRecursive(fs, node->right, maxCatCount); fs << "}"; | |
| 124 | 64 | } |
| 125 | 65 | } |
| 126 | 66 | |
| 127 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 128 | 67 | class BoostedForestClassifier : public Classifier |
| 129 | 68 | { |
| 130 | 69 | Q_OBJECT |
| ... | ... | @@ -143,7 +82,7 @@ class BoostedForestClassifier : public Classifier |
| 143 | 82 | BR_PROPERTY(int, maxDepth, 1) |
| 144 | 83 | BR_PROPERTY(int, maxWeakCount, 100) |
| 145 | 84 | |
| 146 | - QList<Node*> weakClassifiers; | |
| 85 | + QList<Node*> classifiers; | |
| 147 | 86 | float threshold; |
| 148 | 87 | |
| 149 | 88 | void train(const QList<Mat> &images, const QList<float> &labels) |
| ... | ... | @@ -157,65 +96,39 @@ class BoostedForestClassifier : public Classifier |
| 157 | 96 | featureEvaluator.setImage(images[i], labels[i], i); |
| 158 | 97 | |
| 159 | 98 | CascadeBoost boost; |
| 160 | - boost.train(&featureEvaluator, images.size(), 2048, 2048, params); | |
| 161 | -<<<<<<< HEAD | |
| 162 | - | |
| 163 | - threshold = boost.getThreshold(); | |
| 164 | - | |
| 165 | - foreach (const CvBoostTree *tree, boost.getClassifiers()) { | |
| 166 | -======= | |
| 99 | + boost.train(&featureEvaluator, images.size(), 1024, 1024, params); | |
| 167 | 100 | |
| 168 | - // Convert into simpler, cleaner cascade after training | |
| 169 | 101 | threshold = boost.getThreshold(); |
| 170 | 102 | |
| 171 | - foreach (const CvBoostTree *tree, boost.getTrees()) { | |
| 172 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 103 | + foreach (const CvBoostTree *classifier, boost.getClassifers()) { | |
| 173 | 104 | Node *root = new Node; |
| 174 | - buildTreeRecursive(root, tree->get_root(), representation->maxCatCount()); | |
| 175 | - weakClassifiers.append(root); | |
| 105 | + buildTreeRecursive(root, classifier->get_root(), representation->maxCatCount()); | |
| 106 | + classifiers.append(root); | |
| 176 | 107 | } |
| 177 | 108 | } |
| 178 | 109 | |
| 179 | - float classify(const Mat &image) const | |
| 110 | + float classify(const Mat &_image) const | |
| 180 | 111 | { |
| 181 | -<<<<<<< HEAD | |
| 182 | - float sum = 0; | |
| 183 | - foreach (const Node *root, weakClassifiers) { | |
| 184 | - const Node *node = root; | |
| 185 | - | |
| 186 | - while (node->left) { | |
| 187 | - if (representation->maxCatCount() > 1) { | |
| 188 | - int c = (int)representation->evaluate(image, node->featureIdx); | |
| 189 | - node = (node->subset[c >> 5] & (1 << (c & 31))) ? node->left : node->right; | |
| 190 | - } else { | |
| 191 | - float val = representation->evaluate(image, node->featureIdx); | |
| 192 | -======= | |
| 193 | - Mat pp; | |
| 194 | - representation->preprocess(image, pp); | |
| 112 | + Mat image; | |
| 113 | + representation->preprocess(_image, image); | |
| 195 | 114 | |
| 196 | 115 | float sum = 0; |
| 116 | + for (int i = 0; i < classifiers.size(); i++) { | |
| 117 | + Node *node = classifiers[i]; | |
| 197 | 118 | |
| 198 | - foreach (const Node *node, weakClassifiers) { | |
| 199 | 119 | while (node->left) { |
| 200 | 120 | if (representation->maxCatCount() > 1) { |
| 201 | - int c = (int)representation->evaluate(pp, node->featureIdx); | |
| 202 | - node = (node->subset[c >> 5] & (1 << (c & 31))) ? node->left : node->right; | |
| 121 | + int c = (int)representation->evaluate(image, node->featureIdx); | |
| 122 | + node = (2*((node->subset[c >> 5] & (1 << (c & 31))) == 0) - 1) < 0 ? node->left : node->right; | |
| 203 | 123 | } else { |
| 204 | - double val = representation->evaluate(pp, node->featureIdx); | |
| 205 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 206 | - node = val < node->threshold ? node->left : node->right; | |
| 124 | + double val = representation->evaluate(image, node->featureIdx); | |
| 125 | + node = val <= node->threshold ? node->left : node->right; | |
| 207 | 126 | } |
| 208 | 127 | } |
| 209 | 128 | sum += node->value; |
| 210 | 129 | } |
| 211 | -<<<<<<< HEAD | |
| 212 | - return sum < threshold - FLT_EPSILON ? 0.0 : 1.0; | |
| 213 | -======= | |
| 214 | - | |
| 215 | - if (sum < threshold) | |
| 216 | - return 0.0f; //-std::abs(sum); | |
| 217 | - return 1.0f; //std::abs(sum); | |
| 218 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 130 | + | |
| 131 | + return sum < threshold - THRESHOLD_EPS ? 0.0f : 1.0f; | |
| 219 | 132 | } |
| 220 | 133 | |
| 221 | 134 | int numFeatures() const |
| ... | ... | @@ -235,38 +148,15 @@ class BoostedForestClassifier : public Classifier |
| 235 | 148 | |
| 236 | 149 | void write(FileStorage &fs) const |
| 237 | 150 | { |
| 238 | -<<<<<<< HEAD | |
| 239 | - fs << "weakCount" << weakClassifiers.size(); | |
| 240 | -======= | |
| 241 | - fs << "numWeak" << weakClassifiers.size(); | |
| 242 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 243 | 151 | fs << "stageThreshold" << threshold; |
| 152 | + fs << "weakSize" << classifiers.size(); | |
| 244 | 153 | fs << "weakClassifiers" << "["; |
| 245 | - foreach (const Node *root, weakClassifiers) { | |
| 154 | + foreach (const Node *root, classifiers) { | |
| 246 | 155 | fs << "{"; |
| 247 | 156 | writeRecursive(fs, root, representation->maxCatCount()); |
| 248 | 157 | fs << "}"; |
| 249 | 158 | } |
| 250 | 159 | fs << "]"; |
| 251 | -<<<<<<< HEAD | |
| 252 | -======= | |
| 253 | - } | |
| 254 | - | |
| 255 | - void read(const FileNode &node) | |
| 256 | - { | |
| 257 | - weakClassifiers.reserve((int)node["numWeak"]); | |
| 258 | - threshold = (float)node["stageThreshold"]; | |
| 259 | - | |
| 260 | - FileNode weaks_fn = node["weakClassifiers"]; | |
| 261 | - for (FileNodeIterator weaks_it = weaks_fn.begin(); weaks_it != weaks_fn.end(); ++weaks_it) { | |
| 262 | - FileNode weak_fn = *weaks_it; | |
| 263 | - | |
| 264 | - Node *root = new Node; | |
| 265 | - readRecursive(weak_fn, root, representation->maxCatCount()); | |
| 266 | - | |
| 267 | - weakClassifiers.append(root); | |
| 268 | - } | |
| 269 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 270 | 160 | } |
| 271 | 161 | }; |
| 272 | 162 | ... | ... |
openbr/plugins/classification/cascade.cpp
| 1 | 1 | #include <opencv2/imgproc/imgproc.hpp> |
| 2 | 2 | |
| 3 | 3 | #include <openbr/plugins/openbr_internal.h> |
| 4 | -#include <openbr/core/boost.h> | |
| 5 | 4 | |
| 6 | 5 | using namespace cv; |
| 7 | 6 | |
| ... | ... | @@ -112,14 +111,12 @@ class CascadeClassifier : public Classifier |
| 112 | 111 | Q_PROPERTY(int numPos READ get_numPos WRITE set_numPos RESET reset_numPos STORED false) |
| 113 | 112 | Q_PROPERTY(int numNegs READ get_numNegs WRITE set_numNegs RESET reset_numNegs STORED false) |
| 114 | 113 | Q_PROPERTY(float maxFAR READ get_maxFAR WRITE set_maxFAR RESET reset_maxFAR STORED false) |
| 115 | - Q_PROPERTY(bool ROCMode READ get_ROCMode WRITE set_ROCMode RESET reset_ROCMode STORED false) | |
| 116 | 114 | |
| 117 | 115 | BR_PROPERTY(QString, stageDescription, "") |
| 118 | 116 | BR_PROPERTY(int, numStages, 20) |
| 119 | 117 | BR_PROPERTY(int, numPos, 1000) |
| 120 | 118 | BR_PROPERTY(int, numNegs, 1000) |
| 121 | 119 | BR_PROPERTY(float, maxFAR, pow(0.5, numStages)) |
| 122 | - BR_PROPERTY(bool, ROCMode, false) | |
| 123 | 120 | |
| 124 | 121 | QList<Classifier *> stages; |
| 125 | 122 | |
| ... | ... | @@ -158,21 +155,9 @@ class CascadeClassifier : public Classifier |
| 158 | 155 | float classify(const Mat &image) const |
| 159 | 156 | { |
| 160 | 157 | foreach (const Classifier *stage, stages) |
| 161 | - if (stage->classify(image) == 0) | |
| 158 | + if (stage->classify(image) == 0.0f) | |
| 162 | 159 | return 0.0f; |
| 163 | 160 | return 1.0f; |
| 164 | - | |
| 165 | - /*if (stages.size() == 0) // special case for empty cascade | |
| 166 | - return 1.0f; | |
| 167 | - | |
| 168 | - float result = 0.0f; | |
| 169 | - for (int stageIdx = 0; stageIdx < stages.size(); stageIdx++) { | |
| 170 | - result = stages[stageIdx]->classify(image); | |
| 171 | - | |
| 172 | - if (result < 0) | |
| 173 | - return stageIdx > (stages.size() - 4) ? stageIdx * result : 0.0f; | |
| 174 | - } | |
| 175 | - return std::abs(stages.size() * result);*/ | |
| 176 | 161 | } |
| 177 | 162 | |
| 178 | 163 | int numFeatures() const |
| ... | ... | @@ -192,13 +177,7 @@ class CascadeClassifier : public Classifier |
| 192 | 177 | |
| 193 | 178 | void write(FileStorage &fs) const |
| 194 | 179 | { |
| 195 | -<<<<<<< HEAD | |
| 196 | - fs << "stageCount" << stages.size(); | |
| 197 | - | |
| 198 | 180 | fs << "stages" << "["; |
| 199 | -======= | |
| 200 | - fs << CC_STAGES << "["; | |
| 201 | ->>>>>>> 4fab7f69ddc82d6ba40a73fc6233e3cc9871473e | |
| 202 | 181 | foreach (const Classifier *stage, stages) { |
| 203 | 182 | fs << "{"; |
| 204 | 183 | stage->write(fs); |
| ... | ... | @@ -217,7 +196,7 @@ private: |
| 217 | 196 | if (!imgHandler.getPos(pos)) |
| 218 | 197 | qFatal("Cannot get another positive sample!"); |
| 219 | 198 | |
| 220 | - if (classify(pos) > 0.0f) { | |
| 199 | + if (classify(pos) == 1.0f) { | |
| 221 | 200 | printf("POS current samples: %d\r", images.size()); |
| 222 | 201 | images.append(pos); |
| 223 | 202 | labels.append(1.0f); |
| ... | ... | @@ -233,7 +212,7 @@ private: |
| 233 | 212 | if (!imgHandler.getNeg(neg)) |
| 234 | 213 | qFatal("Cannot get another negative sample!"); |
| 235 | 214 | |
| 236 | - if (classify(neg) > 0.0f) { | |
| 215 | + if (classify(neg) == 1.0f) { | |
| 237 | 216 | printf("NEG current samples: %d\r", images.size() - posCount); |
| 238 | 217 | images.append(neg); |
| 239 | 218 | labels.append(0.0f); | ... | ... |
openbr/plugins/imgproc/slidingwindow.cpp
| ... | ... | @@ -21,8 +21,6 @@ |
| 21 | 21 | #include <openbr/core/qtutils.h> |
| 22 | 22 | |
| 23 | 23 | #include <opencv2/highgui/highgui.hpp> |
| 24 | -#include <opencv2/imgproc/imgproc.hpp> | |
| 25 | -#include <opencv2/objdetect/objdetect.hpp> | |
| 26 | 24 | |
| 27 | 25 | using namespace cv; |
| 28 | 26 | |
| ... | ... | @@ -41,23 +39,11 @@ class SlidingWindowTransform : public Transform |
| 41 | 39 | Q_OBJECT |
| 42 | 40 | |
| 43 | 41 | Q_PROPERTY(br::Classifier *classifier READ get_classifier WRITE set_classifier RESET reset_classifier STORED false) |
| 44 | - Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false) | |
| 45 | - Q_PROPERTY(int maxSize READ get_maxSize WRITE set_maxSize RESET reset_maxSize STORED false) | |
| 46 | - Q_PROPERTY(float scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false) | |
| 47 | - Q_PROPERTY(int minNeighbors READ get_minNeighbors WRITE set_minNeighbors RESET reset_minNeighbors STORED false) | |
| 48 | - Q_PROPERTY(float eps READ get_eps WRITE set_eps RESET reset_eps STORED false) | |
| 49 | - | |
| 50 | 42 | Q_PROPERTY(QString cascadeDir READ get_cascadeDir WRITE set_cascadeDir RESET reset_cascadeDir STORED false) |
| 51 | 43 | Q_PROPERTY(QString vecFile READ get_vecFile WRITE set_vecFile RESET reset_vecFile STORED false) |
| 52 | 44 | Q_PROPERTY(QString negFile READ get_negFile WRITE set_negFile RESET reset_negFile STORED false) |
| 53 | 45 | |
| 54 | 46 | BR_PROPERTY(br::Classifier *, classifier, NULL) |
| 55 | - BR_PROPERTY(int, minSize, 24) | |
| 56 | - BR_PROPERTY(int, maxSize, -1) | |
| 57 | - BR_PROPERTY(float, scaleFactor, 1.2) | |
| 58 | - BR_PROPERTY(int, minNeighbors, 5) | |
| 59 | - BR_PROPERTY(float, eps, 0.2) | |
| 60 | - | |
| 61 | 47 | BR_PROPERTY(QString, cascadeDir, "") |
| 62 | 48 | BR_PROPERTY(QString, vecFile, "vec.vec") |
| 63 | 49 | BR_PROPERTY(QString, negFile, "neg.txt") |
| ... | ... | @@ -135,11 +121,6 @@ class SlidingWindowTransform : public Transform |
| 135 | 121 | return negs; |
| 136 | 122 | } |
| 137 | 123 | |
| 138 | - void init() | |
| 139 | - { | |
| 140 | - cascadeDir = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + cascadeDir; | |
| 141 | - } | |
| 142 | - | |
| 143 | 124 | void train(const TemplateList &_data) |
| 144 | 125 | { |
| 145 | 126 | (void)_data; |
| ... | ... | @@ -159,109 +140,34 @@ class SlidingWindowTransform : public Transform |
| 159 | 140 | } |
| 160 | 141 | |
| 161 | 142 | classifier->train(images, labels); |
| 143 | + } | |
| 144 | + | |
| 145 | + void project(const Template &src, Template &dst) const | |
| 146 | + { | |
| 147 | + (void)src; (void)dst; | |
| 148 | + } | |
| 149 | + | |
| 150 | + void load(QDataStream &stream) | |
| 151 | + { | |
| 152 | + (void) stream; | |
| 153 | + return; | |
| 154 | + } | |
| 162 | 155 | |
| 163 | - // save the cascade | |
| 164 | - std::string filename = cascadeDir.toStdString() + "/cascade.xml"; | |
| 165 | - FileStorage fs(filename, FileStorage::WRITE ); | |
| 156 | + void store(QDataStream &stream) const | |
| 157 | + { | |
| 158 | + (void) stream; | |
| 166 | 159 | |
| 160 | + QString filename = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + cascadeDir + "/cascade.xml"; | |
| 161 | + FileStorage fs(filename.toStdString(), FileStorage::WRITE); | |
| 167 | 162 | if ( !fs.isOpened() ) |
| 168 | 163 | return; |
| 169 | 164 | |
| 170 | - fs << FileStorage::getDefaultObjectName(filename) << "{"; | |
| 165 | + fs << FileStorage::getDefaultObjectName(filename.toStdString()) << "{"; | |
| 171 | 166 | |
| 172 | 167 | classifier->write(fs); |
| 173 | 168 | |
| 174 | 169 | fs << "}"; |
| 175 | 170 | } |
| 176 | - | |
| 177 | - void project(const Template &src, Template &dst) const | |
| 178 | - { | |
| 179 | - TemplateList temp; | |
| 180 | - project(TemplateList() << src, temp); | |
| 181 | - if (!temp.isEmpty()) dst = temp.first(); | |
| 182 | - } | |
| 183 | - | |
| 184 | - void project(const TemplateList &src, TemplateList &dst) const | |
| 185 | - { | |
| 186 | - foreach (const Template &t, src) { | |
| 187 | - const bool enrollAll = t.file.getBool("enrollAll"); | |
| 188 | - | |
| 189 | - // Mirror the behavior of ExpandTransform in the special case | |
| 190 | - // of an empty template. | |
| 191 | - if (t.empty() && !enrollAll) { | |
| 192 | - dst.append(t); | |
| 193 | - continue; | |
| 194 | - } | |
| 195 | - | |
| 196 | - for (int i = 0; i < t.size(); i++) { | |
| 197 | - Mat image; | |
| 198 | - OpenCVUtils::cvtUChar(t[i], image); | |
| 199 | - | |
| 200 | - std::vector<Rect> rects; | |
| 201 | - std::vector<int> rejectLevels; | |
| 202 | - std::vector<double> levelWeights; | |
| 203 | - | |
| 204 | - Size minObjectSize(minSize, minSize); | |
| 205 | - Size maxObjectSize(maxSize, maxSize); | |
| 206 | - if (maxObjectSize.height == 0 || maxObjectSize.width == 0) | |
| 207 | - maxObjectSize = image.size(); | |
| 208 | - | |
| 209 | - Mat imageBuffer(image.rows + 1, image.cols + 1, CV_8U); | |
| 210 | - | |
| 211 | - for (double factor = 1; ; factor *= scaleFactor) { | |
| 212 | - Size originalWindowSize = classifier->windowSize(); | |
| 213 | - | |
| 214 | - Size windowSize(cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); | |
| 215 | - Size scaledImageSize(cvRound(image.cols/factor ), cvRound(image.rows/factor)); | |
| 216 | - Size processingRectSize(scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height); | |
| 217 | - | |
| 218 | - if (processingRectSize.width <= 0 || processingRectSize.height <= 0) | |
| 219 | - break; | |
| 220 | - if (windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height) | |
| 221 | - break; | |
| 222 | - if (windowSize.width < minObjectSize.width || windowSize.height < minObjectSize.height) | |
| 223 | - continue; | |
| 224 | - | |
| 225 | - Mat scaledImage(scaledImageSize, CV_8U, imageBuffer.data); | |
| 226 | - resize(image, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR); | |
| 227 | - | |
| 228 | - int yStep = factor > 2. ? 1 : 2; | |
| 229 | - for (int y = 0; y < processingRectSize.height; y += yStep) { | |
| 230 | - for (int x = 0; x < processingRectSize.width; x += yStep) { | |
| 231 | - Mat window = scaledImage(Rect(Point(x, y), classifier->windowSize())).clone(); | |
| 232 | - | |
| 233 | - float result = classifier->classify(window); | |
| 234 | - | |
| 235 | - if (result > 0) { | |
| 236 | - rects.push_back(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height)); | |
| 237 | - rejectLevels.push_back(1); | |
| 238 | - levelWeights.push_back(result); | |
| 239 | - } | |
| 240 | - if (result == 0) | |
| 241 | - x += yStep; | |
| 242 | - } | |
| 243 | - } | |
| 244 | - } | |
| 245 | - | |
| 246 | - groupRectangles(rects, rejectLevels, levelWeights, minNeighbors, eps); | |
| 247 | - | |
| 248 | - if (!enrollAll && rects.empty()) | |
| 249 | - rects.push_back(Rect(0, 0, image.cols, image.rows)); | |
| 250 | - | |
| 251 | - for (size_t j = 0; j < rects.size(); j++) { | |
| 252 | - Template u(t.file, image); | |
| 253 | - if (rejectLevels.size() > j) | |
| 254 | - u.file.set("Confidence", rejectLevels[j]*levelWeights[j]); | |
| 255 | - else | |
| 256 | - u.file.set("Confidence", 1); | |
| 257 | - const QRectF rect = OpenCVUtils::fromRect(rects[j]); | |
| 258 | - u.file.appendRect(rect); | |
| 259 | - u.file.set("Face", rect); | |
| 260 | - dst.append(u); | |
| 261 | - } | |
| 262 | - } | |
| 263 | - } | |
| 264 | - } | |
| 265 | 171 | }; |
| 266 | 172 | |
| 267 | 173 | BR_REGISTER(Transform, SlidingWindowTransform) | ... | ... |
openbr/plugins/representation/mblbp.cpp
| ... | ... | @@ -58,6 +58,7 @@ class MBLBPRepresentation : public Representation |
| 58 | 58 | return result; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | + void write(FileStorage &fs, const Mat &featureMap); | |
| 61 | 62 | int numFeatures() const { return features.size(); } |
| 62 | 63 | Size preWindowSize() const { return Size(winWidth, winHeight); } |
| 63 | 64 | Size postWindowSize() const { return Size(winWidth + 1, winHeight + 1); } |
| ... | ... | @@ -78,6 +79,20 @@ class MBLBPRepresentation : public Representation |
| 78 | 79 | |
| 79 | 80 | BR_REGISTER(Representation, MBLBPRepresentation) |
| 80 | 81 | |
| 82 | +void MBLBPRepresentation::write(FileStorage &fs, const Mat &featureMap) | |
| 83 | +{ | |
| 84 | + fs << "features" << "["; | |
| 85 | + const Mat_<int>& featureMap_ = (const Mat_<int>&)featureMap; | |
| 86 | + for ( int fi = 0; fi < featureMap.cols; fi++ ) | |
| 87 | + if ( featureMap_(0, fi) >= 0 ) | |
| 88 | + { | |
| 89 | + fs << "{"; | |
| 90 | + features[fi].write( fs ); | |
| 91 | + fs << "}"; | |
| 92 | + } | |
| 93 | + fs << "]"; | |
| 94 | +} | |
| 95 | + | |
| 81 | 96 | MBLBPRepresentation::Feature::Feature( int offset, int x, int y, int _blockWidth, int _blockHeight ) |
| 82 | 97 | { |
| 83 | 98 | Rect tr = rect = cvRect(x, y, _blockWidth, _blockHeight); | ... | ... |