Commit 8f957ce1d545c5c53a982ac38dc782510d0c2c66

Authored by Scott Klum
2 parents 0bcb4058 568379f5

Merge branch 'master' of https://github.com/biometrics/openbr

app/br/br.cpp
@@ -146,6 +146,9 @@ public: @@ -146,6 +146,9 @@ public:
146 } else if (!strcmp(fun, "plotDetection")) { 146 } else if (!strcmp(fun, "plotDetection")) {
147 check(parc >= 2, "Incorrect parameter count for 'plotDetection'."); 147 check(parc >= 2, "Incorrect parameter count for 'plotDetection'.");
148 br_plot_detection(parc-1, parv, parv[parc-1], true); 148 br_plot_detection(parc-1, parv, parv[parc-1], true);
  149 + } else if (!strcmp(fun, "plotLandmarking")) {
  150 + check(parc >= 2, "Incorrect parameter count for 'plotLandmarking'.");
  151 + br_plot_landmarking(parc-1, parv, parv[parc-1], true);
149 } else if (!strcmp(fun, "plotMetadata")) { 152 } else if (!strcmp(fun, "plotMetadata")) {
150 check(parc >= 2, "Incorrect parameter count for 'plotMetadata'."); 153 check(parc >= 2, "Incorrect parameter count for 'plotMetadata'.");
151 br_plot_metadata(parc-1, parv, parv[parc-1], true); 154 br_plot_metadata(parc-1, parv, parv[parc-1], true);
@@ -224,6 +227,7 @@ private: @@ -224,6 +227,7 @@ private:
224 "-evalLandmarking <predicted_gallery> <truth_gallery> [{csv} [<normalization_index_a> <normalization_index_b>]]\n" 227 "-evalLandmarking <predicted_gallery> <truth_gallery> [{csv} [<normalization_index_a> <normalization_index_b>]]\n"
225 "-evalRegression <predicted_gallery> <truth_gallery> <predicted property name> <ground truth property name>\n" 228 "-evalRegression <predicted_gallery> <truth_gallery> <predicted property name> <ground truth property name>\n"
226 "-plotDetection <file> ... <file> {destination}\n" 229 "-plotDetection <file> ... <file> {destination}\n"
  230 + "-plotLandmarking <file> ... <file> {destination}\n"
227 "-plotMetadata <file> ... <file> <columns>\n" 231 "-plotMetadata <file> ... <file> <columns>\n"
228 "-getHeader <matrix>\n" 232 "-getHeader <matrix>\n"
229 "-setHeader {<matrix>} <target_gallery> <query_gallery>\n" 233 "-setHeader {<matrix>} <target_gallery> <query_gallery>\n"
openbr/core/plot.cpp
@@ -302,7 +302,6 @@ bool filesHaveSinglePoint(const QStringList &amp;files) { @@ -302,7 +302,6 @@ bool filesHaveSinglePoint(const QStringList &amp;files) {
302 bool PlotDetection(const QStringList &files, const File &destination, bool show) 302 bool PlotDetection(const QStringList &files, const File &destination, bool show)
303 { 303 {
304 qDebug("Plotting %d detection file(s) to %s", files.size(), qPrintable(destination)); 304 qDebug("Plotting %d detection file(s) to %s", files.size(), qPrintable(destination));
305 -  
306 RPlot p(files, destination, false); 305 RPlot p(files, destination, false);
307 306
308 p.file.write("# Split data into individual plots\n" 307 p.file.write("# Split data into individual plots\n"
@@ -345,6 +344,22 @@ bool PlotDetection(const QStringList &amp;files, const File &amp;destination, bool show) @@ -345,6 +344,22 @@ bool PlotDetection(const QStringList &amp;files, const File &amp;destination, bool show)
345 return p.finalize(show); 344 return p.finalize(show);
346 } 345 }
347 346
  347 +bool PlotLandmarking(const QStringList &files, const File &destination, bool show)
  348 +{
  349 + qDebug("Plotting %d landmarking file(s) to %s", files.size(), qPrintable(destination));
  350 + RPlot p(files, destination, false);
  351 +
  352 + p.file.write("# Split data into individual plots\n"
  353 + "plot_index = which(names(data)==\"Plot\")\n"
  354 + "Box <- data[grep(\"Box\",data$Plot),-c(1)]\n"
  355 + "rm(data)\n"
  356 + "\n");
  357 +
  358 + p.file.write("ggplot(Box, aes(factor(X),Y)) + geom_boxplot() + geom_jitter(size=1.33,alpha=0.66) + scale_x_discrete(\"Landmark\") + scale_y_log10(\"Normalized Error\", breaks=c(0.01,0.1,1,10)) + annotation_logticks(sides=\"l\")\n\n");
  359 +
  360 + return p.finalize(show);
  361 +}
  362 +
348 bool PlotMetadata(const QStringList &files, const QString &columns, bool show) 363 bool PlotMetadata(const QStringList &files, const QString &columns, bool show)
349 { 364 {
350 qDebug("Plotting %d metadata file(s) for columns %s", files.size(), qPrintable(columns)); 365 qDebug("Plotting %d metadata file(s) for columns %s", files.size(), qPrintable(columns));
openbr/core/plot.h
@@ -26,6 +26,7 @@ namespace br @@ -26,6 +26,7 @@ namespace br
26 { 26 {
27 bool Plot(const QStringList &files, const File &destination, bool show = false); 27 bool Plot(const QStringList &files, const File &destination, bool show = false);
28 bool PlotDetection(const QStringList &files, const File &destination, bool show = false); 28 bool PlotDetection(const QStringList &files, const File &destination, bool show = false);
  29 + bool PlotLandmarking(const QStringList &files, const File &destination, bool show = false);
29 bool PlotMetadata(const QStringList &files, const QString &destination, bool show = false); 30 bool PlotMetadata(const QStringList &files, const QString &destination, bool show = false);
30 } 31 }
31 32
openbr/openbr.cpp
@@ -182,6 +182,11 @@ bool br_plot_detection(int num_files, const char *files[], const char *destinati @@ -182,6 +182,11 @@ bool br_plot_detection(int num_files, const char *files[], const char *destinati
182 return PlotDetection(QtUtils::toStringList(num_files, files), destination, show); 182 return PlotDetection(QtUtils::toStringList(num_files, files), destination, show);
183 } 183 }
184 184
  185 +bool br_plot_landmarking(int num_files, const char *files[], const char *destination, bool show)
  186 +{
  187 + return PlotLandmarking(QtUtils::toStringList(num_files, files), destination, show);
  188 +}
  189 +
185 bool br_plot_metadata(int num_files, const char *files[], const char *columns, bool show) 190 bool br_plot_metadata(int num_files, const char *files[], const char *columns, bool show)
186 { 191 {
187 return PlotMetadata(QtUtils::toStringList(num_files, files), columns, show); 192 return PlotMetadata(QtUtils::toStringList(num_files, files), columns, show);
openbr/openbr.h
@@ -295,6 +295,18 @@ BR_EXPORT bool br_plot(int num_files, const char *files[], const char *destinati @@ -295,6 +295,18 @@ BR_EXPORT bool br_plot(int num_files, const char *files[], const char *destinati
295 BR_EXPORT bool br_plot_detection(int num_files, const char *files[], const char *destination, bool show = false); 295 BR_EXPORT bool br_plot_detection(int num_files, const char *files[], const char *destination, bool show = false);
296 296
297 /*! 297 /*!
  298 + * \brief Renders landmarking performance figures for a set of <tt>.csv</tt> files created by \ref br_eval_landmarking.
  299 + *
  300 + * In order of their output, the figures are:
  301 + * -# Normalized error box plots (Box)
  302 + *
  303 + * Landmarking error is normalized against the distance between two predifined points, usually inter-ocular distance (IOD).
  304 + *
  305 + * \see br_plot
  306 + */
  307 +BR_EXPORT bool br_plot_landmarking(int num_files, const char *files[], const char *destination, bool show = false);
  308 +
  309 +/*!
298 * \brief Renders metadata figures for a set of <tt>.csv</tt> files with specified columns. 310 * \brief Renders metadata figures for a set of <tt>.csv</tt> files with specified columns.
299 * 311 *
300 * Several files will be created: 312 * Several files will be created:
openbr/plugins/algorithms.cpp
@@ -50,9 +50,9 @@ class AlgorithmsInitializer : public Initializer @@ -50,9 +50,9 @@ class AlgorithmsInitializer : public Initializer
50 Globals->abbreviations.insert("PerFrameDetection", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true)+Show(false,[FrameNumber])+Discard)"); 50 Globals->abbreviations.insert("PerFrameDetection", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true)+Show(false,[FrameNumber])+Discard)");
51 Globals->abbreviations.insert("AgeGenderDemo", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+Expand+<FaceClassificationRegistration>+<FaceClassificationExtraction>+<AgeRegressor>/<GenderClassifier>+Discard+RestoreMat(original)+Draw(inPlace=true)+DrawPropertiesPoint([Age,Gender],Affine_0,inPlace=true)+SaveMat(original)+Discard+Contract+RestoreMat(original)+FPSCalc+Show(false,[AvgFPS,Age,Gender])+Discard)"); 51 Globals->abbreviations.insert("AgeGenderDemo", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+Expand+<FaceClassificationRegistration>+<FaceClassificationExtraction>+<AgeRegressor>/<GenderClassifier>+Discard+RestoreMat(original)+Draw(inPlace=true)+DrawPropertiesPoint([Age,Gender],Affine_0,inPlace=true)+SaveMat(original)+Discard+Contract+RestoreMat(original)+FPSCalc+Show(false,[AvgFPS,Age,Gender])+Discard)");
52 52
53 - Globals->abbreviations.insert("HOG", "Stream(DropFrames(5)+Cvt(Gray)+KeyPointDetector(SIFT)+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat)+Contract+CatRows+KMeans(500)+Hist(500)+SVM");  
54 - Globals->abbreviations.insert("HOF", "Stream(DropFrames(5)+KeyPointDetector(SIFT)+AggregateFrames(2)+OpticalFlow+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat)+Contract+CatRows+KMeans(500)+Hist(500)");  
55 - Globals->abbreviations.insert("HOGHOF", "Stream(DropFrames(5)+KeyPointDetector(SIFT)+AggregateFrames(2)+(OpticalFlow++ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat+Contract)/(First+Cvt(Gray)+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat+Contract)+CatCols)+Contract+CatRows+KMeans(500)+Hist(500)+SVM"); 53 + Globals->abbreviations.insert("HOG", "Stream(DropFrames(5)+Cvt(Gray)+Grid(5,5)+ROIFromPts(32,24)+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat)+Contract+CatRows+KMeans(500)+Hist(500)+SVM");
  54 + Globals->abbreviations.insert("HOF", "Stream(DropFrames(5)+Grid(5,5)+AggregateFrames(2)+OpticalFlow+ROIFromPts(32,24)+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat)+Contract+CatRows+KMeans(500)+Hist(500)");
  55 + Globals->abbreviations.insert("HOGHOF", "Stream(DropFrames(5)+Grid(5,5)+AggregateFrames(2)+(OpticalFlow+ROIFromPts(32,24)+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat+Contract)/(First+Cvt(Gray)+ROIFromPts(32,24)+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat+Contract)+CatCols)+Contract+CatRows+KMeans(500)+Hist(500)+SVM");
56 56
57 // Generic Image Processing 57 // Generic Image Processing
58 Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)"); 58 Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)");
openbr/plugins/crop.cpp
@@ -69,6 +69,31 @@ BR_REGISTER(Transform, ROITransform) @@ -69,6 +69,31 @@ BR_REGISTER(Transform, ROITransform)
69 69
70 /*! 70 /*!
71 * \ingroup transforms 71 * \ingroup transforms
  72 + * \brief Crops the rectangular regions of interest from given points and sizes.
  73 + * \author Austin Blanton \cite imaus10
  74 + */
  75 +class ROIFromPtsTransform : public UntrainableTransform
  76 +{
  77 + Q_OBJECT
  78 + Q_PROPERTY(int width READ get_width WRITE set_width RESET reset_width STORED false)
  79 + Q_PROPERTY(int height READ get_height WRITE set_height RESET reset_height STORED false)
  80 + BR_PROPERTY(int, width, 1)
  81 + BR_PROPERTY(int, height, 1)
  82 +
  83 + void project(const Template &src, Template &dst) const
  84 + {
  85 + foreach (const QPointF &pt, src.file.points()) {
  86 + int x = pt.x() - (width/2);
  87 + int y = pt.y() - (height/2);
  88 + dst += src.m()(Rect(x, y, width, height));
  89 + }
  90 + }
  91 +};
  92 +
  93 +BR_REGISTER(Transform, ROIFromPtsTransform)
  94 +
  95 +/*!
  96 + * \ingroup transforms
72 * \brief Resize the template 97 * \brief Resize the template
73 * \author Josh Klontz \cite jklontz 98 * \author Josh Klontz \cite jklontz
74 * \note Method: Area should be used for shrinking an image, Cubic for slow but accurate enlargment, Bilin for fast enlargement. 99 * \note Method: Area should be used for shrinking an image, Cubic for slow but accurate enlargment, Bilin for fast enlargement.
openbr/plugins/eigen3.cpp
@@ -253,9 +253,7 @@ class DFFSTransform : public Transform @@ -253,9 +253,7 @@ class DFFSTransform : public Transform
253 { 253 {
254 Q_OBJECT 254 Q_OBJECT
255 Q_PROPERTY(float keep READ get_keep WRITE set_keep RESET reset_keep STORED false) 255 Q_PROPERTY(float keep READ get_keep WRITE set_keep RESET reset_keep STORED false)
256 - Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform STORED false)  
257 BR_PROPERTY(float, keep, 0.95) 256 BR_PROPERTY(float, keep, 0.95)
258 - BR_PROPERTY(br::Transform*, transform, NULL)  
259 257
260 PCATransform pca; 258 PCATransform pca;
261 Transform *cvtFloat; 259 Transform *cvtFloat;
openbr/plugins/frames.cpp
@@ -52,6 +52,11 @@ private: @@ -52,6 +52,11 @@ private:
52 { 52 {
53 (void) stream; 53 (void) stream;
54 } 54 }
  55 +
  56 + void init()
  57 + {
  58 + TimeVaryingTransform::init();
  59 + }
55 }; 60 };
56 61
57 BR_REGISTER(Transform, AggregateFrames) 62 BR_REGISTER(Transform, AggregateFrames)
openbr/plugins/fst3.cmake deleted
1 -set(BR_WITH_FST3 OFF CACHE BOOL "Build with Feature Selection Toolbox 3")  
2 -  
3 -if(${BR_WITH_FST3})  
4 - find_package(FST3 REQUIRED)  
5 - set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} plugins/fst3.cpp ${FST3_SRC})  
6 -  
7 - find_package(Boost REQUIRED)  
8 - include_directories(${Boost_INCLUDE_DIRS})  
9 - set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} boost_thread)  
10 -  
11 - find_package(LibSVM REQUIRED)  
12 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} ${LibSVM_SRC})  
13 -endif()  
openbr/plugins/fst3.cpp deleted
1 -#include <QMap>  
2 -#include <QString>  
3 -#include <QStringList>  
4 -#include <QTime>  
5 -#include <opencv2/core/core.hpp>  
6 -#include <opencv2/imgproc/imgproc.hpp>  
7 -#include <mm_plugin.h>  
8 -  
9 -#include "model.h"  
10 -#include "common/opencvutils.h"  
11 -#include "common/qtutils.h"  
12 -#include "plugins/meta.h"  
13 -#include "plugins/regions.h"  
14 -  
15 -//#ifdef MM_SDK_TRAINABLE  
16 -#include <boost/smart_ptr.hpp>  
17 -#include <exception>  
18 -#include <iostream>  
19 -#include <cstdlib>  
20 -#include <sstream>  
21 -#include <string>  
22 -#include <vector>  
23 -  
24 -#include <error.hpp>  
25 -#include <global.hpp>  
26 -#include <subset.hpp>  
27 -#include <data_intervaller.hpp>  
28 -#include <data_splitter.hpp>  
29 -#include <data_splitter_5050.hpp>  
30 -#include <data_splitter_cv.hpp>  
31 -#include <data_splitter_resub.hpp>  
32 -#include <data_scaler.hpp>  
33 -#include <data_scaler_void.hpp>  
34 -#include <data_accessor_splitting_mem.hpp>  
35 -#include <criterion_wrapper.hpp>  
36 -#include <distance_euclid.hpp>  
37 -#include <classifier_knn.hpp>  
38 -#include <seq_step_straight_threaded.hpp>  
39 -#include <search_seq_dos.hpp>  
40 -#include <search_seq_sfs.hpp>  
41 -#include <search_seq_sffs.hpp>  
42 -#include <search_monte_carlo_threaded.hpp>  
43 -  
44 -using namespace FST;  
45 -//#endif // MM_SDK_TRAINABLE  
46 -  
47 -using namespace mm;  
48 -  
49 -enum DimensionStatus {  
50 - On,  
51 - Off,  
52 - Ignore  
53 -};  
54 -  
55 -//#ifdef MM_SDK_TRAINABLE  
56 -template<typename DATATYPE, typename IDXTYPE, class INTERVALCONTAINER>  
57 -class FST3Data_Accessor_Splitting_MemMM : public Data_Accessor_Splitting_Mem<DATATYPE,IDXTYPE,INTERVALCONTAINER>  
58 -{  
59 - QList<MatrixList> mll;  
60 - QList<DimensionStatus> dsl;  
61 - int features;  
62 - QMap<int, int> labelCounts;  
63 -  
64 -public:  
65 - typedef Data_Accessor_Splitting_Mem<DATATYPE,IDXTYPE,INTERVALCONTAINER> DASM;  
66 - typedef boost::shared_ptr<Data_Scaler<DATATYPE> > PScaler;  
67 - typedef typename DASM::PSplitters PSplitters;  
68 -  
69 - FST3Data_Accessor_Splitting_MemMM(const QList<MatrixList> &_mll, const QList<DimensionStatus> &_dsl, const PSplitters _dsp, const PScaler _dsc)  
70 - : Data_Accessor_Splitting_Mem<DATATYPE,IDXTYPE,INTERVALCONTAINER>("MM", _dsp, _dsc), mll(_mll), dsl(_dsl)  
71 - {  
72 - features = 0;  
73 - foreach (DimensionStatus ds, dsl)  
74 - if (ds != Ignore) features++;  
75 - labelCounts = mll.first().labelCounts();  
76 - }  
77 -  
78 - FST3Data_Accessor_Splitting_MemMM(const MatrixList &_ml, const PSplitters _dsp, const PScaler _dsc)  
79 - : Data_Accessor_Splitting_Mem<DATATYPE,IDXTYPE,INTERVALCONTAINER>("MM", _dsp, _dsc)  
80 - {  
81 - mll.append(_ml);  
82 - features = _ml.first().total() * _ml.first().channels();  
83 - for (int i=0; i<features; i++)  
84 - dsl.append(Off);  
85 - labelCounts = _ml.labelCounts();  
86 - }  
87 -  
88 - FST3Data_Accessor_Splitting_MemMM* sharing_clone() const;  
89 - virtual std::ostream& print(std::ostream& os) const;  
90 -  
91 -protected:  
92 - FST3Data_Accessor_Splitting_MemMM(const Data_Accessor_Splitting_MemMM &damt, int x)  
93 - : Data_Accessor_Splitting_Mem<DATATYPE,IDXTYPE,INTERVALCONTAINER>(damt, x)  
94 - {} // weak (referencing) copy-constructor to be used in sharing_clone()  
95 -  
96 - virtual void initial_data_read(); //!< \note off-limits in shared_clone  
97 - virtual void initial_file_prepare() {}  
98 -  
99 -public:  
100 - virtual unsigned int file_getNoOfClasses() const { return labelCounts.size(); }  
101 - virtual unsigned int file_getNoOfFeatures() const { return features; }  
102 - virtual IDXTYPE file_getClassSize(unsigned int cls) const { return labelCounts[cls]; }  
103 -};  
104 -  
105 -template<typename DATATYPE, typename IDXTYPE, class INTERVALCONTAINER>  
106 -void FST3Data_Accessor_Splitting_MemMM<DATATYPE,IDXTYPE,INTERVALCONTAINER>::initial_data_read() //!< \note off-limits in shared_clone  
107 -{  
108 - if (Clonable::is_sharing_clone()) throw fst_error("Data_Accessor_Splitting_MemMM()::initial_data_read() called from shared_clone instance.");  
109 - IDXTYPE idx=0;  
110 -  
111 - // TODO: Assert that ml data type is DATATYPE  
112 - const QList<float> labels = mll.first().labels();  
113 - foreach (int label, labelCounts.keys()) {  
114 - for (int i=0; i<labels.size(); i++) {  
115 - if (labels[i] == label) {  
116 - int dslIndex = 0;  
117 - foreach (const MatrixList &ml, mll) {  
118 - const Matrix &m = ml[i];  
119 - const int dims = m.total() * m.channels();  
120 - for (int j=0; j<dims; j++)  
121 - if (dsl[dslIndex++] != Ignore)  
122 - this->data[idx++] = reinterpret_cast<float*>(m.data)[j];  
123 - }  
124 - }  
125 - }  
126 - }  
127 -}  
128 -  
129 -/*template<typename DATATYPE, typename IDXTYPE, class INTERVALCONTAINER>  
130 -Data_Accessor_Splitting_MemMM<DATATYPE,IDXTYPE,INTERVALCONTAINER>* Data_Accessor_Splitting_MemMM<DATATYPE,IDXTYPE,INTERVALCONTAINER>::sharing_clone() const  
131 -{  
132 - Data_Accessor_Splitting_MemMM<DATATYPE,IDXTYPE,INTERVALCONTAINER> *clone=new Data_Accessor_Splitting_MemMM<DATATYPE,IDXTYPE,INTERVALCONTAINER>(*this, (int)0);  
133 - clone->set_sharing_cloned();  
134 - return clone;  
135 -}  
136 -  
137 -template<typename DATATYPE, typename IDXTYPE, class INTERVALCONTAINER>  
138 -std::ostream& Data_Accessor_Splitting_MemMM<DATATYPE,IDXTYPE,INTERVALCONTAINER>::print(std::ostream& os) const  
139 -{  
140 - DASM::print(os);  
141 - os << std::endl << "Data_Accessor_Splitting_MemMM()";  
142 - return os;  
143 -}*/  
144 -  
145 -//#endif // MM_SDK_TRAINABLE  
146 -  
147 -  
148 -class FST3DOS : public Feature  
149 -{  
150 - friend class Maker<DOS,true>;  
151 -  
152 - int delta;  
153 -  
154 - mm::Remap remap;  
155 -  
156 - DOS(int delta = 1)  
157 - {  
158 - this->delta = delta;  
159 - }  
160 -  
161 - static QString args()  
162 - {  
163 - return "delta = 1";  
164 - }  
165 -  
166 - static DOS *make(const QString &args)  
167 - {  
168 - QStringList words = QtUtils::parse(args);  
169 - if (words.size() > 1) qFatal("DOS::make invalid argument count.");  
170 -  
171 - int delta = 1;  
172 -  
173 - bool ok;  
174 - switch (words.size()) {  
175 - case 1:  
176 - delta = words[0].toInt(&ok); if (!ok) qFatal("DOS::make expected integer delta.");  
177 - }  
178 -  
179 - return new DOS(delta);  
180 - }  
181 -  
182 - QSharedPointer<Feature> clone() const  
183 - {  
184 - return QSharedPointer<Feature>(new DOS(delta));  
185 - }  
186 -  
187 - void train(const MatrixList &data, Matrix &metadata)  
188 - {  
189 - (void) metadata;  
190 - //#ifdef MM_SDK_TRAINABLE  
191 - try {  
192 - typedef float RETURNTYPE; typedef float DATATYPE; typedef float REALTYPE;  
193 - typedef unsigned int IDXTYPE; typedef unsigned int DIMTYPE; typedef int BINTYPE;  
194 - typedef Subset<BINTYPE, DIMTYPE> SUBSET;  
195 - typedef Data_Intervaller<std::vector<Data_Interval<IDXTYPE> >,IDXTYPE> INTERVALLER;  
196 - typedef boost::shared_ptr<Data_Splitter<INTERVALLER,IDXTYPE> > PSPLITTER;  
197 - typedef Data_Splitter_CV<INTERVALLER,IDXTYPE> SPLITTERCV;  
198 - typedef Data_Splitter_5050<INTERVALLER,IDXTYPE> SPLITTER5050;  
199 - typedef Data_Splitter_Resub<INTERVALLER,IDXTYPE> SPLITTERRESUB;  
200 - typedef Data_Accessor_Splitting_MemMM<DATATYPE,IDXTYPE,INTERVALLER> DATAACCESSOR;  
201 - typedef Distance_Euclid<DATATYPE,DIMTYPE,SUBSET> DISTANCE;  
202 - typedef Classifier_kNN<RETURNTYPE,DATATYPE,IDXTYPE,DIMTYPE,SUBSET,DATAACCESSOR,DISTANCE> CLASSIFIERKNN;  
203 - typedef Criterion_Wrapper<RETURNTYPE,SUBSET,CLASSIFIERKNN,DATAACCESSOR> WRAPPERKNN;  
204 - typedef Sequential_Step_Straight_Threaded<RETURNTYPE,DIMTYPE,SUBSET,WRAPPERKNN,24> EVALUATOR;  
205 -  
206 - // Initialize dataset  
207 - PSPLITTER dsp_outer(new SPLITTER5050()); // keep second half of data for independent testing of final classification performance  
208 - PSPLITTER dsp_inner(new SPLITTERCV(3)); // in the course of search use the first half of data by 3-fold cross-validation in wrapper FS criterion evaluation  
209 - boost::shared_ptr<Data_Scaler<DATATYPE> > dsc(new Data_Scaler_void<DATATYPE>()); // do not scale data  
210 - boost::shared_ptr<std::vector<PSPLITTER> > splitters(new std::vector<PSPLITTER>); // set-up data access  
211 - splitters->push_back(dsp_outer); //splitters->push_back(dsp_inner);  
212 - boost::shared_ptr<DATAACCESSOR> da(new DATAACCESSOR(data, splitters, dsc));  
213 - da->initialize();  
214 - da->setSplittingDepth(0); if(!da->getFirstSplit()) throw fst_error("50/50 data split failed.");  
215 - //da->setSplittingDepth(1); if(!da->getFirstSplit()) throw fst_error("3-fold cross-validation failure.");  
216 - boost::shared_ptr<SUBSET> sub(new SUBSET(da->getNoOfFeatures())); // initiate the storage for subset to-be-selected  
217 - //sub->select_all();  
218 -  
219 - // Run search  
220 - boost::shared_ptr<CLASSIFIERKNN> cknn(new CLASSIFIERKNN); cknn->set_k(1);  
221 - boost::shared_ptr<WRAPPERKNN> wknn(new WRAPPERKNN);  
222 - wknn->initialize(cknn,da);  
223 - boost::shared_ptr<EVALUATOR> eval(new EVALUATOR); // set-up the standard sequential search step object (option: hybrid, ensemble, etc.)  
224 - //Search_DOS<RETURNTYPE,DIMTYPE,SUBSET,WRAPPERKNN,EVALUATOR> srch(eval); // set-up Sequential Forward Floating Selection search procedure  
225 - //srch.set_delta(delta);  
226 -  
227 - //FST::Search_SFFS<RETURNTYPE,DIMTYPE,SUBSET,WRAPPERKNN,EVALUATOR> srch(eval);  
228 - //srch.set_search_direction(FST::BACKWARD);  
229 -  
230 - //FST::Search_SFS<RETURNTYPE,DIMTYPE,SUBSET,WRAPPERKNN,EVALUATOR> srch(eval);  
231 - //srch.set_search_direction(FST::FORWARD);  
232 -  
233 - FST::Search_Monte_Carlo_Threaded<RETURNTYPE,DIMTYPE,SUBSET,WRAPPERKNN,24> srch;  
234 - srch.set_cardinality_randomization(0.5); // probability of inclusion of each particular feature (~implies also the expected subset size)  
235 - srch.set_stopping_condition(0/*max trials*/,30/*seconds*/); // one or both values must have positive value  
236 -  
237 - RETURNTYPE critval_train;  
238 - if(!srch.search(0,critval_train,sub,wknn,std::cout)) throw fst_error("Search not finished.");  
239 -  
240 - // Create map matrix  
241 - const int dims = sub->get_d_raw();  
242 - cv::Mat xMap(1, dims, CV_16SC1),  
243 - yMap(1, dims, CV_16SC1);  
244 - int index = 0;  
245 - for (int i=0; i<dims; i++) {  
246 - if (sub->selected_raw(i)) {  
247 - xMap.at<short>(0, index) = i;  
248 - yMap.at<short>(0, index) = 0;  
249 - index++;  
250 - }  
251 - }  
252 -  
253 - remap = Remap(xMap, yMap, cv::INTER_NEAREST);  
254 - }  
255 - catch (fst_error &e) { qFatal("FST ERROR: %s, code=%d", e.what(), e.code()); }  
256 - catch (std::exception &e) { qFatal("non-FST ERROR: %s", e.what()); }  
257 - metadata >> remap;  
258 - //#else // MM_SDK_TRAINABLE  
259 - //qFatal("StreamwiseFS::train not supported.");  
260 - //#endif // MM_SDK_TRAINABLE  
261 - }  
262 -  
263 - void project(const Matrix &src, Matrix &dst) const  
264 - {  
265 - dst = src;  
266 - dst >> remap;  
267 - }  
268 -  
269 - void store(QDataStream &stream) const  
270 - {  
271 - stream << remap;  
272 - }  
273 -  
274 - void load(QDataStream &stream)  
275 - {  
276 - stream >> remap;  
277 - }  
278 -};  
279 -  
280 -MM_REGISTER(Feature, FST3DOS, true)  
281 -  
282 -  
283 -class FST3StreamwiseFS : public Feature  
284 -{  
285 - friend class Maker<StreamwiseFS,true>;  
286 -  
287 - QSharedPointer<Feature> weakLearnerTemplate;  
288 - int time;  
289 -  
290 - mm::Dup dup;  
291 - mm::Remap remap;  
292 -  
293 - StreamwiseFS(const QSharedPointer<Feature> &weakLearnerTemplate, int time)  
294 - : dup(weakLearnerTemplate, 1)  
295 - {  
296 - this->weakLearnerTemplate = weakLearnerTemplate;  
297 - this->time = time;  
298 - }  
299 -  
300 - static QString args()  
301 - {  
302 - return "<feature> weakLearnerTemplate, int time";  
303 - }  
304 -  
305 - static StreamwiseFS *make(const QString &args)  
306 - {  
307 - QStringList words = QtUtils::parse(args);  
308 - if (words.size() != 2) qFatal("StreamwiseFS::make invalid argument count.");  
309 -  
310 - QSharedPointer<Feature> weakLearnerTemplate = Feature::make(words[0]);  
311 - bool ok;  
312 - int time = words[1].toInt(&ok); assert(ok);  
313 -  
314 - return new StreamwiseFS(weakLearnerTemplate, time);  
315 - }  
316 -  
317 - QSharedPointer<Feature> clone() const  
318 - {  
319 - return QSharedPointer<Feature>(new StreamwiseFS(weakLearnerTemplate, time));  
320 - }  
321 -  
322 - void train(const MatrixList &data, Matrix &metadata)  
323 - {  
324 - QList< QSharedPointer<Feature> > weakLearners;  
325 - QList<MatrixList> projectedDataList;  
326 - QList<int> weakLearnerDimsList;  
327 - QList<DimensionStatus> dimStatusList;  
328 -  
329 - QTime timer; timer.start();  
330 - while (timer.elapsed() / 1000 < time) {  
331 - // Construct a new weak learner  
332 - QSharedPointer<Feature> newWeakLearner = weakLearnerTemplate->clone();  
333 - Matrix metadataCopy(metadata);  
334 - newWeakLearner->train(data, metadataCopy);  
335 - weakLearners.append(newWeakLearner);  
336 -  
337 - MatrixList projectedData = data;  
338 - projectedData >> *newWeakLearner;  
339 - projectedDataList.append(projectedData);  
340 - weakLearnerDimsList.append(projectedData.first().total() * projectedData.first().channels());  
341 - for (int i=0; i<weakLearnerDimsList.last(); i++) dimStatusList.append(Off);  
342 -  
343 - //#ifdef MM_SDK_TRAINABLE  
344 - try  
345 - {  
346 - typedef float RETURNTYPE; typedef float DATATYPE; typedef float REALTYPE;  
347 - typedef unsigned int IDXTYPE; typedef unsigned int DIMTYPE; typedef int BINTYPE;  
348 - typedef Subset<BINTYPE, DIMTYPE> SUBSET;  
349 - typedef Data_Intervaller<std::vector<Data_Interval<IDXTYPE> >,IDXTYPE> INTERVALLER;  
350 - typedef boost::shared_ptr<Data_Splitter<INTERVALLER,IDXTYPE> > PSPLITTER;  
351 - typedef Data_Splitter_CV<INTERVALLER,IDXTYPE> SPLITTERCV;  
352 - typedef Data_Splitter_5050<INTERVALLER,IDXTYPE> SPLITTER5050;  
353 - typedef Data_Accessor_Splitting_MemMM<DATATYPE,IDXTYPE,INTERVALLER> DATAACCESSOR;  
354 - typedef Distance_Euclid<DATATYPE,DIMTYPE,SUBSET> DISTANCE;  
355 - typedef Classifier_kNN<RETURNTYPE,DATATYPE,IDXTYPE,DIMTYPE,SUBSET,DATAACCESSOR,DISTANCE> CLASSIFIERKNN;  
356 - typedef Criterion_Wrapper<RETURNTYPE,SUBSET,CLASSIFIERKNN,DATAACCESSOR> WRAPPERKNN;  
357 - typedef Sequential_Step_Straight_Threaded<RETURNTYPE,DIMTYPE,SUBSET,WRAPPERKNN,24> EVALUATOR;  
358 -  
359 - // Initialize dataset  
360 - PSPLITTER dsp_outer(new SPLITTER5050()); // keep second half of data for independent testing of final classification performance  
361 - PSPLITTER dsp_inner(new SPLITTERCV(3)); // in the course of search use the first half of data by 3-fold cross-validation in wrapper FS criterion evaluation  
362 - boost::shared_ptr<Data_Scaler<DATATYPE> > dsc(new Data_Scaler_void<DATATYPE>()); // do not scale data  
363 - boost::shared_ptr<std::vector<PSPLITTER> > splitters(new std::vector<PSPLITTER>); // set-up data access  
364 - splitters->push_back(dsp_outer); splitters->push_back(dsp_inner);  
365 - boost::shared_ptr<DATAACCESSOR> da(new DATAACCESSOR(projectedDataList, dimStatusList, splitters, dsc));  
366 - da->initialize();  
367 - da->setSplittingDepth(0); if(!da->getFirstSplit()) throw fst_error("50/50 data split failed.");  
368 - da->setSplittingDepth(1); if(!da->getFirstSplit()) throw fst_error("3-fold cross-validation failure.");  
369 - boost::shared_ptr<SUBSET> sub(new SUBSET(da->getNoOfFeatures())); // initiate the storage for subset to-be-selected  
370 -  
371 - { // Initialize subset from previous iteration results  
372 - sub->deselect_all();  
373 - int index = 0;  
374 - for (int i=0; i<dimStatusList.size(); i++) {  
375 - if (dimStatusList[i] == On) sub->select(index);  
376 - if (dimStatusList[i] != Ignore) index++;  
377 - }  
378 - }  
379 -  
380 - // Run search  
381 - boost::shared_ptr<CLASSIFIERKNN> cknn(new CLASSIFIERKNN); cknn->set_k(3); // set-up 3-Nearest Neighbor classifier based on Euclidean distances  
382 - boost::shared_ptr<WRAPPERKNN> wknn(new WRAPPERKNN); // wrap the 3-NN classifier to enable its usage as FS criterion (criterion value will be estimated by 3-fold cross-val.)  
383 - wknn->initialize(cknn,da);  
384 - boost::shared_ptr<EVALUATOR> eval(new EVALUATOR); // set-up the standard sequential search step object (option: hybrid, ensemble, etc.)  
385 - Search_DOS<RETURNTYPE,DIMTYPE,SUBSET,WRAPPERKNN,EVALUATOR> srch(eval); // set-up Sequential Forward Floating Selection search procedure  
386 - srch.set_delta(1);  
387 - RETURNTYPE critval_train;  
388 - if(!srch.search(0,critval_train,sub,wknn,std::cout)) throw fst_error("Search not finished.");  
389 -  
390 - { // Update results  
391 - int dslIndex = dimStatusList.size() - 1;  
392 - int subIndex = da->getNoOfFeatures() - 1;  
393 - for (int wlIndex = weakLearnerDimsList.size()-1; wlIndex >= 0; wlIndex--) {  
394 - const int weakLearnerDims = weakLearnerDimsList[wlIndex];  
395 - int numSelectedDims = 0;  
396 - for (int i=0; i<weakLearnerDims; i++) {  
397 - if (dimStatusList[dslIndex] != Ignore)  
398 - dimStatusList[dslIndex] = sub->selected_raw(subIndex--) ? numSelectedDims++, On : Ignore;  
399 - dslIndex--;  
400 - }  
401 -  
402 - if (numSelectedDims == 0) {  
403 - for (int j=0; j<weakLearnerDims; j++)  
404 - dimStatusList.removeAt(dslIndex+1);  
405 - weakLearnerDimsList.removeAt(wlIndex);  
406 - projectedDataList.removeAt(wlIndex);  
407 - weakLearners.removeAt(wlIndex);  
408 - }  
409 - }  
410 - }  
411 - }  
412 - catch (fst_error &e) { qFatal("FST ERROR: %s, code=%d", e.what(), e.code()); }  
413 - catch (std::exception &e) { qFatal("non-FST ERROR: %s", e.what()); }  
414 - //#else // MM_SDK_TRAINABLE  
415 - //qFatal("StreamwiseFS::train not supported.");  
416 - //#endif // MM_SDK_TRAINABLE  
417 - }  
418 -  
419 - dup = Dup(weakLearners);  
420 -  
421 - // Create map matrix  
422 - int dims = 0;  
423 - foreach (DimensionStatus ds, dimStatusList) if (ds == On) dims++;  
424 - cv::Mat xMap(1, dims, CV_16SC1),  
425 - yMap(1, dims, CV_16SC1);  
426 - int index = 0;  
427 - for (int i=0; i<dimStatusList.size(); i++) {  
428 - if (dimStatusList[i] == On) {  
429 - xMap.at<short>(0, index) = i;  
430 - yMap.at<short>(0, index) = 0;  
431 - index++;  
432 - }  
433 - }  
434 -  
435 - remap = Remap(xMap, yMap, cv::INTER_NEAREST);  
436 - }  
437 -  
438 - void project(const Matrix &src, Matrix &dst) const  
439 - {  
440 - dst = src;  
441 - dst >> dup >> mm::Cat >> remap;  
442 - }  
443 -  
444 - void store(QDataStream &stream) const  
445 - {  
446 - stream << dup << remap;  
447 - }  
448 -  
449 - void load(QDataStream &stream)  
450 - {  
451 - stream >> dup >> remap;  
452 - }  
453 -};  
454 -  
455 -MM_REGISTER(Feature, FST3StreamwiseFS, true)  
openbr/plugins/gui.cpp
@@ -350,6 +350,8 @@ public: @@ -350,6 +350,8 @@ public:
350 if (!Globals->useGui) 350 if (!Globals->useGui)
351 return; 351 return;
352 352
  353 + TimeVaryingTransform::init();
  354 +
353 if (displayBuffer) 355 if (displayBuffer)
354 delete displayBuffer; 356 delete displayBuffer;
355 displayBuffer = new QPixmap(); 357 displayBuffer = new QPixmap();
@@ -530,6 +532,7 @@ public: @@ -530,6 +532,7 @@ public:
530 target_wait = 1000.0 / targetFPS; 532 target_wait = 1000.0 / targetFPS;
531 timer.start(); 533 timer.start();
532 last_time = timer.elapsed(); 534 last_time = timer.elapsed();
  535 + TimeVaryingTransform::init();
533 } 536 }
534 537
535 protected: 538 protected:
@@ -583,6 +586,7 @@ public: @@ -583,6 +586,7 @@ public:
583 { 586 {
584 initialized = false; 587 initialized = false;
585 framesSeen = 0; 588 framesSeen = 0;
  589 + TimeVaryingTransform::init();
586 } 590 }
587 591
588 protected: 592 protected:
openbr/plugins/keypoint.cpp
@@ -222,9 +222,9 @@ class GridTransform : public UntrainableTransform @@ -222,9 +222,9 @@ class GridTransform : public UntrainableTransform
222 QList<QPointF> landmarks; 222 QList<QPointF> landmarks;
223 const float row_step = 1.f * src.m().rows / rows; 223 const float row_step = 1.f * src.m().rows / rows;
224 const float column_step = 1.f * src.m().cols / columns; 224 const float column_step = 1.f * src.m().cols / columns;
225 - for (float i=row_step/2; i<src.m().rows; i+=row_step)  
226 - for (float j=column_step/2; j<src.m().cols; j+=column_step)  
227 - landmarks.append(QPointF(i,j)); 225 + for (float y=row_step/2; y<src.m().rows; y+=row_step)
  226 + for (float x=column_step/2; x<src.m().cols; x+=column_step)
  227 + landmarks.append(QPointF(x,y));
228 dst = src; 228 dst = src;
229 dst.file.setPoints(landmarks); 229 dst.file.setPoints(landmarks);
230 } 230 }
openbr/plugins/meta.cpp
@@ -264,7 +264,6 @@ class ContractTransform : public UntrainableMetaTransform @@ -264,7 +264,6 @@ class ContractTransform : public UntrainableMetaTransform
264 264
265 virtual void project(const TemplateList &src, TemplateList &dst) const 265 virtual void project(const TemplateList &src, TemplateList &dst) const
266 { 266 {
267 - //dst = Expanded(src);  
268 if (src.empty()) return; 267 if (src.empty()) return;
269 Template out; 268 Template out;
270 269
@@ -682,8 +681,10 @@ public: @@ -682,8 +681,10 @@ public:
682 681
683 void init() 682 void init()
684 { 683 {
685 - if (transform && transform->timeVarying())  
686 - transform = new br::TimeInvariantWrapperTransform(transform); 684 + if (!transform)
  685 + return;
  686 +
  687 + trainable = transform->trainable;
687 } 688 }
688 689
689 }; 690 };
openbr/plugins/openbr_internal.h
@@ -24,81 +24,27 @@ private: @@ -24,81 +24,27 @@ private:
24 }; 24 };
25 25
26 /*! 26 /*!
27 - * \brief A br::MetaTransform that does not require training data. 27 + * \brief A br::Transform expecting multiple matrices per template.
28 */ 28 */
29 -class BR_EXPORT UntrainableMetaTransform : public UntrainableTransform 29 +class BR_EXPORT MetaTransform : public Transform
30 { 30 {
31 Q_OBJECT 31 Q_OBJECT
32 32
33 protected: 33 protected:
34 - UntrainableMetaTransform() : UntrainableTransform(false) {}  
35 -};  
36 -  
37 -/*!  
38 - * \brief A br::Transform for which the results of project may change due to prior calls to project  
39 - */  
40 -class BR_EXPORT TimeVaryingTransform : public Transform  
41 -{  
42 - Q_OBJECT  
43 -  
44 -public:  
45 - virtual bool timeVarying() const { return true; }  
46 -  
47 - virtual void project(const Template &src, Template &dst) const  
48 - {  
49 - qFatal("No const project defined for time-varying transform");  
50 - (void) dst; (void) src;  
51 - }  
52 -  
53 - virtual void project(const TemplateList &src, TemplateList &dst) const  
54 - {  
55 - qFatal("No const project defined for time-varying transform");  
56 - (void) dst; (void) src;  
57 - }  
58 -  
59 - // Get a compile failure if this isn't here to go along with the other  
60 - // projectUpdate, no idea why  
61 - virtual void projectUpdate(const Template & src, Template & dst)  
62 - {  
63 - (void) src; (void) dst;  
64 - qFatal("do something useful");  
65 - }  
66 -  
67 - virtual void projectUpdate(const TemplateList &src, TemplateList &dst)  
68 - {  
69 - foreach (const Template & src_part, src) {  
70 - Template out;  
71 - projectUpdate(src_part, out);  
72 - dst.append(out);  
73 - }  
74 - }  
75 -  
76 - /*!  
77 - *\brief For transforms that don't do any training, this default implementation  
78 - * which creates a new copy of the Transform from its description string is sufficient.  
79 - */  
80 - virtual Transform * smartCopy()  
81 - {  
82 - return this->clone();  
83 - }  
84 -  
85 -  
86 -protected:  
87 - TimeVaryingTransform(bool independent = true, bool trainable = true) : Transform(independent, trainable) {} 34 + MetaTransform() : Transform(false) {}
88 }; 35 };
89 36
90 /*! 37 /*!
91 - * \brief A br::Transform expecting multiple matrices per template. 38 + * \brief A br::MetaTransform that does not require training data.
92 */ 39 */
93 -class BR_EXPORT MetaTransform : public Transform 40 +class BR_EXPORT UntrainableMetaTransform : public UntrainableTransform
94 { 41 {
95 Q_OBJECT 42 Q_OBJECT
96 43
97 protected: 44 protected:
98 - MetaTransform() : Transform(false) {} 45 + UntrainableMetaTransform() : UntrainableTransform(false) {}
99 }; 46 };
100 47
101 -  
102 class TransformCopier : public ResourceMaker<Transform> 48 class TransformCopier : public ResourceMaker<Transform>
103 { 49 {
104 public: 50 public:
@@ -151,6 +97,71 @@ private: @@ -151,6 +97,71 @@ private:
151 Transform * baseTransform; 97 Transform * baseTransform;
152 }; 98 };
153 99
  100 +/*!
  101 + * \brief A br::Transform for which the results of project may change due to prior calls to project
  102 + */
  103 +class BR_EXPORT TimeVaryingTransform : public Transform
  104 +{
  105 + Q_OBJECT
  106 +
  107 +public:
  108 +
  109 + virtual bool timeVarying() const { return true; }
  110 +
  111 + virtual void project(const Template &src, Template &dst) const
  112 + {
  113 + timeInvariantAlias->project(src,dst);
  114 + }
  115 +
  116 + virtual void project(const TemplateList &src, TemplateList &dst) const
  117 + {
  118 + timeInvariantAlias->project(src,dst);
  119 + }
  120 +
  121 + // Get a compile failure if this isn't here to go along with the other
  122 + // projectUpdate, no idea why
  123 + virtual void projectUpdate(const Template & src, Template & dst)
  124 + {
  125 + (void) src; (void) dst;
  126 + qFatal("do something useful");
  127 + }
  128 +
  129 + virtual void projectUpdate(const TemplateList &src, TemplateList &dst)
  130 + {
  131 + foreach (const Template & src_part, src) {
  132 + Template out;
  133 + projectUpdate(src_part, out);
  134 + dst.append(out);
  135 + }
  136 + }
  137 +
  138 + /*!
  139 + *\brief For transforms that don't do any training, this default implementation
  140 + * which creates a new copy of the Transform from its description string is sufficient.
  141 + */
  142 + virtual Transform * smartCopy()
  143 + {
  144 + return this->clone();
  145 + }
  146 +
  147 + void init()
  148 + {
  149 + delete timeInvariantAlias;
  150 + timeInvariantAlias = new TimeInvariantWrapperTransform(this);
  151 + }
  152 +
  153 +protected:
  154 + Transform * timeInvariantAlias;
  155 + TimeVaryingTransform(bool independent = true, bool trainable = true) : Transform(independent, trainable)
  156 + {
  157 + timeInvariantAlias = NULL;
  158 + }
  159 + ~TimeVaryingTransform()
  160 + {
  161 + delete timeInvariantAlias;
  162 + }
  163 +};
  164 +
154 165
155 /*! 166 /*!
156 * \brief A MetaTransform that aggregates some sub-transforms 167 * \brief A MetaTransform that aggregates some sub-transforms
@@ -165,15 +176,17 @@ public: @@ -165,15 +176,17 @@ public:
165 176
166 virtual void project(const Template &src, Template &dst) const 177 virtual void project(const Template &src, Template &dst) const
167 { 178 {
168 - if (timeVarying()) qFatal("No const project defined for time-varying transform"); 179 + if (timeVarying()) {
  180 + timeInvariantAlias->project(src,dst);
  181 + return;
  182 + }
169 _project(src, dst); 183 _project(src, dst);
170 } 184 }
171 185
172 virtual void project(const TemplateList &src, TemplateList &dst) const 186 virtual void project(const TemplateList &src, TemplateList &dst) const
173 { 187 {
174 if (timeVarying()) { 188 if (timeVarying()) {
175 - CompositeTransform * non_const = const_cast<CompositeTransform *>(this);  
176 - non_const->projectUpdate(src,dst); 189 + timeInvariantAlias->project(src,dst);
177 return; 190 return;
178 } 191 }
179 _project(src, dst); 192 _project(src, dst);
@@ -190,6 +203,10 @@ public: @@ -190,6 +203,10 @@ public:
190 isTimeVarying = isTimeVarying || transform->timeVarying(); 203 isTimeVarying = isTimeVarying || transform->timeVarying();
191 trainable = trainable || transform->trainable; 204 trainable = trainable || transform->trainable;
192 } 205 }
  206 +
  207 + // If we are time varying, set up timeInvariantAlias
  208 + if (this->timeVarying())
  209 + TimeVaryingTransform::init();
193 } 210 }
194 211
195 /*! 212 /*!
openbr/plugins/phash.cmake deleted
1 -set(BR_WITH_PHASH OFF CACHE BOOL "Build with pHash")  
2 -  
3 -if(${BR_WITH_PHASH})  
4 - find_package(pHash REQUIRED)  
5 - find_package(CImg REQUIRED)  
6 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/phash.cpp ${PHASH_SRC})  
7 -endif()  
openbr/plugins/phash.cpp deleted
1 -#include <opencv2/core/core.hpp>  
2 -#include <pHash.h>  
3 -#include <mm_plugin.h>  
4 -  
5 -using namespace mm;  
6 -  
7 -/**** PHASH ****/  
8 -class pHashEnroll : public UntrainableFeature  
9 -{  
10 - void project(const Matrix &src, Matrix &dst) const  
11 - {  
12 - CImg<uint8_t> cImg(src.data, src.cols, src.rows, 1, src.channels());  
13 - cv::Mat m(1, sizeof(ulong64), CV_8UC1);  
14 - ulong64 hash;  
15 - if (ph_dct_imagehash(cImg, hash) == -1)  
16 - qFatal("pHashEnroll::project ph_dct_imagehash failure for file %s.", qPrintable(src.metadata.fileName));  
17 - memcpy(m.data, &hash, sizeof(ulong64));  
18 - dst = Matrix(m, src.metadata);  
19 - }  
20 -  
21 - /*** Taken from pHash, modified to take in a CImg instead of a file. ***/  
22 - static CImg<float>* ph_dct_matrix(const int N){  
23 - CImg<float> *ptr_matrix = new CImg<float>(N,N,1,1,1/sqrt((float)N));  
24 - const float c1 = sqrt(2.0/N);  
25 - for (int x=0;x<N;x++){  
26 - for (int y=1;y<N;y++){  
27 - *ptr_matrix->data(x,y) = c1*cos((cimg::PI/2/N)*y*(2*x+1));  
28 - }  
29 - }  
30 - return ptr_matrix;  
31 - }  
32 -  
33 - static int ph_dct_imagehash(CImg<uint8_t> src, ulong64 &hash)  
34 - {  
35 - CImg<float> meanfilter(7,7,1,1,1);  
36 - CImg<float> img;  
37 - if (src.spectrum() == 3){  
38 - img = src.RGBtoYCbCr().channel(0).get_convolve(meanfilter);  
39 - } else if (src.spectrum() == 4){  
40 - int width = img.width();  
41 - int height = img.height();  
42 - int depth = img.depth();  
43 - img = src.crop(0,0,0,0,width-1,height-1,depth-1,2).RGBtoYCbCr().channel(0).get_convolve(meanfilter);  
44 - } else {  
45 - img = src.channel(0).get_convolve(meanfilter);  
46 - }  
47 -  
48 - img.resize(32,32);  
49 - CImg<float> *C = ph_dct_matrix(32);  
50 - CImg<float> Ctransp = C->get_transpose();  
51 -  
52 - CImg<float> dctImage = (*C)*img*Ctransp;  
53 -  
54 - CImg<float> subsec = dctImage.crop(1,1,8,8).unroll('x');;  
55 -  
56 - float median = subsec.median();  
57 - ulong64 one = 0x0000000000000001;  
58 - hash = 0x0000000000000000;  
59 - for (int i=0;i< 64;i++){  
60 - float current = subsec(i);  
61 - if (current > median)  
62 - hash |= one;  
63 - one = one << 1;  
64 - }  
65 -  
66 - delete C;  
67 -  
68 - return 0;  
69 - }  
70 -};  
71 -  
72 -MM_REGISTER(Feature, pHashEnroll, false)  
73 -  
74 -  
75 -/**** PHASH_COMPARE ****/  
76 -class pHashCompare : public ComparerBase  
77 -{  
78 - float compare(const cv::Mat &a, const cv::Mat &b) const  
79 - {  
80 - return 1.f - 1.f * ph_hamming_distance(*reinterpret_cast<ulong64*>(a.data), *reinterpret_cast<ulong64*>(b.data)) / 64;  
81 - }  
82 -};  
83 -  
84 -MM_REGISTER(Comparer, pHashCompare, false)  
85 -  
86 -  
87 -/**** PHASH ****/  
88 -class pHash : public Algorithm  
89 -{  
90 - QString algorithm() const  
91 - {  
92 - return "Open+pHashEnroll:Identity:pHashCompare";  
93 - }  
94 -};  
95 -  
96 -MM_REGISTER(Algorithm, pHash, false)  
openbr/plugins/pp4.cmake deleted
1 -set(BR_WITH_PP4 OFF CACHE BOOL "Build with PittPatt 4")  
2 -  
3 -if(${BR_WITH_PP4})  
4 - find_package(PP4 REQUIRED)  
5 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/pp4.cpp)  
6 - set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${PP4_LIBS})  
7 - install(DIRECTORY ${PP4_DIR}/lib/ DESTINATION lib)  
8 - install(DIRECTORY ${PP4_DIR}/models/ DESTINATION models/pp4)  
9 -endif()  
openbr/plugins/pp4.cpp deleted
1 -#include <QThreadPool>  
2 -#include <pittpatt_errors.h>  
3 -#include <pittpatt_nc_sdk.h>  
4 -#include <pittpatt_raw_image_io.h>  
5 -#include <pittpatt_license.h>  
6 -#include <mm_plugin.h>  
7 -  
8 -#define TRY(CC) \  
9 -{ \  
10 - if ((CC) != PPR_SUCCESS) qFatal("%d error (%s, %d): %s.", CC, __FILE__, __LINE__, ppr_error_message(CC)); \  
11 -}  
12 -  
13 -#define TRY_VIDEO(CC) \  
14 -{ \  
15 - if ((CC) != PPR_VIDEO_IO_SUCCESS) qFatal("%d error (%s, %d): %s.", CC, __FILE__, __LINE__, ppr_video_io_error_message(CC)); \  
16 -}  
17 -  
18 -#define TRY_RAW_IMAGE(CC) \  
19 -{ \  
20 - if ((CC) != PPR_RAW_IMAGE_SUCCESS) qFatal("%d error (%s, %d): %s.", CC, __FILE__, __LINE__, ppr_raw_image_error_message(CC)); \  
21 -}  
22 -  
23 -using namespace mm;  
24 -  
25 -/*!  
26 - * \brief PittPatt 4 context  
27 - * \author Josh Klontz \cite jklontz  
28 - * \warning Needs a maintainer.  
29 - */  
30 -struct PP4Context  
31 -{  
32 - static ppr_context_type context;  
33 -  
34 - static void createRawImage(const cv::Mat &src, ppr_raw_image_type &dst)  
35 - {  
36 - ppr_raw_image_create(&dst, src.cols, src.rows, PPR_RAW_IMAGE_BGR24);  
37 - assert((src.type() == CV_8UC3) && src.isContinuous());  
38 - memcpy(dst.data, src.data, 3*src.rows*src.cols);  
39 - }  
40 -  
41 - static void createMat(const ppr_template_type &src, cv::Mat &dst)  
42 - {  
43 - ppr_flat_template_type flat_template;  
44 - TRY(ppr_flatten_template(context,src,&flat_template))  
45 - dst = cv::Mat(1, flat_template.num_bytes, CV_8UC1, flat_template.data).clone();  
46 - ppr_free_flat_template(flat_template);  
47 - }  
48 -  
49 - static void createTemplate(const cv::Mat &src, ppr_template_type *dst)  
50 - {  
51 - ppr_flat_template_type flat_template;  
52 - flat_template.num_bytes = src.cols;  
53 - flat_template.data = src.data;  
54 - TRY(ppr_unflatten_template(context, flat_template, dst))  
55 - }  
56 -  
57 - static QString toString(const ppr_landmark_category_type &category)  
58 - {  
59 - switch (category) {  
60 - case PPR_LANDMARK_LEFT_EYE:  
61 - return "Left_Eye";  
62 - case PPR_LANDMARK_RIGHT_EYE:  
63 - return "Right_Eye";  
64 - case PPR_LANDMARK_NOSE_BASE:  
65 - return "Nose_Base";  
66 - case PPR_LANDMARK_NOSE_BRIDGE:  
67 - return "Nose_Bridge";  
68 - case PPR_LANDMARK_NOSE_TIP:  
69 - return "Nose_Tip";  
70 - case PPR_LANDMARK_NOSE_TOP:  
71 - return "Nose_Top";  
72 - case PPR_LANDMARK_EYE_NOSE:  
73 - return "Eye_Nose";  
74 - case PPR_LANDMARK_MOUTH:  
75 - return "Mouth";  
76 - }  
77 -  
78 - return "Unknown";  
79 - }  
80 -  
81 - static File toMetadata(const ppr_object_type &object)  
82 - {  
83 - File metadata;  
84 - metadata.insert("PP4_Object_X", object.position.x - object.dimensions.width/2);  
85 - metadata.insert("PP4_Object_Y", object.position.y - object.dimensions.height/2);  
86 - metadata.insert("PP4_Object_Width", object.dimensions.width);  
87 - metadata.insert("PP4_Object_Height", object.dimensions.height);  
88 - metadata.insert("PP4_Object_Confidence", object.confidence);  
89 - metadata.insert("PP4_Object_Roll", object.rotation.roll);  
90 - metadata.insert("PP4_Object_Pitch", object.rotation.pitch);  
91 - metadata.insert("PP4_Object_Yaw", object.rotation.yaw);  
92 - metadata.insert("PP4_Object_Precision", object.rotation.precision);  
93 - metadata.insert("PP4_Object_ModelID", object.model_id);  
94 - metadata.insert("PP4_Object_NumLandmarks", object.num_landmarks);  
95 - metadata.insert("PP4_Object_Size", object.size);  
96 -  
97 - QList<ppr_landmark_category_type> categories;  
98 - categories << PPR_LANDMARK_RIGHT_EYE  
99 - << PPR_LANDMARK_LEFT_EYE  
100 - << PPR_LANDMARK_NOSE_BASE  
101 - << PPR_LANDMARK_NOSE_BRIDGE  
102 - << PPR_LANDMARK_NOSE_TIP  
103 - << PPR_LANDMARK_NOSE_TOP  
104 - << PPR_LANDMARK_EYE_NOSE  
105 - << PPR_LANDMARK_MOUTH;  
106 -  
107 - for (int i=0; i<categories.size(); i++) {  
108 - ppr_landmark_category_type category = categories[i];  
109 - QString metadataString = QString("PP4_Landmark%1_%2").arg(QString::number(i), toString(category));  
110 -  
111 - bool found = false;  
112 - for (int j=0; j<object.num_landmarks; j++) {  
113 - ppr_landmark_type &landmark = object.landmarks[j];  
114 - if (landmark.category != category) continue;  
115 -  
116 - metadata.insert(metadataString+"_X", landmark.position.x);  
117 - metadata.insert(metadataString+"_Y", landmark.position.y);  
118 - metadata.insert(metadataString+"_Category", landmark.category);  
119 - metadata.insert(metadataString+"_ModelID", landmark.model_id);  
120 - metadata.insert(metadataString+"_Index", j);  
121 - found = true;  
122 - break;  
123 - }  
124 -  
125 - if (!found) {  
126 - metadata.insert(metadataString+"_X", -1);  
127 - metadata.insert(metadataString+"_Y", -1);  
128 - metadata.insert(metadataString+"_Category", -1);  
129 - metadata.insert(metadataString+"_ModelID", -1);  
130 - metadata.insert(metadataString+"_Index", -1);  
131 - }  
132 - }  
133 -  
134 - return metadata;  
135 - }  
136 -  
137 - static ppr_object_type fromMetadata(const File &metadata)  
138 - {  
139 - ppr_object_type object;  
140 -  
141 - object.position.x = metadata.value("PP4_Object_X").toFloat() + metadata.value("PP4_Object_Width").toFloat()/2;  
142 - object.position.y = metadata.value("PP4_Object_Y").toFloat() + metadata.value("PP4_Object_Height").toFloat()/2;  
143 - object.dimensions.width = metadata.value("PP4_Object_Width").toFloat();  
144 - object.dimensions.height = metadata.value("PP4_Object_Height").toFloat();  
145 - object.confidence = metadata.value("PP4_Object_Confidence").toFloat();  
146 - object.rotation.roll = metadata.value("PP4_Object_Roll").toFloat();  
147 - object.rotation.pitch = metadata.value("PP4_Object_Pitch").toFloat();  
148 - object.rotation.yaw = metadata.value("PP4_Object_Yaw").toFloat();  
149 - object.rotation.precision = (ppr_precision_type) metadata.value("PP4_Object_Precision").toFloat();  
150 - object.model_id = metadata.value("PP4_Object_ModelID").toInt();  
151 - object.num_landmarks = metadata.value("PP4_Object_NumLandmarks").toInt();  
152 - object.size = metadata.value("PP4_Object_Size").toFloat();  
153 -  
154 - QStringList landmarkNames = QStringList(metadata.keys()).filter(QRegExp("(.*)_Category")).replaceInStrings("_Category", "");  
155 - object.landmarks = new ppr_landmark_type[object.num_landmarks];  
156 - for (int j=0; j<landmarkNames.size(); j++) {  
157 - int landmarkIndex = metadata.value(landmarkNames[j]+"_Index").toInt();  
158 - if (landmarkIndex == -1) continue;  
159 - object.landmarks[landmarkIndex].position.x = metadata.value(landmarkNames[j]+"_X").toFloat();  
160 - object.landmarks[landmarkIndex].position.y = metadata.value(landmarkNames[j]+"_Y").toFloat();  
161 - object.landmarks[landmarkIndex].category = (ppr_landmark_category_type)metadata.value(landmarkNames[j]+"_Category").toInt();  
162 - object.landmarks[landmarkIndex].model_id = metadata.value(landmarkNames[j]+"_ModelID").toInt();  
163 - landmarkIndex++;  
164 - }  
165 -  
166 - return object;  
167 - }  
168 -  
169 - static void freeObject(ppr_object_type &object)  
170 - {  
171 - delete[] object.landmarks;  
172 - object.landmarks = NULL;  
173 - object.num_landmarks = 0;  
174 - }  
175 -};  
176 -  
177 -ppr_context_type PP4Context::context;  
178 -  
179 -/*!  
180 - * \ingroup initializers  
181 - * \brief Initialize PittPatt 4  
182 - * \author Josh Klontz \cite jklontz  
183 - * \warning Needs a maintainer.  
184 - */  
185 -class PP4Initializer : public Initializer  
186 - , public PP4Context  
187 -{  
188 - Q_OBJECT  
189 -  
190 - void initialize() const  
191 - {  
192 - context = ppr_get_context();  
193 - TRY(ppr_enable_recognition(context))  
194 - TRY(ppr_set_license(context, my_license_id, my_license_key))  
195 - TRY(ppr_set_models_path(context, qPrintable(Globals->SDKPath + "/models/pp4")))  
196 - TRY(ppr_set_num_recognition_threads(context, QThreadPool::globalInstance()->maxThreadCount()))  
197 - TRY(ppr_set_num_detection_threads(context, 1))  
198 - TRY(ppr_set_detection_precision(context, PPR_FINE_PRECISION))  
199 - TRY(ppr_set_landmark_detector_type(context, PPR_DUAL_MULTI_POSE_LANDMARK_DETECTOR, PPR_AUTOMATIC_LANDMARKS))  
200 - TRY(ppr_set_min_size(context, 4))  
201 - TRY(ppr_set_frontal_yaw_constraint(context, PPR_FRONTAL_YAW_CONSTRAINT_PERMISSIVE))  
202 - TRY(ppr_set_template_extraction_type(context, PPR_EXTRACT_DOUBLE))  
203 - TRY(ppr_initialize_context(context))  
204 - Globals->Abbreviations.insert("PP4", "Open+PP4Detect!PP4Enroll:PP4Compare");  
205 - }  
206 -  
207 - void finalize() const  
208 - {  
209 - TRY(ppr_release_context(context))  
210 - ppr_finalize_sdk();  
211 - }  
212 -};  
213 -  
214 -MM_REGISTER(Initializer, PP4Initializer, "")  
215 -  
216 -/*!  
217 - * \ingroup transforms  
218 - * \brief Detect a face in PittPatt 4  
219 - * \author Josh Klontz \cite jklontz  
220 - * \warning Needs a maintainer.  
221 - */  
222 -class PP4Detect : public UntrainableMetaFeature  
223 - , public PP4Context  
224 -{  
225 - Q_OBJECT  
226 -  
227 - void project(const Template &src, Template &dst) const  
228 - {  
229 - dst.file = src.file;  
230 -  
231 - foreach (const cv::Mat &matrix, src) {  
232 - ppr_raw_image_type raw_image;  
233 - createRawImage(matrix, raw_image);  
234 - ppr_image_type image;  
235 - TRY(ppr_create_image(raw_image, &image))  
236 - ppr_object_list_type object_list;  
237 - TRY(ppr_detect_objects(context, image, &object_list))  
238 -  
239 - QList<ppr_object_type> objects;  
240 - if (src.file.getBool("ForceEnrollment")) objects = getBestObject(object_list);  
241 - else objects = getAllObjects(object_list);  
242 -  
243 - foreach (const ppr_object_type &object, objects) {  
244 - dst.file.append(toMetadata(object));  
245 - dst += matrix;  
246 - }  
247 -  
248 - ppr_free_object_list(object_list);  
249 - ppr_free_image(image);  
250 - ppr_raw_image_free(raw_image);  
251 - }  
252 -  
253 - if (src.file.getBool("ForceEnrollment") && dst.isEmpty()) dst += cv::Mat();  
254 - }  
255 -  
256 -private:  
257 - QList<ppr_object_type> getBestObject(ppr_object_list_type object_list) const  
258 - {  
259 - int best_index = -1;  
260 - float best_confidence = 0;  
261 - for (int i=0; i<object_list.num_objects; i++) {  
262 - ppr_object_type object = object_list.objects[i];  
263 - ppr_object_suitability_type suitability;  
264 - TRY(ppr_is_object_suitable_for_recognition(context, object, &suitability))  
265 - if (suitability != PPR_OBJECT_SUITABLE_FOR_RECOGNITION) continue;  
266 - if ((object.confidence > best_confidence) ||  
267 - (best_index == -1)) {  
268 - best_confidence = object.confidence;  
269 - best_index = i;  
270 - }  
271 - }  
272 -  
273 - QList<ppr_object_type> objects;  
274 - if (best_index != -1) objects.append(object_list.objects[best_index]);  
275 - return objects;  
276 - }  
277 -  
278 - QList<ppr_object_type> getAllObjects(ppr_object_list_type object_list) const  
279 - {  
280 - QList<ppr_object_type> objects;  
281 - for (int i=0; i<object_list.num_objects; i++)  
282 - objects.append(object_list.objects[i]);  
283 - return objects;  
284 - }  
285 -};  
286 -  
287 -MM_REGISTER(Feature, PP4Detect, "")  
288 -  
289 -/*!  
290 - * \ingroup transforms  
291 - * \brief Enroll face in PittPatt 4  
292 - * \author Josh Klontz \cite jklontz  
293 - * \warning Needs a maintainer.  
294 - */  
295 -class PP4Enroll : public UntrainableMetaFeature  
296 - , public PP4Context  
297 -{  
298 - Q_OBJECT  
299 -  
300 - void project(const Template &src, Template &dst) const  
301 - {  
302 - if (!src.m().data) {  
303 - dst += cv::Mat();  
304 - return;  
305 - }  
306 -  
307 - ppr_raw_image_type raw_image;  
308 - createRawImage(src, raw_image);  
309 - ppr_image_type image;  
310 - TRY(ppr_create_image(raw_image, &image))  
311 -  
312 - ppr_object_type object = fromMetadata(src.file);  
313 -  
314 - ppr_template_type curr_template;  
315 - TRY(ppr_extract_template_from_object(context, image, object, &curr_template))  
316 -  
317 - freeObject(object);  
318 -  
319 - cv::Mat m;  
320 - createMat(curr_template, m);  
321 - dst += m;  
322 -  
323 - ppr_free_template(curr_template);  
324 - ppr_free_image(image);  
325 - ppr_raw_image_free(raw_image);  
326 - }  
327 -};  
328 -  
329 -MM_REGISTER(Feature, PP4Enroll, "")  
330 -  
331 -  
332 -class PP4Compare : public Comparer,  
333 - public PP4Context  
334 -{  
335 - Q_OBJECT  
336 -  
337 - void compare(const TemplateList &target, const TemplateList &query, Output *output) const  
338 - {  
339 - ppr_gallery_type target_gallery, query_gallery;  
340 - ppr_create_gallery(context, &target_gallery);  
341 - ppr_create_gallery(context, &query_gallery);  
342 - QList<int> target_template_ids, query_template_ids;  
343 - enroll(target, &target_gallery, target_template_ids);  
344 - enroll(query, &query_gallery, query_template_ids);  
345 -  
346 - ppr_similarity_matrix_type similarity_matrix;  
347 - TRY(ppr_compare_galleries(context, query_gallery, target_gallery, &similarity_matrix))  
348 -  
349 - for (int i=0; i<query_template_ids.size(); i++) {  
350 - int query_template_id = query_template_ids[i];  
351 - for (int j=0; j<target_template_ids.size(); j++) {  
352 - int target_template_id = target_template_ids[j];  
353 - float score = -std::numeric_limits<float>::max();  
354 - if ((query_template_id != -1) && (target_template_id != -1)) {  
355 - TRY(ppr_get_similarity_matrix_element(context, similarity_matrix, query_template_id, target_template_id, &score))  
356 - }  
357 - output->setData(score, i, j);  
358 - }  
359 - }  
360 -  
361 - ppr_free_similarity_matrix(similarity_matrix);  
362 - ppr_free_gallery(target_gallery);  
363 - ppr_free_gallery(query_gallery);  
364 - }  
365 -  
366 - void enroll(const TemplateList &templates, ppr_gallery_type *gallery, QList<int> &template_ids) const  
367 - {  
368 - foreach (const Template &t, templates) {  
369 - if (t.m().data) {  
370 - ppr_template_type u;  
371 - createTemplate(t.m(), &u);  
372 - int template_id;  
373 - TRY(ppr_copy_template_to_gallery(context, gallery, u, &template_id))  
374 - template_ids.append(template_id);  
375 - ppr_free_template(u);  
376 - } else {  
377 - template_ids.append(-1);  
378 - }  
379 - }  
380 - }  
381 -};  
382 -  
383 -MM_REGISTER(Comparer, PP4Compare, "")  
384 -  
385 -#include "plugins/pp4.moc"  
openbr/plugins/regions.cpp
@@ -141,13 +141,15 @@ class CatColsTransform : public UntrainableMetaTransform @@ -141,13 +141,15 @@ class CatColsTransform : public UntrainableMetaTransform
141 141
142 void project(const Template &src, Template &dst) const 142 void project(const Template &src, Template &dst) const
143 { 143 {
  144 + int half = src.size()/2;
  145 + for (int i=0; i<half; i++) {
  146 + Mat first = src[i];
  147 + Mat second = src[half+i];
  148 + Mat both;
  149 + hconcat(first, second, both);
  150 + dst.append(both);
  151 + }
144 dst.file = src.file; 152 dst.file = src.file;
145 - Mat m = OpenCVUtils::toMatByRow(src);  
146 - // right now this just splits src in half and joins them horizontally  
147 - // TODO: add partitions parameter for more than a single split  
148 - Mat first = m.rowRange(Range(0, m.rows/2));  
149 - Mat second = m.rowRange(Range(m.rows/2, m.rows));  
150 - hconcat(first, second, dst);  
151 } 153 }
152 }; 154 };
153 155
openbr/plugins/stream.cpp
@@ -707,8 +707,7 @@ public: @@ -707,8 +707,7 @@ public:
707 if (input == NULL) { 707 if (input == NULL) {
708 qFatal("null input to multi-thread stage"); 708 qFatal("null input to multi-thread stage");
709 } 709 }
710 - // Project the input we got  
711 - transform->projectUpdate(input->data); 710 + input->data >> *transform;
712 711
713 should_continue = nextStage->tryAcquireNextStage(input); 712 should_continue = nextStage->tryAcquireNextStage(input);
714 713
@@ -1300,6 +1299,12 @@ public: @@ -1300,6 +1299,12 @@ public:
1300 { 1299 {
1301 if (!transform) 1300 if (!transform)
1302 return; 1301 return;
  1302 +
  1303 + // Set up timeInvariantAlias
  1304 + // this is only safe because copies are actually made in project
  1305 + // calls, not during init.
  1306 + TimeVaryingTransform::init();
  1307 +
1303 trainable = transform->trainable; 1308 trainable = transform->trainable;
1304 1309
1305 basis.setParent(this->parent()); 1310 basis.setParent(this->parent());
openbr/plugins/topsurf.cmake deleted
1 -set(BR_WITH_TOPSURF OFF CACHE BOOL "Build with TOP-SURF")  
2 -  
3 -if(${BR_WITH_TOPSURF})  
4 - find_package(TopSurf REQUIRED)  
5 - set(THIRDPARTY_SRC ${THIRDPARTY_SRC} plugins/topsurf.cpp ${TOPSURF_SRC} ${TOPSURF_FLANN_SRC})  
6 - install(DIRECTORY ${TOPSURF_DIR}/dictionary_10000  
7 - ${TOPSURF_DIR}/dictionary_20000  
8 - ${TOPSURF_DIR}/dictionary_40000  
9 - DESTINATION models/topsurf)  
10 -endif()  
openbr/plugins/topsurf.cpp deleted
1 -#include <topsurf/descriptor.h>  
2 -#include <topsurf/topsurf.h>  
3 -#include <mm_plugin.h>  
4 -  
5 -#include "common/opencvutils.h"  
6 -#include "common/qtutils.h"  
7 -#include "common/resource.h"  
8 -  
9 -using namespace cv;  
10 -using namespace mm;  
11 -using namespace std;  
12 -  
13 -class TopSurfInitializer : public Initializer  
14 -{  
15 - void initialize() const  
16 - {  
17 - Globals.Abbreviations.insert("TopSurf", "Open!TopSurfExtract(40000):TopSurfCompare");  
18 - Globals.Abbreviations.insert("TopSurfM", "Open!TopSurfExtract(1000000):TopSurfCompare");  
19 - Globals.Abbreviations.insert("TopSurfKNN", "Open!TopSurfExtract+TopSurfKNN");  
20 - Globals.Abbreviations.insert("DocumentClassification", "TopSurfKNN");  
21 - }  
22 -  
23 - void finalize() const {}  
24 -};  
25 -  
26 -MM_REGISTER(Initializer, TopSurfInitializer, false)  
27 -  
28 -  
29 -class TopSurfResourceMaker : public ResourceMaker<TopSurf>  
30 -{  
31 - QString file;  
32 -  
33 -public:  
34 - TopSurfResourceMaker(const QString &dictionary)  
35 - {  
36 - file = Globals.SDKPath + "/models/topsurf/dictionary_" + dictionary;  
37 - }  
38 -  
39 -private:  
40 - TopSurf *make() const  
41 - {  
42 - TopSurf *topSurf = new TopSurf(256, 100);  
43 - if (!topSurf->LoadDictionary(qPrintable(file)))  
44 - qFatal("TopSurfResourceMaker::make failed to load dictionary.");  
45 - return topSurf;  
46 - }  
47 -};  
48 -  
49 -  
50 -/****  
51 -TopSurfExtract  
52 - Wrapper to TopSurf::ExtractDescriptor()  
53 - B. Thomee, E.M. Bakker, and M.S. Lew, "TOP-SURF: a visual words toolkit",  
54 - in Proceedings of the 18th ACM International Conference on Multimedia, pp. 1473-1476, Firenze, Italy, 2010.  
55 -****/  
56 -class TopSurfExtract : public UntrainableFeature  
57 -{  
58 - Q_OBJECT  
59 - Q_PROPERTY(QString dictionary READ get_dictionary WRITE set_dictionary)  
60 - MM_MEMBER(QString, dictionary)  
61 -  
62 - Resource<TopSurf> topSurfResource;  
63 -  
64 -public:  
65 - TopSurfExtract() : topSurfResource(new TopSurfResourceMaker("10000")) {}  
66 -  
67 -private:  
68 - void init()  
69 - {  
70 - topSurfResource.setResourceMaker(new TopSurfResourceMaker(dictionary));  
71 - }  
72 -  
73 - void project(const Template &src, Template &dst) const  
74 - {  
75 - // Compute descriptor (not thread safe)  
76 - TopSurf *topSurf = topSurfResource.acquire();  
77 - TOPSURF_DESCRIPTOR descriptor;  
78 - IplImage iplSrc = src.m();  
79 - if (!topSurf->ExtractDescriptor(iplSrc, descriptor))  
80 - qFatal("TopSurfExtract::project ExtractDescriptor failure.");  
81 - topSurfResource.release(topSurf);  
82 -  
83 - // Copy descriptor and clean up  
84 - unsigned char *data;  
85 - int length;  
86 - Descriptor2Array(descriptor, data, length);  
87 - Mat m(1, length, CV_8UC1);  
88 - memcpy(m.data, data, length);  
89 - delete data;  
90 - TopSurf::ReleaseDescriptor(descriptor);  
91 - dst = m;  
92 - }  
93 -  
94 -public:  
95 - static QString args()  
96 - {  
97 - return "10000|20000|40000 dictionary = 10000";  
98 - }  
99 -  
100 - static TopSurfExtract *make(const QStringList &args)  
101 - {  
102 - (void) args;  
103 - return new TopSurfExtract();  
104 - }  
105 -};  
106 -  
107 -MM_REGISTER(Feature, TopSurfExtract, true)  
108 -  
109 -  
110 -class TopSurfHist : public UntrainableFeature  
111 -{  
112 - Q_OBJECT  
113 - Q_PROPERTY(int size READ get_size WRITE set_size)  
114 - MM_MEMBER(int, size)  
115 -  
116 - void project(const Template &src, Template &dst) const  
117 - {  
118 - TOPSURF_DESCRIPTOR td;  
119 - Array2Descriptor(src.m().data, td);  
120 -  
121 - Mat m(1, size, CV_32FC1);  
122 - m.setTo(0);  
123 - for (int i=0; i<td.count; i++)  
124 - m.at<float>(0, td.visualword[i].identifier % size)++;  
125 -  
126 - TopSurf::ReleaseDescriptor(td);  
127 - dst = m;  
128 - }  
129 -  
130 -public:  
131 - static QString args()  
132 - {  
133 - return "int size = 10000";  
134 - }  
135 -  
136 - static TopSurfHist *make(const QStringList &args)  
137 - {  
138 - (void) args;  
139 - return new TopSurfHist();  
140 - }  
141 -};  
142 -  
143 -MM_REGISTER(Feature, TopSurfHist, true)  
144 -  
145 -  
146 -// Wrapper around TopSurf CompareDescriptors  
147 -float TopSurfSimilarity(const Mat &a, const Mat &b, bool cosine)  
148 -{  
149 - TOPSURF_DESCRIPTOR tda, tdb;  
150 - Array2Descriptor(a.data, tda);  
151 - Array2Descriptor(b.data, tdb);  
152 -  
153 - float result;  
154 - if (cosine) result = TopSurf::CompareDescriptorsCosine(tda, tdb);  
155 - else result = TopSurf::CompareDescriptorsAbsolute(tda, tdb);  
156 -  
157 - TopSurf::ReleaseDescriptor(tda);  
158 - TopSurf::ReleaseDescriptor(tdb);  
159 - return result;  
160 -}  
161 -  
162 -  
163 -/****  
164 -TopSurfCompare  
165 - Wrapper to TopSurf_CompareDescriptors()  
166 - B. Thomee, E.M. Bakker, and M.S. Lew, "TOP-SURF: a visual words toolkit",  
167 - in Proceedings of the 18th ACM International Conference on Multimedia, pp. 1473-1476, Firenze, Italy, 2010.  
168 -****/  
169 -class TopSurfCompare : public ComparerBase  
170 -{  
171 - Q_OBJECT  
172 - Q_PROPERTY(bool cosine READ get_cosine WRITE set_cosine)  
173 - MM_MEMBER(bool, cosine)  
174 -  
175 - float compare(const Mat &a, const Mat &b) const  
176 - {  
177 - return TopSurfSimilarity(a, b, cosine);  
178 - }  
179 -  
180 -public:  
181 - static QString args()  
182 - {  
183 - return "bool cosine = 1";  
184 - }  
185 -  
186 - static TopSurfCompare *make(const QStringList &args)  
187 - {  
188 - (void) args;  
189 - return new TopSurfCompare();  
190 - }  
191 -};  
192 -  
193 -MM_REGISTER(Comparer, TopSurfCompare, true)  
194 -  
195 -  
196 -/****  
197 -TopSurfKNN  
198 - KNN classifier for TopSurf features.  
199 -****/  
200 -class TopSurfKNN : public Feature  
201 -{  
202 - Q_OBJECT  
203 - Q_PROPERTY(int k READ get_k WRITE set_k)  
204 - Q_PROPERTY(bool cosine READ get_cosine WRITE set_cosine)  
205 - MM_MEMBER(int, k)  
206 - MM_MEMBER(bool, cosine)  
207 -  
208 - TemplateList data;  
209 -  
210 -private:  
211 - void train(const TemplateList &data)  
212 - {  
213 - this->data = data;  
214 - }  
215 -  
216 - void project(const Template &src, Template &dst) const  
217 - {  
218 - // Compute distance to each descriptor  
219 - QList< QPair<float, int> > distances; // <distance, label>  
220 - distances.reserve(data.size());  
221 - foreach (const Template &t, data)  
222 - distances.append(QPair<float, int>(TopSurfSimilarity(src, t, cosine), t.file.label()));  
223 -  
224 - // Find nearest neighbors  
225 - qSort(distances);  
226 - QHash<int, QPair<int, float> > counts; // <label, <count, cumulative distance>>  
227 - for (int i=0; i<k; i++) {  
228 - QPair<float,int> &distance = distances[i];  
229 - QPair<int,float> &count = counts[distance.second];  
230 - count.first++;  
231 - count.second += distance.first;  
232 - }  
233 -  
234 - // Find most occuring label  
235 - int best_label = -1;  
236 - int best_count = 0;  
237 - float best_distance = numeric_limits<float>::max();  
238 - foreach (int label, counts.keys()) {  
239 - const QPair<int, float> &count = counts[label];  
240 - if ((count.first > best_count) || ((count.first == best_count) && (count.second < best_distance))) {  
241 - best_label = label;  
242 - best_count = count.first;  
243 - best_distance = count.second;  
244 - }  
245 - }  
246 - assert(best_label != -1);  
247 -  
248 - // Measure confidence  
249 - int rest_count = 0;  
250 - float rest_distance = 0;  
251 - foreach (int label, counts.keys()) {  
252 - if (label != best_label) {  
253 - const QPair<int, float> &count = counts[label];  
254 - rest_count = count.first;  
255 - rest_distance = count.second;  
256 - }  
257 - }  
258 -  
259 - dst = src;  
260 - dst.file["Label"] = best_label;  
261 - dst.file["Confidence"] = (float)best_count/(float)k;  
262 - }  
263 -  
264 - void store(QDataStream &stream) const  
265 - {  
266 - stream << data;  
267 - }  
268 -  
269 - void load(QDataStream &stream)  
270 - {  
271 - stream >> data;  
272 - }  
273 -  
274 -public:  
275 - static QString args()  
276 - {  
277 - return "int k, int cosine = 1";  
278 - }  
279 -  
280 - static TopSurfKNN *make(const QStringList &args)  
281 - {  
282 - (void) args;  
283 - return new TopSurfKNN();  
284 - }  
285 -};  
286 -  
287 -MM_REGISTER(Feature, TopSurfKNN, true)  
288 -  
289 -#include "topsurf.moc"  
openbr/plugins/yubico.cmake deleted
1 -set(BR_WITH_YUBICO OFF CACHE BOOL "Build YubiKey authentication")  
2 -  
3 -if(${BR_WITH_YUBICO})  
4 - find_package(YubiKey REQUIRED) # For decrypting YubiKeys  
5 - find_package(YKPers REQUIRED) # For reading YubiKeys  
6 -  
7 - install(FILES ${YUBIKEY_LICENSE} RENAME YubiKey DESTINATION share/openbr/licenses)  
8 - install(FILES ${YKPERS_LICENSE} RENAME YKPers DESTINATION share/openbr/licenses)  
9 - install(FILES ${YKPERS_RULES} DESTINATION share/openbr)  
10 -  
11 - set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} ${YUBIKEY_SRC} ${YKPERS_SRC} plugins/yubico.cpp)  
12 - set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${YKPERS_LIBS})  
13 -endif()  
openbr/plugins/yubico.cpp deleted
1 -#include <mm_plugin.h>  
2 -#include <yubikey.h>  
3 -#include <ykdef.h>  
4 -#include <ykpers.h>  
5 -#include <stdlib.h>  
6 -#include <time.h>  
7 -  
8 -/****  
9 -YubiKey Challenge-Response Authentication  
10 -  
11 -To configure YubiKeys for mm usage:  
12 -1) Download the cross platform personalization tool from http://yubico.com/personalization-tool.  
13 -2) Insert YubiKey and launch the personalization tool (may require sudo access).  
14 -3) Click "Challenge-Response Mode".  
15 -4) Click "Yubico OTP".  
16 -5) Select "Configuration Slot 2"  
17 -6) In the Private Identity text box enter "21 92 78 11 55 8a".  
18 -7) In the Secret Key text box enter "e7 32 df 49 f3 87 e6 89 04 d2 03 6a 59 ad b7 2f".  
19 -8) Click "Write Configuration".  
20 -9) Done!  
21 -  
22 -Unix implementation derived from "ykchalresp.c" in ykpers repository.  
23 -Windows implementation derived from "MFCTestDlg.cpp" in Yubikey Client API installer.  
24 -  
25 -!!! Attention Linux Users !!!  
26 -cp trunk/3rdparty/ykpers-1.6.3/70-yubikey.rules /etc/udev/rules.d  
27 -  
28 -!!! Attention Windows Users !!!  
29 -Install Yubikey Client API.  
30 -****/  
31 -  
32 -using namespace mm;  
33 -  
34 -static int challenge_response(YK_KEY *yk, int slot,  
35 - unsigned char *challenge, unsigned int len,  
36 - bool hmac, bool may_block, bool verbose, unsigned char output_buf[(SHA1_MAX_BLOCK_SIZE * 2) + 1])  
37 -{  
38 - unsigned char response[64];  
39 - int yk_cmd;  
40 - unsigned int flags = 0;  
41 - unsigned int response_len = 0;  
42 - unsigned int expect_bytes = 0;  
43 -  
44 - memset(response, 0, sizeof(response));  
45 -  
46 - if (may_block)  
47 - flags |= YK_FLAG_MAYBLOCK;  
48 -  
49 - if (verbose) {  
50 - fprintf(stderr, "Sending %i bytes %s challenge to slot %i\n", len, (hmac == true) ? "HMAC" : "Yubico", slot);  
51 - //_yk_hexdump(challenge, len);  
52 - }  
53 -  
54 - switch(slot) {  
55 - case 1:  
56 - yk_cmd = (hmac == true) ? SLOT_CHAL_HMAC1 : SLOT_CHAL_OTP1;  
57 - break;  
58 - case 2:  
59 - yk_cmd = (hmac == true) ? SLOT_CHAL_HMAC2 : SLOT_CHAL_OTP2;  
60 - break;  
61 - }  
62 -  
63 - if (!yk_write_to_key(yk, yk_cmd, challenge, len))  
64 - return 0;  
65 -  
66 - if (verbose) {  
67 - fprintf(stderr, "Reading response...\n");  
68 - }  
69 -  
70 - /* HMAC responses are 160 bits, Yubico 128 */  
71 - expect_bytes = (hmac == true) ? 20 : 16;  
72 -  
73 - if (! yk_read_response_from_key(yk, slot, flags,  
74 - &response, sizeof(response),  
75 - expect_bytes,  
76 - &response_len))  
77 - return 0;  
78 -  
79 - if (hmac && response_len > 20)  
80 - response_len = 20;  
81 - if (! hmac && response_len > 16)  
82 - response_len = 16;  
83 -  
84 - memset(output_buf, 0, SHA1_MAX_BLOCK_SIZE * 2 + 1);  
85 - if (hmac) {  
86 - yubikey_hex_encode((char *)output_buf, (char *)response, response_len);  
87 - } else {  
88 - yubikey_modhex_encode((char *)output_buf, (char *)response, response_len);  
89 - }  
90 - // printf("%s\n", output_buf);  
91 -  
92 - return 1;  
93 -}  
94 -  
95 -/*!  
96 - * \ingroup initializers  
97 - * \brief Initialize yubikey  
98 - * \author Josh Klontz \cite jklontz  
99 - */  
100 -class YubiKey : public Initializer  
101 -{  
102 - Q_OBJECT  
103 -  
104 - void initialize() const  
105 - {  
106 - // Read from device  
107 - YK_KEY *yk = 0;  
108 -  
109 - if (!yk_init())  
110 - qFatal("YubiKey::initialize yk_init failure.");  
111 -  
112 - if (!(yk = yk_open_first_key()))  
113 - qFatal("Could not connect to license.");  
114 -  
115 - // Challenge value is arbitrary  
116 - srand(time(NULL));  
117 - uint8_t challenge[6] = {rand()%255, rand()%255, rand()%255, rand()%255, rand()%255, rand()%255};  
118 - unsigned char output_buf[(SHA1_MAX_BLOCK_SIZE * 2) + 1];  
119 - if (!challenge_response(yk, 2, challenge, 6, false, true, false, output_buf))  
120 - qFatal("YubiKey::initialize challenge_response failure.");  
121 -  
122 - if (yk && !yk_close_key(yk))  
123 - qFatal("YubiKey::initialize yk_close_key failure.");  
124 -  
125 - if (!yk_release())  
126 - qFatal("YubiKey::initialize yk_release failure.");  
127 -  
128 - // Check response  
129 - // Our Secret Key! Shhh...  
130 - const uint8_t key[YUBIKEY_KEY_SIZE] = {0xe7, 0x32, 0xdf, 0x49, 0xf3, 0x87, 0xe6, 0x89, 0x04, 0xd2, 0x03, 0x6a, 0x59, 0xad, 0xb7, 0x2f};  
131 - yubikey_token_st out;  
132 - yubikey_parse(output_buf, key, &out);  
133 -  
134 - // Our Private Identity! Shhh...  
135 - uint8_t uid[YUBIKEY_UID_SIZE] = {0x21, 0x92, 0x78, 0x11, 0x55, 0x8a};  
136 - if ((uid[0] != (out.uid[0] ^ challenge[0])) ||  
137 - (uid[1] != (out.uid[1] ^ challenge[1])) ||  
138 - (uid[2] != (out.uid[2] ^ challenge[2])) ||  
139 - (uid[3] != (out.uid[3] ^ challenge[3])) ||  
140 - (uid[4] != (out.uid[4] ^ challenge[4])) ||  
141 - (uid[5] != (out.uid[5] ^ challenge[5])))  
142 - qFatal("Invalid license.");  
143 - }  
144 -  
145 - void finalize() const  
146 - {  
147 - // Nothing to do  
148 - }  
149 -};  
150 -  
151 -MM_REGISTER(Initializer,YubiKey,"")  
152 -  
153 -#include "yubico.moc"  
share/openbr/cmake/FindCT8.cmake deleted
1 -# ================================================================  
2 -# The CT8 CMake configuration file  
3 -#  
4 -# Usage from an external project:  
5 -# In your CMakeLists.txt, add these lines:  
6 -#  
7 -# find_package(CT8 REQUIRED)  
8 -# target_link_libraries(MY_TARGET ${CT8_LIBS})  
9 -# ================================================================  
10 -  
11 -set(CT8_DIR "CT8_DIR-NOTFOUND" CACHE PATH "Cognitec FaceVACS 8.x directory")  
12 -  
13 -  
14 -if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")  
15 - set(ARCH_STRING x86_64)  
16 -else("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")  
17 - set(ARCH_STRING x86_32)  
18 -endif("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")  
19 -  
20 -if(DEFINED MSVC80)  
21 - set(COMP_DIR_EXT "msc_8.0-ipp_crtdll")  
22 -elseif(DEFINED MSVC90)  
23 - set(COMP_DIR_EXT "msc_9.0-ipp_crtdll")  
24 -elseif(DEFINED MSVC10)  
25 - set(COMP_DIR_EXT "msc_10.0-ipp_crtdll")  
26 -elseif(CMAKE_HOST_APPLE)  
27 - set(COMP_DIR_EXT "gcc-4.2-ipp")  
28 -else()  
29 - set(COMP_DIR_EXT "gcc-4.3-ipp")  
30 -endif()  
31 -  
32 -set(CT8_DIR_LIB ${CT8_DIR}/lib/${ARCH_STRING}/${COMP_DIR_EXT} )  
33 -set(CT8_LIBRARY_RELEASE libfrsdk-8.6.0)  
34 -set(CT8_LIBRARY_DEBUG libfrsdk-8.6.0d)  
35 -  
36 -include_directories(${CT8_DIR}/include)  
37 -link_directories(${CT8_DIR_LIB} ${CT8_DIR_LIB}_g)  
share/openbr/cmake/FindFST3.cmake deleted
1 -find_path(FST3_DIR _src_criteria/classifier.hpp ${CMAKE_SOURCE_DIR}/3rdparty/*)  
2 -mark_as_advanced(FST3_DIR)  
3 -include_directories(${FST3_DIR}/_src_criteria ${FST3_DIR}/_src_dataio ${FST3_DIR}/_src_global ${FST3_DIR}/_src_search)  
4 -set(FST3_SRC ${FST3_DIR}/_src_global/global.cpp)  
share/openbr/cmake/FindPP4.cmake deleted
1 -# ================================================================  
2 -# The PP4 CMake configuration file  
3 -#  
4 -# Usage from an external project:  
5 -# In your CMakeLists.txt, add these lines:  
6 -#  
7 -# find_package(PP4 REQUIRED)  
8 -# target_link_libraries(MY_TARGET ${PP4_LIBS})  
9 -# ================================================================  
10 -  
11 -find_path(PP4_DIR include/pittpatt_nc_sdk.h ${CMAKE_SOURCE_DIR}/3rdparty/*)  
12 -include_directories(${PP4_DIR}/include)  
13 -link_directories(${PP4_DIR}/lib)  
14 -set(PP4_LIBS pittpatt_nc_sdk  
15 - pittpatt_raw_image  
16 - pittpatt_raw_image_io  
17 - pittpatt_recognition_core  
18 - pittpatt_video_io)  
share/openbr/cmake/FindTopSurf.cmake deleted
1 -find_path(TOPSURF_DIR topsurf/topsurf.h ${CMAKE_SOURCE_DIR}/3rdparty/*)  
2 -mark_as_advanced(TOPSURF_DIR)  
3 -include_directories(${TOPSURF_DIR})  
4 -aux_source_directory(${TOPSURF_DIR}/topsurf TOPSURF_SRC)  
5 -aux_source_directory(${TOPSURF_DIR}/topsurf/flann TOPSURF_FLANN_SRC)  
share/openbr/cmake/FindYubiKey.cmake deleted
1 -find_path(YUBIKEY_DIR yubikey.h ${CMAKE_SOURCE_DIR}/3rdparty/*)  
2 -mark_as_advanced(YUBIKEY_DIR)  
3 -include_directories(${YUBIKEY_DIR})  
4 -if(MSVC)  
5 - include_directories(${YUBIKEY_DIR}/stdbool)  
6 -endif()  
7 -  
8 -if(NOT TARGET yubikey)  
9 - set(YUBIKEY_SRC ${YUBIKEY_DIR}/ykaes.c ${YUBIKEY_DIR}/ykcrc.c ${YUBIKEY_DIR}/ykhex.c ${YUBIKEY_DIR}/ykmodhex.c ${YUBIKEY_DIR}/yktoken.c)  
10 - if(WIN32)  
11 - set_source_files_properties(${YUBIKEY_SRC} PROPERTIES LANGUAGE CXX)  
12 - endif()  
13 -endif()  
14 -  
15 -set(YUBIKEY_LICENSE ${YUBIKEY_DIR}/COPYING)  
share/openbr/cmake/FindpHash.cmake deleted
1 -find_path(PHASH_DIR src/pHash.h ${CMAKE_SOURCE_DIR}/3rdparty/*)  
2 -mark_as_advanced(PHASH_DIR)  
3 -include_directories(${PHASH_DIR} ${PHASH_DIR}/src)  
4 -set(PHASH_SRC ${PHASH_DIR}/src/pHash.cpp ${PHASH_DIR}/src/ph_fft.c)  
1 -Subproject commit dccddf4dd3a5239911807beeec39308f8890b1e4 1 +Subproject commit a73d51013ea05f263e88a28539393159fff2183e