Commit e4d4166cfff76ae8a0241253713a8ad3c5f2d412

Authored by Jordan Cheney
2 parents 8fde04e6 f213e68c

Merge branch 'reorg'

Showing 317 changed files with 19149 additions and 13709 deletions

Too many changes.

To preserve performance only 100 of 317 files are displayed.

openbr/plugins/classification/adaboost.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/opencvutils.h>
  19 +
  20 +using namespace cv;
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +/*!
  26 + * \ingroup transforms
  27 + * \brief Wraps OpenCV's Ada Boost framework
  28 + * \author Scott Klum \cite sklum
  29 + * \brief http://docs.opencv.org/modules/ml/doc/boosting.html
  30 + */
  31 +class AdaBoostTransform : public Transform
  32 +{
  33 + Q_OBJECT
  34 + Q_ENUMS(Type)
  35 + Q_ENUMS(SplitCriteria)
  36 +
  37 + Q_PROPERTY(Type type READ get_type WRITE set_type RESET reset_type STORED false)
  38 + Q_PROPERTY(SplitCriteria splitCriteria READ get_splitCriteria WRITE set_splitCriteria RESET reset_splitCriteria STORED false)
  39 + Q_PROPERTY(int weakCount READ get_weakCount WRITE set_weakCount RESET reset_weakCount STORED false)
  40 + Q_PROPERTY(float trimRate READ get_trimRate WRITE set_trimRate RESET reset_trimRate STORED false)
  41 + Q_PROPERTY(int folds READ get_folds WRITE set_folds RESET reset_folds STORED false)
  42 + Q_PROPERTY(int maxDepth READ get_maxDepth WRITE set_maxDepth RESET reset_maxDepth STORED false)
  43 + Q_PROPERTY(bool returnConfidence READ get_returnConfidence WRITE set_returnConfidence RESET reset_returnConfidence STORED false)
  44 + Q_PROPERTY(bool overwriteMat READ get_overwriteMat WRITE set_overwriteMat RESET reset_overwriteMat STORED false)
  45 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  46 + Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)
  47 +
  48 +public:
  49 + enum Type { Discrete = CvBoost::DISCRETE,
  50 + Real = CvBoost::REAL,
  51 + Logit = CvBoost::LOGIT,
  52 + Gentle = CvBoost::GENTLE};
  53 +
  54 + enum SplitCriteria { Default = CvBoost::DEFAULT,
  55 + Gini = CvBoost::GINI,
  56 + Misclass = CvBoost::MISCLASS,
  57 + Sqerr = CvBoost::SQERR};
  58 +
  59 +private:
  60 + BR_PROPERTY(Type, type, Real)
  61 + BR_PROPERTY(SplitCriteria, splitCriteria, Default)
  62 + BR_PROPERTY(int, weakCount, 100)
  63 + BR_PROPERTY(float, trimRate, .95)
  64 + BR_PROPERTY(int, folds, 0)
  65 + BR_PROPERTY(int, maxDepth, 1)
  66 + BR_PROPERTY(bool, returnConfidence, true)
  67 + BR_PROPERTY(bool, overwriteMat, true)
  68 + BR_PROPERTY(QString, inputVariable, "Label")
  69 + BR_PROPERTY(QString, outputVariable, "")
  70 +
  71 + CvBoost boost;
  72 +
  73 + void train(const TemplateList &data)
  74 + {
  75 + Mat samples = OpenCVUtils::toMat(data.data());
  76 + Mat labels = OpenCVUtils::toMat(File::get<float>(data, inputVariable));
  77 +
  78 + Mat types = Mat(samples.cols + 1, 1, CV_8U);
  79 + types.setTo(Scalar(CV_VAR_NUMERICAL));
  80 + types.at<char>(samples.cols, 0) = CV_VAR_CATEGORICAL;
  81 +
  82 + CvBoostParams params;
  83 + params.boost_type = type;
  84 + params.split_criteria = splitCriteria;
  85 + params.weak_count = weakCount;
  86 + params.weight_trim_rate = trimRate;
  87 + params.cv_folds = folds;
  88 + params.max_depth = maxDepth;
  89 +
  90 + boost.train( samples, CV_ROW_SAMPLE, labels, Mat(), Mat(), types, Mat(),
  91 + params);
  92 + }
  93 +
  94 + void project(const Template &src, Template &dst) const
  95 + {
  96 + dst = src;
  97 + float response;
  98 + if (returnConfidence) {
  99 + response = boost.predict(src.m().reshape(1,1),Mat(),Range::all(),false,true)/weakCount;
  100 + } else {
  101 + response = boost.predict(src.m().reshape(1,1));
  102 + }
  103 +
  104 + if (overwriteMat) {
  105 + dst.m() = Mat(1, 1, CV_32F);
  106 + dst.m().at<float>(0, 0) = response;
  107 + } else {
  108 + dst.file.set(outputVariable, response);
  109 + }
  110 + }
  111 +
  112 + void load(QDataStream &stream)
  113 + {
  114 + OpenCVUtils::loadModel(boost,stream);
  115 + }
  116 +
  117 + void store(QDataStream &stream) const
  118 + {
  119 + OpenCVUtils::storeModel(boost,stream);
  120 + }
  121 +
  122 +
  123 + void init()
  124 + {
  125 + if (outputVariable.isEmpty())
  126 + outputVariable = inputVariable;
  127 + }
  128 +};
  129 +
  130 +BR_REGISTER(Transform, AdaBoostTransform)
  131 +
  132 +} // namespace br
  133 +
  134 +#include "classification/adaboost.moc"
... ...
openbr/plugins/ebif.cpp renamed to openbr/plugins/classification/ebif.cpp
  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 +
1 17 #include <opencv2/imgproc/imgproc.hpp>
2 18  
3   -#include "openbr_internal.h"
4   -#include "openbr/core/common.h"
5   -#include "openbr/core/opencvutils.h"
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/common.h>
  21 +#include <openbr/core/opencvutils.h>
6 22  
7 23 using namespace cv;
8 24  
... ... @@ -128,4 +144,4 @@ BR_REGISTER(Transform, EBIFTransform)
128 144  
129 145 } // namespace br
130 146  
131   -#include "ebif.moc"
  147 +#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 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/opencvutils.h>
3 19  
4   -using namespace std;
5 20 using namespace cv;
6 21  
7 22 namespace br
... ... @@ -250,113 +265,6 @@ class ForestInductionTransform : public ForestTransform
250 265  
251 266 BR_REGISTER(Transform, ForestInductionTransform)
252 267  
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 268 } // namespace br
361 269  
362   -#include "tree.moc"
  270 +#include "classification/forest.moc"
... ...
openbr/plugins/ipc2013.cpp renamed to openbr/plugins/classification/ipc2013.cpp
1   -#include "openbr_internal.h"
2 1 #include <pxcaccelerator.h>
3 2 #include <pxcface.h>
4 3 #include <pxcimage.h>
5 4 #include <pxcsession.h>
6 5  
  6 +#include <openbr/plugins/openbr_internal.h>
  7 +
7 8 using namespace br;
8 9  
9 10 static PXCSession *pxcSession = NULL;
... ...
openbr/plugins/eigen3.cpp renamed to openbr/plugins/classification/lda.cpp
... ... @@ -16,11 +16,11 @@
16 16  
17 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 25 namespace br
26 26 {
... ... @@ -652,46 +652,6 @@ class SparseLDATransform : public Transform
652 652  
653 653 BR_REGISTER(Transform, SparseLDATransform)
654 654  
655   -/*!
656   - * \ingroup distances
657   - * \brief L1 distance computed using eigen.
658   - * \author Josh Klontz \cite jklontz
659   - */
660   -class L1Distance : public UntrainableDistance
661   -{
662   - Q_OBJECT
663   -
664   - float compare(const cv::Mat &a, const cv::Mat &b) const
665   - {
666   - const int size = a.rows * a.cols;
667   - Eigen::Map<Eigen::VectorXf> aMap((float*)a.data, size);
668   - Eigen::Map<Eigen::VectorXf> bMap((float*)b.data, size);
669   - return (aMap-bMap).cwiseAbs().sum();
670   - }
671   -};
672   -
673   -BR_REGISTER(Distance, L1Distance)
674   -
675   -/*!
676   - * \ingroup distances
677   - * \brief L2 distance computed using eigen.
678   - * \author Josh Klontz \cite jklontz
679   - */
680   -class L2Distance : public UntrainableDistance
681   -{
682   - Q_OBJECT
683   -
684   - float compare(const cv::Mat &a, const cv::Mat &b) const
685   - {
686   - const int size = a.rows * a.cols;
687   - Eigen::Map<Eigen::VectorXf> aMap((float*)a.data, size);
688   - Eigen::Map<Eigen::VectorXf> bMap((float*)b.data, size);
689   - return (aMap-bMap).squaredNorm();
690   - }
691   -};
692   -
693   -BR_REGISTER(Distance, L2Distance)
694   -
695 655 } // namespace br
696 656  
697   -#include "eigen3.moc"
  657 +#include "classification/lda.moc"
... ...
openbr/plugins/liblinear.cpp renamed to openbr/plugins/classification/liblinear.cpp
... ... @@ -2,8 +2,8 @@
2 2 #include <opencv2/core/core.hpp>
3 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 8 #include <linear.h>
9 9  
... ...
openbr/plugins/nn.cpp renamed to openbr/plugins/classification/mlp.cpp
  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 +
1 17 #include <opencv2/ml/ml.hpp>
2 18  
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>
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/opencvutils.h>
9 21  
10   -using namespace std;
11 22 using namespace cv;
12 23  
13 24 namespace br
14 25 {
15 26  
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 27 /*!
50 28 * \ingroup transforms
51 29 * \brief Wraps OpenCV's multi-layer perceptron framework
... ... @@ -124,12 +102,12 @@ private:
124 102  
125 103 void load(QDataStream &stream)
126 104 {
127   - loadMLP(mlp,stream);
  105 + OpenCVUtils::loadModel(mlp, stream);
128 106 }
129 107  
130 108 void store(QDataStream &stream) const
131 109 {
132   - storeMLP(mlp,stream);
  110 + OpenCVUtils::storeModel(mlp, stream);
133 111 }
134 112 };
135 113  
... ... @@ -137,4 +115,4 @@ BR_REGISTER(Transform, MLPTransform)
137 115  
138 116 } // namespace br
139 117  
140   -#include "nn.moc"
  118 +#include "classification/mlp.moc"
... ...
openbr/plugins/nt4.cpp renamed to openbr/plugins/classification/nt4.cpp
... ... @@ -457,4 +457,4 @@ class NT4Compare : public Distance
457 457  
458 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 593  
594 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 18 #include <opencv2/core/core.hpp>
19 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 24 using namespace cv;
25 25  
... ... @@ -261,4 +261,4 @@ BR_REGISTER(Distance, SVMDistance)
261 261  
262 262 } // namespace br
263 263  
264   -#include "svm.moc"
  264 +#include "classification/svm.moc"
... ...
openbr/plugins/classification/turk.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief Convenience class for training turk attribute regressors
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class TurkClassifierTransform : public Transform
  28 +{
  29 + Q_OBJECT
  30 + Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key STORED false)
  31 + Q_PROPERTY(QStringList values READ get_values WRITE set_values RESET reset_values STORED false)
  32 + Q_PROPERTY(bool isMeta READ get_isMeta WRITE set_isMeta RESET reset_isMeta STORED false)
  33 + BR_PROPERTY(QString, key, QString())
  34 + BR_PROPERTY(QStringList, values, QStringList())
  35 + BR_PROPERTY(bool, isMeta, false)
  36 +
  37 + Transform *child;
  38 +
  39 + void init()
  40 + {
  41 + QStringList classifiers;
  42 + foreach (const QString &value, values)
  43 + 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()));
  44 + child = Transform::make(classifiers.join("/") + (classifiers.size() > 1 ? "+Cat" : ""));
  45 + }
  46 +
  47 + void train(const QList<TemplateList> &data)
  48 + {
  49 + child->train(data);
  50 + }
  51 +
  52 + void project(const Template &src, Template &dst) const
  53 + {
  54 + child->project(src, dst);
  55 + }
  56 +
  57 + void store(QDataStream &stream) const
  58 + {
  59 + child->store(stream);
  60 + }
  61 +
  62 + void load(QDataStream &stream)
  63 + {
  64 + child->load(stream);
  65 + }
  66 +};
  67 +
  68 +BR_REGISTER(Transform, TurkClassifierTransform)
  69 +
  70 +} // namespace br
  71 +
  72 +#include "classification/turk.moc"
... ...
openbr/plugins/cluster/collectnn.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief Collect nearest neighbors and append them to metadata.
  25 + * \author Charles Otto \cite caotto
  26 + */
  27 +class CollectNNTransform : public UntrainableMetaTransform
  28 +{
  29 + Q_OBJECT
  30 +
  31 + Q_PROPERTY(int keep READ get_keep WRITE set_keep RESET reset_keep STORED false)
  32 + BR_PROPERTY(int, keep, 20)
  33 +
  34 + void project(const Template &src, Template &dst) const
  35 + {
  36 + dst.file = src.file;
  37 + dst.clear();
  38 + dst.m() = cv::Mat();
  39 + Neighbors neighbors;
  40 + for (int i=0; i < src.m().cols;i++) {
  41 + // skip self compares
  42 + if (i == src.file.get<int>("FrameNumber"))
  43 + continue;
  44 + neighbors.append(Neighbor(i, src.m().at<float>(0,i)));
  45 + }
  46 + int actuallyKeep = std::min(keep, neighbors.size());
  47 + std::partial_sort(neighbors.begin(), neighbors.begin()+actuallyKeep, neighbors.end(), compareNeighbors);
  48 +
  49 + Neighbors selected = neighbors.mid(0, actuallyKeep);
  50 + dst.file.set("neighbors", QVariant::fromValue(selected));
  51 + }
  52 +};
  53 +
  54 +BR_REGISTER(Transform, CollectNNTransform)
  55 +
  56 +} // namespace br
  57 +
  58 +#include "cluster/collectnn.moc"
... ...
openbr/plugins/cluster/kmeans.cpp 0 → 100644
  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 <opencv2/flann/flann.hpp>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/opencvutils.h>
  21 +
  22 +using namespace cv;
  23 +
  24 +namespace br
  25 +{
  26 +
  27 +/*!
  28 + * \ingroup transforms
  29 + * \brief Wraps OpenCV kmeans and flann.
  30 + * \author Josh Klontz \cite jklontz
  31 + */
  32 +class KMeansTransform : public Transform
  33 +{
  34 + Q_OBJECT
  35 + Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false)
  36 + Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false)
  37 + BR_PROPERTY(int, kTrain, 256)
  38 + BR_PROPERTY(int, kSearch, 1)
  39 +
  40 + Mat centers;
  41 + mutable QScopedPointer<flann::Index> index;
  42 + mutable QMutex mutex;
  43 +
  44 + void reindex()
  45 + {
  46 + index.reset(new flann::Index(centers, flann::LinearIndexParams()));
  47 + }
  48 +
  49 + void train(const TemplateList &data)
  50 + {
  51 + Mat bestLabels;
  52 + const double compactness = kmeans(OpenCVUtils::toMatByRow(data.data()), kTrain, bestLabels, TermCriteria(TermCriteria::MAX_ITER, 10, 0), 3, KMEANS_PP_CENTERS, centers);
  53 + qDebug("KMeans compactness = %f", compactness);
  54 + reindex();
  55 + }
  56 +
  57 + void project(const Template &src, Template &dst) const
  58 + {
  59 + QMutexLocker locker(&mutex);
  60 + Mat dists, indicies;
  61 + index->knnSearch(src, indicies, dists, kSearch);
  62 + dst = indicies.reshape(1, 1);
  63 + }
  64 +
  65 + void load(QDataStream &stream)
  66 + {
  67 + stream >> centers;
  68 + reindex();
  69 + }
  70 +
  71 + void store(QDataStream &stream) const
  72 + {
  73 + stream << centers;
  74 + }
  75 +};
  76 +
  77 +BR_REGISTER(Transform, KMeansTransform)
  78 +
  79 +} // namespace br
  80 +
  81 +#include "cluster/kmeans.moc"
... ...
openbr/plugins/cluster.cpp renamed to openbr/plugins/cluster/knn.cpp
... ... @@ -14,12 +14,8 @@
14 14 * limitations under the License. *
15 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16  
17   -#include <opencv2/flann/flann.hpp>
18   -
19   -#include "openbr_internal.h"
20   -#include "openbr/core/common.h"
21   -#include "openbr/core/opencvutils.h"
22   -#include <fstream>
  17 +#include <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/common.h>
23 19  
24 20 using namespace cv;
25 21  
... ... @@ -28,58 +24,6 @@ namespace br
28 24  
29 25 /*!
30 26 * \ingroup transforms
31   - * \brief Wraps OpenCV kmeans and flann.
32   - * \author Josh Klontz \cite jklontz
33   - */
34   -class KMeansTransform : public Transform
35   -{
36   - Q_OBJECT
37   - Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false)
38   - Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false)
39   - BR_PROPERTY(int, kTrain, 256)
40   - BR_PROPERTY(int, kSearch, 1)
41   -
42   - Mat centers;
43   - mutable QScopedPointer<flann::Index> index;
44   - mutable QMutex mutex;
45   -
46   - void reindex()
47   - {
48   - index.reset(new flann::Index(centers, flann::LinearIndexParams()));
49   - }
50   -
51   - void train(const TemplateList &data)
52   - {
53   - Mat bestLabels;
54   - const double compactness = kmeans(OpenCVUtils::toMatByRow(data.data()), kTrain, bestLabels, TermCriteria(TermCriteria::MAX_ITER, 10, 0), 3, KMEANS_PP_CENTERS, centers);
55   - qDebug("KMeans compactness = %f", compactness);
56   - reindex();
57   - }
58   -
59   - void project(const Template &src, Template &dst) const
60   - {
61   - QMutexLocker locker(&mutex);
62   - Mat dists, indicies;
63   - index->knnSearch(src, indicies, dists, kSearch);
64   - dst = indicies.reshape(1, 1);
65   - }
66   -
67   - void load(QDataStream &stream)
68   - {
69   - stream >> centers;
70   - reindex();
71   - }
72   -
73   - void store(QDataStream &stream) const
74   - {
75   - stream << centers;
76   - }
77   -};
78   -
79   -BR_REGISTER(Transform, KMeansTransform)
80   -
81   -/*!
82   - * \ingroup transforms
83 27 * \brief K nearest neighbors classifier.
84 28 * \author Josh Klontz \cite jklontz
85 29 */
... ... @@ -151,148 +95,6 @@ class KNNTransform : public Transform
151 95  
152 96 BR_REGISTER(Transform, KNNTransform)
153 97  
154   -/*!
155   - * \ingroup transforms
156   - * \brief Chooses k random points to be centroids.
157   - * \author Austin Blanton \cite imaus10
158   - * \see KMeansTransform
159   - */
160   -class RandomCentroidsTransform : public Transform
161   -{
162   - Q_OBJECT
163   - Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false)
164   - Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false)
165   - BR_PROPERTY(int, kTrain, 256)
166   - BR_PROPERTY(int, kSearch, 1)
167   -
168   - Mat centers;
169   - mutable QScopedPointer<flann::Index> index;
170   - mutable QMutex mutex;
171   -
172   - void reindex()
173   - {
174   - index.reset(new flann::Index(centers, flann::LinearIndexParams()));
175   - }
176   -
177   - void train(const TemplateList &data)
178   - {
179   - Mat flat = OpenCVUtils::toMatByRow(data.data());
180   - QList<int> sample = Common::RandSample(kTrain, flat.rows, 0, true);
181   - foreach (const int &idx, sample)
182   - centers.push_back(flat.row(idx));
183   - reindex();
184   - }
185   -
186   - void project(const Template &src, Template &dst) const
187   - {
188   - QMutexLocker locker(&mutex);
189   - Mat dists, indicies;
190   - index->knnSearch(src, indicies, dists, kSearch);
191   - dst = indicies.reshape(1, 1);
192   - }
193   -
194   - void load(QDataStream &stream)
195   - {
196   - stream >> centers;
197   - reindex();
198   - }
199   -
200   - void store(QDataStream &stream) const
201   - {
202   - stream << centers;
203   - }
204   -};
205   -
206   -BR_REGISTER(Transform, RandomCentroidsTransform)
207   -
208   -class RegInitializer : public Initializer
209   -{
210   - Q_OBJECT
211   -
212   - void initialize() const
213   - {
214   - qRegisterMetaType<br::Neighbors>();
215   - }
216   -};
217   -BR_REGISTER(Initializer, RegInitializer)
218   -
219   -class CollectNNTransform : public UntrainableMetaTransform
220   -{
221   - Q_OBJECT
222   -
223   - Q_PROPERTY(int keep READ get_keep WRITE set_keep RESET reset_keep STORED false)
224   - BR_PROPERTY(int, keep, 20)
225   -
226   - void project(const Template &src, Template &dst) const
227   - {
228   - dst.file = src.file;
229   - dst.clear();
230   - dst.m() = cv::Mat();
231   - Neighbors neighbors;
232   - for (int i=0; i < src.m().cols;i++) {
233   - // skip self compares
234   - if (i == src.file.get<int>("FrameNumber"))
235   - continue;
236   - neighbors.append(Neighbor(i, src.m().at<float>(0,i)));
237   - }
238   - int actuallyKeep = std::min(keep, neighbors.size());
239   - std::partial_sort(neighbors.begin(), neighbors.begin()+actuallyKeep, neighbors.end(), compareNeighbors);
240   -
241   - Neighbors selected = neighbors.mid(0, actuallyKeep);
242   - dst.file.set("neighbors", QVariant::fromValue(selected));
243   - }
244   -};
245   -BR_REGISTER(Transform, CollectNNTransform)
246   -
247   -class LogNNTransform : public TimeVaryingTransform
248   -{
249   - Q_OBJECT
250   -
251   - Q_PROPERTY(QString fileName READ get_fileName WRITE set_fileName RESET reset_fileName STORED false)
252   - BR_PROPERTY(QString, fileName, "")
253   -
254   - std::fstream fout;
255   -
256   - void projectUpdate(const Template &src, Template &dst)
257   - {
258   - dst = src;
259   -
260   - if (!dst.file.contains("neighbors")) {
261   - fout << std::endl;
262   - return;
263   - }
264   -
265   - Neighbors neighbors = dst.file.get<Neighbors>("neighbors");
266   - if (neighbors.isEmpty() ) {
267   - fout << std::endl;
268   - return;
269   - }
270   -
271   - QString aLine;
272   - aLine.append(QString::number(neighbors[0].first)+":"+QString::number(neighbors[0].second));
273   - for (int i=1; i < neighbors.size();i++)
274   - aLine.append(","+QString::number(neighbors[i].first)+":"+QString::number(neighbors[i].second));
275   -
276   - fout << qPrintable(aLine) << std::endl;
277   - }
278   -
279   - void init()
280   - {
281   - if (!fileName.isEmpty())
282   - fout.open(qPrintable(fileName), std::ios_base::out);
283   - }
284   -
285   - void finalize(TemplateList &output)
286   - {
287   - (void) output;
288   - fout.close();
289   - }
290   -
291   -public:
292   - LogNNTransform() : TimeVaryingTransform(false, false) {}
293   -};
294   -BR_REGISTER(Transform, LogNNTransform)
295   -
296 98 } // namespace br
297 99  
298   -#include "cluster.moc"
  100 +#include "cluster/knn.moc"
... ...
openbr/plugins/cluster/lognn.cpp 0 → 100644
  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 <fstream>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +/*!
  25 + * \ingroup transforms
  26 + * \brief Log nearest neighbors to specified file.
  27 + * \author Charles Otto \cite caotto
  28 + */
  29 +class LogNNTransform : public TimeVaryingTransform
  30 +{
  31 + Q_OBJECT
  32 +
  33 + Q_PROPERTY(QString fileName READ get_fileName WRITE set_fileName RESET reset_fileName STORED false)
  34 + BR_PROPERTY(QString, fileName, "")
  35 +
  36 + std::fstream fout;
  37 +
  38 + void projectUpdate(const Template &src, Template &dst)
  39 + {
  40 + dst = src;
  41 +
  42 + if (!dst.file.contains("neighbors")) {
  43 + fout << std::endl;
  44 + return;
  45 + }
  46 +
  47 + Neighbors neighbors = dst.file.get<Neighbors>("neighbors");
  48 + if (neighbors.isEmpty() ) {
  49 + fout << std::endl;
  50 + return;
  51 + }
  52 +
  53 + QString aLine;
  54 + aLine.append(QString::number(neighbors[0].first)+":"+QString::number(neighbors[0].second));
  55 + for (int i=1; i < neighbors.size();i++)
  56 + aLine.append(","+QString::number(neighbors[i].first)+":"+QString::number(neighbors[i].second));
  57 +
  58 + fout << qPrintable(aLine) << std::endl;
  59 + }
  60 +
  61 + void init()
  62 + {
  63 + if (!fileName.isEmpty())
  64 + fout.open(qPrintable(fileName), std::ios_base::out);
  65 + }
  66 +
  67 + void finalize(TemplateList &output)
  68 + {
  69 + (void) output;
  70 + fout.close();
  71 + }
  72 +
  73 +public:
  74 + LogNNTransform() : TimeVaryingTransform(false, false) {}
  75 +};
  76 +
  77 +BR_REGISTER(Transform, LogNNTransform)
  78 +
  79 +} // namespace br
  80 +
  81 +#include "cluster/lognn.moc"
... ...
openbr/plugins/cluster/randomcentroids.cpp 0 → 100644
  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 <opencv2/flann/flann.hpp>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/common.h>
  21 +#include <openbr/core/opencvutils.h>
  22 +
  23 +using namespace cv;
  24 +
  25 +namespace br
  26 +{
  27 +
  28 +/*!
  29 + * \ingroup transforms
  30 + * \brief Chooses k random points to be centroids.
  31 + * \author Austin Blanton \cite imaus10
  32 + * \see KMeansTransform
  33 + */
  34 +class RandomCentroidsTransform : public Transform
  35 +{
  36 + Q_OBJECT
  37 + Q_PROPERTY(int kTrain READ get_kTrain WRITE set_kTrain RESET reset_kTrain STORED false)
  38 + Q_PROPERTY(int kSearch READ get_kSearch WRITE set_kSearch RESET reset_kSearch STORED false)
  39 + BR_PROPERTY(int, kTrain, 256)
  40 + BR_PROPERTY(int, kSearch, 1)
  41 +
  42 + Mat centers;
  43 + mutable QScopedPointer<flann::Index> index;
  44 + mutable QMutex mutex;
  45 +
  46 + void reindex()
  47 + {
  48 + index.reset(new flann::Index(centers, flann::LinearIndexParams()));
  49 + }
  50 +
  51 + void train(const TemplateList &data)
  52 + {
  53 + Mat flat = OpenCVUtils::toMatByRow(data.data());
  54 + QList<int> sample = Common::RandSample(kTrain, flat.rows, 0, true);
  55 + foreach (const int &idx, sample)
  56 + centers.push_back(flat.row(idx));
  57 + reindex();
  58 + }
  59 +
  60 + void project(const Template &src, Template &dst) const
  61 + {
  62 + QMutexLocker locker(&mutex);
  63 + Mat dists, indicies;
  64 + index->knnSearch(src, indicies, dists, kSearch);
  65 + dst = indicies.reshape(1, 1);
  66 + }
  67 +
  68 + void load(QDataStream &stream)
  69 + {
  70 + stream >> centers;
  71 + reindex();
  72 + }
  73 +
  74 + void store(QDataStream &stream) const
  75 + {
  76 + stream << centers;
  77 + }
  78 +};
  79 +
  80 +BR_REGISTER(Transform, RandomCentroidsTransform)
  81 +
  82 +} //namespace br
  83 +
  84 +#include "cluster/randomcentroids.moc"
... ...
openbr/plugins/cmake/eigen3.cmake 0 → 100644
  1 +set(BR_WITH_EIGEN3 ON CACHE BOOL "Build Eigen3 plugins")
  2 +
  3 +if(${BR_WITH_EIGEN3})
  4 + find_package(Eigen3 REQUIRED)
  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/distance/L1.cpp)
  9 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/distance/L2.cpp)
  10 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/imgproc/revertaffine.cpp)
  11 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/imgproc/integralsampler.cpp)
  12 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/imgproc/recursiveintegralsampler.cpp)
  13 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/metadata/consolidatedetections.cpp)
  14 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/metadata/delaunay.cpp)
  15 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/metadata/procrustes.cpp)
  16 +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 2  
3 3 if(${BR_WITH_IPC2013})
4 4 find_package(IPC2013 REQUIRED)
5   - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/ipc2013.cpp)
6 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${IPC2013_LIBS})
7 6 install(DIRECTORY ${IPC2013_DIR}/bin/x64/ DESTINATION bin)
  7 +else()
  8 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/ipc2013.cpp)
8 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 3 if (${BR_WITH_JAVA})
4 4 find_package(JNI REQUIRED)
5 5 find_package(JAVA REQUIRED)
6   - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/jni.cpp)
7 6 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${JNI_LIBRARIES})
8 7  
9 8 include_directories(${JAVA_INCLUDE_PATH})
10 9 include_directories(${JAVA_INCLUDE_PATH2})
11   -
  10 +else()
  11 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/core/jni.cpp)
12 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 3 if(${BR_WITH_LIBLINEAR})
4 4 find_package(LibLinear REQUIRED)
5 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 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 2  
3 3 if(${BR_WITH_LIKELY})
4 4 find_package(Likely REQUIRED)
5   - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/likely.cpp)
6 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 10 endif()
... ...
openbr/plugins/mongoose.cmake renamed to openbr/plugins/cmake/mongoose.cmake
1 1 set(BR_WITH_MONGOOSE OFF CACHE BOOL "Build with Mongoose")
2 2 if(${BR_WITH_MONGOOSE})
3 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 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 8 endif()
... ...
openbr/plugins/qtnetwork.cmake renamed to openbr/plugins/cmake/network.cmake
... ... @@ -3,6 +3,10 @@ if(${BR_WITH_QTNETWORK})
3 3 find_package(Qt5Network)
4 4 find_package(HttpParser)
5 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 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 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 2  
3 3 if(${BR_WITH_NT4})
4 4 find_package(NT4 REQUIRED)
5   - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/nt4.cpp)
6 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${NT4_LIBS})
7 6 install(DIRECTORY ${NT4_DIR_LIB}/ DESTINATION lib)
  7 +else()
  8 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/nt4.cpp)
8 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 2  
3 3 if(${BR_WITH_PP4})
4 4 find_package(PP4 REQUIRED)
5   - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/pp4.cpp)
6 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${PP4_LIBS})
7 6 install(DIRECTORY ${PP4_DIR}/lib/ DESTINATION lib)
8 7 install(DIRECTORY ${PP4_DIR}/models/ DESTINATION models/pp4)
  8 +else()
  9 + set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/classification/pp4.cpp)
9 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 2  
3 3 if(${BR_WITH_PP5})
4 4 find_package(PP5 REQUIRED)
5   - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/pp5.cpp)
6 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${PP5_LIBS})
7 6  
8 7 if(WIN32)
... ... @@ -12,4 +11,6 @@ if(${BR_WITH_PP5})
12 11 endif()
13 12  
14 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 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
1   -set(BR_WITH_STASM4 ON CACHE BOOL "Build with Stasm")
  1 +set(BR_WITH_STASM4 OFF CACHE BOOL "Build with Stasm")
2 2  
3 3 if(${BR_WITH_STASM4})
4 4 find_package(Stasm4 REQUIRED)
5   - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/stasm4.cpp)
6 5 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${Stasm4_LIBS})
7 6  
8 7 if(WIN32)
... ... @@ -12,4 +11,7 @@ if(${BR_WITH_STASM4})
12 11 endif()
13 12  
14 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 17 endif()
... ...
openbr/plugins/algorithms.cpp renamed to openbr/plugins/core/algorithms.cpp
... ... @@ -14,7 +14,7 @@
14 14 * limitations under the License. *
15 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16  
17   -#include "openbr_internal.h"
  17 +#include <openbr/plugins/openbr_internal.h>
18 18  
19 19 namespace br
20 20 {
... ... @@ -108,4 +108,4 @@ BR_REGISTER(Initializer, AlgorithmsInitializer)
108 108  
109 109 } // namespace br
110 110  
111   -#include "algorithms.moc"
  111 +#include "core/algorithms.moc"
... ...
openbr/plugins/core/attributealgorithms.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup initializers
  24 + * \brief Initializes global abbreviations with implemented algorithms for attributes
  25 + * \author Babatunde Ogunfemi \cite baba1472
  26 + */
  27 +class AttributeAlgorithmsInitializer : public Initializer
  28 +{
  29 + Q_OBJECT
  30 +
  31 + void initialize() const
  32 + {
  33 + // Constants
  34 + 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)])";
  35 + 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)";
  36 +
  37 + QString NOSE="RectFromStasmNoseWithBridge+ROI+Resize(36,24)+" + SUBSPACE;
  38 + QString MOUTH="RectFromStasmMouth+ROI+Resize(24,36)+" + SUBSPACE;
  39 + QString EYES="RectFromStasmEyes+ROI+Resize(24,36)+" + SUBSPACE;
  40 + QString HAIR="RectFromStasmHair+ROI+Resize(24,36)+" + SUBSPACE;
  41 + QString BROW="RectFromStasmBrow+ROI+Resize(24,36)+" + SUBSPACE;
  42 + QString JAW="RectFromStasmJaw+ROI+Resize(36,36)+" + SUBSPACE;
  43 + QString FACE = "Crop(24,30,144,190)+Resize(36,36)+" + SUBSPACE;
  44 +
  45 + // All Attributes
  46 + Globals->abbreviations.insert("AllAttributes", "AttributeBrow/AttributeMouth/AttributeEyes/AttributeFace/AttributeHair/AttributeNose/AttributeJaw");
  47 + Globals->abbreviations.insert("AllAttributesMatching", "(AttributeBrow)/(AttributeMouth)/(AttributeEyes)/(AttributeFace)/(AttributeHair)/(AttributeNose)/(AttributeJaw):AttributeMatch");
  48 +
  49 + //Individual Attributes
  50 + Globals->abbreviations.insert("AttributeBrow", "(" + BASE+ "+" + BROW + "+"
  51 + "TurkClassifier(eyebrowposition,[closebrows,highbrows],3)/"
  52 + "TurkClassifier(unibrow,[unibrow],3)/"
  53 + "TurkClassifier(eyebroworientation,[eyebrowsdown,eyebrowsuptodown],3)/"
  54 + "TurkClassifier(thickeyebrows,[thickeyebrows,lighteyebrows],3))");
  55 + Globals->abbreviations.insert("AttributeMouth", "(" + BASE + "+" + MOUTH + "+"
  56 + "TurkClassifier(smiling,[smiling],3)/"
  57 + "TurkClassifier(lipthickness,[cherry,big,small],3)/"
  58 + "TurkClassifier(mouthbite,[underbite,overbite],3)/"
  59 + "TurkClassifier(mouthopen,[closed,noteeth,halfteeth,allteeth],3)/"
  60 + "TurkClassifier(mouthwidth,[small,wide],3)/"
  61 + "TurkClassifier(mustache,[nomustache,linemustache,lightmustache,normalmustache,down],3)/"
  62 + "TurkClassifier(mouthasymmetry,[asymmetrical],3))");
  63 + Globals->abbreviations.insert("AttributeEyes", "(" + BASE + "+" + EYES + "+ "
  64 + "TurkClassifier(eyeseparation,[close,wide],3)/"
  65 + "TurkClassifier(eyeslant,[slant2,slant1,wild],3)/"
  66 + "TurkClassifier(benteyes,[bent])/"
  67 + "TurkClassifier(eyecolor,[darkeyes,lighteyes],3)/"
  68 + "TurkClassifier(baggyeyes,[baggy],3)/"
  69 + "TurkClassifier(almondeyes,[almond],3)/"
  70 + "TurkClassifier(buriedeyes,[buriedeyes],3)/"
  71 + "TurkClassifier(sleepyeyes,[sleepy],3)/"
  72 + "TurkClassifier(lineeyes,[line],3)/"
  73 + "TurkClassifier(roundeyes,[round],3)/"
  74 + "TurkClassifier(sharpeyes,[sharp],3)/"
  75 + "TurkClassifier(smalleyes,[smalleyes],3)/"
  76 + "TurkClassifier(glasses,[glasses],3)/"
  77 + "TurkClassifier(eyelashvisibility,[feweyelashes],3))");
  78 + Globals->abbreviations.insert("AttributeFace", "(" + BASE + "+" + FACE + "+"
  79 + "TurkClassifier(gender,[male],3)/"
  80 + "TurkClassifier(faceshape,[round,triangular,rectangular],3)/"
  81 + "TurkClassifier(cheekdensity,[puffy,in,normal],3)/"
  82 + "TurkClassifier(facemarks,[scars,moles,normal],3)/"
  83 + "TurkClassifier(facelength,[long],3)/"
  84 + "TurkClassifier(nosetoeyedist,[short,long],3)/"
  85 + "TurkClassifier(nosetomouthdist,[long,small],3))");
  86 + Globals->abbreviations.insert("AttributeHair", "(" + BASE + "+" + HAIR + "+"
  87 + "TurkClassifier(foreheadwrinkles,[wrinkled],3)/"
  88 + "TurkClassifier(foreheadsize,[smallforehead,largeforehead],3)/"
  89 + "TurkClassifier(haircolor,[darkhair,lighthair,greyhair],3)/"
  90 + "TurkClassifier(hairdensity,[thick,bald,thin,halfbald],3)/"
  91 + "TurkClassifier(widowspeak,[widowspeak],3)/"
  92 + "TurkClassifier(hairstyle,[curlyhair],3))");
  93 + Globals->abbreviations.insert("AttributeNose", "(" + BASE + "+" + NOSE + "+"
  94 + "TurkClassifier(noseorientation,[upnose,downnose],3)/"
  95 + "TurkClassifier(nosewidth,[small,thick],3)/"
  96 + "TurkClassifier(nosesize,[smallnose,bignose],3)/"
  97 + "TurkClassifier(brokennose,[broken],3))");
  98 + Globals->abbreviations.insert("AttributeJaw", "(" + BASE + "+" + JAW + "+"
  99 + "TurkClassifier(beard,[nobeard,bigbeard,lightbeard,goatee,linebeard,normalbeard,lincolnbeard],3)/"
  100 + "TurkClassifier(chinsize,[shortchin,longchin],3))");
  101 + Globals->abbreviations.insert("AttributeMatch", "Fuse(["
  102 + "Turk(eyebrowposition,[closebrows,highbrows],3),"
  103 + "Turk(unibrow,[unibrow],3),"
  104 + "Turk(eyebroworientation,[eyebrowsdown,eyebrowsuptodown],3),"
  105 + "Turk(thickeyebrows,[thickeyebrows,lighteyebrows],3),"
  106 + "Turk(smiling,[smiling],3),"
  107 + "Turk(lipthickness,[cherry,big,small],3),"
  108 + "Turk(mouthbite,[underbite,overbite],3),"
  109 + "Turk(mouthopen,[closed,noteeth,halfteeth,allteeth],3),"
  110 + "Turk(mouthwidth,[small,wide],3),"
  111 + "Turk(mustache,[nomustache,linemustache,lightmustache,normalmustache,down],3),"
  112 + "Turk(mouthasymmetry,[asymmetrical],3),"
  113 + "Turk(eyeseparation,[close,wide],3),"
  114 + "Turk(eyeslant,[slant2,slant1,wild],3),"
  115 + "Turk(benteyes,[bent],3),"
  116 + "Turk(eyecolor,[darkeyes,lighteyes],3),"
  117 + "Turk(baggyeyes,[baggy],3),"
  118 + "Turk(almondeyes,[almond],3),"
  119 + "Turk(buriedeyes,[buriedeyes],3),"
  120 + "Turk(sleepyeyes,[sleepy],3),"
  121 + "Turk(lineeyes,[line],3),"
  122 + "Turk(roundeyes,[round],3),"
  123 + "Turk(sharpeyes,[sharp],3),"
  124 + "Turk(smalleyes,[smalleyes],3),"
  125 + "Turk(glasses,[glasses],3),"
  126 + "Turk(eyelashvisibility,[feweyelashes],3),"
  127 + "Turk(gender,[male],3),"
  128 + "Turk(faceshape,[round,triangular,rectangular],3),"
  129 + "Turk(cheekdensity,[puffy,in,normal],3),"
  130 + "Turk(facemarks,[scars,moles,normal],3),"
  131 + "Turk(facelength,[long],3),"
  132 + "Turk(nosetoeyedist,[short,long],3),"
  133 + "Turk(nosetomouthdist,[long,small],3),"
  134 + "Turk(foreheadwrinkles,[wrinkled],3),"
  135 + "Turk(foreheadsize,[smallforehead,largeforehead],3),"
  136 + "Turk(haircolor,[darkhair,lighthair,greyhair],3),"
  137 + "Turk(hairdensity,[thick,bald,thin,halfbald],3),"
  138 + "Turk(widowspeak,[widowspeak],3),"
  139 + "Turk(hairstyle,[curlyhair],3),"
  140 + "Turk(noseorientation,[upnose,downnose],3),"
  141 + "Turk(nosewidth,[small,thick],3),"
  142 + "Turk(nosesize,[smallnose,bignose],3),"
  143 + "Turk(brokennose,[broken],3),"
  144 + "Turk(beard,[nobeard,bigbeard,lightbeard,goatee,linebeard,normalbeard,lincolnbeard],3),"
  145 + "Turk(chinsize,[shortchin,longchin],3)])");
  146 + }
  147 +};
  148 +
  149 +BR_REGISTER(Initializer, AttributeAlgorithmsInitializer)
  150 +
  151 +} // namespace br
  152 +
  153 +#include "core/attributealgorithms.moc"
... ...
openbr/plugins/core/cache.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief Caches br::Transform::project() results.
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class CacheTransform : public MetaTransform
  28 +{
  29 + Q_OBJECT
  30 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  31 + BR_PROPERTY(br::Transform*, transform, NULL)
  32 +
  33 + static QHash<QString, Template> cache;
  34 + static QMutex cacheLock;
  35 +
  36 +public:
  37 + ~CacheTransform()
  38 + {
  39 + if (cache.isEmpty()) return;
  40 +
  41 + // Write to cache
  42 + QFile file("Cache");
  43 + if (!file.open(QFile::WriteOnly))
  44 + qFatal("Unable to open %s for writing.", qPrintable(file.fileName()));
  45 + QDataStream stream(&file);
  46 + stream << cache;
  47 + file.close();
  48 + }
  49 +
  50 +private:
  51 + void init()
  52 + {
  53 + if (!transform) return;
  54 +
  55 + trainable = transform->trainable;
  56 + if (!cache.isEmpty()) return;
  57 +
  58 + // Read from cache
  59 + QFile file("Cache");
  60 + if (file.exists()) {
  61 + if (!file.open(QFile::ReadOnly))
  62 + qFatal("Unable to open %s for reading.", qPrintable(file.fileName()));
  63 + QDataStream stream(&file);
  64 + stream >> cache;
  65 + file.close();
  66 + }
  67 + }
  68 +
  69 + void train(const QList<TemplateList> &data)
  70 + {
  71 + transform->train(data);
  72 + }
  73 +
  74 + void project(const Template &src, Template &dst) const
  75 + {
  76 + const QString &file = src.file;
  77 + if (cache.contains(file)) {
  78 + dst = cache[file];
  79 + } else {
  80 + transform->project(src, dst);
  81 + cacheLock.lock();
  82 + cache[file] = dst;
  83 + cacheLock.unlock();
  84 + }
  85 + }
  86 +};
  87 +
  88 +QHash<QString, Template> CacheTransform::cache;
  89 +QMutex CacheTransform::cacheLock;
  90 +
  91 +BR_REGISTER(Transform, CacheTransform)
  92 +
  93 +} // namespace br
  94 +
  95 +#include "core/cache.moc"
... ...
openbr/plugins/core/contract.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief It's like the opposite of ExpandTransform, but not really
  25 + * \author Charles Otto \cite caotto
  26 + *
  27 + * Given a set of templatelists as input, concatenate them onto a single Template
  28 + */
  29 +class ContractTransform : public UntrainableMetaTransform
  30 +{
  31 + Q_OBJECT
  32 +
  33 + virtual void project(const TemplateList &src, TemplateList &dst) const
  34 + {
  35 + if (src.empty()) return;
  36 + Template out;
  37 +
  38 + foreach (const Template &t, src) {
  39 + out.merge(t);
  40 + }
  41 + out.file.clearRects();
  42 + foreach (const Template &t, src) {
  43 + if (!t.file.rects().empty())
  44 + out.file.appendRects(t.file.rects());
  45 + }
  46 + dst.clear();
  47 + dst.append(out);
  48 + }
  49 +
  50 + virtual void project(const Template &src, Template &dst) const
  51 + {
  52 + qFatal("this has gone bad");
  53 + (void) src; (void) dst;
  54 + }
  55 +};
  56 +
  57 +BR_REGISTER(Transform, ContractTransform)
  58 +
  59 +} // namespace br
  60 +
  61 +#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 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/common.h>
6 21  
7 22 namespace br
8 23 {
... ... @@ -134,138 +149,6 @@ class CrossValidateTransform : public MetaTransform
134 149  
135 150 BR_REGISTER(Transform, CrossValidateTransform)
136 151  
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 152 } // namespace br
270 153  
271   -#include "validate.moc"
  154 +#include "core/crossvalidate.moc"
... ...
openbr/plugins/core/discard.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief Removes all template's matrices.
  25 + * \see IdentityTransform FirstTransform RestTransform RemoveTransform
  26 + * \author Josh Klontz \cite jklontz
  27 + */
  28 +class DiscardTransform : public UntrainableMetaTransform
  29 +{
  30 + Q_OBJECT
  31 +
  32 + void project(const Template &src, Template &dst) const
  33 + {
  34 + dst.file = src.file;
  35 + }
  36 +};
  37 +
  38 +BR_REGISTER(Transform, DiscardTransform)
  39 +
  40 +} // namespace br
  41 +
  42 +#include "core/discard.moc"
... ...
openbr/plugins/core/discardtemplates.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +class DiscardTemplatesTransform : public UntrainableMetaTransform
  23 +{
  24 + Q_OBJECT
  25 +
  26 + void project(const Template &src, Template &dst) const
  27 + {
  28 + (void) src; (void) dst;
  29 + qFatal("Incorrect project called on DiscardTemplatesTransform");
  30 + }
  31 + void project(const TemplateList &src, TemplateList &dst) const
  32 + {
  33 + (void) src;
  34 + dst.clear();
  35 + }
  36 +};
  37 +
  38 +BR_REGISTER(Transform, DiscardTemplatesTransform)
  39 +
  40 +} // namespace br
  41 +
  42 +#include "core/discardtemplates.moc"
... ...
openbr/plugins/core/distributetemplate.cpp 0 → 100644
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +static void _projectList(const Transform *transform, const TemplateList *src, TemplateList *dst)
  25 +{
  26 + transform->project(*src, *dst);
  27 +}
  28 +
  29 +class DistributeTemplateTransform : public MetaTransform
  30 +{
  31 + Q_OBJECT
  32 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  33 + BR_PROPERTY(br::Transform*, transform, NULL)
  34 +
  35 +public:
  36 +
  37 + Transform *smartCopy(bool &newTransform)
  38 + {
  39 + if (!transform->timeVarying()) {
  40 + newTransform = false;
  41 + return this;
  42 + }
  43 + newTransform = true;
  44 +
  45 + DistributeTemplateTransform *output = new DistributeTemplateTransform;
  46 + bool newChild = false;
  47 + output->transform = transform->smartCopy(newChild);
  48 + if (newChild)
  49 + output->transform->setParent(output);
  50 +
  51 + return output;
  52 + }
  53 +
  54 + void train(const QList<TemplateList> &data)
  55 + {
  56 + if (!transform->trainable) {
  57 + qWarning("Attempted to train untrainable transform, nothing will happen.");
  58 + return;
  59 + }
  60 +
  61 + QList<TemplateList> separated;
  62 + foreach (const TemplateList &list, data) {
  63 + foreach (const Template &t, list) {
  64 + separated.append(TemplateList());
  65 + separated.last().append(t);
  66 + }
  67 + }
  68 +
  69 + transform->train(separated);
  70 + }
  71 +
  72 + void project(const Template &src, Template &dst) const
  73 + {
  74 + TemplateList input;
  75 + input.append(src);
  76 + TemplateList output;
  77 + project(input, output);
  78 +
  79 + if (output.size() != 1) qFatal("output contains more than 1 template");
  80 + else dst = output[0];
  81 + }
  82 +
  83 + // For each input template, form a single element TemplateList, push all those
  84 + // lists through transform, and form dst by concatenating the results.
  85 + // Process the single elemnt templates in parallel if parallelism is enabled.
  86 + void project(const TemplateList &src, TemplateList &dst) const
  87 + {
  88 + // Pre-allocate output for each template
  89 + QList<TemplateList> output_buffer;
  90 + output_buffer.reserve(src.size());
  91 +
  92 + // Can't declare this local to the loop because it would go out of scope
  93 + QList<TemplateList> input_buffer;
  94 + input_buffer.reserve(src.size());
  95 +
  96 + QFutureSynchronizer<void> futures;
  97 +
  98 + for (int i =0; i < src.size();i++) {
  99 + input_buffer.append(TemplateList());
  100 + output_buffer.append(TemplateList());
  101 + }
  102 + QList<QFuture<void> > temp;
  103 + temp.reserve(src.size());
  104 + for (int i=0; i<src.size(); i++) {
  105 + input_buffer[i].append(src[i]);
  106 +
  107 + if (Globals->parallelism > 1) temp.append(QtConcurrent::run(_projectList, transform, &input_buffer[i], &output_buffer[i]));
  108 + else _projectList(transform, &input_buffer[i], &output_buffer[i]);
  109 + }
  110 + // We add the futures in reverse order, since in Qt 5.1 at least the
  111 + // waiting thread will wait on them in the order added (which for uniform priority
  112 + // threads is the order of execution), and we want the waiting thread to go in the opposite order
  113 + // so that it can steal runnables and do something besides wait.
  114 + for (int i = temp.size() - 1; i >= 0; i--) {
  115 + futures.addFuture(temp[i]);
  116 + }
  117 +
  118 + futures.waitForFinished();
  119 +
  120 + for (int i=0; i<src.size(); i++) dst.append(output_buffer[i]);
  121 + }
  122 +
  123 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  124 + {
  125 + this->project(src, dst);
  126 + return;
  127 + }
  128 +
  129 + void init()
  130 + {
  131 + if (!transform)
  132 + return;
  133 +
  134 + trainable = transform->trainable;
  135 + }
  136 +
  137 +};
  138 +BR_REGISTER(Transform, DistributeTemplateTransform)
  139 +
  140 +} // namespace br
  141 +
  142 +#include "core/distributetemplate.moc"
... ...
openbr/plugins/core/downsampletraining.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +static TemplateList Downsample(const TemplateList &templates, int classes, int instances, float fraction, const QString &inputVariable, const QStringList &gallery, const QStringList &subjects)
  23 +{
  24 + // Return early when no downsampling is required
  25 + if ((classes == std::numeric_limits<int>::max()) &&
  26 + (instances == std::numeric_limits<int>::max()) &&
  27 + (fraction >= 1) &&
  28 + (gallery.isEmpty()) &&
  29 + (subjects.isEmpty()))
  30 + return templates;
  31 +
  32 + const bool atLeast = instances < 0;
  33 + instances = abs(instances);
  34 +
  35 + QList<QString> allLabels = File::get<QString>(templates, inputVariable);
  36 +
  37 + QList<QString> uniqueLabels = allLabels.toSet().toList();
  38 + qSort(uniqueLabels);
  39 +
  40 + QMap<QString,int> counts = templates.countValues<QString>(inputVariable, instances != std::numeric_limits<int>::max());
  41 +
  42 + if ((instances != std::numeric_limits<int>::max()) && (classes != std::numeric_limits<int>::max()))
  43 + foreach (const QString &label, counts.keys())
  44 + if (counts[label] < instances)
  45 + counts.remove(label);
  46 +
  47 + uniqueLabels = counts.keys();
  48 + if ((classes != std::numeric_limits<int>::max()) && (uniqueLabels.size() < classes))
  49 + qWarning("Downsample requested %d classes but only %d are available.", classes, uniqueLabels.size());
  50 +
  51 + QList<QString> selectedLabels = uniqueLabels;
  52 + if (classes < uniqueLabels.size()) {
  53 + std::random_shuffle(selectedLabels.begin(), selectedLabels.end());
  54 + selectedLabels = selectedLabels.mid(0, classes);
  55 + }
  56 +
  57 + TemplateList downsample;
  58 + for (int i=0; i<selectedLabels.size(); i++) {
  59 + const QString selectedLabel = selectedLabels[i];
  60 + QList<int> indices;
  61 + for (int j=0; j<allLabels.size(); j++)
  62 + if ((allLabels[j] == selectedLabel) && (!templates.value(j).file.get<bool>("FTE", false)) && (!templates.value(j).file.get<bool>("PossibleFTE", false)))
  63 + indices.append(j);
  64 +
  65 + std::random_shuffle(indices.begin(), indices.end());
  66 + const int max = atLeast ? indices.size() : std::min(indices.size(), instances);
  67 + for (int j=0; j<max; j++)
  68 + downsample.append(templates.value(indices[j]));
  69 + }
  70 +
  71 + if (fraction < 1) {
  72 + std::random_shuffle(downsample.begin(), downsample.end());
  73 + downsample = downsample.mid(0, downsample.size()*fraction);
  74 + }
  75 +
  76 + if (!gallery.isEmpty())
  77 + for (int i=downsample.size()-1; i>=0; i--)
  78 + if (!gallery.contains(downsample[i].file.get<QString>("Gallery")))
  79 + downsample.removeAt(i);
  80 +
  81 + if (!subjects.isEmpty())
  82 + for (int i=downsample.size()-1; i>=0; i--)
  83 + if (subjects.contains(downsample[i].file.get<QString>(inputVariable)))
  84 + downsample.removeAt(i);
  85 +
  86 + return downsample;
  87 +}
  88 +
  89 +class DownsampleTrainingTransform : public Transform
  90 +{
  91 + Q_OBJECT
  92 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform STORED true)
  93 + Q_PROPERTY(int classes READ get_classes WRITE set_classes RESET reset_classes STORED false)
  94 + Q_PROPERTY(int instances READ get_instances WRITE set_instances RESET reset_instances STORED false)
  95 + Q_PROPERTY(float fraction READ get_fraction WRITE set_fraction RESET reset_fraction STORED false)
  96 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  97 + Q_PROPERTY(QStringList gallery READ get_gallery WRITE set_gallery RESET reset_gallery STORED false)
  98 + Q_PROPERTY(QStringList subjects READ get_subjects WRITE set_subjects RESET reset_subjects STORED false)
  99 + BR_PROPERTY(br::Transform*, transform, NULL)
  100 + BR_PROPERTY(int, classes, std::numeric_limits<int>::max())
  101 + BR_PROPERTY(int, instances, std::numeric_limits<int>::max())
  102 + BR_PROPERTY(float, fraction, 1)
  103 + BR_PROPERTY(QString, inputVariable, "Label")
  104 + BR_PROPERTY(QStringList, gallery, QStringList())
  105 + BR_PROPERTY(QStringList, subjects, QStringList())
  106 +
  107 +
  108 + Transform *simplify(bool &newTForm)
  109 + {
  110 + Transform *res = transform->simplify(newTForm);
  111 + return res;
  112 + }
  113 +
  114 + void project(const Template &src, Template &dst) const
  115 + {
  116 + transform->project(src,dst);
  117 + }
  118 +
  119 +
  120 + void train(const TemplateList &data)
  121 + {
  122 + if (!transform || !transform->trainable)
  123 + return;
  124 +
  125 + TemplateList downsampled = Downsample(data, classes, instances, fraction, inputVariable, gallery, subjects);
  126 +
  127 + transform->train(downsampled);
  128 + }
  129 +};
  130 +
  131 +BR_REGISTER(Transform, DownsampleTrainingTransform)
  132 +
  133 +} // namespace br
  134 +
  135 +#include "core/downsampletraining.moc"
... ...
openbr/plugins/core/event.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +class EventTransform : public UntrainableMetaTransform
  23 +{
  24 + Q_OBJECT
  25 + Q_PROPERTY(QString eventName READ get_eventName WRITE set_eventName RESET reset_eventName STORED false)
  26 + BR_PROPERTY(QString, eventName, "")
  27 +
  28 + TemplateEvent event;
  29 +
  30 + void project(const Template &src, Template &dst) const
  31 + {
  32 + dst = src;
  33 + event.pulseSignal(dst);
  34 + }
  35 +
  36 + TemplateEvent *getEvent(const QString &name)
  37 + {
  38 + return name == eventName ? &event : NULL;
  39 + }
  40 +};
  41 +
  42 +BR_REGISTER(Transform, EventTransform)
  43 +
  44 +} // namespace br
  45 +
  46 +#include "core/event.moc"
... ...
openbr/plugins/core/expand.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +static TemplateList Expanded(const TemplateList &templates)
  23 +{
  24 + TemplateList expanded;
  25 + foreach (const Template &t, templates) {
  26 + const bool enrollAll = t.file.get<bool>("enrollAll");
  27 + if (t.isEmpty()) {
  28 + if (!enrollAll)
  29 + expanded.append(t);
  30 + continue;
  31 + }
  32 +
  33 + const QList<QPointF> points = t.file.points();
  34 + const QList<QRectF> rects = t.file.rects();
  35 + if (points.size() % t.size() != 0) qFatal("Uneven point count.");
  36 + if (rects.size() % t.size() != 0) qFatal("Uneven rect count.");
  37 + const int pointStep = points.size() / t.size();
  38 + const int rectStep = rects.size() / t.size();
  39 +
  40 + for (int i=0; i<t.size(); i++) {
  41 + expanded.append(Template(t.file, t[i]));
  42 + expanded.last().file.setRects(rects.mid(i*rectStep, rectStep));
  43 + expanded.last().file.setPoints(points.mid(i*pointStep, pointStep));
  44 + }
  45 + }
  46 + return expanded;
  47 +}
  48 +
  49 +/*!
  50 + * \ingroup transforms
  51 + * \brief Performs an expansion step on input templatelists
  52 + * \author Josh Klontz \cite jklontz
  53 + *
  54 + * Each matrix in an input Template is expanded into its own template.
  55 + *
  56 + * \see PipeTransform
  57 + */
  58 +class ExpandTransform : public UntrainableMetaTransform
  59 +{
  60 + Q_OBJECT
  61 +
  62 + virtual void project(const TemplateList &src, TemplateList &dst) const
  63 + {
  64 + dst = Expanded(src);
  65 + }
  66 +
  67 + virtual void project(const Template &src, Template &dst) const
  68 + {
  69 + dst = src;
  70 + qDebug("Called Expand project(Template,Template), nothing will happen");
  71 + }
  72 +};
  73 +
  74 +BR_REGISTER(Transform, ExpandTransform)
  75 +
  76 +} // namespace br
  77 +
  78 +#include "core/expand.moc"
... ...
openbr/plugins/core/first.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief Removes all but the first matrix from the template.
  25 + * \see IdentityTransform DiscardTransform RestTransform RemoveTransform
  26 + * \author Josh Klontz \cite jklontz
  27 + */
  28 +class FirstTransform : public UntrainableMetaTransform
  29 +{
  30 + Q_OBJECT
  31 +
  32 + void project(const Template &src, Template &dst) const
  33 + {
  34 + // AggregateFrames will leave the Template empty
  35 + // if it hasn't filled up the buffer
  36 + // so we gotta anticipate an empty Template
  37 + if (src.empty()) return;
  38 + dst.file = src.file;
  39 + dst = src.m();
  40 + }
  41 +};
  42 +
  43 +BR_REGISTER(Transform, FirstTransform)
  44 +
  45 +} // namespace br
  46 +
  47 +#include "core/first.moc"
... ...
openbr/plugins/core/fork.cpp 0 → 100644
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +static void _train(Transform *transform, const QList<TemplateList> *data)
  25 +{
  26 + transform->train(*data);
  27 +}
  28 +
  29 +/*!
  30 + * \ingroup transforms
  31 + * \brief Transforms in parallel.
  32 + * \author Josh Klontz \cite jklontz
  33 + *
  34 + * The source br::Template is seperately given to each transform and the results are appended together.
  35 + *
  36 + * \see PipeTransform
  37 + */
  38 +class ForkTransform : public CompositeTransform
  39 +{
  40 + Q_OBJECT
  41 +
  42 + void train(const QList<TemplateList> &data)
  43 + {
  44 + if (!trainable) return;
  45 + QFutureSynchronizer<void> futures;
  46 + for (int i=0; i<transforms.size(); i++)
  47 + futures.addFuture(QtConcurrent::run(_train, transforms[i], &data));
  48 + futures.waitForFinished();
  49 + }
  50 +
  51 + // same as _project, but calls projectUpdate on sub-transforms
  52 + void projectupdate(const Template &src, Template &dst)
  53 + {
  54 + foreach (Transform *f, transforms) {
  55 + try {
  56 + Template res;
  57 + f->projectUpdate(src, res);
  58 + dst.merge(res);
  59 + } catch (...) {
  60 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  61 + dst = Template(src.file);
  62 + dst.file.fte = true;
  63 + break;
  64 + }
  65 + }
  66 + }
  67 +
  68 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  69 + {
  70 + dst.reserve(src.size());
  71 + for (int i=0; i<src.size(); i++) dst.append(Template(src[i].file));
  72 + foreach (Transform *f, transforms) {
  73 + TemplateList m;
  74 + f->projectUpdate(src, m);
  75 + if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size.");
  76 + for (int i=0; i<src.size(); i++) dst[i].merge(m[i]);
  77 + }
  78 + }
  79 +
  80 + // this is probably going to go bad, fork transform probably won't work well in a variable
  81 + // input/output scenario
  82 + virtual void finalize(TemplateList &output)
  83 + {
  84 + output.clear();
  85 + // For each transform,
  86 + for (int i = 0; i < transforms.size(); i++)
  87 + {
  88 + // Collect any final templates
  89 + TemplateList last_set;
  90 + transforms[i]->finalize(last_set);
  91 + if (last_set.empty())
  92 + continue;
  93 +
  94 + if (output.empty()) output = last_set;
  95 + else
  96 + {
  97 + // is the number of templates received from this transform consistent with the number
  98 + // received previously? If not we can't do anything coherent here.
  99 + if (last_set.size() != output.size())
  100 + qFatal("mismatched template list sizes in ForkTransform");
  101 + for (int j = 0; j < output.size(); j++) {
  102 + output[j].append(last_set[j]);
  103 + }
  104 + }
  105 + }
  106 + }
  107 +
  108 +protected:
  109 +
  110 + // Apply each transform to src, concatenate the results
  111 + void _project(const Template &src, Template &dst) const
  112 + {
  113 + foreach (const Transform *f, transforms) {
  114 + try {
  115 + dst.merge((*f)(src));
  116 + } catch (...) {
  117 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  118 + dst = Template(src.file);
  119 + dst.file.fte = true;
  120 + break;
  121 + }
  122 + }
  123 + }
  124 +
  125 + void _project(const TemplateList &src, TemplateList &dst) const
  126 + {
  127 + dst.reserve(src.size());
  128 + for (int i=0; i<src.size(); i++) dst.append(Template(src[i].file));
  129 + foreach (const Transform *f, transforms) {
  130 + TemplateList m;
  131 + f->project(src, m);
  132 + if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size.");
  133 + for (int i=0; i<src.size(); i++) dst[i].merge(m[i]);
  134 + }
  135 + }
  136 +
  137 +};
  138 +
  139 +BR_REGISTER(Transform, ForkTransform)
  140 +
  141 +} // namespace br
  142 +
  143 +#include "core/fork.moc"
... ...
openbr/plugins/core/fte.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/common.h>
  19 +
  20 +namespace br
  21 +{
  22 +
  23 +/*!
  24 + * \ingroup transforms
  25 + * \brief Flags images that failed to enroll based on the specified transform.
  26 + * \author Josh Klontz \cite jklontz
  27 + */
  28 +class FTETransform : public Transform
  29 +{
  30 + Q_OBJECT
  31 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  32 + Q_PROPERTY(float min READ get_min WRITE set_min RESET reset_min)
  33 + Q_PROPERTY(float max READ get_max WRITE set_max RESET reset_max)
  34 + BR_PROPERTY(br::Transform*, transform, NULL)
  35 + BR_PROPERTY(float, min, -std::numeric_limits<float>::max())
  36 + BR_PROPERTY(float, max, std::numeric_limits<float>::max())
  37 +
  38 + void train(const TemplateList &data)
  39 + {
  40 + transform->train(data);
  41 +
  42 + TemplateList projectedData;
  43 + transform->project(data, projectedData);
  44 +
  45 + QList<float> vals;
  46 + foreach (const Template &t, projectedData) {
  47 + if (!t.file.contains(transform->objectName()))
  48 + qFatal("Matrix metadata missing key %s.", qPrintable(transform->objectName()));
  49 + vals.append(t.file.get<float>(transform->objectName()));
  50 + }
  51 + float q1, q3;
  52 + Common::Median(vals, &q1, &q3);
  53 + min = q1 - 1.5 * (q3 - q1);
  54 + max = q3 + 1.5 * (q3 - q1);
  55 + }
  56 +
  57 + void project(const Template &src, Template &dst) const
  58 + {
  59 + Template projectedSrc;
  60 + transform->project(src, projectedSrc);
  61 + const float val = projectedSrc.file.get<float>(transform->objectName());
  62 +
  63 + dst = src;
  64 + dst.file.set(transform->objectName(), val);
  65 + dst.file.set("PossibleFTE", (val < min) || (val > max));
  66 + }
  67 +};
  68 +
  69 +BR_REGISTER(Transform, FTETransform)
  70 +
  71 +} // namespace br
  72 +
  73 +#include "core/fte.moc"
... ...
openbr/plugins/core/gallerycompare.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/opencvutils.h>
  19 +
  20 +namespace br
  21 +{
  22 +
  23 +/*!
  24 + * \ingroup transforms
  25 + * \brief Compare each template to a fixed gallery (with name = galleryName), using the specified distance.
  26 + * dst will contain a 1 by n vector of scores.
  27 + * \author Charles Otto \cite caotto
  28 + */
  29 +class GalleryCompareTransform : public Transform
  30 +{
  31 + Q_OBJECT
  32 + Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED true)
  33 + Q_PROPERTY(QString galleryName READ get_galleryName WRITE set_galleryName RESET reset_galleryName STORED false)
  34 + BR_PROPERTY(br::Distance*, distance, NULL)
  35 + BR_PROPERTY(QString, galleryName, "")
  36 +
  37 + TemplateList gallery;
  38 +
  39 + void project(const Template &src, Template &dst) const
  40 + {
  41 + dst = src;
  42 + if (gallery.isEmpty())
  43 + return;
  44 +
  45 + QList<float> line = distance->compare(gallery, src);
  46 + dst.m() = OpenCVUtils::toMat(line, 1);
  47 + }
  48 +
  49 + void init()
  50 + {
  51 + if (!galleryName.isEmpty())
  52 + gallery = TemplateList::fromGallery(galleryName);
  53 + }
  54 +
  55 + void train(const TemplateList &data)
  56 + {
  57 + gallery = data;
  58 + }
  59 +
  60 + void store(QDataStream &stream) const
  61 + {
  62 + br::Object::store(stream);
  63 + stream << gallery;
  64 + }
  65 +
  66 + void load(QDataStream &stream)
  67 + {
  68 + br::Object::load(stream);
  69 + stream >> gallery;
  70 + }
  71 +
  72 +public:
  73 + GalleryCompareTransform() : Transform(false, true) {}
  74 +};
  75 +
  76 +BR_REGISTER(Transform, GalleryCompareTransform)
  77 +
  78 +} // namespace br
  79 +
  80 +#include "core/gallerycompare.moc"
... ...
openbr/plugins/core/identity.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief A no-op transform.
  25 + * \see DiscardTransform FirstTransform RestTransform RemoveTransform
  26 + * \author Josh Klontz \cite jklontz
  27 + */
  28 +class IdentityTransform : public UntrainableMetaTransform
  29 +{
  30 + Q_OBJECT
  31 +
  32 + void project(const Template &src, Template &dst) const
  33 + {
  34 + dst = src;
  35 + }
  36 +};
  37 +
  38 +BR_REGISTER(Transform, IdentityTransform)
  39 +
  40 +} // namespace br
  41 +
  42 +#include "core/identity.moc"
... ...
openbr/plugins/core/independent.cpp 0 → 100644
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +using namespace cv;
  22 +
  23 +namespace br
  24 +{
  25 +
  26 +/*!
  27 + * \ingroup transforms
  28 + * \brief Clones the transform so that it can be applied independently.
  29 + * \author Josh Klontz \cite jklontz
  30 + * \em Independent transforms expect single-matrix templates.
  31 + */
  32 +class IndependentTransform : public MetaTransform
  33 +{
  34 + Q_OBJECT
  35 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
  36 + BR_PROPERTY(br::Transform*, transform, NULL)
  37 +
  38 + QList<Transform*> transforms;
  39 +
  40 + QString description(bool expanded) const
  41 + {
  42 + return transform->description(expanded);
  43 + }
  44 +
  45 + // can't use general setPropertyRecursive because of transforms oddness
  46 + bool setPropertyRecursive(const QString &name, QVariant value)
  47 + {
  48 + if (br::Object::setExistingProperty(name, value))
  49 + return true;
  50 +
  51 + if (!transform->setPropertyRecursive(name, value))
  52 + return false;
  53 +
  54 + for (int i=0;i < transforms.size();i++)
  55 + transforms[i]->setPropertyRecursive(name, value);
  56 +
  57 + return true;
  58 + }
  59 +
  60 + Transform *simplify(bool &newTransform)
  61 + {
  62 + newTransform = false;
  63 + bool newChild = false;
  64 + Transform *temp = transform->simplify(newChild);
  65 + if (temp == transform) {
  66 + return this;
  67 + }
  68 + IndependentTransform* indep = new IndependentTransform();
  69 + indep->transform = temp;
  70 +
  71 + IndependentTransform *test = dynamic_cast<IndependentTransform *> (temp);
  72 + if (test) {
  73 + // child was independent? this changes things...
  74 + indep->transform = test->transform;
  75 + for (int i=0; i < transforms.size(); i++) {
  76 + bool newThing = false;
  77 + IndependentTransform *probe = dynamic_cast<IndependentTransform *> (transforms[i]->simplify(newThing));
  78 + indep->transforms.append(probe->transform);
  79 + if (newThing)
  80 + probe->setParent(indep);
  81 + }
  82 + indep->file = indep->transform->file;
  83 + indep->trainable = indep->transform->trainable;
  84 + indep->setObjectName(indep->transform->objectName());
  85 +
  86 + return indep;
  87 + }
  88 +
  89 + if (newChild)
  90 + indep->transform->setParent(indep);
  91 +
  92 + for (int i=0; i < transforms.size();i++) {
  93 + bool subTform = false;
  94 + indep->transforms.append(transforms[i]->simplify(subTform));
  95 + if (subTform)
  96 + indep->transforms[i]->setParent(indep);
  97 + }
  98 +
  99 + indep->file = indep->transform->file;
  100 + indep->trainable = indep->transform->trainable;
  101 + indep->setObjectName(indep->transform->objectName());
  102 +
  103 + return indep;
  104 + }
  105 +
  106 + void init()
  107 + {
  108 + transforms.clear();
  109 + if (transform == NULL)
  110 + return;
  111 +
  112 + transform->setParent(this);
  113 + transforms.append(transform);
  114 + file = transform->file;
  115 + trainable = transform->trainable;
  116 + setObjectName(transform->objectName());
  117 + }
  118 +
  119 + Transform *clone() const
  120 + {
  121 + IndependentTransform *independentTransform = new IndependentTransform();
  122 + independentTransform->transform = transform->clone();
  123 + independentTransform->init();
  124 + return independentTransform;
  125 + }
  126 +
  127 + bool timeVarying() const { return transform->timeVarying(); }
  128 +
  129 + static void _train(Transform *transform, const TemplateList *data)
  130 + {
  131 + transform->train(*data);
  132 + }
  133 +
  134 + void train(const TemplateList &data)
  135 + {
  136 + // Don't bother if the transform is untrainable
  137 + if (!trainable) return;
  138 +
  139 + QList<TemplateList> templatesList;
  140 + foreach (const Template &t, data) {
  141 + if ((templatesList.size() != t.size()) && !templatesList.isEmpty())
  142 + qWarning("Independent::train (%s) template %s of size %d differs from expected size %d.", qPrintable(objectName()), qPrintable(t.file.name), t.size(), templatesList.size());
  143 + while (templatesList.size() < t.size())
  144 + templatesList.append(TemplateList());
  145 + for (int i=0; i<t.size(); i++)
  146 + templatesList[i].append(Template(t.file, t[i]));
  147 + }
  148 +
  149 + while (transforms.size() < templatesList.size())
  150 + transforms.append(transform->clone());
  151 +
  152 + QFutureSynchronizer<void> futures;
  153 + for (int i=0; i<templatesList.size(); i++)
  154 + futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i]));
  155 + futures.waitForFinished();
  156 + }
  157 +
  158 + void project(const Template &src, Template &dst) const
  159 + {
  160 + dst.file = src.file;
  161 + QList<Mat> mats;
  162 + for (int i=0; i<src.size(); i++) {
  163 + transforms[i%transforms.size()]->project(Template(src.file, src[i]), dst);
  164 + mats.append(dst);
  165 + dst.clear();
  166 + }
  167 + dst.append(mats);
  168 + }
  169 +
  170 + void projectUpdate(const Template &src, Template &dst)
  171 + {
  172 + dst.file = src.file;
  173 + QList<Mat> mats;
  174 + for (int i=0; i<src.size(); i++) {
  175 + transforms[i%transforms.size()]->projectUpdate(Template(src.file, src[i]), dst);
  176 + mats.append(dst);
  177 + dst.clear();
  178 + }
  179 + dst.append(mats);
  180 + }
  181 +
  182 + void finalize(TemplateList &out)
  183 + {
  184 + if (transforms.empty())
  185 + return;
  186 +
  187 + transforms[0]->finalize(out);
  188 + for (int i=1; i < transforms.size(); i++) {
  189 + TemplateList temp;
  190 + transforms[i]->finalize(temp);
  191 +
  192 + for (int j=0; j < out.size(); j++)
  193 + out[j].append(temp[j]);
  194 + }
  195 + }
  196 +
  197 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  198 + {
  199 + dst.reserve(src.size());
  200 + foreach (const Template &t, src) {
  201 + dst.append(Template());
  202 + projectUpdate(t, dst.last());
  203 + }
  204 + }
  205 +
  206 + void store(QDataStream &stream) const
  207 + {
  208 + const int size = transforms.size();
  209 + stream << size;
  210 + for (int i=0; i<size; i++)
  211 + transforms[i]->store(stream);
  212 + }
  213 +
  214 + void load(QDataStream &stream)
  215 + {
  216 + int size;
  217 + stream >> size;
  218 + while (transforms.size() < size)
  219 + transforms.append(transform->clone());
  220 + for (int i=0; i<size; i++)
  221 + transforms[i]->load(stream);
  222 + }
  223 +};
  224 +
  225 +BR_REGISTER(Transform, IndependentTransform)
  226 +
  227 +} // namespace br
  228 +
  229 +#include "core/independent.moc"
... ...
openbr/plugins/jni.cpp renamed to openbr/plugins/core/jni.cpp
1 1 //Need to include location of jvm.dll (jdk version) and its parent directory in the environment variables
2 2  
3 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 6 #include <jni.h>
7 7  
8 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 3 namespace br
8 4 {
... ... @@ -57,68 +53,6 @@ public:
57 53  
58 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 56 } // namespace br
123 57  
124   -#include "likely.moc"
  58 +#include "core/likely.moc"
... ...
openbr/plugins/core/loadstore.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/qtutils.h>
  19 +
  20 +namespace br
  21 +{
  22 +
  23 +/*!
  24 + * \ingroup transforms
  25 + * \brief Caches transform training.
  26 + * \author Josh Klontz \cite jklontz
  27 + */
  28 +class LoadStoreTransform : public MetaTransform
  29 +{
  30 + Q_OBJECT
  31 + Q_PROPERTY(QString transformString READ get_transformString WRITE set_transformString RESET reset_transformString STORED false)
  32 + Q_PROPERTY(QString fileName READ get_fileName WRITE set_fileName RESET reset_fileName STORED false)
  33 + BR_PROPERTY(QString, transformString, "Identity")
  34 + BR_PROPERTY(QString, fileName, QString())
  35 +
  36 +public:
  37 + Transform *transform;
  38 +
  39 + LoadStoreTransform() : transform(NULL) {}
  40 +
  41 + QString description(bool expanded = false) const
  42 + {
  43 + if (expanded) {
  44 + QString res = transform->description(expanded);
  45 + return res;
  46 + }
  47 + return br::Object::description(expanded);
  48 + }
  49 +
  50 + Transform *simplify(bool &newTForm)
  51 + {
  52 + Transform *res = transform->simplify(newTForm);
  53 + return res;
  54 + }
  55 +
  56 + QList<Object *> getChildren() const
  57 + {
  58 + QList<Object *> rval;
  59 + rval.append(transform);
  60 + return rval;
  61 + }
  62 +private:
  63 +
  64 + void init()
  65 + {
  66 + if (transform != NULL) return;
  67 + if (fileName.isEmpty()) fileName = QRegExp("^[_a-zA-Z0-9]+$").exactMatch(transformString) ? transformString : QtUtils::shortTextHash(transformString);
  68 +
  69 + if (!tryLoad())
  70 + transform = make(transformString);
  71 + else
  72 + trainable = false;
  73 + }
  74 +
  75 + bool timeVarying() const
  76 + {
  77 + return transform->timeVarying();
  78 + }
  79 +
  80 + void train(const QList<TemplateList> &data)
  81 + {
  82 + if (QFileInfo(getFileName()).exists())
  83 + return;
  84 +
  85 + transform->train(data);
  86 +
  87 + qDebug("Storing %s", qPrintable(fileName));
  88 + QtUtils::BlockCompression compressedOut;
  89 + QFile fout(fileName);
  90 + QtUtils::touchDir(fout);
  91 + compressedOut.setBasis(&fout);
  92 +
  93 + QDataStream stream(&compressedOut);
  94 + QString desc = transform->description();
  95 +
  96 + if (!compressedOut.open(QFile::WriteOnly))
  97 + qFatal("Failed to open %s for writing.", qPrintable(file));
  98 +
  99 + stream << desc;
  100 + transform->store(stream);
  101 + compressedOut.close();
  102 + }
  103 +
  104 + void project(const Template &src, Template &dst) const
  105 + {
  106 + transform->project(src, dst);
  107 + }
  108 +
  109 + void project(const TemplateList &src, TemplateList &dst) const
  110 + {
  111 + transform->project(src, dst);
  112 + }
  113 +
  114 + void projectUpdate(const Template &src, Template &dst)
  115 + {
  116 + transform->projectUpdate(src, dst);
  117 + }
  118 +
  119 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  120 + {
  121 + transform->projectUpdate(src, dst);
  122 + }
  123 +
  124 + void finalize(TemplateList &output)
  125 + {
  126 + transform->finalize(output);
  127 + }
  128 +
  129 + QString getFileName() const
  130 + {
  131 + if (QFileInfo(fileName).exists()) return fileName;
  132 + const QString file = Globals->sdkPath + "/share/openbr/models/transforms/" + fileName;
  133 + return QFileInfo(file).exists() ? file : QString();
  134 + }
  135 +
  136 + bool tryLoad()
  137 + {
  138 + const QString file = getFileName();
  139 + if (file.isEmpty()) return false;
  140 +
  141 + qDebug("Loading %s", qPrintable(file));
  142 + QFile fin(file);
  143 + QtUtils::BlockCompression reader(&fin);
  144 + if (!reader.open(QIODevice::ReadOnly)) {
  145 + if (QFileInfo(file).exists()) qFatal("Unable to open %s for reading. Check file permissions.", qPrintable(file));
  146 + else qFatal("Unable to open %s for reading. File does not exist.", qPrintable(file));
  147 + }
  148 +
  149 + QDataStream stream(&reader);
  150 + stream >> transformString;
  151 +
  152 + transform = Transform::make(transformString);
  153 + transform->load(stream);
  154 +
  155 + return true;
  156 + }
  157 +};
  158 +
  159 +BR_REGISTER(Transform, LoadStoreTransform)
  160 +
  161 +} // namespace br
  162 +
  163 +#include "core/loadstore.moc"
... ...
openbr/plugins/core/pipe.cpp 0 → 100644
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +/*!
  25 + * \ingroup Transforms
  26 + * \brief Transforms in series.
  27 + * \author Josh Klontz \cite jklontz
  28 + *
  29 + * The source br::Template is given to the first transform and the resulting br::Template is passed to the next transform, etc.
  30 + *
  31 + * \see ExpandTransform
  32 + * \see ForkTransform
  33 + */
  34 +class PipeTransform : public CompositeTransform
  35 +{
  36 + Q_OBJECT
  37 +
  38 + void _projectPartial(TemplateList *srcdst, int startIndex, int stopIndex)
  39 + {
  40 + TemplateList ftes;
  41 + for (int i=startIndex; i<stopIndex; i++) {
  42 + TemplateList res;
  43 + transforms[i]->project(*srcdst, res);
  44 +
  45 + splitFTEs(res, ftes);
  46 + *srcdst = res;
  47 + }
  48 + }
  49 +
  50 + void train(const QList<TemplateList> &data)
  51 + {
  52 + if (!trainable) return;
  53 +
  54 + QList<TemplateList> dataLines(data);
  55 +
  56 + int i = 0;
  57 + while (i < transforms.size()) {
  58 + // Conditional statement covers likely case that first transform is untrainable
  59 + if (transforms[i]->trainable) {
  60 + qDebug() << "Training " << transforms[i]->description() << "\n...";
  61 + transforms[i]->train(dataLines);
  62 + }
  63 +
  64 + // if the transform is time varying, we can't project it in parallel
  65 + if (transforms[i]->timeVarying()) {
  66 + qDebug() << "Projecting " << transforms[i]->description() << "\n...";
  67 + for (int j=0; j < dataLines.size();j++) {
  68 + TemplateList junk;
  69 + splitFTEs(dataLines[j], junk);
  70 +
  71 + transforms[i]->projectUpdate(dataLines[j], dataLines[j]);
  72 + }
  73 +
  74 + // advance i since we already projected for this stage.
  75 + i++;
  76 +
  77 + // the next stage might be trainable, so continue to evaluate it.
  78 + continue;
  79 + }
  80 +
  81 + // We project through any subsequent untrainable transforms at once
  82 + // as a memory optimization in case any of these intermediate
  83 + // transforms allocate a lot of memory (like OpenTransform)
  84 + // then we don't want all the training templates to be processed
  85 + // by that transform at once if we can avoid it.
  86 + int nextTrainableTransform = i+1;
  87 + while ((nextTrainableTransform < transforms.size()) &&
  88 + !transforms[nextTrainableTransform]->trainable &&
  89 + !transforms[nextTrainableTransform]->timeVarying())
  90 + nextTrainableTransform++;
  91 +
  92 + // No more trainable transforms? Don't need any more projects then
  93 + if (nextTrainableTransform == transforms.size())
  94 + break;
  95 +
  96 + fprintf(stderr, "Projecting %s", qPrintable(transforms[i]->description()));
  97 + for (int j=i+1; j < nextTrainableTransform; j++)
  98 + fprintf(stderr,"+%s", qPrintable(transforms[j]->description()));
  99 + fprintf(stderr, "\n...\n");
  100 + fflush(stderr);
  101 +
  102 + QFutureSynchronizer<void> futures;
  103 + for (int j=0; j < dataLines.size(); j++)
  104 + futures.addFuture(QtConcurrent::run(this, &PipeTransform::_projectPartial, &dataLines[j], i, nextTrainableTransform));
  105 + futures.waitForFinished();
  106 +
  107 + i = nextTrainableTransform;
  108 + }
  109 + }
  110 +
  111 + void projectUpdate(const Template &src, Template &dst)
  112 + {
  113 + dst = src;
  114 + foreach (Transform *f, transforms) {
  115 + try {
  116 + f->projectUpdate(dst);
  117 + if (dst.file.fte)
  118 + break;
  119 + } catch (...) {
  120 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  121 + dst = Template(src.file);
  122 + dst.file.fte = true;
  123 + break;
  124 + }
  125 + }
  126 + }
  127 +
  128 + // For time varying transforms, parallel execution over individual templates
  129 + // won't work.
  130 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  131 + {
  132 + TemplateList ftes;
  133 + dst = src;
  134 + foreach (Transform *f, transforms) {
  135 + TemplateList res;
  136 + f->projectUpdate(dst, res);
  137 + splitFTEs(res, ftes);
  138 + dst = res;
  139 + }
  140 + dst.append(ftes);
  141 + }
  142 +
  143 + virtual void finalize(TemplateList &output)
  144 + {
  145 + output.clear();
  146 + // For each transform,
  147 + for (int i = 0; i < transforms.size(); i++)
  148 + {
  149 +
  150 + // Collect any final templates
  151 + TemplateList last_set;
  152 + transforms[i]->finalize(last_set);
  153 + if (last_set.empty())
  154 + continue;
  155 + // Push any templates received through the remaining transforms in the sequence
  156 + for (int j = (i+1); j < transforms.size();j++)
  157 + {
  158 + transforms[j]->projectUpdate(last_set);
  159 + }
  160 + // append the result to the output set
  161 + output.append(last_set);
  162 + }
  163 + }
  164 +
  165 + void init()
  166 + {
  167 + QList<Transform *> flattened;
  168 + for (int i=0;i < transforms.size(); i++)
  169 + {
  170 + PipeTransform *probe = dynamic_cast<PipeTransform *> (transforms[i]);
  171 + if (!probe) {
  172 + flattened.append(transforms[i]);
  173 + continue;
  174 + }
  175 + for (int j=0; j < probe->transforms.size(); j++)
  176 + flattened.append(probe->transforms[j]);
  177 + }
  178 + transforms = flattened;
  179 +
  180 + CompositeTransform::init();
  181 + }
  182 +
  183 +protected:
  184 + // Template list project -- process templates in parallel through Transform::project
  185 + // or if parallelism is disabled, handle them sequentially
  186 + void _project(const TemplateList &src, TemplateList &dst) const
  187 + {
  188 + TemplateList ftes;
  189 + dst = src;
  190 + foreach (const Transform *f, transforms) {
  191 + TemplateList res;
  192 + f->project(dst, res);
  193 + splitFTEs(res, ftes);
  194 + dst = res;
  195 + }
  196 + dst.append(ftes);
  197 + }
  198 +
  199 + // Single template const project, pass the template through each sub-transform, one after the other
  200 + virtual void _project(const Template &src, Template &dst) const
  201 + {
  202 + dst = src;
  203 + foreach (const Transform *f, transforms) {
  204 + try {
  205 + dst >> *f;
  206 + if (dst.file.fte)
  207 + break;
  208 + } catch (...) {
  209 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  210 + dst = Template(src.file);
  211 + dst.file.fte = true;
  212 + }
  213 + }
  214 + }
  215 +};
  216 +
  217 +BR_REGISTER(Transform, PipeTransform)
  218 +
  219 +} // namespace br
  220 +
  221 +#include "core/pipe.moc"
... ...
openbr/plugins/process.cpp renamed to openbr/plugins/core/processwrapper.cpp
1   -
  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 + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 16  
3 17 #include <QBuffer>
4 18 #include <QCoreApplication>
... ... @@ -9,8 +23,8 @@
9 23 #include <QUuid>
10 24 #include <QWaitCondition>
11 25  
12   -#include "openbr_internal.h"
13   -#include "openbr/core/opencvutils.h"
  26 +#include <openbr/plugins/openbr_internal.h>
  27 +#include <openbr/core/opencvutils.h>
14 28  
15 29 using namespace cv;
16 30  
... ... @@ -658,4 +672,4 @@ BR_REGISTER(Transform, ProcessWrapperTransform)
658 672  
659 673 }
660 674  
661   -#include "process.moc"
  675 +#include "core/processwrapper.moc"
... ...
openbr/plugins/core/progresscounter.cpp 0 → 100644
  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 <QElapsedTimer>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/qtutils.h>
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +class ProgressCounterTransform : public TimeVaryingTransform
  26 +{
  27 + Q_OBJECT
  28 +
  29 + Q_PROPERTY(qint64 totalProgress READ get_totalProgress WRITE set_totalProgress RESET reset_totalProgress STORED false)
  30 + BR_PROPERTY(qint64, totalProgress, 1)
  31 +
  32 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  33 + {
  34 + dst = src;
  35 +
  36 + qint64 elapsed = timer.elapsed();
  37 + int last_frame = -2;
  38 + if (!dst.empty()) {
  39 + for (int i=0;i < dst.size();i++) {
  40 + int frame = dst[i].file.get<int>("FrameNumber", -1);
  41 + if (frame == last_frame && frame != -1)
  42 + continue;
  43 +
  44 + // Use 1 as the starting index for progress output
  45 + Globals->currentProgress = dst[i].file.get<qint64>("progress",0)+1;
  46 + dst[i].file.remove("progress");
  47 + last_frame = frame;
  48 +
  49 + Globals->currentStep++;
  50 + }
  51 + }
  52 +
  53 + // updated every second
  54 + if (elapsed > 1000) {
  55 + Globals->printStatus();
  56 + timer.start();
  57 + }
  58 +
  59 + return;
  60 + }
  61 +
  62 + void train(const TemplateList& data)
  63 + {
  64 + (void) data;
  65 + }
  66 +
  67 + void finalize(TemplateList &data)
  68 + {
  69 + (void) data;
  70 + float p = br_progress();
  71 + 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);
  72 + timer.start();
  73 + Globals->startTime.start();
  74 + Globals->currentStep = 0;
  75 + Globals->currentProgress = 0;
  76 + Globals->totalSteps = totalProgress;
  77 + }
  78 +
  79 + void init()
  80 + {
  81 + timer.start();
  82 + Globals->startTime.start();
  83 + Globals->currentProgress = 0;
  84 + Globals->currentStep = 0;
  85 + Globals->totalSteps = totalProgress;
  86 + }
  87 +
  88 +public:
  89 + ProgressCounterTransform() : TimeVaryingTransform(false,false) {}
  90 + QElapsedTimer timer;
  91 +};
  92 +
  93 +BR_REGISTER(Transform, ProgressCounterTransform)
  94 +
  95 +} // namespace br
  96 +
  97 +#include "core/progresscounter.moc"
... ...
openbr/plugins/core/registrar.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup initializers
  24 + * \brief Register custom objects with Qt meta object system.
  25 + * \author Charles Otto \cite caotto
  26 + */
  27 +class Registrar : public Initializer
  28 +{
  29 + Q_OBJECT
  30 +
  31 + void initialize() const
  32 + {
  33 + qRegisterMetaType<br::Neighbors>();
  34 + }
  35 +};
  36 +
  37 +BR_REGISTER(Initializer, Registrar)
  38 +
  39 +} // namespace br
  40 +
  41 +#include "core/registrar.moc"
... ...
openbr/plugins/core/remove.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief Removes the matrix from the template at the specified index.
  25 + * \author Josh Klontz \cite jklontz
  26 + * \see IdentityTransform DiscardTransform FirstTransform RestTransform
  27 + */
  28 +//! [example_transform]
  29 +class RemoveTransform : public UntrainableMetaTransform
  30 +{
  31 + Q_OBJECT
  32 + Q_PROPERTY(int index READ get_index WRITE set_index RESET reset_index STORED false)
  33 + BR_PROPERTY(int, index, 0)
  34 +
  35 + void project(const Template &src, Template &dst) const
  36 + {
  37 + dst = src;
  38 + dst.removeAt(index);
  39 + }
  40 +};
  41 +
  42 +BR_REGISTER(Transform, RemoveTransform)
  43 +//! [example_transform]
  44 +
  45 +} // namespace br
  46 +
  47 +#include "core/remove.moc"
... ...
openbr/plugins/core/rest.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief Removes the first matrix from the template.
  25 + * \see IdentityTransform DiscardTransform FirstTransform RemoveTransform
  26 + * \author Josh Klontz \cite jklontz
  27 + */
  28 +class RestTransform : public UntrainableMetaTransform
  29 +{
  30 + Q_OBJECT
  31 +
  32 + void project(const Template &src, Template &dst) const
  33 + {
  34 + dst = src;
  35 + dst.removeFirst();
  36 + }
  37 +};
  38 +
  39 +BR_REGISTER(Transform, RestTransform)
  40 +
  41 +} // namespace br
  42 +
  43 +#include "core/rest.moc"
... ...
openbr/plugins/core/schrodinger.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief Generates two templates, one of which is passed through a transform and the other
  25 + * is not. No cats were harmed in the making of this transform.
  26 + * \author Scott Klum \cite sklum
  27 + */
  28 +class SchrodingerTransform : public MetaTransform
  29 +{
  30 + Q_OBJECT
  31 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  32 + BR_PROPERTY(br::Transform*, transform, NULL)
  33 +
  34 +public:
  35 + void train(const TemplateList &data)
  36 + {
  37 + transform->train(data);
  38 + }
  39 +
  40 + void project(const TemplateList &src, TemplateList &dst) const
  41 + {
  42 + foreach(const Template &t, src) {
  43 + dst.append(t);
  44 + Template u;
  45 + transform->project(t,u);
  46 + dst.append(u);
  47 + }
  48 + }
  49 +
  50 + void project(const Template &src, Template &dst) const {
  51 + TemplateList temp;
  52 + project(TemplateList() << src, temp);
  53 + if (!temp.isEmpty()) dst = temp.first();
  54 + }
  55 +
  56 +};
  57 +BR_REGISTER(Transform, SchrodingerTransform)
  58 +
  59 +} // namespace br
  60 +
  61 +#include "core/schrodinger.moc"
... ...
openbr/plugins/core/singleton.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup transforms
  24 + * \brief A globally shared transform.
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class SingletonTransform : public MetaTransform
  28 +{
  29 + Q_OBJECT
  30 + Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
  31 + BR_PROPERTY(QString, description, "Identity")
  32 +
  33 + static QMutex mutex;
  34 + static QHash<QString,Transform*> transforms;
  35 + static QHash<QString,int> trainingReferenceCounts;
  36 + static QHash<QString,TemplateList> trainingData;
  37 +
  38 + Transform *transform;
  39 +
  40 + void init()
  41 + {
  42 + QMutexLocker locker(&mutex);
  43 + if (!transforms.contains(description)) {
  44 + transforms.insert(description, make(description));
  45 + trainingReferenceCounts.insert(description, 0);
  46 + }
  47 +
  48 + transform = transforms[description];
  49 + trainingReferenceCounts[description]++;
  50 + }
  51 +
  52 + void train(const TemplateList &data)
  53 + {
  54 + QMutexLocker locker(&mutex);
  55 + trainingData[description].append(data);
  56 + trainingReferenceCounts[description]--;
  57 + if (trainingReferenceCounts[description] > 0) return;
  58 + transform->train(trainingData[description]);
  59 + trainingData[description].clear();
  60 + }
  61 +
  62 + void project(const Template &src, Template &dst) const
  63 + {
  64 + transform->project(src, dst);
  65 + }
  66 +
  67 + void store(QDataStream &stream) const
  68 + {
  69 + if (transform->parent() == this)
  70 + transform->store(stream);
  71 + }
  72 +
  73 + void load(QDataStream &stream)
  74 + {
  75 + if (transform->parent() == this)
  76 + transform->load(stream);
  77 + }
  78 +};
  79 +
  80 +QMutex SingletonTransform::mutex;
  81 +QHash<QString,Transform*> SingletonTransform::transforms;
  82 +QHash<QString,int> SingletonTransform::trainingReferenceCounts;
  83 +QHash<QString,TemplateList> SingletonTransform::trainingData;
  84 +
  85 +BR_REGISTER(Transform, SingletonTransform)
  86 +
  87 +} // namespace br
  88 +
  89 +#include "core/singleton.moc"
... ...
openbr/plugins/stream.cpp renamed to openbr/plugins/core/stream.cpp
  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 +
1 17 #include <fstream>
2 18 #include <QReadWriteLock>
3 19 #include <QWaitCondition>
... ... @@ -8,10 +24,11 @@
8 24 #include <QtConcurrent>
9 25 #include <opencv/highgui.h>
10 26 #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"
  27 +
  28 +#include <openbr/plugins/openbr_internal.h>
  29 +#include <openbr/core/common.h>
  30 +#include <openbr/core/opencvutils.h>
  31 +#include <openbr/core/qtutils.h>
15 32  
16 33 using namespace cv;
17 34 using namespace std;
... ... @@ -1360,5 +1377,5 @@ BR_REGISTER(Transform, StreamTransform)
1360 1377  
1361 1378 } // namespace br
1362 1379  
1363   -#include "stream.moc"
  1380 +#include "core/stream.moc"
1364 1381  
... ...
openbr/plugins/crop.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 <opencv2/imgproc/imgproc.hpp>
18   -#include "openbr_internal.h"
19   -
20   -#include "openbr/core/opencvutils.h"
21   -
22   -using namespace cv;
23   -
24   -namespace br
25   -{
26   -
27   -/*!
28   - * \ingroup transforms
29   - * \brief Crops about the specified region of interest.
30   - * \author Josh Klontz \cite jklontz
31   - */
32   -class CropTransform : public UntrainableTransform
33   -{
34   - Q_OBJECT
35   - Q_PROPERTY(int x READ get_x WRITE set_x RESET reset_x STORED false)
36   - Q_PROPERTY(int y READ get_y WRITE set_y RESET reset_y STORED false)
37   - Q_PROPERTY(int width READ get_width WRITE set_width RESET reset_width STORED false)
38   - Q_PROPERTY(int height READ get_height WRITE set_height RESET reset_height STORED false)
39   - BR_PROPERTY(int, x, 0)
40   - BR_PROPERTY(int, y, 0)
41   - BR_PROPERTY(int, width, -1)
42   - BR_PROPERTY(int, height, -1)
43   -
44   - void project(const Template &src, Template &dst) const
45   - {
46   - dst = Mat(src, Rect(x, y, width < 1 ? src.m().cols-x-abs(width) : width, height < 1 ? src.m().rows-y-abs(height) : height));
47   - }
48   -};
49   -
50   -BR_REGISTER(Transform, CropTransform)
51   -
52   -/*!
53   - * \ingroup transforms
54   - * \brief Crops the rectangular regions of interest.
55   - * \author Josh Klontz \cite jklontz
56   - */
57   -class ROITransform : public UntrainableTransform
58   -{
59   - Q_OBJECT
60   - Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
61   - BR_PROPERTY(QString, propName, "")
62   -
63   - void project(const Template &src, Template &dst) const
64   - {
65   - if (!propName.isEmpty()) {
66   - QRectF rect = src.file.get<QRectF>(propName);
67   - dst += src.m()(OpenCVUtils::toRect(rect));
68   - } else if (!src.file.rects().empty()) {
69   - foreach (const QRectF &rect, src.file.rects())
70   - dst += src.m()(OpenCVUtils::toRect(rect));
71   - } else if (src.file.contains(QStringList() << "X" << "Y" << "Width" << "Height")) {
72   - dst += src.m()(Rect(src.file.get<int>("X"),
73   - src.file.get<int>("Y"),
74   - src.file.get<int>("Width"),
75   - src.file.get<int>("Height")));
76   - } else {
77   - dst = src;
78   - if (Globals->verbose)
79   - qWarning("No rects present in file.");
80   - }
81   - }
82   -};
83   -
84   -BR_REGISTER(Transform, ROITransform)
85   -
86   -/*!
87   - * \ingroup transforms
88   - * \brief Crops the rectangular regions of interest from given points and sizes.
89   - * \author Austin Blanton \cite imaus10
90   - */
91   -class ROIFromPtsTransform : public UntrainableTransform
92   -{
93   - Q_OBJECT
94   - Q_PROPERTY(int width READ get_width WRITE set_width RESET reset_width STORED false)
95   - Q_PROPERTY(int height READ get_height WRITE set_height RESET reset_height STORED false)
96   - BR_PROPERTY(int, width, 1)
97   - BR_PROPERTY(int, height, 1)
98   -
99   - void project(const Template &src, Template &dst) const
100   - {
101   - foreach (const QPointF &pt, src.file.points()) {
102   - int x = pt.x() - (width/2);
103   - int y = pt.y() - (height/2);
104   - dst += src.m()(Rect(x, y, width, height));
105   - }
106   - }
107   -};
108   -
109   -BR_REGISTER(Transform, ROIFromPtsTransform)
110   -
111   -/*!
112   - * \ingroup transforms
113   - * \brief Resize the template
114   - * \author Josh Klontz \cite jklontz
115   - * \note Method: Area should be used for shrinking an image, Cubic for slow but accurate enlargment, Bilin for fast enlargement.
116   - * \param preserveAspect If true, the image will be sized per specification, but
117   - * a border will be applied to preserve aspect ratio.
118   - */
119   -class ResizeTransform : public UntrainableTransform
120   -{
121   - Q_OBJECT
122   - Q_ENUMS(Method)
123   -
124   -public:
125   - /*!< */
126   - enum Method { Near = INTER_NEAREST,
127   - Area = INTER_AREA,
128   - Bilin = INTER_LINEAR,
129   - Cubic = INTER_CUBIC,
130   - Lanczo = INTER_LANCZOS4};
131   -
132   -private:
133   - Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
134   - Q_PROPERTY(int columns READ get_columns WRITE set_columns RESET reset_columns STORED false)
135   - Q_PROPERTY(Method method READ get_method WRITE set_method RESET reset_method STORED false)
136   - Q_PROPERTY(bool preserveAspect READ get_preserveAspect WRITE set_preserveAspect RESET reset_preserveAspect STORED false)
137   - BR_PROPERTY(int, rows, -1)
138   - BR_PROPERTY(int, columns, -1)
139   - BR_PROPERTY(Method, method, Bilin)
140   - BR_PROPERTY(bool, preserveAspect, false)
141   -
142   - void project(const Template &src, Template &dst) const
143   - {
144   - if (!preserveAspect)
145   - resize(src, dst, Size((columns == -1) ? src.m().cols*rows/src.m().rows : columns, rows), 0, 0, method);
146   - else {
147   - float inRatio = (float) src.m().rows / src.m().cols;
148   - float outRatio = (float) rows / columns;
149   - dst = Mat::zeros(rows, columns, src.m().type());
150   - if (outRatio > inRatio) {
151   - float heightAR = src.m().rows * inRatio / outRatio;
152   - Mat buffer;
153   - resize(src, buffer, Size(columns, heightAR), 0, 0, method);
154   - buffer.copyTo(dst.m()(Rect(0, (rows - heightAR) / 2, columns, heightAR)));
155   - } else {
156   - float widthAR = src.m().cols / inRatio * outRatio;
157   - Mat buffer;
158   - resize(src, buffer, Size(widthAR, rows), 0, 0, method);
159   - buffer.copyTo(dst.m()(Rect((columns - widthAR) / 2, 0, widthAR, rows)));
160   - }
161   - }
162   - }
163   -};
164   -
165   -BR_REGISTER(Transform, ResizeTransform)
166   -
167   -/*!
168   - * \ingroup transforms
169   - * \brief Limit the size of the template
170   - * \author Josh Klontz \cite jklontz
171   - */
172   -class LimitSizeTransform : public UntrainableTransform
173   -{
174   - Q_OBJECT
175   - Q_PROPERTY(int max READ get_max WRITE set_max RESET reset_max STORED false)
176   - BR_PROPERTY(int, max, -1)
177   -
178   - void project(const Template &src, Template &dst) const
179   - {
180   - const Mat &m = src;
181   - if (m.rows > m.cols)
182   - if (m.rows > max) resize(m, dst, Size(std::max(1, m.cols * max / m.rows), max));
183   - else dst = m;
184   - else
185   - if (m.cols > max) resize(m, dst, Size(max, std::max(1, m.rows * max / m.cols)));
186   - else dst = m;
187   - }
188   -};
189   -
190   -BR_REGISTER(Transform, LimitSizeTransform)
191   -
192   -/*!
193   - * \ingroup transforms
194   - * \brief Enforce a multiple of \em n columns.
195   - * \author Josh Klontz \cite jklontz
196   - */
197   -class DivTransform : public UntrainableTransform
198   -{
199   - Q_OBJECT
200   - Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
201   - BR_PROPERTY(int, n, 1)
202   -
203   - void project(const Template &src, Template &dst) const
204   - {
205   - dst = Mat(src, Rect(0,0,n*(src.m().cols/n),src.m().rows));
206   - }
207   -};
208   -
209   -BR_REGISTER(Transform, DivTransform)
210   -
211   -/*!
212   - * \ingroup transforms
213   - * \brief Crop out black borders
214   - * \author Josh Klontz \cite jklontz
215   - */
216   -class CropBlackTransform : public UntrainableTransform
217   -{
218   - Q_OBJECT
219   -
220   - void project(const Template &src, Template &dst) const
221   - {
222   - Mat gray;
223   - OpenCVUtils::cvtGray(src, gray);
224   -
225   - int xStart = 0;
226   - while (xStart < gray.cols) {
227   - if (mean(gray.col(xStart))[0] >= 1) break;
228   - xStart++;
229   - }
230   -
231   - int xEnd = gray.cols - 1;
232   - while (xEnd >= 0) {
233   - if (mean(gray.col(xEnd))[0] >= 1) break;
234   - xEnd--;
235   - }
236   -
237   - int yStart = 0;
238   - while (yStart < gray.rows) {
239   - if (mean(gray.col(yStart))[0] >= 1) break;
240   - yStart++;
241   - }
242   -
243   - int yEnd = gray.rows - 1;
244   - while (yEnd >= 0) {
245   - if (mean(gray.col(yEnd))[0] >= 1) break;
246   - yEnd--;
247   - }
248   -
249   - dst = src.m()(Rect(xStart, yStart, xEnd-xStart, yEnd-yStart));
250   - }
251   -};
252   -
253   -BR_REGISTER(Transform, CropBlackTransform)
254   -
255   -/*!
256   - * \ingroup transforms
257   - * \brief Divide the matrix into 4 smaller matricies of equal size.
258   - * \author Josh Klontz \cite jklontz
259   - */
260   -class SubdivideTransform : public UntrainableTransform
261   -{
262   - Q_OBJECT
263   -
264   - void project(const Template &src, Template &dst) const
265   - {
266   - const Mat &m = src;
267   - const int subrows = m.rows/2;
268   - const int subcolumns = m.cols/2;
269   - dst.append(Mat(m,Rect(0, 0, subcolumns, subrows)).clone());
270   - dst.append(Mat(m,Rect(subcolumns, 0, subcolumns, subrows)).clone());
271   - dst.append(Mat(m,Rect(0, subrows, subcolumns, subrows)).clone());
272   - dst.append(Mat(m,Rect(subcolumns, subrows, subcolumns, subrows)).clone());
273   - }
274   -};
275   -
276   -BR_REGISTER(Transform, SubdivideTransform)
277   -
278   -/*!
279   - * \ingroup transforms
280   - * \brief Trim the image so the width and the height are the same size.
281   - * \author Josh Klontz \cite jklontz
282   - */
283   -class CropSquareTransform : public UntrainableTransform
284   -{
285   - Q_OBJECT
286   -
287   - void project(const Template &src, Template &dst) const
288   - {
289   - const Mat &m = src;
290   - const int newSize = min(m.rows, m.cols);
291   - dst = Mat(m, Rect((m.cols-newSize)/2, (m.rows-newSize)/2, newSize, newSize));
292   - }
293   -};
294   -
295   -BR_REGISTER(Transform, CropSquareTransform)
296   -
297   -} // namespace br
298   -
299   -#include "crop.moc"
openbr/plugins/cvt.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 <opencv2/imgproc/imgproc_c.h>
18   -#include <opencv2/imgproc/imgproc.hpp>
19   -#include "openbr_internal.h"
20   -#include "openbr/core/opencvutils.h"
21   -
22   -using namespace cv;
23   -
24   -namespace br
25   -{
26   -
27   -/*!
28   - * \ingroup transforms
29   - * \brief Colorspace conversion.
30   - * \author Josh Klontz \cite jklontz
31   - */
32   -class CvtTransform : public UntrainableTransform
33   -{
34   - Q_OBJECT
35   - Q_ENUMS(ColorSpace)
36   - Q_PROPERTY(ColorSpace colorSpace READ get_colorSpace WRITE set_colorSpace RESET reset_colorSpace STORED false)
37   - Q_PROPERTY(int channel READ get_channel WRITE set_channel RESET reset_channel STORED false)
38   -
39   -public:
40   - enum ColorSpace { Gray = CV_BGR2GRAY,
41   - RGBGray = CV_RGB2GRAY,
42   - HLS = CV_BGR2HLS,
43   - HSV = CV_BGR2HSV,
44   - Lab = CV_BGR2Lab,
45   - Luv = CV_BGR2Luv,
46   - RGB = CV_BGR2RGB,
47   - XYZ = CV_BGR2XYZ,
48   - YCrCb = CV_BGR2YCrCb,
49   - Color = CV_GRAY2BGR };
50   -
51   -private:
52   - BR_PROPERTY(ColorSpace, colorSpace, Gray)
53   - BR_PROPERTY(int, channel, -1)
54   -
55   - void project(const Template &src, Template &dst) const
56   - {
57   - if (src.m().channels() > 1 || colorSpace == CV_GRAY2BGR) cvtColor(src, dst, colorSpace);
58   - else dst = src;
59   -
60   - if (channel != -1) {
61   - std::vector<Mat> mv;
62   - split(dst, mv);
63   - dst = mv[channel % (int)mv.size()];
64   - }
65   - }
66   -};
67   -
68   -BR_REGISTER(Transform, CvtTransform)
69   -
70   -/*!
71   - * \ingroup transforms
72   - * \brief Convert to floating point format.
73   - * \author Josh Klontz \cite jklontz
74   - */
75   -class CvtFloatTransform : public UntrainableTransform
76   -{
77   - Q_OBJECT
78   -
79   - void project(const Template &src, Template &dst) const
80   - {
81   - src.m().convertTo(dst, CV_32F);
82   - }
83   -};
84   -
85   -BR_REGISTER(Transform, CvtFloatTransform)
86   -
87   -/*!
88   - * \ingroup transforms
89   - * \brief Convert to uchar format
90   - * \author Josh Klontz \cite jklontz
91   - */
92   -class CvtUCharTransform : public UntrainableTransform
93   -{
94   - Q_OBJECT
95   -
96   - void project(const Template &src, Template &dst) const
97   - {
98   - OpenCVUtils::cvtUChar(src, dst);
99   - }
100   -};
101   -
102   -BR_REGISTER(Transform, CvtUCharTransform)
103   -
104   -/*!
105   - * \ingroup transforms
106   - * \brief Scales using the given factor
107   - * \author Scott Klum \cite sklum
108   - */
109   -class ScaleTransform : public UntrainableTransform
110   -{
111   - Q_OBJECT
112   -
113   - Q_PROPERTY(float scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
114   - BR_PROPERTY(float, scaleFactor, 1.)
115   -
116   - void project(const Template &src, Template &dst) const
117   - {
118   - resize(src, dst, Size(src.m().cols*scaleFactor,src.m().rows*scaleFactor));
119   - }
120   -};
121   -
122   -BR_REGISTER(Transform, ScaleTransform)
123   -
124   -/*!
125   - * \ingroup transforms
126   - * \brief Split a multi-channel matrix into several single-channel matrices.
127   - * \author Josh Klontz \cite jklontz
128   - */
129   -class SplitChannelsTransform : public UntrainableTransform
130   -{
131   - Q_OBJECT
132   -
133   - void project(const Template &src, Template &dst) const
134   - {
135   - std::vector<Mat> mv;
136   - split(src, mv);
137   - foreach (const Mat &m, mv)
138   - dst += m;
139   - }
140   -};
141   -
142   -BR_REGISTER(Transform, SplitChannelsTransform)
143   -
144   -/*!
145   - * \ingroup transforms
146   - * \brief Enforce the matrix has a certain number of channels by adding or removing channels.
147   - * \author Josh Klontz \cite jklontz
148   - */
149   -class EnsureChannelsTransform : public UntrainableTransform
150   -{
151   - Q_OBJECT
152   - Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
153   - BR_PROPERTY(int, n, 1)
154   -
155   - void project(const Template &src, Template &dst) const
156   - {
157   - if (src.m().channels() == n) {
158   - dst = src;
159   - } else {
160   - std::vector<Mat> mv;
161   - split(src, mv);
162   -
163   - // Add extra channels
164   - while ((int)mv.size() < n) {
165   - for (int i=0; i<src.m().channels(); i++) {
166   - mv.push_back(mv[i]);
167   - if ((int)mv.size() == n)
168   - break;
169   - }
170   - }
171   -
172   - // Remove extra channels
173   - while ((int)mv.size() > n)
174   - mv.pop_back();
175   -
176   - merge(mv, dst);
177   - }
178   - }
179   -};
180   -
181   -BR_REGISTER(Transform, EnsureChannelsTransform)
182   -
183   -/*!
184   - * \ingroup transforms
185   - * \brief Drop the alpha channel (if exists).
186   - * \author Austin Blanton \cite imaus10
187   - */
188   -class DiscardAlphaTransform : public UntrainableTransform
189   -{
190   - Q_OBJECT
191   -
192   - void project(const Template &src, Template &dst) const
193   - {
194   - if (src.m().channels() > 4 || src.m().channels() == 2) {
195   - dst.file.fte = true;
196   - return;
197   - }
198   -
199   - dst = src;
200   - if (src.m().channels() == 4) {
201   - std::vector<Mat> mv;
202   - split(src, mv);
203   - mv.pop_back();
204   - merge(mv, dst);
205   - }
206   - }
207   -};
208   -
209   -BR_REGISTER(Transform, DiscardAlphaTransform)
210   -
211   -/*!
212   - * \ingroup transforms
213   - * \brief Normalized RG color space.
214   - * \author Josh Klontz \cite jklontz
215   - */
216   -class RGTransform : public UntrainableTransform
217   -{
218   - Q_OBJECT
219   -
220   - void project(const Template &src, Template &dst) const
221   - {
222   - if (src.m().type() != CV_8UC3)
223   - qFatal("Expected CV_8UC3 images.");
224   -
225   - const Mat &m = src.m();
226   - Mat R(m.size(), CV_8UC1); // R / (R+G+B)
227   - Mat G(m.size(), CV_8UC1); // G / (R+G+B)
228   -
229   - for (int i=0; i<m.rows; i++)
230   - for (int j=0; j<m.cols; j++) {
231   - Vec3b v = m.at<Vec3b>(i,j);
232   - const int b = v[0];
233   - const int g = v[1];
234   - const int r = v[2];
235   - const int sum = b + g + r;
236   - if (sum > 0) {
237   - R.at<uchar>(i, j) = saturate_cast<uchar>(255.0*r/(r+g+b));
238   - G.at<uchar>(i, j) = saturate_cast<uchar>(255.0*g/(r+g+b));
239   - } else {
240   - R.at<uchar>(i, j) = 0;
241   - G.at<uchar>(i, j) = 0;
242   - }
243   - }
244   -
245   - dst.append(R);
246   - dst.append(G);
247   - }
248   -};
249   -
250   -BR_REGISTER(Transform, RGTransform)
251   -
252   -/*!
253   - * \ingroup transforms
254   - * \brief dst = a*src+b
255   - * \author Josh Klontz \cite jklontz
256   - */
257   -class MAddTransform : public UntrainableTransform
258   -{
259   - Q_OBJECT
260   - Q_PROPERTY(double a READ get_a WRITE set_a RESET reset_a STORED false)
261   - Q_PROPERTY(double b READ get_b WRITE set_b RESET reset_b STORED false)
262   - BR_PROPERTY(double, a, 1)
263   - BR_PROPERTY(double, b, 0)
264   -
265   - void project(const Template &src, Template &dst) const
266   - {
267   - src.m().convertTo(dst.m(), src.m().depth(), a, b);
268   - }
269   -};
270   -
271   -BR_REGISTER(Transform, MAddTransform)
272   -
273   -/*!
274   - * \ingroup transforms
275   - * \brief Computes the absolute value of each element.
276   - * \author Josh Klontz \cite jklontz
277   - */
278   -class AbsTransform : public UntrainableTransform
279   -{
280   - Q_OBJECT
281   -
282   - void project(const Template &src, Template &dst) const
283   - {
284   - dst = abs(src);
285   - }
286   -};
287   -
288   -BR_REGISTER(Transform, AbsTransform)
289   -
290   -} // namespace br
291   -
292   -#include "cvt.moc"
openbr/plugins/distance.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 <QFutureSynchronizer>
18   -#include <QtConcurrentRun>
19   -#include <numeric>
20   -#include <opencv2/imgproc/imgproc.hpp>
21   -#include <opencv2/imgproc/imgproc_c.h>
22   -#include "openbr_internal.h"
23   -
24   -#include "openbr/core/distance_sse.h"
25   -#include "openbr/core/qtutils.h"
26   -#include "openbr/core/opencvutils.h"
27   -
28   -using namespace cv;
29   -
30   -namespace br
31   -{
32   -
33   -/*!
34   - * \ingroup distances
35   - * \brief Standard distance metrics
36   - * \author Josh Klontz \cite jklontz
37   - */
38   -class DistDistance : public UntrainableDistance
39   -{
40   - Q_OBJECT
41   - Q_ENUMS(Metric)
42   - Q_PROPERTY(Metric metric READ get_metric WRITE set_metric RESET reset_metric STORED false)
43   - Q_PROPERTY(bool negLogPlusOne READ get_negLogPlusOne WRITE set_negLogPlusOne RESET reset_negLogPlusOne STORED false)
44   -
45   -public:
46   - /*!< */
47   - enum Metric { Correlation,
48   - ChiSquared,
49   - Intersection,
50   - Bhattacharyya,
51   - INF,
52   - L1,
53   - L2,
54   - Cosine,
55   - Dot};
56   -
57   -private:
58   - BR_PROPERTY(Metric, metric, L2)
59   - BR_PROPERTY(bool, negLogPlusOne, true)
60   -
61   - float compare(const Mat &a, const Mat &b) const
62   - {
63   - if ((a.size != b.size) ||
64   - (a.type() != b.type()))
65   - return -std::numeric_limits<float>::max();
66   -
67   -// TODO: this max value is never returned based on the switch / default
68   - float result = std::numeric_limits<float>::max();
69   - switch (metric) {
70   - case Correlation:
71   - return compareHist(a, b, CV_COMP_CORREL);
72   - case ChiSquared:
73   - result = compareHist(a, b, CV_COMP_CHISQR);
74   - break;
75   - case Intersection:
76   - result = compareHist(a, b, CV_COMP_INTERSECT);
77   - break;
78   - case Bhattacharyya:
79   - result = compareHist(a, b, CV_COMP_BHATTACHARYYA);
80   - break;
81   - case INF:
82   - result = norm(a, b, NORM_INF);
83   - break;
84   - case L1:
85   - result = norm(a, b, NORM_L1);
86   - break;
87   - case L2:
88   - result = norm(a, b, NORM_L2);
89   - break;
90   - case Cosine:
91   - return cosine(a, b);
92   - case Dot:
93   - return a.dot(b);
94   - default:
95   - qFatal("Invalid metric");
96   - }
97   -
98   - if (result != result)
99   - qFatal("NaN result.");
100   -
101   - return negLogPlusOne ? -log(result+1) : result;
102   - }
103   -
104   - static float cosine(const Mat &a, const Mat &b)
105   - {
106   - float dot = 0;
107   - float magA = 0;
108   - float magB = 0;
109   -
110   - for (int row=0; row<a.rows; row++) {
111   - for (int col=0; col<a.cols; col++) {
112   - const float target = a.at<float>(row,col);
113   - const float query = b.at<float>(row,col);
114   - dot += target * query;
115   - magA += target * target;
116   - magB += query * query;
117   - }
118   - }
119   -
120   - return dot / (sqrt(magA)*sqrt(magB));
121   - }
122   -};
123   -
124   -BR_REGISTER(Distance, DistDistance)
125   -
126   -/*!
127   - * \ingroup distances
128   - * \brief DistDistance wrapper.
129   - * \author Josh Klontz \cite jklontz
130   - */
131   -class DefaultDistance : public UntrainableDistance
132   -{
133   - Q_OBJECT
134   - Distance *distance;
135   -
136   - void init()
137   - {
138   - distance = Distance::make("Dist("+file.suffix()+")");
139   - }
140   -
141   - float compare(const cv::Mat &a, const cv::Mat &b) const
142   - {
143   - return distance->compare(a, b);
144   - }
145   -};
146   -
147   -BR_REGISTER(Distance, DefaultDistance)
148   -
149   -/*!
150   - * \ingroup distances
151   - * \brief Distances in series.
152   - * \author Josh Klontz \cite jklontz
153   - *
154   - * The templates are compared using each br::Distance in order.
155   - * If the result of the comparison with any given distance is -FLOAT_MAX then this result is returned early.
156   - * Otherwise the returned result is the value of comparing the templates using the last br::Distance.
157   - */
158   -class PipeDistance : public Distance
159   -{
160   - Q_OBJECT
161   - Q_PROPERTY(QList<br::Distance*> distances READ get_distances WRITE set_distances RESET reset_distances)
162   - BR_PROPERTY(QList<br::Distance*>, distances, QList<br::Distance*>())
163   -
164   - void train(const TemplateList &data)
165   - {
166   - QFutureSynchronizer<void> futures;
167   - foreach (br::Distance *distance, distances)
168   - futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
169   - futures.waitForFinished();
170   - }
171   -
172   - float compare(const Template &a, const Template &b) const
173   - {
174   - float result = -std::numeric_limits<float>::max();
175   - foreach (br::Distance *distance, distances) {
176   - result = distance->compare(a, b);
177   - if (result == -std::numeric_limits<float>::max())
178   - return result;
179   - }
180   - return result;
181   - }
182   -};
183   -
184   -BR_REGISTER(Distance, PipeDistance)
185   -
186   -/*!
187   - * \ingroup distances
188   - * \brief Fuses similarity scores across multiple matrices of compared templates
189   - * \author Scott Klum \cite sklum
190   - * \note Operation: Mean, sum, min, max are supported.
191   - */
192   -class FuseDistance : public Distance
193   -{
194   - Q_OBJECT
195   - Q_ENUMS(Operation)
196   - Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
197   - Q_PROPERTY(Operation operation READ get_operation WRITE set_operation RESET reset_operation STORED false)
198   - Q_PROPERTY(QList<float> weights READ get_weights WRITE set_weights RESET reset_weights STORED false)
199   -
200   - QList<br::Distance*> distances;
201   -
202   -public:
203   - /*!< */
204   - enum Operation {Mean, Sum, Max, Min};
205   -
206   -private:
207   - BR_PROPERTY(QString, description, "L2")
208   - BR_PROPERTY(Operation, operation, Mean)
209   - BR_PROPERTY(QList<float>, weights, QList<float>())
210   -
211   - void train(const TemplateList &src)
212   - {
213   - // Partition the templates by matrix
214   - QList<int> split;
215   - for (int i=0; i<src.at(0).size(); i++) split.append(1);
216   -
217   - QList<TemplateList> partitionedSrc = src.partition(split);
218   -
219   - while (distances.size() < partitionedSrc.size())
220   - distances.append(make(description));
221   -
222   - // Train on each of the partitions
223   - for (int i=0; i<distances.size(); i++)
224   - distances[i]->train(partitionedSrc[i]);
225   - }
226   -
227   - float compare(const Template &a, const Template &b) const
228   - {
229   - if (a.size() != b.size()) qFatal("Comparison size mismatch");
230   -
231   - QList<float> scores;
232   - for (int i=0; i<distances.size(); i++) {
233   - float weight;
234   - weights.isEmpty() ? weight = 1. : weight = weights[i];
235   - scores.append(weight*distances[i]->compare(Template(a.file, a[i]),Template(b.file, b[i])));
236   - }
237   -
238   - switch (operation) {
239   - case Mean:
240   - return std::accumulate(scores.begin(),scores.end(),0.0)/(float)scores.size();
241   - break;
242   - case Sum:
243   - return std::accumulate(scores.begin(),scores.end(),0.0);
244   - break;
245   - case Min:
246   - return *std::min_element(scores.begin(),scores.end());
247   - break;
248   - case Max:
249   - return *std::max_element(scores.begin(),scores.end());
250   - break;
251   - default:
252   - qFatal("Invalid operation.");
253   - }
254   - return 0;
255   - }
256   -
257   - void store(QDataStream &stream) const
258   - {
259   - stream << distances.size();
260   - foreach (Distance *distance, distances)
261   - distance->store(stream);
262   - }
263   -
264   - void load(QDataStream &stream)
265   - {
266   - int numDistances;
267   - stream >> numDistances;
268   - while (distances.size() < numDistances)
269   - distances.append(make(description));
270   - foreach (Distance *distance, distances)
271   - distance->load(stream);
272   - }
273   -};
274   -
275   -BR_REGISTER(Distance, FuseDistance)
276   -
277   -/*!
278   - * \ingroup distances
279   - * \brief Fast 8-bit L1 distance
280   - * \author Josh Klontz \cite jklontz
281   - */
282   -class ByteL1Distance : public UntrainableDistance
283   -{
284   - Q_OBJECT
285   -
286   - float compare(const unsigned char *a, const unsigned char *b, size_t size) const
287   - {
288   - return l1(a, b, size);
289   - }
290   -};
291   -
292   -BR_REGISTER(Distance, ByteL1Distance)
293   -
294   -/*!
295   - * \ingroup distances
296   - * \brief Fast 4-bit L1 distance
297   - * \author Josh Klontz \cite jklontz
298   - */
299   -class HalfByteL1Distance : public UntrainableDistance
300   -{
301   - Q_OBJECT
302   -
303   - float compare(const Mat &a, const Mat &b) const
304   - {
305   - return packed_l1(a.data, b.data, a.total());
306   - }
307   -};
308   -
309   -BR_REGISTER(Distance, HalfByteL1Distance)
310   -
311   -/*!
312   - * \ingroup distances
313   - * \brief Returns -log(distance(a,b)+1)
314   - * \author Josh Klontz \cite jklontz
315   - */
316   -class NegativeLogPlusOneDistance : public UntrainableDistance
317   -{
318   - Q_OBJECT
319   - Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
320   - BR_PROPERTY(br::Distance*, distance, NULL)
321   -
322   - void train(const TemplateList &src)
323   - {
324   - distance->train(src);
325   - }
326   -
327   - float compare(const Template &a, const Template &b) const
328   - {
329   - return -log(distance->compare(a,b)+1);
330   - }
331   -
332   - void store(QDataStream &stream) const
333   - {
334   - distance->store(stream);
335   - }
336   -
337   - void load(QDataStream &stream)
338   - {
339   - distance->load(stream);
340   - }
341   -};
342   -
343   -BR_REGISTER(Distance, NegativeLogPlusOneDistance)
344   -
345   -/*!
346   - * \ingroup distances
347   - * \brief Returns \c true if the templates are identical, \c false otherwise.
348   - * \author Josh Klontz \cite jklontz
349   - */
350   -class IdenticalDistance : public UntrainableDistance
351   -{
352   - Q_OBJECT
353   -
354   - float compare(const Mat &a, const Mat &b) const
355   - {
356   - const size_t size = a.total() * a.elemSize();
357   - if (size != b.total() * b.elemSize()) return 0;
358   - for (size_t i=0; i<size; i++)
359   - if (a.data[i] != b.data[i]) return 0;
360   - return 1;
361   - }
362   -};
363   -
364   -BR_REGISTER(Distance, IdenticalDistance)
365   -
366   -/*!
367   - * \ingroup distances
368   - * \brief Online distance metric to attenuate match scores across multiple frames
369   - * \author Brendan klare \cite bklare
370   - */
371   -class OnlineDistance : public UntrainableDistance
372   -{
373   - Q_OBJECT
374   - Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
375   - Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false)
376   - BR_PROPERTY(br::Distance*, distance, NULL)
377   - BR_PROPERTY(float, alpha, 0.1f)
378   -
379   - mutable QHash<QString,float> scoreHash;
380   - mutable QMutex mutex;
381   -
382   - float compare(const Template &target, const Template &query) const
383   - {
384   - float currentScore = distance->compare(target, query);
385   -
386   - QMutexLocker mutexLocker(&mutex);
387   - return scoreHash[target.file.name] = (1.0- alpha) * scoreHash[target.file.name] + alpha * currentScore;
388   - }
389   -};
390   -
391   -BR_REGISTER(Distance, OnlineDistance)
392   -
393   -/*!
394   - * \ingroup distances
395   - * \brief Attenuation function based distance from attributes
396   - * \author Scott Klum \cite sklum
397   - */
398   -class AttributeDistance : public UntrainableDistance
399   -{
400   - Q_OBJECT
401   - Q_PROPERTY(QString attribute READ get_attribute WRITE set_attribute RESET reset_attribute STORED false)
402   - BR_PROPERTY(QString, attribute, QString())
403   -
404   - float compare(const Template &target, const Template &query) const
405   - {
406   - float queryValue = query.file.get<float>(attribute);
407   - float targetValue = target.file.get<float>(attribute);
408   -
409   - // TODO: Set this magic number to something meaningful
410   - float stddev = 1;
411   -
412   - if (queryValue == targetValue) return 1;
413   - else return 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((targetValue-queryValue)/stddev, 2));
414   - }
415   -};
416   -
417   -BR_REGISTER(Distance, AttributeDistance)
418   -
419   -/*!
420   - * \ingroup distances
421   - * \brief Sum match scores across multiple distances
422   - * \author Scott Klum \cite sklum
423   - */
424   -class SumDistance : public UntrainableDistance
425   -{
426   - Q_OBJECT
427   - Q_PROPERTY(QList<br::Distance*> distances READ get_distances WRITE set_distances RESET reset_distances)
428   - BR_PROPERTY(QList<br::Distance*>, distances, QList<br::Distance*>())
429   -
430   - void train(const TemplateList &data)
431   - {
432   - QFutureSynchronizer<void> futures;
433   - foreach (br::Distance *distance, distances)
434   - futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
435   - futures.waitForFinished();
436   - }
437   -
438   - float compare(const Template &target, const Template &query) const
439   - {
440   - float result = 0;
441   -
442   - foreach (br::Distance *distance, distances) {
443   - result += distance->compare(target, query);
444   -
445   - if (result == -std::numeric_limits<float>::max())
446   - return result;
447   - }
448   -
449   - return result;
450   - }
451   -};
452   -
453   -BR_REGISTER(Distance, SumDistance)
454   -
455   -/*!
456   - * \ingroup transforms
457   - * \brief Compare each template to a fixed gallery (with name = galleryName), using the specified distance.
458   - * dst will contain a 1 by n vector of scores.
459   - * \author Charles Otto \cite caotto
460   - */
461   -class GalleryCompareTransform : public Transform
462   -{
463   - Q_OBJECT
464   - Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED true)
465   - Q_PROPERTY(QString galleryName READ get_galleryName WRITE set_galleryName RESET reset_galleryName STORED false)
466   - BR_PROPERTY(br::Distance*, distance, NULL)
467   - BR_PROPERTY(QString, galleryName, "")
468   -
469   - TemplateList gallery;
470   -
471   - void project(const Template &src, Template &dst) const
472   - {
473   - dst = src;
474   - if (gallery.isEmpty())
475   - return;
476   -
477   - QList<float> line = distance->compare(gallery, src);
478   - dst.m() = OpenCVUtils::toMat(line, 1);
479   - }
480   -
481   - void init()
482   - {
483   - if (!galleryName.isEmpty())
484   - gallery = TemplateList::fromGallery(galleryName);
485   - }
486   -
487   - void train(const TemplateList &data)
488   - {
489   - gallery = data;
490   - }
491   -
492   - void store(QDataStream &stream) const
493   - {
494   - br::Object::store(stream);
495   - stream << gallery;
496   - }
497   -
498   - void load(QDataStream &stream)
499   - {
500   - br::Object::load(stream);
501   - stream >> gallery;
502   - }
503   -
504   -public:
505   - GalleryCompareTransform() : Transform(false, true) {}
506   -};
507   -
508   -BR_REGISTER(Transform, GalleryCompareTransform)
509   -
510   -
511   -} // namespace br
512   -#include "distance.moc"
openbr/plugins/distance/L2.cpp 0 → 100644
  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 <Eigen/Dense>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +/*!
  25 + * \ingroup distances
  26 + * \brief L2 distance computed using eigen.
  27 + * \author Josh Klontz \cite jklontz
  28 + */
  29 +class L2Distance : public UntrainableDistance
  30 +{
  31 + Q_OBJECT
  32 +
  33 + float compare(const cv::Mat &a, const cv::Mat &b) const
  34 + {
  35 + const int size = a.rows * a.cols;
  36 + Eigen::Map<Eigen::VectorXf> aMap((float*)a.data, size);
  37 + Eigen::Map<Eigen::VectorXf> bMap((float*)b.data, size);
  38 + return (aMap-bMap).squaredNorm();
  39 + }
  40 +};
  41 +
  42 +BR_REGISTER(Distance, L2Distance)
  43 +
  44 +} // namespace br
  45 +
  46 +#include "distance/L2.moc"
... ...
openbr/plugins/distance/attribute.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief Attenuation function based distance from attributes
  25 + * \author Scott Klum \cite sklum
  26 + */
  27 +class AttributeDistance : public UntrainableDistance
  28 +{
  29 + Q_OBJECT
  30 + Q_PROPERTY(QString attribute READ get_attribute WRITE set_attribute RESET reset_attribute STORED false)
  31 + BR_PROPERTY(QString, attribute, QString())
  32 +
  33 + float compare(const Template &target, const Template &query) const
  34 + {
  35 + float queryValue = query.file.get<float>(attribute);
  36 + float targetValue = target.file.get<float>(attribute);
  37 +
  38 + // TODO: Set this magic number to something meaningful
  39 + float stddev = 1;
  40 +
  41 + if (queryValue == targetValue) return 1;
  42 + else return 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((targetValue-queryValue)/stddev, 2));
  43 + }
  44 +};
  45 +
  46 +BR_REGISTER(Distance, AttributeDistance)
  47 +
  48 +} // namespace br
  49 +
  50 +#include "distance/attribute.moc"
... ...
openbr/plugins/distance/bayesianquantization.cpp 0 → 100644
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/opencvutils.h>
  21 +
  22 +using namespace cv;
  23 +
  24 +namespace br
  25 +{
  26 +
  27 +/*!
  28 + * \ingroup distances
  29 + * \brief Bayesian quantization distance
  30 + * \author Josh Klontz \cite jklontz
  31 + */
  32 +class BayesianQuantizationDistance : public Distance
  33 +{
  34 + Q_OBJECT
  35 +
  36 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  37 + BR_PROPERTY(QString, inputVariable, "Label")
  38 +
  39 + QVector<float> loglikelihoods;
  40 +
  41 + static void computeLogLikelihood(const Mat &data, const QList<int> &labels, float *loglikelihood)
  42 + {
  43 + const QList<uchar> vals = OpenCVUtils::matrixToVector<uchar>(data);
  44 + if (vals.size() != labels.size())
  45 + qFatal("Logic error.");
  46 +
  47 + QVector<quint64> genuines(256, 0), impostors(256,0);
  48 + for (int i=0; i<vals.size(); i++)
  49 + for (int j=i+1; j<vals.size(); j++)
  50 + if (labels[i] == labels[j]) genuines[abs(vals[i]-vals[j])]++;
  51 + else impostors[abs(vals[i]-vals[j])]++;
  52 +
  53 + quint64 totalGenuines(0), totalImpostors(0);
  54 + for (int i=0; i<256; i++) {
  55 + totalGenuines += genuines[i];
  56 + totalImpostors += impostors[i];
  57 + }
  58 +
  59 + for (int i=0; i<256; i++)
  60 + loglikelihood[i] = log((float(genuines[i]+1)/totalGenuines)/(float(impostors[i]+1)/totalImpostors));
  61 + }
  62 +
  63 + void train(const TemplateList &src)
  64 + {
  65 + if ((src.first().size() > 1) || (src.first().m().type() != CV_8UC1))
  66 + qFatal("Expected sigle matrix templates of type CV_8UC1!");
  67 +
  68 + const Mat data = OpenCVUtils::toMat(src.data());
  69 + const QList<int> templateLabels = src.indexProperty(inputVariable);
  70 + loglikelihoods = QVector<float>(data.cols*256, 0);
  71 +
  72 + QFutureSynchronizer<void> futures;
  73 + for (int i=0; i<data.cols; i++)
  74 + futures.addFuture(QtConcurrent::run(&BayesianQuantizationDistance::computeLogLikelihood, data.col(i), templateLabels, &loglikelihoods.data()[i*256]));
  75 + futures.waitForFinished();
  76 + }
  77 +
  78 + float compare(const cv::Mat &a, const cv::Mat &b) const
  79 + {
  80 + const uchar *aData = a.data;
  81 + const uchar *bData = b.data;
  82 + const int size = a.rows * a.cols;
  83 + float likelihood = 0;
  84 + for (int i=0; i<size; i++)
  85 + likelihood += loglikelihoods[i*256+abs(aData[i]-bData[i])];
  86 + return likelihood;
  87 + }
  88 +
  89 + void store(QDataStream &stream) const
  90 + {
  91 + stream << loglikelihoods;
  92 + }
  93 +
  94 + void load(QDataStream &stream)
  95 + {
  96 + stream >> loglikelihoods;
  97 + }
  98 +};
  99 +
  100 +BR_REGISTER(Distance, BayesianQuantizationDistance)
  101 +
  102 +} // namespace br
  103 +
  104 +#include "distance/bayesianquantization.moc"
... ...
openbr/plugins/distance/byteL1.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/distance_sse.h>
  19 +
  20 +namespace br
  21 +{
  22 +
  23 +/*!
  24 + * \ingroup distances
  25 + * \brief Fast 8-bit L1 distance
  26 + * \author Josh Klontz \cite jklontz
  27 + */
  28 +class ByteL1Distance : public UntrainableDistance
  29 +{
  30 + Q_OBJECT
  31 +
  32 + float compare(const unsigned char *a, const unsigned char *b, size_t size) const
  33 + {
  34 + return l1(a, b, size);
  35 + }
  36 +};
  37 +
  38 +BR_REGISTER(Distance, ByteL1Distance)
  39 +
  40 +} // namespace br
  41 +
  42 +#include "distance/byteL1.moc"
... ...
openbr/plugins/distance/crossvalidate.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief Cross validate a distance metric.
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class CrossValidateDistance : public UntrainableDistance
  28 +{
  29 + Q_OBJECT
  30 +
  31 + float compare(const Template &a, const Template &b) const
  32 + {
  33 + static const QString key("Partition"); // More efficient to preallocate this
  34 + const int partitionA = a.file.get<int>(key, 0);
  35 + const int partitionB = b.file.get<int>(key, 0);
  36 + return (partitionA != partitionB) ? -std::numeric_limits<float>::max() : 0;
  37 + }
  38 +};
  39 +
  40 +BR_REGISTER(Distance, CrossValidateDistance)
  41 +
  42 +} // namespace br
  43 +
  44 +#include "distance/crossvalidate.moc"
... ...
openbr/plugins/distance/default.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief DistDistance wrapper.
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class DefaultDistance : public UntrainableDistance
  28 +{
  29 + Q_OBJECT
  30 + Distance *distance;
  31 +
  32 + void init()
  33 + {
  34 + distance = Distance::make("Dist("+file.suffix()+")");
  35 + }
  36 +
  37 + float compare(const cv::Mat &a, const cv::Mat &b) const
  38 + {
  39 + return distance->compare(a, b);
  40 + }
  41 +};
  42 +
  43 +BR_REGISTER(Distance, DefaultDistance)
  44 +
  45 +} // namespace br
  46 +
  47 +#include "distance/default.moc"
... ...
openbr/plugins/distance/dist.cpp 0 → 100644
  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 <opencv2/imgproc/imgproc.hpp>
  18 +#include <openbr/plugins/openbr_internal.h>
  19 +
  20 +using namespace cv;
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +/*!
  26 + * \ingroup distances
  27 + * \brief Standard distance metrics
  28 + * \author Josh Klontz \cite jklontz
  29 + */
  30 +class DistDistance : public UntrainableDistance
  31 +{
  32 + Q_OBJECT
  33 + Q_ENUMS(Metric)
  34 + Q_PROPERTY(Metric metric READ get_metric WRITE set_metric RESET reset_metric STORED false)
  35 + Q_PROPERTY(bool negLogPlusOne READ get_negLogPlusOne WRITE set_negLogPlusOne RESET reset_negLogPlusOne STORED false)
  36 +
  37 +public:
  38 + /*!< */
  39 + enum Metric { Correlation,
  40 + ChiSquared,
  41 + Intersection,
  42 + Bhattacharyya,
  43 + INF,
  44 + L1,
  45 + L2,
  46 + Cosine,
  47 + Dot};
  48 +
  49 +private:
  50 + BR_PROPERTY(Metric, metric, L2)
  51 + BR_PROPERTY(bool, negLogPlusOne, true)
  52 +
  53 + float compare(const Mat &a, const Mat &b) const
  54 + {
  55 + if ((a.size != b.size) ||
  56 + (a.type() != b.type()))
  57 + return -std::numeric_limits<float>::max();
  58 +
  59 +// TODO: this max value is never returned based on the switch / default
  60 + float result = std::numeric_limits<float>::max();
  61 + switch (metric) {
  62 + case Correlation:
  63 + return compareHist(a, b, CV_COMP_CORREL);
  64 + case ChiSquared:
  65 + result = compareHist(a, b, CV_COMP_CHISQR);
  66 + break;
  67 + case Intersection:
  68 + result = compareHist(a, b, CV_COMP_INTERSECT);
  69 + break;
  70 + case Bhattacharyya:
  71 + result = compareHist(a, b, CV_COMP_BHATTACHARYYA);
  72 + break;
  73 + case INF:
  74 + result = norm(a, b, NORM_INF);
  75 + break;
  76 + case L1:
  77 + result = norm(a, b, NORM_L1);
  78 + break;
  79 + case L2:
  80 + result = norm(a, b, NORM_L2);
  81 + break;
  82 + case Cosine:
  83 + return cosine(a, b);
  84 + case Dot:
  85 + return a.dot(b);
  86 + default:
  87 + qFatal("Invalid metric");
  88 + }
  89 +
  90 + if (result != result)
  91 + qFatal("NaN result.");
  92 +
  93 + return negLogPlusOne ? -log(result+1) : result;
  94 + }
  95 +
  96 + static float cosine(const Mat &a, const Mat &b)
  97 + {
  98 + float dot = 0;
  99 + float magA = 0;
  100 + float magB = 0;
  101 +
  102 + for (int row=0; row<a.rows; row++) {
  103 + for (int col=0; col<a.cols; col++) {
  104 + const float target = a.at<float>(row,col);
  105 + const float query = b.at<float>(row,col);
  106 + dot += target * query;
  107 + magA += target * target;
  108 + magB += query * query;
  109 + }
  110 + }
  111 +
  112 + return dot / (sqrt(magA)*sqrt(magB));
  113 + }
  114 +};
  115 +
  116 +BR_REGISTER(Distance, DistDistance)
  117 +
  118 +} // namespace br
  119 +
  120 +#include "distance/dist.moc"
... ...
openbr/plugins/distance/filter.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief Checks target metadata against filters.
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class FilterDistance : public UntrainableDistance
  28 +{
  29 + Q_OBJECT
  30 +
  31 + float compare(const Template &a, const Template &b) const
  32 + {
  33 + (void) b; // Query template isn't checked
  34 + foreach (const QString &key, Globals->filters.keys()) {
  35 + bool keep = false;
  36 + const QString metadata = a.file.get<QString>(key, "");
  37 + if (Globals->filters[key].isEmpty()) continue;
  38 + if (metadata.isEmpty()) return -std::numeric_limits<float>::max();
  39 + foreach (const QString &value, Globals->filters[key]) {
  40 + if (metadata == value) {
  41 + keep = true;
  42 + break;
  43 + }
  44 + }
  45 + if (!keep) return -std::numeric_limits<float>::max();
  46 + }
  47 + return 0;
  48 + }
  49 +};
  50 +
  51 +BR_REGISTER(Distance, FilterDistance)
  52 +
  53 +} // namespace br
  54 +
  55 +#include "distance/filter.moc"
... ...
openbr/plugins/distance/fuse.cpp 0 → 100644
  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 <numeric>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +/*!
  25 + * \ingroup distances
  26 + * \brief Fuses similarity scores across multiple matrices of compared templates
  27 + * \author Scott Klum \cite sklum
  28 + * \note Operation: Mean, sum, min, max are supported.
  29 + */
  30 +class FuseDistance : public Distance
  31 +{
  32 + Q_OBJECT
  33 + Q_ENUMS(Operation)
  34 + Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
  35 + Q_PROPERTY(Operation operation READ get_operation WRITE set_operation RESET reset_operation STORED false)
  36 + Q_PROPERTY(QList<float> weights READ get_weights WRITE set_weights RESET reset_weights STORED false)
  37 +
  38 + QList<br::Distance*> distances;
  39 +
  40 +public:
  41 + /*!< */
  42 + enum Operation {Mean, Sum, Max, Min};
  43 +
  44 +private:
  45 + BR_PROPERTY(QString, description, "L2")
  46 + BR_PROPERTY(Operation, operation, Mean)
  47 + BR_PROPERTY(QList<float>, weights, QList<float>())
  48 +
  49 + void train(const TemplateList &src)
  50 + {
  51 + // Partition the templates by matrix
  52 + QList<int> split;
  53 + for (int i=0; i<src.at(0).size(); i++) split.append(1);
  54 +
  55 + QList<TemplateList> partitionedSrc = src.partition(split);
  56 +
  57 + while (distances.size() < partitionedSrc.size())
  58 + distances.append(make(description));
  59 +
  60 + // Train on each of the partitions
  61 + for (int i=0; i<distances.size(); i++)
  62 + distances[i]->train(partitionedSrc[i]);
  63 + }
  64 +
  65 + float compare(const Template &a, const Template &b) const
  66 + {
  67 + if (a.size() != b.size()) qFatal("Comparison size mismatch");
  68 +
  69 + QList<float> scores;
  70 + for (int i=0; i<distances.size(); i++) {
  71 + float weight;
  72 + weights.isEmpty() ? weight = 1. : weight = weights[i];
  73 + scores.append(weight*distances[i]->compare(Template(a.file, a[i]),Template(b.file, b[i])));
  74 + }
  75 +
  76 + switch (operation) {
  77 + case Mean:
  78 + return std::accumulate(scores.begin(),scores.end(),0.0)/(float)scores.size();
  79 + break;
  80 + case Sum:
  81 + return std::accumulate(scores.begin(),scores.end(),0.0);
  82 + break;
  83 + case Min:
  84 + return *std::min_element(scores.begin(),scores.end());
  85 + break;
  86 + case Max:
  87 + return *std::max_element(scores.begin(),scores.end());
  88 + break;
  89 + default:
  90 + qFatal("Invalid operation.");
  91 + }
  92 + return 0;
  93 + }
  94 +
  95 + void store(QDataStream &stream) const
  96 + {
  97 + stream << distances.size();
  98 + foreach (Distance *distance, distances)
  99 + distance->store(stream);
  100 + }
  101 +
  102 + void load(QDataStream &stream)
  103 + {
  104 + int numDistances;
  105 + stream >> numDistances;
  106 + while (distances.size() < numDistances)
  107 + distances.append(make(description));
  108 + foreach (Distance *distance, distances)
  109 + distance->load(stream);
  110 + }
  111 +};
  112 +
  113 +BR_REGISTER(Distance, FuseDistance)
  114 +
  115 +} // namespace br
  116 +
  117 +#include "distance/fuse.moc"
... ...
openbr/plugins/distance/halfbyteL1.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/distance_sse.h>
  19 +
  20 +using namespace cv;
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +/*!
  26 + * \ingroup distances
  27 + * \brief Fast 4-bit L1 distance
  28 + * \author Josh Klontz \cite jklontz
  29 + */
  30 +class HalfByteL1Distance : public UntrainableDistance
  31 +{
  32 + Q_OBJECT
  33 +
  34 + float compare(const Mat &a, const Mat &b) const
  35 + {
  36 + return packed_l1(a.data, b.data, a.total());
  37 + }
  38 +};
  39 +
  40 +BR_REGISTER(Distance, HalfByteL1Distance)
  41 +
  42 +
  43 +} // namespace br
  44 +
  45 +#include "distance/halfbyteL1.moc"
... ...
openbr/plugins/distance/heatmap.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief 1v1 heat map comparison
  25 + * \author Scott Klum \cite sklum
  26 + */
  27 +class HeatMapDistance : public Distance
  28 +{
  29 + Q_OBJECT
  30 + Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false)
  31 + Q_PROPERTY(int step READ get_step WRITE set_step RESET reset_step STORED false)
  32 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  33 + BR_PROPERTY(QString, description, "IdenticalDistance")
  34 + BR_PROPERTY(int, step, 1)
  35 + BR_PROPERTY(QString, inputVariable, "Label")
  36 +
  37 + QList<br::Distance*> distances;
  38 +
  39 + void train(const TemplateList &src)
  40 + {
  41 + QList<TemplateList> patches;
  42 +
  43 + // Split src into list of TemplateLists of corresponding patches across all Templates
  44 + for (int i=0; i<step; i++) {
  45 + TemplateList patchBuffer;
  46 + for (int j=0; j<src.size(); j++)
  47 + patchBuffer.append(Template(src[j].file, src[j][i]));
  48 + patches.append(patchBuffer);
  49 + patchBuffer.clear();
  50 + }
  51 +
  52 + while (distances.size() < patches.size())
  53 + distances.append(make(description));
  54 +
  55 + // Train on a distance for each patch
  56 + for (int i=0; i<distances.size(); i++)
  57 + distances[i]->train(patches[i]);
  58 + }
  59 +
  60 + float compare(const cv::Mat &target, const cv::Mat &query) const
  61 + {
  62 + (void) target;
  63 + (void) query;
  64 + qFatal("Heatmap Distance not compatible with Template to Template comparison.");
  65 +
  66 + return 0;
  67 + }
  68 +
  69 + void compare(const TemplateList &target, const TemplateList &query, Output *output) const
  70 + {
  71 + for (int i=0; i<target.size(); i++) {
  72 + if (target[i].size() != step || query[i].size() != step) qFatal("Heatmap step not equal to the number of patches.");
  73 + for (int j=0; j<step; j++)
  74 + output->setRelative(distances[j]->compare(target[i][j],query[i][j]), j, 0);
  75 + }
  76 + }
  77 +
  78 + void store(QDataStream &stream) const
  79 + {
  80 + stream << distances.size();
  81 + foreach (Distance *distance, distances)
  82 + distance->store(stream);
  83 + }
  84 +
  85 + void load(QDataStream &stream)
  86 + {
  87 + int numDistances;
  88 + stream >> numDistances;
  89 + while (distances.size() < numDistances)
  90 + distances.append(make(description));
  91 + foreach (Distance *distance, distances)
  92 + distance->load(stream);
  93 + }
  94 +};
  95 +
  96 +BR_REGISTER(Distance, HeatMapDistance)
  97 +
  98 +} // namespace br
  99 +
  100 +#include "distance/heatmap.moc"
... ...
openbr/plugins/distance/identical.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +using namespace cv;
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +/*!
  25 + * \ingroup distances
  26 + * \brief Returns \c true if the templates are identical, \c false otherwise.
  27 + * \author Josh Klontz \cite jklontz
  28 + */
  29 +class IdenticalDistance : public UntrainableDistance
  30 +{
  31 + Q_OBJECT
  32 +
  33 + float compare(const Mat &a, const Mat &b) const
  34 + {
  35 + const size_t size = a.total() * a.elemSize();
  36 + if (size != b.total() * b.elemSize()) return 0;
  37 + for (size_t i=0; i<size; i++)
  38 + if (a.data[i] != b.data[i]) return 0;
  39 + return 1;
  40 + }
  41 +};
  42 +
  43 +BR_REGISTER(Distance, IdenticalDistance)
  44 +
  45 +} // namespace br
  46 +
  47 +#include "distance/identical.moc"
... ...
openbr/plugins/distance/keypointmatcher.cpp 0 → 100644
  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 <opencv2/features2d/features2d.hpp>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +using namespace cv;
  22 +
  23 +namespace br
  24 +{
  25 +
  26 +/*!
  27 + * \ingroup transforms
  28 + * \brief Wraps OpenCV Key Point Matcher
  29 + * \author Josh Klontz \cite jklontz
  30 + */
  31 +class KeyPointMatcherDistance : public UntrainableDistance
  32 +{
  33 + Q_OBJECT
  34 + Q_PROPERTY(QString matcher READ get_matcher WRITE set_matcher RESET reset_matcher STORED false)
  35 + Q_PROPERTY(float maxRatio READ get_maxRatio WRITE set_maxRatio RESET reset_maxRatio STORED false)
  36 + BR_PROPERTY(QString, matcher, "BruteForce")
  37 + BR_PROPERTY(float, maxRatio, 0.8)
  38 +
  39 + Ptr<DescriptorMatcher> descriptorMatcher;
  40 +
  41 + void init()
  42 + {
  43 + descriptorMatcher = DescriptorMatcher::create(matcher.toStdString());
  44 + if (descriptorMatcher.empty())
  45 + qFatal("Failed to create DescriptorMatcher: %s", qPrintable(matcher));
  46 + }
  47 +
  48 + float compare(const Mat &a, const Mat &b) const
  49 + {
  50 + if ((a.rows < 2) || (b.rows < 2)) return 0;
  51 +
  52 + std::vector< std::vector<DMatch> > matches;
  53 + if (a.rows < b.rows) descriptorMatcher->knnMatch(a, b, matches, 2);
  54 + else descriptorMatcher->knnMatch(b, a, matches, 2);
  55 +
  56 + QList<float> distances;
  57 + foreach (const std::vector<DMatch> &match, matches) {
  58 + if (match[0].distance / match[1].distance > maxRatio) continue;
  59 + distances.append(match[0].distance);
  60 + }
  61 + qSort(distances);
  62 +
  63 + float similarity = 0;
  64 + for (int i=0; i<distances.size(); i++)
  65 + similarity += 1.f/(1+distances[i])/(i+1);
  66 + return similarity;
  67 + }
  68 +};
  69 +
  70 +BR_REGISTER(Distance, KeyPointMatcherDistance)
  71 +
  72 +} // namespace br
  73 +
  74 +#include "distance/keypointmatcher.moc"
... ...
openbr/plugins/distance/l1.cpp 0 → 100644
  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 <Eigen/Dense>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +/*!
  25 + * \ingroup distances
  26 + * \brief L1 distance computed using eigen.
  27 + * \author Josh Klontz \cite jklontz
  28 + */
  29 +class L1Distance : public UntrainableDistance
  30 +{
  31 + Q_OBJECT
  32 +
  33 + float compare(const cv::Mat &a, const cv::Mat &b) const
  34 + {
  35 + const int size = a.rows * a.cols;
  36 + Eigen::Map<Eigen::VectorXf> aMap((float*)a.data, size);
  37 + Eigen::Map<Eigen::VectorXf> bMap((float*)b.data, size);
  38 + return (aMap-bMap).cwiseAbs().sum();
  39 + }
  40 +};
  41 +
  42 +BR_REGISTER(Distance, L1Distance)
  43 +
  44 +} // namespace br
  45 +
  46 +#include "distance/L1.moc"
... ...
openbr/plugins/distance/matchprobability.cpp 0 → 100644
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/common.h>
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +float KDEPointer(const QList<float> *scores, double x, double h)
  26 +{
  27 + return Common::KernelDensityEstimation(*scores, x, h);
  28 +}
  29 +
  30 +/* Kernel Density Estimator */
  31 +struct KDE
  32 +{
  33 + float min, max;
  34 + double mean, stddev;
  35 + QList<float> bins;
  36 +
  37 + KDE() : min(0), max(1), mean(0), stddev(1) {}
  38 +
  39 + KDE(const QList<float> &scores, bool trainKDE)
  40 + {
  41 + Common::MinMax(scores, &min, &max);
  42 + Common::MeanStdDev(scores, &mean, &stddev);
  43 +
  44 + if (!trainKDE)
  45 + return;
  46 +
  47 + double h = Common::KernelDensityBandwidth(scores);
  48 + const int size = 255;
  49 + bins.reserve(size);
  50 +
  51 + QFutureSynchronizer<float> futures;
  52 +
  53 + for (int i=0; i < size; i++)
  54 + futures.addFuture(QtConcurrent::run(KDEPointer, &scores, min + (max-min)*i/(size-1), h));
  55 + futures.waitForFinished();
  56 +
  57 + foreach(const QFuture<float> & future, futures.futures())
  58 + bins.append(future.result());
  59 + }
  60 +
  61 + float operator()(float score, bool gaussian = true) const
  62 + {
  63 + if (gaussian) return 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((score-mean)/stddev, 2));
  64 + if (bins.empty())
  65 + return -std::numeric_limits<float>::max();
  66 +
  67 + if (score <= min) return bins.first();
  68 + if (score >= max) return bins.last();
  69 + const float x = (score-min)/(max-min)*bins.size();
  70 + const float y1 = bins[floor(x)];
  71 + const float y2 = bins[ceil(x)];
  72 + return y1 + (y2-y1)*(x-floor(x));
  73 + }
  74 +};
  75 +
  76 +QDataStream &operator<<(QDataStream &stream, const KDE &kde)
  77 +{
  78 + return stream << kde.min << kde.max << kde.mean << kde.stddev << kde.bins;
  79 +}
  80 +
  81 +QDataStream &operator>>(QDataStream &stream, KDE &kde)
  82 +{
  83 + return stream >> kde.min >> kde.max >> kde.mean >> kde.stddev >> kde.bins;
  84 +}
  85 +
  86 +/* Match Probability */
  87 +struct MP
  88 +{
  89 + KDE genuine, impostor;
  90 + MP() {}
  91 + MP(const QList<float> &genuineScores, const QList<float> &impostorScores, bool trainKDE)
  92 + : genuine(genuineScores, trainKDE), impostor(impostorScores, trainKDE) {}
  93 + float operator()(float score, bool gaussian = true) const
  94 + {
  95 + const float g = genuine(score, gaussian);
  96 + const float s = g / (impostor(score, gaussian) + g);
  97 + return s;
  98 + }
  99 +};
  100 +
  101 +QDataStream &operator<<(QDataStream &stream, const MP &nmp)
  102 +{
  103 + return stream << nmp.genuine << nmp.impostor;
  104 +}
  105 +
  106 +QDataStream &operator>>(QDataStream &stream, MP &nmp)
  107 +{
  108 + return stream >> nmp.genuine >> nmp.impostor;
  109 +}
  110 +
  111 +/*!
  112 + * \ingroup distances
  113 + * \brief Match Probability \cite klare12
  114 + * \author Josh Klontz \cite jklontz
  115 + */
  116 +class MatchProbabilityDistance : public Distance
  117 +{
  118 + Q_OBJECT
  119 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  120 + Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false)
  121 + Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false)
  122 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  123 +
  124 + MP mp;
  125 +
  126 + void train(const TemplateList &src)
  127 + {
  128 + distance->train(src);
  129 +
  130 + const QList<int> labels = src.indexProperty(inputVariable);
  131 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));
  132 + distance->compare(src, src, matrixOutput.data());
  133 +
  134 + QList<float> genuineScores, impostorScores;
  135 + genuineScores.reserve(labels.size());
  136 + impostorScores.reserve(labels.size()*labels.size());
  137 + for (int i=0; i<src.size(); i++) {
  138 + for (int j=0; j<i; j++) {
  139 + const float score = matrixOutput.data()->data.at<float>(i, j);
  140 + if (score == -std::numeric_limits<float>::max()) continue;
  141 + if (crossModality && src[i].file.get<QString>("MODALITY") == src[j].file.get<QString>("MODALITY")) continue;
  142 + if (labels[i] == labels[j]) genuineScores.append(score);
  143 + else impostorScores.append(score);
  144 + }
  145 + }
  146 +
  147 + mp = MP(genuineScores, impostorScores, !gaussian);
  148 + }
  149 +
  150 + float compare(const Template &target, const Template &query) const
  151 + {
  152 + return normalize(distance->compare(target, query));
  153 + }
  154 +
  155 + float compare(const cv::Mat &target, const cv::Mat &query) const
  156 + {
  157 + return normalize(distance->compare(target, query));
  158 + }
  159 +
  160 + float compare(const uchar *a, const uchar *b, size_t size) const
  161 + {
  162 + return normalize(distance->compare(a, b, size));
  163 + }
  164 +
  165 + float normalize(float score) const
  166 + {
  167 + if (score == -std::numeric_limits<float>::max()) return score;
  168 + if (!Globals->scoreNormalization) return -log(score+1);
  169 + return mp(score, gaussian);
  170 + }
  171 +
  172 + void store(QDataStream &stream) const
  173 + {
  174 + distance->store(stream);
  175 + stream << mp;
  176 + }
  177 +
  178 + void load(QDataStream &stream)
  179 + {
  180 + distance->load(stream);
  181 + stream >> mp;
  182 + }
  183 +
  184 +protected:
  185 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  186 + BR_PROPERTY(bool, gaussian, true)
  187 + BR_PROPERTY(bool, crossModality, false)
  188 + BR_PROPERTY(QString, inputVariable, "Label")
  189 +};
  190 +
  191 +BR_REGISTER(Distance, MatchProbabilityDistance)
  192 +
  193 +} // namespace br
  194 +
  195 +#include "distance/matchprobability.moc"
... ...
openbr/plugins/distance/metadata.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/qtutils.h>
  19 +
  20 +namespace br
  21 +{
  22 +
  23 +/*!
  24 + * \ingroup distances
  25 + * \brief Checks target metadata against query metadata.
  26 + * \author Scott Klum \cite sklum
  27 + */
  28 +class MetadataDistance : public UntrainableDistance
  29 +{
  30 + Q_OBJECT
  31 +
  32 + Q_PROPERTY(QStringList filters READ get_filters WRITE set_filters RESET reset_filters STORED false)
  33 + BR_PROPERTY(QStringList, filters, QStringList())
  34 +
  35 + float compare(const Template &a, const Template &b) const
  36 + {
  37 + foreach (const QString &key, filters) {
  38 + QString aValue = a.file.get<QString>(key, QString());
  39 + QString bValue = b.file.get<QString>(key, QString());
  40 +
  41 + // The query value may be a range. Let's check.
  42 + if (bValue.isEmpty()) bValue = QtUtils::toString(b.file.get<QPointF>(key, QPointF()));
  43 +
  44 + if (aValue.isEmpty() || bValue.isEmpty()) continue;
  45 +
  46 + bool keep = false;
  47 + bool ok;
  48 +
  49 + QPointF range = QtUtils::toPoint(bValue,&ok);
  50 +
  51 + if (ok) /* Range */ {
  52 + int value = range.x();
  53 + int upperBound = range.y();
  54 +
  55 + while (value <= upperBound) {
  56 + if (aValue == QString::number(value)) {
  57 + keep = true;
  58 + break;
  59 + }
  60 + value++;
  61 + }
  62 + }
  63 + else if (aValue == bValue) keep = true;
  64 +
  65 + if (!keep) return -std::numeric_limits<float>::max();
  66 + }
  67 + return 0;
  68 + }
  69 +};
  70 +
  71 +
  72 +BR_REGISTER(Distance, MetadataDistance)
  73 +
  74 +} // namespace br
  75 +
  76 +#include "distance/metadata.moc"
... ...
openbr/plugins/distance/neglogplusone.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief Returns -log(distance(a,b)+1)
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class NegativeLogPlusOneDistance : public UntrainableDistance
  28 +{
  29 + Q_OBJECT
  30 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  31 + BR_PROPERTY(br::Distance*, distance, NULL)
  32 +
  33 + void train(const TemplateList &src)
  34 + {
  35 + distance->train(src);
  36 + }
  37 +
  38 + float compare(const Template &a, const Template &b) const
  39 + {
  40 + return -log(distance->compare(a,b)+1);
  41 + }
  42 +
  43 + void store(QDataStream &stream) const
  44 + {
  45 + distance->store(stream);
  46 + }
  47 +
  48 + void load(QDataStream &stream)
  49 + {
  50 + distance->load(stream);
  51 + }
  52 +};
  53 +
  54 +BR_REGISTER(Distance, NegativeLogPlusOneDistance)
  55 +
  56 +} // namespace br
  57 +
  58 +#include "distance/neglogplusone.moc"
... ...
openbr/plugins/distance/online.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief Online distance metric to attenuate match scores across multiple frames
  25 + * \author Brendan klare \cite bklare
  26 + */
  27 +class OnlineDistance : public UntrainableDistance
  28 +{
  29 + Q_OBJECT
  30 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  31 + Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false)
  32 + BR_PROPERTY(br::Distance*, distance, NULL)
  33 + BR_PROPERTY(float, alpha, 0.1f)
  34 +
  35 + mutable QHash<QString,float> scoreHash;
  36 + mutable QMutex mutex;
  37 +
  38 + float compare(const Template &target, const Template &query) const
  39 + {
  40 + float currentScore = distance->compare(target, query);
  41 +
  42 + QMutexLocker mutexLocker(&mutex);
  43 + return scoreHash[target.file.name] = (1.0- alpha) * scoreHash[target.file.name] + alpha * currentScore;
  44 + }
  45 +};
  46 +
  47 +BR_REGISTER(Distance, OnlineDistance)
  48 +
  49 +} // namespace br
  50 +
  51 +#include "distance/online.moc"
... ...
openbr/plugins/distance/pipe.cpp 0 → 100644
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +/*!
  25 + * \ingroup distances
  26 + * \brief Distances in series.
  27 + * \author Josh Klontz \cite jklontz
  28 + *
  29 + * The templates are compared using each br::Distance in order.
  30 + * If the result of the comparison with any given distance is -FLOAT_MAX then this result is returned early.
  31 + * Otherwise the returned result is the value of comparing the templates using the last br::Distance.
  32 + */
  33 +class PipeDistance : public Distance
  34 +{
  35 + Q_OBJECT
  36 + Q_PROPERTY(QList<br::Distance*> distances READ get_distances WRITE set_distances RESET reset_distances)
  37 + BR_PROPERTY(QList<br::Distance*>, distances, QList<br::Distance*>())
  38 +
  39 + void train(const TemplateList &data)
  40 + {
  41 + QFutureSynchronizer<void> futures;
  42 + foreach (br::Distance *distance, distances)
  43 + futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
  44 + futures.waitForFinished();
  45 + }
  46 +
  47 + float compare(const Template &a, const Template &b) const
  48 + {
  49 + float result = -std::numeric_limits<float>::max();
  50 + foreach (br::Distance *distance, distances) {
  51 + result = distance->compare(a, b);
  52 + if (result == -std::numeric_limits<float>::max())
  53 + return result;
  54 + }
  55 + return result;
  56 + }
  57 +};
  58 +
  59 +BR_REGISTER(Distance, PipeDistance)
  60 +
  61 +} // namespace br
  62 +
  63 +#include "distance/pipe.moc"
... ...
openbr/plugins/distance/reject.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief Sets distance to -FLOAT_MAX if a target template has/doesn't have a key.
  25 + * \author Scott Klum \cite sklum
  26 + */
  27 +class RejectDistance : public UntrainableDistance
  28 +{
  29 + Q_OBJECT
  30 +
  31 + Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)
  32 + BR_PROPERTY(QStringList, keys, QStringList())
  33 + Q_PROPERTY(bool rejectIfContains READ get_rejectIfContains WRITE set_rejectIfContains RESET reset_rejectIfContains STORED false)
  34 + BR_PROPERTY(bool, rejectIfContains, false)
  35 +
  36 + float compare(const Template &a, const Template &b) const
  37 + {
  38 + // We don't look at the query
  39 + (void) b;
  40 +
  41 + foreach (const QString &key, keys)
  42 + if ((rejectIfContains && a.file.contains(key)) || (!rejectIfContains && !a.file.contains(key)))
  43 + return -std::numeric_limits<float>::max();
  44 +
  45 + return 0;
  46 + }
  47 +};
  48 +
  49 +
  50 +BR_REGISTER(Distance, RejectDistance)
  51 +
  52 +} // namespace br
  53 +
  54 +#include "distance/reject.moc"
... ...
openbr/plugins/distance/sum.cpp 0 → 100644
  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 <QtConcurrent>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +
  21 +namespace br
  22 +{
  23 +
  24 +/*!
  25 + * \ingroup distances
  26 + * \brief Sum match scores across multiple distances
  27 + * \author Scott Klum \cite sklum
  28 + */
  29 +class SumDistance : public UntrainableDistance
  30 +{
  31 + Q_OBJECT
  32 + Q_PROPERTY(QList<br::Distance*> distances READ get_distances WRITE set_distances RESET reset_distances)
  33 + BR_PROPERTY(QList<br::Distance*>, distances, QList<br::Distance*>())
  34 +
  35 + void train(const TemplateList &data)
  36 + {
  37 + QFutureSynchronizer<void> futures;
  38 + foreach (br::Distance *distance, distances)
  39 + futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
  40 + futures.waitForFinished();
  41 + }
  42 +
  43 + float compare(const Template &target, const Template &query) const
  44 + {
  45 + float result = 0;
  46 +
  47 + foreach (br::Distance *distance, distances) {
  48 + result += distance->compare(target, query);
  49 +
  50 + if (result == -std::numeric_limits<float>::max())
  51 + return result;
  52 + }
  53 +
  54 + return result;
  55 + }
  56 +};
  57 +
  58 +BR_REGISTER(Distance, SumDistance)
  59 +
  60 +} // namespace br
  61 +
  62 +#include "distance/sum.moc"
... ...
openbr/plugins/distance/turk.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/opencvutils.h>
  19 +
  20 +namespace br
  21 +{
  22 +
  23 +/*!
  24 + * \ingroup distances
  25 + * \brief Unmaps Turk HITs to be compared against query mats
  26 + * \author Scott Klum \cite sklum
  27 + */
  28 +class TurkDistance : public UntrainableDistance
  29 +{
  30 + Q_OBJECT
  31 + Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key)
  32 + Q_PROPERTY(QStringList values READ get_values WRITE set_values RESET reset_values STORED false)
  33 + BR_PROPERTY(QString, key, QString())
  34 + BR_PROPERTY(QStringList, values, QStringList())
  35 +
  36 + bool targetHuman;
  37 + bool queryMachine;
  38 +
  39 + void init()
  40 + {
  41 + targetHuman = Globals->property("TurkTargetHuman").toBool();
  42 + queryMachine = Globals->property("TurkQueryMachine").toBool();
  43 + }
  44 +
  45 + cv::Mat getValues(const Template &t) const
  46 + {
  47 + QList<float> result;
  48 + foreach (const QString &value, values)
  49 + result.append(t.file.get<float>(key + "_" + value));
  50 + return OpenCVUtils::toMat(result, 1);
  51 + }
  52 +
  53 + float compare(const Template &target, const Template &query) const
  54 + {
  55 + const cv::Mat a = targetHuman ? getValues(target) : target.m();
  56 + const cv::Mat b = queryMachine ? query.m() : getValues(query);
  57 + return -norm(a, b, cv::NORM_L1);
  58 + }
  59 +};
  60 +
  61 +BR_REGISTER(Distance, TurkDistance)
  62 +
  63 +} // namespace br
  64 +
  65 +#include "distance/turk.moc"
... ...
openbr/plugins/distance/unit.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup distances
  24 + * \brief Linear normalizes of a distance so the mean impostor score is 0 and the mean genuine score is 1.
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class UnitDistance : public Distance
  28 +{
  29 + Q_OBJECT
  30 + Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance)
  31 + Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a)
  32 + Q_PROPERTY(float b READ get_b WRITE set_b RESET reset_b)
  33 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  34 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  35 + BR_PROPERTY(float, a, 1)
  36 + BR_PROPERTY(float, b, 0)
  37 + BR_PROPERTY(QString, inputVariable, "Label")
  38 +
  39 + void train(const TemplateList &templates)
  40 + {
  41 + const TemplateList samples = templates.mid(0, 2000);
  42 + const QList<int> sampleLabels = samples.indexProperty(inputVariable);
  43 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(samples.size()), FileList(samples.size())));
  44 + Distance::compare(samples, samples, matrixOutput.data());
  45 +
  46 + double genuineAccumulator, impostorAccumulator;
  47 + int genuineCount, impostorCount;
  48 + genuineAccumulator = impostorAccumulator = genuineCount = impostorCount = 0;
  49 +
  50 + for (int i=0; i<samples.size(); i++) {
  51 + for (int j=0; j<i; j++) {
  52 + const float val = matrixOutput.data()->data.at<float>(i, j);
  53 + if (sampleLabels[i] == sampleLabels[j]) {
  54 + genuineAccumulator += val;
  55 + genuineCount++;
  56 + } else {
  57 + impostorAccumulator += val;
  58 + impostorCount++;
  59 + }
  60 + }
  61 + }
  62 +
  63 + if (genuineCount == 0) { qWarning("No genuine matches."); return; }
  64 + if (impostorCount == 0) { qWarning("No impostor matches."); return; }
  65 +
  66 + double genuineMean = genuineAccumulator / genuineCount;
  67 + double impostorMean = impostorAccumulator / impostorCount;
  68 +
  69 + if (genuineMean == impostorMean) { qWarning("Genuines and impostors are indistinguishable."); return; }
  70 +
  71 + a = 1.0/(genuineMean-impostorMean);
  72 + b = impostorMean;
  73 +
  74 + qDebug("a = %f, b = %f", a, b);
  75 + }
  76 +
  77 + float compare(const Template &target, const Template &query) const
  78 + {
  79 + return a * (distance->compare(target, query) - b);
  80 + }
  81 +};
  82 +
  83 +BR_REGISTER(Distance, UnitDistance)
  84 +
  85 +} // namespace br
  86 +
  87 +#include "distance/unit.moc"
... ...
openbr/plugins/distance/zscore.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/common.h>
  19 +
  20 +namespace br
  21 +{
  22 +
  23 +class ZScoreDistance : public Distance
  24 +{
  25 + Q_OBJECT
  26 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  27 + Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false)
  28 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  29 + BR_PROPERTY(bool, crossModality, false)
  30 +
  31 + float min, max;
  32 + double mean, stddev;
  33 +
  34 + void train(const TemplateList &src)
  35 + {
  36 + distance->train(src);
  37 +
  38 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));
  39 + distance->compare(src, src, matrixOutput.data());
  40 +
  41 + QList<float> scores;
  42 + scores.reserve(src.size()*src.size());
  43 + for (int i=0; i<src.size(); i++) {
  44 + for (int j=0; j<i; j++) {
  45 + const float score = matrixOutput.data()->data.at<float>(i, j);
  46 + if (score == -std::numeric_limits<float>::max()) continue;
  47 + if (crossModality && src[i].file.get<QString>("MODALITY") == src[j].file.get<QString>("MODALITY")) continue;
  48 + scores.append(score);
  49 + }
  50 + }
  51 +
  52 + Common::MinMax(scores, &min, &max);
  53 + Common::MeanStdDev(scores, &mean, &stddev);
  54 +
  55 + if (stddev == 0) qFatal("Stddev is 0.");
  56 + }
  57 +
  58 + float compare(const Template &target, const Template &query) const
  59 + {
  60 + float score = distance->compare(target,query);
  61 + if (score == -std::numeric_limits<float>::max()) score = (min - mean) / stddev;
  62 + else if (score == std::numeric_limits<float>::max()) score = (max - mean) / stddev;
  63 + else score = (score - mean) / stddev;
  64 + return score;
  65 + }
  66 +
  67 + void store(QDataStream &stream) const
  68 + {
  69 + distance->store(stream);
  70 + stream << min << max << mean << stddev;
  71 + }
  72 +
  73 + void load(QDataStream &stream)
  74 + {
  75 + distance->load(stream);
  76 + stream >> min >> max >> mean >> stddev;
  77 + }
  78 +};
  79 +
  80 +BR_REGISTER(Distance, ZScoreDistance)
  81 +
  82 +} // namespace br
  83 +
  84 +#include "distance/zscore.moc"
... ...
openbr/plugins/draw.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 <opencv2/highgui/highgui.hpp>
18   -#include <opencv2/highgui/highgui_c.h>
19   -#include <opencv2/imgproc/imgproc.hpp>
20   -#include <vector>
21   -#include "openbr_internal.h"
22   -#include "openbr/core/opencvutils.h"
23   -
24   -using namespace cv;
25   -
26   -namespace br
27   -{
28   -
29   -/*!
30   - * \ingroup transforms
31   - * \brief Renders metadata onto the image.
32   - *
33   - * The inPlace argument controls whether or not the image is cloned before the metadata is drawn.
34   - *
35   - * \author Josh Klontz \cite jklontz
36   - */
37   -class DrawTransform : public UntrainableTransform
38   -{
39   - Q_OBJECT
40   - Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false)
41   - Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false)
42   - Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false)
43   - Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
44   - Q_PROPERTY(int lineThickness READ get_lineThickness WRITE set_lineThickness RESET reset_lineThickness STORED false)
45   - Q_PROPERTY(bool named READ get_named WRITE set_named RESET reset_named STORED false)
46   - Q_PROPERTY(bool location READ get_location WRITE set_location RESET reset_location STORED false)
47   - BR_PROPERTY(bool, verbose, false)
48   - BR_PROPERTY(bool, points, true)
49   - BR_PROPERTY(bool, rects, true)
50   - BR_PROPERTY(bool, inPlace, false)
51   - BR_PROPERTY(int, lineThickness, 1)
52   - BR_PROPERTY(bool, named, true)
53   - BR_PROPERTY(bool, location, true)
54   -
55   - void project(const Template &src, Template &dst) const
56   - {
57   - const Scalar color(0,255,0);
58   - const Scalar verboseColor(255, 255, 0);
59   - dst.m() = inPlace ? src.m() : src.m().clone();
60   -
61   - if (points) {
62   - const QList<Point2f> pointsList = (named) ? OpenCVUtils::toPoints(src.file.points()+src.file.namedPoints()) : OpenCVUtils::toPoints(src.file.points());
63   - for (int i=0; i<pointsList.size(); i++) {
64   - const Point2f &point = pointsList[i];
65   - circle(dst, point, 3, color, -1);
66   - QString label = (location) ? QString("%1,(%2,%3)").arg(QString::number(i),QString::number(point.x),QString::number(point.y)) : QString("%1").arg(QString::number(i));
67   - if (verbose) putText(dst, label.toStdString(), point, FONT_HERSHEY_SIMPLEX, 0.5, verboseColor, 1);
68   - }
69   - }
70   - if (rects) {
71   - foreach (const Rect &rect, OpenCVUtils::toRects(src.file.namedRects() + src.file.rects()))
72   - rectangle(dst, rect, color, lineThickness);
73   - }
74   - }
75   -};
76   -
77   -BR_REGISTER(Transform, DrawTransform)
78   -
79   -
80   -/*!
81   - * \ingroup transforms
82   - * \brief Draw the value of the specified property at the specified point on the image
83   - *
84   - * The inPlace argument controls whether or not the image is cloned before it is drawn on.
85   - *
86   - * \author Charles Otto \cite caotto
87   - */
88   -class DrawPropertyPointTransform : public UntrainableTransform
89   -{
90   - Q_OBJECT
91   - Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
92   - Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false)
93   - Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
94   - BR_PROPERTY(QString, propName, "")
95   - BR_PROPERTY(QString, pointName, "")
96   - BR_PROPERTY(bool, inPlace, false)
97   -
98   -
99   - void project(const Template &src, Template &dst) const
100   - {
101   - dst = src;
102   - if (propName.isEmpty() || pointName.isEmpty())
103   - return;
104   -
105   - dst.m() = inPlace ? src.m() : src.m().clone();
106   -
107   - const Scalar textColor(255, 255, 0);
108   -
109   - QVariant prop = dst.file.value(propName);
110   -
111   -
112   - if (!prop.canConvert(QVariant::String))
113   - return;
114   - QString propString = prop.toString();
115   -
116   - QVariant point = dst.file.value(pointName);
117   -
118   - if (!point.canConvert(QVariant::PointF))
119   - return;
120   -
121   - QPointF targetPoint = point.toPointF();
122   -
123   - Point2f cvPoint =OpenCVUtils::toPoint(targetPoint);
124   -
125   - std::string text = propName.toStdString() + ": " + propString.toStdString();
126   - putText(dst, text, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1);
127   - }
128   -
129   -};
130   -BR_REGISTER(Transform, DrawPropertyPointTransform)
131   -
132   -/*!
133   - * \ingroup transforms
134   - * \brief Draw the values of a list of properties at the specified point on the image
135   - *
136   - * The inPlace argument controls whether or not the image is cloned before it is drawn on.
137   - *
138   - * \author Charles Otto \cite caotto
139   - */
140   -class DrawPropertiesPointTransform : public UntrainableTransform
141   -{
142   - Q_OBJECT
143   - Q_PROPERTY(QStringList propNames READ get_propNames WRITE set_propNames RESET reset_propNames STORED false)
144   - Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false)
145   - Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false)
146   - BR_PROPERTY(QStringList, propNames, QStringList())
147   - BR_PROPERTY(QString, pointName, "")
148   - BR_PROPERTY(bool, inPlace, false)
149   -
150   - void project(const Template &src, Template &dst) const
151   - {
152   - dst = src;
153   - if (propNames.isEmpty() || pointName.isEmpty())
154   - return;
155   -
156   - dst.m() = inPlace ? src.m() : src.m().clone();
157   -
158   - QVariant point = dst.file.value(pointName);
159   -
160   - if (!point.canConvert(QVariant::PointF))
161   - return;
162   -
163   - QPointF targetPoint = point.toPointF();
164   -
165   - Point2f cvPoint =OpenCVUtils::toPoint(targetPoint);
166   -
167   -
168   - const Scalar textColor(255, 255, 0);
169   -
170   - std::string outString = "";
171   - foreach (const QString &propName, propNames)
172   - {
173   - QVariant prop = dst.file.value(propName);
174   -
175   - if (!prop.canConvert(QVariant::String))
176   - continue;
177   - QString propString = prop.toString();
178   - outString += propName.toStdString() + ": " + propString.toStdString() + " ";
179   -
180   - }
181   - if (outString.empty())
182   - return;
183   -
184   - putText(dst, outString, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1);
185   - }
186   -
187   -};
188   -BR_REGISTER(Transform, DrawPropertiesPointTransform)
189   -
190   -
191   -/*!
192   - * \ingroup transforms
193   - * \brief Draws a grid on the image
194   - * \author Josh Klontz \cite jklontz
195   - */
196   -class DrawGridTransform : public UntrainableTransform
197   -{
198   - Q_OBJECT
199   - Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
200   - Q_PROPERTY(int columns READ get_columns WRITE set_columns RESET reset_columns STORED false)
201   - Q_PROPERTY(int r READ get_r WRITE set_r RESET reset_r STORED false)
202   - Q_PROPERTY(int g READ get_g WRITE set_g RESET reset_g STORED false)
203   - Q_PROPERTY(int b READ get_b WRITE set_b RESET reset_b STORED false)
204   - BR_PROPERTY(int, rows, 0)
205   - BR_PROPERTY(int, columns, 0)
206   - BR_PROPERTY(int, r, 196)
207   - BR_PROPERTY(int, g, 196)
208   - BR_PROPERTY(int, b, 196)
209   -
210   - void project(const Template &src, Template &dst) const
211   - {
212   - Mat m = src.m().clone();
213   - float rowStep = 1.f * m.rows / (rows+1);
214   - float columnStep = 1.f * m.cols / (columns+1);
215   - int thickness = qMin(m.rows, m.cols) / 256;
216   - for (float row = rowStep/2; row < m.rows; row += rowStep)
217   - line(m, Point(0, row), Point(m.cols, row), Scalar(r, g, b), thickness, CV_AA);
218   - for (float column = columnStep/2; column < m.cols; column += columnStep)
219   - line(m, Point(column, 0), Point(column, m.rows), Scalar(r, g, b), thickness, CV_AA);
220   - dst = m;
221   - }
222   -};
223   -
224   -BR_REGISTER(Transform, DrawGridTransform)
225   -
226   -/*!
227   - * \ingroup transforms
228   - * \brief Computes the mean of a set of templates.
229   - * \note Suitable for visualization only as it sets every projected template to the mean template.
230   - * \author Scott Klum \cite sklum
231   - */
232   -class MeanTransform : public Transform
233   -{
234   - Q_OBJECT
235   -
236   - Mat mean;
237   -
238   - void train(const TemplateList &data)
239   - {
240   - mean = Mat::zeros(data[0].m().rows,data[0].m().cols,CV_32F);
241   -
242   - for (int i = 0; i < data.size(); i++) {
243   - Mat converted;
244   - data[i].m().convertTo(converted, CV_32F);
245   - mean += converted;
246   - }
247   -
248   - mean /= data.size();
249   - }
250   -
251   - void project(const Template &src, Template &dst) const
252   - {
253   - dst = src;
254   - dst.m() = mean;
255   - }
256   -
257   -};
258   -
259   -BR_REGISTER(Transform, MeanTransform)
260   -
261   -/*!
262   - * \ingroup transforms
263   - * \brief Load the image named in the specified property, draw it on the current matrix adjacent to the rect specified in the other property.
264   - * \author Charles Otto \cite caotto
265   - */
266   -class AdjacentOverlayTransform : public Transform
267   -{
268   - Q_OBJECT
269   -
270   - Q_PROPERTY(QString imgName READ get_imgName WRITE set_imgName RESET reset_imgName STORED false)
271   - Q_PROPERTY(QString targetName READ get_targetName WRITE set_targetName RESET reset_targetName STORED false)
272   - BR_PROPERTY(QString, imgName, "")
273   - BR_PROPERTY(QString, targetName, "")
274   -
275   - QSharedPointer<Transform> opener;
276   - void project(const Template &src, Template &dst) const
277   - {
278   - dst = src;
279   -
280   - if (imgName.isEmpty() || targetName.isEmpty() || !dst.file.contains(imgName) || !dst.file.contains(targetName))
281   - return;
282   -
283   - QVariant temp = src.file.value(imgName);
284   - cv::Mat im;
285   - // is this a filename?
286   - if (temp.canConvert<QString>()) {
287   - QString im_name = temp.toString();
288   - Template temp_im;
289   - opener->project(File(im_name), temp_im);
290   - im = temp_im.m();
291   - }
292   - // a cv::Mat ?
293   - else if (temp.canConvert<cv::Mat>())
294   - im = src.file.get<cv::Mat>(imgName);
295   - else
296   - qDebug() << "Unrecognized property type " << imgName << "for" << src.file.name;
297   -
298   - // Location of detected face in source image
299   - QRectF target_location = src.file.get<QRectF>(targetName);
300   -
301   - // match width with target region
302   - qreal target_width = target_location.width();
303   - qreal current_width = im.cols;
304   - qreal current_height = im.rows;
305   -
306   - qreal aspect_ratio = current_height / current_width;
307   - qreal target_height = target_width * aspect_ratio;
308   -
309   - cv::resize(im, im, cv::Size(target_width, target_height));
310   -
311   - // ROI used to maybe crop the matched image
312   - cv::Rect clip_roi;
313   - clip_roi.x = 0;
314   - clip_roi.y = 0;
315   - clip_roi.width = im.cols;
316   - clip_roi.height= im.rows <= dst.m().rows ? im.rows : dst.m().rows;
317   -
318   - int half_width = src.m().cols / 2;
319   - int out_x = 0;
320   -
321   - // place in the source image we will copy the matched image to.
322   - cv::Rect target_roi;
323   - bool left_side = false;
324   - int width_adjust = 0;
325   - // Place left
326   - if (target_location.center().rx() > half_width) {
327   - out_x = target_location.left() - im.cols;
328   - if (out_x < 0) {
329   - width_adjust = abs(out_x);
330   - out_x = 0;
331   - }
332   - left_side = true;
333   - }
334   - // place right
335   - else {
336   - out_x = target_location.right();
337   - int high = out_x + im.cols;
338   - if (high >= src.m().cols) {
339   - width_adjust = abs(high - src.m().cols + 1);
340   - }
341   - }
342   -
343   - cv::Mat outIm;
344   - if (width_adjust)
345   - {
346   - outIm.create(dst.m().rows, dst.m().cols + width_adjust, CV_8UC3);
347   - memset(outIm.data, 127, outIm.rows * outIm.cols * outIm.channels());
348   -
349   - Rect temp;
350   -
351   - if (left_side)
352   - temp = Rect(abs(width_adjust), 0, dst.m().cols, dst.m().rows);
353   -
354   - else
355   - temp = Rect(0, 0, dst.m().cols, dst.m().rows);
356   -
357   - dst.m().copyTo(outIm(temp));
358   -
359   - }
360   - else
361   - outIm = dst.m();
362   -
363   - if (clip_roi.height + target_location.top() >= outIm.rows)
364   - {
365   - clip_roi.height -= abs(outIm.rows - (clip_roi.height + target_location.top() ));
366   - }
367   - if (clip_roi.x + clip_roi.width >= im.cols) {
368   - clip_roi.width -= abs(im.cols - (clip_roi.x + clip_roi.width + 1));
369   - if (clip_roi.width < 0)
370   - clip_roi.width = 1;
371   - }
372   -
373   - if (clip_roi.y + clip_roi.height >= im.rows) {
374   - clip_roi.height -= abs(im.rows - (clip_roi.y + clip_roi.height + 1));
375   - }
376   - if (clip_roi.x < 0)
377   - clip_roi.x = 0;
378   - if (clip_roi.y < 0)
379   - clip_roi.y = 0;
380   -
381   - if (clip_roi.height < 0)
382   - clip_roi.height = 0;
383   -
384   - if (clip_roi.width < 0)
385   - clip_roi.width = 0;
386   -
387   -
388   - if (clip_roi.y + clip_roi.height >= im.rows)
389   - {
390   - qDebug() << "Bad clip y" << clip_roi.y + clip_roi.height << im.rows;
391   - }
392   - if (clip_roi.x + clip_roi.width >= im.cols)
393   - {
394   - qDebug() << "Bad clip x" << clip_roi.x + clip_roi.width << im.cols;
395   - }
396   -
397   - if (clip_roi.y < 0 || clip_roi.height < 0)
398   - {
399   - qDebug() << "bad clip y, low" << clip_roi.y << clip_roi.height;
400   - qFatal("die");
401   - }
402   - if (clip_roi.x < 0 || clip_roi.width < 0)
403   - {
404   - qDebug() << "bad clip x, low" << clip_roi.x << clip_roi.width;
405   - qFatal("die");
406   - }
407   -
408   - target_roi.x = out_x;
409   - target_roi.width = clip_roi.width;
410   - target_roi.y = target_location.top();
411   - target_roi.height = clip_roi.height;
412   -
413   -
414   - im = im(clip_roi);
415   -
416   - if (target_roi.x < 0 || target_roi.x >= outIm.cols)
417   - {
418   - qDebug() << "Bad xdim in targetROI!" << target_roi.x << " out im x: " << outIm.cols;
419   - qFatal("die");
420   - }
421   -
422   - if (target_roi.x + target_roi.width < 0 || (target_roi.x + target_roi.width) >= outIm.cols)
423   - {
424   - qDebug() << "Bad xdim in targetROI!" << target_roi.x + target_roi.width;
425   - qFatal("die");
426   - }
427   -
428   - if (target_roi.y < 0 || target_roi.y >= outIm.rows)
429   - {
430   - qDebug() << "Bad ydim in targetROI!" << target_roi.y;
431   - qFatal("die");
432   - }
433   -
434   - if ((target_roi.y + target_roi.height) < 0 || (target_roi.y + target_roi.height) > outIm.rows)
435   - {
436   - qDebug() << "Bad ydim in targetROI!" << target_roi.y + target_roi.height;
437   - qDebug() << "target_roi.y: " << target_roi.y << " height: " << target_roi.height;
438   - qFatal("die");
439   - }
440   -
441   -
442   - std::vector<cv::Mat> channels;
443   - cv::split(outIm, channels);
444   -
445   - std::vector<cv::Mat> patch_channels;
446   - cv::split(im, patch_channels);
447   -
448   - for (size_t i=0; i < channels.size(); i++)
449   - {
450   - cv::addWeighted(channels[i](target_roi), 0, patch_channels[i % patch_channels.size()], 1, 0,channels[i](target_roi));
451   - }
452   - cv::merge(channels, outIm);
453   - dst.m() = outIm;
454   -
455   - }
456   -
457   - void init()
458   - {
459   - opener = QSharedPointer<br::Transform>(br::Transform::make("Cache(Open)", NULL));
460   - }
461   -
462   -};
463   -
464   -BR_REGISTER(Transform, AdjacentOverlayTransform)
465   -
466   -/*!
467   - * \ingroup transforms
468   - * \brief Draw a line representing the direction and magnitude of optical flow at the specified points.
469   - * \author Austin Blanton \cite imaus10
470   - */
471   -class DrawOpticalFlow : public UntrainableTransform
472   -{
473   - Q_OBJECT
474   - Q_PROPERTY(QString original READ get_original WRITE set_original RESET reset_original STORED false)
475   - BR_PROPERTY(QString, original, "original")
476   -
477   - void project(const Template &src, Template &dst) const
478   - {
479   - const Scalar color(0,255,0);
480   - Mat flow = src.m();
481   - dst = src;
482   - if (!dst.file.contains(original)) qFatal("The original img must be saved in the metadata with SaveMat.");
483   - dst.m() = dst.file.get<Mat>(original);
484   - dst.file.remove(original);
485   - foreach (const Point2f &pt, OpenCVUtils::toPoints(dst.file.points())) {
486   - Point2f dxy = flow.at<Point2f>(pt.y, pt.x);
487   - Point2f newPt(pt.x+dxy.x, pt.y+dxy.y);
488   - line(dst, pt, newPt, color);
489   - }
490   - }
491   -};
492   -BR_REGISTER(Transform, DrawOpticalFlow)
493   -
494   -/*!
495   - * \ingroup transforms
496   - * \brief Fill in the segmentations or draw a line between intersecting segments.
497   - * \author Austin Blanton \cite imaus10
498   - */
499   -class DrawSegmentation : public UntrainableTransform
500   -{
501   - Q_OBJECT
502   - Q_PROPERTY(bool fillSegment READ get_fillSegment WRITE set_fillSegment RESET reset_fillSegment STORED false)
503   - BR_PROPERTY(bool, fillSegment, true)
504   -
505   - void project(const Template &src, Template &dst) const
506   - {
507   - if (!src.file.contains("SegmentsMask") || !src.file.contains("NumSegments")) qFatal("Must supply a Contours object in the metadata to drawContours.");
508   - Mat segments = src.file.get<Mat>("SegmentsMask");
509   - int numSegments = src.file.get<int>("NumSegments");
510   -
511   - dst.file = src.file;
512   - Mat drawn = fillSegment ? Mat(segments.size(), CV_8UC3, Scalar::all(0)) : src.m();
513   -
514   - for (int i=1; i<numSegments+1; i++) {
515   - Mat mask = segments == i;
516   - if (fillSegment) { // color the whole segment
517   - // set to a random color - get ready for a craaaazy acid trip
518   - int b = theRNG().uniform(0, 255);
519   - int g = theRNG().uniform(0, 255);
520   - int r = theRNG().uniform(0, 255);
521   - drawn.setTo(Scalar(r,g,b), mask);
522   - } else { // draw lines where there's a color change
523   - vector<vector<Point> > contours;
524   - Scalar color(0,255,0);
525   - findContours(mask, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
526   - drawContours(drawn, contours, -1, color);
527   - }
528   - }
529   -
530   - dst.m() = drawn;
531   - }
532   -};
533   -BR_REGISTER(Transform, DrawSegmentation)
534   -
535   -/*!
536   - * \ingroup transforms
537   - * \brief Write all mats to disk as images.
538   - * \author Brendan Klare \cite bklare
539   - */
540   -class WriteImageTransform : public TimeVaryingTransform
541   -{
542   - Q_OBJECT
543   - Q_PROPERTY(QString outputDirectory READ get_outputDirectory WRITE set_outputDirectory RESET reset_outputDirectory STORED false)
544   - Q_PROPERTY(QString imageName READ get_imageName WRITE set_imageName RESET reset_imageName STORED false)
545   - Q_PROPERTY(QString imgExtension READ get_imgExtension WRITE set_imgExtension RESET reset_imgExtension STORED false)
546   - BR_PROPERTY(QString, outputDirectory, "Temp")
547   - BR_PROPERTY(QString, imageName, "image")
548   - BR_PROPERTY(QString, imgExtension, "jpg")
549   -
550   - int cnt;
551   -
552   - void init() {
553   - cnt = 0;
554   - if (! QDir(outputDirectory).exists())
555   - QDir().mkdir(outputDirectory);
556   - }
557   -
558   - void projectUpdate(const Template &src, Template &dst)
559   - {
560   - dst = src;
561   - OpenCVUtils::saveImage(dst.m(), QString("%1/%2_%3.%4").arg(outputDirectory).arg(imageName).arg(cnt++, 5, 10, QChar('0')).arg(imgExtension));
562   - }
563   -
564   -};
565   -BR_REGISTER(Transform, WriteImageTransform)
566   -
567   -
568   -/**
569   - * @brief The MeanImageTransform class computes the average template/image
570   - * and save the result as an encoded image.
571   - */
572   -class MeanImageTransform : public TimeVaryingTransform
573   -{
574   - Q_OBJECT
575   -
576   - Q_PROPERTY(QString imgname READ get_imgname WRITE set_imgname RESET reset_imgname STORED false)
577   - Q_PROPERTY(QString ext READ get_ext WRITE set_ext RESET reset_ext STORED false)
578   -
579   - BR_PROPERTY(QString, imgname, "average")
580   - BR_PROPERTY(QString, ext, "jpg")
581   -
582   - Mat average;
583   - int cnt;
584   -
585   - void init()
586   - {
587   - cnt = 0;
588   - }
589   -
590   - void projectUpdate(const Template &src, Template &dst)
591   - {
592   - dst = src;
593   - if (cnt == 0) {
594   - if (src.m().channels() == 1)
595   - average = Mat::zeros(dst.m().size(),CV_64FC1);
596   - else if (src.m().channels() == 3)
597   - average = Mat::zeros(dst.m().size(),CV_64FC3);
598   - else
599   - qFatal("Unsupported number of channels");
600   - }
601   -
602   - Mat temp;
603   - if (src.m().channels() == 1) {
604   - src.m().convertTo(temp, CV_64FC1);
605   - average += temp;
606   - } else if (src.m().channels() == 3) {
607   - src.m().convertTo(temp, CV_64FC3);
608   - average += temp;
609   - } else
610   - qFatal("Unsupported number of channels");
611   -
612   - cnt++;
613   - }
614   -
615   - virtual void finalize(TemplateList &output)
616   - {
617   - average /= float(cnt);
618   - imwrite(QString("%1.%2").arg(imgname).arg(ext).toStdString(), average);
619   - output = TemplateList();
620   - }
621   -
622   -
623   -public:
624   - MeanImageTransform() : TimeVaryingTransform(false, false) {}
625   -};
626   -
627   -BR_REGISTER(Transform, MeanImageTransform)
628   -
629   -
630   -// TODO: re-implement EditTransform using Qt
631   -#if 0
632   -/*!
633   - * \ingroup transforms
634   - * \brief Remove landmarks.
635   - * \author Josh Klontz \cite jklontz
636   - */
637   -class EditTransform : public UntrainableTransform
638   -{
639   - Q_OBJECT
640   -
641   - Transform *draw;
642   - static Template currentTemplate;
643   - static QMutex currentTemplateLock;
644   -
645   - void init()
646   - {
647   - draw = make("Draw");
648   - Globals->setProperty("parallelism", "0"); // Can only work in single threaded mode
649   - }
650   -
651   - void project(const Template &src, Template &dst) const
652   - {
653   - dst = src;
654   -
655   - if (Globals->parallelism) {
656   - qWarning("Edit::project() only works in single threaded mode.");
657   - return;
658   - }
659   -
660   - currentTemplateLock.lock();
661   - currentTemplate = src;
662   - OpenCVUtils::showImage(src, "Edit", false);
663   - setMouseCallback("Edit", mouseCallback, (void*)this);
664   - mouseEvent(0, 0, 0, 0);
665   - waitKey(-1);
666   - dst = currentTemplate;
667   - currentTemplateLock.unlock();
668   - }
669   -
670   - static void mouseCallback(int event, int x, int y, int flags, void *userdata)
671   - {
672   - ((const EditTransform*)userdata)->mouseEvent(event, x, y, flags);
673   - }
674   -
675   - void mouseEvent(int event, int x, int y, int flags) const
676   - {
677   - (void) event;
678   - if (flags) {
679   - QList<QRectF> rects = currentTemplate.file.rects();
680   - for (int i=rects.size()-1; i>=0; i--)
681   - if (rects[i].contains(x,y))
682   - rects.removeAt(i);
683   - currentTemplate.file.setRects(rects);
684   - }
685   -
686   - Template temp;
687   - draw->project(currentTemplate, temp);
688   - OpenCVUtils::showImage(temp, "Edit", false);
689   - }
690   -};
691   -
692   -Template EditTransform::currentTemplate;
693   -QMutex EditTransform::currentTemplateLock;
694   -
695   -BR_REGISTER(Transform, EditTransform)
696   -#endif
697   -
698   -} // namespace br
699   -
700   -#include "draw.moc"
openbr/plugins/eigen3.cmake deleted
1   -set(BR_WITH_EIGEN3 ON CACHE BOOL "Build Eigen3 plugins")
2   -
3   -if(${BR_WITH_EIGEN3})
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)
7   -endif()
openbr/plugins/filter.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 <opencv2/imgproc/imgproc.hpp>
18   -#include "openbr_internal.h"
19   -#include "openbr/core/tanh_sse.h"
20   -
21   -using namespace cv;
22   -
23   -namespace br
24   -{
25   -
26   -/*!
27   - * \ingroup transforms
28   - * \brief Gamma correction
29   - * \author Josh Klontz \cite jklontz
30   - */
31   -class GammaTransform : public UntrainableTransform
32   -{
33   - Q_OBJECT
34   - Q_PROPERTY(float gamma READ get_gamma WRITE set_gamma RESET reset_gamma STORED false)
35   - BR_PROPERTY(float, gamma, 0.2)
36   -
37   - Mat lut;
38   -
39   - void init()
40   - {
41   - lut.create(256, 1, CV_32FC1);
42   - if (gamma == 0) for (int i=0; i<256; i++) lut.at<float>(i,0) = log((float)i);
43   - else for (int i=0; i<256; i++) lut.at<float>(i,0) = pow(i, gamma);
44   - }
45   -
46   - void project(const Template &src, Template &dst) const
47   - {
48   - if (src.m().depth() == CV_8U) LUT(src, lut, dst);
49   - else pow(src, gamma, dst);
50   - }
51   -};
52   -
53   -BR_REGISTER(Transform, GammaTransform)
54   -
55   -/*!
56   - * \ingroup transforms
57   - * \brief Gaussian blur
58   - * \author Josh Klontz \cite jklontz
59   - */
60   -class BlurTransform : public UntrainableTransform
61   -{
62   - Q_OBJECT
63   - Q_PROPERTY(float sigma READ get_sigma WRITE set_sigma RESET reset_sigma STORED false)
64   - Q_PROPERTY(bool ROI READ get_ROI WRITE set_ROI RESET reset_ROI STORED false)
65   - BR_PROPERTY(float, sigma, 1)
66   - BR_PROPERTY(bool, ROI, false)
67   -
68   - void project(const Template &src, Template &dst) const
69   - {
70   - if (!ROI) GaussianBlur(src, dst, Size(0,0), sigma);
71   - else {
72   - dst.m() = src.m();
73   - foreach (const QRectF &rect, src.file.rects()) {
74   - Rect region(rect.x(), rect.y(), rect.width(), rect.height());
75   - Mat input = dst.m();
76   - Mat output = input.clone();
77   - GaussianBlur(input(region), output(region), Size(0,0), sigma);
78   - dst.m() = output;
79   - }
80   - }
81   - }
82   -};
83   -
84   -BR_REGISTER(Transform, BlurTransform)
85   -
86   -/*!
87   - * \ingroup transforms
88   - * \brief Difference of gaussians
89   - * \author Josh Klontz \cite jklontz
90   - */
91   -class DoGTransform : public UntrainableTransform
92   -{
93   - Q_OBJECT
94   - Q_PROPERTY(float sigma0 READ get_sigma0 WRITE set_sigma0 RESET reset_sigma0 STORED false)
95   - Q_PROPERTY(float sigma1 READ get_sigma1 WRITE set_sigma1 RESET reset_sigma1 STORED false)
96   - BR_PROPERTY(float, sigma0, 1)
97   - BR_PROPERTY(float, sigma1, 2)
98   -
99   - Size ksize0, ksize1;
100   -
101   - static Size getKernelSize(double sigma)
102   - {
103   - // Inverts OpenCV's conversion from kernel size to sigma:
104   - // sigma = ((ksize-1)*0.5 - 1)*0.3 + 0.8
105   - // See documentation for cv::getGaussianKernel()
106   - int ksize = ((sigma - 0.8) / 0.3 + 1) * 2 + 1;
107   - if (ksize % 2 == 0) ksize++;
108   - return Size(ksize, ksize);
109   - }
110   -
111   - void init()
112   - {
113   - ksize0 = getKernelSize(sigma0);
114   - ksize1 = getKernelSize(sigma1);
115   - }
116   -
117   - void project(const Template &src, Template &dst) const
118   - {
119   - Mat g0, g1;
120   - GaussianBlur(src, g0, ksize0, 0);
121   - GaussianBlur(src, g1, ksize1, 0);
122   - subtract(g0, g1, dst);
123   - }
124   -};
125   -
126   -BR_REGISTER(Transform, DoGTransform)
127   -
128   -/*!
129   - * \ingroup transforms
130   - * \brief Meyers, E.; Wolf, L.
131   - * “Using biologically inspired features for face processing,”
132   - * Int. Journal of Computer Vision, vol. 76, no. 1, pp 93–104, 2008.
133   - * \author Scott Klum \cite sklum
134   - */
135   -
136   -class CSDNTransform : public UntrainableTransform
137   -{
138   - Q_OBJECT
139   -
140   - Q_PROPERTY(float s READ get_s WRITE set_s RESET reset_s STORED false)
141   - BR_PROPERTY(int, s, 16)
142   -
143   - void project(const Template &src, Template &dst) const
144   - {
145   - if (src.m().channels() != 1) qFatal("Expected single channel source matrix.");
146   -
147   - const int nRows = src.m().rows;
148   - const int nCols = src.m().cols;
149   -
150   - Mat m;
151   - src.m().convertTo(m, CV_32FC1);
152   -
153   - const int surround = s/2;
154   -
155   - for ( int i = 0; i < nRows; i++ ) {
156   - for ( int j = 0; j < nCols; j++ ) {
157   - int width = min( j+surround, nCols ) - max( 0, j-surround );
158   - int height = min( i+surround, nRows ) - max( 0, i-surround );
159   -
160   - Rect_<int> ROI(max(0, j-surround), max(0, i-surround), width, height);
161   -
162   - Scalar_<float> avg = mean(m(ROI));
163   -
164   - m.at<float>(i,j) = m.at<float>(i,j) - avg[0];
165   - }
166   - }
167   -
168   - dst = m;
169   -
170   - }
171   -};
172   -
173   -BR_REGISTER(Transform, CSDNTransform)
174   -
175   -/*!
176   - * \ingroup transforms
177   - * \brief Xiaoyang Tan; Triggs, B.;
178   - * "Enhanced Local Texture Feature Sets for Face Recognition Under Difficult Lighting Conditions,"
179   - * Image Processing, IEEE Transactions on , vol.19, no.6, pp.1635-1650, June 2010
180   - * \author Josh Klontz \cite jklontz
181   - */
182   -class ContrastEqTransform : public UntrainableTransform
183   -{
184   - Q_OBJECT
185   - Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a STORED false)
186   - Q_PROPERTY(float t READ get_t WRITE set_t RESET reset_t STORED false)
187   - BR_PROPERTY(float, a, 1)
188   - BR_PROPERTY(float, t, 0.1)
189   -
190   - void project(const Template &src, Template &dst) const
191   - {
192   - if (src.m().channels() != 1) qFatal("Expected single channel source matrix.");
193   -
194   - // Stage 1
195   - Mat stage1;
196   - {
197   - Mat abs_dst;
198   - absdiff(src, Scalar(0), abs_dst);
199   - Mat pow_dst;
200   - pow(abs_dst, a, pow_dst);
201   - float denominator = pow((float)mean(pow_dst)[0], 1.f/a);
202   - src.m().convertTo(stage1, CV_32F, 1/denominator);
203   - }
204   -
205   - // Stage 2
206   - Mat stage2;
207   - {
208   - Mat abs_dst;
209   - absdiff(stage1, Scalar(0), abs_dst);
210   - Mat min_dst;
211   - min(abs_dst, t, min_dst);
212   - Mat pow_dst;
213   - pow(min_dst, a, pow_dst);
214   - float denominator = pow((float)mean(pow_dst)[0], 1.f/a);
215   - stage1.convertTo(stage2, CV_32F, 1/denominator);
216   - }
217   -
218   - // Hyperbolic tangent
219   - const int nRows = src.m().rows;
220   - const int nCols = src.m().cols;
221   - const float* p = (const float*)stage2.ptr();
222   - Mat m(nRows, nCols, CV_32FC1);
223   - for (int i=0; i<nRows; i++)
224   - for (int j=0; j<nCols; j++)
225   - m.at<float>(i, j) = fast_tanh(p[i*nCols+j]);
226   - // TODO: m.at<float>(i, j) = t * fast_tanh(p[i*nCols+j] / t);
227   -
228   - dst = m;
229   - }
230   -};
231   -
232   -BR_REGISTER(Transform, ContrastEqTransform)
233   -
234   -/*!
235   - * \ingroup transforms
236   - * \brief Raise each element to the specified power.
237   - * \author Josh Klontz \cite jklontz
238   - */
239   -class PowTransform : public UntrainableTransform
240   -{
241   - Q_OBJECT
242   - Q_PROPERTY(float power READ get_power WRITE set_power RESET reset_power STORED false)
243   - Q_PROPERTY(bool preserveSign READ get_preserveSign WRITE set_preserveSign RESET reset_preserveSign STORED false)
244   - BR_PROPERTY(float, power, 2)
245   - BR_PROPERTY(bool, preserveSign, false)
246   -
247   - void project(const Template &src, Template &dst) const
248   - {
249   - pow(preserveSign ? abs(src) : src.m(), power, dst);
250   - if (preserveSign) subtract(Scalar::all(0), dst, dst, src.m() < 0);
251   - }
252   -};
253   -
254   -BR_REGISTER(Transform, PowTransform)
255   -
256   -} // namespace br
257   -
258   -#include "filter.moc"
openbr/plugins/format.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 <QDate>
18   -#include <QSize>
19   -#include <QChar>
20   -#ifndef BR_EMBEDDED
21   -#include <QtXml>
22   -#endif // BR_EMBEDDED
23   -#include <QFile>
24   -#include <QFileInfo>
25   -
26   -#include <opencv2/highgui/highgui.hpp>
27   -#include <opencv2/highgui/highgui_c.h>
28   -#include "openbr_internal.h"
29   -
30   -#include "openbr/core/bee.h"
31   -#include "openbr/core/opencvutils.h"
32   -#include "openbr/core/qtutils.h"
33   -
34   -using namespace cv;
35   -
36   -namespace br
37   -{
38   -
39   - /*!
40   - * \ingroup formats
41   - * \brief Read all frames of a video using OpenCV
42   - * \author Charles Otto \cite caotto
43   - */
44   -class videoFormat : public Format
45   -{
46   - Q_OBJECT
47   -
48   -public:
49   - Template read() const
50   - {
51   - if (!file.exists() )
52   - return Template();
53   -
54   - VideoCapture videoSource(file.name.toStdString());
55   - videoSource.open(file.name.toStdString() );
56   -
57   -
58   - Template frames;
59   - if (!videoSource.isOpened()) {
60   - qWarning("video file open failed");
61   - return frames;
62   - }
63   -
64   - bool open = true;
65   - while (open) {
66   - cv::Mat frame;
67   - open = videoSource.read(frame);
68   - if (!open) break;
69   -
70   - frames.append(cv::Mat());
71   - frames.back() = frame.clone();
72   - }
73   -
74   - return frames;
75   - }
76   -
77   - void write(const Template &t) const
78   - {
79   - int fourcc = OpenCVUtils::getFourcc();
80   - VideoWriter videoSink(file.name.toStdString(), fourcc, 30, t.begin()->size());
81   -
82   - // Did we successfully open the output file?
83   - if (!videoSink.isOpened() ) qFatal("Failed to open output file");
84   -
85   - for (Template::const_iterator it = t.begin(); it!= t.end(); ++it) {
86   - videoSink << *it;
87   - }
88   - }
89   -};
90   -
91   -BR_REGISTER(Format, videoFormat)
92   -
93   -/*!
94   - * \ingroup formats
95   - * \brief A simple binary matrix format.
96   - * \author Josh Klontz \cite jklontz
97   - * First 4 bytes indicate the number of rows.
98   - * Second 4 bytes indicate the number of columns.
99   - * The rest of the bytes are 32-bit floating data elements in row-major order.
100   - */
101   -class binFormat : public Format
102   -{
103   - Q_OBJECT
104   - Q_PROPERTY(bool raw READ get_raw WRITE set_raw RESET reset_raw STORED false)
105   - BR_PROPERTY(bool, raw, false)
106   -
107   - Template read() const
108   - {
109   - QByteArray data;
110   - QtUtils::readFile(file, data);
111   - if (raw) {
112   - return Template(file, Mat(1, data.size(), CV_8UC1, data.data()).clone());
113   - } else {
114   - return Template(file, Mat(((quint32*)data.data())[0],
115   - ((quint32*)data.data())[1],
116   - CV_32FC1,
117   - data.data()+8).clone());
118   - }
119   - }
120   -
121   - void write(const Template &t) const
122   - {
123   - QFile f(file);
124   - QtUtils::touchDir(f);
125   - if (!f.open(QFile::WriteOnly))
126   - qFatal("Failed to open %s for writing.", qPrintable(file));
127   -
128   - Mat m;
129   - if (!raw) {
130   - if (t.m().type() != CV_32FC1)
131   - t.m().convertTo(m, CV_32F);
132   - else m = t.m();
133   -
134   - if (m.channels() != 1) qFatal("Only supports single channel matrices.");
135   -
136   - f.write((const char *) &m.rows, 4);
137   - f.write((const char *) &m.cols, 4);
138   - }
139   - else m = t.m();
140   -
141   - qint64 rowSize = m.cols * sizeof(float);
142   - for (int i=0; i < m.rows; i++)
143   - {
144   - f.write((const char *) m.row(i).data, rowSize);
145   - }
146   - f.close();
147   - }
148   -};
149   -
150   -BR_REGISTER(Format, binFormat)
151   -
152   -/*!
153   - * \ingroup formats
154   - * \brief Reads a comma separated value file.
155   - * \author Josh Klontz \cite jklontz
156   - */
157   -class csvFormat : public Format
158   -{
159   - Q_OBJECT
160   -
161   - Template read() const
162   - {
163   - QFile f(file.name);
164   - f.open(QFile::ReadOnly);
165   - QStringList lines(QString(f.readAll()).split(QRegularExpression("[\n|\r\n|\r]"), QString::SkipEmptyParts));
166   - f.close();
167   -
168   - bool isUChar = true;
169   - QList< QList<float> > valsList;
170   - foreach (const QString &line, lines) {
171   - QList<float> vals;
172   - foreach (const QString &word, line.split(QRegExp(" *, *"), QString::SkipEmptyParts)) {
173   - bool ok;
174   - const float val = word.toFloat(&ok);
175   - vals.append(val);
176   - isUChar = isUChar && (val == float(uchar(val)));
177   - }
178   - if (!vals.isEmpty())
179   - valsList.append(vals);
180   - }
181   -
182   - Mat m(valsList.size(), valsList[0].size(), CV_32FC1);
183   - for (int i=0; i<valsList.size(); i++)
184   - for (int j=0; j<valsList[i].size(); j++)
185   - m.at<float>(i,j) = valsList[i][j];
186   -
187   - if (isUChar) m.convertTo(m, CV_8U);
188   - return Template(m);
189   - }
190   -
191   - void write(const Template &t) const
192   - {
193   - const Mat &m = t.m();
194   - if (t.size() != 1) qFatal("Only supports single matrix templates.");
195   - if (m.channels() != 1) qFatal("Only supports single channel matrices.");
196   -
197   - QStringList lines; lines.reserve(m.rows);
198   - for (int r=0; r<m.rows; r++) {
199   - QStringList elements; elements.reserve(m.cols);
200   - for (int c=0; c<m.cols; c++)
201   - elements.append(OpenCVUtils::elemToString(m, r, c));
202   - lines.append(elements.join(","));
203   - }
204   -
205   - QtUtils::writeFile(file, lines);
206   - }
207   -};
208   -
209   -BR_REGISTER(Format, csvFormat)
210   -
211   -/*!
212   - * \ingroup formats
213   - * \brief Reads image files.
214   - * \author Josh Klontz \cite jklontz
215   - */
216   -class DefaultFormat : public Format
217   -{
218   - Q_OBJECT
219   -
220   - Template read() const
221   - {
222   - Template t;
223   -
224   - if (file.name.startsWith("http://") || file.name.startsWith("https://") || file.name.startsWith("www.")) {
225   - if (Factory<Format>::names().contains("url")) {
226   - File urlFile = file;
227   - urlFile.name.append(".url");
228   - QScopedPointer<Format> url(Factory<Format>::make(urlFile));
229   - t = url->read();
230   - }
231   - } else {
232   - Mat m = imread(file.resolved().toStdString());
233   - if (m.data) {
234   - t.append(m);
235   - } else {
236   - videoFormat videoReader;
237   - videoReader.file = file;
238   - t = videoReader.read();
239   - }
240   - }
241   -
242   - return t;
243   - }
244   -
245   - void write(const Template &t) const
246   - {
247   - if (t.size() > 1) {
248   - videoFormat videoWriter;
249   - videoWriter.file = file;
250   - videoWriter.write(t);
251   - } else if (t.size() == 1) {
252   - QtUtils::touchDir(QDir(file.path()));
253   - imwrite(file.name.toStdString(), t);
254   - }
255   - }
256   -};
257   -
258   -BR_REGISTER(Format, DefaultFormat)
259   -
260   -/*!
261   - * \ingroup formats
262   - * \brief Reads a NIST LFFS file.
263   - * \author Josh Klontz \cite jklontz
264   - */
265   -class lffsFormat : public Format
266   -{
267   - Q_OBJECT
268   -
269   - Template read() const
270   - {
271   - QByteArray byteArray;
272   - QtUtils::readFile(file.name, byteArray);
273   - return Mat(1, byteArray.size(), CV_8UC1, byteArray.data()).clone();
274   - }
275   -
276   - void write(const Template &t) const
277   - {
278   - QByteArray byteArray((const char*)t.m().data, t.m().total()*t.m().elemSize());
279   - QtUtils::writeFile(file.name, byteArray);
280   - }
281   -};
282   -
283   -BR_REGISTER(Format, lffsFormat)
284   -
285   -/*!
286   - * \ingroup formats
287   - * \brief Reads a NIST BEE similarity matrix.
288   - * \author Josh Klontz \cite jklontz
289   - */
290   -class mtxFormat : public Format
291   -{
292   - Q_OBJECT
293   -
294   - Template read() const
295   - {
296   - QString target, query;
297   - Template result = BEE::readMatrix(file, &target, &query);
298   - result.file.set("Target", target);
299   - result.file.set("Query", query);
300   - return result;
301   - }
302   -
303   - void write(const Template &t) const
304   - {
305   - BEE::writeMatrix(t, file);
306   - }
307   -};
308   -
309   -BR_REGISTER(Format, mtxFormat)
310   -
311   -/*!
312   - * \ingroup formats
313   - * \brief Reads a NIST BEE mask matrix.
314   - * \author Josh Klontz \cite jklontz
315   - */
316   -class maskFormat : public mtxFormat
317   -{
318   - Q_OBJECT
319   -};
320   -
321   -BR_REGISTER(Format, maskFormat)
322   -
323   -/*!
324   - * \ingroup formats
325   - * \brief MATLAB <tt>.mat</tt> format.
326   - * \author Josh Klontz \cite jklontz
327   - * http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf
328   - * \note matFormat is known not to work with compressed matrices
329   - */
330   -class matFormat : public Format
331   -{
332   - Q_OBJECT
333   -
334   - struct Element
335   - {
336   - // It is always best to cast integers to a Qt integer type, such as qint16 or quint32, when reading and writing.
337   - // This ensures that you always know exactly what size integers you are reading and writing, no matter what the
338   - // underlying platform and architecture the application happens to be running on.
339   - // http://qt-project.org/doc/qt-4.8/datastreamformat.html
340   - quint32 type, bytes;
341   - QByteArray data;
342   - Element() : type(0), bytes(0) {}
343   - Element(QDataStream &stream)
344   - : type(0), bytes(0)
345   - {
346   - // Read first 4 bytes into type (32 bit integer),
347   - // specifying the type of data used
348   - if (stream.readRawData((char*)&type, 4) != 4)
349   - qFatal("Unexpected end of file.");
350   -
351   - if (type >= 1 << 16) {
352   - // Small data format
353   - bytes = type;
354   - type = type & 0x0000FFFF;
355   - bytes = bytes >> 16;
356   - } else {
357   - // Regular format
358   - // Read 4 bytes into bytes (32 bit integer),
359   - // specifying the size of the element
360   - if (stream.readRawData((char*)&bytes, 4) != 4)
361   - qFatal("Unexpected end of file.");
362   - }
363   -
364   - // Set the size of data to bytes
365   - data.resize(bytes);
366   -
367   - // Read bytes amount of data from the file into data
368   - if (int(bytes) != stream.readRawData(data.data(), bytes))
369   - qFatal("Unexpected end of file.");
370   -
371   - // Alignment
372   - int skipBytes = (bytes < 4) ? (4 - bytes) : (8 - bytes%8)%8;
373   - if (skipBytes != 0) stream.skipRawData(skipBytes);
374   - }
375   - };
376   -
377   - Template read() const
378   - {
379   - QByteArray byteArray;
380   - QtUtils::readFile(file, byteArray);
381   - QDataStream f(byteArray);
382   -
383   - { // Check header
384   - QByteArray header(128, 0);
385   - f.readRawData(header.data(), 128);
386   - if (!header.startsWith("MATLAB 5.0 MAT-file"))
387   - qFatal("Invalid MAT header.");
388   - }
389   -
390   - Template t(file);
391   -
392   - while (!f.atEnd()) {
393   - Element element(f);
394   -
395   - // miCOMPRESSED
396   - if (element.type == 15) {
397   - // Prepend the number of bytes to element.data
398   - element.data.prepend((char*)&element.bytes, 4); // Qt zlib wrapper requires this to preallocate the buffer
399   - QDataStream uncompressed(qUncompress(element.data));
400   - element = Element(uncompressed);
401   - }
402   -
403   - // miMATRIX
404   - if (element.type == 14) {
405   - QDataStream matrix(element.data);
406   - qint32 rows = 0, columns = 0;
407   - int matrixType = 0;
408   - QByteArray matrixData;
409   - while (!matrix.atEnd()) {
410   - Element subelement(matrix);
411   - if (subelement.type == 5) { // Dimensions array
412   - if (subelement.bytes == 8) {
413   - rows = ((qint32*)subelement.data.data())[0];
414   - columns = ((qint32*)subelement.data.data())[1];
415   - } else {
416   - qWarning("matFormat::read can only handle 2D arrays.");
417   - }
418   - } else if (subelement.type == 7) { //miSINGLE
419   - matrixType = CV_32FC1;
420   - matrixData = subelement.data;
421   - } else if (subelement.type == 9) { //miDOUBLE
422   - matrixType = CV_64FC1;
423   - matrixData = subelement.data;
424   - }
425   - }
426   -
427   - if ((rows > 0) && (columns > 0) && (matrixType != 0) && !matrixData.isEmpty()) {
428   - Mat transposed;
429   - transpose(Mat(columns, rows, matrixType, matrixData.data()), transposed);
430   - t.append(transposed);
431   - }
432   - }
433   - }
434   -
435   - return t;
436   - }
437   -
438   - void write(const Template &t) const
439   - {
440   - QByteArray data;
441   - QDataStream stream(&data, QFile::WriteOnly);
442   -
443   - { // Header
444   - QByteArray header = "MATLAB 5.0 MAT-file; Made with OpenBR | www.openbiometrics.org\n";
445   - QByteArray buffer(116-header.size(), 0);
446   - stream.writeRawData(header.data(), header.size());
447   - stream.writeRawData(buffer.data(), buffer.size());
448   - quint64 subsystem = 0;
449   - quint16 version = 0x0100;
450   - const char *endianness = "IM";
451   - stream.writeRawData((const char*)&subsystem, 8);
452   - stream.writeRawData((const char*)&version, 2);
453   - stream.writeRawData(endianness, 2);
454   - }
455   -
456   - for (int i=0; i<t.size(); i++) {
457   - const Mat &m = t[i];
458   - if (m.channels() != 1) qFatal("Only supports single channel matrices.");
459   -
460   - QByteArray subdata;
461   - QDataStream substream(&subdata, QFile::WriteOnly);
462   -
463   - { // Array Flags
464   - quint32 type = 6;
465   - quint32 bytes = 8;
466   - quint64 arrayClass = 0;
467   - switch (m.type()) {
468   - case CV_64FC1: arrayClass = 6; break;
469   - case CV_32FC1: arrayClass = 7; break;
470   - case CV_8UC1: arrayClass = 8; break;
471   - case CV_8SC1: arrayClass = 9; break;
472   - case CV_16UC1: arrayClass = 10; break;
473   - case CV_16SC1: arrayClass = 11; break;
474   - case CV_32SC1: arrayClass = 12; break;
475   - default: qFatal("Unsupported matrix class.");
476   - }
477   - substream.writeRawData((const char*)&type, 4);
478   - substream.writeRawData((const char*)&bytes, 4);
479   - substream.writeRawData((const char*)&arrayClass, 8);
480   - }
481   -
482   - { // Dimensions Array
483   - quint32 type = 5;
484   - quint32 bytes = 8;
485   - substream.writeRawData((const char*)&type, 4);
486   - substream.writeRawData((const char*)&bytes, 4);
487   - substream.writeRawData((const char*)&m.rows, 4);
488   - substream.writeRawData((const char*)&m.cols, 4);
489   - }
490   -
491   - { // Array Name
492   - QByteArray name(qPrintable(QString("OpenBR_%1").arg(QString::number(i))));
493   - quint32 type = 1;
494   - quint32 bytes = name.size();
495   - QByteArray buffer((8 - bytes%8)%8, 0);
496   - substream.writeRawData((const char*)&type, 4);
497   - substream.writeRawData((const char*)&bytes, 4);
498   - substream.writeRawData(name.data(), name.size());
499   - substream.writeRawData(buffer.data(), buffer.size());
500   - }
501   -
502   - { // Real part
503   - quint32 type = 0;
504   - switch (m.type()) {
505   - case CV_8SC1: type = 1; break;
506   - case CV_8UC1: type = 2; break;
507   - case CV_16SC1: type = 3; break;
508   - case CV_16UC1: type = 4; break;
509   - case CV_32SC1: type = 5; break;
510   - case CV_32FC1: type = 7; break;
511   - case CV_64FC1: type = 9; break;
512   - default: qFatal("Unsupported matrix type.");
513   - }
514   - quint32 bytes = m.elemSize() * m.rows * m.cols;
515   - QByteArray buffer((8 - bytes%8)%8, 0);
516   - Mat transposed;
517   - transpose(m, transposed);
518   - substream.writeRawData((const char*)&type, 4);
519   - substream.writeRawData((const char*)&bytes, 4);
520   - substream.writeRawData((const char*)transposed.data, bytes);
521   - substream.writeRawData(buffer.data(), buffer.size());
522   - }
523   -
524   - { // Matrix
525   - quint32 type = 14;
526   - quint32 bytes = subdata.size();
527   - stream.writeRawData((const char*)&type, 4);
528   - stream.writeRawData((const char*)&bytes, 4);
529   - stream.writeRawData(subdata.data(), subdata.size());
530   - }
531   - }
532   -
533   - QtUtils::writeFile(file, data);
534   - }
535   -};
536   -
537   -BR_REGISTER(Format, matFormat)
538   -
539   -/*!
540   - * \ingroup formats
541   - * \brief Returns an empty matrix.
542   - * \author Josh Klontz \cite jklontz
543   - */
544   -class nullFormat : public Format
545   -{
546   - Q_OBJECT
547   -
548   - Template read() const
549   - {
550   - return Template(file, Mat());
551   - }
552   -
553   - void write(const Template &t) const
554   - {
555   - (void)t;
556   - }
557   -};
558   -
559   -BR_REGISTER(Format, nullFormat)
560   -
561   -/*!
562   - * \ingroup formats
563   - * \brief RAW format
564   - *
565   - * http://www.nist.gov/srd/nistsd27.cfm
566   - * \author Josh Klontz \cite jklontz
567   - */
568   -class rawFormat : public Format
569   -{
570   - Q_OBJECT
571   - static QHash<QString, QHash<QString,QSize> > imageSizes; // QHash<Path, QHash<File,Size> >
572   -
573   - Template read() const
574   - {
575   - QString path = file.path();
576   - if (!imageSizes.contains(path)) {
577   - static QMutex mutex;
578   - QMutexLocker locker(&mutex);
579   -
580   - if (!imageSizes.contains(path)) {
581   - const QString imageSize = path+"/ImageSize.txt";
582   - QStringList lines;
583   - if (QFileInfo(imageSize).exists()) {
584   - lines = QtUtils::readLines(imageSize);
585   - lines.removeFirst(); // Remove header
586   - }
587   -
588   - QHash<QString,QSize> sizes;
589   - QRegExp whiteSpace("\\s+");
590   - foreach (const QString &line, lines) {
591   - QStringList words = line.split(whiteSpace);
592   - if (words.size() != 3) continue;
593   - sizes.insert(words[0], QSize(words[2].toInt(), words[1].toInt()));
594   - }
595   -
596   - imageSizes.insert(path, sizes);
597   - }
598   - }
599   -
600   - QByteArray data;
601   - QtUtils::readFile(file, data);
602   -
603   - QSize size = imageSizes[path][file.baseName()];
604   - if (!size.isValid()) size = QSize(800,768);
605   - if (data.size() != size.width() * size.height())
606   - qFatal("Expected %d*%d bytes, got %d.", size.height(), size.width(), data.size());
607   - return Template(file, Mat(size.height(), size.width(), CV_8UC1, data.data()).clone());
608   - }
609   -
610   - void write(const Template &t) const
611   - {
612   - QtUtils::writeFile(file, QByteArray().setRawData((const char*)t.m().data, t.m().total() * t.m().elemSize()));
613   - }
614   -};
615   -
616   -QHash<QString, QHash<QString,QSize> > rawFormat::imageSizes;
617   -
618   -BR_REGISTER(Format, rawFormat)
619   -
620   -/*!
621   - * \ingroup formats
622   - * \brief Retrieves an image from a webcam.
623   - * \author Josh Klontz \cite jklontz
624   - */
625   -class webcamFormat : public Format
626   -{
627   - Q_OBJECT
628   -
629   - Template read() const
630   - {
631   - static QScopedPointer<VideoCapture> videoCapture;
632   -
633   - if (videoCapture.isNull())
634   - videoCapture.reset(new VideoCapture(0));
635   -
636   - Mat m;
637   - videoCapture->read(m);
638   - return Template(m);
639   - }
640   -
641   - void write(const Template &t) const
642   - {
643   - (void) t;
644   - qFatal("Not supported.");
645   - }
646   -};
647   -
648   -BR_REGISTER(Format, webcamFormat)
649   -
650   -/*!
651   - * \ingroup formats
652   - * \brief Decodes images from Base64 xml
653   - * \author Scott Klum \cite sklum
654   - * \author Josh Klontz \cite jklontz
655   - */
656   -class xmlFormat : public Format
657   -{
658   - Q_OBJECT
659   -
660   - Template read() const
661   - {
662   - Template t;
663   -
664   -#ifndef BR_EMBEDDED
665   - QString fileName = file.get<QString>("path") + file.name;
666   -
667   - QDomDocument doc(fileName);
668   - QFile f(fileName);
669   -
670   - if (!f.open(QIODevice::ReadOnly)) qFatal("Unable to open %s for reading.", qPrintable(file.flat()));
671   - if (!doc.setContent(&f)) qWarning("Unable to parse %s.", qPrintable(file.flat()));
672   - f.close();
673   -
674   - QDomElement docElem = doc.documentElement();
675   - QDomNode subject = docElem.firstChild();
676   - while (!subject.isNull()) {
677   - QDomNode fileNode = subject.firstChild();
678   -
679   - while (!fileNode.isNull()) {
680   - QDomElement e = fileNode.toElement();
681   -
682   - if (e.tagName() == "FORMAL_IMG") {
683   - QByteArray byteArray = QByteArray::fromBase64(qPrintable(e.text()));
684   - Mat m = imdecode(Mat(3, byteArray.size(), CV_8UC3, byteArray.data()), CV_LOAD_IMAGE_COLOR);
685   - if (!m.data) qWarning("xmlFormat::read failed to decode image data.");
686   - t.append(m);
687   - } else if ((e.tagName() == "RELEASE_IMG") ||
688   - (e.tagName() == "PREBOOK_IMG") ||
689   - (e.tagName() == "LPROFILE") ||
690   - (e.tagName() == "RPROFILE")) {
691   - // Ignore these other image fields for now
692   - } else {
693   - t.file.set(e.tagName(), e.text());
694   - }
695   -
696   - fileNode = fileNode.nextSibling();
697   - }
698   - subject = subject.nextSibling();
699   - }
700   -
701   - // Calculate age
702   - if (t.file.contains("DOB")) {
703   - const QDate dob = QDate::fromString(t.file.get<QString>("DOB").left(10), "yyyy-MM-dd");
704   - const QDate current = QDate::currentDate();
705   - int age = current.year() - dob.year();
706   - if (current.month() < dob.month()) age--;
707   - t.file.set("Age", age);
708   - }
709   -#endif // BR_EMBEDDED
710   -
711   - return t;
712   - }
713   -
714   - void write(const Template &t) const
715   - {
716   - QStringList lines;
717   - lines.append("<?xml version=\"1.0\" standalone=\"yes\"?>");
718   - lines.append("<openbr-xml-format>");
719   - lines.append("\t<xml-data>");
720   - foreach (const QString &key, t.file.localKeys()) {
721   - if ((key == "Index") || (key == "Label")) continue;
722   - lines.append("\t\t<"+key+">"+QtUtils::toString(t.file.value(key))+"</"+key+">");
723   - }
724   - std::vector<uchar> data;
725   - imencode(".jpg",t.m(),data);
726   - QByteArray byteArray = QByteArray::fromRawData((const char*)data.data(), data.size());
727   - lines.append("\t\t<FORMAL_IMG>"+byteArray.toBase64()+"</FORMAL_IMG>");
728   - lines.append("\t</xml-data>");
729   - lines.append("</openbr-xml-format>");
730   - QtUtils::writeFile(file, lines);
731   - }
732   -};
733   -
734   -BR_REGISTER(Format, xmlFormat)
735   -
736   -/*!
737   - * \ingroup formats
738   - * \brief Reads in scores or ground truth from a text table.
739   - * \author Josh Klontz \cite jklontz
740   - *
741   - * Example of the format:
742   - * \code
743   - * 2.2531514 FALSE 99990377 99990164
744   - * 2.2549822 TRUE 99990101 99990101
745   - * \endcode
746   - */
747   -class scoresFormat : public Format
748   -{
749   - Q_OBJECT
750   - Q_PROPERTY(int column READ get_column WRITE set_column RESET reset_column STORED false)
751   - Q_PROPERTY(bool groundTruth READ get_groundTruth WRITE set_groundTruth RESET reset_groundTruth STORED false)
752   - Q_PROPERTY(QString delimiter READ get_delimiter WRITE set_delimiter RESET reset_delimiter STORED false)
753   - BR_PROPERTY(int, column, 0)
754   - BR_PROPERTY(bool, groundTruth, false)
755   - BR_PROPERTY(QString, delimiter, "\t")
756   -
757   - Template read() const
758   - {
759   - QFile f(file.name);
760   - if (!f.open(QFile::ReadOnly | QFile::Text))
761   - qFatal("Failed to open %s for reading.", qPrintable(f.fileName()));
762   - QList<float> values;
763   - while (!f.atEnd()) {
764   - const QStringList words = QString(f.readLine()).split(delimiter);
765   - if (words.size() <= column) qFatal("Expected file to have at least %d columns.", column+1);
766   - const QString &word = words[column];
767   - bool ok;
768   - float value = word.toFloat(&ok);
769   - if (!ok) value = (QtUtils::toBool(word) ? BEE::Match : BEE::NonMatch);
770   - values.append(value);
771   - }
772   - if (values.size() == 1)
773   - qWarning("Only one value read, double check file line endings.");
774   - Mat result = OpenCVUtils::toMat(values);
775   - if (groundTruth) result.convertTo(result, CV_8U);
776   - return result;
777   - }
778   -
779   - void write(const Template &t) const
780   - {
781   - (void) t;
782   - qFatal("Not implemented.");
783   - }
784   -};
785   -
786   -BR_REGISTER(Format, scoresFormat)
787   -
788   -/*!
789   - * \ingroup formats
790   - * \brief Reads FBI EBTS transactions.
791   - * \author Scott Klum \cite sklum
792   - * https://www.fbibiospecs.org/ebts.html
793   - */
794   -class ebtsFormat : public Format
795   -{
796   - Q_OBJECT
797   -
798   - struct Field {
799   - int type;
800   - QList<QByteArray> data;
801   - };
802   -
803   - struct Record {
804   - int type;
805   - quint32 bytes;
806   - int position; // Starting position of record
807   -
808   - QHash<int,QList<QByteArray> > fields;
809   - };
810   -
811   - quint32 recordBytes(const QByteArray &byteArray, const float recordType, int from) const
812   - {
813   - bool ok;
814   - quint32 size;
815   -
816   - if (recordType == 4 || recordType == 7) {
817   - // read first four bytes
818   - ok = true;
819   - size = qFromBigEndian<quint32>((const uchar*)byteArray.mid(from,4).constData());
820   - } else {
821   - int index = byteArray.indexOf(QChar(0x1D), from);
822   - size = byteArray.mid(from, index-from).split(':').last().toInt(&ok);
823   - }
824   -
825   - return ok ? size : -1;
826   - }
827   -
828   - void parseRecord(const QByteArray &byteArray, Record &record) const
829   - {
830   - if (record.type == 4 || record.type == 7) {
831   - // Just a binary blob
832   - // Read everything after the first four bytes
833   - // Not current supported
834   - } else {
835   - // Continue reading fields until we get all the data
836   - unsigned int position = record.position;
837   - while (position < record.position + record.bytes) {
838   - int index = byteArray.indexOf(QChar(0x1D), position);
839   - Field field = parseField(byteArray.mid(position, index-position),QChar(0x1F));
840   - if (field.type == 999 ) {
841   - // Data begin after the field identifier and the colon
842   - int dataBegin = byteArray.indexOf(':', position)+1;
843   - field.data.clear();
844   - field.data.append(byteArray.mid(dataBegin, record.bytes-(dataBegin-record.position)));
845   -
846   - // Data fields are always last in the record
847   - record.fields.insert(field.type,field.data);
848   - break;
849   - }
850   - // Advance the position accounting for the separator
851   - position += index-position+1;
852   - record.fields.insert(field.type,field.data);
853   - }
854   - }
855   - }
856   -
857   - Field parseField(const QByteArray &byteArray, const QChar &sep) const
858   - {
859   - bool ok;
860   - Field f;
861   -
862   - QList<QByteArray> data = byteArray.split(':');
863   -
864   - f.type = data.first().split('.').last().toInt(&ok);
865   - f.data = data.last().split(sep.toLatin1());
866   -
867   - return f;
868   - }
869   -
870   - Template read() const
871   - {
872   - QByteArray byteArray;
873   - QtUtils::readFile(file, byteArray);
874   -
875   - Template t;
876   -
877   - Mat m;
878   -
879   - QList<Record> records;
880   -
881   - // Read the type one record (every EBTS file will have one of these)
882   - Record r1;
883   - r1.type = 1;
884   - r1.position = 0;
885   - r1.bytes = recordBytes(byteArray,r1.type,r1.position);
886   -
887   - // The fields in a type 1 record are strictly defined
888   - QList<QByteArray> data = byteArray.mid(r1.position,r1.bytes).split(QChar(0x1D).toLatin1());
889   - foreach (const QByteArray &datum, data) {
890   - Field f = parseField(datum,QChar(0x1F));
891   - r1.fields.insert(f.type,f.data);
892   - }
893   -
894   - records.append(r1);
895   -
896   - // Read the type two record (every EBTS file will have one of these)
897   - Record r2;
898   - r2.type = 2;
899   - r2.position = r1.bytes;
900   - r2.bytes = recordBytes(byteArray,r2.type,r2.position);
901   -
902   - // The fields in a type 2 record are strictly defined
903   - data = byteArray.mid(r2.position,r2.bytes).split(QChar(0x1D).toLatin1());
904   - foreach (const QByteArray &datum, data) {
905   - Field f = parseField(datum,QChar(0x1F));
906   - r2.fields.insert(f.type,f.data);
907   - }
908   -
909   - // Demographics
910   - if (r2.fields.contains(18)) {
911   - QString name = r2.fields.value(18).first();
912   - QStringList names = name.split(',');
913   - t.file.set("FIRSTNAME", names.at(1));
914   - t.file.set("LASTNAME", names.at(0));
915   - }
916   -
917   - if (r2.fields.contains(22)) t.file.set("DOB", r2.fields.value(22).first().toInt());
918   - if (r2.fields.contains(24)) t.file.set("GENDER", QString(r2.fields.value(24).first()));
919   - if (r2.fields.contains(25)) t.file.set("RACE", QString(r2.fields.value(25).first()));
920   -
921   - if (t.file.contains("DOB")) {
922   - const QDate dob = QDate::fromString(t.file.get<QString>("DOB"), "yyyyMMdd");
923   - const QDate current = QDate::currentDate();
924   - int age = current.year() - dob.year();
925   - if (current.month() < dob.month()) age--;
926   - t.file.set("Age", age);
927   - }
928   -
929   - records.append(r2);
930   -
931   - // The third field of the first record contains informations about all the remaining records in the transaction
932   - // We don't care about the first two and the final items
933   - QList<QByteArray> recordTypes = r1.fields.value(3);
934   - for (int i=2; i<recordTypes.size()-1; i++) {
935   - // The first two bytes indicate the record index (and we don't want the separator), but we only care about the type
936   - QByteArray recordType = recordTypes[i].mid(3);
937   - Record r;
938   - r.type = recordType.toInt();
939   - records.append(r);
940   - }
941   -
942   - QList<int> frontalIdxs;
943   - int position = r1.bytes + r2.bytes;
944   - for (int i=2; i<records.size(); i++) {
945   - records[i].position = position;
946   - records[i].bytes = recordBytes(byteArray,records[i].type,position);
947   -
948   - parseRecord(byteArray, records[i]);
949   - if (records[i].type == 10) frontalIdxs.append(i);
950   - position += records[i].bytes;
951   - }
952   -
953   - if (!frontalIdxs.isEmpty()) {
954   - // We use the first type 10 record to get the frontal
955   - QByteArray frontal = records[frontalIdxs.first()].fields.value(999).first();
956   - m = imdecode(Mat(3, frontal.size(), CV_8UC3, frontal.data()), CV_LOAD_IMAGE_COLOR);
957   - if (!m.data) qWarning("ebtsFormat::read failed to decode image data.");
958   - t.m() = m;
959   - } else qWarning("ebtsFormat::cannot find image data within file.");
960   -
961   - return t;
962   - }
963   -
964   - void write(const Template &t) const
965   - {
966   - (void) t;
967   - qFatal("Writing EBTS files is not supported.");
968   - }
969   -};
970   -
971   -BR_REGISTER(Format, ebtsFormat)
972   -
973   -} // namespace br
974   -
975   -#include "format.moc"
openbr/plugins/format/binary.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/qtutils.h>
  19 +
  20 +using namespace cv;
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +/*!
  26 + * \ingroup formats
  27 + * \brief A simple binary matrix format.
  28 + * \author Josh Klontz \cite jklontz
  29 + * First 4 bytes indicate the number of rows.
  30 + * Second 4 bytes indicate the number of columns.
  31 + * The rest of the bytes are 32-bit floating data elements in row-major order.
  32 + */
  33 +class binaryFormat : public Format
  34 +{
  35 + Q_OBJECT
  36 + Q_PROPERTY(bool raw READ get_raw WRITE set_raw RESET reset_raw STORED false)
  37 + BR_PROPERTY(bool, raw, false)
  38 +
  39 + Template read() const
  40 + {
  41 + QByteArray data;
  42 + QtUtils::readFile(file, data);
  43 + if (raw) {
  44 + return Template(file, Mat(1, data.size(), CV_8UC1, data.data()).clone());
  45 + } else {
  46 + return Template(file, Mat(((quint32*)data.data())[0],
  47 + ((quint32*)data.data())[1],
  48 + CV_32FC1,
  49 + data.data()+8).clone());
  50 + }
  51 + }
  52 +
  53 + void write(const Template &t) const
  54 + {
  55 + QFile f(file);
  56 + QtUtils::touchDir(f);
  57 + if (!f.open(QFile::WriteOnly))
  58 + qFatal("Failed to open %s for writing.", qPrintable(file));
  59 +
  60 + Mat m;
  61 + if (!raw) {
  62 + if (t.m().type() != CV_32FC1)
  63 + t.m().convertTo(m, CV_32F);
  64 + else m = t.m();
  65 +
  66 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
  67 +
  68 + f.write((const char *) &m.rows, 4);
  69 + f.write((const char *) &m.cols, 4);
  70 + }
  71 + else m = t.m();
  72 +
  73 + qint64 rowSize = m.cols * sizeof(float);
  74 + for (int i=0; i < m.rows; i++)
  75 + {
  76 + f.write((const char *) m.row(i).data, rowSize);
  77 + }
  78 + f.close();
  79 + }
  80 +};
  81 +
  82 +BR_REGISTER(Format, binaryFormat)
  83 +
  84 +} // namespace br
  85 +
  86 +#include "format/binary.moc"
... ...
openbr/plugins/format/csv.cpp 0 → 100644
  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 <QRegularExpression>
  18 +
  19 +#include <openbr/plugins/openbr_internal.h>
  20 +#include <openbr/core/opencvutils.h>
  21 +#include <openbr/core/qtutils.h>
  22 +
  23 +using namespace cv;
  24 +
  25 +namespace br
  26 +{
  27 +
  28 +/*!
  29 + * \ingroup formats
  30 + * \brief Reads a comma separated value file.
  31 + * \author Josh Klontz \cite jklontz
  32 + */
  33 +class csvFormat : public Format
  34 +{
  35 + Q_OBJECT
  36 +
  37 + Template read() const
  38 + {
  39 + QFile f(file.name);
  40 + f.open(QFile::ReadOnly);
  41 + QStringList lines(QString(f.readAll()).split(QRegularExpression("[\n|\r\n|\r]"), QString::SkipEmptyParts));
  42 + f.close();
  43 +
  44 + bool isUChar = true;
  45 + QList< QList<float> > valsList;
  46 + foreach (const QString &line, lines) {
  47 + QList<float> vals;
  48 + foreach (const QString &word, line.split(QRegExp(" *, *"), QString::SkipEmptyParts)) {
  49 + bool ok;
  50 + const float val = word.toFloat(&ok);
  51 + vals.append(val);
  52 + isUChar = isUChar && (val == float(uchar(val)));
  53 + }
  54 + if (!vals.isEmpty())
  55 + valsList.append(vals);
  56 + }
  57 +
  58 + Mat m(valsList.size(), valsList[0].size(), CV_32FC1);
  59 + for (int i=0; i<valsList.size(); i++)
  60 + for (int j=0; j<valsList[i].size(); j++)
  61 + m.at<float>(i,j) = valsList[i][j];
  62 +
  63 + if (isUChar) m.convertTo(m, CV_8U);
  64 + return Template(m);
  65 + }
  66 +
  67 + void write(const Template &t) const
  68 + {
  69 + const Mat &m = t.m();
  70 + if (t.size() != 1) qFatal("Only supports single matrix templates.");
  71 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
  72 +
  73 + QStringList lines; lines.reserve(m.rows);
  74 + for (int r=0; r<m.rows; r++) {
  75 + QStringList elements; elements.reserve(m.cols);
  76 + for (int c=0; c<m.cols; c++)
  77 + elements.append(OpenCVUtils::elemToString(m, r, c));
  78 + lines.append(elements.join(","));
  79 + }
  80 +
  81 + QtUtils::writeFile(file, lines);
  82 + }
  83 +};
  84 +
  85 +BR_REGISTER(Format, csvFormat)
  86 +
  87 +} // namespace br
  88 +
  89 +#include "format/csv.moc"
... ...
openbr/plugins/format/ebts.cpp 0 → 100644
  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 <QtEndian>
  18 +#include <opencv2/highgui/highgui.hpp>
  19 +
  20 +#include <openbr/plugins/openbr_internal.h>
  21 +#include <openbr/core/qtutils.h>
  22 +
  23 +using namespace cv;
  24 +
  25 +namespace br
  26 +{
  27 +
  28 +/*!
  29 + * \ingroup formats
  30 + * \brief Reads FBI EBTS transactions.
  31 + * \author Scott Klum \cite sklum
  32 + * https://www.fbibiospecs.org/ebts.html
  33 + */
  34 +class ebtsFormat : public Format
  35 +{
  36 + Q_OBJECT
  37 +
  38 + struct Field {
  39 + int type;
  40 + QList<QByteArray> data;
  41 + };
  42 +
  43 + struct Record {
  44 + int type;
  45 + quint32 bytes;
  46 + int position; // Starting position of record
  47 +
  48 + QHash<int,QList<QByteArray> > fields;
  49 + };
  50 +
  51 + quint32 recordBytes(const QByteArray &byteArray, const float recordType, int from) const
  52 + {
  53 + bool ok;
  54 + quint32 size;
  55 +
  56 + if (recordType == 4 || recordType == 7) {
  57 + // read first four bytes
  58 + ok = true;
  59 + size = qFromBigEndian<quint32>((const uchar*)byteArray.mid(from,4).constData());
  60 + } else {
  61 + int index = byteArray.indexOf(QChar(0x1D), from);
  62 + size = byteArray.mid(from, index-from).split(':').last().toInt(&ok);
  63 + }
  64 +
  65 + return ok ? size : -1;
  66 + }
  67 +
  68 + void parseRecord(const QByteArray &byteArray, Record &record) const
  69 + {
  70 + if (record.type == 4 || record.type == 7) {
  71 + // Just a binary blob
  72 + // Read everything after the first four bytes
  73 + // Not current supported
  74 + } else {
  75 + // Continue reading fields until we get all the data
  76 + unsigned int position = record.position;
  77 + while (position < record.position + record.bytes) {
  78 + int index = byteArray.indexOf(QChar(0x1D), position);
  79 + Field field = parseField(byteArray.mid(position, index-position),QChar(0x1F));
  80 + if (field.type == 999 ) {
  81 + // Data begin after the field identifier and the colon
  82 + int dataBegin = byteArray.indexOf(':', position)+1;
  83 + field.data.clear();
  84 + field.data.append(byteArray.mid(dataBegin, record.bytes-(dataBegin-record.position)));
  85 +
  86 + // Data fields are always last in the record
  87 + record.fields.insert(field.type,field.data);
  88 + break;
  89 + }
  90 + // Advance the position accounting for the separator
  91 + position += index-position+1;
  92 + record.fields.insert(field.type,field.data);
  93 + }
  94 + }
  95 + }
  96 +
  97 + Field parseField(const QByteArray &byteArray, const QChar &sep) const
  98 + {
  99 + bool ok;
  100 + Field f;
  101 +
  102 + QList<QByteArray> data = byteArray.split(':');
  103 +
  104 + f.type = data.first().split('.').last().toInt(&ok);
  105 + f.data = data.last().split(sep.toLatin1());
  106 +
  107 + return f;
  108 + }
  109 +
  110 + Template read() const
  111 + {
  112 + QByteArray byteArray;
  113 + QtUtils::readFile(file, byteArray);
  114 +
  115 + Template t;
  116 +
  117 + Mat m;
  118 +
  119 + QList<Record> records;
  120 +
  121 + // Read the type one record (every EBTS file will have one of these)
  122 + Record r1;
  123 + r1.type = 1;
  124 + r1.position = 0;
  125 + r1.bytes = recordBytes(byteArray,r1.type,r1.position);
  126 +
  127 + // The fields in a type 1 record are strictly defined
  128 + QList<QByteArray> data = byteArray.mid(r1.position,r1.bytes).split(QChar(0x1D).toLatin1());
  129 + foreach (const QByteArray &datum, data) {
  130 + Field f = parseField(datum,QChar(0x1F));
  131 + r1.fields.insert(f.type,f.data);
  132 + }
  133 +
  134 + records.append(r1);
  135 +
  136 + // Read the type two record (every EBTS file will have one of these)
  137 + Record r2;
  138 + r2.type = 2;
  139 + r2.position = r1.bytes;
  140 + r2.bytes = recordBytes(byteArray,r2.type,r2.position);
  141 +
  142 + // The fields in a type 2 record are strictly defined
  143 + data = byteArray.mid(r2.position,r2.bytes).split(QChar(0x1D).toLatin1());
  144 + foreach (const QByteArray &datum, data) {
  145 + Field f = parseField(datum,QChar(0x1F));
  146 + r2.fields.insert(f.type,f.data);
  147 + }
  148 +
  149 + // Demographics
  150 + if (r2.fields.contains(18)) {
  151 + QString name = r2.fields.value(18).first();
  152 + QStringList names = name.split(',');
  153 + t.file.set("FIRSTNAME", names.at(1));
  154 + t.file.set("LASTNAME", names.at(0));
  155 + }
  156 +
  157 + if (r2.fields.contains(22)) t.file.set("DOB", r2.fields.value(22).first().toInt());
  158 + if (r2.fields.contains(24)) t.file.set("GENDER", QString(r2.fields.value(24).first()));
  159 + if (r2.fields.contains(25)) t.file.set("RACE", QString(r2.fields.value(25).first()));
  160 +
  161 + if (t.file.contains("DOB")) {
  162 + const QDate dob = QDate::fromString(t.file.get<QString>("DOB"), "yyyyMMdd");
  163 + const QDate current = QDate::currentDate();
  164 + int age = current.year() - dob.year();
  165 + if (current.month() < dob.month()) age--;
  166 + t.file.set("Age", age);
  167 + }
  168 +
  169 + records.append(r2);
  170 +
  171 + // The third field of the first record contains informations about all the remaining records in the transaction
  172 + // We don't care about the first two and the final items
  173 + QList<QByteArray> recordTypes = r1.fields.value(3);
  174 + for (int i=2; i<recordTypes.size()-1; i++) {
  175 + // The first two bytes indicate the record index (and we don't want the separator), but we only care about the type
  176 + QByteArray recordType = recordTypes[i].mid(3);
  177 + Record r;
  178 + r.type = recordType.toInt();
  179 + records.append(r);
  180 + }
  181 +
  182 + QList<int> frontalIdxs;
  183 + int position = r1.bytes + r2.bytes;
  184 + for (int i=2; i<records.size(); i++) {
  185 + records[i].position = position;
  186 + records[i].bytes = recordBytes(byteArray,records[i].type,position);
  187 +
  188 + parseRecord(byteArray, records[i]);
  189 + if (records[i].type == 10) frontalIdxs.append(i);
  190 + position += records[i].bytes;
  191 + }
  192 +
  193 + if (!frontalIdxs.isEmpty()) {
  194 + // We use the first type 10 record to get the frontal
  195 + QByteArray frontal = records[frontalIdxs.first()].fields.value(999).first();
  196 + m = imdecode(Mat(3, frontal.size(), CV_8UC3, frontal.data()), CV_LOAD_IMAGE_COLOR);
  197 + if (!m.data) qWarning("ebtsFormat::read failed to decode image data.");
  198 + t.m() = m;
  199 + } else qWarning("ebtsFormat::cannot find image data within file.");
  200 +
  201 + return t;
  202 + }
  203 +
  204 + void write(const Template &t) const
  205 + {
  206 + (void) t;
  207 + qFatal("Writing EBTS files is not supported.");
  208 + }
  209 +};
  210 +
  211 +BR_REGISTER(Format, ebtsFormat)
  212 +
  213 +} // namespace br
  214 +
  215 +#include "format/ebts.moc"
... ...
openbr/plugins/format/lffs.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/qtutils.h>
  19 +
  20 +using namespace cv;
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +/*!
  26 + * \ingroup formats
  27 + * \brief Reads a NIST LFFS file.
  28 + * \author Josh Klontz \cite jklontz
  29 + */
  30 +class lffsFormat : public Format
  31 +{
  32 + Q_OBJECT
  33 +
  34 + Template read() const
  35 + {
  36 + QByteArray byteArray;
  37 + QtUtils::readFile(file.name, byteArray);
  38 + return Mat(1, byteArray.size(), CV_8UC1, byteArray.data()).clone();
  39 + }
  40 +
  41 + void write(const Template &t) const
  42 + {
  43 + QByteArray byteArray((const char*)t.m().data, t.m().total()*t.m().elemSize());
  44 + QtUtils::writeFile(file.name, byteArray);
  45 + }
  46 +};
  47 +
  48 +BR_REGISTER(Format, lffsFormat)
  49 +
  50 +} // namespace br
  51 +
  52 +#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 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/qtutils.h>
  19 +
  20 +using namespace cv;
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +/*!
  26 + * \ingroup formats
  27 + * \brief MATLAB <tt>.mat</tt> format.
  28 + * \author Josh Klontz \cite jklontz
  29 + * http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf
  30 + * \note matFormat is known not to work with compressed matrices
  31 + */
  32 +class matFormat : public Format
  33 +{
  34 + Q_OBJECT
  35 +
  36 + struct Element
  37 + {
  38 + // It is always best to cast integers to a Qt integer type, such as qint16 or quint32, when reading and writing.
  39 + // This ensures that you always know exactly what size integers you are reading and writing, no matter what the
  40 + // underlying platform and architecture the application happens to be running on.
  41 + // http://qt-project.org/doc/qt-4.8/datastreamformat.html
  42 + quint32 type, bytes;
  43 + QByteArray data;
  44 + Element() : type(0), bytes(0) {}
  45 + Element(QDataStream &stream)
  46 + : type(0), bytes(0)
  47 + {
  48 + // Read first 4 bytes into type (32 bit integer),
  49 + // specifying the type of data used
  50 + if (stream.readRawData((char*)&type, 4) != 4)
  51 + qFatal("Unexpected end of file.");
  52 +
  53 + if (type >= 1 << 16) {
  54 + // Small data format
  55 + bytes = type;
  56 + type = type & 0x0000FFFF;
  57 + bytes = bytes >> 16;
  58 + } else {
  59 + // Regular format
  60 + // Read 4 bytes into bytes (32 bit integer),
  61 + // specifying the size of the element
  62 + if (stream.readRawData((char*)&bytes, 4) != 4)
  63 + qFatal("Unexpected end of file.");
  64 + }
  65 +
  66 + // Set the size of data to bytes
  67 + data.resize(bytes);
  68 +
  69 + // Read bytes amount of data from the file into data
  70 + if (int(bytes) != stream.readRawData(data.data(), bytes))
  71 + qFatal("Unexpected end of file.");
  72 +
  73 + // Alignment
  74 + int skipBytes = (bytes < 4) ? (4 - bytes) : (8 - bytes%8)%8;
  75 + if (skipBytes != 0) stream.skipRawData(skipBytes);
  76 + }
  77 + };
  78 +
  79 + Template read() const
  80 + {
  81 + QByteArray byteArray;
  82 + QtUtils::readFile(file, byteArray);
  83 + QDataStream f(byteArray);
  84 +
  85 + { // Check header
  86 + QByteArray header(128, 0);
  87 + f.readRawData(header.data(), 128);
  88 + if (!header.startsWith("MATLAB 5.0 MAT-file"))
  89 + qFatal("Invalid MAT header.");
  90 + }
  91 +
  92 + Template t(file);
  93 +
  94 + while (!f.atEnd()) {
  95 + Element element(f);
  96 +
  97 + // miCOMPRESSED
  98 + if (element.type == 15) {
  99 + // Prepend the number of bytes to element.data
  100 + element.data.prepend((char*)&element.bytes, 4); // Qt zlib wrapper requires this to preallocate the buffer
  101 + QDataStream uncompressed(qUncompress(element.data));
  102 + element = Element(uncompressed);
  103 + }
  104 +
  105 + // miMATRIX
  106 + if (element.type == 14) {
  107 + QDataStream matrix(element.data);
  108 + qint32 rows = 0, columns = 0;
  109 + int matrixType = 0;
  110 + QByteArray matrixData;
  111 + while (!matrix.atEnd()) {
  112 + Element subelement(matrix);
  113 + if (subelement.type == 5) { // Dimensions array
  114 + if (subelement.bytes == 8) {
  115 + rows = ((qint32*)subelement.data.data())[0];
  116 + columns = ((qint32*)subelement.data.data())[1];
  117 + } else {
  118 + qWarning("matFormat::read can only handle 2D arrays.");
  119 + }
  120 + } else if (subelement.type == 7) { //miSINGLE
  121 + matrixType = CV_32FC1;
  122 + matrixData = subelement.data;
  123 + } else if (subelement.type == 9) { //miDOUBLE
  124 + matrixType = CV_64FC1;
  125 + matrixData = subelement.data;
  126 + }
  127 + }
  128 +
  129 + if ((rows > 0) && (columns > 0) && (matrixType != 0) && !matrixData.isEmpty()) {
  130 + Mat transposed;
  131 + transpose(Mat(columns, rows, matrixType, matrixData.data()), transposed);
  132 + t.append(transposed);
  133 + }
  134 + }
  135 + }
  136 +
  137 + return t;
  138 + }
  139 +
  140 + void write(const Template &t) const
  141 + {
  142 + QByteArray data;
  143 + QDataStream stream(&data, QFile::WriteOnly);
  144 +
  145 + { // Header
  146 + QByteArray header = "MATLAB 5.0 MAT-file; Made with OpenBR | www.openbiometrics.org\n";
  147 + QByteArray buffer(116-header.size(), 0);
  148 + stream.writeRawData(header.data(), header.size());
  149 + stream.writeRawData(buffer.data(), buffer.size());
  150 + quint64 subsystem = 0;
  151 + quint16 version = 0x0100;
  152 + const char *endianness = "IM";
  153 + stream.writeRawData((const char*)&subsystem, 8);
  154 + stream.writeRawData((const char*)&version, 2);
  155 + stream.writeRawData(endianness, 2);
  156 + }
  157 +
  158 + for (int i=0; i<t.size(); i++) {
  159 + const Mat &m = t[i];
  160 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
  161 +
  162 + QByteArray subdata;
  163 + QDataStream substream(&subdata, QFile::WriteOnly);
  164 +
  165 + { // Array Flags
  166 + quint32 type = 6;
  167 + quint32 bytes = 8;
  168 + quint64 arrayClass = 0;
  169 + switch (m.type()) {
  170 + case CV_64FC1: arrayClass = 6; break;
  171 + case CV_32FC1: arrayClass = 7; break;
  172 + case CV_8UC1: arrayClass = 8; break;
  173 + case CV_8SC1: arrayClass = 9; break;
  174 + case CV_16UC1: arrayClass = 10; break;
  175 + case CV_16SC1: arrayClass = 11; break;
  176 + case CV_32SC1: arrayClass = 12; break;
  177 + default: qFatal("Unsupported matrix class.");
  178 + }
  179 + substream.writeRawData((const char*)&type, 4);
  180 + substream.writeRawData((const char*)&bytes, 4);
  181 + substream.writeRawData((const char*)&arrayClass, 8);
  182 + }
  183 +
  184 + { // Dimensions Array
  185 + quint32 type = 5;
  186 + quint32 bytes = 8;
  187 + substream.writeRawData((const char*)&type, 4);
  188 + substream.writeRawData((const char*)&bytes, 4);
  189 + substream.writeRawData((const char*)&m.rows, 4);
  190 + substream.writeRawData((const char*)&m.cols, 4);
  191 + }
  192 +
  193 + { // Array Name
  194 + QByteArray name(qPrintable(QString("OpenBR_%1").arg(QString::number(i))));
  195 + quint32 type = 1;
  196 + quint32 bytes = name.size();
  197 + QByteArray buffer((8 - bytes%8)%8, 0);
  198 + substream.writeRawData((const char*)&type, 4);
  199 + substream.writeRawData((const char*)&bytes, 4);
  200 + substream.writeRawData(name.data(), name.size());
  201 + substream.writeRawData(buffer.data(), buffer.size());
  202 + }
  203 +
  204 + { // Real part
  205 + quint32 type = 0;
  206 + switch (m.type()) {
  207 + case CV_8SC1: type = 1; break;
  208 + case CV_8UC1: type = 2; break;
  209 + case CV_16SC1: type = 3; break;
  210 + case CV_16UC1: type = 4; break;
  211 + case CV_32SC1: type = 5; break;
  212 + case CV_32FC1: type = 7; break;
  213 + case CV_64FC1: type = 9; break;
  214 + default: qFatal("Unsupported matrix type.");
  215 + }
  216 + quint32 bytes = m.elemSize() * m.rows * m.cols;
  217 + QByteArray buffer((8 - bytes%8)%8, 0);
  218 + Mat transposed;
  219 + transpose(m, transposed);
  220 + substream.writeRawData((const char*)&type, 4);
  221 + substream.writeRawData((const char*)&bytes, 4);
  222 + substream.writeRawData((const char*)transposed.data, bytes);
  223 + substream.writeRawData(buffer.data(), buffer.size());
  224 + }
  225 +
  226 + { // Matrix
  227 + quint32 type = 14;
  228 + quint32 bytes = subdata.size();
  229 + stream.writeRawData((const char*)&type, 4);
  230 + stream.writeRawData((const char*)&bytes, 4);
  231 + stream.writeRawData(subdata.data(), subdata.size());
  232 + }
  233 + }
  234 +
  235 + QtUtils::writeFile(file, data);
  236 + }
  237 +};
  238 +
  239 +BR_REGISTER(Format, matFormat)
  240 +
  241 +} // namespace br
  242 +
  243 +#include "format/mat.moc"
... ...
openbr/plugins/format/mtx.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/bee.h>
  19 +
  20 +namespace br
  21 +{
  22 +
  23 +/*!
  24 + * \ingroup formats
  25 + * \brief Reads a NIST BEE similarity matrix.
  26 + * \author Josh Klontz \cite jklontz
  27 + */
  28 +class mtxFormat : public Format
  29 +{
  30 + Q_OBJECT
  31 +
  32 + Template read() const
  33 + {
  34 + QString target, query;
  35 + Template result = BEE::readMatrix(file, &target, &query);
  36 + result.file.set("Target", target);
  37 + result.file.set("Query", query);
  38 + return result;
  39 + }
  40 +
  41 + void write(const Template &t) const
  42 + {
  43 + BEE::writeMatrix(t, file);
  44 + }
  45 +};
  46 +
  47 +BR_REGISTER(Format, mtxFormat)
  48 +
  49 +/*!
  50 + * \ingroup formats
  51 + * \brief Reads a NIST BEE mask matrix.
  52 + * \author Josh Klontz \cite jklontz
  53 + */
  54 +class maskFormat : public mtxFormat
  55 +{
  56 + Q_OBJECT
  57 +};
  58 +
  59 +BR_REGISTER(Format, maskFormat)
  60 +
  61 +} // namespace br
  62 +
  63 +#include "format/mtx.moc"
... ...
openbr/plugins/format/null.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +
  19 +namespace br
  20 +{
  21 +
  22 +/*!
  23 + * \ingroup formats
  24 + * \brief Returns an empty matrix.
  25 + * \author Josh Klontz \cite jklontz
  26 + */
  27 +class nullFormat : public Format
  28 +{
  29 + Q_OBJECT
  30 +
  31 + Template read() const
  32 + {
  33 + return Template(file, cv::Mat());
  34 + }
  35 +
  36 + void write(const Template &t) const
  37 + {
  38 + (void)t;
  39 + }
  40 +};
  41 +
  42 +BR_REGISTER(Format, nullFormat)
  43 +
  44 +} // namespace br
  45 +
  46 +#include "format/null.moc"
... ...
openbr/plugins/format/post.cpp 0 → 100644
  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 <QTcpSocket>
  18 +#include <opencv2/highgui/highgui.hpp>
  19 +
  20 +#include <openbr/plugins/openbr_internal.h>
  21 +#include <http_parser.h>
  22 +
  23 +using namespace cv;
  24 +
  25 +namespace br
  26 +{
  27 +
  28 +/*!
  29 + * \ingroup formats
  30 + * \brief Handle POST requests
  31 + * \author Josh Klontz \cite jklontz
  32 + */
  33 +class postFormat : public Format
  34 +{
  35 + Q_OBJECT
  36 +
  37 + Template read() const
  38 + {
  39 + Template t(file);
  40 +
  41 + // Read from socket
  42 + QTcpSocket *socket = new QTcpSocket();
  43 + socket->setSocketDescriptor(file.get<qintptr>("socketDescriptor"));
  44 + socket->write("HTTP/1.1 200 OK\r\n"
  45 + "Content-Type: text/html; charset=UTF-8\r\n\r\n"
  46 + "Hello World!\r\n");
  47 + socket->waitForBytesWritten();
  48 + socket->waitForReadyRead();
  49 + QByteArray data = socket->readAll();
  50 + socket->close();
  51 + delete socket;
  52 +
  53 + qDebug() << data;
  54 +
  55 + // Parse data
  56 + http_parser_settings settings;
  57 + settings.on_body = bodyCallback;
  58 + settings.on_headers_complete = NULL;
  59 + settings.on_header_field = NULL;
  60 + settings.on_header_value = NULL;
  61 + settings.on_message_begin = NULL;
  62 + settings.on_message_complete = NULL;
  63 + settings.on_status_complete = NULL;
  64 + settings.on_url = NULL;
  65 +
  66 + {
  67 + QByteArray body;
  68 + http_parser parser;
  69 + http_parser_init(&parser, HTTP_REQUEST);
  70 + parser.data = &body;
  71 + http_parser_execute(&parser, &settings, data.data(), data.size());
  72 + data = body;
  73 + }
  74 +
  75 + data.prepend("HTTP/1.1 200 OK");
  76 + QByteArray body;
  77 + { // Image data is two layers deep
  78 + http_parser parser;
  79 + http_parser_init(&parser, HTTP_BOTH);
  80 + parser.data = &body;
  81 + http_parser_execute(&parser, &settings, data.data(), data.size());
  82 + }
  83 +
  84 + t.append(imdecode(Mat(1, body.size(), CV_8UC1, body.data()), 1));
  85 + return t;
  86 + }
  87 +
  88 + void write(const Template &t) const
  89 + {
  90 + (void) t;
  91 + qFatal("Not supported!");
  92 + }
  93 +
  94 + static int bodyCallback(http_parser *parser, const char *at, size_t length)
  95 + {
  96 + QByteArray *byteArray = (QByteArray*)parser->data;
  97 + *byteArray = QByteArray(at, length);
  98 + return 0;
  99 + }
  100 +};
  101 +
  102 +BR_REGISTER(Format, postFormat)
  103 +
  104 +} // namespace br
  105 +
  106 +#include "format/post.moc"
... ...
openbr/plugins/format/raw.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/qtutils.h>
  19 +
  20 +using namespace cv;
  21 +
  22 +namespace br
  23 +{
  24 +
  25 +/*!
  26 + * \ingroup formats
  27 + * \brief RAW format
  28 + *
  29 + * http://www.nist.gov/srd/nistsd27.cfm
  30 + * \author Josh Klontz \cite jklontz
  31 + */
  32 +class rawFormat : public Format
  33 +{
  34 + Q_OBJECT
  35 + static QHash<QString, QHash<QString,QSize> > imageSizes; // QHash<Path, QHash<File,Size> >
  36 +
  37 + Template read() const
  38 + {
  39 + QString path = file.path();
  40 + if (!imageSizes.contains(path)) {
  41 + static QMutex mutex;
  42 + QMutexLocker locker(&mutex);
  43 +
  44 + if (!imageSizes.contains(path)) {
  45 + const QString imageSize = path+"/ImageSize.txt";
  46 + QStringList lines;
  47 + if (QFileInfo(imageSize).exists()) {
  48 + lines = QtUtils::readLines(imageSize);
  49 + lines.removeFirst(); // Remove header
  50 + }
  51 +
  52 + QHash<QString,QSize> sizes;
  53 + QRegExp whiteSpace("\\s+");
  54 + foreach (const QString &line, lines) {
  55 + QStringList words = line.split(whiteSpace);
  56 + if (words.size() != 3) continue;
  57 + sizes.insert(words[0], QSize(words[2].toInt(), words[1].toInt()));
  58 + }
  59 +
  60 + imageSizes.insert(path, sizes);
  61 + }
  62 + }
  63 +
  64 + QByteArray data;
  65 + QtUtils::readFile(file, data);
  66 +
  67 + QSize size = imageSizes[path][file.baseName()];
  68 + if (!size.isValid()) size = QSize(800,768);
  69 + if (data.size() != size.width() * size.height())
  70 + qFatal("Expected %d*%d bytes, got %d.", size.height(), size.width(), data.size());
  71 + return Template(file, Mat(size.height(), size.width(), CV_8UC1, data.data()).clone());
  72 + }
  73 +
  74 + void write(const Template &t) const
  75 + {
  76 + QtUtils::writeFile(file, QByteArray().setRawData((const char*)t.m().data, t.m().total() * t.m().elemSize()));
  77 + }
  78 +};
  79 +
  80 +QHash<QString, QHash<QString,QSize> > rawFormat::imageSizes;
  81 +
  82 +BR_REGISTER(Format, rawFormat)
  83 +
  84 +} // namespace br
  85 +
  86 +#include "format/raw.moc"
... ...
openbr/plugins/format/scores.cpp 0 → 100644
  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 <openbr/plugins/openbr_internal.h>
  18 +#include <openbr/core/qtutils.h>
  19 +#include <openbr/core/opencvutils.h>
  20 +#include <openbr/core/bee.h>
  21 +
  22 +using namespace cv;
  23 +
  24 +namespace br
  25 +{
  26 +
  27 +/*!
  28 + * \ingroup formats
  29 + * \brief Reads in scores or ground truth from a text table.
  30 + * \author Josh Klontz \cite jklontz
  31 + *
  32 + * Example of the format:
  33 + * \code
  34 + * 2.2531514 FALSE 99990377 99990164
  35 + * 2.2549822 TRUE 99990101 99990101
  36 + * \endcode
  37 + */
  38 +class scoresFormat : public Format
  39 +{
  40 + Q_OBJECT
  41 + Q_PROPERTY(int column READ get_column WRITE set_column RESET reset_column STORED false)
  42 + Q_PROPERTY(bool groundTruth READ get_groundTruth WRITE set_groundTruth RESET reset_groundTruth STORED false)
  43 + Q_PROPERTY(QString delimiter READ get_delimiter WRITE set_delimiter RESET reset_delimiter STORED false)
  44 + BR_PROPERTY(int, column, 0)
  45 + BR_PROPERTY(bool, groundTruth, false)
  46 + BR_PROPERTY(QString, delimiter, "\t")
  47 +
  48 + Template read() const
  49 + {
  50 + QFile f(file.name);
  51 + if (!f.open(QFile::ReadOnly | QFile::Text))
  52 + qFatal("Failed to open %s for reading.", qPrintable(f.fileName()));
  53 + QList<float> values;
  54 + while (!f.atEnd()) {
  55 + const QStringList words = QString(f.readLine()).split(delimiter);
  56 + if (words.size() <= column) qFatal("Expected file to have at least %d columns.", column+1);
  57 + const QString &word = words[column];
  58 + bool ok;
  59 + float value = word.toFloat(&ok);
  60 + if (!ok) value = (QtUtils::toBool(word) ? BEE::Match : BEE::NonMatch);
  61 + values.append(value);
  62 + }
  63 + if (values.size() == 1)
  64 + qWarning("Only one value read, double check file line endings.");
  65 + Mat result = OpenCVUtils::toMat(values);
  66 + if (groundTruth) result.convertTo(result, CV_8U);
  67 + return result;
  68 + }
  69 +
  70 + void write(const Template &t) const
  71 + {
  72 + (void) t;
  73 + qFatal("Not implemented.");
  74 + }
  75 +};
  76 +
  77 +BR_REGISTER(Format, scoresFormat)
  78 +
  79 +} // namespace br
  80 +
  81 +#include "format/scores.moc"
... ...