Commit 8f957ce1d545c5c53a982ac38dc782510d0c2c66
Merge branch 'master' of https://github.com/biometrics/openbr
Showing
32 changed files
with
178 additions
and
1597 deletions
app/br/br.cpp
| ... | ... | @@ -146,6 +146,9 @@ public: |
| 146 | 146 | } else if (!strcmp(fun, "plotDetection")) { |
| 147 | 147 | check(parc >= 2, "Incorrect parameter count for 'plotDetection'."); |
| 148 | 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 | 152 | } else if (!strcmp(fun, "plotMetadata")) { |
| 150 | 153 | check(parc >= 2, "Incorrect parameter count for 'plotMetadata'."); |
| 151 | 154 | br_plot_metadata(parc-1, parv, parv[parc-1], true); |
| ... | ... | @@ -224,6 +227,7 @@ private: |
| 224 | 227 | "-evalLandmarking <predicted_gallery> <truth_gallery> [{csv} [<normalization_index_a> <normalization_index_b>]]\n" |
| 225 | 228 | "-evalRegression <predicted_gallery> <truth_gallery> <predicted property name> <ground truth property name>\n" |
| 226 | 229 | "-plotDetection <file> ... <file> {destination}\n" |
| 230 | + "-plotLandmarking <file> ... <file> {destination}\n" | |
| 227 | 231 | "-plotMetadata <file> ... <file> <columns>\n" |
| 228 | 232 | "-getHeader <matrix>\n" |
| 229 | 233 | "-setHeader {<matrix>} <target_gallery> <query_gallery>\n" | ... | ... |
openbr/core/plot.cpp
| ... | ... | @@ -302,7 +302,6 @@ bool filesHaveSinglePoint(const QStringList &files) { |
| 302 | 302 | bool PlotDetection(const QStringList &files, const File &destination, bool show) |
| 303 | 303 | { |
| 304 | 304 | qDebug("Plotting %d detection file(s) to %s", files.size(), qPrintable(destination)); |
| 305 | - | |
| 306 | 305 | RPlot p(files, destination, false); |
| 307 | 306 | |
| 308 | 307 | p.file.write("# Split data into individual plots\n" |
| ... | ... | @@ -345,6 +344,22 @@ bool PlotDetection(const QStringList &files, const File &destination, bool show) |
| 345 | 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 | 363 | bool PlotMetadata(const QStringList &files, const QString &columns, bool show) |
| 349 | 364 | { |
| 350 | 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 | 26 | { |
| 27 | 27 | bool Plot(const QStringList &files, const File &destination, bool show = false); |
| 28 | 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 | 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 | 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 | 190 | bool br_plot_metadata(int num_files, const char *files[], const char *columns, bool show) |
| 186 | 191 | { |
| 187 | 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 | 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 | 310 | * \brief Renders metadata figures for a set of <tt>.csv</tt> files with specified columns. |
| 299 | 311 | * |
| 300 | 312 | * Several files will be created: | ... | ... |
openbr/plugins/algorithms.cpp
| ... | ... | @@ -50,9 +50,9 @@ class AlgorithmsInitializer : public Initializer |
| 50 | 50 | Globals->abbreviations.insert("PerFrameDetection", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true)+Show(false,[FrameNumber])+Discard)"); |
| 51 | 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 | 57 | // Generic Image Processing |
| 58 | 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 | 69 | |
| 70 | 70 | /*! |
| 71 | 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 | 97 | * \brief Resize the template |
| 73 | 98 | * \author Josh Klontz \cite jklontz |
| 74 | 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 | 253 | { |
| 254 | 254 | Q_OBJECT |
| 255 | 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 | 256 | BR_PROPERTY(float, keep, 0.95) |
| 258 | - BR_PROPERTY(br::Transform*, transform, NULL) | |
| 259 | 257 | |
| 260 | 258 | PCATransform pca; |
| 261 | 259 | Transform *cvtFloat; | ... | ... |
openbr/plugins/frames.cpp
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 | 350 | if (!Globals->useGui) |
| 351 | 351 | return; |
| 352 | 352 | |
| 353 | + TimeVaryingTransform::init(); | |
| 354 | + | |
| 353 | 355 | if (displayBuffer) |
| 354 | 356 | delete displayBuffer; |
| 355 | 357 | displayBuffer = new QPixmap(); |
| ... | ... | @@ -530,6 +532,7 @@ public: |
| 530 | 532 | target_wait = 1000.0 / targetFPS; |
| 531 | 533 | timer.start(); |
| 532 | 534 | last_time = timer.elapsed(); |
| 535 | + TimeVaryingTransform::init(); | |
| 533 | 536 | } |
| 534 | 537 | |
| 535 | 538 | protected: |
| ... | ... | @@ -583,6 +586,7 @@ public: |
| 583 | 586 | { |
| 584 | 587 | initialized = false; |
| 585 | 588 | framesSeen = 0; |
| 589 | + TimeVaryingTransform::init(); | |
| 586 | 590 | } |
| 587 | 591 | |
| 588 | 592 | protected: | ... | ... |
openbr/plugins/keypoint.cpp
| ... | ... | @@ -222,9 +222,9 @@ class GridTransform : public UntrainableTransform |
| 222 | 222 | QList<QPointF> landmarks; |
| 223 | 223 | const float row_step = 1.f * src.m().rows / rows; |
| 224 | 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 | 228 | dst = src; |
| 229 | 229 | dst.file.setPoints(landmarks); |
| 230 | 230 | } | ... | ... |
openbr/plugins/meta.cpp
| ... | ... | @@ -264,7 +264,6 @@ class ContractTransform : public UntrainableMetaTransform |
| 264 | 264 | |
| 265 | 265 | virtual void project(const TemplateList &src, TemplateList &dst) const |
| 266 | 266 | { |
| 267 | - //dst = Expanded(src); | |
| 268 | 267 | if (src.empty()) return; |
| 269 | 268 | Template out; |
| 270 | 269 | |
| ... | ... | @@ -682,8 +681,10 @@ public: |
| 682 | 681 | |
| 683 | 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 | 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 | 31 | Q_OBJECT |
| 32 | 32 | |
| 33 | 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 | 42 | Q_OBJECT |
| 96 | 43 | |
| 97 | 44 | protected: |
| 98 | - MetaTransform() : Transform(false) {} | |
| 45 | + UntrainableMetaTransform() : UntrainableTransform(false) {} | |
| 99 | 46 | }; |
| 100 | 47 | |
| 101 | - | |
| 102 | 48 | class TransformCopier : public ResourceMaker<Transform> |
| 103 | 49 | { |
| 104 | 50 | public: |
| ... | ... | @@ -151,6 +97,71 @@ private: |
| 151 | 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 | 167 | * \brief A MetaTransform that aggregates some sub-transforms |
| ... | ... | @@ -165,15 +176,17 @@ public: |
| 165 | 176 | |
| 166 | 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 | 183 | _project(src, dst); |
| 170 | 184 | } |
| 171 | 185 | |
| 172 | 186 | virtual void project(const TemplateList &src, TemplateList &dst) const |
| 173 | 187 | { |
| 174 | 188 | if (timeVarying()) { |
| 175 | - CompositeTransform * non_const = const_cast<CompositeTransform *>(this); | |
| 176 | - non_const->projectUpdate(src,dst); | |
| 189 | + timeInvariantAlias->project(src,dst); | |
| 177 | 190 | return; |
| 178 | 191 | } |
| 179 | 192 | _project(src, dst); |
| ... | ... | @@ -190,6 +203,10 @@ public: |
| 190 | 203 | isTimeVarying = isTimeVarying || transform->timeVarying(); |
| 191 | 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
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 | 141 | |
| 142 | 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 | 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 | 707 | if (input == NULL) { |
| 708 | 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 | 712 | should_continue = nextStage->tryAcquireNextStage(input); |
| 714 | 713 | |
| ... | ... | @@ -1300,6 +1299,12 @@ public: |
| 1300 | 1299 | { |
| 1301 | 1300 | if (!transform) |
| 1302 | 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 | 1308 | trainable = transform->trainable; |
| 1304 | 1309 | |
| 1305 | 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
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
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