Commit e4d4166cfff76ae8a0241253713a8ad3c5f2d412
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
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
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
openbr/plugins/pp4.cpp renamed to openbr/plugins/classification/pp4.cpp
openbr/plugins/pp5.cpp renamed to openbr/plugins/classification/pp5.cpp
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 "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 "Use Java Code") |
| 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 "Build with LibLinear") |
| 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 "Build with Likely") |
| 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 "Build with Neurotec Biometric 4") |
| 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 "Build with PittPatt 4") |
| 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 "Build with PittPatt 5") |
| 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
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
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" | ... | ... |