Commit fdda9f5c7bcbc72568f0438b913a2c5c011f2724

Authored by Scott Klum
2 parents 33f7ed28 702b2f03

Merge branch 'temp'

openbr/core/eval.cpp
@@ -842,7 +842,10 @@ static QStringList computeDetectionResults(const QList<ResolvedDetection> &detec @@ -842,7 +842,10 @@ static QStringList computeDetectionResults(const QList<ResolvedDetection> &detec
842 } 842 }
843 } 843 }
844 844
845 - if (discrete) qDebug("Total TP vs. FP: %f to %f", TP, FP); 845 + if (discrete) {
  846 + qDebug("Total TP vs. FP: %f to %f", TP, FP);
  847 + qDebug("Overall Recall (TP vs. possible TP): %f (%f vs. %d)", TP / totalTrueDetections, TP, totalTrueDetections);
  848 + }
846 849
847 const int keep = qMin(points.size(), Max_Points); 850 const int keep = qMin(points.size(), Max_Points);
848 if (keep < 1) qFatal("Insufficient points."); 851 if (keep < 1) qFatal("Insufficient points.");
openbr/plugins/classification/cascade.cpp
@@ -92,6 +92,8 @@ struct Miner @@ -92,6 +92,8 @@ struct Miner
92 * \br_property int numPos The number of positives to feed each stage during training 92 * \br_property int numPos The number of positives to feed each stage during training
93 * \br_property int numNegs The number of negatives to feed each stage during training. A negative sample must have been classified by the previous stages in the cascade as positive to be fed to the next stage during training. 93 * \br_property int numNegs The number of negatives to feed each stage during training. A negative sample must have been classified by the previous stages in the cascade as positive to be fed to the next stage during training.
94 * \br_property float maxFAR A termination parameter. Calculated as (number of passed negatives) / (total number of checked negatives) for a given stage during training. If that number is below the given maxFAR cascade training is terminated early. This can help prevent overfitting. 94 * \br_property float maxFAR A termination parameter. Calculated as (number of passed negatives) / (total number of checked negatives) for a given stage during training. If that number is below the given maxFAR cascade training is terminated early. This can help prevent overfitting.
  95 + * \br_property bool requireAllStages If true, the cascade will train until it has the number of stages specified by numStages even if the FAR at a given is lower than maxFAR.
  96 + * \br_property int maxStage Parameter to limit the stages used at test time. If -1 (default), all numStages stages will be used.
95 * \br_paper Paul Viola, Michael Jones 97 * \br_paper Paul Viola, Michael Jones
96 * Rapid Object Detection using a Boosted Cascade of Simple Features 98 * Rapid Object Detection using a Boosted Cascade of Simple Features
97 * CVPR, 2001 99 * CVPR, 2001
@@ -107,6 +109,7 @@ class CascadeClassifier : public Classifier @@ -107,6 +109,7 @@ class CascadeClassifier : public Classifier
107 Q_PROPERTY(int numNegs READ get_numNegs WRITE set_numNegs RESET reset_numNegs STORED false) 109 Q_PROPERTY(int numNegs READ get_numNegs WRITE set_numNegs RESET reset_numNegs STORED false)
108 Q_PROPERTY(float maxFAR READ get_maxFAR WRITE set_maxFAR RESET reset_maxFAR STORED false) 110 Q_PROPERTY(float maxFAR READ get_maxFAR WRITE set_maxFAR RESET reset_maxFAR STORED false)
109 Q_PROPERTY(bool requireAllStages READ get_requireAllStages WRITE set_requireAllStages RESET reset_requireAllStages STORED false) 111 Q_PROPERTY(bool requireAllStages READ get_requireAllStages WRITE set_requireAllStages RESET reset_requireAllStages STORED false)
  112 + Q_PROPERTY(int maxStage READ get_maxStage WRITE set_maxStage RESET reset_maxStage STORED false)
110 113
111 BR_PROPERTY(QString, stageDescription, "") 114 BR_PROPERTY(QString, stageDescription, "")
112 BR_PROPERTY(int, numStages, 20) 115 BR_PROPERTY(int, numStages, 20)
@@ -114,6 +117,7 @@ class CascadeClassifier : public Classifier @@ -114,6 +117,7 @@ class CascadeClassifier : public Classifier
114 BR_PROPERTY(int, numNegs, 1000) 117 BR_PROPERTY(int, numNegs, 1000)
115 BR_PROPERTY(float, maxFAR, pow(0.5, numStages)) 118 BR_PROPERTY(float, maxFAR, pow(0.5, numStages))
116 BR_PROPERTY(bool, requireAllStages, false) 119 BR_PROPERTY(bool, requireAllStages, false)
  120 + BR_PROPERTY(int, maxStage, -1)
117 121
118 QList<Classifier *> stages; 122 QList<Classifier *> stages;
119 TemplateList posImages, negImages; 123 TemplateList posImages, negImages;
@@ -231,7 +235,11 @@ class CascadeClassifier : public Classifier @@ -231,7 +235,11 @@ class CascadeClassifier : public Classifier
231 float classify(const Template &src, bool process, float *confidence) const 235 float classify(const Template &src, bool process, float *confidence) const
232 { 236 {
233 float stageConf = 0.0f; 237 float stageConf = 0.0f;
234 - foreach (const Classifier *stage, stages) { 238 + const int stopStage = maxStage == -1 ? numStages : maxStage;
  239 + int stageIndex = 0;
  240 + foreach (const Classifier *stage, stages) {
  241 + if (stageIndex == stopStage)
  242 + break;
235 float result = stage->classify(src, process, &stageConf); 243 float result = stage->classify(src, process, &stageConf);
236 if (confidence) 244 if (confidence)
237 *confidence += stageConf; 245 *confidence += stageConf;
openbr/plugins/imgproc/slidingwindow.cpp
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 #include <openbr/core/qtutils.h> 19 #include <openbr/core/qtutils.h>
20 20
21 #include <opencv2/imgproc/imgproc.hpp> 21 #include <opencv2/imgproc/imgproc.hpp>
  22 +#include <opencv2/highgui/highgui.hpp>
22 23
23 using namespace cv; 24 using namespace cv;
24 25
@@ -50,6 +51,7 @@ class SlidingWindowTransform : public MetaTransform @@ -50,6 +51,7 @@ class SlidingWindowTransform : public MetaTransform
50 Q_PROPERTY(float eps READ get_eps WRITE set_eps RESET reset_eps STORED false) 51 Q_PROPERTY(float eps READ get_eps WRITE set_eps RESET reset_eps STORED false)
51 Q_PROPERTY(float minNeighbors READ get_minNeighbors WRITE set_minNeighbors RESET reset_minNeighbors STORED false) 52 Q_PROPERTY(float minNeighbors READ get_minNeighbors WRITE set_minNeighbors RESET reset_minNeighbors STORED false)
52 Q_PROPERTY(bool group READ get_group WRITE set_group RESET reset_group STORED false) 53 Q_PROPERTY(bool group READ get_group WRITE set_group RESET reset_group STORED false)
  54 + Q_PROPERTY(int shrinkingFactor READ get_shrinkingFactor WRITE set_shrinkingFactor RESET reset_shrinkingFactor STORED false)
53 BR_PROPERTY(br::Classifier*, classifier, NULL) 55 BR_PROPERTY(br::Classifier*, classifier, NULL)
54 BR_PROPERTY(int, minSize, 20) 56 BR_PROPERTY(int, minSize, 20)
55 BR_PROPERTY(int, maxSize, -1) 57 BR_PROPERTY(int, maxSize, -1)
@@ -58,6 +60,7 @@ class SlidingWindowTransform : public MetaTransform @@ -58,6 +60,7 @@ class SlidingWindowTransform : public MetaTransform
58 BR_PROPERTY(float, eps, 0.2) 60 BR_PROPERTY(float, eps, 0.2)
59 BR_PROPERTY(int, minNeighbors, 3) 61 BR_PROPERTY(int, minNeighbors, 3)
60 BR_PROPERTY(bool, group, true) 62 BR_PROPERTY(bool, group, true)
  63 + BR_PROPERTY(int, shrinkingFactor, 1)
61 64
62 void train(const TemplateList &data) 65 void train(const TemplateList &data)
63 { 66 {
@@ -100,42 +103,47 @@ class SlidingWindowTransform : public MetaTransform @@ -100,42 +103,47 @@ class SlidingWindowTransform : public MetaTransform
100 QList<float> confidences; 103 QList<float> confidences;
101 104
102 int dx, dy; 105 int dx, dy;
103 - const Size originalWindowSize = classifier->windowSize(&dx, &dy); 106 + const Size classifierSize = classifier->windowSize(&dx, &dy);
104 107
105 for (double factor = 1; ; factor *= scaleFactor) { 108 for (double factor = 1; ; factor *= scaleFactor) {
106 - const Size windowSize(cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor));  
107 - const Size scaledImageSize(cvRound(imageSize.width/factor), cvRound(imageSize.height/factor));  
108 - const Size processingRectSize(scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height); 109 + // TODO: This should support non-square sizes
  110 + // Compute the size of the window in which we will detect faces
  111 + const Size detectionSize(cvRound(minSize*factor),cvRound(minSize*factor));
109 112
110 - if (processingRectSize.width <= 0 || processingRectSize.height <= 0)  
111 - break;  
112 - if (windowSize.width < minSize || windowSize.height < minSize)  
113 - continue; 113 + // Stop if detection size is bigger than the image itself
  114 + if (detectionSize.width > imageSize.width || detectionSize.height > imageSize.height)
  115 + break;
  116 +
  117 + const float widthScale = (float)classifierSize.width/detectionSize.width;
  118 + const float heightScale = (float)classifierSize.height/detectionSize.height;
  119 +
  120 + // Scale the image such that the detection size within the image corresponds to the respresentation size
  121 + const Size scaledImageSize(cvRound(imageSize.width*widthScale), cvRound(imageSize.height*heightScale));
114 122
115 Template rep(t.file); 123 Template rep(t.file);
116 foreach (const Mat &m, t) { 124 foreach (const Mat &m, t) {
117 Mat scaledImage; 125 Mat scaledImage;
118 - resize(m, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR); 126 + resize(m, scaledImage, scaledImageSize, 0, 0, CV_INTER_AREA);
119 rep.append(scaledImage); 127 rep.append(scaledImage);
120 } 128 }
121 rep = classifier->preprocess(rep); 129 rep = classifier->preprocess(rep);
122 - 130 +
123 // Pre-allocate the window to avoid constructing this every iteration 131 // Pre-allocate the window to avoid constructing this every iteration
124 Template window(t.file); 132 Template window(t.file);
125 for (int i=0; i<rep.size(); i++) 133 for (int i=0; i<rep.size(); i++)
126 window.append(Mat()); 134 window.append(Mat());
127 135
128 - const int step = factor > 2.0 ? 1 : 2;  
129 - for (int y = 0; y < processingRectSize.height; y += step) {  
130 - for (int x = 0; x < processingRectSize.width; x += step) { 136 + const int step = factor > 2.0 ? shrinkingFactor : shrinkingFactor*2;
  137 + for (int y = 0; y < scaledImageSize.height-classifierSize.height; y += step) {
  138 + for (int x = 0; x < scaledImageSize.width-classifierSize.width; x += step) {
131 for (int i=0; i<rep.size(); i++) 139 for (int i=0; i<rep.size(); i++)
132 - window[i] = rep[i](Rect(Point(x, y), Size(originalWindowSize.width + dx, originalWindowSize.height + dy))).clone(); 140 + window[i] = rep[i](Rect(Point(x, y), Size(classifierSize.width+dx, classifierSize.height+dy))).clone();
133 141
134 float confidence = 0; 142 float confidence = 0;
135 int result = classifier->classify(window, false, &confidence); 143 int result = classifier->classify(window, false, &confidence);
136 144
137 if (result == 1) { 145 if (result == 1) {
138 - rects.append(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height)); 146 + rects.append(Rect(cvRound(x/widthScale), cvRound(y/heightScale), detectionSize.width, detectionSize.height));
139 confidences.append(confidence); 147 confidences.append(confidence);
140 } 148 }
141 149