Commit 81f98a0a858a060220dc40dfd7d3e1326b46ff2f

Authored by Jordan Cheney
1 parent 9355e316

Finished reorg. Comments and fixes to follow

Showing 309 changed files with 10084 additions and 9140 deletions

Too many changes.

To preserve performance only 100 of 309 files are displayed.

openbr/plugins/classification/adaboost.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +using namespace cv;
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Wraps OpenCV's Ada Boost framework
  12 + * \author Scott Klum \cite sklum
  13 + * \brief http://docs.opencv.org/modules/ml/doc/boosting.html
  14 + */
  15 +class AdaBoostTransform : public Transform
  16 +{
  17 + Q_OBJECT
  18 + Q_ENUMS(Type)
  19 + Q_ENUMS(SplitCriteria)
  20 +
  21 + Q_PROPERTY(Type type READ get_type WRITE set_type RESET reset_type STORED false)
  22 + Q_PROPERTY(SplitCriteria splitCriteria READ get_splitCriteria WRITE set_splitCriteria RESET reset_splitCriteria STORED false)
  23 + Q_PROPERTY(int weakCount READ get_weakCount WRITE set_weakCount RESET reset_weakCount STORED false)
  24 + Q_PROPERTY(float trimRate READ get_trimRate WRITE set_trimRate RESET reset_trimRate STORED false)
  25 + Q_PROPERTY(int folds READ get_folds WRITE set_folds RESET reset_folds STORED false)
  26 + Q_PROPERTY(int maxDepth READ get_maxDepth WRITE set_maxDepth RESET reset_maxDepth STORED false)
  27 + Q_PROPERTY(bool returnConfidence READ get_returnConfidence WRITE set_returnConfidence RESET reset_returnConfidence STORED false)
  28 + Q_PROPERTY(bool overwriteMat READ get_overwriteMat WRITE set_overwriteMat RESET reset_overwriteMat STORED false)
  29 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  30 + Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)
  31 +
  32 +public:
  33 + enum Type { Discrete = CvBoost::DISCRETE,
  34 + Real = CvBoost::REAL,
  35 + Logit = CvBoost::LOGIT,
  36 + Gentle = CvBoost::GENTLE};
  37 +
  38 + enum SplitCriteria { Default = CvBoost::DEFAULT,
  39 + Gini = CvBoost::GINI,
  40 + Misclass = CvBoost::MISCLASS,
  41 + Sqerr = CvBoost::SQERR};
  42 +
  43 +private:
  44 + BR_PROPERTY(Type, type, Real)
  45 + BR_PROPERTY(SplitCriteria, splitCriteria, Default)
  46 + BR_PROPERTY(int, weakCount, 100)
  47 + BR_PROPERTY(float, trimRate, .95)
  48 + BR_PROPERTY(int, folds, 0)
  49 + BR_PROPERTY(int, maxDepth, 1)
  50 + BR_PROPERTY(bool, returnConfidence, true)
  51 + BR_PROPERTY(bool, overwriteMat, true)
  52 + BR_PROPERTY(QString, inputVariable, "Label")
  53 + BR_PROPERTY(QString, outputVariable, "")
  54 +
  55 + CvBoost boost;
  56 +
  57 + void train(const TemplateList &data)
  58 + {
  59 + Mat samples = OpenCVUtils::toMat(data.data());
  60 + Mat labels = OpenCVUtils::toMat(File::get<float>(data, inputVariable));
  61 +
  62 + Mat types = Mat(samples.cols + 1, 1, CV_8U);
  63 + types.setTo(Scalar(CV_VAR_NUMERICAL));
  64 + types.at<char>(samples.cols, 0) = CV_VAR_CATEGORICAL;
  65 +
  66 + CvBoostParams params;
  67 + params.boost_type = type;
  68 + params.split_criteria = splitCriteria;
  69 + params.weak_count = weakCount;
  70 + params.weight_trim_rate = trimRate;
  71 + params.cv_folds = folds;
  72 + params.max_depth = maxDepth;
  73 +
  74 + boost.train( samples, CV_ROW_SAMPLE, labels, Mat(), Mat(), types, Mat(),
  75 + params);
  76 + }
  77 +
  78 + void project(const Template &src, Template &dst) const
  79 + {
  80 + dst = src;
  81 + float response;
  82 + if (returnConfidence) {
  83 + response = boost.predict(src.m().reshape(1,1),Mat(),Range::all(),false,true)/weakCount;
  84 + } else {
  85 + response = boost.predict(src.m().reshape(1,1));
  86 + }
  87 +
  88 + if (overwriteMat) {
  89 + dst.m() = Mat(1, 1, CV_32F);
  90 + dst.m().at<float>(0, 0) = response;
  91 + } else {
  92 + dst.file.set(outputVariable, response);
  93 + }
  94 + }
  95 +
  96 + void load(QDataStream &stream)
  97 + {
  98 + OpenCVUtils::loadModel(boost,stream);
  99 + }
  100 +
  101 + void store(QDataStream &stream) const
  102 + {
  103 + OpenCVUtils::storeModel(boost,stream);
  104 + }
  105 +
  106 +
  107 + void init()
  108 + {
  109 + if (outputVariable.isEmpty())
  110 + outputVariable = inputVariable;
  111 + }
  112 +};
  113 +
  114 +BR_REGISTER(Transform, AdaBoostTransform)
  115 +
  116 +} // namespace br
  117 +
  118 +#include "classification/adaboost.moc"
openbr/plugins/classification/ebif.cpp
@@ -128,4 +128,4 @@ BR_REGISTER(Transform, EBIFTransform) @@ -128,4 +128,4 @@ BR_REGISTER(Transform, EBIFTransform)
128 128
129 } // namespace br 129 } // namespace br
130 130
131 -#include "ebif.moc" 131 +#include "classification/ebif.moc"
openbr/plugins/tree.cpp renamed to openbr/plugins/classification/forest.cpp
1 -#include "openbr_internal.h"  
2 -#include "openbr/core/opencvutils.h" 1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
3 3
4 -using namespace std;  
5 using namespace cv; 4 using namespace cv;
6 5
7 namespace br 6 namespace br
@@ -250,113 +249,6 @@ class ForestInductionTransform : public ForestTransform @@ -250,113 +249,6 @@ class ForestInductionTransform : public ForestTransform
250 249
251 BR_REGISTER(Transform, ForestInductionTransform) 250 BR_REGISTER(Transform, ForestInductionTransform)
252 251
253 -/*!  
254 - * \ingroup transforms  
255 - * \brief Wraps OpenCV's Ada Boost framework  
256 - * \author Scott Klum \cite sklum  
257 - * \brief http://docs.opencv.org/modules/ml/doc/boosting.html  
258 - */  
259 -class AdaBoostTransform : public Transform  
260 -{  
261 - Q_OBJECT  
262 - Q_ENUMS(Type)  
263 - Q_ENUMS(SplitCriteria)  
264 -  
265 - Q_PROPERTY(Type type READ get_type WRITE set_type RESET reset_type STORED false)  
266 - Q_PROPERTY(SplitCriteria splitCriteria READ get_splitCriteria WRITE set_splitCriteria RESET reset_splitCriteria STORED false)  
267 - Q_PROPERTY(int weakCount READ get_weakCount WRITE set_weakCount RESET reset_weakCount STORED false)  
268 - Q_PROPERTY(float trimRate READ get_trimRate WRITE set_trimRate RESET reset_trimRate STORED false)  
269 - Q_PROPERTY(int folds READ get_folds WRITE set_folds RESET reset_folds STORED false)  
270 - Q_PROPERTY(int maxDepth READ get_maxDepth WRITE set_maxDepth RESET reset_maxDepth STORED false)  
271 - Q_PROPERTY(bool returnConfidence READ get_returnConfidence WRITE set_returnConfidence RESET reset_returnConfidence STORED false)  
272 - Q_PROPERTY(bool overwriteMat READ get_overwriteMat WRITE set_overwriteMat RESET reset_overwriteMat STORED false)  
273 - Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)  
274 - Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)  
275 -  
276 -public:  
277 - enum Type { Discrete = CvBoost::DISCRETE,  
278 - Real = CvBoost::REAL,  
279 - Logit = CvBoost::LOGIT,  
280 - Gentle = CvBoost::GENTLE};  
281 -  
282 - enum SplitCriteria { Default = CvBoost::DEFAULT,  
283 - Gini = CvBoost::GINI,  
284 - Misclass = CvBoost::MISCLASS,  
285 - Sqerr = CvBoost::SQERR};  
286 -  
287 -private:  
288 - BR_PROPERTY(Type, type, Real)  
289 - BR_PROPERTY(SplitCriteria, splitCriteria, Default)  
290 - BR_PROPERTY(int, weakCount, 100)  
291 - BR_PROPERTY(float, trimRate, .95)  
292 - BR_PROPERTY(int, folds, 0)  
293 - BR_PROPERTY(int, maxDepth, 1)  
294 - BR_PROPERTY(bool, returnConfidence, true)  
295 - BR_PROPERTY(bool, overwriteMat, true)  
296 - BR_PROPERTY(QString, inputVariable, "Label")  
297 - BR_PROPERTY(QString, outputVariable, "")  
298 -  
299 - CvBoost boost;  
300 -  
301 - void train(const TemplateList &data)  
302 - {  
303 - Mat samples = OpenCVUtils::toMat(data.data());  
304 - Mat labels = OpenCVUtils::toMat(File::get<float>(data, inputVariable));  
305 -  
306 - Mat types = Mat(samples.cols + 1, 1, CV_8U);  
307 - types.setTo(Scalar(CV_VAR_NUMERICAL));  
308 - types.at<char>(samples.cols, 0) = CV_VAR_CATEGORICAL;  
309 -  
310 - CvBoostParams params;  
311 - params.boost_type = type;  
312 - params.split_criteria = splitCriteria;  
313 - params.weak_count = weakCount;  
314 - params.weight_trim_rate = trimRate;  
315 - params.cv_folds = folds;  
316 - params.max_depth = maxDepth;  
317 -  
318 - boost.train( samples, CV_ROW_SAMPLE, labels, Mat(), Mat(), types, Mat(),  
319 - params);  
320 - }  
321 -  
322 - void project(const Template &src, Template &dst) const  
323 - {  
324 - dst = src;  
325 - float response;  
326 - if (returnConfidence) {  
327 - response = boost.predict(src.m().reshape(1,1),Mat(),Range::all(),false,true)/weakCount;  
328 - } else {  
329 - response = boost.predict(src.m().reshape(1,1));  
330 - }  
331 -  
332 - if (overwriteMat) {  
333 - dst.m() = Mat(1, 1, CV_32F);  
334 - dst.m().at<float>(0, 0) = response;  
335 - } else {  
336 - dst.file.set(outputVariable, response);  
337 - }  
338 - }  
339 -  
340 - void load(QDataStream &stream)  
341 - {  
342 - OpenCVUtils::loadModel(boost,stream);  
343 - }  
344 -  
345 - void store(QDataStream &stream) const  
346 - {  
347 - OpenCVUtils::storeModel(boost,stream);  
348 - }  
349 -  
350 -  
351 - void init()  
352 - {  
353 - if (outputVariable.isEmpty())  
354 - outputVariable = inputVariable;  
355 - }  
356 -};  
357 -  
358 -BR_REGISTER(Transform, AdaBoostTransform)  
359 -  
360 } // namespace br 252 } // namespace br
361 253
362 -#include "tree.moc" 254 +#include "classification/forest.moc"
openbr/plugins/ipc2013.cpp renamed to openbr/plugins/classification/ipc2013.cpp
1 -#include "openbr_internal.h"  
2 #include <pxcaccelerator.h> 1 #include <pxcaccelerator.h>
3 #include <pxcface.h> 2 #include <pxcface.h>
4 #include <pxcimage.h> 3 #include <pxcimage.h>
5 #include <pxcsession.h> 4 #include <pxcsession.h>
6 5
  6 +#include <openbr/plugins/openbr_internal.h>
  7 +
7 using namespace br; 8 using namespace br;
8 9
9 static PXCSession *pxcSession = NULL; 10 static PXCSession *pxcSession = NULL;
openbr/plugins/eigen3.cpp renamed to openbr/plugins/classification/lda.cpp
@@ -16,11 +16,11 @@ @@ -16,11 +16,11 @@
16 16
17 #include <Eigen/Dense> 17 #include <Eigen/Dense>
18 18
19 -#include "openbr_internal.h" 19 +#include <openbr/plugins/openbr_internal.h>
20 20
21 -#include "openbr/core/common.h"  
22 -#include "openbr/core/eigenutils.h"  
23 -#include "openbr/core/opencvutils.h" 21 +#include <openbr/core/common.h>
  22 +#include <openbr/core/eigenutils.h>
  23 +#include <openbr/core/opencvutils.h>
24 24
25 namespace br 25 namespace br
26 { 26 {
@@ -654,4 +654,4 @@ BR_REGISTER(Transform, SparseLDATransform) @@ -654,4 +654,4 @@ BR_REGISTER(Transform, SparseLDATransform)
654 654
655 } // namespace br 655 } // namespace br
656 656
657 -#include "eigen3.moc" 657 +#include "classification/lda.moc"
openbr/plugins/liblinear.cpp renamed to openbr/plugins/classification/liblinear.cpp
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 #include <opencv2/core/core.hpp> 2 #include <opencv2/core/core.hpp>
3 #include <opencv2/ml/ml.hpp> 3 #include <opencv2/ml/ml.hpp>
4 4
5 -#include "openbr_internal.h"  
6 -#include "openbr/core/opencvutils.h" 5 +#include <openbr/plugins/openbr_internal.h>
  6 +#include <openbr/core/opencvutils.h>
7 7
8 #include <linear.h> 8 #include <linear.h>
9 9
openbr/plugins/nn.cpp renamed to openbr/plugins/classification/mlp.cpp
1 #include <opencv2/ml/ml.hpp> 1 #include <opencv2/ml/ml.hpp>
2 2
3 -#include "openbr_internal.h"  
4 -#include "openbr/core/qtutils.h"  
5 -#include "openbr/core/opencvutils.h"  
6 -#include "openbr/core/eigenutils.h"  
7 -#include <QString>  
8 -#include <QTemporaryFile>  
9 -  
10 -using namespace std; 3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/opencvutils.h>
  5 +
11 using namespace cv; 6 using namespace cv;
12 7
13 namespace br 8 namespace br
14 { 9 {
15 10
16 -static void storeMLP(const CvANN_MLP &mlp, QDataStream &stream)  
17 -{  
18 - // Create local file  
19 - QTemporaryFile tempFile;  
20 - tempFile.open();  
21 - tempFile.close();  
22 -  
23 - // Save MLP to local file  
24 - mlp.save(qPrintable(tempFile.fileName()));  
25 -  
26 - // Copy local file contents to stream  
27 - tempFile.open();  
28 - QByteArray data = tempFile.readAll();  
29 - tempFile.close();  
30 - stream << data;  
31 -}  
32 -  
33 -static void loadMLP(CvANN_MLP &mlp, QDataStream &stream)  
34 -{  
35 - // Copy local file contents from stream  
36 - QByteArray data;  
37 - stream >> data;  
38 -  
39 - // Create local file  
40 - QTemporaryFile tempFile(QDir::tempPath()+"/MLP");  
41 - tempFile.open();  
42 - tempFile.write(data);  
43 - tempFile.close();  
44 -  
45 - // Load MLP from local file  
46 - mlp.load(qPrintable(tempFile.fileName()));  
47 -}  
48 -  
49 /*! 11 /*!
50 * \ingroup transforms 12 * \ingroup transforms
51 * \brief Wraps OpenCV's multi-layer perceptron framework 13 * \brief Wraps OpenCV's multi-layer perceptron framework
@@ -124,12 +86,12 @@ private: @@ -124,12 +86,12 @@ private:
124 86
125 void load(QDataStream &stream) 87 void load(QDataStream &stream)
126 { 88 {
127 - loadMLP(mlp,stream); 89 + OpenCVUtils::loadModel(mlp, stream);
128 } 90 }
129 91
130 void store(QDataStream &stream) const 92 void store(QDataStream &stream) const
131 { 93 {
132 - storeMLP(mlp,stream); 94 + OpenCVUtils::storeModel(mlp, stream);
133 } 95 }
134 }; 96 };
135 97
@@ -137,4 +99,4 @@ BR_REGISTER(Transform, MLPTransform) @@ -137,4 +99,4 @@ BR_REGISTER(Transform, MLPTransform)
137 99
138 } // namespace br 100 } // namespace br
139 101
140 -#include "nn.moc" 102 +#include "classification/mlp.moc"
openbr/plugins/nt4.cpp renamed to openbr/plugins/classification/nt4.cpp
@@ -457,4 +457,4 @@ class NT4Compare : public Distance @@ -457,4 +457,4 @@ class NT4Compare : public Distance
457 457
458 BR_REGISTER(Distance, NT4Compare) 458 BR_REGISTER(Distance, NT4Compare)
459 459
460 -#include "nt4.moc" 460 +#include "classification/nt4.moc"
openbr/plugins/pp4.cpp renamed to openbr/plugins/classification/pp4.cpp
openbr/plugins/pp5.cpp renamed to openbr/plugins/classification/pp5.cpp
@@ -593,4 +593,4 @@ class PP5GalleryTransform: public UntrainableMetaTransform @@ -593,4 +593,4 @@ class PP5GalleryTransform: public UntrainableMetaTransform
593 593
594 BR_REGISTER(Transform, PP5GalleryTransform) 594 BR_REGISTER(Transform, PP5GalleryTransform)
595 595
596 -#include "plugins/pp5.moc" 596 +#include "classification/pp5.moc"
openbr/plugins/svm.cpp renamed to openbr/plugins/classification/svm.cpp
@@ -18,8 +18,8 @@ @@ -18,8 +18,8 @@
18 #include <opencv2/core/core.hpp> 18 #include <opencv2/core/core.hpp>
19 #include <opencv2/ml/ml.hpp> 19 #include <opencv2/ml/ml.hpp>
20 20
21 -#include "openbr_internal.h"  
22 -#include "openbr/core/opencvutils.h" 21 +#include <openbr/plugins/openbr_internal.h>
  22 +#include <openbr/core/opencvutils.h>
23 23
24 using namespace cv; 24 using namespace cv;
25 25
@@ -261,4 +261,4 @@ BR_REGISTER(Distance, SVMDistance) @@ -261,4 +261,4 @@ BR_REGISTER(Distance, SVMDistance)
261 261
262 } // namespace br 262 } // namespace br
263 263
264 -#include "svm.moc" 264 +#include "classification/svm.moc"
openbr/plugins/classification/turk.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Convenience class for training turk attribute regressors
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class TurkClassifierTransform : public Transform
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key STORED false)
  15 + Q_PROPERTY(QStringList values READ get_values WRITE set_values RESET reset_values STORED false)
  16 + Q_PROPERTY(bool isMeta READ get_isMeta WRITE set_isMeta RESET reset_isMeta STORED false)
  17 + BR_PROPERTY(QString, key, QString())
  18 + BR_PROPERTY(QStringList, values, QStringList())
  19 + BR_PROPERTY(bool, isMeta, false)
  20 +
  21 + Transform *child;
  22 +
  23 + void init()
  24 + {
  25 + QStringList classifiers;
  26 + foreach (const QString &value, values)
  27 + classifiers.append(QString("(SVM(RBF,EPS_SVR,returnDFVal=true,inputVariable=%1,outputVariable=predicted_%1)%2)").arg(key + "_" + value, isMeta ? QString("+Average+SaveMat(predicted_%1)").arg(value) : QString()));
  28 + child = Transform::make(classifiers.join("/") + (classifiers.size() > 1 ? "+Cat" : ""));
  29 + }
  30 +
  31 + void train(const QList<TemplateList> &data)
  32 + {
  33 + child->train(data);
  34 + }
  35 +
  36 + void project(const Template &src, Template &dst) const
  37 + {
  38 + child->project(src, dst);
  39 + }
  40 +
  41 + void store(QDataStream &stream) const
  42 + {
  43 + child->store(stream);
  44 + }
  45 +
  46 + void load(QDataStream &stream)
  47 + {
  48 + child->load(stream);
  49 + }
  50 +};
  51 +
  52 +BR_REGISTER(Transform, TurkClassifierTransform)
  53 +
  54 +} // namespace br
  55 +
  56 +#include "classification/turk.moc"
openbr/plugins/cluster/collectnn.cpp
@@ -39,4 +39,4 @@ BR_REGISTER(Transform, CollectNNTransform) @@ -39,4 +39,4 @@ BR_REGISTER(Transform, CollectNNTransform)
39 39
40 } // namespace br 40 } // namespace br
41 41
42 -#include "collectnn.moc" 42 +#include "cluster/collectnn.moc"
openbr/plugins/cluster/kmeans.cpp
@@ -62,4 +62,4 @@ BR_REGISTER(Transform, KMeansTransform) @@ -62,4 +62,4 @@ BR_REGISTER(Transform, KMeansTransform)
62 62
63 } // namespace br 63 } // namespace br
64 64
65 -#include "kmeans.moc" 65 +#include "cluster/kmeans.moc"
openbr/plugins/cluster/knn.cpp
@@ -81,4 +81,4 @@ BR_REGISTER(Transform, KNNTransform) @@ -81,4 +81,4 @@ BR_REGISTER(Transform, KNNTransform)
81 81
82 } // namespace br 82 } // namespace br
83 83
84 -#include "knn.moc" 84 +#include "cluster/knn.moc"
openbr/plugins/cluster/lognn.cpp
@@ -62,4 +62,4 @@ BR_REGISTER(Transform, LogNNTransform) @@ -62,4 +62,4 @@ BR_REGISTER(Transform, LogNNTransform)
62 62
63 } // namespace br 63 } // namespace br
64 64
65 -#include "lognn.moc" 65 +#include "cluster/lognn.moc"
openbr/plugins/cluster/randomcentroids.cpp
@@ -65,4 +65,4 @@ BR_REGISTER(Transform, RandomCentroidsTransform) @@ -65,4 +65,4 @@ BR_REGISTER(Transform, RandomCentroidsTransform)
65 65
66 } //namespace br 66 } //namespace br
67 67
68 -#include "randomcentroids.moc" 68 +#include "cluster/randomcentroids.moc"
openbr/plugins/eigen3.cmake renamed to openbr/plugins/cmake/eigen3.cmake
@@ -2,6 +2,8 @@ set(BR_WITH_EIGEN3 ON CACHE BOOL &quot;Build Eigen3 plugins&quot;) @@ -2,6 +2,8 @@ set(BR_WITH_EIGEN3 ON CACHE BOOL &quot;Build Eigen3 plugins&quot;)
2 2
3 if(${BR_WITH_EIGEN3}) 3 if(${BR_WITH_EIGEN3})
4 find_package(Eigen3 REQUIRED) 4 find_package(Eigen3 REQUIRED)
5 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/eigen3.cpp)  
6 install(FILES ${EIGEN3_LICENSE} RENAME Eigen3 DESTINATION share/openbr/licenses) 5 install(FILES ${EIGEN3_LICENSE} RENAME Eigen3 DESTINATION share/openbr/licenses)
  6 +else()
  7 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/lda.cpp)
  8 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/imgproc/revertaffine.cpp)
7 endif() 9 endif()
openbr/plugins/ipc2013.cmake renamed to openbr/plugins/cmake/ipc2013.cmake
@@ -2,7 +2,8 @@ set(BR_WITH_IPC2013 OFF CACHE BOOL &quot;Build with Intel Perceptual Computing SDK 20 @@ -2,7 +2,8 @@ set(BR_WITH_IPC2013 OFF CACHE BOOL &quot;Build with Intel Perceptual Computing SDK 20
2 2
3 if(${BR_WITH_IPC2013}) 3 if(${BR_WITH_IPC2013})
4 find_package(IPC2013 REQUIRED) 4 find_package(IPC2013 REQUIRED)
5 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/ipc2013.cpp)  
6 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${IPC2013_LIBS}) 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${IPC2013_LIBS})
7 install(DIRECTORY ${IPC2013_DIR}/bin/x64/ DESTINATION bin) 6 install(DIRECTORY ${IPC2013_DIR}/bin/x64/ DESTINATION bin)
  7 +else()
  8 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/ipc2013.cpp)
8 endif() 9 endif()
openbr/plugins/jni.cmake renamed to openbr/plugins/cmake/jni.cmake
@@ -3,10 +3,10 @@ set(BR_WITH_JAVA OFF CACHE BOOL &quot;Use Java Code&quot;) @@ -3,10 +3,10 @@ set(BR_WITH_JAVA OFF CACHE BOOL &quot;Use Java Code&quot;)
3 if (${BR_WITH_JAVA}) 3 if (${BR_WITH_JAVA})
4 find_package(JNI REQUIRED) 4 find_package(JNI REQUIRED)
5 find_package(JAVA REQUIRED) 5 find_package(JAVA REQUIRED)
6 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/jni.cpp)  
7 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${JNI_LIBRARIES}) 6 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${JNI_LIBRARIES})
8 7
9 include_directories(${JAVA_INCLUDE_PATH}) 8 include_directories(${JAVA_INCLUDE_PATH})
10 include_directories(${JAVA_INCLUDE_PATH2}) 9 include_directories(${JAVA_INCLUDE_PATH2})
11 - 10 +else()
  11 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/core/jni.cpp)
12 endif() 12 endif()
openbr/plugins/liblinear.cmake renamed to openbr/plugins/cmake/liblinear.cmake
@@ -3,5 +3,6 @@ set(BR_WITH_LIBLINEAR OFF CACHE BOOL &quot;Build with LibLinear&quot;) @@ -3,5 +3,6 @@ set(BR_WITH_LIBLINEAR OFF CACHE BOOL &quot;Build with LibLinear&quot;)
3 if(${BR_WITH_LIBLINEAR}) 3 if(${BR_WITH_LIBLINEAR})
4 find_package(LibLinear REQUIRED) 4 find_package(LibLinear REQUIRED)
5 set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} ${LibLinear_SRC}) 5 set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} ${LibLinear_SRC})
6 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/liblinear.cpp) 6 +else()
  7 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/liblinear.cpp)
7 endif() 8 endif()
openbr/plugins/likely.cmake renamed to openbr/plugins/cmake/likely.cmake
@@ -2,6 +2,9 @@ set(BR_WITH_LIKELY OFF CACHE BOOL &quot;Build with Likely&quot;) @@ -2,6 +2,9 @@ set(BR_WITH_LIKELY OFF CACHE BOOL &quot;Build with Likely&quot;)
2 2
3 if(${BR_WITH_LIKELY}) 3 if(${BR_WITH_LIKELY})
4 find_package(Likely REQUIRED) 4 find_package(Likely REQUIRED)
5 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/likely.cpp)  
6 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${Likely_LIBS}) 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${Likely_LIBS})
  6 +else()
  7 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/core/likely.cpp)
  8 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/format/lmat.cpp)
  9 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/gallery/lmat.cpp)
7 endif() 10 endif()
openbr/plugins/mongoose.cmake renamed to openbr/plugins/cmake/mongoose.cmake
1 set(BR_WITH_MONGOOSE OFF CACHE BOOL "Build with Mongoose") 1 set(BR_WITH_MONGOOSE OFF CACHE BOOL "Build with Mongoose")
2 if(${BR_WITH_MONGOOSE}) 2 if(${BR_WITH_MONGOOSE})
3 find_package(Mongoose) 3 find_package(Mongoose)
4 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/mongoose.cpp ${MONGOOSE_SRC}) 4 + set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} ${MONGOOSE_SRC})
5 install(FILES ${MONGOOSE_LICENSE} RENAME mongoose DESTINATION share/openbr/licenses) 5 install(FILES ${MONGOOSE_LICENSE} RENAME mongoose DESTINATION share/openbr/licenses)
  6 +else()
  7 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/metadata/mongoose.cpp)
6 endif() 8 endif()
openbr/plugins/qtnetwork.cmake renamed to openbr/plugins/cmake/network.cmake
@@ -3,6 +3,10 @@ if(${BR_WITH_QTNETWORK}) @@ -3,6 +3,10 @@ if(${BR_WITH_QTNETWORK})
3 find_package(Qt5Network) 3 find_package(Qt5Network)
4 find_package(HttpParser) 4 find_package(HttpParser)
5 set(QT_DEPENDENCIES ${QT_DEPENDENCIES} Network) 5 set(QT_DEPENDENCIES ${QT_DEPENDENCIES} Network)
6 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/qtnetwork.cpp ${HTTPPARSER_SRC}) 6 + set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} ${HTTPPARSER_SRC})
7 install(FILES ${HTTPPARSER_LICENSE} RENAME http-parser DESTINATION share/openbr/licenses) 7 install(FILES ${HTTPPARSER_LICENSE} RENAME http-parser DESTINATION share/openbr/licenses)
  8 +else()
  9 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/format/urlformat.cpp)
  10 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/format/postformat.cpp)
  11 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/gallery/postgallery.cpp)
8 endif() 12 endif()
openbr/plugins/nt4.cmake renamed to openbr/plugins/cmake/nt4.cmake
@@ -2,7 +2,8 @@ set(BR_WITH_NT4 OFF CACHE BOOL &quot;Build with Neurotec Biometric 4&quot;) @@ -2,7 +2,8 @@ set(BR_WITH_NT4 OFF CACHE BOOL &quot;Build with Neurotec Biometric 4&quot;)
2 2
3 if(${BR_WITH_NT4}) 3 if(${BR_WITH_NT4})
4 find_package(NT4 REQUIRED) 4 find_package(NT4 REQUIRED)
5 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/nt4.cpp)  
6 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${NT4_LIBS}) 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${NT4_LIBS})
7 install(DIRECTORY ${NT4_DIR_LIB}/ DESTINATION lib) 6 install(DIRECTORY ${NT4_DIR_LIB}/ DESTINATION lib)
  7 +else()
  8 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/nt4.cpp)
8 endif() 9 endif()
openbr/plugins/pp4.cmake renamed to openbr/plugins/cmake/pp4.cmake
@@ -2,8 +2,9 @@ set(BR_WITH_PP4 OFF CACHE BOOL &quot;Build with PittPatt 4&quot;) @@ -2,8 +2,9 @@ set(BR_WITH_PP4 OFF CACHE BOOL &quot;Build with PittPatt 4&quot;)
2 2
3 if(${BR_WITH_PP4}) 3 if(${BR_WITH_PP4})
4 find_package(PP4 REQUIRED) 4 find_package(PP4 REQUIRED)
5 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/pp4.cpp)  
6 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${PP4_LIBS}) 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${PP4_LIBS})
7 install(DIRECTORY ${PP4_DIR}/lib/ DESTINATION lib) 6 install(DIRECTORY ${PP4_DIR}/lib/ DESTINATION lib)
8 install(DIRECTORY ${PP4_DIR}/models/ DESTINATION models/pp4) 7 install(DIRECTORY ${PP4_DIR}/models/ DESTINATION models/pp4)
  8 +else()
  9 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/pp4.cpp)
9 endif() 10 endif()
openbr/plugins/pp5.cmake renamed to openbr/plugins/cmake/pp5.cmake
@@ -2,7 +2,6 @@ set(BR_WITH_PP5 OFF CACHE BOOL &quot;Build with PittPatt 5&quot;) @@ -2,7 +2,6 @@ set(BR_WITH_PP5 OFF CACHE BOOL &quot;Build with PittPatt 5&quot;)
2 2
3 if(${BR_WITH_PP5}) 3 if(${BR_WITH_PP5})
4 find_package(PP5 REQUIRED) 4 find_package(PP5 REQUIRED)
5 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/pp5.cpp)  
6 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${PP5_LIBS}) 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${PP5_LIBS})
7 6
8 if(WIN32) 7 if(WIN32)
@@ -12,4 +11,6 @@ if(${BR_WITH_PP5}) @@ -12,4 +11,6 @@ if(${BR_WITH_PP5})
12 endif() 11 endif()
13 12
14 install(DIRECTORY ${PP5_DIR}/models/ DESTINATION share/openbr/models/pp5) 13 install(DIRECTORY ${PP5_DIR}/models/ DESTINATION share/openbr/models/pp5)
  14 +else()
  15 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/pp5.cpp)
15 endif() 16 endif()
openbr/plugins/cmake/show.cmake 0 → 100644
  1 +if(${BR_EMBEDDED})
  2 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/gui/show.cpp)
  3 +endif()
openbr/plugins/stasm4.cmake renamed to openbr/plugins/cmake/stasm4.cmake
@@ -2,7 +2,6 @@ set(BR_WITH_STASM4 OFF CACHE BOOL &quot;Build with Stasm&quot;) @@ -2,7 +2,6 @@ set(BR_WITH_STASM4 OFF CACHE BOOL &quot;Build with Stasm&quot;)
2 2
3 if(${BR_WITH_STASM4}) 3 if(${BR_WITH_STASM4})
4 find_package(Stasm4 REQUIRED) 4 find_package(Stasm4 REQUIRED)
5 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/stasm4.cpp)  
6 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${Stasm4_LIBS}) 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${Stasm4_LIBS})
7 6
8 if(WIN32) 7 if(WIN32)
@@ -12,4 +11,7 @@ if(${BR_WITH_STASM4}) @@ -12,4 +11,7 @@ if(${BR_WITH_STASM4})
12 endif() 11 endif()
13 12
14 install(DIRECTORY ${Stasm_DIR}/data/ DESTINATION share/openbr/models/stasm) 13 install(DIRECTORY ${Stasm_DIR}/data/ DESTINATION share/openbr/models/stasm)
  14 +else()
  15 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/metadata/stasm4.cpp)
  16 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/imgproc/revertaffine.cpp)
15 endif() 17 endif()
openbr/plugins/core/algorithms.cpp
@@ -108,4 +108,4 @@ BR_REGISTER(Initializer, AlgorithmsInitializer) @@ -108,4 +108,4 @@ BR_REGISTER(Initializer, AlgorithmsInitializer)
108 108
109 } // namespace br 109 } // namespace br
110 110
111 -#include "algorithms.moc" 111 +#include "core/algorithms.moc"
openbr/plugins/core/attributealgorithms.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup initializers
  8 + * \brief Initializes global abbreviations with implemented algorithms for attributes
  9 + * \author Babatunde Ogunfemi \cite baba1472
  10 + */
  11 +class AttributeAlgorithmsInitializer : public Initializer
  12 +{
  13 + Q_OBJECT
  14 +
  15 + void initialize() const
  16 + {
  17 + // Constants
  18 + QString BASE="Open+PP5Register+Rename(PP5_Landmark0_Right_Eye,Affine_0)+Rename(PP5_Landmark1_Left_Eye,Affine_1)+Affine(192,240,.345,.475)+Cvt(Gray)+Stasm(false,true,[(66.24,114),(125.76,114)])";
  19 + QString SUBSPACE ="Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+RectRegions(8,8,4,4)+Hist(59)+Cat+PCA(0.95)";
  20 +
  21 + QString NOSE="RectFromStasmNoseWithBridge+ROI+Resize(36,24)+" + SUBSPACE;
  22 + QString MOUTH="RectFromStasmMouth+ROI+Resize(24,36)+" + SUBSPACE;
  23 + QString EYES="RectFromStasmEyes+ROI+Resize(24,36)+" + SUBSPACE;
  24 + QString HAIR="RectFromStasmHair+ROI+Resize(24,36)+" + SUBSPACE;
  25 + QString BROW="RectFromStasmBrow+ROI+Resize(24,36)+" + SUBSPACE;
  26 + QString JAW="RectFromStasmJaw+ROI+Resize(36,36)+" + SUBSPACE;
  27 + QString FACE = "Crop(24,30,144,190)+Resize(36,36)+" + SUBSPACE;
  28 +
  29 + // All Attributes
  30 + Globals->abbreviations.insert("AllAttributes", "AttributeBrow/AttributeMouth/AttributeEyes/AttributeFace/AttributeHair/AttributeNose/AttributeJaw");
  31 + Globals->abbreviations.insert("AllAttributesMatching", "(AttributeBrow)/(AttributeMouth)/(AttributeEyes)/(AttributeFace)/(AttributeHair)/(AttributeNose)/(AttributeJaw):AttributeMatch");
  32 +
  33 + //Individual Attributes
  34 + Globals->abbreviations.insert("AttributeBrow", "(" + BASE+ "+" + BROW + "+"
  35 + "TurkClassifier(eyebrowposition,[closebrows,highbrows],3)/"
  36 + "TurkClassifier(unibrow,[unibrow],3)/"
  37 + "TurkClassifier(eyebroworientation,[eyebrowsdown,eyebrowsuptodown],3)/"
  38 + "TurkClassifier(thickeyebrows,[thickeyebrows,lighteyebrows],3))");
  39 + Globals->abbreviations.insert("AttributeMouth", "(" + BASE + "+" + MOUTH + "+"
  40 + "TurkClassifier(smiling,[smiling],3)/"
  41 + "TurkClassifier(lipthickness,[cherry,big,small],3)/"
  42 + "TurkClassifier(mouthbite,[underbite,overbite],3)/"
  43 + "TurkClassifier(mouthopen,[closed,noteeth,halfteeth,allteeth],3)/"
  44 + "TurkClassifier(mouthwidth,[small,wide],3)/"
  45 + "TurkClassifier(mustache,[nomustache,linemustache,lightmustache,normalmustache,down],3)/"
  46 + "TurkClassifier(mouthasymmetry,[asymmetrical],3))");
  47 + Globals->abbreviations.insert("AttributeEyes", "(" + BASE + "+" + EYES + "+ "
  48 + "TurkClassifier(eyeseparation,[close,wide],3)/"
  49 + "TurkClassifier(eyeslant,[slant2,slant1,wild],3)/"
  50 + "TurkClassifier(benteyes,[bent])/"
  51 + "TurkClassifier(eyecolor,[darkeyes,lighteyes],3)/"
  52 + "TurkClassifier(baggyeyes,[baggy],3)/"
  53 + "TurkClassifier(almondeyes,[almond],3)/"
  54 + "TurkClassifier(buriedeyes,[buriedeyes],3)/"
  55 + "TurkClassifier(sleepyeyes,[sleepy],3)/"
  56 + "TurkClassifier(lineeyes,[line],3)/"
  57 + "TurkClassifier(roundeyes,[round],3)/"
  58 + "TurkClassifier(sharpeyes,[sharp],3)/"
  59 + "TurkClassifier(smalleyes,[smalleyes],3)/"
  60 + "TurkClassifier(glasses,[glasses],3)/"
  61 + "TurkClassifier(eyelashvisibility,[feweyelashes],3))");
  62 + Globals->abbreviations.insert("AttributeFace", "(" + BASE + "+" + FACE + "+"
  63 + "TurkClassifier(gender,[male],3)/"
  64 + "TurkClassifier(faceshape,[round,triangular,rectangular],3)/"
  65 + "TurkClassifier(cheekdensity,[puffy,in,normal],3)/"
  66 + "TurkClassifier(facemarks,[scars,moles,normal],3)/"
  67 + "TurkClassifier(facelength,[long],3)/"
  68 + "TurkClassifier(nosetoeyedist,[short,long],3)/"
  69 + "TurkClassifier(nosetomouthdist,[long,small],3))");
  70 + Globals->abbreviations.insert("AttributeHair", "(" + BASE + "+" + HAIR + "+"
  71 + "TurkClassifier(foreheadwrinkles,[wrinkled],3)/"
  72 + "TurkClassifier(foreheadsize,[smallforehead,largeforehead],3)/"
  73 + "TurkClassifier(haircolor,[darkhair,lighthair,greyhair],3)/"
  74 + "TurkClassifier(hairdensity,[thick,bald,thin,halfbald],3)/"
  75 + "TurkClassifier(widowspeak,[widowspeak],3)/"
  76 + "TurkClassifier(hairstyle,[curlyhair],3))");
  77 + Globals->abbreviations.insert("AttributeNose", "(" + BASE + "+" + NOSE + "+"
  78 + "TurkClassifier(noseorientation,[upnose,downnose],3)/"
  79 + "TurkClassifier(nosewidth,[small,thick],3)/"
  80 + "TurkClassifier(nosesize,[smallnose,bignose],3)/"
  81 + "TurkClassifier(brokennose,[broken],3))");
  82 + Globals->abbreviations.insert("AttributeJaw", "(" + BASE + "+" + JAW + "+"
  83 + "TurkClassifier(beard,[nobeard,bigbeard,lightbeard,goatee,linebeard,normalbeard,lincolnbeard],3)/"
  84 + "TurkClassifier(chinsize,[shortchin,longchin],3))");
  85 + Globals->abbreviations.insert("AttributeMatch", "Fuse(["
  86 + "Turk(eyebrowposition,[closebrows,highbrows],3),"
  87 + "Turk(unibrow,[unibrow],3),"
  88 + "Turk(eyebroworientation,[eyebrowsdown,eyebrowsuptodown],3),"
  89 + "Turk(thickeyebrows,[thickeyebrows,lighteyebrows],3),"
  90 + "Turk(smiling,[smiling],3),"
  91 + "Turk(lipthickness,[cherry,big,small],3),"
  92 + "Turk(mouthbite,[underbite,overbite],3),"
  93 + "Turk(mouthopen,[closed,noteeth,halfteeth,allteeth],3),"
  94 + "Turk(mouthwidth,[small,wide],3),"
  95 + "Turk(mustache,[nomustache,linemustache,lightmustache,normalmustache,down],3),"
  96 + "Turk(mouthasymmetry,[asymmetrical],3),"
  97 + "Turk(eyeseparation,[close,wide],3),"
  98 + "Turk(eyeslant,[slant2,slant1,wild],3),"
  99 + "Turk(benteyes,[bent],3),"
  100 + "Turk(eyecolor,[darkeyes,lighteyes],3),"
  101 + "Turk(baggyeyes,[baggy],3),"
  102 + "Turk(almondeyes,[almond],3),"
  103 + "Turk(buriedeyes,[buriedeyes],3),"
  104 + "Turk(sleepyeyes,[sleepy],3),"
  105 + "Turk(lineeyes,[line],3),"
  106 + "Turk(roundeyes,[round],3),"
  107 + "Turk(sharpeyes,[sharp],3),"
  108 + "Turk(smalleyes,[smalleyes],3),"
  109 + "Turk(glasses,[glasses],3),"
  110 + "Turk(eyelashvisibility,[feweyelashes],3),"
  111 + "Turk(gender,[male],3),"
  112 + "Turk(faceshape,[round,triangular,rectangular],3),"
  113 + "Turk(cheekdensity,[puffy,in,normal],3),"
  114 + "Turk(facemarks,[scars,moles,normal],3),"
  115 + "Turk(facelength,[long],3),"
  116 + "Turk(nosetoeyedist,[short,long],3),"
  117 + "Turk(nosetomouthdist,[long,small],3),"
  118 + "Turk(foreheadwrinkles,[wrinkled],3),"
  119 + "Turk(foreheadsize,[smallforehead,largeforehead],3),"
  120 + "Turk(haircolor,[darkhair,lighthair,greyhair],3),"
  121 + "Turk(hairdensity,[thick,bald,thin,halfbald],3),"
  122 + "Turk(widowspeak,[widowspeak],3),"
  123 + "Turk(hairstyle,[curlyhair],3),"
  124 + "Turk(noseorientation,[upnose,downnose],3),"
  125 + "Turk(nosewidth,[small,thick],3),"
  126 + "Turk(nosesize,[smallnose,bignose],3),"
  127 + "Turk(brokennose,[broken],3),"
  128 + "Turk(beard,[nobeard,bigbeard,lightbeard,goatee,linebeard,normalbeard,lincolnbeard],3),"
  129 + "Turk(chinsize,[shortchin,longchin],3)])");
  130 + }
  131 +};
  132 +
  133 +BR_REGISTER(Initializer, AttributeAlgorithmsInitializer)
  134 +
  135 +} // namespace br
  136 +
  137 +#include "core/attributealgorithms.moc"
openbr/plugins/core/cache.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Caches br::Transform::project() results.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class CacheTransform : public MetaTransform
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  15 + BR_PROPERTY(br::Transform*, transform, NULL)
  16 +
  17 + static QHash<QString, Template> cache;
  18 + static QMutex cacheLock;
  19 +
  20 +public:
  21 + ~CacheTransform()
  22 + {
  23 + if (cache.isEmpty()) return;
  24 +
  25 + // Write to cache
  26 + QFile file("Cache");
  27 + if (!file.open(QFile::WriteOnly))
  28 + qFatal("Unable to open %s for writing.", qPrintable(file.fileName()));
  29 + QDataStream stream(&file);
  30 + stream << cache;
  31 + file.close();
  32 + }
  33 +
  34 +private:
  35 + void init()
  36 + {
  37 + if (!transform) return;
  38 +
  39 + trainable = transform->trainable;
  40 + if (!cache.isEmpty()) return;
  41 +
  42 + // Read from cache
  43 + QFile file("Cache");
  44 + if (file.exists()) {
  45 + if (!file.open(QFile::ReadOnly))
  46 + qFatal("Unable to open %s for reading.", qPrintable(file.fileName()));
  47 + QDataStream stream(&file);
  48 + stream >> cache;
  49 + file.close();
  50 + }
  51 + }
  52 +
  53 + void train(const QList<TemplateList> &data)
  54 + {
  55 + transform->train(data);
  56 + }
  57 +
  58 + void project(const Template &src, Template &dst) const
  59 + {
  60 + const QString &file = src.file;
  61 + if (cache.contains(file)) {
  62 + dst = cache[file];
  63 + } else {
  64 + transform->project(src, dst);
  65 + cacheLock.lock();
  66 + cache[file] = dst;
  67 + cacheLock.unlock();
  68 + }
  69 + }
  70 +};
  71 +
  72 +QHash<QString, Template> CacheTransform::cache;
  73 +QMutex CacheTransform::cacheLock;
  74 +
  75 +BR_REGISTER(Transform, CacheTransform)
  76 +
  77 +} // namespace br
  78 +
  79 +#include "core/cache.moc"
openbr/plugins/core/contract.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief It's like the opposite of ExpandTransform, but not really
  9 + * \author Charles Otto \cite caotto
  10 + *
  11 + * Given a set of templatelists as input, concatenate them onto a single Template
  12 + */
  13 +class ContractTransform : public UntrainableMetaTransform
  14 +{
  15 + Q_OBJECT
  16 +
  17 + virtual void project(const TemplateList &src, TemplateList &dst) const
  18 + {
  19 + if (src.empty()) return;
  20 + Template out;
  21 +
  22 + foreach (const Template &t, src) {
  23 + out.merge(t);
  24 + }
  25 + out.file.clearRects();
  26 + foreach (const Template &t, src) {
  27 + if (!t.file.rects().empty())
  28 + out.file.appendRects(t.file.rects());
  29 + }
  30 + dst.clear();
  31 + dst.append(out);
  32 + }
  33 +
  34 + virtual void project(const Template &src, Template &dst) const
  35 + {
  36 + qFatal("this has gone bad");
  37 + (void) src; (void) dst;
  38 + }
  39 +};
  40 +
  41 +BR_REGISTER(Transform, ContractTransform)
  42 +
  43 +} // namespace br
  44 +
  45 +#include "core/contract.moc"
openbr/plugins/validate.cpp renamed to openbr/plugins/core/crossvalidate.cpp
1 -#include <QFutureSynchronizer>  
2 -#include <QtConcurrentRun>  
3 -#include "openbr_internal.h"  
4 -#include "openbr/core/common.h"  
5 -#include <openbr/core/qtutils.h> 1 +#include <QtConcurrent>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/common.h>
6 5
7 namespace br 6 namespace br
8 { 7 {
@@ -134,138 +133,6 @@ class CrossValidateTransform : public MetaTransform @@ -134,138 +133,6 @@ class CrossValidateTransform : public MetaTransform
134 133
135 BR_REGISTER(Transform, CrossValidateTransform) 134 BR_REGISTER(Transform, CrossValidateTransform)
136 135
137 -/*!  
138 - * \ingroup distances  
139 - * \brief Cross validate a distance metric.  
140 - * \author Josh Klontz \cite jklontz  
141 - */  
142 -class CrossValidateDistance : public UntrainableDistance  
143 -{  
144 - Q_OBJECT  
145 -  
146 - float compare(const Template &a, const Template &b) const  
147 - {  
148 - static const QString key("Partition"); // More efficient to preallocate this  
149 - const int partitionA = a.file.get<int>(key, 0);  
150 - const int partitionB = b.file.get<int>(key, 0);  
151 - return (partitionA != partitionB) ? -std::numeric_limits<float>::max() : 0;  
152 - }  
153 -};  
154 -  
155 -BR_REGISTER(Distance, CrossValidateDistance)  
156 -  
157 -/*!  
158 - * \ingroup distances  
159 - * \brief Checks target metadata against filters.  
160 - * \author Josh Klontz \cite jklontz  
161 - */  
162 -class FilterDistance : public UntrainableDistance  
163 -{  
164 - Q_OBJECT  
165 -  
166 - float compare(const Template &a, const Template &b) const  
167 - {  
168 - (void) b; // Query template isn't checked  
169 - foreach (const QString &key, Globals->filters.keys()) {  
170 - bool keep = false;  
171 - const QString metadata = a.file.get<QString>(key, "");  
172 - if (Globals->filters[key].isEmpty()) continue;  
173 - if (metadata.isEmpty()) return -std::numeric_limits<float>::max();  
174 - foreach (const QString &value, Globals->filters[key]) {  
175 - if (metadata == value) {  
176 - keep = true;  
177 - break;  
178 - }  
179 - }  
180 - if (!keep) return -std::numeric_limits<float>::max();  
181 - }  
182 - return 0;  
183 - }  
184 -};  
185 -  
186 -BR_REGISTER(Distance, FilterDistance)  
187 -  
188 -/*!  
189 - * \ingroup distances  
190 - * \brief Checks target metadata against query metadata.  
191 - * \author Scott Klum \cite sklum  
192 - */  
193 -class MetadataDistance : public UntrainableDistance  
194 -{  
195 - Q_OBJECT  
196 -  
197 - Q_PROPERTY(QStringList filters READ get_filters WRITE set_filters RESET reset_filters STORED false)  
198 - BR_PROPERTY(QStringList, filters, QStringList())  
199 -  
200 - float compare(const Template &a, const Template &b) const  
201 - {  
202 - foreach (const QString &key, filters) {  
203 - QString aValue = a.file.get<QString>(key, QString());  
204 - QString bValue = b.file.get<QString>(key, QString());  
205 -  
206 - // The query value may be a range. Let's check.  
207 - if (bValue.isEmpty()) bValue = QtUtils::toString(b.file.get<QPointF>(key, QPointF()));  
208 -  
209 - if (aValue.isEmpty() || bValue.isEmpty()) continue;  
210 -  
211 - bool keep = false;  
212 - bool ok;  
213 -  
214 - QPointF range = QtUtils::toPoint(bValue,&ok);  
215 -  
216 - if (ok) /* Range */ {  
217 - int value = range.x();  
218 - int upperBound = range.y();  
219 -  
220 - while (value <= upperBound) {  
221 - if (aValue == QString::number(value)) {  
222 - keep = true;  
223 - break;  
224 - }  
225 - value++;  
226 - }  
227 - }  
228 - else if (aValue == bValue) keep = true;  
229 -  
230 - if (!keep) return -std::numeric_limits<float>::max();  
231 - }  
232 - return 0;  
233 - }  
234 -};  
235 -  
236 -  
237 -BR_REGISTER(Distance, MetadataDistance)  
238 -  
239 -/*!  
240 - * \ingroup distances  
241 - * \brief Sets distance to -FLOAT_MAX if a target template has/doesn't have a key.  
242 - * \author Scott Klum \cite sklum  
243 - */  
244 -class RejectDistance : public UntrainableDistance  
245 -{  
246 - Q_OBJECT  
247 -  
248 - Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)  
249 - BR_PROPERTY(QStringList, keys, QStringList())  
250 - Q_PROPERTY(bool rejectIfContains READ get_rejectIfContains WRITE set_rejectIfContains RESET reset_rejectIfContains STORED false)  
251 - BR_PROPERTY(bool, rejectIfContains, false)  
252 -  
253 - float compare(const Template &a, const Template &b) const  
254 - {  
255 - // We don't look at the query  
256 - (void) b;  
257 -  
258 - foreach (const QString &key, keys)  
259 - if ((rejectIfContains && a.file.contains(key)) || (!rejectIfContains && !a.file.contains(key)))  
260 - return -std::numeric_limits<float>::max();  
261 -  
262 - return 0;  
263 - }  
264 -};  
265 -  
266 -  
267 -BR_REGISTER(Distance, RejectDistance)  
268 -  
269 } // namespace br 136 } // namespace br
270 137
271 -#include "validate.moc" 138 +#include "core/crossvalidate.moc"
openbr/plugins/core/discard.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Removes all template's matrices.
  9 + * \see IdentityTransform FirstTransform RestTransform RemoveTransform
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class DiscardTransform : public UntrainableMetaTransform
  13 +{
  14 + Q_OBJECT
  15 +
  16 + void project(const Template &src, Template &dst) const
  17 + {
  18 + dst.file = src.file;
  19 + }
  20 +};
  21 +
  22 +BR_REGISTER(Transform, DiscardTransform)
  23 +
  24 +} // namespace br
  25 +
  26 +#include "core/discard.moc"
openbr/plugins/core/discardtemplates.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +class DiscardTemplatesTransform : public UntrainableMetaTransform
  7 +{
  8 + Q_OBJECT
  9 +
  10 + void project(const Template &src, Template &dst) const
  11 + {
  12 + (void) src; (void) dst;
  13 + qFatal("Incorrect project called on DiscardTemplatesTransform");
  14 + }
  15 + void project(const TemplateList &src, TemplateList &dst) const
  16 + {
  17 + (void) src;
  18 + dst.clear();
  19 + }
  20 +};
  21 +
  22 +BR_REGISTER(Transform, DiscardTemplatesTransform)
  23 +
  24 +} // namespace br
  25 +
  26 +#include "core/discardtemplates.moc"
openbr/plugins/core/distributetemplate.cpp 0 → 100644
  1 +#include <QtConcurrent>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +static void _projectList(const Transform *transform, const TemplateList *src, TemplateList *dst)
  9 +{
  10 + transform->project(*src, *dst);
  11 +}
  12 +
  13 +class DistributeTemplateTransform : public MetaTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  17 + BR_PROPERTY(br::Transform*, transform, NULL)
  18 +
  19 +public:
  20 +
  21 + Transform *smartCopy(bool &newTransform)
  22 + {
  23 + if (!transform->timeVarying()) {
  24 + newTransform = false;
  25 + return this;
  26 + }
  27 + newTransform = true;
  28 +
  29 + DistributeTemplateTransform *output = new DistributeTemplateTransform;
  30 + bool newChild = false;
  31 + output->transform = transform->smartCopy(newChild);
  32 + if (newChild)
  33 + output->transform->setParent(output);
  34 +
  35 + return output;
  36 + }
  37 +
  38 + void train(const QList<TemplateList> &data)
  39 + {
  40 + if (!transform->trainable) {
  41 + qWarning("Attempted to train untrainable transform, nothing will happen.");
  42 + return;
  43 + }
  44 +
  45 + QList<TemplateList> separated;
  46 + foreach (const TemplateList &list, data) {
  47 + foreach (const Template &t, list) {
  48 + separated.append(TemplateList());
  49 + separated.last().append(t);
  50 + }
  51 + }
  52 +
  53 + transform->train(separated);
  54 + }
  55 +
  56 + void project(const Template &src, Template &dst) const
  57 + {
  58 + TemplateList input;
  59 + input.append(src);
  60 + TemplateList output;
  61 + project(input, output);
  62 +
  63 + if (output.size() != 1) qFatal("output contains more than 1 template");
  64 + else dst = output[0];
  65 + }
  66 +
  67 + // For each input template, form a single element TemplateList, push all those
  68 + // lists through transform, and form dst by concatenating the results.
  69 + // Process the single elemnt templates in parallel if parallelism is enabled.
  70 + void project(const TemplateList &src, TemplateList &dst) const
  71 + {
  72 + // Pre-allocate output for each template
  73 + QList<TemplateList> output_buffer;
  74 + output_buffer.reserve(src.size());
  75 +
  76 + // Can't declare this local to the loop because it would go out of scope
  77 + QList<TemplateList> input_buffer;
  78 + input_buffer.reserve(src.size());
  79 +
  80 + QFutureSynchronizer<void> futures;
  81 +
  82 + for (int i =0; i < src.size();i++) {
  83 + input_buffer.append(TemplateList());
  84 + output_buffer.append(TemplateList());
  85 + }
  86 + QList<QFuture<void> > temp;
  87 + temp.reserve(src.size());
  88 + for (int i=0; i<src.size(); i++) {
  89 + input_buffer[i].append(src[i]);
  90 +
  91 + if (Globals->parallelism > 1) temp.append(QtConcurrent::run(_projectList, transform, &input_buffer[i], &output_buffer[i]));
  92 + else _projectList(transform, &input_buffer[i], &output_buffer[i]);
  93 + }
  94 + // We add the futures in reverse order, since in Qt 5.1 at least the
  95 + // waiting thread will wait on them in the order added (which for uniform priority
  96 + // threads is the order of execution), and we want the waiting thread to go in the opposite order
  97 + // so that it can steal runnables and do something besides wait.
  98 + for (int i = temp.size() - 1; i >= 0; i--) {
  99 + futures.addFuture(temp[i]);
  100 + }
  101 +
  102 + futures.waitForFinished();
  103 +
  104 + for (int i=0; i<src.size(); i++) dst.append(output_buffer[i]);
  105 + }
  106 +
  107 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  108 + {
  109 + this->project(src, dst);
  110 + return;
  111 + }
  112 +
  113 + void init()
  114 + {
  115 + if (!transform)
  116 + return;
  117 +
  118 + trainable = transform->trainable;
  119 + }
  120 +
  121 +};
  122 +BR_REGISTER(Transform, DistributeTemplateTransform)
  123 +
  124 +} // namespace br
  125 +
  126 +#include "core/distributetemplate.moc"
openbr/plugins/core/downsample.cpp renamed to openbr/plugins/core/downsampletraining.cpp
@@ -116,4 +116,4 @@ BR_REGISTER(Transform, DownsampleTrainingTransform) @@ -116,4 +116,4 @@ BR_REGISTER(Transform, DownsampleTrainingTransform)
116 116
117 } // namespace br 117 } // namespace br
118 118
119 -#include "downsample.moc" 119 +#include "core/downsampletraining.moc"
openbr/plugins/core/event.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +class EventTransform : public UntrainableMetaTransform
  7 +{
  8 + Q_OBJECT
  9 + Q_PROPERTY(QString eventName READ get_eventName WRITE set_eventName RESET reset_eventName STORED false)
  10 + BR_PROPERTY(QString, eventName, "")
  11 +
  12 + TemplateEvent event;
  13 +
  14 + void project(const Template &src, Template &dst) const
  15 + {
  16 + dst = src;
  17 + event.pulseSignal(dst);
  18 + }
  19 +
  20 + TemplateEvent *getEvent(const QString &name)
  21 + {
  22 + return name == eventName ? &event : NULL;
  23 + }
  24 +};
  25 +
  26 +BR_REGISTER(Transform, EventTransform)
  27 +
  28 +} // namespace br
  29 +
  30 +#include "core/event.moc"
openbr/plugins/core/expand.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +static TemplateList Expanded(const TemplateList &templates)
  7 +{
  8 + TemplateList expanded;
  9 + foreach (const Template &t, templates) {
  10 + const bool enrollAll = t.file.get<bool>("enrollAll");
  11 + if (t.isEmpty()) {
  12 + if (!enrollAll)
  13 + expanded.append(t);
  14 + continue;
  15 + }
  16 +
  17 + const QList<QPointF> points = t.file.points();
  18 + const QList<QRectF> rects = t.file.rects();
  19 + if (points.size() % t.size() != 0) qFatal("Uneven point count.");
  20 + if (rects.size() % t.size() != 0) qFatal("Uneven rect count.");
  21 + const int pointStep = points.size() / t.size();
  22 + const int rectStep = rects.size() / t.size();
  23 +
  24 + for (int i=0; i<t.size(); i++) {
  25 + expanded.append(Template(t.file, t[i]));
  26 + expanded.last().file.setRects(rects.mid(i*rectStep, rectStep));
  27 + expanded.last().file.setPoints(points.mid(i*pointStep, pointStep));
  28 + }
  29 + }
  30 + return expanded;
  31 +}
  32 +
  33 +/*!
  34 + * \ingroup transforms
  35 + * \brief Performs an expansion step on input templatelists
  36 + * \author Josh Klontz \cite jklontz
  37 + *
  38 + * Each matrix in an input Template is expanded into its own template.
  39 + *
  40 + * \see PipeTransform
  41 + */
  42 +class ExpandTransform : public UntrainableMetaTransform
  43 +{
  44 + Q_OBJECT
  45 +
  46 + virtual void project(const TemplateList &src, TemplateList &dst) const
  47 + {
  48 + dst = Expanded(src);
  49 + }
  50 +
  51 + virtual void project(const Template &src, Template &dst) const
  52 + {
  53 + dst = src;
  54 + qDebug("Called Expand project(Template,Template), nothing will happen");
  55 + }
  56 +};
  57 +
  58 +BR_REGISTER(Transform, ExpandTransform)
  59 +
  60 +} // namespace br
  61 +
  62 +#include "core/expand.moc"
openbr/plugins/core/first.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Removes all but the first matrix from the template.
  9 + * \see IdentityTransform DiscardTransform RestTransform RemoveTransform
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class FirstTransform : public UntrainableMetaTransform
  13 +{
  14 + Q_OBJECT
  15 +
  16 + void project(const Template &src, Template &dst) const
  17 + {
  18 + // AggregateFrames will leave the Template empty
  19 + // if it hasn't filled up the buffer
  20 + // so we gotta anticipate an empty Template
  21 + if (src.empty()) return;
  22 + dst.file = src.file;
  23 + dst = src.m();
  24 + }
  25 +};
  26 +
  27 +BR_REGISTER(Transform, FirstTransform)
  28 +
  29 +} // namespace br
  30 +
  31 +#include "core/first.moc"
openbr/plugins/core/fork.cpp 0 → 100644
  1 +#include <QtConcurrent>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +static void _train(Transform *transform, const QList<TemplateList> *data)
  9 +{
  10 + transform->train(*data);
  11 +}
  12 +
  13 +/*!
  14 + * \ingroup transforms
  15 + * \brief Transforms in parallel.
  16 + * \author Josh Klontz \cite jklontz
  17 + *
  18 + * The source br::Template is seperately given to each transform and the results are appended together.
  19 + *
  20 + * \see PipeTransform
  21 + */
  22 +class ForkTransform : public CompositeTransform
  23 +{
  24 + Q_OBJECT
  25 +
  26 + void train(const QList<TemplateList> &data)
  27 + {
  28 + if (!trainable) return;
  29 + QFutureSynchronizer<void> futures;
  30 + for (int i=0; i<transforms.size(); i++)
  31 + futures.addFuture(QtConcurrent::run(_train, transforms[i], &data));
  32 + futures.waitForFinished();
  33 + }
  34 +
  35 + // same as _project, but calls projectUpdate on sub-transforms
  36 + void projectupdate(const Template &src, Template &dst)
  37 + {
  38 + foreach (Transform *f, transforms) {
  39 + try {
  40 + Template res;
  41 + f->projectUpdate(src, res);
  42 + dst.merge(res);
  43 + } catch (...) {
  44 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  45 + dst = Template(src.file);
  46 + dst.file.fte = true;
  47 + break;
  48 + }
  49 + }
  50 + }
  51 +
  52 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  53 + {
  54 + dst.reserve(src.size());
  55 + for (int i=0; i<src.size(); i++) dst.append(Template(src[i].file));
  56 + foreach (Transform *f, transforms) {
  57 + TemplateList m;
  58 + f->projectUpdate(src, m);
  59 + if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size.");
  60 + for (int i=0; i<src.size(); i++) dst[i].merge(m[i]);
  61 + }
  62 + }
  63 +
  64 + // this is probably going to go bad, fork transform probably won't work well in a variable
  65 + // input/output scenario
  66 + virtual void finalize(TemplateList &output)
  67 + {
  68 + output.clear();
  69 + // For each transform,
  70 + for (int i = 0; i < transforms.size(); i++)
  71 + {
  72 + // Collect any final templates
  73 + TemplateList last_set;
  74 + transforms[i]->finalize(last_set);
  75 + if (last_set.empty())
  76 + continue;
  77 +
  78 + if (output.empty()) output = last_set;
  79 + else
  80 + {
  81 + // is the number of templates received from this transform consistent with the number
  82 + // received previously? If not we can't do anything coherent here.
  83 + if (last_set.size() != output.size())
  84 + qFatal("mismatched template list sizes in ForkTransform");
  85 + for (int j = 0; j < output.size(); j++) {
  86 + output[j].append(last_set[j]);
  87 + }
  88 + }
  89 + }
  90 + }
  91 +
  92 +protected:
  93 +
  94 + // Apply each transform to src, concatenate the results
  95 + void _project(const Template &src, Template &dst) const
  96 + {
  97 + foreach (const Transform *f, transforms) {
  98 + try {
  99 + dst.merge((*f)(src));
  100 + } catch (...) {
  101 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  102 + dst = Template(src.file);
  103 + dst.file.fte = true;
  104 + break;
  105 + }
  106 + }
  107 + }
  108 +
  109 + void _project(const TemplateList &src, TemplateList &dst) const
  110 + {
  111 + dst.reserve(src.size());
  112 + for (int i=0; i<src.size(); i++) dst.append(Template(src[i].file));
  113 + foreach (const Transform *f, transforms) {
  114 + TemplateList m;
  115 + f->project(src, m);
  116 + if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size.");
  117 + for (int i=0; i<src.size(); i++) dst[i].merge(m[i]);
  118 + }
  119 + }
  120 +
  121 +};
  122 +
  123 +BR_REGISTER(Transform, ForkTransform)
  124 +
  125 +} // namespace br
  126 +
  127 +#include "core/fork.moc"
openbr/plugins/core/fte.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/common.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup transforms
  9 + * \brief Flags images that failed to enroll based on the specified transform.
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class FTETransform : public Transform
  13 +{
  14 + Q_OBJECT
  15 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  16 + Q_PROPERTY(float min READ get_min WRITE set_min RESET reset_min)
  17 + Q_PROPERTY(float max READ get_max WRITE set_max RESET reset_max)
  18 + BR_PROPERTY(br::Transform*, transform, NULL)
  19 + BR_PROPERTY(float, min, -std::numeric_limits<float>::max())
  20 + BR_PROPERTY(float, max, std::numeric_limits<float>::max())
  21 +
  22 + void train(const TemplateList &data)
  23 + {
  24 + transform->train(data);
  25 +
  26 + TemplateList projectedData;
  27 + transform->project(data, projectedData);
  28 +
  29 + QList<float> vals;
  30 + foreach (const Template &t, projectedData) {
  31 + if (!t.file.contains(transform->objectName()))
  32 + qFatal("Matrix metadata missing key %s.", qPrintable(transform->objectName()));
  33 + vals.append(t.file.get<float>(transform->objectName()));
  34 + }
  35 + float q1, q3;
  36 + Common::Median(vals, &q1, &q3);
  37 + min = q1 - 1.5 * (q3 - q1);
  38 + max = q3 + 1.5 * (q3 - q1);
  39 + }
  40 +
  41 + void project(const Template &src, Template &dst) const
  42 + {
  43 + Template projectedSrc;
  44 + transform->project(src, projectedSrc);
  45 + const float val = projectedSrc.file.get<float>(transform->objectName());
  46 +
  47 + dst = src;
  48 + dst.file.set(transform->objectName(), val);
  49 + dst.file.set("PossibleFTE", (val < min) || (val > max));
  50 + }
  51 +};
  52 +
  53 +BR_REGISTER(Transform, FTETransform)
  54 +
  55 +} // namespace br
  56 +
  57 +#include "core/fte.moc"
openbr/plugins/distance/gallerycompare.cpp renamed to openbr/plugins/core/gallerycompare.cpp
@@ -61,4 +61,4 @@ BR_REGISTER(Transform, GalleryCompareTransform) @@ -61,4 +61,4 @@ BR_REGISTER(Transform, GalleryCompareTransform)
61 61
62 } // namespace br 62 } // namespace br
63 63
64 -#include "gallerycompare.moc" 64 +#include "core/gallerycompare.moc"
openbr/plugins/core/identity.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief A no-op transform.
  9 + * \see DiscardTransform FirstTransform RestTransform RemoveTransform
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class IdentityTransform : public UntrainableMetaTransform
  13 +{
  14 + Q_OBJECT
  15 +
  16 + void project(const Template &src, Template &dst) const
  17 + {
  18 + dst = src;
  19 + }
  20 +};
  21 +
  22 +BR_REGISTER(Transform, IdentityTransform)
  23 +
  24 +} // namespace br
  25 +
  26 +#include "core/identity.moc"
openbr/plugins/core/independent.cpp
@@ -210,4 +210,4 @@ BR_REGISTER(Transform, IndependentTransform) @@ -210,4 +210,4 @@ BR_REGISTER(Transform, IndependentTransform)
210 210
211 } // namespace br 211 } // namespace br
212 212
213 -#include "independent.moc" 213 +#include "core/independent.moc"
openbr/plugins/jni.cpp renamed to openbr/plugins/core/jni.cpp
1 //Need to include location of jvm.dll (jdk version) and its parent directory in the environment variables 1 //Need to include location of jvm.dll (jdk version) and its parent directory in the environment variables
2 2
3 #include <limits> 3 #include <limits>
4 -#include "openbr_internal.h"  
5 -#include "openbr/core/resource.h" 4 +#include <openbr/plugins/openbr_internal.h>
  5 +#include <openbr/core/resource.h>
6 #include <jni.h> 6 #include <jni.h>
7 7
8 namespace br 8 namespace br
openbr/plugins/likely.cpp renamed to openbr/plugins/core/likely.cpp
1 -#include <likely.h>  
2 -#include <likely/opencv.hpp>  
3 -  
4 -#include "openbr/core/opencvutils.h"  
5 -#include "openbr_internal.h" 1 +#include <openbr/plugins/openbr_internal.h>
6 2
7 namespace br 3 namespace br
8 { 4 {
@@ -57,68 +53,6 @@ public: @@ -57,68 +53,6 @@ public:
57 53
58 BR_REGISTER(Transform, LikelyTransform) 54 BR_REGISTER(Transform, LikelyTransform)
59 55
60 -/*!  
61 - * \ingroup formats  
62 - * \brief Likely matrix format  
63 - *  
64 - * www.liblikely.org  
65 - * \author Josh Klontz \cite jklontz  
66 - */  
67 -class lmatFormat : public Format  
68 -{  
69 - Q_OBJECT  
70 -  
71 - Template read() const  
72 - {  
73 - const likely_const_mat m = likely_read(qPrintable(file.name), likely_file_guess);  
74 - const Template result(likelyToOpenCVMat(m));  
75 - likely_release_mat(m);  
76 - return result;  
77 - }  
78 -  
79 - void write(const Template &t) const  
80 - {  
81 - const likely_const_mat m = likelyFromOpenCVMat(t);  
82 - likely_write(m, qPrintable(file.name));  
83 - likely_release_mat(m);  
84 - }  
85 -};  
86 -  
87 -BR_REGISTER(Format, lmatFormat)  
88 -  
89 -/*!  
90 - * \ingroup formats  
91 - * \brief Likely matrix format  
92 - *  
93 - * www.liblikely.org  
94 - * \author Josh Klontz \cite jklontz  
95 - */  
96 -class lmatGallery : public Gallery  
97 -{  
98 - Q_OBJECT  
99 - QList<cv::Mat> mats;  
100 -  
101 - ~lmatGallery()  
102 - {  
103 - const likely_const_mat m = likelyFromOpenCVMat(OpenCVUtils::toMatByRow(mats));  
104 - likely_write(m, qPrintable(file.name));  
105 - likely_release_mat(m);  
106 - }  
107 -  
108 - TemplateList readBlock(bool *done)  
109 - {  
110 - *done = true;  
111 - qFatal("Not supported.");  
112 - }  
113 -  
114 - void write(const Template &t)  
115 - {  
116 - mats.append(t);  
117 - }  
118 -};  
119 -  
120 -BR_REGISTER(Gallery, lmatGallery)  
121 -  
122 } // namespace br 56 } // namespace br
123 57
124 -#include "likely.moc" 58 +#include "core/likely.moc"
openbr/plugins/core/loadstore.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/qtutils.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup transforms
  9 + * \brief Caches transform training.
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class LoadStoreTransform : public MetaTransform
  13 +{
  14 + Q_OBJECT
  15 + Q_PROPERTY(QString transformString READ get_transformString WRITE set_transformString RESET reset_transformString STORED false)
  16 + Q_PROPERTY(QString fileName READ get_fileName WRITE set_fileName RESET reset_fileName STORED false)
  17 + BR_PROPERTY(QString, transformString, "Identity")
  18 + BR_PROPERTY(QString, fileName, QString())
  19 +
  20 +public:
  21 + Transform *transform;
  22 +
  23 + LoadStoreTransform() : transform(NULL) {}
  24 +
  25 + QString description(bool expanded = false) const
  26 + {
  27 + if (expanded) {
  28 + QString res = transform->description(expanded);
  29 + return res;
  30 + }
  31 + return br::Object::description(expanded);
  32 + }
  33 +
  34 + Transform *simplify(bool &newTForm)
  35 + {
  36 + Transform *res = transform->simplify(newTForm);
  37 + return res;
  38 + }
  39 +
  40 + QList<Object *> getChildren() const
  41 + {
  42 + QList<Object *> rval;
  43 + rval.append(transform);
  44 + return rval;
  45 + }
  46 +private:
  47 +
  48 + void init()
  49 + {
  50 + if (transform != NULL) return;
  51 + if (fileName.isEmpty()) fileName = QRegExp("^[_a-zA-Z0-9]+$").exactMatch(transformString) ? transformString : QtUtils::shortTextHash(transformString);
  52 +
  53 + if (!tryLoad())
  54 + transform = make(transformString);
  55 + else
  56 + trainable = false;
  57 + }
  58 +
  59 + bool timeVarying() const
  60 + {
  61 + return transform->timeVarying();
  62 + }
  63 +
  64 + void train(const QList<TemplateList> &data)
  65 + {
  66 + if (QFileInfo(getFileName()).exists())
  67 + return;
  68 +
  69 + transform->train(data);
  70 +
  71 + qDebug("Storing %s", qPrintable(fileName));
  72 + QtUtils::BlockCompression compressedOut;
  73 + QFile fout(fileName);
  74 + QtUtils::touchDir(fout);
  75 + compressedOut.setBasis(&fout);
  76 +
  77 + QDataStream stream(&compressedOut);
  78 + QString desc = transform->description();
  79 +
  80 + if (!compressedOut.open(QFile::WriteOnly))
  81 + qFatal("Failed to open %s for writing.", qPrintable(file));
  82 +
  83 + stream << desc;
  84 + transform->store(stream);
  85 + compressedOut.close();
  86 + }
  87 +
  88 + void project(const Template &src, Template &dst) const
  89 + {
  90 + transform->project(src, dst);
  91 + }
  92 +
  93 + void project(const TemplateList &src, TemplateList &dst) const
  94 + {
  95 + transform->project(src, dst);
  96 + }
  97 +
  98 + void projectUpdate(const Template &src, Template &dst)
  99 + {
  100 + transform->projectUpdate(src, dst);
  101 + }
  102 +
  103 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  104 + {
  105 + transform->projectUpdate(src, dst);
  106 + }
  107 +
  108 + void finalize(TemplateList &output)
  109 + {
  110 + transform->finalize(output);
  111 + }
  112 +
  113 + QString getFileName() const
  114 + {
  115 + if (QFileInfo(fileName).exists()) return fileName;
  116 + const QString file = Globals->sdkPath + "/share/openbr/models/transforms/" + fileName;
  117 + return QFileInfo(file).exists() ? file : QString();
  118 + }
  119 +
  120 + bool tryLoad()
  121 + {
  122 + const QString file = getFileName();
  123 + if (file.isEmpty()) return false;
  124 +
  125 + qDebug("Loading %s", qPrintable(file));
  126 + QFile fin(file);
  127 + QtUtils::BlockCompression reader(&fin);
  128 + if (!reader.open(QIODevice::ReadOnly)) {
  129 + if (QFileInfo(file).exists()) qFatal("Unable to open %s for reading. Check file permissions.", qPrintable(file));
  130 + else qFatal("Unable to open %s for reading. File does not exist.", qPrintable(file));
  131 + }
  132 +
  133 + QDataStream stream(&reader);
  134 + stream >> transformString;
  135 +
  136 + transform = Transform::make(transformString);
  137 + transform->load(stream);
  138 +
  139 + return true;
  140 + }
  141 +};
  142 +
  143 +BR_REGISTER(Transform, LoadStoreTransform)
  144 +
  145 +} // namespace br
  146 +
  147 +#include "core/loadstore.moc"
openbr/plugins/core/pipe.cpp 0 → 100644
  1 +#include <QtConcurrent>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup Transforms
  10 + * \brief Transforms in series.
  11 + * \author Josh Klontz \cite jklontz
  12 + *
  13 + * The source br::Template is given to the first transform and the resulting br::Template is passed to the next transform, etc.
  14 + *
  15 + * \see ExpandTransform
  16 + * \see ForkTransform
  17 + */
  18 +class PipeTransform : public CompositeTransform
  19 +{
  20 + Q_OBJECT
  21 +
  22 + void _projectPartial(TemplateList *srcdst, int startIndex, int stopIndex)
  23 + {
  24 + TemplateList ftes;
  25 + for (int i=startIndex; i<stopIndex; i++) {
  26 + TemplateList res;
  27 + transforms[i]->project(*srcdst, res);
  28 +
  29 + splitFTEs(res, ftes);
  30 + *srcdst = res;
  31 + }
  32 + }
  33 +
  34 + void train(const QList<TemplateList> &data)
  35 + {
  36 + if (!trainable) return;
  37 +
  38 + QList<TemplateList> dataLines(data);
  39 +
  40 + int i = 0;
  41 + while (i < transforms.size()) {
  42 + // Conditional statement covers likely case that first transform is untrainable
  43 + if (transforms[i]->trainable) {
  44 + qDebug() << "Training " << transforms[i]->description() << "\n...";
  45 + transforms[i]->train(dataLines);
  46 + }
  47 +
  48 + // if the transform is time varying, we can't project it in parallel
  49 + if (transforms[i]->timeVarying()) {
  50 + qDebug() << "Projecting " << transforms[i]->description() << "\n...";
  51 + for (int j=0; j < dataLines.size();j++) {
  52 + TemplateList junk;
  53 + splitFTEs(dataLines[j], junk);
  54 +
  55 + transforms[i]->projectUpdate(dataLines[j], dataLines[j]);
  56 + }
  57 +
  58 + // advance i since we already projected for this stage.
  59 + i++;
  60 +
  61 + // the next stage might be trainable, so continue to evaluate it.
  62 + continue;
  63 + }
  64 +
  65 + // We project through any subsequent untrainable transforms at once
  66 + // as a memory optimization in case any of these intermediate
  67 + // transforms allocate a lot of memory (like OpenTransform)
  68 + // then we don't want all the training templates to be processed
  69 + // by that transform at once if we can avoid it.
  70 + int nextTrainableTransform = i+1;
  71 + while ((nextTrainableTransform < transforms.size()) &&
  72 + !transforms[nextTrainableTransform]->trainable &&
  73 + !transforms[nextTrainableTransform]->timeVarying())
  74 + nextTrainableTransform++;
  75 +
  76 + // No more trainable transforms? Don't need any more projects then
  77 + if (nextTrainableTransform == transforms.size())
  78 + break;
  79 +
  80 + fprintf(stderr, "Projecting %s", qPrintable(transforms[i]->description()));
  81 + for (int j=i+1; j < nextTrainableTransform; j++)
  82 + fprintf(stderr,"+%s", qPrintable(transforms[j]->description()));
  83 + fprintf(stderr, "\n...\n");
  84 + fflush(stderr);
  85 +
  86 + QFutureSynchronizer<void> futures;
  87 + for (int j=0; j < dataLines.size(); j++)
  88 + futures.addFuture(QtConcurrent::run(this, &PipeTransform::_projectPartial, &dataLines[j], i, nextTrainableTransform));
  89 + futures.waitForFinished();
  90 +
  91 + i = nextTrainableTransform;
  92 + }
  93 + }
  94 +
  95 + void projectUpdate(const Template &src, Template &dst)
  96 + {
  97 + dst = src;
  98 + foreach (Transform *f, transforms) {
  99 + try {
  100 + f->projectUpdate(dst);
  101 + if (dst.file.fte)
  102 + break;
  103 + } catch (...) {
  104 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  105 + dst = Template(src.file);
  106 + dst.file.fte = true;
  107 + break;
  108 + }
  109 + }
  110 + }
  111 +
  112 + // For time varying transforms, parallel execution over individual templates
  113 + // won't work.
  114 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  115 + {
  116 + TemplateList ftes;
  117 + dst = src;
  118 + foreach (Transform *f, transforms) {
  119 + TemplateList res;
  120 + f->projectUpdate(dst, res);
  121 + splitFTEs(res, ftes);
  122 + dst = res;
  123 + }
  124 + dst.append(ftes);
  125 + }
  126 +
  127 + virtual void finalize(TemplateList &output)
  128 + {
  129 + output.clear();
  130 + // For each transform,
  131 + for (int i = 0; i < transforms.size(); i++)
  132 + {
  133 +
  134 + // Collect any final templates
  135 + TemplateList last_set;
  136 + transforms[i]->finalize(last_set);
  137 + if (last_set.empty())
  138 + continue;
  139 + // Push any templates received through the remaining transforms in the sequence
  140 + for (int j = (i+1); j < transforms.size();j++)
  141 + {
  142 + transforms[j]->projectUpdate(last_set);
  143 + }
  144 + // append the result to the output set
  145 + output.append(last_set);
  146 + }
  147 + }
  148 +
  149 + void init()
  150 + {
  151 + QList<Transform *> flattened;
  152 + for (int i=0;i < transforms.size(); i++)
  153 + {
  154 + PipeTransform *probe = dynamic_cast<PipeTransform *> (transforms[i]);
  155 + if (!probe) {
  156 + flattened.append(transforms[i]);
  157 + continue;
  158 + }
  159 + for (int j=0; j < probe->transforms.size(); j++)
  160 + flattened.append(probe->transforms[j]);
  161 + }
  162 + transforms = flattened;
  163 +
  164 + CompositeTransform::init();
  165 + }
  166 +
  167 +protected:
  168 + // Template list project -- process templates in parallel through Transform::project
  169 + // or if parallelism is disabled, handle them sequentially
  170 + void _project(const TemplateList &src, TemplateList &dst) const
  171 + {
  172 + TemplateList ftes;
  173 + dst = src;
  174 + foreach (const Transform *f, transforms) {
  175 + TemplateList res;
  176 + f->project(dst, res);
  177 + splitFTEs(res, ftes);
  178 + dst = res;
  179 + }
  180 + dst.append(ftes);
  181 + }
  182 +
  183 + // Single template const project, pass the template through each sub-transform, one after the other
  184 + virtual void _project(const Template &src, Template &dst) const
  185 + {
  186 + dst = src;
  187 + foreach (const Transform *f, transforms) {
  188 + try {
  189 + dst >> *f;
  190 + if (dst.file.fte)
  191 + break;
  192 + } catch (...) {
  193 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  194 + dst = Template(src.file);
  195 + dst.file.fte = true;
  196 + }
  197 + }
  198 + }
  199 +};
  200 +
  201 +BR_REGISTER(Transform, PipeTransform)
  202 +
  203 +} // namespace br
  204 +
  205 +#include "core/pipe.moc"
openbr/plugins/process.cpp renamed to openbr/plugins/core/processwrapper.cpp
@@ -9,8 +9,8 @@ @@ -9,8 +9,8 @@
9 #include <QUuid> 9 #include <QUuid>
10 #include <QWaitCondition> 10 #include <QWaitCondition>
11 11
12 -#include "openbr_internal.h"  
13 -#include "openbr/core/opencvutils.h" 12 +#include <openbr/plugins/openbr_internal.h>
  13 +#include <openbr/core/opencvutils.h>
14 14
15 using namespace cv; 15 using namespace cv;
16 16
@@ -658,4 +658,4 @@ BR_REGISTER(Transform, ProcessWrapperTransform) @@ -658,4 +658,4 @@ BR_REGISTER(Transform, ProcessWrapperTransform)
658 658
659 } 659 }
660 660
661 -#include "process.moc" 661 +#include "core/processwrapper.moc"
openbr/plugins/core/progresscounter.cpp 0 → 100644
  1 +#include <QElapsedTimer>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/qtutils.h>
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +class ProgressCounterTransform : public TimeVaryingTransform
  10 +{
  11 + Q_OBJECT
  12 +
  13 + Q_PROPERTY(qint64 totalProgress READ get_totalProgress WRITE set_totalProgress RESET reset_totalProgress STORED false)
  14 + BR_PROPERTY(qint64, totalProgress, 1)
  15 +
  16 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  17 + {
  18 + dst = src;
  19 +
  20 + qint64 elapsed = timer.elapsed();
  21 + int last_frame = -2;
  22 + if (!dst.empty()) {
  23 + for (int i=0;i < dst.size();i++) {
  24 + int frame = dst[i].file.get<int>("FrameNumber", -1);
  25 + if (frame == last_frame && frame != -1)
  26 + continue;
  27 +
  28 + // Use 1 as the starting index for progress output
  29 + Globals->currentProgress = dst[i].file.get<qint64>("progress",0)+1;
  30 + dst[i].file.remove("progress");
  31 + last_frame = frame;
  32 +
  33 + Globals->currentStep++;
  34 + }
  35 + }
  36 +
  37 + // updated every second
  38 + if (elapsed > 1000) {
  39 + Globals->printStatus();
  40 + timer.start();
  41 + }
  42 +
  43 + return;
  44 + }
  45 +
  46 + void train(const TemplateList& data)
  47 + {
  48 + (void) data;
  49 + }
  50 +
  51 + void finalize(TemplateList &data)
  52 + {
  53 + (void) data;
  54 + float p = br_progress();
  55 + qDebug("\r%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(0).toStdString().c_str(), Globals->currentStep);
  56 + timer.start();
  57 + Globals->startTime.start();
  58 + Globals->currentStep = 0;
  59 + Globals->currentProgress = 0;
  60 + Globals->totalSteps = totalProgress;
  61 + }
  62 +
  63 + void init()
  64 + {
  65 + timer.start();
  66 + Globals->startTime.start();
  67 + Globals->currentProgress = 0;
  68 + Globals->currentStep = 0;
  69 + Globals->totalSteps = totalProgress;
  70 + }
  71 +
  72 +public:
  73 + ProgressCounterTransform() : TimeVaryingTransform(false,false) {}
  74 + QElapsedTimer timer;
  75 +};
  76 +
  77 +BR_REGISTER(Transform, ProgressCounterTransform)
  78 +
  79 +} // namespace br
  80 +
  81 +#include "core/progresscounter.moc"
openbr/plugins/core/registrar.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup initializers
  8 + * \brief Register custom objects with Qt meta object system.
  9 + * \author Charles Otto \cite caotto
  10 + */
  11 +class Registrar : public Initializer
  12 +{
  13 + Q_OBJECT
  14 +
  15 + void initialize() const
  16 + {
  17 + qRegisterMetaType<br::Neighbors>();
  18 + }
  19 +};
  20 +
  21 +BR_REGISTER(Initializer, Registrar)
  22 +
  23 +} // namespace br
  24 +
  25 +#include "core/registrar.moc"
openbr/plugins/core/remove.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Removes the matrix from the template at the specified index.
  9 + * \author Josh Klontz \cite jklontz
  10 + * \see IdentityTransform DiscardTransform FirstTransform RestTransform
  11 + */
  12 +//! [example_transform]
  13 +class RemoveTransform : public UntrainableMetaTransform
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(int index READ get_index WRITE set_index RESET reset_index STORED false)
  17 + BR_PROPERTY(int, index, 0)
  18 +
  19 + void project(const Template &src, Template &dst) const
  20 + {
  21 + dst = src;
  22 + dst.removeAt(index);
  23 + }
  24 +};
  25 +
  26 +BR_REGISTER(Transform, RemoveTransform)
  27 +//! [example_transform]
  28 +
  29 +} // namespace br
  30 +
  31 +#include "core/remove.moc"
openbr/plugins/core/rest.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Removes the first matrix from the template.
  9 + * \see IdentityTransform DiscardTransform FirstTransform RemoveTransform
  10 + * \author Josh Klontz \cite jklontz
  11 + */
  12 +class RestTransform : public UntrainableMetaTransform
  13 +{
  14 + Q_OBJECT
  15 +
  16 + void project(const Template &src, Template &dst) const
  17 + {
  18 + dst = src;
  19 + dst.removeFirst();
  20 + }
  21 +};
  22 +
  23 +BR_REGISTER(Transform, RestTransform)
  24 +
  25 +} // namespace br
  26 +
  27 +#include "core/rest.moc"
openbr/plugins/core/schrodinger.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Generates two templates, one of which is passed through a transform and the other
  9 + * is not. No cats were harmed in the making of this transform.
  10 + * \author Scott Klum \cite sklum
  11 + */
  12 +class SchrodingerTransform : public MetaTransform
  13 +{
  14 + Q_OBJECT
  15 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  16 + BR_PROPERTY(br::Transform*, transform, NULL)
  17 +
  18 +public:
  19 + void train(const TemplateList &data)
  20 + {
  21 + transform->train(data);
  22 + }
  23 +
  24 + void project(const TemplateList &src, TemplateList &dst) const
  25 + {
  26 + foreach(const Template &t, src) {
  27 + dst.append(t);
  28 + Template u;
  29 + transform->project(t,u);
  30 + dst.append(u);
  31 + }
  32 + }
  33 +
  34 + void project(const Template &src, Template &dst) const {
  35 + TemplateList temp;
  36 + project(TemplateList() << src, temp);
  37 + if (!temp.isEmpty()) dst = temp.first();
  38 + }
  39 +
  40 +};
  41 +BR_REGISTER(Transform, SchrodingerTransform)
  42 +
  43 +} // namespace br
  44 +
  45 +#include "core/schrodinger.moc"
openbr/plugins/core/singleton.cpp
@@ -70,4 +70,4 @@ BR_REGISTER(Transform, SingletonTransform) @@ -70,4 +70,4 @@ BR_REGISTER(Transform, SingletonTransform)
70 70
71 } // namespace br 71 } // namespace br
72 72
73 -#include "singleton.moc" 73 +#include "core/singleton.moc"
openbr/plugins/stream.cpp renamed to openbr/plugins/core/stream.cpp
@@ -8,10 +8,11 @@ @@ -8,10 +8,11 @@
8 #include <QtConcurrent> 8 #include <QtConcurrent>
9 #include <opencv/highgui.h> 9 #include <opencv/highgui.h>
10 #include <opencv2/highgui/highgui.hpp> 10 #include <opencv2/highgui/highgui.hpp>
11 -#include "openbr_internal.h"  
12 -#include "openbr/core/common.h"  
13 -#include "openbr/core/opencvutils.h"  
14 -#include "openbr/core/qtutils.h" 11 +
  12 +#include <openbr/plugins/openbr_internal.h>
  13 +#include <openbr/core/common.h>
  14 +#include <openbr/core/opencvutils.h>
  15 +#include <openbr/core/qtutils.h>
15 16
16 using namespace cv; 17 using namespace cv;
17 using namespace std; 18 using namespace std;
@@ -1360,5 +1361,5 @@ BR_REGISTER(Transform, StreamTransform) @@ -1360,5 +1361,5 @@ BR_REGISTER(Transform, StreamTransform)
1360 1361
1361 } // namespace br 1362 } // namespace br
1362 1363
1363 -#include "stream.moc" 1364 +#include "core/stream.moc"
1364 1365
openbr/plugins/distance/L2.cpp
@@ -27,4 +27,4 @@ BR_REGISTER(Distance, L2Distance) @@ -27,4 +27,4 @@ BR_REGISTER(Distance, L2Distance)
27 27
28 } // namespace br 28 } // namespace br
29 29
30 -#include "L2.moc" 30 +#include "distance/L2.moc"
openbr/plugins/distance/attribute.cpp
@@ -31,4 +31,4 @@ BR_REGISTER(Distance, AttributeDistance) @@ -31,4 +31,4 @@ BR_REGISTER(Distance, AttributeDistance)
31 31
32 } // namespace br 32 } // namespace br
33 33
34 -#include "attribute.moc" 34 +#include "distance/attribute.moc"
openbr/plugins/distance/bayesianquantization.cpp 0 → 100644
  1 +#include <QtConcurrent>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/opencvutils.h>
  5 +
  6 +using namespace cv;
  7 +
  8 +namespace br
  9 +{
  10 +
  11 +/*!
  12 + * \ingroup distances
  13 + * \brief Bayesian quantization distance
  14 + * \author Josh Klontz \cite jklontz
  15 + */
  16 +class BayesianQuantizationDistance : public Distance
  17 +{
  18 + Q_OBJECT
  19 +
  20 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  21 + BR_PROPERTY(QString, inputVariable, "Label")
  22 +
  23 + QVector<float> loglikelihoods;
  24 +
  25 + static void computeLogLikelihood(const Mat &data, const QList<int> &labels, float *loglikelihood)
  26 + {
  27 + const QList<uchar> vals = OpenCVUtils::matrixToVector<uchar>(data);
  28 + if (vals.size() != labels.size())
  29 + qFatal("Logic error.");
  30 +
  31 + QVector<quint64> genuines(256, 0), impostors(256,0);
  32 + for (int i=0; i<vals.size(); i++)
  33 + for (int j=i+1; j<vals.size(); j++)
  34 + if (labels[i] == labels[j]) genuines[abs(vals[i]-vals[j])]++;
  35 + else impostors[abs(vals[i]-vals[j])]++;
  36 +
  37 + quint64 totalGenuines(0), totalImpostors(0);
  38 + for (int i=0; i<256; i++) {
  39 + totalGenuines += genuines[i];
  40 + totalImpostors += impostors[i];
  41 + }
  42 +
  43 + for (int i=0; i<256; i++)
  44 + loglikelihood[i] = log((float(genuines[i]+1)/totalGenuines)/(float(impostors[i]+1)/totalImpostors));
  45 + }
  46 +
  47 + void train(const TemplateList &src)
  48 + {
  49 + if ((src.first().size() > 1) || (src.first().m().type() != CV_8UC1))
  50 + qFatal("Expected sigle matrix templates of type CV_8UC1!");
  51 +
  52 + const Mat data = OpenCVUtils::toMat(src.data());
  53 + const QList<int> templateLabels = src.indexProperty(inputVariable);
  54 + loglikelihoods = QVector<float>(data.cols*256, 0);
  55 +
  56 + QFutureSynchronizer<void> futures;
  57 + for (int i=0; i<data.cols; i++)
  58 + futures.addFuture(QtConcurrent::run(&BayesianQuantizationDistance::computeLogLikelihood, data.col(i), templateLabels, &loglikelihoods.data()[i*256]));
  59 + futures.waitForFinished();
  60 + }
  61 +
  62 + float compare(const cv::Mat &a, const cv::Mat &b) const
  63 + {
  64 + const uchar *aData = a.data;
  65 + const uchar *bData = b.data;
  66 + const int size = a.rows * a.cols;
  67 + float likelihood = 0;
  68 + for (int i=0; i<size; i++)
  69 + likelihood += loglikelihoods[i*256+abs(aData[i]-bData[i])];
  70 + return likelihood;
  71 + }
  72 +
  73 + void store(QDataStream &stream) const
  74 + {
  75 + stream << loglikelihoods;
  76 + }
  77 +
  78 + void load(QDataStream &stream)
  79 + {
  80 + stream >> loglikelihoods;
  81 + }
  82 +};
  83 +
  84 +BR_REGISTER(Distance, BayesianQuantizationDistance)
  85 +
  86 +} // namespace br
  87 +
  88 +#include "distance/bayesianquantization.moc"
openbr/plugins/distance/byteL1.cpp
@@ -23,4 +23,4 @@ BR_REGISTER(Distance, ByteL1Distance) @@ -23,4 +23,4 @@ BR_REGISTER(Distance, ByteL1Distance)
23 23
24 } // namespace br 24 } // namespace br
25 25
26 -#include "byteL1.moc" 26 +#include "distance/byteL1.moc"
openbr/plugins/distance/crossvalidate.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief Cross validate a distance metric.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class CrossValidateDistance : public UntrainableDistance
  12 +{
  13 + Q_OBJECT
  14 +
  15 + float compare(const Template &a, const Template &b) const
  16 + {
  17 + static const QString key("Partition"); // More efficient to preallocate this
  18 + const int partitionA = a.file.get<int>(key, 0);
  19 + const int partitionB = b.file.get<int>(key, 0);
  20 + return (partitionA != partitionB) ? -std::numeric_limits<float>::max() : 0;
  21 + }
  22 +};
  23 +
  24 +BR_REGISTER(Distance, CrossValidateDistance)
  25 +
  26 +} // namespace br
  27 +
  28 +#include "distance/crossvalidate.moc"
openbr/plugins/distance/default.cpp
@@ -28,4 +28,4 @@ BR_REGISTER(Distance, DefaultDistance) @@ -28,4 +28,4 @@ BR_REGISTER(Distance, DefaultDistance)
28 28
29 } // namespace br 29 } // namespace br
30 30
31 -#include "default.moc" 31 +#include "distance/default.moc"
openbr/plugins/distance/dist.cpp
@@ -101,4 +101,4 @@ BR_REGISTER(Distance, DistDistance) @@ -101,4 +101,4 @@ BR_REGISTER(Distance, DistDistance)
101 101
102 } // namespace br 102 } // namespace br
103 103
104 -#include "dist.moc" 104 +#include "distance/dist.moc"
openbr/plugins/distance/filter.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief Checks target metadata against filters.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class FilterDistance : public UntrainableDistance
  12 +{
  13 + Q_OBJECT
  14 +
  15 + float compare(const Template &a, const Template &b) const
  16 + {
  17 + (void) b; // Query template isn't checked
  18 + foreach (const QString &key, Globals->filters.keys()) {
  19 + bool keep = false;
  20 + const QString metadata = a.file.get<QString>(key, "");
  21 + if (Globals->filters[key].isEmpty()) continue;
  22 + if (metadata.isEmpty()) return -std::numeric_limits<float>::max();
  23 + foreach (const QString &value, Globals->filters[key]) {
  24 + if (metadata == value) {
  25 + keep = true;
  26 + break;
  27 + }
  28 + }
  29 + if (!keep) return -std::numeric_limits<float>::max();
  30 + }
  31 + return 0;
  32 + }
  33 +};
  34 +
  35 +BR_REGISTER(Distance, FilterDistance)
  36 +
  37 +} // namespace br
  38 +
  39 +#include "distance/filter.moc"
openbr/plugins/distance/fuse.cpp
@@ -98,4 +98,4 @@ BR_REGISTER(Distance, FuseDistance) @@ -98,4 +98,4 @@ BR_REGISTER(Distance, FuseDistance)
98 98
99 } // namespace br 99 } // namespace br
100 100
101 -#include "fuse.moc" 101 +#include "distance/fuse.moc"
openbr/plugins/distance/halfbyteL1.cpp
@@ -26,4 +26,4 @@ BR_REGISTER(Distance, HalfByteL1Distance) @@ -26,4 +26,4 @@ BR_REGISTER(Distance, HalfByteL1Distance)
26 26
27 } // namespace br 27 } // namespace br
28 28
29 -#include "halfbyteL1.moc" 29 +#include "distance/halfbyteL1.moc"
openbr/plugins/distance/heatmap.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief 1v1 heat map comparison
  9 + * \author Scott Klum \cite sklum
  10 + */
  11 +class HeatMapDistance : public Distance
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
  15 + Q_PROPERTY(int step READ get_step WRITE set_step RESET reset_step STORED false)
  16 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  17 + BR_PROPERTY(QString, description, "IdenticalDistance")
  18 + BR_PROPERTY(int, step, 1)
  19 + BR_PROPERTY(QString, inputVariable, "Label")
  20 +
  21 + QList<br::Distance*> distances;
  22 +
  23 + void train(const TemplateList &src)
  24 + {
  25 + QList<TemplateList> patches;
  26 +
  27 + // Split src into list of TemplateLists of corresponding patches across all Templates
  28 + for (int i=0; i<step; i++) {
  29 + TemplateList patchBuffer;
  30 + for (int j=0; j<src.size(); j++)
  31 + patchBuffer.append(Template(src[j].file, src[j][i]));
  32 + patches.append(patchBuffer);
  33 + patchBuffer.clear();
  34 + }
  35 +
  36 + while (distances.size() < patches.size())
  37 + distances.append(make(description));
  38 +
  39 + // Train on a distance for each patch
  40 + for (int i=0; i<distances.size(); i++)
  41 + distances[i]->train(patches[i]);
  42 + }
  43 +
  44 + float compare(const cv::Mat &target, const cv::Mat &query) const
  45 + {
  46 + (void) target;
  47 + (void) query;
  48 + qFatal("Heatmap Distance not compatible with Template to Template comparison.");
  49 +
  50 + return 0;
  51 + }
  52 +
  53 + void compare(const TemplateList &target, const TemplateList &query, Output *output) const
  54 + {
  55 + for (int i=0; i<target.size(); i++) {
  56 + if (target[i].size() != step || query[i].size() != step) qFatal("Heatmap step not equal to the number of patches.");
  57 + for (int j=0; j<step; j++)
  58 + output->setRelative(distances[j]->compare(target[i][j],query[i][j]), j, 0);
  59 + }
  60 + }
  61 +
  62 + void store(QDataStream &stream) const
  63 + {
  64 + stream << distances.size();
  65 + foreach (Distance *distance, distances)
  66 + distance->store(stream);
  67 + }
  68 +
  69 + void load(QDataStream &stream)
  70 + {
  71 + int numDistances;
  72 + stream >> numDistances;
  73 + while (distances.size() < numDistances)
  74 + distances.append(make(description));
  75 + foreach (Distance *distance, distances)
  76 + distance->load(stream);
  77 + }
  78 +};
  79 +
  80 +BR_REGISTER(Distance, HeatMapDistance)
  81 +
  82 +} // namespace br
  83 +
  84 +#include "distance/heatmap.moc"
openbr/plugins/distance/identical.cpp
@@ -28,4 +28,4 @@ BR_REGISTER(Distance, IdenticalDistance) @@ -28,4 +28,4 @@ BR_REGISTER(Distance, IdenticalDistance)
28 28
29 } // namespace br 29 } // namespace br
30 30
31 -#include "identical.moc" 31 +#include "distance/identical.moc"
openbr/plugins/distance/keypointmatcher.cpp
@@ -55,4 +55,4 @@ BR_REGISTER(Distance, KeyPointMatcherDistance) @@ -55,4 +55,4 @@ BR_REGISTER(Distance, KeyPointMatcherDistance)
55 55
56 } // namespace br 56 } // namespace br
57 57
58 -#include "keypointmatcher.moc" 58 +#include "distance/keypointmatcher.moc"
openbr/plugins/distance/l1.cpp
@@ -27,4 +27,4 @@ BR_REGISTER(Distance, L1Distance) @@ -27,4 +27,4 @@ BR_REGISTER(Distance, L1Distance)
27 27
28 } // namespace br 28 } // namespace br
29 29
30 -#include "L1.moc" 30 +#include "distance/L1.moc"
openbr/plugins/quality.cpp renamed to openbr/plugins/distance/matchprobability.cpp
1 -#include <QFutureSynchronizer>  
2 #include <QtConcurrent> 1 #include <QtConcurrent>
3 -#include "openbr_internal.h"  
4 2
5 -#include "openbr/core/common.h"  
6 -#include "openbr/core/opencvutils.h" 3 +#include <openbr/plugins/openbr_internal.h>
  4 +#include <openbr/core/common.h>
7 5
8 namespace br 6 namespace br
9 { 7 {
10 8
11 -/*!  
12 - * \ingroup transforms  
13 - * \brief Impostor Uniqueness Measure \cite klare12  
14 - * \author Josh Klontz \cite jklontz  
15 - */  
16 -class ImpostorUniquenessMeasureTransform : public Transform  
17 -{  
18 - Q_OBJECT  
19 - Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)  
20 - Q_PROPERTY(double mean READ get_mean WRITE set_mean RESET reset_mean)  
21 - Q_PROPERTY(double stddev READ get_stddev WRITE set_stddev RESET reset_stddev)  
22 - Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)  
23 - BR_PROPERTY(br::Distance*, distance, Distance::make("Dist(L2)", this))  
24 - BR_PROPERTY(double, mean, 0)  
25 - BR_PROPERTY(double, stddev, 1)  
26 - BR_PROPERTY(QString, inputVariable, "Label")  
27 -  
28 - TemplateList impostors;  
29 -  
30 - float calculateIUM(const Template &probe, const TemplateList &gallery) const  
31 - {  
32 - const QString probeLabel = probe.file.get<QString>(inputVariable);  
33 - TemplateList subset = gallery;  
34 - for (int j=subset.size()-1; j>=0; j--)  
35 - if (subset[j].file.get<QString>(inputVariable) == probeLabel)  
36 - subset.removeAt(j);  
37 -  
38 - QList<float> scores = distance->compare(subset, probe);  
39 - float min, max;  
40 - Common::MinMax(scores, &min, &max);  
41 - double mean = Common::Mean(scores);  
42 - return (max-mean)/(max-min);  
43 - }  
44 -  
45 - void train(const TemplateList &data)  
46 - {  
47 - distance->train(data);  
48 - impostors = data;  
49 -  
50 - QList<float> iums; iums.reserve(impostors.size());  
51 - for (int i=0; i<data.size(); i++)  
52 - iums.append(calculateIUM(impostors[i], impostors));  
53 -  
54 - Common::MeanStdDev(iums, &mean, &stddev);  
55 - }  
56 -  
57 - void project(const Template &src, Template &dst) const  
58 - {  
59 - dst = src;  
60 - float ium = calculateIUM(src, impostors);  
61 - dst.file.set("Impostor_Uniqueness_Measure", ium);  
62 - dst.file.set("Impostor_Uniqueness_Measure_Bin", ium < mean-stddev ? 0 : (ium < mean+stddev ? 1 : 2));  
63 - }  
64 -  
65 - void store(QDataStream &stream) const  
66 - {  
67 - distance->store(stream);  
68 - stream << mean << stddev << impostors;  
69 - }  
70 -  
71 - void load(QDataStream &stream)  
72 - {  
73 - distance->load(stream);  
74 - stream >> mean >> stddev >> impostors;  
75 - }  
76 -};  
77 -  
78 -BR_REGISTER(Transform, ImpostorUniquenessMeasureTransform)  
79 -  
80 -  
81 float KDEPointer(const QList<float> *scores, double x, double h) 9 float KDEPointer(const QList<float> *scores, double x, double h)
82 { 10 {
83 return Common::KernelDensityEstimation(*scores, x, h); 11 return Common::KernelDensityEstimation(*scores, x, h);
@@ -119,7 +47,7 @@ struct KDE @@ -119,7 +47,7 @@ struct KDE
119 if (gaussian) return 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((score-mean)/stddev, 2)); 47 if (gaussian) return 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((score-mean)/stddev, 2));
120 if (bins.empty()) 48 if (bins.empty())
121 return -std::numeric_limits<float>::max(); 49 return -std::numeric_limits<float>::max();
122 - 50 +
123 if (score <= min) return bins.first(); 51 if (score <= min) return bins.first();
124 if (score >= max) return bins.last(); 52 if (score >= max) return bins.last();
125 const float x = (score-min)/(max-min)*bins.size(); 53 const float x = (score-min)/(max-min)*bins.size();
@@ -186,7 +114,7 @@ class MatchProbabilityDistance : public Distance @@ -186,7 +114,7 @@ class MatchProbabilityDistance : public Distance
186 const QList<int> labels = src.indexProperty(inputVariable); 114 const QList<int> labels = src.indexProperty(inputVariable);
187 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size()))); 115 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));
188 distance->compare(src, src, matrixOutput.data()); 116 distance->compare(src, src, matrixOutput.data());
189 - 117 +
190 QList<float> genuineScores, impostorScores; 118 QList<float> genuineScores, impostorScores;
191 genuineScores.reserve(labels.size()); 119 genuineScores.reserve(labels.size());
192 impostorScores.reserve(labels.size()*labels.size()); 120 impostorScores.reserve(labels.size()*labels.size());
@@ -199,7 +127,7 @@ class MatchProbabilityDistance : public Distance @@ -199,7 +127,7 @@ class MatchProbabilityDistance : public Distance
199 else impostorScores.append(score); 127 else impostorScores.append(score);
200 } 128 }
201 } 129 }
202 - 130 +
203 mp = MP(genuineScores, impostorScores, !gaussian); 131 mp = MP(genuineScores, impostorScores, !gaussian);
204 } 132 }
205 133
@@ -246,204 +174,6 @@ protected: @@ -246,204 +174,6 @@ protected:
246 174
247 BR_REGISTER(Distance, MatchProbabilityDistance) 175 BR_REGISTER(Distance, MatchProbabilityDistance)
248 176
249 -class ZScoreDistance : public Distance  
250 -{  
251 - Q_OBJECT  
252 - Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)  
253 - Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false)  
254 - BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))  
255 - BR_PROPERTY(bool, crossModality, false)  
256 -  
257 - float min, max;  
258 - double mean, stddev;  
259 -  
260 - void train(const TemplateList &src)  
261 - {  
262 - distance->train(src);  
263 -  
264 - QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));  
265 - distance->compare(src, src, matrixOutput.data());  
266 -  
267 - QList<float> scores;  
268 - scores.reserve(src.size()*src.size());  
269 - for (int i=0; i<src.size(); i++) {  
270 - for (int j=0; j<i; j++) {  
271 - const float score = matrixOutput.data()->data.at<float>(i, j);  
272 - if (score == -std::numeric_limits<float>::max()) continue;  
273 - if (crossModality && src[i].file.get<QString>("MODALITY") == src[j].file.get<QString>("MODALITY")) continue;  
274 - scores.append(score);  
275 - }  
276 - }  
277 -  
278 - Common::MinMax(scores, &min, &max);  
279 - Common::MeanStdDev(scores, &mean, &stddev);  
280 -  
281 - if (stddev == 0) qFatal("Stddev is 0.");  
282 - }  
283 -  
284 - float compare(const Template &target, const Template &query) const  
285 - {  
286 - float score = distance->compare(target,query);  
287 - if (score == -std::numeric_limits<float>::max()) score = (min - mean) / stddev;  
288 - else if (score == std::numeric_limits<float>::max()) score = (max - mean) / stddev;  
289 - else score = (score - mean) / stddev;  
290 - return score;  
291 - }  
292 -  
293 - void store(QDataStream &stream) const  
294 - {  
295 - distance->store(stream);  
296 - stream << min << max << mean << stddev;  
297 - }  
298 -  
299 - void load(QDataStream &stream)  
300 - {  
301 - distance->load(stream);  
302 - stream >> min >> max >> mean >> stddev;  
303 - }  
304 -};  
305 -  
306 -BR_REGISTER(Distance, ZScoreDistance)  
307 -  
308 -/*!  
309 - * \ingroup distances  
310 - * \brief 1v1 heat map comparison  
311 - * \author Scott Klum \cite sklum  
312 - */  
313 -class HeatMapDistance : public Distance  
314 -{  
315 - Q_OBJECT  
316 - Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)  
317 - Q_PROPERTY(int step READ get_step WRITE set_step RESET reset_step STORED false)  
318 - Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)  
319 - BR_PROPERTY(QString, description, "IdenticalDistance")  
320 - BR_PROPERTY(int, step, 1)  
321 - BR_PROPERTY(QString, inputVariable, "Label")  
322 -  
323 - QList<br::Distance*> distances;  
324 -  
325 - void train(const TemplateList &src)  
326 - {  
327 - QList<TemplateList> patches;  
328 -  
329 - // Split src into list of TemplateLists of corresponding patches across all Templates  
330 - for (int i=0; i<step; i++) {  
331 - TemplateList patchBuffer;  
332 - for (int j=0; j<src.size(); j++)  
333 - patchBuffer.append(Template(src[j].file, src[j][i]));  
334 - patches.append(patchBuffer);  
335 - patchBuffer.clear();  
336 - }  
337 -  
338 - while (distances.size() < patches.size())  
339 - distances.append(make(description));  
340 -  
341 - // Train on a distance for each patch  
342 - for (int i=0; i<distances.size(); i++)  
343 - distances[i]->train(patches[i]);  
344 - }  
345 -  
346 - float compare(const cv::Mat &target, const cv::Mat &query) const  
347 - {  
348 - (void) target;  
349 - (void) query;  
350 - qFatal("Heatmap Distance not compatible with Template to Template comparison.");  
351 -  
352 - return 0;  
353 - }  
354 -  
355 - void compare(const TemplateList &target, const TemplateList &query, Output *output) const  
356 - {  
357 - for (int i=0; i<target.size(); i++) {  
358 - if (target[i].size() != step || query[i].size() != step) qFatal("Heatmap step not equal to the number of patches.");  
359 - for (int j=0; j<step; j++)  
360 - output->setRelative(distances[j]->compare(target[i][j],query[i][j]), j, 0);  
361 - }  
362 - }  
363 -  
364 - void store(QDataStream &stream) const  
365 - {  
366 - stream << distances.size();  
367 - foreach (Distance *distance, distances)  
368 - distance->store(stream);  
369 - }  
370 -  
371 - void load(QDataStream &stream)  
372 - {  
373 - int numDistances;  
374 - stream >> numDistances;  
375 - while (distances.size() < numDistances)  
376 - distances.append(make(description));  
377 - foreach (Distance *distance, distances)  
378 - distance->load(stream);  
379 - }  
380 -};  
381 -  
382 -BR_REGISTER(Distance, HeatMapDistance)  
383 -  
384 -/*!  
385 - * \ingroup distances  
386 - * \brief Linear normalizes of a distance so the mean impostor score is 0 and the mean genuine score is 1.  
387 - * \author Josh Klontz \cite jklontz  
388 - */  
389 -class UnitDistance : public Distance  
390 -{  
391 - Q_OBJECT  
392 - Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance)  
393 - Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a)  
394 - Q_PROPERTY(float b READ get_b WRITE set_b RESET reset_b)  
395 - Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)  
396 - BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))  
397 - BR_PROPERTY(float, a, 1)  
398 - BR_PROPERTY(float, b, 0)  
399 - BR_PROPERTY(QString, inputVariable, "Label")  
400 -  
401 - void train(const TemplateList &templates)  
402 - {  
403 - const TemplateList samples = templates.mid(0, 2000);  
404 - const QList<int> sampleLabels = samples.indexProperty(inputVariable);  
405 - QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(samples.size()), FileList(samples.size())));  
406 - Distance::compare(samples, samples, matrixOutput.data());  
407 -  
408 - double genuineAccumulator, impostorAccumulator;  
409 - int genuineCount, impostorCount;  
410 - genuineAccumulator = impostorAccumulator = genuineCount = impostorCount = 0;  
411 -  
412 - for (int i=0; i<samples.size(); i++) {  
413 - for (int j=0; j<i; j++) {  
414 - const float val = matrixOutput.data()->data.at<float>(i, j);  
415 - if (sampleLabels[i] == sampleLabels[j]) {  
416 - genuineAccumulator += val;  
417 - genuineCount++;  
418 - } else {  
419 - impostorAccumulator += val;  
420 - impostorCount++;  
421 - }  
422 - }  
423 - }  
424 -  
425 - if (genuineCount == 0) { qWarning("No genuine matches."); return; }  
426 - if (impostorCount == 0) { qWarning("No impostor matches."); return; }  
427 -  
428 - double genuineMean = genuineAccumulator / genuineCount;  
429 - double impostorMean = impostorAccumulator / impostorCount;  
430 -  
431 - if (genuineMean == impostorMean) { qWarning("Genuines and impostors are indistinguishable."); return; }  
432 -  
433 - a = 1.0/(genuineMean-impostorMean);  
434 - b = impostorMean;  
435 -  
436 - qDebug("a = %f, b = %f", a, b);  
437 - }  
438 -  
439 - float compare(const Template &target, const Template &query) const  
440 - {  
441 - return a * (distance->compare(target, query) - b);  
442 - }  
443 -};  
444 -  
445 -BR_REGISTER(Distance, UnitDistance)  
446 -  
447 } // namespace br 177 } // namespace br
448 178
449 -#include "quality.moc" 179 +#include "distance/matchprobability.moc"
openbr/plugins/distance/metadata.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/qtutils.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup distances
  9 + * \brief Checks target metadata against query metadata.
  10 + * \author Scott Klum \cite sklum
  11 + */
  12 +class MetadataDistance : public UntrainableDistance
  13 +{
  14 + Q_OBJECT
  15 +
  16 + Q_PROPERTY(QStringList filters READ get_filters WRITE set_filters RESET reset_filters STORED false)
  17 + BR_PROPERTY(QStringList, filters, QStringList())
  18 +
  19 + float compare(const Template &a, const Template &b) const
  20 + {
  21 + foreach (const QString &key, filters) {
  22 + QString aValue = a.file.get<QString>(key, QString());
  23 + QString bValue = b.file.get<QString>(key, QString());
  24 +
  25 + // The query value may be a range. Let's check.
  26 + if (bValue.isEmpty()) bValue = QtUtils::toString(b.file.get<QPointF>(key, QPointF()));
  27 +
  28 + if (aValue.isEmpty() || bValue.isEmpty()) continue;
  29 +
  30 + bool keep = false;
  31 + bool ok;
  32 +
  33 + QPointF range = QtUtils::toPoint(bValue,&ok);
  34 +
  35 + if (ok) /* Range */ {
  36 + int value = range.x();
  37 + int upperBound = range.y();
  38 +
  39 + while (value <= upperBound) {
  40 + if (aValue == QString::number(value)) {
  41 + keep = true;
  42 + break;
  43 + }
  44 + value++;
  45 + }
  46 + }
  47 + else if (aValue == bValue) keep = true;
  48 +
  49 + if (!keep) return -std::numeric_limits<float>::max();
  50 + }
  51 + return 0;
  52 + }
  53 +};
  54 +
  55 +
  56 +BR_REGISTER(Distance, MetadataDistance)
  57 +
  58 +} // namespace br
  59 +
  60 +#include "distance/metadata.moc"
openbr/plugins/distance/neglogplusone.cpp
@@ -39,4 +39,4 @@ BR_REGISTER(Distance, NegativeLogPlusOneDistance) @@ -39,4 +39,4 @@ BR_REGISTER(Distance, NegativeLogPlusOneDistance)
39 39
40 } // namespace br 40 } // namespace br
41 41
42 -#include "neglogplusone.moc" 42 +#include "distance/neglogplusone.moc"
openbr/plugins/distance/online.cpp
@@ -32,4 +32,4 @@ BR_REGISTER(Distance, OnlineDistance) @@ -32,4 +32,4 @@ BR_REGISTER(Distance, OnlineDistance)
32 32
33 } // namespace br 33 } // namespace br
34 34
35 -#include "online.moc" 35 +#include "distance/online.moc"
openbr/plugins/distance/pipe.cpp
@@ -44,4 +44,4 @@ BR_REGISTER(Distance, PipeDistance) @@ -44,4 +44,4 @@ BR_REGISTER(Distance, PipeDistance)
44 44
45 } // namespace br 45 } // namespace br
46 46
47 -#include "pipe.moc" 47 +#include "distance/pipe.moc"
openbr/plugins/distance/reject.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief Sets distance to -FLOAT_MAX if a target template has/doesn't have a key.
  9 + * \author Scott Klum \cite sklum
  10 + */
  11 +class RejectDistance : public UntrainableDistance
  12 +{
  13 + Q_OBJECT
  14 +
  15 + Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)
  16 + BR_PROPERTY(QStringList, keys, QStringList())
  17 + Q_PROPERTY(bool rejectIfContains READ get_rejectIfContains WRITE set_rejectIfContains RESET reset_rejectIfContains STORED false)
  18 + BR_PROPERTY(bool, rejectIfContains, false)
  19 +
  20 + float compare(const Template &a, const Template &b) const
  21 + {
  22 + // We don't look at the query
  23 + (void) b;
  24 +
  25 + foreach (const QString &key, keys)
  26 + if ((rejectIfContains && a.file.contains(key)) || (!rejectIfContains && !a.file.contains(key)))
  27 + return -std::numeric_limits<float>::max();
  28 +
  29 + return 0;
  30 + }
  31 +};
  32 +
  33 +
  34 +BR_REGISTER(Distance, RejectDistance)
  35 +
  36 +} // namespace br
  37 +
  38 +#include "distance/reject.moc"
openbr/plugins/distance/sum.cpp
@@ -43,4 +43,4 @@ BR_REGISTER(Distance, SumDistance) @@ -43,4 +43,4 @@ BR_REGISTER(Distance, SumDistance)
43 43
44 } // namespace br 44 } // namespace br
45 45
46 -#include "sum.moc" 46 +#include "distance/sum.moc"
openbr/plugins/distance/turk.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup distances
  9 + * \brief Unmaps Turk HITs to be compared against query mats
  10 + * \author Scott Klum \cite sklum
  11 + */
  12 +class TurkDistance : public UntrainableDistance
  13 +{
  14 + Q_OBJECT
  15 + Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key)
  16 + Q_PROPERTY(QStringList values READ get_values WRITE set_values RESET reset_values STORED false)
  17 + BR_PROPERTY(QString, key, QString())
  18 + BR_PROPERTY(QStringList, values, QStringList())
  19 +
  20 + bool targetHuman;
  21 + bool queryMachine;
  22 +
  23 + void init()
  24 + {
  25 + targetHuman = Globals->property("TurkTargetHuman").toBool();
  26 + queryMachine = Globals->property("TurkQueryMachine").toBool();
  27 + }
  28 +
  29 + cv::Mat getValues(const Template &t) const
  30 + {
  31 + QList<float> result;
  32 + foreach (const QString &value, values)
  33 + result.append(t.file.get<float>(key + "_" + value));
  34 + return OpenCVUtils::toMat(result, 1);
  35 + }
  36 +
  37 + float compare(const Template &target, const Template &query) const
  38 + {
  39 + const cv::Mat a = targetHuman ? getValues(target) : target.m();
  40 + const cv::Mat b = queryMachine ? query.m() : getValues(query);
  41 + return -norm(a, b, cv::NORM_L1);
  42 + }
  43 +};
  44 +
  45 +BR_REGISTER(Distance, TurkDistance)
  46 +
  47 +} // namespace br
  48 +
  49 +#include "distance/turk.moc"
openbr/plugins/distance/unit.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup distances
  8 + * \brief Linear normalizes of a distance so the mean impostor score is 0 and the mean genuine score is 1.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class UnitDistance : public Distance
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance)
  15 + Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a)
  16 + Q_PROPERTY(float b READ get_b WRITE set_b RESET reset_b)
  17 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  18 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  19 + BR_PROPERTY(float, a, 1)
  20 + BR_PROPERTY(float, b, 0)
  21 + BR_PROPERTY(QString, inputVariable, "Label")
  22 +
  23 + void train(const TemplateList &templates)
  24 + {
  25 + const TemplateList samples = templates.mid(0, 2000);
  26 + const QList<int> sampleLabels = samples.indexProperty(inputVariable);
  27 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(samples.size()), FileList(samples.size())));
  28 + Distance::compare(samples, samples, matrixOutput.data());
  29 +
  30 + double genuineAccumulator, impostorAccumulator;
  31 + int genuineCount, impostorCount;
  32 + genuineAccumulator = impostorAccumulator = genuineCount = impostorCount = 0;
  33 +
  34 + for (int i=0; i<samples.size(); i++) {
  35 + for (int j=0; j<i; j++) {
  36 + const float val = matrixOutput.data()->data.at<float>(i, j);
  37 + if (sampleLabels[i] == sampleLabels[j]) {
  38 + genuineAccumulator += val;
  39 + genuineCount++;
  40 + } else {
  41 + impostorAccumulator += val;
  42 + impostorCount++;
  43 + }
  44 + }
  45 + }
  46 +
  47 + if (genuineCount == 0) { qWarning("No genuine matches."); return; }
  48 + if (impostorCount == 0) { qWarning("No impostor matches."); return; }
  49 +
  50 + double genuineMean = genuineAccumulator / genuineCount;
  51 + double impostorMean = impostorAccumulator / impostorCount;
  52 +
  53 + if (genuineMean == impostorMean) { qWarning("Genuines and impostors are indistinguishable."); return; }
  54 +
  55 + a = 1.0/(genuineMean-impostorMean);
  56 + b = impostorMean;
  57 +
  58 + qDebug("a = %f, b = %f", a, b);
  59 + }
  60 +
  61 + float compare(const Template &target, const Template &query) const
  62 + {
  63 + return a * (distance->compare(target, query) - b);
  64 + }
  65 +};
  66 +
  67 +BR_REGISTER(Distance, UnitDistance)
  68 +
  69 +} // namespace br
  70 +
  71 +#include "distance/unit.moc"
openbr/plugins/distance/zscore.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/common.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +class ZScoreDistance : public Distance
  8 +{
  9 + Q_OBJECT
  10 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  11 + Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false)
  12 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  13 + BR_PROPERTY(bool, crossModality, false)
  14 +
  15 + float min, max;
  16 + double mean, stddev;
  17 +
  18 + void train(const TemplateList &src)
  19 + {
  20 + distance->train(src);
  21 +
  22 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));
  23 + distance->compare(src, src, matrixOutput.data());
  24 +
  25 + QList<float> scores;
  26 + scores.reserve(src.size()*src.size());
  27 + for (int i=0; i<src.size(); i++) {
  28 + for (int j=0; j<i; j++) {
  29 + const float score = matrixOutput.data()->data.at<float>(i, j);
  30 + if (score == -std::numeric_limits<float>::max()) continue;
  31 + if (crossModality && src[i].file.get<QString>("MODALITY") == src[j].file.get<QString>("MODALITY")) continue;
  32 + scores.append(score);
  33 + }
  34 + }
  35 +
  36 + Common::MinMax(scores, &min, &max);
  37 + Common::MeanStdDev(scores, &mean, &stddev);
  38 +
  39 + if (stddev == 0) qFatal("Stddev is 0.");
  40 + }
  41 +
  42 + float compare(const Template &target, const Template &query) const
  43 + {
  44 + float score = distance->compare(target,query);
  45 + if (score == -std::numeric_limits<float>::max()) score = (min - mean) / stddev;
  46 + else if (score == std::numeric_limits<float>::max()) score = (max - mean) / stddev;
  47 + else score = (score - mean) / stddev;
  48 + return score;
  49 + }
  50 +
  51 + void store(QDataStream &stream) const
  52 + {
  53 + distance->store(stream);
  54 + stream << min << max << mean << stddev;
  55 + }
  56 +
  57 + void load(QDataStream &stream)
  58 + {
  59 + distance->load(stream);
  60 + stream >> min >> max >> mean >> stddev;
  61 + }
  62 +};
  63 +
  64 +BR_REGISTER(Distance, ZScoreDistance)
  65 +
  66 +} // namespace br
  67 +
  68 +#include "distance/zscore.moc"
openbr/plugins/format/binary.cpp
@@ -67,4 +67,4 @@ BR_REGISTER(Format, binaryFormat) @@ -67,4 +67,4 @@ BR_REGISTER(Format, binaryFormat)
67 67
68 } // namespace br 68 } // namespace br
69 69
70 -#include "binary.moc" 70 +#include "format/binary.moc"
openbr/plugins/format/csv.cpp
@@ -70,4 +70,4 @@ BR_REGISTER(Format, csvFormat) @@ -70,4 +70,4 @@ BR_REGISTER(Format, csvFormat)
70 70
71 } // namespace br 71 } // namespace br
72 72
73 -#include "csv.moc" 73 +#include "format/csv.moc"
openbr/plugins/format/ebts.cpp
@@ -196,4 +196,4 @@ BR_REGISTER(Format, ebtsFormat) @@ -196,4 +196,4 @@ BR_REGISTER(Format, ebtsFormat)
196 196
197 } // namespace br 197 } // namespace br
198 198
199 -#include "ebts.moc" 199 +#include "format/ebts.moc"
openbr/plugins/format/lffs.cpp
@@ -33,4 +33,4 @@ BR_REGISTER(Format, lffsFormat) @@ -33,4 +33,4 @@ BR_REGISTER(Format, lffsFormat)
33 33
34 } // namespace br 34 } // namespace br
35 35
36 -#include "lffs.moc" 36 +#include "format/lffs.moc"
openbr/plugins/format/lmat.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup formats
  8 + * \brief Likely matrix format
  9 + *
  10 + * www.liblikely.org
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class lmatFormat : public Format
  14 +{
  15 + Q_OBJECT
  16 +
  17 + Template read() const
  18 + {
  19 + const likely_const_mat m = likely_read(qPrintable(file.name), likely_file_guess);
  20 + const Template result(likelyToOpenCVMat(m));
  21 + likely_release_mat(m);
  22 + return result;
  23 + }
  24 +
  25 + void write(const Template &t) const
  26 + {
  27 + const likely_const_mat m = likelyFromOpenCVMat(t);
  28 + likely_write(m, qPrintable(file.name));
  29 + likely_release_mat(m);
  30 + }
  31 +};
  32 +
  33 +BR_REGISTER(Format, lmatFormat)
  34 +
  35 +} // namespace br
  36 +
  37 +#include "format/lmat.moc"
openbr/plugins/format/mat.cpp
@@ -224,4 +224,4 @@ BR_REGISTER(Format, matFormat) @@ -224,4 +224,4 @@ BR_REGISTER(Format, matFormat)
224 224
225 } // namespace br 225 } // namespace br
226 226
227 -#include "mat.moc" 227 +#include "format/mat.moc"
openbr/plugins/format/mtx.cpp
@@ -44,4 +44,4 @@ BR_REGISTER(Format, maskFormat) @@ -44,4 +44,4 @@ BR_REGISTER(Format, maskFormat)
44 44
45 } // namespace br 45 } // namespace br
46 46
47 -#include "mtx.moc" 47 +#include "format/mtx.moc"
openbr/plugins/format/null.cpp
@@ -27,4 +27,4 @@ BR_REGISTER(Format, nullFormat) @@ -27,4 +27,4 @@ BR_REGISTER(Format, nullFormat)
27 27
28 } // namespace br 28 } // namespace br
29 29
30 -#include "null.moc" 30 +#include "format/null.moc"
openbr/plugins/format/post.cpp 0 → 100644
  1 +#include <QTcpSocket>
  2 +#include <opencv2/highgui/highgui.hpp>
  3 +
  4 +#include <openbr/plugins/openbr_internal.h>
  5 +#include <http_parser.h>
  6 +
  7 +using namespace cv;
  8 +
  9 +namespace br
  10 +{
  11 +
  12 +/*!
  13 + * \ingroup formats
  14 + * \brief Handle POST requests
  15 + * \author Josh Klontz \cite jklontz
  16 + */
  17 +class postFormat : public Format
  18 +{
  19 + Q_OBJECT
  20 +
  21 + Template read() const
  22 + {
  23 + Template t(file);
  24 +
  25 + // Read from socket
  26 + QTcpSocket *socket = new QTcpSocket();
  27 + socket->setSocketDescriptor(file.get<qintptr>("socketDescriptor"));
  28 + socket->write("HTTP/1.1 200 OK\r\n"
  29 + "Content-Type: text/html; charset=UTF-8\r\n\r\n"
  30 + "Hello World!\r\n");
  31 + socket->waitForBytesWritten();
  32 + socket->waitForReadyRead();
  33 + QByteArray data = socket->readAll();
  34 + socket->close();
  35 + delete socket;
  36 +
  37 + qDebug() << data;
  38 +
  39 + // Parse data
  40 + http_parser_settings settings;
  41 + settings.on_body = bodyCallback;
  42 + settings.on_headers_complete = NULL;
  43 + settings.on_header_field = NULL;
  44 + settings.on_header_value = NULL;
  45 + settings.on_message_begin = NULL;
  46 + settings.on_message_complete = NULL;
  47 + settings.on_status_complete = NULL;
  48 + settings.on_url = NULL;
  49 +
  50 + {
  51 + QByteArray body;
  52 + http_parser parser;
  53 + http_parser_init(&parser, HTTP_REQUEST);
  54 + parser.data = &body;
  55 + http_parser_execute(&parser, &settings, data.data(), data.size());
  56 + data = body;
  57 + }
  58 +
  59 + data.prepend("HTTP/1.1 200 OK");
  60 + QByteArray body;
  61 + { // Image data is two layers deep
  62 + http_parser parser;
  63 + http_parser_init(&parser, HTTP_BOTH);
  64 + parser.data = &body;
  65 + http_parser_execute(&parser, &settings, data.data(), data.size());
  66 + }
  67 +
  68 + t.append(imdecode(Mat(1, body.size(), CV_8UC1, body.data()), 1));
  69 + return t;
  70 + }
  71 +
  72 + void write(const Template &t) const
  73 + {
  74 + (void) t;
  75 + qFatal("Not supported!");
  76 + }
  77 +
  78 + static int bodyCallback(http_parser *parser, const char *at, size_t length)
  79 + {
  80 + QByteArray *byteArray = (QByteArray*)parser->data;
  81 + *byteArray = QByteArray(at, length);
  82 + return 0;
  83 + }
  84 +};
  85 +
  86 +BR_REGISTER(Format, postFormat)
  87 +
  88 +} // namespace br
  89 +
  90 +#include "format/post.moc"
openbr/plugins/format/raw.cpp
@@ -67,4 +67,4 @@ BR_REGISTER(Format, rawFormat) @@ -67,4 +67,4 @@ BR_REGISTER(Format, rawFormat)
67 67
68 } // namespace br 68 } // namespace br
69 69
70 -#include "raw.moc" 70 +#include "format/raw.moc"
openbr/plugins/format/scores.cpp
@@ -62,4 +62,4 @@ BR_REGISTER(Format, scoresFormat) @@ -62,4 +62,4 @@ BR_REGISTER(Format, scoresFormat)
62 62
63 } // namespace br 63 } // namespace br
64 64
65 -#include "scores.moc" 65 +#include "format/scores.moc"
openbr/plugins/format/url.cpp 0 → 100644
  1 +#include <QtNetwork>
  2 +#include <opencv2/highgui/highgui.hpp>
  3 +
  4 +#include <openbr/plugins/openbr_internal.h>
  5 +
  6 +using namespace cv;
  7 +
  8 +namespace br
  9 +{
  10 +
  11 +/*!
  12 + * \ingroup formats
  13 + * \brief Reads image files from the web.
  14 + * \author Josh Klontz \cite jklontz
  15 + */
  16 +class urlFormat : public Format
  17 +{
  18 + Q_OBJECT
  19 +
  20 + Template read() const
  21 + {
  22 + Template t;
  23 +
  24 + QNetworkAccessManager networkAccessManager;
  25 + QNetworkRequest request(QString(file.name).remove(".url"));
  26 + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
  27 + QNetworkReply *reply = networkAccessManager.get(request);
  28 +
  29 + while (!reply->isFinished()) QCoreApplication::processEvents();
  30 + if (reply->error()) qWarning("%s (%s)", qPrintable(reply->errorString()), qPrintable(QString::number(reply->error())));
  31 +
  32 + QByteArray data = reply->readAll();
  33 + delete reply;
  34 +
  35 + Mat m = imdecode(Mat(1, data.size(), CV_8UC1, data.data()), 1);
  36 + if (m.data) t.append(m);
  37 +
  38 + return t;
  39 + }
  40 +
  41 + void write(const Template &t) const
  42 + {
  43 + (void) t;
  44 + qFatal("Not supported.");
  45 + }
  46 +};
  47 +
  48 +BR_REGISTER(Format, urlFormat)
  49 +
  50 +} // namespace br
  51 +
  52 +#include "format/url.moc"
openbr/plugins/format/video.cpp
@@ -144,4 +144,4 @@ BR_REGISTER(Format, DefaultFormat) @@ -144,4 +144,4 @@ BR_REGISTER(Format, DefaultFormat)
144 144
145 } // namespace br 145 } // namespace br
146 146
147 -#include "video.moc" 147 +#include "format/video.moc"
openbr/plugins/format/xml.cpp
@@ -99,4 +99,4 @@ BR_REGISTER(Format, xmlFormat) @@ -99,4 +99,4 @@ BR_REGISTER(Format, xmlFormat)
99 99
100 } // namespace br 100 } // namespace br
101 101
102 -#include "xml.moc" 102 +#include "format/xml.moc"
openbr/plugins/gallery.cpp deleted
1 -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  
2 - * Copyright 2012 The MITRE Corporation *  
3 - * *  
4 - * Licensed under the Apache License, Version 2.0 (the "License"); *  
5 - * you may not use this file except in compliance with the License. *  
6 - * You may obtain a copy of the License at *  
7 - * *  
8 - * http://www.apache.org/licenses/LICENSE-2.0 *  
9 - * *  
10 - * Unless required by applicable law or agreed to in writing, software *  
11 - * distributed under the License is distributed on an "AS IS" BASIS, *  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *  
13 - * See the License for the specific language governing permissions and *  
14 - * limitations under the License. *  
15 - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */  
16 -  
17 -#include <QtCore>  
18 -#include <QtConcurrentRun>  
19 -#ifndef BR_EMBEDDED  
20 -#include <QNetworkAccessManager>  
21 -#include <QNetworkReply>  
22 -#include <QSqlDatabase>  
23 -#include <QSqlError>  
24 -#include <QSqlQuery>  
25 -#include <QSqlRecord>  
26 -#include <QXmlStreamReader>  
27 -#endif // BR_EMBEDDED  
28 -#include <opencv2/highgui/highgui.hpp>  
29 -#include "openbr_internal.h"  
30 -  
31 -#include "openbr/universal_template.h"  
32 -#include "openbr/core/bee.h"  
33 -#include "openbr/core/common.h"  
34 -#include "openbr/core/opencvutils.h"  
35 -#include "openbr/core/qtutils.h"  
36 -  
37 -#include <fstream>  
38 -  
39 -#ifdef CVMATIO  
40 -#include "MatlabIO.hpp"  
41 -#include "MatlabIOContainer.hpp"  
42 -#endif  
43 -  
44 -#ifdef _WIN32  
45 -#include <io.h>  
46 -#include <fcntl.h>  
47 -#endif // _WIN32  
48 -  
49 -namespace br  
50 -{  
51 -  
52 -/*!  
53 - * \ingroup galleries  
54 - * \brief Weka ARFF file format.  
55 - * \author Josh Klontz \cite jklontz  
56 - * http://weka.wikispaces.com/ARFF+%28stable+version%29  
57 - */  
58 -class arffGallery : public Gallery  
59 -{  
60 - Q_OBJECT  
61 - QFile arffFile;  
62 -  
63 - TemplateList readBlock(bool *done)  
64 - {  
65 - (void) done;  
66 - qFatal("Not implemented.");  
67 - return TemplateList();  
68 - }  
69 -  
70 - void write(const Template &t)  
71 - {  
72 - if (!arffFile.isOpen()) {  
73 - arffFile.setFileName(file.name);  
74 - arffFile.open(QFile::WriteOnly);  
75 - arffFile.write("% OpenBR templates\n"  
76 - "@RELATION OpenBR\n"  
77 - "\n");  
78 -  
79 - const int dimensions = t.m().rows * t.m().cols;  
80 - for (int i=0; i<dimensions; i++)  
81 - arffFile.write(qPrintable("@ATTRIBUTE v" + QString::number(i) + " REAL\n"));  
82 - arffFile.write(qPrintable("@ATTRIBUTE class string\n"));  
83 -  
84 - arffFile.write("\n@DATA\n");  
85 - }  
86 -  
87 - arffFile.write(qPrintable(OpenCVUtils::matrixToStringList(t).join(',')));  
88 - arffFile.write(qPrintable(",'" + t.file.get<QString>("Label") + "'\n"));  
89 - }  
90 -  
91 - void init()  
92 - {  
93 - //  
94 - }  
95 -};  
96 -  
97 -BR_REGISTER(Gallery, arffGallery)  
98 -  
99 -class BinaryGallery : public Gallery  
100 -{  
101 - Q_OBJECT  
102 -  
103 - void init()  
104 - {  
105 - const QString baseName = file.baseName();  
106 -  
107 - if (baseName == "stdin") {  
108 -#ifdef _WIN32  
109 - if(_setmode(_fileno(stdin), _O_BINARY) == -1)  
110 - qFatal("Failed to set stdin to binary mode!");  
111 -#endif // _WIN32  
112 -  
113 - gallery.open(stdin, QFile::ReadOnly);  
114 - } else if (baseName == "stdout") {  
115 -#ifdef _WIN32  
116 - if(_setmode(_fileno(stdout), _O_BINARY) == -1)  
117 - qFatal("Failed to set stdout to binary mode!");  
118 -#endif // _WIN32  
119 -  
120 - gallery.open(stdout, QFile::WriteOnly);  
121 - } else if (baseName == "stderr") {  
122 -#ifdef _WIN32  
123 - if(_setmode(_fileno(stderr), _O_BINARY) == -1)  
124 - qFatal("Failed to set stderr to binary mode!");  
125 -#endif // _WIN32  
126 -  
127 - gallery.open(stderr, QFile::WriteOnly);  
128 - } else {  
129 - // Defer opening the file, in the general case we don't know if we  
130 - // need read or write mode yet  
131 - return;  
132 - }  
133 - stream.setDevice(&gallery);  
134 - }  
135 -  
136 - void readOpen()  
137 - {  
138 - if (!gallery.isOpen()) {  
139 - gallery.setFileName(file);  
140 - if (!gallery.exists())  
141 - qFatal("File %s does not exist", qPrintable(gallery.fileName()));  
142 -  
143 - QFile::OpenMode mode = QFile::ReadOnly;  
144 - if (!gallery.open(mode))  
145 - qFatal("Can't open gallery: %s for reading", qPrintable(gallery.fileName()));  
146 - stream.setDevice(&gallery);  
147 - }  
148 - }  
149 -  
150 - void writeOpen()  
151 - {  
152 - if (!gallery.isOpen()) {  
153 - gallery.setFileName(file);  
154 -  
155 - // Do we remove the pre-existing gallery?  
156 - if (file.get<bool>("remove"))  
157 - gallery.remove();  
158 - QtUtils::touchDir(gallery);  
159 - QFile::OpenMode mode = QFile::WriteOnly;  
160 -  
161 - // Do we append?  
162 - if (file.get<bool>("append"))  
163 - mode |= QFile::Append;  
164 -  
165 - if (!gallery.open(mode))  
166 - qFatal("Can't open gallery: %s for writing", qPrintable(gallery.fileName()));  
167 - stream.setDevice(&gallery);  
168 - }  
169 - }  
170 -  
171 - TemplateList readBlock(bool *done)  
172 - {  
173 - readOpen();  
174 - if (gallery.atEnd())  
175 - gallery.seek(0);  
176 -  
177 - TemplateList templates;  
178 - while ((templates.size() < readBlockSize) && !gallery.atEnd()) {  
179 - const Template t = readTemplate();  
180 - if (!t.isEmpty() || !t.file.isNull()) {  
181 - templates.append(t);  
182 - templates.last().file.set("progress", position());  
183 - }  
184 -  
185 - // Special case for pipes where we want to process data as soon as it is available  
186 - if (gallery.isSequential())  
187 - break;  
188 - }  
189 -  
190 - *done = gallery.atEnd();  
191 - return templates;  
192 - }  
193 -  
194 - void write(const Template &t)  
195 - {  
196 - writeOpen();  
197 - writeTemplate(t);  
198 - if (gallery.isSequential())  
199 - gallery.flush();  
200 - }  
201 -  
202 -protected:  
203 - QFile gallery;  
204 - QDataStream stream;  
205 -  
206 - qint64 totalSize()  
207 - {  
208 - readOpen();  
209 - return gallery.size();  
210 - }  
211 -  
212 - qint64 position()  
213 - {  
214 - return gallery.pos();  
215 - }  
216 -  
217 - virtual Template readTemplate() = 0;  
218 - virtual void writeTemplate(const Template &t) = 0;  
219 -};  
220 -  
221 -/*!  
222 - * \ingroup galleries  
223 - * \brief A binary gallery.  
224 - *  
225 - * Designed to be a literal translation of templates to disk.  
226 - * Compatible with TemplateList::fromBuffer.  
227 - * \author Josh Klontz \cite jklontz  
228 - */  
229 -class galGallery : public BinaryGallery  
230 -{  
231 - Q_OBJECT  
232 -  
233 - Template readTemplate()  
234 - {  
235 - Template t;  
236 - stream >> t;  
237 - return t;  
238 - }  
239 -  
240 - void writeTemplate(const Template &t)  
241 - {  
242 - if (t.isEmpty() && t.file.isNull())  
243 - return;  
244 - else if (t.file.fte)  
245 - stream << Template(t.file); // only write metadata for failure to enroll  
246 - else  
247 - stream << t;  
248 - }  
249 -};  
250 -  
251 -BR_REGISTER(Gallery, galGallery)  
252 -  
253 -/*!  
254 - * \ingroup galleries  
255 - * \brief A contiguous array of br_universal_template.  
256 - * \author Josh Klontz \cite jklontz  
257 - */  
258 -class utGallery : public BinaryGallery  
259 -{  
260 - Q_OBJECT  
261 -  
262 - Template readTemplate()  
263 - {  
264 - Template t;  
265 - br_universal_template ut;  
266 - if (gallery.read((char*)&ut, sizeof(br_universal_template)) == sizeof(br_universal_template)) {  
267 - QByteArray data(ut.urlSize + ut.fvSize, Qt::Uninitialized);  
268 - char *dst = data.data();  
269 - qint64 bytesNeeded = ut.urlSize + ut.fvSize;  
270 - while (bytesNeeded > 0) {  
271 - qint64 bytesRead = gallery.read(dst, bytesNeeded);  
272 - if (bytesRead <= 0) {  
273 - qDebug() << gallery.errorString();  
274 - qFatal("Unexepected EOF while reading universal template data, needed: %d more of: %d bytes.", int(bytesNeeded), int(ut.urlSize + ut.fvSize));  
275 - }  
276 - bytesNeeded -= bytesRead;  
277 - dst += bytesRead;  
278 - }  
279 -  
280 - t.file.set("ImageID", QVariant(QByteArray((const char*)ut.imageID, 16).toHex()));  
281 - t.file.set("AlgorithmID", ut.algorithmID);  
282 - t.file.set("URL", QString(data.data()));  
283 - char *dataStart = data.data() + ut.urlSize;  
284 - uint32_t dataSize = ut.fvSize;  
285 - if ((ut.algorithmID <= -1) && (ut.algorithmID >= -3)) {  
286 - t.file.set("FrontalFace", QRectF(ut.x, ut.y, ut.width, ut.height));  
287 - uint32_t *rightEyeX = reinterpret_cast<uint32_t*>(dataStart);  
288 - dataStart += sizeof(uint32_t);  
289 - uint32_t *rightEyeY = reinterpret_cast<uint32_t*>(dataStart);  
290 - dataStart += sizeof(uint32_t);  
291 - uint32_t *leftEyeX = reinterpret_cast<uint32_t*>(dataStart);  
292 - dataStart += sizeof(uint32_t);  
293 - uint32_t *leftEyeY = reinterpret_cast<uint32_t*>(dataStart);  
294 - dataStart += sizeof(uint32_t);  
295 - dataSize -= sizeof(uint32_t)*4;  
296 - t.file.set("First_Eye", QPointF(*rightEyeX, *rightEyeY));  
297 - t.file.set("Second_Eye", QPointF(*leftEyeX, *leftEyeY));  
298 - } else {  
299 - t.file.set("X", ut.x);  
300 - t.file.set("Y", ut.y);  
301 - t.file.set("Width", ut.width);  
302 - t.file.set("Height", ut.height);  
303 - }  
304 - t.file.set("Label", ut.label);  
305 - t.append(cv::Mat(1, dataSize, CV_8UC1, dataStart).clone() /* We don't want a shallow copy! */);  
306 - } else {  
307 - if (!gallery.atEnd())  
308 - qFatal("Failed to read universal template header!");  
309 - }  
310 - return t;  
311 - }  
312 -  
313 - void writeTemplate(const Template &t)  
314 - {  
315 - const QByteArray imageID = QByteArray::fromHex(t.file.get<QByteArray>("ImageID", QByteArray(32, '0')));  
316 - if (imageID.size() != 16)  
317 - qFatal("Expected 16-byte ImageID, got: %d bytes.", imageID.size());  
318 -  
319 - const int32_t algorithmID = (t.isEmpty() || t.file.fte) ? 0 : t.file.get<int32_t>("AlgorithmID");  
320 - const QByteArray url = t.file.get<QString>("URL", t.file.name).toLatin1();  
321 -  
322 - uint32_t x = 0, y = 0, width = 0, height = 0;  
323 - QByteArray header;  
324 - if ((algorithmID <= -1) && (algorithmID >= -3)) {  
325 - const QRectF frontalFace = t.file.get<QRectF>("FrontalFace");  
326 - x = frontalFace.x();  
327 - y = frontalFace.y();  
328 - width = frontalFace.width();  
329 - height = frontalFace.height();  
330 -  
331 - const QPointF firstEye = t.file.get<QPointF>("First_Eye");  
332 - const QPointF secondEye = t.file.get<QPointF>("Second_Eye");  
333 - const uint32_t rightEyeX = firstEye.x();  
334 - const uint32_t rightEyeY = firstEye.y();  
335 - const uint32_t leftEyeX = secondEye.x();  
336 - const uint32_t leftEyeY = secondEye.y();  
337 -  
338 - header.append((const char*)&rightEyeX, sizeof(uint32_t));  
339 - header.append((const char*)&rightEyeY, sizeof(uint32_t));  
340 - header.append((const char*)&leftEyeX , sizeof(uint32_t));  
341 - header.append((const char*)&leftEyeY , sizeof(uint32_t));  
342 - } else {  
343 - x = t.file.get<uint32_t>("X", 0);  
344 - y = t.file.get<uint32_t>("Y", 0);  
345 - width = t.file.get<uint32_t>("Width", 0);  
346 - height = t.file.get<uint32_t>("Height", 0);  
347 - }  
348 - const uint32_t label = t.file.get<uint32_t>("Label", 0);  
349 -  
350 - gallery.write(imageID);  
351 - gallery.write((const char*) &algorithmID, sizeof(int32_t));  
352 - gallery.write((const char*) &x , sizeof(uint32_t));  
353 - gallery.write((const char*) &y , sizeof(uint32_t));  
354 - gallery.write((const char*) &width , sizeof(uint32_t));  
355 - gallery.write((const char*) &height , sizeof(uint32_t));  
356 - gallery.write((const char*) &label , sizeof(uint32_t));  
357 -  
358 - const uint32_t urlSize = url.size() + 1;  
359 - gallery.write((const char*) &urlSize, sizeof(uint32_t));  
360 -  
361 - const uint32_t signatureSize = (algorithmID == 0) ? 0 : t.m().rows * t.m().cols * t.m().elemSize();  
362 - const uint32_t fvSize = header.size() + signatureSize;  
363 - gallery.write((const char*) &fvSize, sizeof(uint32_t));  
364 -  
365 - gallery.write((const char*) url.data(), urlSize);  
366 - if (algorithmID != 0) {  
367 - gallery.write(header);  
368 - gallery.write((const char*) t.m().data, signatureSize);  
369 - }  
370 - }  
371 -};  
372 -  
373 -BR_REGISTER(Gallery, utGallery)  
374 -  
375 -/*!  
376 - * \ingroup galleries  
377 - * \brief Newline-separated URLs.  
378 - * \author Josh Klontz \cite jklontz  
379 - */  
380 -class urlGallery : public BinaryGallery  
381 -{  
382 - Q_OBJECT  
383 -  
384 - Template readTemplate()  
385 - {  
386 - Template t;  
387 - const QString url = QString::fromLocal8Bit(gallery.readLine()).simplified();  
388 - if (!url.isEmpty())  
389 - t.file.set("URL", url);  
390 - return t;  
391 - }  
392 -  
393 - void writeTemplate(const Template &t)  
394 - {  
395 - const QString url = t.file.get<QString>("URL", t.file.name);  
396 - if (!url.isEmpty()) {  
397 - gallery.write(qPrintable(url));  
398 - gallery.write("\n");  
399 - }  
400 - }  
401 -};  
402 -  
403 -BR_REGISTER(Gallery, urlGallery)  
404 -  
405 -/*!  
406 - * \ingroup galleries  
407 - * \brief Newline-separated JSON objects.  
408 - * \author Josh Klontz \cite jklontz  
409 - */  
410 -class jsonGallery : public BinaryGallery  
411 -{  
412 - Q_OBJECT  
413 -  
414 - Template readTemplate()  
415 - {  
416 - QJsonParseError error;  
417 - const QByteArray line = gallery.readLine().simplified();  
418 - if (line.isEmpty())  
419 - return Template();  
420 - File file = QJsonDocument::fromJson(line, &error).object().toVariantMap();  
421 - if (error.error != QJsonParseError::NoError) {  
422 - qWarning("Couldn't parse: %s\n", line.data());  
423 - qFatal("%s\n", qPrintable(error.errorString()));  
424 - }  
425 - return file;  
426 - }  
427 -  
428 - void writeTemplate(const Template &t)  
429 - {  
430 - const QByteArray json = QJsonDocument(QJsonObject::fromVariantMap(t.file.localMetadata())).toJson().replace('\n', "");  
431 - if (!json.isEmpty()) {  
432 - gallery.write(json);  
433 - gallery.write("\n");  
434 - }  
435 - }  
436 -};  
437 -  
438 -BR_REGISTER(Gallery, jsonGallery)  
439 -  
440 -/*!  
441 - * \ingroup galleries  
442 - * \brief Reads/writes templates to/from folders.  
443 - * \author Josh Klontz \cite jklontz  
444 - * \param regexp An optional regular expression to match against the files extension.  
445 - */  
446 -class EmptyGallery : public Gallery  
447 -{  
448 - Q_OBJECT  
449 - Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false)  
450 - BR_PROPERTY(QString, regexp, QString())  
451 -  
452 - qint64 gallerySize;  
453 -  
454 - void init()  
455 - {  
456 - QDir dir(file.name);  
457 - QtUtils::touchDir(dir);  
458 - gallerySize = dir.count();  
459 - }  
460 -  
461 - TemplateList readBlock(bool *done)  
462 - {  
463 - TemplateList templates;  
464 - *done = true;  
465 -  
466 - // Enrolling a null file is used as an idiom to initialize an algorithm  
467 - if (file.isNull()) return templates;  
468 -  
469 - // Add immediate subfolders  
470 - QDir dir(file);  
471 - QList< QFuture<TemplateList> > futures;  
472 - foreach (const QString &folder, QtUtils::naturalSort(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))) {  
473 - const QDir subdir = dir.absoluteFilePath(folder);  
474 - futures.append(QtConcurrent::run(&EmptyGallery::getTemplates, subdir));  
475 - }  
476 - foreach (const QFuture<TemplateList> &future, futures)  
477 - templates.append(future.result());  
478 -  
479 - // Add root folder  
480 - foreach (const QString &fileName, QtUtils::getFiles(file.name, false))  
481 - templates.append(File(fileName, dir.dirName()));  
482 -  
483 - if (!regexp.isEmpty()) {  
484 - QRegExp re(regexp);  
485 - re.setPatternSyntax(QRegExp::Wildcard);  
486 - for (int i=templates.size()-1; i>=0; i--) {  
487 - if (!re.exactMatch(templates[i].file.fileName())) {  
488 - templates.removeAt(i);  
489 - }  
490 - }  
491 - }  
492 -  
493 - for (int i = 0; i < templates.size(); i++) templates[i].file.set("progress", i);  
494 -  
495 - return templates;  
496 - }  
497 -  
498 - void write(const Template &t)  
499 - {  
500 - static QMutex diskLock;  
501 -  
502 - // Enrolling a null file is used as an idiom to initialize an algorithm  
503 - if (file.name.isEmpty()) return;  
504 -  
505 - const QString newFormat = file.get<QString>("newFormat",QString());  
506 - QString destination = file.name + "/" + (file.getBool("preservePath") ? t.file.path()+"/" : QString());  
507 - destination += (newFormat.isEmpty() ? t.file.fileName() : t.file.baseName()+newFormat);  
508 -  
509 - QMutexLocker diskLocker(&diskLock); // Windows prefers to crash when writing to disk in parallel  
510 - if (t.isNull()) {  
511 - QtUtils::copyFile(t.file.resolved(), destination);  
512 - } else {  
513 - QScopedPointer<Format> format(Factory<Format>::make(destination));  
514 - format->write(t);  
515 - }  
516 - }  
517 -  
518 - qint64 totalSize()  
519 - {  
520 - return gallerySize;  
521 - }  
522 -  
523 - static TemplateList getTemplates(const QDir &dir)  
524 - {  
525 - const QStringList files = QtUtils::getFiles(dir, true);  
526 - TemplateList templates; templates.reserve(files.size());  
527 - foreach (const QString &file, files)  
528 - templates.append(File(file, dir.dirName()));  
529 - return templates;  
530 - }  
531 -};  
532 -  
533 -BR_REGISTER(Gallery, EmptyGallery)  
534 -  
535 -/*!  
536 - * \ingroup galleries  
537 - * \brief Crawl a root location for image files.  
538 - * \author Josh Klontz \cite jklontz  
539 - */  
540 -class crawlGallery : public Gallery  
541 -{  
542 - Q_OBJECT  
543 - Q_PROPERTY(bool autoRoot READ get_autoRoot WRITE set_autoRoot RESET reset_autoRoot STORED false)  
544 - Q_PROPERTY(int depth READ get_depth WRITE set_depth RESET reset_depth STORED false)  
545 - Q_PROPERTY(bool depthFirst READ get_depthFirst WRITE set_depthFirst RESET reset_depthFirst STORED false)  
546 - Q_PROPERTY(int images READ get_images WRITE set_images RESET reset_images STORED false)  
547 - Q_PROPERTY(bool json READ get_json WRITE set_json RESET reset_json STORED false)  
548 - Q_PROPERTY(int timeLimit READ get_timeLimit WRITE set_timeLimit RESET reset_timeLimit STORED false)  
549 - BR_PROPERTY(bool, autoRoot, false)  
550 - BR_PROPERTY(int, depth, INT_MAX)  
551 - BR_PROPERTY(bool, depthFirst, false)  
552 - BR_PROPERTY(int, images, INT_MAX)  
553 - BR_PROPERTY(bool, json, false)  
554 - BR_PROPERTY(int, timeLimit, INT_MAX)  
555 -  
556 - QTime elapsed;  
557 - TemplateList templates;  
558 -  
559 - void crawl(QFileInfo url, int currentDepth = 0)  
560 - {  
561 - if ((templates.size() >= images) || (currentDepth >= depth) || (elapsed.elapsed()/1000 >= timeLimit))  
562 - return;  
563 -  
564 - if (url.filePath().startsWith("file://"))  
565 - url = QFileInfo(url.filePath().mid(7));  
566 -  
567 - if (url.isDir()) {  
568 - const QDir dir(url.absoluteFilePath());  
569 - const QFileInfoList files = dir.entryInfoList(QDir::Files);  
570 - const QFileInfoList subdirs = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);  
571 - foreach (const QFileInfo &first, depthFirst ? subdirs : files)  
572 - crawl(first, currentDepth + 1);  
573 - foreach (const QFileInfo &second, depthFirst ? files : subdirs)  
574 - crawl(second, currentDepth + 1);  
575 - } else if (url.isFile()) {  
576 - const QString suffix = url.suffix();  
577 - if ((suffix == "bmp") || (suffix == "jpg") || (suffix == "jpeg") || (suffix == "png") || (suffix == "tiff")) {  
578 - File f;  
579 - if (json) f.set("URL", "file://"+url.canonicalFilePath());  
580 - else f.name = "file://"+url.canonicalFilePath();  
581 - templates.append(f);  
582 - }  
583 - }  
584 - }  
585 -  
586 - void init()  
587 - {  
588 - elapsed.start();  
589 - const QString root = file.name.mid(0, file.name.size()-6); // Remove .crawl suffix";  
590 - if (!root.isEmpty()) {  
591 - crawl(root);  
592 - } else {  
593 - if (autoRoot) {  
594 - foreach (const QString &path, QStandardPaths::standardLocations(QStandardPaths::HomeLocation))  
595 - crawl(path);  
596 - } else {  
597 - QFile file;  
598 - file.open(stdin, QFile::ReadOnly);  
599 - while (!file.atEnd()) {  
600 - const QString url = QString::fromLocal8Bit(file.readLine()).simplified();  
601 - if (!url.isEmpty())  
602 - crawl(url);  
603 - }  
604 - }  
605 - }  
606 - }  
607 -  
608 - TemplateList readBlock(bool *done)  
609 - {  
610 - *done = true;  
611 - return templates;  
612 - }  
613 -  
614 - void write(const Template &)  
615 - {  
616 - qFatal("Not supported");  
617 - }  
618 -};  
619 -  
620 -BR_REGISTER(Gallery, crawlGallery)  
621 -  
622 -/*!  
623 - * \ingroup galleries  
624 - * \brief Treats the gallery as a br::Format.  
625 - * \author Josh Klontz \cite jklontz  
626 - */  
627 -class DefaultGallery : public Gallery  
628 -{  
629 - Q_OBJECT  
630 -  
631 - TemplateList readBlock(bool *done)  
632 - {  
633 - *done = true;  
634 - return TemplateList() << file;  
635 - }  
636 -  
637 - void write(const Template &t)  
638 - {  
639 - QScopedPointer<Format> format(Factory<Format>::make(file));  
640 - format->write(t);  
641 - }  
642 -  
643 - qint64 totalSize()  
644 - {  
645 - return 1;  
646 - }  
647 -};  
648 -  
649 -BR_REGISTER(Gallery, DefaultGallery)  
650 -  
651 -/*!  
652 - * \ingroup galleries  
653 - * \brief Combine all templates into one large matrix and process it as a br::Format  
654 - * \author Josh Klontz \cite jklontz  
655 - */  
656 -class matrixGallery : public Gallery  
657 -{  
658 - Q_OBJECT  
659 - Q_PROPERTY(const QString extension READ get_extension WRITE set_extension RESET reset_extension STORED false)  
660 - BR_PROPERTY(QString, extension, "mtx")  
661 -  
662 - TemplateList templates;  
663 -  
664 - ~matrixGallery()  
665 - {  
666 - if (templates.isEmpty())  
667 - return;  
668 -  
669 - QScopedPointer<Format> format(Factory<Format>::make(getFormat()));  
670 - format->write(Template(file, OpenCVUtils::toMat(templates.data())));  
671 - }  
672 -  
673 - File getFormat() const  
674 - {  
675 - return file.name.left(file.name.size() - file.suffix().size()) + extension;  
676 - }  
677 -  
678 - TemplateList readBlock(bool *done)  
679 - {  
680 - *done = true;  
681 - return TemplateList() << getFormat();  
682 - }  
683 -  
684 - void write(const Template &t)  
685 - {  
686 - templates.append(t);  
687 - }  
688 -};  
689 -  
690 -BR_REGISTER(Gallery, matrixGallery)  
691 -  
692 -/*!  
693 - * \ingroup initializers  
694 - * \brief Initialization support for memGallery.  
695 - * \author Josh Klontz \cite jklontz  
696 - */  
697 -class MemoryGalleries : public Initializer  
698 -{  
699 - Q_OBJECT  
700 -  
701 - void initialize() const {}  
702 -  
703 - void finalize() const  
704 - {  
705 - galleries.clear();  
706 - }  
707 -  
708 -public:  
709 - static QHash<File, TemplateList> galleries; /*!< TODO */  
710 -};  
711 -  
712 -QHash<File, TemplateList> MemoryGalleries::galleries;  
713 -  
714 -BR_REGISTER(Initializer, MemoryGalleries)  
715 -  
716 -/*!  
717 - * \ingroup galleries  
718 - * \brief A gallery held in memory.  
719 - * \author Josh Klontz \cite jklontz  
720 - */  
721 -class memGallery : public Gallery  
722 -{  
723 - Q_OBJECT  
724 - int block;  
725 - qint64 gallerySize;  
726 -  
727 - void init()  
728 - {  
729 - block = 0;  
730 - File galleryFile = file.name.mid(0, file.name.size()-4);  
731 - if ((galleryFile.suffix() == "gal") && galleryFile.exists() && !MemoryGalleries::galleries.contains(file)) {  
732 - QSharedPointer<Gallery> gallery(Factory<Gallery>::make(galleryFile));  
733 - MemoryGalleries::galleries[file] = gallery->read();  
734 - gallerySize = MemoryGalleries::galleries[file].size();  
735 - }  
736 - }  
737 -  
738 - TemplateList readBlock(bool *done)  
739 - {  
740 - TemplateList templates = MemoryGalleries::galleries[file].mid(block*readBlockSize, readBlockSize);  
741 - for (qint64 i = 0; i < templates.size();i++) {  
742 - templates[i].file.set("progress", i + block * readBlockSize);  
743 - }  
744 -  
745 - *done = (templates.size() < readBlockSize);  
746 - block = *done ? 0 : block+1;  
747 - return templates;  
748 - }  
749 -  
750 - void write(const Template &t)  
751 - {  
752 - MemoryGalleries::galleries[file].append(t);  
753 - }  
754 -  
755 - qint64 totalSize()  
756 - {  
757 - return gallerySize;  
758 - }  
759 -  
760 - qint64 position()  
761 - {  
762 - return block * readBlockSize;  
763 - }  
764 -  
765 -};  
766 -  
767 -BR_REGISTER(Gallery, memGallery)  
768 -  
769 -FileList FileList::fromGallery(const File &rFile, bool cache)  
770 -{  
771 - File file = rFile;  
772 - file.remove("append");  
773 -  
774 - File targetMeta = file;  
775 - targetMeta.name = targetMeta.path() + targetMeta.baseName() + "_meta" + targetMeta.hash() + ".mem";  
776 -  
777 - FileList fileData;  
778 -  
779 - // Did we already read the data?  
780 - if (MemoryGalleries::galleries.contains(targetMeta))  
781 - {  
782 - return MemoryGalleries::galleries[targetMeta].files();  
783 - }  
784 -  
785 - TemplateList templates;  
786 - // OK we read the data in some form, does the gallery type containing matrices?  
787 - if ((QStringList() << "gal" << "mem" << "template" << "ut").contains(file.suffix())) {  
788 - // Retrieve it block by block, dropping matrices from read templates.  
789 - QScopedPointer<Gallery> gallery(Gallery::make(file));  
790 - gallery->set_readBlockSize(10);  
791 - bool done = false;  
792 - while (!done)  
793 - {  
794 - TemplateList tList = gallery->readBlock(&done);  
795 - for (int i=0; i < tList.size();i++)  
796 - {  
797 - tList[i].clear();  
798 - templates.append(tList[i].file);  
799 - }  
800 - }  
801 - }  
802 - else {  
803 - // this is a gallery format that doesn't include matrices, so we can just read it  
804 - QScopedPointer<Gallery> gallery(Gallery::make(file));  
805 - templates= gallery->read();  
806 - }  
807 -  
808 - if (cache)  
809 - {  
810 - QScopedPointer<Gallery> memOutput(Gallery::make(targetMeta));  
811 - memOutput->writeBlock(templates);  
812 - }  
813 - fileData = templates.files();  
814 - return fileData;  
815 -}  
816 -  
817 -/*!  
818 - * \ingroup galleries  
819 - * \brief Treats each line as a file.  
820 - * \author Josh Klontz \cite jklontz  
821 - *  
822 - * Columns should be comma separated with first row containing headers.  
823 - * The first column in the file should be the path to the file to enroll.  
824 - * Other columns will be treated as file metadata.  
825 - *  
826 - * \see txtGallery  
827 - */  
828 -class csvGallery : public FileGallery  
829 -{  
830 - Q_OBJECT  
831 - Q_PROPERTY(int fileIndex READ get_fileIndex WRITE set_fileIndex RESET reset_fileIndex)  
832 - BR_PROPERTY(int, fileIndex, 0)  
833 -  
834 - FileList files;  
835 - QStringList headers;  
836 -  
837 - ~csvGallery()  
838 - {  
839 - f.close();  
840 -  
841 - if (files.isEmpty()) return;  
842 -  
843 - QMap<QString,QVariant> samples;  
844 - foreach (const File &file, files)  
845 - foreach (const QString &key, file.localKeys())  
846 - if (!samples.contains(key))  
847 - samples.insert(key, file.value(key));  
848 -  
849 - // Don't create columns in the CSV for these special fields  
850 - samples.remove("Points");  
851 - samples.remove("Rects");  
852 -  
853 - QStringList lines;  
854 - lines.reserve(files.size()+1);  
855 -  
856 - QMap<QString, int> columnCounts;  
857 -  
858 - { // Make header  
859 - QStringList words;  
860 - words.append("File");  
861 - foreach (const QString &key, samples.keys()) {  
862 - int count = 0;  
863 - words.append(getCSVElement(key, samples[key], true, count));  
864 - columnCounts.insert(key, count);  
865 - }  
866 - lines.append(words.join(","));  
867 - }  
868 -  
869 - // Make table  
870 - foreach (const File &file, files) {  
871 - QStringList words;  
872 - words.append(file.name);  
873 - foreach (const QString &key, samples.keys()) {  
874 - int count = columnCounts[key];  
875 - words.append(getCSVElement(key, file.value(key), false, count));  
876 - }  
877 - lines.append(words.join(","));  
878 - }  
879 -  
880 - QtUtils::writeFile(file, lines);  
881 - }  
882 -  
883 - TemplateList readBlock(bool *done)  
884 - {  
885 - readOpen();  
886 - *done = false;  
887 - TemplateList templates;  
888 - if (!file.exists()) {  
889 - *done = true;  
890 - return templates;  
891 - }  
892 - QRegExp regexp("\\s*,\\s*");  
893 -  
894 - if (f.pos() == 0)  
895 - {  
896 - // read a line  
897 - QByteArray lineBytes = f.readLine();  
898 - QString line = QString::fromLocal8Bit(lineBytes).trimmed();  
899 - headers = line.split(regexp);  
900 - }  
901 -  
902 - for (qint64 i = 0; i < this->readBlockSize && !f.atEnd(); i++){  
903 - QByteArray lineBytes = f.readLine();  
904 - QString line = QString::fromLocal8Bit(lineBytes).trimmed();  
905 -  
906 - QStringList words = line.split(regexp);  
907 - if (words.size() != headers.size()) continue;  
908 - File fi;  
909 - for (int j=0; j<words.size(); j++) {  
910 - if (j == 0) fi.name = words[j];  
911 - else fi.set(headers[j], words[j]);  
912 - }  
913 - templates.append(fi);  
914 - templates.last().file.set("progress", f.pos());  
915 - }  
916 - *done = f.atEnd();  
917 -  
918 - return templates;  
919 - }  
920 -  
921 - void write(const Template &t)  
922 - {  
923 - files.append(t.file);  
924 - }  
925 -  
926 - static QString getCSVElement(const QString &key, const QVariant &value, bool header, int & columnCount)  
927 - {  
928 - if (header)  
929 - columnCount = 1;  
930 -  
931 - if (value.canConvert<QString>()) {  
932 - if (header) return key;  
933 - else {  
934 - if (columnCount != 1)  
935 - qFatal("Inconsistent datatype for key %s, csv file cannot be generated", qPrintable(key));  
936 - return value.value<QString>();  
937 - }  
938 - } else if (value.canConvert<QPointF>()) {  
939 - const QPointF point = value.value<QPointF>();  
940 - if (header) {  
941 - columnCount = 2;  
942 - return key+"_X,"+key+"_Y";  
943 - }  
944 - else {  
945 - if (columnCount != 2)  
946 - qFatal("Inconsistent datatype for key %s, csv file cannot be generated", qPrintable(key));  
947 -  
948 - return QString::number(point.x())+","+QString::number(point.y());  
949 - }  
950 - } else if (value.canConvert<QRectF>()) {  
951 - const QRectF rect = value.value<QRectF>();  
952 - if (header) {  
953 - columnCount = 4;  
954 - return key+"_X,"+key+"_Y,"+key+"_Width,"+key+"_Height";  
955 - }  
956 - else {  
957 - if (columnCount != 4)  
958 - qFatal("Inconsistent datatype for key %s, csv file cannot be generated", qPrintable(key));  
959 -  
960 - return QString::number(rect.x())+","+QString::number(rect.y())+","+QString::number(rect.width())+","+QString::number(rect.height());  
961 - }  
962 - } else {  
963 - if (header) return key;  
964 - else {  
965 - QString output = QString::number(std::numeric_limits<float>::quiet_NaN());  
966 - for (int i = 1; i < columnCount; i++)  
967 - output += "," + QString::number(std::numeric_limits<float>::quiet_NaN());  
968 - return output;  
969 - }  
970 - }  
971 - }  
972 -};  
973 -  
974 -BR_REGISTER(Gallery, csvGallery)  
975 -  
976 -/*!  
977 - * \ingroup galleries  
978 - * \brief Treats each line as a file.  
979 - * \author Josh Klontz \cite jklontz  
980 - *  
981 - * The entire line is treated as the file path. An optional label may be specified using a space ' ' separator:  
982 - *  
983 -\verbatim  
984 -<FILE>  
985 -<FILE>  
986 -...  
987 -<FILE>  
988 -\endverbatim  
989 - * or  
990 -\verbatim  
991 -<FILE> <LABEL>  
992 -<FILE> <LABEL>  
993 -...  
994 -<FILE> <LABEL>  
995 -\endverbatim  
996 - * \see csvGallery  
997 - */  
998 -class txtGallery : public FileGallery  
999 -{  
1000 - Q_OBJECT  
1001 - Q_PROPERTY(QString label READ get_label WRITE set_label RESET reset_label STORED false)  
1002 - BR_PROPERTY(QString, label, "")  
1003 -  
1004 - TemplateList readBlock(bool *done)  
1005 - {  
1006 - readOpen();  
1007 - *done = false;  
1008 - if (f.atEnd())  
1009 - f.seek(0);  
1010 -  
1011 - TemplateList templates;  
1012 -  
1013 - for (qint64 i = 0; i < readBlockSize; i++)  
1014 - {  
1015 - QByteArray lineBytes = f.readLine();  
1016 - QString line = QString::fromLocal8Bit(lineBytes).trimmed();  
1017 -  
1018 - if (!line.isEmpty()){  
1019 - int splitIndex = line.lastIndexOf(' ');  
1020 - if (splitIndex == -1) templates.append(File(line));  
1021 - else templates.append(File(line.mid(0, splitIndex), line.mid(splitIndex+1)));  
1022 - templates.last().file.set("progress", this->position());  
1023 - }  
1024 -  
1025 - if (f.atEnd()) {  
1026 - *done=true;  
1027 - break;  
1028 - }  
1029 - }  
1030 -  
1031 - return templates;  
1032 - }  
1033 -  
1034 - void write(const Template &t)  
1035 - {  
1036 - writeOpen();  
1037 - QString line = t.file.name;  
1038 - if (!label.isEmpty())  
1039 - line += " " + t.file.get<QString>(label);  
1040 -  
1041 - f.write((line+"\n").toLocal8Bit() );  
1042 - }  
1043 -};  
1044 -  
1045 -BR_REGISTER(Gallery, txtGallery)  
1046 -  
1047 -/*!  
1048 - * \ingroup galleries  
1049 - * \brief Treats each line as a call to File::flat()  
1050 - * \author Josh Klontz \cite jklontz  
1051 - */  
1052 -class flatGallery : public FileGallery  
1053 -{  
1054 - Q_OBJECT  
1055 -  
1056 - TemplateList readBlock(bool *done)  
1057 - {  
1058 - readOpen();  
1059 - *done = false;  
1060 - if (f.atEnd())  
1061 - f.seek(0);  
1062 -  
1063 - TemplateList templates;  
1064 -  
1065 - for (qint64 i = 0; i < readBlockSize; i++)  
1066 - {  
1067 - QByteArray line = f.readLine();  
1068 -  
1069 - if (!line.isEmpty()) {  
1070 - templates.append(File(QString::fromLocal8Bit(line).trimmed()));  
1071 - templates.last().file.set("progress", this->position());  
1072 - }  
1073 -  
1074 - if (f.atEnd()) {  
1075 - *done=true;  
1076 - break;  
1077 - }  
1078 - }  
1079 -  
1080 - return templates;  
1081 - }  
1082 -  
1083 - void write(const Template &t)  
1084 - {  
1085 - writeOpen();  
1086 - f.write((t.file.flat()+"\n").toLocal8Bit() );  
1087 - }  
1088 -};  
1089 -  
1090 -BR_REGISTER(Gallery, flatGallery)  
1091 -  
1092 -/*!  
1093 - * \ingroup galleries  
1094 - * \brief A \ref sigset input.  
1095 - * \author Josh Klontz \cite jklontz  
1096 - */  
1097 -class xmlGallery : public FileGallery  
1098 -{  
1099 - Q_OBJECT  
1100 - Q_PROPERTY(bool ignoreMetadata READ get_ignoreMetadata WRITE set_ignoreMetadata RESET reset_ignoreMetadata STORED false)  
1101 - BR_PROPERTY(bool, ignoreMetadata, false)  
1102 - FileList files;  
1103 -  
1104 - QXmlStreamReader reader;  
1105 -  
1106 - QString currentSignatureName;  
1107 - bool signatureActive;  
1108 -  
1109 - ~xmlGallery()  
1110 - {  
1111 - f.close();  
1112 - if (!files.isEmpty())  
1113 - BEE::writeSigset(file, files, ignoreMetadata);  
1114 - }  
1115 -  
1116 - TemplateList readBlock(bool *done)  
1117 - {  
1118 - if (readOpen())  
1119 - reader.setDevice(&f);  
1120 -  
1121 - if (reader.atEnd())  
1122 - f.seek(0);  
1123 -  
1124 - TemplateList templates;  
1125 - qint64 count = 0;  
1126 -  
1127 - while (!reader.atEnd())  
1128 - {  
1129 - // if an identity is active we try to read presentations  
1130 - if (signatureActive)  
1131 - {  
1132 - while (signatureActive)  
1133 - {  
1134 - QXmlStreamReader::TokenType signatureToken = reader.readNext();  
1135 -  
1136 - // did the signature end?  
1137 - if (signatureToken == QXmlStreamReader::EndElement && reader.name() == "biometric-signature") {  
1138 - signatureActive = false;  
1139 - break;  
1140 - }  
1141 -  
1142 - // did we reach the end of the document? Theoretically this shoudln't happen without reaching the end of  
1143 - if (signatureToken == QXmlStreamReader::EndDocument)  
1144 - break;  
1145 -  
1146 - // a presentation!  
1147 - if (signatureToken == QXmlStreamReader::StartElement && reader.name() == "presentation") {  
1148 - templates.append(Template(File("",currentSignatureName)));  
1149 - foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {  
1150 - // file-name is stored directly on file, not as a key/value pair  
1151 - if (attribute.name() == "file-name")  
1152 - templates.last().file.name = attribute.value().toString();  
1153 - // other values are directly set as metadata  
1154 - else if (!ignoreMetadata) templates.last().file.set(attribute.name().toString(), attribute.value().toString());  
1155 - }  
1156 -  
1157 - // a presentation can have bounding boxes as child elements  
1158 - QList<QRectF> rects = templates.last().file.rects();  
1159 - while (true)  
1160 - {  
1161 - QXmlStreamReader::TokenType pToken = reader.readNext();  
1162 - if (pToken == QXmlStreamReader::EndElement && reader.name() == "presentation")  
1163 - break;  
1164 -  
1165 - if (pToken == QXmlStreamReader::StartElement)  
1166 - {  
1167 - if (reader.attributes().hasAttribute("x")  
1168 - && reader.attributes().hasAttribute("y")  
1169 - && reader.attributes().hasAttribute("width")  
1170 - && reader.attributes().hasAttribute("height") )  
1171 - {  
1172 - // get bounding box properties as attributes, just going to assume this all works  
1173 - qreal x = reader.attributes().value("x").string()->toDouble();  
1174 - qreal y = reader.attributes().value("y").string()->toDouble();  
1175 - qreal width = reader.attributes().value("width").string()->toDouble();  
1176 - qreal height = reader.attributes().value("height").string()->toDouble();  
1177 - rects += QRectF(x, y, width, height);  
1178 - }  
1179 - }  
1180 - }  
1181 - templates.last().file.setRects(rects);  
1182 - templates.last().file.set("progress", f.pos());  
1183 -  
1184 - // we read another complete template  
1185 - count++;  
1186 - }  
1187 - }  
1188 - }  
1189 - // otherwise, keep reading elements until the next identity is reacehed  
1190 - else  
1191 - {  
1192 - QXmlStreamReader::TokenType token = reader.readNext();  
1193 -  
1194 - // end of file?  
1195 - if (token == QXmlStreamReader::EndDocument)  
1196 - break;  
1197 -  
1198 - // we are only interested in new elements  
1199 - if (token != QXmlStreamReader::StartElement)  
1200 - continue;  
1201 -  
1202 - QStringRef elName = reader.name();  
1203 -  
1204 - // biometric-signature-set is the root element  
1205 - if (elName == "biometric-signature-set")  
1206 - continue;  
1207 -  
1208 - // biometric-signature -- an identity  
1209 - if (elName == "biometric-signature")  
1210 - {  
1211 - // read the name associated with the current signature  
1212 - if (!reader.attributes().hasAttribute("name"))  
1213 - {  
1214 - qDebug() << "Biometric signature missing name";  
1215 - continue;  
1216 - }  
1217 - currentSignatureName = reader.attributes().value("name").toString();  
1218 - signatureActive = true;  
1219 -  
1220 - // If we've already read enough templates for this block, then break here.  
1221 - // We wait untill the start of the next signature to be sure that done should  
1222 - // actually be false (i.e. there are actually items left in this file)  
1223 - if (count >= this->readBlockSize) {  
1224 - *done = false;  
1225 - return templates;  
1226 - }  
1227 -  
1228 - }  
1229 - }  
1230 - }  
1231 - *done = true;  
1232 -  
1233 - return templates;  
1234 - }  
1235 -  
1236 - void write(const Template &t)  
1237 - {  
1238 - files.append(t.file);  
1239 - }  
1240 -  
1241 - void init()  
1242 - {  
1243 - FileGallery::init();  
1244 - }  
1245 -};  
1246 -  
1247 -BR_REGISTER(Gallery, xmlGallery)  
1248 -  
1249 -/*!  
1250 - * \ingroup galleries  
1251 - * \brief Treat the file as a single binary template.  
1252 - * \author Josh Klontz \cite jklontz  
1253 - */  
1254 -class templateGallery : public Gallery  
1255 -{  
1256 - Q_OBJECT  
1257 -  
1258 - TemplateList readBlock(bool *done)  
1259 - {  
1260 - *done = true;  
1261 - QByteArray data;  
1262 - QtUtils::readFile(file.name.left(file.name.size()-QString(".template").size()), data);  
1263 - return TemplateList() << Template(file, cv::Mat(1, data.size(), CV_8UC1, data.data()).clone());  
1264 - }  
1265 -  
1266 - void write(const Template &t)  
1267 - {  
1268 - (void) t;  
1269 - qFatal("No supported.");  
1270 - }  
1271 -  
1272 - void init()  
1273 - {  
1274 - //  
1275 - }  
1276 -};  
1277 -  
1278 -BR_REGISTER(Gallery, templateGallery)  
1279 -  
1280 -/*!  
1281 - * \ingroup galleries  
1282 - * \brief Database input.  
1283 - * \author Josh Klontz \cite jklontz  
1284 - */  
1285 -class dbGallery : public Gallery  
1286 -{  
1287 - Q_OBJECT  
1288 -  
1289 - TemplateList readBlock(bool *done)  
1290 - {  
1291 - TemplateList templates;  
1292 - br::File import = file.get<QString>("import", "");  
1293 - QString query = file.get<QString>("query");  
1294 - QString subset = file.get<QString>("subset", "");  
1295 -  
1296 -#ifndef BR_EMBEDDED  
1297 - QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");  
1298 - db.setDatabaseName(file);  
1299 - if (!db.open()) qFatal("Failed to open SQLite database %s.", qPrintable(file.name));  
1300 -  
1301 - if (!import.isNull()) {  
1302 - qDebug("Parsing %s", qPrintable(import.name));  
1303 - QStringList lines = QtUtils::readLines(import);  
1304 - QList<QStringList> cells; cells.reserve(lines.size());  
1305 - const QRegExp re("\\s*,\\s*");  
1306 - foreach (const QString &line, lines) {  
1307 - cells.append(line.split(re));  
1308 - if (cells.last().size() != cells.first().size()) qFatal("Column count mismatch.");  
1309 - }  
1310 -  
1311 - QStringList columns, qMarks;  
1312 - QList<QVariantList> variantLists;  
1313 - for (int i=0; i<cells[0].size(); i++) {  
1314 - bool isNumeric;  
1315 - cells[1][i].toInt(&isNumeric);  
1316 - columns.append(cells[0][i] + (isNumeric ? " INTEGER" : " STRING"));  
1317 - qMarks.append("?");  
1318 -  
1319 - QVariantList variantList; variantList.reserve(lines.size()-1);  
1320 - for (int j=1; j<lines.size(); j++) {  
1321 - if (isNumeric) variantList << cells[j][i].toInt();  
1322 - else variantList << cells[j][i];  
1323 - }  
1324 - variantLists.append(variantList);  
1325 - }  
1326 -  
1327 - const QString &table = import.baseName();  
1328 - qDebug("Creating table %s", qPrintable(table));  
1329 - QSqlQuery q(db);  
1330 - if (!q.exec("CREATE TABLE " + table + " (" + columns.join(", ") + ");"))  
1331 - qFatal("%s.", qPrintable(q.lastError().text()));  
1332 - if (!q.prepare("insert into " + table + " values (" + qMarks.join(", ") + ")"))  
1333 - qFatal("%s.", qPrintable(q.lastError().text()));  
1334 - foreach (const QVariantList &vl, variantLists)  
1335 - q.addBindValue(vl);  
1336 - if (!q.execBatch()) qFatal("%s.", qPrintable(q.lastError().text()));  
1337 - }  
1338 -  
1339 - QSqlQuery q(db);  
1340 - if (query.startsWith('\'') && query.endsWith('\''))  
1341 - query = query.mid(1, query.size()-2);  
1342 - if (!q.exec(query))  
1343 - qFatal("%s.", qPrintable(q.lastError().text()));  
1344 -  
1345 - if ((q.record().count() == 0) || (q.record().count() > 3))  
1346 - qFatal("Query record expected one to three fields, got %d.", q.record().count());  
1347 - const bool hasMetadata = (q.record().count() >= 2);  
1348 - const bool hasFilter = (q.record().count() >= 3);  
1349 -  
1350 - QString labelName = "Label";  
1351 - if (q.record().count() >= 2)  
1352 - labelName = q.record().fieldName(1);  
1353 -  
1354 - // subset = seed:subjectMaxSize:numSubjects:subjectMinSize or  
1355 - // subset = seed:{Metadata,...,Metadata}:numSubjects  
1356 - int seed = 0, subjectMaxSize = std::numeric_limits<int>::max(), numSubjects = std::numeric_limits<int>::max(), subjectMinSize = 0;  
1357 - QList<QRegExp> metadataFields;  
1358 - if (!subset.isEmpty()) {  
1359 - const QStringList &words = subset.split(":");  
1360 - QtUtils::checkArgsSize("Input", words, 2, 4);  
1361 - if (words[0] == "train") seed = 0;  
1362 - else if (words[0] == "test" ) seed = 1;  
1363 - else seed = QtUtils::toInt(words[0]);  
1364 - if (words[1].startsWith('{') && words[1].endsWith('}')) {  
1365 - foreach (const QString &regexp, words[1].mid(1, words[1].size()-2).split(","))  
1366 - metadataFields.append(QRegExp(regexp));  
1367 - subjectMaxSize = metadataFields.size();  
1368 - } else {  
1369 - subjectMaxSize = QtUtils::toInt(words[1]);  
1370 - }  
1371 - numSubjects = words.size() >= 3 ? QtUtils::toInt(words[2]) : std::numeric_limits<int>::max();  
1372 - subjectMinSize = words.size() >= 4 ? QtUtils::toInt(words[3]) : subjectMaxSize;  
1373 - }  
1374 -  
1375 - srand(seed);  
1376 -  
1377 - typedef QPair<QString,QString> Entry; // QPair<File,Metadata>  
1378 - QHash<QString, QList<Entry> > entries; // QHash<Label, QList<Entry> >  
1379 - while (q.next()) {  
1380 - if (hasFilter && (seed >= 0) && (qHash(q.value(2).toString()) % 2 != (uint)seed % 2)) continue; // Ensures training and testing filters don't overlap  
1381 -  
1382 - if (metadataFields.isEmpty())  
1383 - entries[hasMetadata ? q.value(1).toString() : ""].append(QPair<QString,QString>(q.value(0).toString(), hasFilter ? q.value(2).toString() : ""));  
1384 - else  
1385 - entries[hasFilter ? q.value(2).toString() : ""].append(QPair<QString,QString>(q.value(0).toString(), hasMetadata ? q.value(1).toString() : ""));  
1386 - }  
1387 -  
1388 - QStringList labels = entries.keys();  
1389 - qSort(labels);  
1390 -  
1391 - if (hasFilter && ((labels.size() > numSubjects) || (numSubjects == std::numeric_limits<int>::max())))  
1392 - std::random_shuffle(labels.begin(), labels.end());  
1393 -  
1394 - foreach (const QString &label, labels) {  
1395 - QList<Entry> entryList = entries[label];  
1396 - if ((entryList.size() >= subjectMinSize) && (numSubjects > 0)) {  
1397 -  
1398 - if (!metadataFields.isEmpty()) {  
1399 - QList<Entry> subEntryList;  
1400 - foreach (const QRegExp &metadata, metadataFields) {  
1401 - for (int i=0; i<entryList.size(); i++) {  
1402 - if (metadata.exactMatch(entryList[i].second)) {  
1403 - subEntryList.append(entryList.takeAt(i));  
1404 - break;  
1405 - }  
1406 - }  
1407 - }  
1408 - if (subEntryList.size() == metadataFields.size())  
1409 - entryList = subEntryList;  
1410 - else  
1411 - continue;  
1412 - }  
1413 -  
1414 - if (entryList.size() > subjectMaxSize)  
1415 - std::random_shuffle(entryList.begin(), entryList.end());  
1416 - foreach (const Entry &entry, entryList.mid(0, subjectMaxSize)) {  
1417 - templates.append(File(entry.first));  
1418 - templates.last().file.set(labelName, label);  
1419 - }  
1420 - numSubjects--;  
1421 - }  
1422 - }  
1423 -  
1424 - db.close();  
1425 -#endif // BR_EMBEDDED  
1426 -  
1427 - *done = true;  
1428 - return templates;  
1429 - }  
1430 -  
1431 - void write(const Template &t)  
1432 - {  
1433 - (void) t;  
1434 - qFatal("Not supported.");  
1435 - }  
1436 -  
1437 - void init()  
1438 - {  
1439 - //  
1440 - }  
1441 -};  
1442 -  
1443 -BR_REGISTER(Gallery, dbGallery)  
1444 -  
1445 -/*!  
1446 - * \ingroup inputs  
1447 - * \brief Input from a google image search.  
1448 - * \author Josh Klontz \cite jklontz  
1449 - */  
1450 -class googleGallery : public Gallery  
1451 -{  
1452 - Q_OBJECT  
1453 -  
1454 - TemplateList readBlock(bool *done)  
1455 - {  
1456 - TemplateList templates;  
1457 -  
1458 - static const QString search = "http://images.google.com/images?q=%1&start=%2";  
1459 - QString query = file.name.left(file.name.size()-7); // remove ".google"  
1460 -  
1461 -#ifndef BR_EMBEDDED  
1462 - QNetworkAccessManager networkAccessManager;  
1463 - for (int i=0; i<100; i+=20) { // Retrieve 100 images  
1464 - QNetworkRequest request(search.arg(query, QString::number(i)));  
1465 - QNetworkReply *reply = networkAccessManager.get(request);  
1466 -  
1467 - while (!reply->isFinished())  
1468 - QThread::yieldCurrentThread();  
1469 -  
1470 - QString data(reply->readAll());  
1471 - delete reply;  
1472 -  
1473 - QStringList words = data.split("imgurl=");  
1474 - words.takeFirst(); // Remove header  
1475 - foreach (const QString &word, words) {  
1476 - QString url = word.left(word.indexOf("&amp"));  
1477 - url = url.replace("%2520","%20");  
1478 - int junk = url.indexOf('%', url.lastIndexOf('.'));  
1479 - if (junk != -1) url = url.left(junk);  
1480 - templates.append(File(url,query));  
1481 - }  
1482 - }  
1483 -#endif // BR_EMBEDDED  
1484 -  
1485 - *done = true;  
1486 - return templates;  
1487 - }  
1488 -  
1489 - void write(const Template &)  
1490 - {  
1491 - qFatal("Not supported.");  
1492 - }  
1493 -};  
1494 -  
1495 -BR_REGISTER(Gallery, googleGallery)  
1496 -  
1497 -/*!  
1498 - * \ingroup galleries  
1499 - * \brief Print template statistics.  
1500 - * \author Josh Klontz \cite jklontz  
1501 - */  
1502 -class statGallery : public Gallery  
1503 -{  
1504 - Q_OBJECT  
1505 - QSet<QString> subjects;  
1506 - QList<int> bytes;  
1507 -  
1508 - ~statGallery()  
1509 - {  
1510 - int emptyTemplates = 0;  
1511 - for (int i=bytes.size()-1; i>=0; i--)  
1512 - if (bytes[i] == 0) {  
1513 - bytes.removeAt(i);  
1514 - emptyTemplates++;  
1515 - }  
1516 -  
1517 - double bytesMean, bytesStdDev;  
1518 - Common::MeanStdDev(bytes, &bytesMean, &bytesStdDev);  
1519 - printf("Subjects: %d\nEmpty Templates: %d/%d\nBytes/Template: %.4g +/- %.4g\n",  
1520 - subjects.size(), emptyTemplates, emptyTemplates+bytes.size(), bytesMean, bytesStdDev);  
1521 - }  
1522 -  
1523 - TemplateList readBlock(bool *done)  
1524 - {  
1525 - *done = true;  
1526 - return TemplateList() << file;  
1527 - }  
1528 -  
1529 - void write(const Template &t)  
1530 - {  
1531 - subjects.insert(t.file.get<QString>("Label"));  
1532 - bytes.append(t.bytes());  
1533 - }  
1534 -};  
1535 -  
1536 -BR_REGISTER(Gallery, statGallery)  
1537 -  
1538 -/*!  
1539 - * \ingroup galleries  
1540 - * \brief Implements the FDDB detection format.  
1541 - * \author Josh Klontz \cite jklontz  
1542 - *  
1543 - * http://vis-www.cs.umass.edu/fddb/README.txt  
1544 - */  
1545 -class FDDBGallery : public Gallery  
1546 -{  
1547 - Q_OBJECT  
1548 -  
1549 - TemplateList readBlock(bool *done)  
1550 - {  
1551 - *done = true;  
1552 - QStringList lines = QtUtils::readLines(file);  
1553 - TemplateList templates;  
1554 - while (!lines.empty()) {  
1555 - const QString fileName = lines.takeFirst();  
1556 - int numDetects = lines.takeFirst().toInt();  
1557 - for (int i=0; i<numDetects; i++) {  
1558 - const QStringList detect = lines.takeFirst().split(' ');  
1559 - Template t(fileName);  
1560 - QList<QVariant> faceList; //to be consistent with slidingWindow  
1561 - if (detect.size() == 5) { //rectangle  
1562 - faceList.append(QRectF(detect[0].toFloat(), detect[1].toFloat(), detect[2].toFloat(), detect[3].toFloat()));  
1563 - t.file.set("Confidence", detect[4].toFloat());  
1564 - } else if (detect.size() == 6) { //ellipse  
1565 - float x = detect[3].toFloat(),  
1566 - y = detect[4].toFloat(),  
1567 - radius = detect[1].toFloat();  
1568 - faceList.append(QRectF(x - radius,y - radius,radius * 2.0, radius * 2.0));  
1569 - t.file.set("Confidence", detect[5].toFloat());  
1570 - } else {  
1571 - qFatal("Unknown FDDB annotation format.");  
1572 - }  
1573 - t.file.set("Face", faceList);  
1574 - t.file.set("Label",QString("face"));  
1575 - templates.append(t);  
1576 - }  
1577 - }  
1578 - return templates;  
1579 - }  
1580 -  
1581 - void write(const Template &t)  
1582 - {  
1583 - (void) t;  
1584 - qFatal("Not implemented.");  
1585 - }  
1586 -  
1587 - void init()  
1588 - {  
1589 - //  
1590 - }  
1591 -};  
1592 -  
1593 -BR_REGISTER(Gallery, FDDBGallery)  
1594 -  
1595 -/*!  
1596 - * \ingroup galleries  
1597 - * \brief Text format for associating anonymous landmarks with images.  
1598 - * \author Josh Klontz \cite jklontz  
1599 - *  
1600 - * \code  
1601 - * file_name:x1,y1,x2,y2,...,xn,yn  
1602 - * file_name:x1,y1,x2,y2,...,xn,yn  
1603 - * ...  
1604 - * file_name:x1,y1,x2,y2,...,xn,yn  
1605 - * \endcode  
1606 - */  
1607 -class landmarksGallery : public Gallery  
1608 -{  
1609 - Q_OBJECT  
1610 -  
1611 - TemplateList readBlock(bool *done)  
1612 - {  
1613 - *done = true;  
1614 - TemplateList templates;  
1615 - foreach (const QString &line, QtUtils::readLines(file)) {  
1616 - const QStringList words = line.split(':');  
1617 - if (words.size() != 2) qFatal("Expected exactly one ':' in: %s.", qPrintable(line));  
1618 - File file(words[0]);  
1619 - const QList<float> vals = QtUtils::toFloats(words[1].split(','));  
1620 - if (vals.size() % 2 != 0) qFatal("Expected an even number of comma-separated values.");  
1621 - QList<QPointF> points; points.reserve(vals.size()/2);  
1622 - for (int i=0; i<vals.size(); i+=2)  
1623 - points.append(QPointF(vals[i], vals[i+1]));  
1624 - file.setPoints(points);  
1625 - templates.append(file);  
1626 - }  
1627 - return templates;  
1628 - }  
1629 -  
1630 - void write(const Template &t)  
1631 - {  
1632 - (void) t;  
1633 - qFatal("Not implemented.");  
1634 - }  
1635 -  
1636 - void init()  
1637 - {  
1638 - //  
1639 - }  
1640 -};  
1641 -  
1642 -BR_REGISTER(Gallery, landmarksGallery)  
1643 -  
1644 -#ifdef CVMATIO  
1645 -  
1646 -using namespace cv;  
1647 -  
1648 -class vbbGallery : public Gallery  
1649 -{  
1650 - Q_OBJECT  
1651 -  
1652 - void init()  
1653 - {  
1654 - MatlabIO matio;  
1655 - QString filename = (Globals->path.isEmpty() ? "" : Globals->path + "/") + file.name;  
1656 - bool ok = matio.open(filename.toStdString(), "r");  
1657 - if (!ok) qFatal("Couldn't open the vbb file");  
1658 -  
1659 - vector<MatlabIOContainer> variables;  
1660 - variables = matio.read();  
1661 - matio.close();  
1662 -  
1663 - double vers = variables[1].data<Mat>().at<double>(0,0);  
1664 - if (vers != 1.4) qFatal("This is an old vbb version, we don't mess with that.");  
1665 -  
1666 - A = variables[0].data<vector<vector<MatlabIOContainer> > >().at(0);  
1667 - objLists = A.at(1).data<vector<MatlabIOContainer> >();  
1668 -  
1669 - // start at the first frame (duh!)  
1670 - currFrame = 0;  
1671 - }  
1672 -  
1673 - TemplateList readBlock(bool *done)  
1674 - {  
1675 - *done = false;  
1676 - Template rects(file);  
1677 - if (objLists[currFrame].typeEquals<vector<vector<MatlabIOContainer> > >()) {  
1678 - vector<vector<MatlabIOContainer> > bbs = objLists[currFrame].data<vector<vector<MatlabIOContainer> > >();  
1679 - for (unsigned int i=0; i<bbs.size(); i++) {  
1680 - vector<MatlabIOContainer> bb = bbs[i];  
1681 - Mat pos = bb[1].data<Mat>();  
1682 - double left = pos.at<double>(0,0);  
1683 - double top = pos.at<double>(0,1);  
1684 - double width = pos.at<double>(0,2);  
1685 - double height = pos.at<double>(0,3);  
1686 - rects.file.appendRect(QRectF(left, top, width, height));  
1687 - }  
1688 - }  
1689 - TemplateList tl;  
1690 - tl.append(rects);  
1691 - if (++currFrame == (int)objLists.size()) *done = true;  
1692 - return tl;  
1693 - }  
1694 -  
1695 - void write(const Template &t)  
1696 - {  
1697 - (void)t; qFatal("Not implemented");  
1698 - }  
1699 -  
1700 -private:  
1701 - // this holds a bunch of stuff, maybe we'll use it all later  
1702 - vector<MatlabIOContainer> A;  
1703 - // this, a field in A, holds bounding boxes for each frame  
1704 - vector<MatlabIOContainer> objLists;  
1705 - int currFrame;  
1706 -};  
1707 -  
1708 -BR_REGISTER(Gallery, vbbGallery)  
1709 -  
1710 -#endif  
1711 -  
1712 -  
1713 -// Read a video frame by frame using cv::VideoCapture  
1714 -class videoGallery : public Gallery  
1715 -{  
1716 - Q_OBJECT  
1717 -public:  
1718 - qint64 idx;  
1719 - ~videoGallery()  
1720 - {  
1721 - video.release();  
1722 - }  
1723 -  
1724 - static QMutex openLock;  
1725 -  
1726 - virtual void deferredInit()  
1727 - {  
1728 - bool status = video.open(QtUtils::getAbsolutePath(file.name).toStdString());  
1729 -  
1730 - if (!status)  
1731 - qFatal("Failed to open file %s with path %s", qPrintable(file.name), qPrintable(QtUtils::getAbsolutePath(file.name)));  
1732 - }  
1733 -  
1734 - TemplateList readBlock(bool *done)  
1735 - {  
1736 - if (!video.isOpened()) {  
1737 - // opening videos appears to not be thread safe on windows  
1738 - QMutexLocker lock(&openLock);  
1739 -  
1740 - deferredInit();  
1741 - idx = 0;  
1742 - }  
1743 -  
1744 - Template output;  
1745 - output.file = file;  
1746 - output.m() = cv::Mat();  
1747 -  
1748 - cv::Mat temp;  
1749 - bool res = video.read(temp);  
1750 -  
1751 - if (!res) {  
1752 - // The video capture broke, return an empty list.  
1753 - output.m() = cv::Mat();  
1754 - video.release();  
1755 - *done = true;  
1756 - return TemplateList();  
1757 - }  
1758 -  
1759 - // This clone is critical, if we don't do it then the output matrix will  
1760 - // be an alias of an internal buffer of the video source, leading to various  
1761 - // problems later.  
1762 - output.m() = temp.clone();  
1763 -  
1764 - output.file.set("progress", idx);  
1765 - idx++;  
1766 -  
1767 - TemplateList rVal;  
1768 - rVal.append(temp);  
1769 - *done = false;  
1770 - return rVal;  
1771 - }  
1772 -  
1773 - void write(const Template &t)  
1774 - {  
1775 - (void)t; qFatal("Not implemented");  
1776 - }  
1777 -  
1778 -protected:  
1779 - cv::VideoCapture video;  
1780 -};  
1781 -BR_REGISTER(Gallery,videoGallery)  
1782 -  
1783 -QMutex videoGallery::openLock;  
1784 -  
1785 -class aviGallery : public videoGallery  
1786 -{  
1787 - Q_OBJECT  
1788 -};  
1789 -BR_REGISTER(Gallery, aviGallery)  
1790 -  
1791 -class wmvGallery : public videoGallery  
1792 -{  
1793 - Q_OBJECT  
1794 -};  
1795 -BR_REGISTER(Gallery, wmvGallery)  
1796 -  
1797 -// Mostly the same as videoGallery, but we open the VideoCapture with an integer index  
1798 -// rather than file name/web address  
1799 -class webcamGallery : public videoGallery  
1800 -{  
1801 -public:  
1802 - Q_OBJECT  
1803 -  
1804 - void deferredInit()  
1805 - {  
1806 - bool intOK = false;  
1807 - int anInt = file.baseName().toInt(&intOK);  
1808 -  
1809 - if (!intOK)  
1810 - qFatal("Expected integer basename, got %s", qPrintable(file.baseName()));  
1811 -  
1812 - bool rc = video.open(anInt);  
1813 -  
1814 - if (!rc)  
1815 - qFatal("Failed to open webcam with index: %s", qPrintable(file.baseName()));  
1816 - }  
1817 -  
1818 -};  
1819 -BR_REGISTER(Gallery,webcamGallery)  
1820 -  
1821 -class seqGallery : public Gallery  
1822 -{  
1823 -public:  
1824 - Q_OBJECT  
1825 -  
1826 - bool open()  
1827 - {  
1828 - seqFile.open(QtUtils::getAbsolutePath(file.name).toStdString().c_str(), std::ios::in | std::ios::binary | std::ios::ate);  
1829 - if (!isOpen()) {  
1830 - qDebug("Failed to open file %s for reading", qPrintable(file.name));  
1831 - return false;  
1832 - }  
1833 -  
1834 - int headSize = 1024;  
1835 - // start at end of file to get full size  
1836 - int fileSize = seqFile.tellg();  
1837 - if (fileSize < headSize) {  
1838 - qDebug("No header in seq file");  
1839 - return false;  
1840 - }  
1841 -  
1842 - // first 4 bytes store 0xEDFE, next 24 store 'Norpix seq '  
1843 - char firstFour[4];  
1844 - seqFile.seekg(0, std::ios::beg);  
1845 - seqFile.read(firstFour, 4);  
1846 - char nextTwentyFour[24];  
1847 - readText(24, nextTwentyFour);  
1848 - if (firstFour[0] != (char)0xED || firstFour[1] != (char)0xFE || strncmp(nextTwentyFour, "Norpix seq", 10) != 0) {  
1849 - qDebug("Invalid header in seq file");  
1850 - return false;  
1851 - }  
1852 -  
1853 - // next 8 bytes for version (skipped below) and header size (1024), then 512 for descr  
1854 - seqFile.seekg(4, std::ios::cur);  
1855 - int hSize = readInt();  
1856 - if (hSize != headSize) {  
1857 - qDebug("Invalid header size");  
1858 - return false;  
1859 - }  
1860 - char desc[512];  
1861 - readText(512, desc);  
1862 - file.set("Description", QString(desc));  
1863 -  
1864 - width = readInt();  
1865 - height = readInt();  
1866 - // get # channels from bit depth  
1867 - numChan = readInt()/8;  
1868 - int imageBitDepthReal = readInt();  
1869 - if (imageBitDepthReal != 8) {  
1870 - qDebug("Invalid bit depth");  
1871 - return false;  
1872 - }  
1873 - // the size of just the image part of a raw img  
1874 - imgSizeBytes = readInt();  
1875 -  
1876 - int imgFormatInt = readInt();  
1877 - if (imgFormatInt == 100 || imgFormatInt == 200 || imgFormatInt == 101) {  
1878 - imgFormat = "raw";  
1879 - } else if (imgFormatInt == 102 || imgFormatInt == 201 || imgFormatInt == 103 ||  
1880 - imgFormatInt == 1 || imgFormatInt == 2) {  
1881 - imgFormat = "compressed";  
1882 - } else {  
1883 - qFatal("unsupported image format");  
1884 - }  
1885 -  
1886 - numFrames = readInt();  
1887 - // skip empty int  
1888 - seqFile.seekg(4, std::ios::cur);  
1889 - // the size of a full raw file, with extra crap after img data  
1890 - trueImgSizeBytes = readInt();  
1891 -  
1892 - // gather all the frame positions in an array  
1893 - seekPos.reserve(numFrames);  
1894 - // start at end of header  
1895 - seekPos.append(headSize);  
1896 - // extra 8 bytes at end of img  
1897 - int extra = 8;  
1898 - for (int i=1; i<numFrames; i++) {  
1899 - int s;  
1900 - // compressed images have different sizes  
1901 - // the first byte at the beginning of the file  
1902 - // says how big the current img is  
1903 - if (imgFormat == "compressed") {  
1904 - int lastPos = seekPos[i-1];  
1905 - seqFile.seekg(lastPos, std::ios::beg);  
1906 - int currSize = readInt();  
1907 - s = lastPos + currSize + extra;  
1908 -  
1909 - // but there might be 16 extra bytes instead of 8...  
1910 - if (i == 1) {  
1911 - seqFile.seekg(s, std::ios::beg);  
1912 - char zero;  
1913 - seqFile.read(&zero, 1);  
1914 - if (zero == 0) {  
1915 - s += 8;  
1916 - extra += 8;  
1917 - }  
1918 - }  
1919 - }  
1920 - // raw images are all the same size  
1921 - else {  
1922 - s = headSize + (i*trueImgSizeBytes);  
1923 - }  
1924 -  
1925 - seekPos.enqueue(s);  
1926 - }  
1927 -  
1928 -#ifdef CVMATIO  
1929 - if (basis.file.contains("vbb")) {  
1930 - QString vbb = basis.file.get<QString>("vbb");  
1931 - annotations = TemplateList::fromGallery(File(vbb));  
1932 - }  
1933 -#else  
1934 - qWarning("cvmatio not installed, bounding boxes will not be available. Add -DBR_WITH_CVMATIO cmake flag to install.");  
1935 -#endif  
1936 -  
1937 - return true;  
1938 - }  
1939 -  
1940 - bool isOpen()  
1941 - {  
1942 - return seqFile.is_open();  
1943 - }  
1944 -  
1945 - void close()  
1946 - {  
1947 - seqFile.close();  
1948 - }  
1949 -  
1950 - TemplateList readBlock(bool *done)  
1951 - {  
1952 - if (!isOpen()) {  
1953 - if (!open())  
1954 - qFatal("Failed to open file %s for reading", qPrintable(file.name));  
1955 - else  
1956 - idx = 0;  
1957 - }  
1958 -  
1959 - // if we've reached the last frame, we're done  
1960 - if (seekPos.size() == 0) {  
1961 - *done = true;  
1962 - return TemplateList();  
1963 - }  
1964 -  
1965 - seqFile.seekg(seekPos.dequeue(), std::ios::beg);  
1966 -  
1967 - cv::Mat temp;  
1968 - // let imdecode do all the work to decode the compressed img  
1969 - if (imgFormat == "compressed") {  
1970 - int imgSize = readInt() - 4;  
1971 - std::vector<char> imgBuf(imgSize);  
1972 - seqFile.read(&imgBuf[0], imgSize);  
1973 - // flags < 0 means load image as-is (keep color info if available)  
1974 - cv::imdecode(imgBuf, -1, &temp);  
1975 - }  
1976 - // raw images can be loaded straight into a Mat  
1977 - else {  
1978 - char *imgBuf = new char[imgSizeBytes];  
1979 - seqFile.read(imgBuf, imgSizeBytes);  
1980 - int type = (numChan == 1 ? CV_8UC1 : CV_8UC3);  
1981 - temp = cv::Mat(height, width, type, imgBuf);  
1982 - }  
1983 - Template output;  
1984 - output.file = file;  
1985 - if (!annotations.empty()) {  
1986 - output.file.setRects(annotations.first().file.rects());  
1987 - annotations.removeFirst();  
1988 - }  
1989 - output.m() = temp;  
1990 - output.file.set("position",idx);  
1991 - idx++;  
1992 -  
1993 - *done = false;  
1994 - TemplateList rVal;  
1995 - rVal.append(output);  
1996 -  
1997 - return rVal;  
1998 - }  
1999 -  
2000 - void write(const Template &t)  
2001 - {  
2002 - (void) t;  
2003 - qFatal("Not implemented.");  
2004 - }  
2005 -  
2006 -private:  
2007 - qint64 idx;  
2008 - int readInt()  
2009 - {  
2010 - int num;  
2011 - seqFile.read((char*)&num, 4);  
2012 - return num;  
2013 - }  
2014 -  
2015 - // apparently the text in seq files is 16 bit characters (UTF-16?)  
2016 - // since we don't really need the last byte, snad since it gets interpreted as  
2017 - // a terminating char, let's just grab the first byte for storage  
2018 - void readText(int bytes, char *buffer)  
2019 - {  
2020 - seqFile.read(buffer, bytes);  
2021 - for (int i=0; i<bytes; i+=2) {  
2022 - buffer[i/2] = buffer[i];  
2023 - }  
2024 - buffer[bytes/2] = '\0';  
2025 - }  
2026 -  
2027 -protected:  
2028 - std::ifstream seqFile;  
2029 - QQueue<int> seekPos;  
2030 - int width, height, numChan, imgSizeBytes, trueImgSizeBytes, numFrames;  
2031 - QString imgFormat;  
2032 - TemplateList annotations;  
2033 -};  
2034 -BR_REGISTER(Gallery, seqGallery)  
2035 -  
2036 -void FileGallery::init()  
2037 -{  
2038 - f.setFileName(file);  
2039 -  
2040 - Gallery::init();  
2041 -}  
2042 -  
2043 -void FileGallery::writeOpen()  
2044 -{  
2045 - if (!f.isOpen() ) {  
2046 - QtUtils::touchDir(f);  
2047 - if (!f.open(QFile::WriteOnly))  
2048 - qFatal("Failed to open %s for writing.", qPrintable(file));  
2049 - }  
2050 -}  
2051 -  
2052 -bool FileGallery::readOpen()  
2053 -{  
2054 - if (!f.isOpen() ) {  
2055 - if (!f.exists() ) {  
2056 - qFatal("File %s does not exist.", qPrintable(file));  
2057 - }  
2058 -  
2059 - if (!f.open(QFile::ReadOnly))  
2060 - qFatal("Failed to open %s for reading.", qPrintable(file));  
2061 - return true;  
2062 - }  
2063 - return false;  
2064 -}  
2065 -  
2066 -qint64 FileGallery::totalSize()  
2067 -{  
2068 - readOpen();  
2069 - return f.size();  
2070 -}  
2071 -  
2072 -  
2073 -} // namespace br  
2074 -  
2075 -#include "gallery.moc"  
openbr/plugins/gallery/arff.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +
  4 +namespace br
  5 +{
  6 +
  7 +/*!
  8 + * \ingroup galleries
  9 + * \brief Weka ARFF file format.
  10 + * \author Josh Klontz \cite jklontz
  11 + * http://weka.wikispaces.com/ARFF+%28stable+version%29
  12 + */
  13 +class arffGallery : public Gallery
  14 +{
  15 + Q_OBJECT
  16 + QFile arffFile;
  17 +
  18 + TemplateList readBlock(bool *done)
  19 + {
  20 + (void) done;
  21 + qFatal("Not implemented.");
  22 + return TemplateList();
  23 + }
  24 +
  25 + void write(const Template &t)
  26 + {
  27 + if (!arffFile.isOpen()) {
  28 + arffFile.setFileName(file.name);
  29 + arffFile.open(QFile::WriteOnly);
  30 + arffFile.write("% OpenBR templates\n"
  31 + "@RELATION OpenBR\n"
  32 + "\n");
  33 +
  34 + const int dimensions = t.m().rows * t.m().cols;
  35 + for (int i=0; i<dimensions; i++)
  36 + arffFile.write(qPrintable("@ATTRIBUTE v" + QString::number(i) + " REAL\n"));
  37 + arffFile.write(qPrintable("@ATTRIBUTE class string\n"));
  38 +
  39 + arffFile.write("\n@DATA\n");
  40 + }
  41 +
  42 + arffFile.write(qPrintable(OpenCVUtils::matrixToStringList(t).join(',')));
  43 + arffFile.write(qPrintable(",'" + t.file.get<QString>("Label") + "'\n"));
  44 + }
  45 +};
  46 +
  47 +BR_REGISTER(Gallery, arffGallery)
  48 +
  49 +} // namespace br
  50 +
  51 +#include "gallery/arff.moc"
openbr/plugins/gallery/binary.cpp 0 → 100644
  1 +#include <QJsonObject>
  2 +#include <QJsonParseError>
  3 +
  4 +#include <openbr/plugins/openbr_internal.h>
  5 +#include <openbr/core/qtutils.h>
  6 +#include <openbr/universal_template.h>
  7 +
  8 +namespace br
  9 +{
  10 +
  11 +class BinaryGallery : public Gallery
  12 +{
  13 + Q_OBJECT
  14 +
  15 + void init()
  16 + {
  17 + const QString baseName = file.baseName();
  18 +
  19 + if (baseName == "stdin") {
  20 +#ifdef _WIN32
  21 + if(_setmode(_fileno(stdin), _O_BINARY) == -1)
  22 + qFatal("Failed to set stdin to binary mode!");
  23 +#endif // _WIN32
  24 +
  25 + gallery.open(stdin, QFile::ReadOnly);
  26 + } else if (baseName == "stdout") {
  27 +#ifdef _WIN32
  28 + if(_setmode(_fileno(stdout), _O_BINARY) == -1)
  29 + qFatal("Failed to set stdout to binary mode!");
  30 +#endif // _WIN32
  31 +
  32 + gallery.open(stdout, QFile::WriteOnly);
  33 + } else if (baseName == "stderr") {
  34 +#ifdef _WIN32
  35 + if(_setmode(_fileno(stderr), _O_BINARY) == -1)
  36 + qFatal("Failed to set stderr to binary mode!");
  37 +#endif // _WIN32
  38 +
  39 + gallery.open(stderr, QFile::WriteOnly);
  40 + } else {
  41 + // Defer opening the file, in the general case we don't know if we
  42 + // need read or write mode yet
  43 + return;
  44 + }
  45 + stream.setDevice(&gallery);
  46 + }
  47 +
  48 + void readOpen()
  49 + {
  50 + if (!gallery.isOpen()) {
  51 + gallery.setFileName(file);
  52 + if (!gallery.exists())
  53 + qFatal("File %s does not exist", qPrintable(gallery.fileName()));
  54 +
  55 + QFile::OpenMode mode = QFile::ReadOnly;
  56 + if (!gallery.open(mode))
  57 + qFatal("Can't open gallery: %s for reading", qPrintable(gallery.fileName()));
  58 + stream.setDevice(&gallery);
  59 + }
  60 + }
  61 +
  62 + void writeOpen()
  63 + {
  64 + if (!gallery.isOpen()) {
  65 + gallery.setFileName(file);
  66 +
  67 + // Do we remove the pre-existing gallery?
  68 + if (file.get<bool>("remove"))
  69 + gallery.remove();
  70 + QtUtils::touchDir(gallery);
  71 + QFile::OpenMode mode = QFile::WriteOnly;
  72 +
  73 + // Do we append?
  74 + if (file.get<bool>("append"))
  75 + mode |= QFile::Append;
  76 +
  77 + if (!gallery.open(mode))
  78 + qFatal("Can't open gallery: %s for writing", qPrintable(gallery.fileName()));
  79 + stream.setDevice(&gallery);
  80 + }
  81 + }
  82 +
  83 + TemplateList readBlock(bool *done)
  84 + {
  85 + readOpen();
  86 + if (gallery.atEnd())
  87 + gallery.seek(0);
  88 +
  89 + TemplateList templates;
  90 + while ((templates.size() < readBlockSize) && !gallery.atEnd()) {
  91 + const Template t = readTemplate();
  92 + if (!t.isEmpty() || !t.file.isNull()) {
  93 + templates.append(t);
  94 + templates.last().file.set("progress", position());
  95 + }
  96 +
  97 + // Special case for pipes where we want to process data as soon as it is available
  98 + if (gallery.isSequential())
  99 + break;
  100 + }
  101 +
  102 + *done = gallery.atEnd();
  103 + return templates;
  104 + }
  105 +
  106 + void write(const Template &t)
  107 + {
  108 + writeOpen();
  109 + writeTemplate(t);
  110 + if (gallery.isSequential())
  111 + gallery.flush();
  112 + }
  113 +
  114 +protected:
  115 + QFile gallery;
  116 + QDataStream stream;
  117 +
  118 + qint64 totalSize()
  119 + {
  120 + readOpen();
  121 + return gallery.size();
  122 + }
  123 +
  124 + qint64 position()
  125 + {
  126 + return gallery.pos();
  127 + }
  128 +
  129 + virtual Template readTemplate() = 0;
  130 + virtual void writeTemplate(const Template &t) = 0;
  131 +};
  132 +
  133 +/*!
  134 + * \ingroup galleries
  135 + * \brief A binary gallery.
  136 + *
  137 + * Designed to be a literal translation of templates to disk.
  138 + * Compatible with TemplateList::fromBuffer.
  139 + * \author Josh Klontz \cite jklontz
  140 + */
  141 +class galGallery : public BinaryGallery
  142 +{
  143 + Q_OBJECT
  144 +
  145 + Template readTemplate()
  146 + {
  147 + Template t;
  148 + stream >> t;
  149 + return t;
  150 + }
  151 +
  152 + void writeTemplate(const Template &t)
  153 + {
  154 + if (t.isEmpty() && t.file.isNull())
  155 + return;
  156 + else if (t.file.fte)
  157 + stream << Template(t.file); // only write metadata for failure to enroll
  158 + else
  159 + stream << t;
  160 + }
  161 +};
  162 +
  163 +BR_REGISTER(Gallery, galGallery)
  164 +
  165 +/*!
  166 + * \ingroup galleries
  167 + * \brief A contiguous array of br_universal_template.
  168 + * \author Josh Klontz \cite jklontz
  169 + */
  170 +class utGallery : public BinaryGallery
  171 +{
  172 + Q_OBJECT
  173 +
  174 + Template readTemplate()
  175 + {
  176 + Template t;
  177 + br_universal_template ut;
  178 + if (gallery.read((char*)&ut, sizeof(br_universal_template)) == sizeof(br_universal_template)) {
  179 + QByteArray data(ut.urlSize + ut.fvSize, Qt::Uninitialized);
  180 + char *dst = data.data();
  181 + qint64 bytesNeeded = ut.urlSize + ut.fvSize;
  182 + while (bytesNeeded > 0) {
  183 + qint64 bytesRead = gallery.read(dst, bytesNeeded);
  184 + if (bytesRead <= 0) {
  185 + qDebug() << gallery.errorString();
  186 + qFatal("Unexepected EOF while reading universal template data, needed: %d more of: %d bytes.", int(bytesNeeded), int(ut.urlSize + ut.fvSize));
  187 + }
  188 + bytesNeeded -= bytesRead;
  189 + dst += bytesRead;
  190 + }
  191 +
  192 + t.file.set("ImageID", QVariant(QByteArray((const char*)ut.imageID, 16).toHex()));
  193 + t.file.set("AlgorithmID", ut.algorithmID);
  194 + t.file.set("URL", QString(data.data()));
  195 + char *dataStart = data.data() + ut.urlSize;
  196 + uint32_t dataSize = ut.fvSize;
  197 + if ((ut.algorithmID <= -1) && (ut.algorithmID >= -3)) {
  198 + t.file.set("FrontalFace", QRectF(ut.x, ut.y, ut.width, ut.height));
  199 + uint32_t *rightEyeX = reinterpret_cast<uint32_t*>(dataStart);
  200 + dataStart += sizeof(uint32_t);
  201 + uint32_t *rightEyeY = reinterpret_cast<uint32_t*>(dataStart);
  202 + dataStart += sizeof(uint32_t);
  203 + uint32_t *leftEyeX = reinterpret_cast<uint32_t*>(dataStart);
  204 + dataStart += sizeof(uint32_t);
  205 + uint32_t *leftEyeY = reinterpret_cast<uint32_t*>(dataStart);
  206 + dataStart += sizeof(uint32_t);
  207 + dataSize -= sizeof(uint32_t)*4;
  208 + t.file.set("First_Eye", QPointF(*rightEyeX, *rightEyeY));
  209 + t.file.set("Second_Eye", QPointF(*leftEyeX, *leftEyeY));
  210 + } else {
  211 + t.file.set("X", ut.x);
  212 + t.file.set("Y", ut.y);
  213 + t.file.set("Width", ut.width);
  214 + t.file.set("Height", ut.height);
  215 + }
  216 + t.file.set("Label", ut.label);
  217 + t.append(cv::Mat(1, dataSize, CV_8UC1, dataStart).clone() /* We don't want a shallow copy! */);
  218 + } else {
  219 + if (!gallery.atEnd())
  220 + qFatal("Failed to read universal template header!");
  221 + }
  222 + return t;
  223 + }
  224 +
  225 + void writeTemplate(const Template &t)
  226 + {
  227 + const QByteArray imageID = QByteArray::fromHex(t.file.get<QByteArray>("ImageID", QByteArray(32, '0')));
  228 + if (imageID.size() != 16)
  229 + qFatal("Expected 16-byte ImageID, got: %d bytes.", imageID.size());
  230 +
  231 + const int32_t algorithmID = (t.isEmpty() || t.file.fte) ? 0 : t.file.get<int32_t>("AlgorithmID");
  232 + const QByteArray url = t.file.get<QString>("URL", t.file.name).toLatin1();
  233 +
  234 + uint32_t x = 0, y = 0, width = 0, height = 0;
  235 + QByteArray header;
  236 + if ((algorithmID <= -1) && (algorithmID >= -3)) {
  237 + const QRectF frontalFace = t.file.get<QRectF>("FrontalFace");
  238 + x = frontalFace.x();
  239 + y = frontalFace.y();
  240 + width = frontalFace.width();
  241 + height = frontalFace.height();
  242 +
  243 + const QPointF firstEye = t.file.get<QPointF>("First_Eye");
  244 + const QPointF secondEye = t.file.get<QPointF>("Second_Eye");
  245 + const uint32_t rightEyeX = firstEye.x();
  246 + const uint32_t rightEyeY = firstEye.y();
  247 + const uint32_t leftEyeX = secondEye.x();
  248 + const uint32_t leftEyeY = secondEye.y();
  249 +
  250 + header.append((const char*)&rightEyeX, sizeof(uint32_t));
  251 + header.append((const char*)&rightEyeY, sizeof(uint32_t));
  252 + header.append((const char*)&leftEyeX , sizeof(uint32_t));
  253 + header.append((const char*)&leftEyeY , sizeof(uint32_t));
  254 + } else {
  255 + x = t.file.get<uint32_t>("X", 0);
  256 + y = t.file.get<uint32_t>("Y", 0);
  257 + width = t.file.get<uint32_t>("Width", 0);
  258 + height = t.file.get<uint32_t>("Height", 0);
  259 + }
  260 + const uint32_t label = t.file.get<uint32_t>("Label", 0);
  261 +
  262 + gallery.write(imageID);
  263 + gallery.write((const char*) &algorithmID, sizeof(int32_t));
  264 + gallery.write((const char*) &x , sizeof(uint32_t));
  265 + gallery.write((const char*) &y , sizeof(uint32_t));
  266 + gallery.write((const char*) &width , sizeof(uint32_t));
  267 + gallery.write((const char*) &height , sizeof(uint32_t));
  268 + gallery.write((const char*) &label , sizeof(uint32_t));
  269 +
  270 + const uint32_t urlSize = url.size() + 1;
  271 + gallery.write((const char*) &urlSize, sizeof(uint32_t));
  272 +
  273 + const uint32_t signatureSize = (algorithmID == 0) ? 0 : t.m().rows * t.m().cols * t.m().elemSize();
  274 + const uint32_t fvSize = header.size() + signatureSize;
  275 + gallery.write((const char*) &fvSize, sizeof(uint32_t));
  276 +
  277 + gallery.write((const char*) url.data(), urlSize);
  278 + if (algorithmID != 0) {
  279 + gallery.write(header);
  280 + gallery.write((const char*) t.m().data, signatureSize);
  281 + }
  282 + }
  283 +};
  284 +
  285 +BR_REGISTER(Gallery, utGallery)
  286 +
  287 +/*!
  288 + * \ingroup galleries
  289 + * \brief Newline-separated URLs.
  290 + * \author Josh Klontz \cite jklontz
  291 + */
  292 +class urlGallery : public BinaryGallery
  293 +{
  294 + Q_OBJECT
  295 +
  296 + Template readTemplate()
  297 + {
  298 + Template t;
  299 + const QString url = QString::fromLocal8Bit(gallery.readLine()).simplified();
  300 + if (!url.isEmpty())
  301 + t.file.set("URL", url);
  302 + return t;
  303 + }
  304 +
  305 + void writeTemplate(const Template &t)
  306 + {
  307 + const QString url = t.file.get<QString>("URL", t.file.name);
  308 + if (!url.isEmpty()) {
  309 + gallery.write(qPrintable(url));
  310 + gallery.write("\n");
  311 + }
  312 + }
  313 +};
  314 +
  315 +BR_REGISTER(Gallery, urlGallery)
  316 +
  317 +/*!
  318 + * \ingroup galleries
  319 + * \brief Newline-separated JSON objects.
  320 + * \author Josh Klontz \cite jklontz
  321 + */
  322 +class jsonGallery : public BinaryGallery
  323 +{
  324 + Q_OBJECT
  325 +
  326 + Template readTemplate()
  327 + {
  328 + QJsonParseError error;
  329 + const QByteArray line = gallery.readLine().simplified();
  330 + if (line.isEmpty())
  331 + return Template();
  332 + File file = QJsonDocument::fromJson(line, &error).object().toVariantMap();
  333 + if (error.error != QJsonParseError::NoError) {
  334 + qWarning("Couldn't parse: %s\n", line.data());
  335 + qFatal("%s\n", qPrintable(error.errorString()));
  336 + }
  337 + return file;
  338 + }
  339 +
  340 + void writeTemplate(const Template &t)
  341 + {
  342 + const QByteArray json = QJsonDocument(QJsonObject::fromVariantMap(t.file.localMetadata())).toJson().replace('\n', "");
  343 + if (!json.isEmpty()) {
  344 + gallery.write(json);
  345 + gallery.write("\n");
  346 + }
  347 + }
  348 +};
  349 +
  350 +BR_REGISTER(Gallery, jsonGallery)
  351 +
  352 +} // namespace br
  353 +
  354 +#include "gallery/binary.moc"
openbr/plugins/gallery/crawl.cpp 0 → 100644
  1 +#include <QStandardPaths>
  2 +
  3 +#include <openbr/plugins/openbr_internal.h>
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +/*!
  9 + * \ingroup galleries
  10 + * \brief Crawl a root location for image files.
  11 + * \author Josh Klontz \cite jklontz
  12 + */
  13 +class crawlGallery : public Gallery
  14 +{
  15 + Q_OBJECT
  16 + Q_PROPERTY(bool autoRoot READ get_autoRoot WRITE set_autoRoot RESET reset_autoRoot STORED false)
  17 + Q_PROPERTY(int depth READ get_depth WRITE set_depth RESET reset_depth STORED false)
  18 + Q_PROPERTY(bool depthFirst READ get_depthFirst WRITE set_depthFirst RESET reset_depthFirst STORED false)
  19 + Q_PROPERTY(int images READ get_images WRITE set_images RESET reset_images STORED false)
  20 + Q_PROPERTY(bool json READ get_json WRITE set_json RESET reset_json STORED false)
  21 + Q_PROPERTY(int timeLimit READ get_timeLimit WRITE set_timeLimit RESET reset_timeLimit STORED false)
  22 + BR_PROPERTY(bool, autoRoot, false)
  23 + BR_PROPERTY(int, depth, INT_MAX)
  24 + BR_PROPERTY(bool, depthFirst, false)
  25 + BR_PROPERTY(int, images, INT_MAX)
  26 + BR_PROPERTY(bool, json, false)
  27 + BR_PROPERTY(int, timeLimit, INT_MAX)
  28 +
  29 + QTime elapsed;
  30 + TemplateList templates;
  31 +
  32 + void crawl(QFileInfo url, int currentDepth = 0)
  33 + {
  34 + if ((templates.size() >= images) || (currentDepth >= depth) || (elapsed.elapsed()/1000 >= timeLimit))
  35 + return;
  36 +
  37 + if (url.filePath().startsWith("file://"))
  38 + url = QFileInfo(url.filePath().mid(7));
  39 +
  40 + if (url.isDir()) {
  41 + const QDir dir(url.absoluteFilePath());
  42 + const QFileInfoList files = dir.entryInfoList(QDir::Files);
  43 + const QFileInfoList subdirs = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
  44 + foreach (const QFileInfo &first, depthFirst ? subdirs : files)
  45 + crawl(first, currentDepth + 1);
  46 + foreach (const QFileInfo &second, depthFirst ? files : subdirs)
  47 + crawl(second, currentDepth + 1);
  48 + } else if (url.isFile()) {
  49 + const QString suffix = url.suffix();
  50 + if ((suffix == "bmp") || (suffix == "jpg") || (suffix == "jpeg") || (suffix == "png") || (suffix == "tiff")) {
  51 + File f;
  52 + if (json) f.set("URL", "file://"+url.canonicalFilePath());
  53 + else f.name = "file://"+url.canonicalFilePath();
  54 + templates.append(f);
  55 + }
  56 + }
  57 + }
  58 +
  59 + void init()
  60 + {
  61 + elapsed.start();
  62 + const QString root = file.name.mid(0, file.name.size()-6); // Remove .crawl suffix";
  63 + if (!root.isEmpty()) {
  64 + crawl(root);
  65 + } else {
  66 + if (autoRoot) {
  67 + foreach (const QString &path, QStandardPaths::standardLocations(QStandardPaths::HomeLocation))
  68 + crawl(path);
  69 + } else {
  70 + QFile file;
  71 + file.open(stdin, QFile::ReadOnly);
  72 + while (!file.atEnd()) {
  73 + const QString url = QString::fromLocal8Bit(file.readLine()).simplified();
  74 + if (!url.isEmpty())
  75 + crawl(url);
  76 + }
  77 + }
  78 + }
  79 + }
  80 +
  81 + TemplateList readBlock(bool *done)
  82 + {
  83 + *done = true;
  84 + return templates;
  85 + }
  86 +
  87 + void write(const Template &)
  88 + {
  89 + qFatal("Not supported");
  90 + }
  91 +};
  92 +
  93 +BR_REGISTER(Gallery, crawlGallery)
  94 +
  95 +} // namespace br
  96 +
  97 +#include "gallery/crawl.moc"