Commit dff99e3e7bc9947e4820a099e2312b6b8a8015f2

Authored by Brendan Klare
2 parents a3d263f0 dc2f8017

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

3rdparty/stasm4.0.0/stasm/asm.cpp
... ... @@ -5,8 +5,6 @@
5 5 #include "stasm.h"
6 6 #include "stasmhash.h"
7 7  
8   -#include <QDebug>
9   -
10 8 namespace stasm
11 9 {
12 10 static void TraceShape( // write an image file showing current shape on the image
... ...
3rdparty/stasm4.0.0/stasm/faceroi.cpp
... ... @@ -3,7 +3,6 @@
3 3 // Copyright (C) 2005-2013, Stephen Milborrow
4 4  
5 5 #include "stasm.h"
6   -#include <QDebug>
7 6  
8 7 namespace stasm
9 8 {
... ...
3rdparty/stasm4.0.0/stasm/pinstart.cpp
... ... @@ -3,7 +3,6 @@
3 3 // Copyright (C) 2005-2013, Stephen Milborrow
4 4  
5 5 #include "stasm.h"
6   -#include <QDebug>
7 6  
8 7 namespace stasm
9 8 {
... ...
3rdparty/stasm4.0.0/stasm/stasm_lib.cpp
... ... @@ -3,7 +3,6 @@
3 3 // Copyright (C) 2005-2013, Stephen Milborrow
4 4  
5 5 #include "stasm.h"
6   -#include <QDebug>
7 6  
8 7 using namespace stasm;
9 8  
... ...
app/br/br.cpp
... ... @@ -138,8 +138,8 @@ public:
138 138 check(parc >= 2 && parc <= 4, "Incorrect parameter count for 'evalClassification'.");
139 139 br_eval_classification(parv[0], parv[1], parc >= 3 ? parv[2] : "", parc >= 4 ? parv[3] : "");
140 140 } else if (!strcmp(fun, "evalClustering")) {
141   - check(parc == 2, "Incorrect parameter count for 'evalClustering'.");
142   - br_eval_clustering(parv[0], parv[1]);
  141 + check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'evalClustering'.");
  142 + br_eval_clustering(parv[0], parv[1], parc == 3 ? parv[2] : "");
143 143 } else if (!strcmp(fun, "evalDetection")) {
144 144 check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'evalDetection'.");
145 145 br_eval_detection(parv[0], parv[1], parc == 3 ? parv[2] : "");
... ...
openbr/core/cluster.cpp
... ... @@ -100,7 +100,9 @@ Neighborhood getNeighborhood(const QStringList &amp;simmats)
100 100 int currentRows = -1;
101 101 int columnOffset = 0;
102 102 for (int j=0; j<numGalleries; j++) {
103   - cv::Mat m = BEE::readMat(simmats[i*numGalleries+j]);
  103 + QScopedPointer<br::Format> format(br::Factory<br::Format>::make(simmats[i*numGalleries+j]));
  104 + br::Template t = format->read();
  105 + cv::Mat m = t.m();
104 106 if (j==0) {
105 107 currentRows = m.rows;
106 108 allNeighbors.resize(currentRows);
... ... @@ -115,8 +117,9 @@ Neighborhood getNeighborhood(const QStringList &amp;simmats)
115 117 float val = m.at<float>(k,l);
116 118 if ((i==j) && (k==l)) continue; // Skips self-similarity scores
117 119  
118   - if ((val != -std::numeric_limits<float>::infinity()) &&
119   - (val != std::numeric_limits<float>::infinity())) {
  120 + if (val != -std::numeric_limits<float>::max()
  121 + && val != -std::numeric_limits<float>::infinity()
  122 + && val != std::numeric_limits<float>::infinity()) {
120 123 globalMax = std::max(globalMax, val);
121 124 globalMin = std::min(globalMin, val);
122 125 }
... ... @@ -157,7 +160,7 @@ Neighborhood getNeighborhood(const QStringList &amp;simmats)
157 160 // Zhu et al. "A Rank-Order Distance based Clustering Algorithm for Face Tagging", CVPR 2011
158 161 br::Clusters br::ClusterGallery(const QStringList &simmats, float aggressiveness, const QString &csv)
159 162 {
160   - qDebug("Clustering %d simmat(s)", simmats.size());
  163 + qDebug("Clustering %d simmat(s), aggressiveness %f", simmats.size(), aggressiveness);
161 164  
162 165 // Read in gallery parts, keeping top neighbors of each template
163 166 Neighborhood neighborhood = getNeighborhood(simmats);
... ... @@ -275,13 +278,14 @@ float jaccardIndex(const QVector&lt;int&gt; &amp;indicesA, const QVector&lt;int&gt; &amp;indicesB)
275 278  
276 279 // Evaluates clustering algorithms based on metrics described in
277 280 // Santo Fortunato "Community detection in graphs", Physics Reports 486 (2010)
278   -void br::EvalClustering(const QString &csv, const QString &input)
  281 +void br::EvalClustering(const QString &csv, const QString &input, QString truth_property)
279 282 {
  283 + if (truth_property.isEmpty())
  284 + truth_property = "Label";
280 285 qDebug("Evaluating %s against %s", qPrintable(csv), qPrintable(input));
281 286  
282   - // We assume clustering algorithms store assigned cluster labels as integers (since the clusters are
283   - // not named). Direct use of ClusterID is not general -cao
284   - QList<int> labels = File::get<int>(TemplateList::fromGallery(input), "ClusterID");
  287 + TemplateList tList = TemplateList::fromGallery(input);
  288 + QList<int> labels = tList.indexProperty(truth_property);
285 289  
286 290 QHash<int, int> labelToIndex;
287 291 int nClusters = 0;
... ...
openbr/core/cluster.h
... ... @@ -28,7 +28,7 @@ namespace br
28 28 typedef QVector<Cluster> Clusters;
29 29  
30 30 Clusters ClusterGallery(const QStringList &simmats, float aggressiveness, const QString &csv);
31   - void EvalClustering(const QString &csv, const QString &input);
  31 + void EvalClustering(const QString &csv, const QString &input, QString truth_property);
32 32  
33 33 Clusters ReadClusters(const QString &csv);
34 34 void WriteClusters(const Clusters &clusters, const QString &csv);
... ...
openbr/core/core.cpp
... ... @@ -21,14 +21,16 @@
21 21 #include "qtutils.h"
22 22 #include "../plugins/openbr_internal.h"
23 23  
24   -using namespace br;
  24 +namespace br {
25 25  
26   -/**** ALGORITHM_CORE ****/
27 26 struct AlgorithmCore
28 27 {
29 28 QSharedPointer<Transform> transform;
30 29 QSharedPointer<Distance> distance;
31 30  
  31 + QString transformString;
  32 + QString distanceString;
  33 +
32 34 AlgorithmCore(const QString &name)
33 35 {
34 36 this->name = name;
... ... @@ -134,6 +136,8 @@ struct AlgorithmCore
134 136 }
135 137 TemplateList data(TemplateList::fromGallery(input));
136 138  
  139 + bool multiProcess = Globals->file.getBool("multiProcess", false);
  140 +
137 141 if (gallery.contains("append"))
138 142 {
139 143 // Remove any templates which are already in the gallery
... ... @@ -155,20 +159,27 @@ struct AlgorithmCore
155 159 Globals->currentStep = 0;
156 160 Globals->totalSteps = data.length();
157 161  
158   - // Trust me, this makes complete sense.
159   - // We're just going to make a pipe with a placeholder first transform
160   - QString pipeDesc = "Identity+GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(data.length())+")+Discard";
161   - QScopedPointer<Transform> basePipe(Transform::make(pipeDesc,NULL));
  162 + QScopedPointer<Transform> basePipe;
162 163  
163   - CompositeTransform * downcast = dynamic_cast<CompositeTransform *>(basePipe.data());
164   - if (downcast == NULL)
165   - qFatal("downcast failed?");
  164 + if (!multiProcess)
  165 + {
  166 + QString pipeDesc = "Identity+GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(data.length())+")+Discard";
  167 + basePipe.reset(Transform::make(pipeDesc,NULL));
  168 + CompositeTransform * downcast = dynamic_cast<CompositeTransform *>(basePipe.data());
  169 + if (downcast == NULL)
  170 + qFatal("downcast failed?");
166 171  
167   - // replace that placeholder with the current algorithm
168   - downcast->transforms[0] = this->transform.data();
  172 + // replace that placeholder with the current algorithm
  173 + downcast->transforms[0] = this->transform.data();
169 174  
170   - // call init on the pipe to collapse the algorithm (if its top level is a pipe)
171   - downcast->init();
  175 + // call init on the pipe to collapse the algorithm (if its top level is a pipe)
  176 + downcast->init();
  177 + }
  178 + else
  179 + {
  180 + QString pipeDesc = "ProcessWrapper("+transformString+")"+"+GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(data.length())+")+Discard";
  181 + basePipe.reset(Transform::make(pipeDesc,NULL));
  182 + }
172 183  
173 184 // Next, we make a Stream (with placeholder transform)
174 185 QString streamDesc = "Stream(Identity, readMode=DistributeFrames)";
... ... @@ -176,7 +187,7 @@ struct AlgorithmCore
176 187 WrapperTransform * wrapper = dynamic_cast<WrapperTransform *> (baseStream.data());
177 188  
178 189 // replace that placeholder with the pipe we built
179   - wrapper->transform = downcast;
  190 + wrapper->transform = basePipe.data();
180 191  
181 192 // and get the final stream's stages by reinterpreting the pipe. Perfectly straightforward.
182 193 wrapper->init();
... ... @@ -241,17 +252,14 @@ struct AlgorithmCore
241 252 dummyTarget.append(targets[0]);
242 253 QScopedPointer<Output> realOutput(Output::make(output, dummyTarget, queryFiles));
243 254  
244   - // Some outputs assume Globals->blockSize is a real thing, of course we have no interest in it.
245   - int old_block_size = Globals->blockSize;
246   - Globals->blockSize = INT_MAX;
  255 + realOutput->set_blockRows(INT_MAX);
  256 + realOutput->set_blockCols(INT_MAX);
247 257 realOutput->setBlock(0,0);
248 258 for (int i=0; i < queries.length(); i++)
249 259 {
250 260 float res = distance->compare(queries[i], targets[i]);
251 261 realOutput->setRelative(res, 0,i);
252 262 }
253   -
254   - Globals->blockSize = old_block_size;
255 263 }
256 264  
257 265 void deduplicate(const File &inputGallery, const File &outputGallery, const float threshold)
... ... @@ -310,7 +318,11 @@ struct AlgorithmCore
310 318 qPrintable(queryGallery.flat()),
311 319 output.isNull() ? "" : qPrintable(" to " + output.flat()));
312 320  
313   - if (output.exists() && output.get<bool>("cache", false)) return;
  321 + // Escape hatch for distances that need to operate directly on the gallery files
  322 + if (distance->compare(targetGallery, queryGallery, output))
  323 + return;
  324 +
  325 + if (output.exists() && output.get<bool>("cache")) return;
314 326 if (queryGallery == ".") queryGallery = targetGallery;
315 327  
316 328 QScopedPointer<Gallery> t, q;
... ... @@ -327,11 +339,13 @@ struct AlgorithmCore
327 339 File splitOutputFile = output.name.arg(i);
328 340 outputFiles.append(splitOutputFile);
329 341 }
  342 + } else {
  343 + outputFiles.append(output);
330 344 }
331   - else outputFiles.append(output);
332 345  
333 346 QList<Output*> outputs;
334   - foreach (const File &outputFile, outputFiles) outputs.append(Output::make(outputFile, targetFiles, queryFiles));
  347 + foreach (const File &outputFile, outputFiles)
  348 + outputs.append(Output::make(outputFile, targetFiles, queryFiles));
335 349  
336 350 if (distance.isNull()) qFatal("Null distance.");
337 351 Globals->currentStep = 0;
... ... @@ -361,7 +375,6 @@ struct AlgorithmCore
361 375 else targetPartitions.append(targets);
362 376  
363 377 outputs[i]->setBlock(queryBlock, targetBlock);
364   -
365 378 distance->compare(targetPartitions[i], queryPartitions[i], outputs[i]);
366 379  
367 380 Globals->currentStep += double(targets.size()) * double(queries.size());
... ... @@ -407,14 +420,22 @@ private:
407 420 if ((words.size() < 1) || (words.size() > 2)) qFatal("Invalid algorithm format.");
408 421 //! [Parsing the algorithm description]
409 422  
  423 + transformString = words[0];
  424 +
410 425  
411 426 //! [Creating the template generation and comparison methods]
412 427 transform = QSharedPointer<Transform>(Transform::make(words[0], NULL));
413   - if (words.size() > 1) distance = QSharedPointer<Distance>(Distance::make(words[1], NULL));
  428 + if (words.size() > 1) {
  429 + distance = QSharedPointer<Distance>(Distance::make(words[1], NULL));
  430 + distanceString = words[1];
  431 + }
414 432 //! [Creating the template generation and comparison methods]
415 433 }
416 434 };
417 435  
  436 +} // namespace br
  437 +
  438 +using namespace br;
418 439  
419 440 class AlgorithmManager : public Initializer
420 441 {
... ...
openbr/core/plot.cpp
... ... @@ -247,7 +247,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
247 247 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) +
248 248 (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) +
249 249 QString(" + scale_x_log10(labels=trans_format(\"log10\", math_format()))") +
250   - (rocOpts.contains("yLimits") ? QString(" + scale_y_continuous(labels=percent, limits=%3)").arg("c"+QtUtils::toString(rocOpts.get<QPointF>("yLimits",QPointF()))) : QString(" + scale_y_continuous(labels=percent)")) +
  250 + (rocOpts.contains("yLimits") ? QString(" + scale_y_continuous(labels=percent) + coord_cartesian(ylim=%1)").arg("c"+QtUtils::toString(rocOpts.get<QPointF>("yLimits",QPointF()))) : QString(" + scale_y_continuous(labels=percent)")) +
251 251 QString(" + annotation_logticks(sides=\"b\")") +
252 252 QString(" + theme(legend.title = element_text(size = %1), plot.title = element_text(size = %1), axis.text = element_text(size = %1), axis.title.x = element_text(size = %1), axis.title.y = element_text(size = %1),"
253 253 " legend.position=%2, legend.background = element_rect(fill = 'white'), panel.grid.major = element_line(colour = \"gray\"), panel.grid.minor = element_line(colour = \"gray\", linetype = \"dashed\"), legend.text = element_text(size = %1))\n\n").arg(QString::number(rocOpts.get<float>("textSize",12)), rocOpts.contains("legendPosition") ? "c"+QtUtils::toString(rocOpts.get<QPointF>("legendPosition")) : "'right'")));
... ... @@ -273,7 +273,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
273 273 (minimalist ? "" : " + scale_x_log10(labels=c(1,5,10,50,100), breaks=c(1,5,10,50,100)) + annotation_logticks(sides=\"b\")") +
274 274 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) +
275 275 (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) +
276   - (cmcOpts.contains("yLimits") ? QString(" + scale_y_continuous(labels=percent, limits=%3)").arg("c"+QtUtils::toString(cmcOpts.get<QPointF>("yLimits",QPointF()))) : QString(" + scale_y_continuous(labels=percent)")) +
  276 + (cmcOpts.contains("yLimits") ? QString(" + scale_y_continuous(labels=percent) + coord_cartesian(ylim=%1)").arg("c"+QtUtils::toString(cmcOpts.get<QPointF>("yLimits",QPointF()))) : QString(" + scale_y_continuous(labels=percent)")) +
277 277 QString(" + theme_minimal() + theme(legend.title = element_text(size = %1), plot.title = element_text(size = %1), axis.text = element_text(size = %1), axis.title.x = element_text(size = %1), axis.title.y = element_text(size = %1),"
278 278 " legend.position=%2, legend.background = element_rect(fill = 'white'), panel.grid.major = element_line(colour = \"gray\"), panel.grid.minor = element_line(colour = \"gray\", linetype = \"dashed\"), legend.text = element_text(size = %1))\n\n").arg(QString::number(cmcOpts.get<float>("textSize",12)), cmcOpts.contains("legendPosition") ? "c"+QtUtils::toString(cmcOpts.get<QPointF>("legendPosition")) : "'right'")));
279 279  
... ...
openbr/openbr.cpp
... ... @@ -109,9 +109,9 @@ void br_eval_classification(const char *predicted_gallery, const char *truth_gal
109 109 EvalClassification(predicted_gallery, truth_gallery, predicted_property, truth_property);
110 110 }
111 111  
112   -void br_eval_clustering(const char *csv, const char *gallery)
  112 +void br_eval_clustering(const char *csv, const char *gallery, const char * truth_property)
113 113 {
114   - EvalClustering(csv, gallery);
  114 + EvalClustering(csv, gallery, truth_property);
115 115 }
116 116  
117 117 float br_eval_detection(const char *predicted_gallery, const char *truth_gallery, const char *csv)
... ... @@ -435,7 +435,14 @@ br_template_list br_load_from_gallery(br_gallery gallery)
435 435 return (br_template_list)tl;
436 436 }
437 437  
438   -void br_add_to_gallery(br_gallery gallery, br_template_list tl)
  438 +void br_add_template_to_gallery(br_gallery gallery, br_template tmpl)
  439 +{
  440 + Gallery *gal = reinterpret_cast<Gallery*>(gallery);
  441 + Template *t = reinterpret_cast<Template*>(tmpl);
  442 + gal->write(*t);
  443 +}
  444 +
  445 +void br_add_template_list_to_gallery(br_gallery gallery, br_template_list tl)
439 446 {
440 447 Gallery *gal = reinterpret_cast<Gallery*>(gallery);
441 448 TemplateList *realTL = reinterpret_cast<TemplateList*>(tl);
... ...
openbr/openbr.h
... ... @@ -167,9 +167,10 @@ BR_EXPORT void br_eval_classification(const char *predicted_gallery, const char
167 167 * \brief Evaluates and prints clustering accuracy to the terminal.
168 168 * \param csv The cluster results file.
169 169 * \param gallery The br::Gallery used to generate the \ref simmat that was clustered.
  170 + * \param truth_property (Optional) which metadata key to use from <i>gallery</i/>, defaults to Label
170 171 * \see br_cluster
171 172 */
172   -BR_EXPORT void br_eval_clustering(const char *csv, const char *gallery);
  173 +BR_EXPORT void br_eval_clustering(const char *csv, const char *gallery, const char * truth_property);
173 174  
174 175 /*!
175 176 * \brief Evaluates and prints detection accuracy to terminal.
... ... @@ -562,9 +563,13 @@ BR_EXPORT br_gallery br_make_gallery(const char *gallery);
562 563 */
563 564 BR_EXPORT br_template_list br_load_from_gallery(br_gallery gallery);
564 565 /*!
  566 + * \brief Write a br::Template to the br::Gallery on disk.
  567 + */
  568 +BR_EXPORT void br_add_template_to_gallery(br_gallery gallery, br_template tmpl);
  569 +/*!
565 570 * \brief Write a br::TemplateList to the br::Gallery on disk.
566 571 */
567   -BR_EXPORT void br_add_to_gallery(br_gallery gallery, br_template_list tl);
  572 +BR_EXPORT void br_add_template_list_to_gallery(br_gallery gallery, br_template_list tl);
568 573 /*!
569 574 * \brief Close the br::Gallery.
570 575 */
... ...
openbr/openbr_plugin.cpp
... ... @@ -408,7 +408,7 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery)
408 408 QStringList labels;
409 409 for (int i=newTemplates.size()-1; i>=0; i--) {
410 410 newTemplates[i].file.set("Index", i+templates.size());
411   - newTemplates[i].file.set("Gallery", gallery.name);
  411 + newTemplates[i].file.set("Gallery", file.name);
412 412  
413 413 QString label = newTemplates.at(i).file.get<QString>("Label");
414 414 // Have we seen this subject before?
... ... @@ -436,7 +436,7 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery)
436 436 } else {
437 437 for (int i=newTemplates.size()-1; i>=0; i--) {
438 438 newTemplates[i].file.set("Index", i+templates.size());
439   - newTemplates[i].file.set("Gallery", gallery.name);
  439 + newTemplates[i].file.set("Gallery", file.name);
440 440  
441 441 if (crossValidate > 0) {
442 442 if (newTemplates[i].file.getBool("duplicatePartitions")) {
... ... @@ -1101,13 +1101,19 @@ void Output::initialize(const FileList &amp;targetFiles, const FileList &amp;queryFiles)
1101 1101 {
1102 1102 this->targetFiles = targetFiles;
1103 1103 this->queryFiles = queryFiles;
  1104 + if (this->blockRows == -1)
  1105 + blockRows = Globals->blockSize;
  1106 +
  1107 + if (this->blockCols == -1)
  1108 + blockCols = Globals->blockSize;
  1109 +
1104 1110 selfSimilar = (queryFiles == targetFiles) && (targetFiles.size() > 1) && (queryFiles.size() > 1);
1105 1111 }
1106 1112  
1107 1113 void Output::setBlock(int rowBlock, int columnBlock)
1108 1114 {
1109   - offset = QPoint((columnBlock == -1) ? 0 : Globals->blockSize*columnBlock,
1110   - (rowBlock == -1) ? 0 : Globals->blockSize*rowBlock);
  1115 + offset = QPoint((columnBlock == -1) ? 0 : blockCols*columnBlock,
  1116 + (rowBlock == -1) ? 0 : blockRows*rowBlock);
1111 1117 if (!next.isNull()) next->setBlock(rowBlock, columnBlock);
1112 1118 }
1113 1119  
... ...
openbr/openbr_plugin.h
... ... @@ -996,6 +996,11 @@ class BR_EXPORT Output : public Object
996 996 Q_OBJECT
997 997  
998 998 public:
  999 + Q_PROPERTY(int blockRows READ get_blockRows WRITE set_blockRows RESET reset_blockRows STORED false)
  1000 + Q_PROPERTY(int blockCols READ get_blockCols WRITE set_blockCols RESET reset_blockCols STORED false)
  1001 + BR_PROPERTY(int, blockRows, -1)
  1002 + BR_PROPERTY(int, blockCols, -1)
  1003 +
999 1004 FileList targetFiles; /*!< \brief List of files representing the gallery templates. */
1000 1005 FileList queryFiles; /*!< \brief List of files representing the probe templates. */
1001 1006 bool selfSimilar; /*!< \brief \c true if the \em targetFiles == \em queryFiles, \c false otherwise. */
... ... @@ -1074,9 +1079,11 @@ public:
1074 1079 */
1075 1080 class BR_EXPORT Gallery : public Object
1076 1081 {
1077   - Q_OBJECT
1078   -
  1082 + Q_OBJECT
1079 1083 public:
  1084 + Q_PROPERTY(int readBlockSize READ get_readBlockSize WRITE set_readBlockSize RESET reset_readBlockSize STORED false)
  1085 + BR_PROPERTY(int, readBlockSize, Globals->blockSize)
  1086 +
1080 1087 virtual ~Gallery() {}
1081 1088 TemplateList read(); /*!< \brief Retrieve all the stored templates. */
1082 1089 FileList files(); /*!< \brief Retrieve all the stored template files. */
... ... @@ -1324,6 +1331,10 @@ protected:
1324 1331  
1325 1332 private:
1326 1333 virtual void compareBlock(const TemplateList &target, const TemplateList &query, Output *output, int targetOffset, int queryOffset) const;
  1334 +
  1335 + friend struct AlgorithmCore;
  1336 + virtual bool compare(const File &targetGallery, const File &queryGallery, const File &output) const /*!< \brief Escape hatch for algorithms that need customized file I/O during comparison. */
  1337 + { (void) targetGallery; (void) queryGallery; (void) output; return false; }
1327 1338 };
1328 1339  
1329 1340 /*!
... ...
openbr/plugins/algorithms.cpp
... ... @@ -64,6 +64,7 @@ class AlgorithmsInitializer : public Initializer
64 64 Globals->abbreviations.insert("SmallSIFT", "Open+LimitSize(512)+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)");
65 65 Globals->abbreviations.insert("SmallSURF", "Open+LimitSize(512)+KeyPointDetector(SURF)+KeyPointDescriptor(SURF):KeyPointMatcher(BruteForce)");
66 66 Globals->abbreviations.insert("ColorHist", "Open+LimitSize(512)+Expand+EnsureChannels(3)+SplitChannels+Hist(256,0,8)+Cat+Normalize(L1):L2");
  67 + Globals->abbreviations.insert("ImageSimilarity", "Open+EnsureChannels(3)+Resize(256,256)+SplitChannels+RectRegions(64,64,64,64)+Hist(256,0,8)+Cat:NegativeLogPlusOne(L2)");
67 68 Globals->abbreviations.insert("ImageClassification", "Open+CropSquare+LimitSize(256)+Cvt(Gray)+Gradient+Bin(0,360,9,true)+Merge+Integral+RecursiveIntegralSampler(4,2,8,Singleton(KMeans(256)))+Cat+CvtFloat+Hist(256)+KNN(5,Dist(L1),false,5)+Rename(KNN,Subject)");
68 69 Globals->abbreviations.insert("TanTriggs", "Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)");
69 70  
... ...
openbr/plugins/distance.cpp
... ... @@ -460,12 +460,13 @@ BR_REGISTER(Distance, SumDistance)
460 460 class GalleryCompareTransform : public Transform
461 461 {
462 462 Q_OBJECT
463   - Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  463 + Q_PROPERTY(QString distanceAlgorithm READ get_distanceAlgorithm WRITE set_distanceAlgorithm RESET reset_distanceAlgorithm STORED false)
464 464 Q_PROPERTY(QString galleryName READ get_galleryName WRITE set_galleryName RESET reset_galleryName STORED false)
465   - BR_PROPERTY(br::Distance*, distance, NULL)
  465 + BR_PROPERTY(QString, distanceAlgorithm, "")
466 466 BR_PROPERTY(QString, galleryName, "")
467 467  
468 468 TemplateList gallery;
  469 + QSharedPointer<Distance> distance;
469 470  
470 471 void project(const Template &src, Template &dst) const
471 472 {
... ... @@ -479,8 +480,13 @@ class GalleryCompareTransform : public Transform
479 480  
480 481 void init()
481 482 {
482   - if (!galleryName.isEmpty())
  483 + if (!galleryName.isEmpty()) {
483 484 gallery = TemplateList::fromGallery(galleryName);
  485 + }
  486 + if (!distanceAlgorithm.isEmpty())
  487 + {
  488 + distance = Distance::fromAlgorithm(distanceAlgorithm);
  489 + }
484 490 }
485 491 };
486 492  
... ...
openbr/plugins/gallery.cpp
... ... @@ -123,7 +123,7 @@ class galGallery : public Gallery
123 123 gallery.seek(0);
124 124  
125 125 TemplateList templates;
126   - while ((templates.size() < Globals->blockSize) && !stream.atEnd()) {
  126 + while ((templates.size() < readBlockSize) && !stream.atEnd()) {
127 127 Template m;
128 128 stream >> m;
129 129 templates.append(m);
... ... @@ -348,8 +348,8 @@ class memGallery : public Gallery
348 348 MemoryGalleries::aligned[file] = true;
349 349 }
350 350  
351   - TemplateList templates = MemoryGalleries::galleries[file].mid(block*Globals->blockSize, Globals->blockSize);
352   - *done = (templates.size() < Globals->blockSize);
  351 + TemplateList templates = MemoryGalleries::galleries[file].mid(block*readBlockSize, readBlockSize);
  352 + *done = (templates.size() < readBlockSize);
353 353 block = *done ? 0 : block+1;
354 354 return templates;
355 355 }
... ...
openbr/plugins/independent.cpp
... ... @@ -9,12 +9,13 @@ using namespace cv;
9 9 namespace br
10 10 {
11 11  
12   -static TemplateList Downsample(const TemplateList &templates, int classes, int instances, float fraction, const QString & inputVariable)
  12 +static TemplateList Downsample(const TemplateList &templates, int classes, int instances, float fraction, const QString & inputVariable, const QStringList &gallery)
13 13 {
14 14 // Return early when no downsampling is required
15 15 if ((classes == std::numeric_limits<int>::max()) &&
16 16 (instances == std::numeric_limits<int>::max()) &&
17   - (fraction >= 1))
  17 + (fraction >= 1) &&
  18 + (gallery.isEmpty()))
18 19 return templates;
19 20  
20 21 const bool atLeast = instances < 0;
... ... @@ -60,6 +61,11 @@ static TemplateList Downsample(const TemplateList &amp;templates, int classes, int i
60 61 downsample = downsample.mid(0, downsample.size()*fraction);
61 62 }
62 63  
  64 + if (!gallery.isEmpty())
  65 + for (int i=downsample.size()-1; i>=0; i--)
  66 + if (!gallery.contains(downsample[i].file.get<QString>("Gallery")))
  67 + downsample.removeAt(i);
  68 +
63 69 return downsample;
64 70 }
65 71  
... ... @@ -71,11 +77,13 @@ class DownsampleTrainingTransform : public Transform
71 77 Q_PROPERTY(int instances READ get_instances WRITE set_instances RESET reset_instances STORED false)
72 78 Q_PROPERTY(float fraction READ get_fraction WRITE set_fraction RESET reset_fraction STORED false)
73 79 Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  80 + Q_PROPERTY(QStringList gallery READ get_gallery WRITE set_gallery RESET reset_gallery STORED false)
74 81 BR_PROPERTY(br::Transform*, transform, NULL)
75 82 BR_PROPERTY(int, classes, std::numeric_limits<int>::max())
76 83 BR_PROPERTY(int, instances, std::numeric_limits<int>::max())
77 84 BR_PROPERTY(float, fraction, 1)
78 85 BR_PROPERTY(QString, inputVariable, "Label")
  86 + BR_PROPERTY(QStringList, gallery, QStringList())
79 87  
80 88 void project(const Template & src, Template & dst) const
81 89 {
... ... @@ -88,7 +96,8 @@ class DownsampleTrainingTransform : public Transform
88 96 if (!transform || !transform->trainable)
89 97 return;
90 98  
91   - TemplateList downsampled = Downsample(data, classes, instances, fraction, inputVariable);
  99 + TemplateList downsampled = Downsample(data, classes, instances, fraction, inputVariable, gallery);
  100 +
92 101 transform->train(downsampled);
93 102 }
94 103 };
... ...
openbr/plugins/likely.cmake 0 โ†’ 100644
  1 +set(BR_WITH_LIKELY OFF CACHE BOOL "Build with Likely")
  2 +
  3 +if(${BR_WITH_LIKELY})
  4 + find_package(Likely REQUIRED)
  5 + set(BR_THIRDPARTY_SRC ${BR_THIRDPARTY_SRC} plugins/likely.cpp)
  6 + set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${Likely_LIBS})
  7 +endif()
... ...
openbr/plugins/likely.cpp 0 โ†’ 100644
  1 +#include <likely.h>
  2 +#include <likely/opencv.hpp>
  3 +
  4 +#include "openbr_internal.h"
  5 +
  6 +namespace br
  7 +{
  8 +
  9 +/*!
  10 + * \ingroup transforms
  11 + * \brief Generic interface to Likely JIT compiler
  12 + *
  13 + * www.liblikely.org
  14 + * \author Josh Klontz \cite jklontz
  15 + */
  16 +class LikelyTransform : public UntrainableTransform
  17 +{
  18 + Q_OBJECT
  19 + Q_PROPERTY(QString kernel READ get_kernel WRITE set_kernel RESET reset_kernel STORED false)
  20 + BR_PROPERTY(QString, kernel, "")
  21 +
  22 + likely_function function;
  23 +
  24 + void init()
  25 + {
  26 + likely_ast ast = likely_ast_from_string(qPrintable(kernel));
  27 + likely_env env = likely_new_env();
  28 + function = likely_compile(ast, env, likely_type_null);
  29 + likely_release_env(env);
  30 + likely_release_ast(ast);
  31 + }
  32 +
  33 + void project(const Template &src, Template &dst) const
  34 + {
  35 + likely_const_mat srcl = likely::fromCvMat(src);
  36 + likely_const_mat dstl = function(srcl);
  37 + dst = likely::toCvMat(dstl);
  38 + likely_release(dstl);
  39 + likely_release(srcl);
  40 + }
  41 +};
  42 +
  43 +BR_REGISTER(Transform, LikelyTransform)
  44 +
  45 +/*!
  46 + * \ingroup formats
  47 + * \brief Likely matrix format
  48 + *
  49 + * www.liblikely.org
  50 + * \author Josh Klontz \cite jklontz
  51 + */
  52 +class lmFormat : public Format
  53 +{
  54 + Q_OBJECT
  55 +
  56 + Template read() const
  57 + {
  58 + likely_const_mat m = likely_read(qPrintable(file.name));
  59 + Template result(likely::toCvMat(m));
  60 + likely_release(m);
  61 + return result;
  62 + }
  63 +
  64 + void write(const Template &t) const
  65 + {
  66 + likely_const_mat m = likely::fromCvMat(t);
  67 + likely_write(m, qPrintable(file.name));
  68 + likely_release(m);
  69 + }
  70 +};
  71 +
  72 +BR_REGISTER(Format, lmFormat)
  73 +
  74 +} // namespace br
  75 +
  76 +#include "likely.moc"
... ...
openbr/plugins/misc.cpp
... ... @@ -552,6 +552,146 @@ public:
552 552  
553 553 BR_REGISTER(Transform, ProgressCounterTransform)
554 554  
  555 +
  556 +class OutputTransform : public TimeVaryingTransform
  557 +{
  558 + Q_OBJECT
  559 +
  560 + Q_PROPERTY(QString outputString READ get_outputString WRITE set_outputString RESET reset_outputString STORED false)
  561 + // names of mem galleries containing filelists we need.
  562 + Q_PROPERTY(QString targetName READ get_targetName WRITE set_targetName RESET reset_targetName STORED false)
  563 + Q_PROPERTY(QString queryName READ get_queryName WRITE set_queryName RESET reset_queryName STORED false)
  564 + Q_PROPERTY(bool transposeMode READ get_transposeMode WRITE set_transposeMode RESET reset_transposeMode STORED false)
  565 +
  566 + BR_PROPERTY(QString, outputString, "")
  567 + BR_PROPERTY(QString, targetName, "")
  568 + BR_PROPERTY(QString, queryName, "")
  569 +
  570 + BR_PROPERTY(bool,transposeMode, false)
  571 + ;
  572 +
  573 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  574 + {
  575 + dst = src;
  576 +
  577 + if (src.empty())
  578 + return;
  579 +
  580 + // we received a template, which is the next row/column in order
  581 + foreach(const Template & t, dst) {
  582 + for (int i=0; i < t.m().cols; i++)
  583 + {
  584 + output->setRelative(t.m().at<float>(0, i), currentRow, currentCol);
  585 +
  586 + // row-major input
  587 + if (!transposeMode)
  588 + currentCol++;
  589 + // col-major input
  590 + else
  591 + currentRow++;
  592 + }
  593 + // filled in a row, advance to the next, reset column position
  594 + if (!transposeMode) {
  595 + currentRow++;
  596 + currentCol = 0;
  597 + }
  598 + // filled in a column, advance, reset row
  599 + else {
  600 + currentCol++;
  601 + currentRow = 0;
  602 + }
  603 + }
  604 +
  605 + bool blockDone = false;
  606 + // In direct mode, we don't buffer rows
  607 + if (!transposeMode)
  608 + {
  609 + currentBlockRow++;
  610 + blockDone = true;
  611 + }
  612 + // in transpose mode, we buffer 100 cols before writing the block
  613 + else if (currentCol == bufferedSize)
  614 + {
  615 + currentBlockCol++;
  616 + blockDone = true;
  617 + }
  618 + else return;
  619 +
  620 + if (blockDone)
  621 + {
  622 + // set the next block, only necessary if we haven't buffered the current item
  623 + output->setBlock(currentBlockRow, currentBlockCol);
  624 + currentRow = 0;
  625 + currentCol = 0;
  626 + }
  627 + }
  628 +
  629 + void train(const TemplateList& data)
  630 + {
  631 + (void) data;
  632 + }
  633 +
  634 + void init()
  635 + {
  636 + if (targetName.isEmpty() || queryName.isEmpty() || outputString.isEmpty())
  637 + return;
  638 +
  639 + QScopedPointer<Gallery> tGallery(Gallery::make(targetName));
  640 + QScopedPointer<Gallery> qGallery(Gallery::make(queryName));
  641 +
  642 + FileList targetFiles = tGallery->files();
  643 + FileList queryFiles = qGallery->files();
  644 +
  645 + currentBlockRow = 0;
  646 + currentBlockCol = 0;
  647 +
  648 + currentRow = 0;
  649 + currentCol = 0;
  650 +
  651 + bufferedSize = 100;
  652 +
  653 + if (transposeMode)
  654 + {
  655 + // buffer 100 cols at a time
  656 + fragmentsPerRow = bufferedSize;
  657 + // a single col contains comparisons to all query files
  658 + fragmentsPerCol = queryFiles.size();
  659 + }
  660 + else
  661 + {
  662 + // a single row contains comparisons to all target files
  663 + fragmentsPerRow = targetFiles.size();
  664 + // we output rows one at a time
  665 + fragmentsPerCol = 1;
  666 + }
  667 +
  668 + output = QSharedPointer<Output>(Output::make(outputString, targetFiles, queryFiles));
  669 + output->blockRows = fragmentsPerCol;
  670 + output->blockCols = fragmentsPerRow;
  671 + output->initialize(targetFiles, queryFiles);
  672 +
  673 + output->setBlock(currentBlockRow, currentBlockCol);
  674 + }
  675 +
  676 + QSharedPointer<Output> output;
  677 +
  678 + int bufferedSize;
  679 +
  680 + int currentRow;
  681 + int currentCol;
  682 +
  683 + int currentBlockRow;
  684 + int currentBlockCol;
  685 +
  686 + int fragmentsPerRow;
  687 + int fragmentsPerCol;
  688 +
  689 +public:
  690 + OutputTransform() : TimeVaryingTransform(false,false) {}
  691 +};
  692 +
  693 +BR_REGISTER(Transform, OutputTransform)
  694 +
555 695 }
556 696  
557 697 #include "misc.moc"
... ...
openbr/plugins/output.cpp
... ... @@ -215,9 +215,11 @@ class mtxOutput : public Output
215 215  
216 216 this->rowBlock = rowBlock;
217 217 this->columnBlock = columnBlock;
218   - blockScores = cv::Mat(std::min(queryFiles.size()-rowBlock*Globals->blockSize, Globals->blockSize),
219   - std::min(targetFiles.size()-columnBlock*Globals->blockSize, Globals->blockSize),
220   - CV_32FC1);
  218 +
  219 + int matrixRows = std::min(queryFiles.size()-rowBlock*this->blockRows, blockRows);
  220 + int matrixCols = std::min(targetFiles.size()-columnBlock*this->blockCols, blockCols);
  221 +
  222 + blockScores = cv::Mat(matrixRows, matrixCols, CV_32FC1);
221 223 }
222 224  
223 225 void setRelative(float value, int i, int j)
... ... @@ -237,7 +239,7 @@ class mtxOutput : public Output
237 239 if (!f.open(QFile::ReadWrite))
238 240 qFatal("Unable to open %s for modifying.", qPrintable(file));
239 241 for (int i=0; i<blockScores.rows; i++) {
240   - f.seek(headerSize + sizeof(float)*(quint64(rowBlock*Globals->blockSize+i)*targetFiles.size()+(columnBlock*Globals->blockSize)));
  242 + f.seek(headerSize + sizeof(float)*(quint64(rowBlock*this->blockRows+i)*targetFiles.size()+(columnBlock*this->blockCols)));
241 243 f.write((const char*)blockScores.row(i).data, sizeof(float)*blockScores.cols);
242 244 }
243 245 f.close();
... ...
openbr/plugins/pp5.cpp
... ... @@ -306,6 +306,22 @@ class PP5CompareDistance : public Distance
306 306 {
307 307 Q_OBJECT
308 308  
  309 + struct NativeGallery
  310 + {
  311 + FileList files;
  312 + QList<int> faceIDs;
  313 + ppr_gallery_type gallery;
  314 + };
  315 +
  316 + mutable QMap<QString, NativeGallery> cache;
  317 + mutable QMutex cacheLock;
  318 +
  319 + ~PP5CompareDistance()
  320 + {
  321 + foreach (const NativeGallery &gallery, cache.values())
  322 + ppr_free_gallery(gallery.gallery);
  323 + }
  324 +
309 325 float compare(const Template &target, const Template &query) const
310 326 {
311 327 TemplateList targetList;
... ... @@ -315,7 +331,6 @@ class PP5CompareDistance : public Distance
315 331 MatrixOutput *score = MatrixOutput::make(targetList.files(), queryList.files());
316 332 compare(targetList, queryList, score);
317 333 return score->data.at<float>(0);
318   -
319 334 }
320 335  
321 336 void compare(const TemplateList &target, const TemplateList &query, Output *output) const
... ... @@ -326,25 +341,27 @@ class PP5CompareDistance : public Distance
326 341 QList<int> target_face_ids, query_face_ids;
327 342 enroll(target, &target_gallery, target_face_ids);
328 343 enroll(query, &query_gallery, query_face_ids);
  344 + compareNative(target_gallery, target_face_ids, query_gallery, query_face_ids, output);
  345 + ppr_free_gallery(target_gallery);
  346 + ppr_free_gallery(query_gallery);
  347 + }
329 348  
330   - ppr_similarity_matrix_type similarity_matrix;
331   - TRY(ppr_compare_galleries(context, query_gallery, target_gallery, &similarity_matrix))
332   -
333   - for (int i=0; i<query_face_ids.size(); i++) {
334   - int query_face_id = query_face_ids[i];
335   - for (int j=0; j<target_face_ids.size(); j++) {
336   - int target_face_id = target_face_ids[j];
  349 + void compareNative(ppr_gallery_type target, const QList<int> &targetIDs, ppr_gallery_type query, const QList<int> &queryIDs, Output *output) const
  350 + {
  351 + ppr_similarity_matrix_type simmat;
  352 + TRY(ppr_compare_galleries(context, query, target, &simmat))
  353 + for (int i=0; i<queryIDs.size(); i++) {
  354 + int query_face_id = queryIDs[i];
  355 + for (int j=0; j<targetIDs.size(); j++) {
  356 + int target_face_id = targetIDs[j];
337 357 float score = -std::numeric_limits<float>::max();
338 358 if ((query_face_id != -1) && (target_face_id != -1)) {
339   - TRY(ppr_get_face_similarity_score(context, similarity_matrix, query_face_id, target_face_id, &score))
  359 + TRY(ppr_get_face_similarity_score(context, simmat, query_face_id, target_face_id, &score))
340 360 }
341 361 output->setRelative(score, i, j);
342 362 }
343 363 }
344   -
345   - ppr_free_similarity_matrix(similarity_matrix);
346   - ppr_free_gallery(target_gallery);
347   - ppr_free_gallery(query_gallery);
  364 + ppr_free_similarity_matrix(simmat);
348 365 }
349 366  
350 367 void enroll(const TemplateList &templates, ppr_gallery_type *gallery, QList<int> &face_ids) const
... ... @@ -363,6 +380,53 @@ class PP5CompareDistance : public Distance
363 380 }
364 381 }
365 382 }
  383 +
  384 + NativeGallery cacheRetain(const File &gallery) const
  385 + {
  386 + QMutexLocker locker(&cacheLock);
  387 + NativeGallery nativeGallery;
  388 + if (cache.contains(gallery.name)) {
  389 + nativeGallery = cache[gallery.name];
  390 + } else {
  391 + ppr_create_gallery(context, &nativeGallery.gallery);
  392 + TemplateList templates = TemplateList::fromGallery(gallery);
  393 + enroll(templates, &nativeGallery.gallery, nativeGallery.faceIDs);
  394 + nativeGallery.files = templates.files();
  395 + if (gallery.get<bool>("retain"))
  396 + cache.insert(gallery.name, nativeGallery);
  397 + }
  398 + return nativeGallery;
  399 + }
  400 +
  401 + void cacheRelease(const File &gallery, const NativeGallery &nativeGallery) const
  402 + {
  403 + QMutexLocker locker(&cacheLock);
  404 + if (cache.contains(gallery.name)) {
  405 + if (gallery.get<bool>("release")) {
  406 + cache.remove(gallery.name);
  407 + ppr_free_gallery(nativeGallery.gallery);
  408 + }
  409 + } else {
  410 + ppr_free_gallery(nativeGallery.gallery);
  411 + }
  412 + }
  413 +
  414 + bool compare(const File &targetGallery, const File &queryGallery, const File &output) const
  415 + {
  416 + if (!targetGallery.get<bool>("native") || !queryGallery.get<bool>("native"))
  417 + return false;
  418 +
  419 + NativeGallery nativeTarget = cacheRetain(targetGallery);
  420 + NativeGallery nativeQuery = cacheRetain(queryGallery);
  421 +
  422 + QScopedPointer<Output> o(Output::make(output, nativeTarget.files, nativeQuery.files));
  423 + o->setBlock(0, 0);
  424 + compareNative(nativeTarget.gallery, nativeTarget.faceIDs, nativeQuery.gallery, nativeQuery.faceIDs, o.data());
  425 +
  426 + cacheRelease(targetGallery, nativeTarget);
  427 + cacheRelease(queryGallery, nativeQuery);
  428 + return true;
  429 + }
366 430 };
367 431  
368 432 BR_REGISTER(Distance, PP5CompareDistance)
... ...
openbr/plugins/stream.cpp
... ... @@ -25,6 +25,7 @@ class Idiocy : public QObject
25 25 public:
26 26 enum StreamModes { StreamVideo,
27 27 DistributeFrames,
  28 + StreamGallery,
28 29 Auto};
29 30  
30 31 Q_ENUMS(StreamModes)
... ... @@ -288,6 +289,75 @@ protected:
288 289 };
289 290  
290 291  
  292 +class StreamGallery : public TemplateProcessor
  293 +{
  294 +public:
  295 + StreamGallery()
  296 + {
  297 +
  298 + }
  299 +
  300 + bool open(Template &input)
  301 + {
  302 + // Create a gallery
  303 + gallery = QSharedPointer<Gallery>(Gallery::make(input.file));
  304 + // Failed ot open the gallery?
  305 + if (gallery.isNull()) {
  306 + qDebug()<<"Failed to create gallery!";
  307 + galleryOk = false;
  308 + return false;
  309 + }
  310 +
  311 + // Set up state variables for future reads
  312 + galleryOk = true;
  313 + gallery->set_readBlockSize(100);
  314 + nextIdx = 0;
  315 + lastBlock = false;
  316 + return galleryOk;
  317 + }
  318 +
  319 + bool isOpen() { return galleryOk; }
  320 +
  321 + void close()
  322 + {
  323 + galleryOk = false;
  324 + currentData.clear();
  325 + nextIdx = 0;
  326 + lastBlock = true;
  327 + }
  328 +
  329 + bool getNextTemplate(Template & output)
  330 + {
  331 + // If we still have data available, we return one of those
  332 + if (nextIdx >= currentData.size())
  333 + {
  334 + // Otherwise, read another block
  335 + if (!lastBlock) {
  336 + currentData = gallery->readBlock(&lastBlock);
  337 + nextIdx = 0;
  338 + }
  339 + else
  340 + {
  341 + galleryOk = false;
  342 + return false;
  343 + }
  344 + }
  345 + // Return the indicated template, and advance the index
  346 + output = currentData[nextIdx++];
  347 + return true;
  348 + }
  349 +
  350 +protected:
  351 +
  352 + QSharedPointer<Gallery> gallery;
  353 + bool galleryOk;
  354 + bool lastBlock;
  355 +
  356 + TemplateList currentData;
  357 + int nextIdx;
  358 +
  359 +};
  360 +
291 361 class DirectReturn : public TemplateProcessor
292 362 {
293 363 public:
... ... @@ -731,6 +801,11 @@ protected:
731 801 if (!frameSource)
732 802 frameSource = new DirectReturn();
733 803 }
  804 + else if (mode == br::Idiocy::StreamGallery)
  805 + {
  806 + if (!frameSource)
  807 + frameSource = new StreamGallery();
  808 + }
734 809 else if (mode == br::Idiocy::StreamVideo)
735 810 {
736 811 if (!frameSource) {
... ...
scripts/brpy/__init__.py
... ... @@ -21,13 +21,27 @@ def _handle_string_func(func):
21 21 return call_func
22 22  
23 23 def init_brpy(br_loc='/usr/local/lib'):
24   - """Takes the ctypes lib object for br and initializes all function inputs and outputs"""
25   - br_loc += '/libopenbr.%s'
26   - if os.path.exists(br_loc % 'dylib'):
27   - br = cdll.LoadLibrary(br_loc % 'dylib')
28   - elif os.path.exists(br_loc % 'so'):
29   - br = cdll.LoadLibrary(br_loc % 'so')
30   - else:
  24 + """Initializes all function inputs and outputs for the br ctypes lib object"""
  25 +
  26 + lib_path = os.environ.get('LD_LIBRARY_PATH')
  27 + paths = [br_loc]
  28 + if lib_path:
  29 + paths.extend(lib_path.split(':'))
  30 +
  31 + found = False
  32 + for p in paths:
  33 + dylib = '%s/%s.%s' % (p, 'libopenbr', 'dylib')
  34 + so = '%s/%s.%s' % (p, 'libopenbr', 'so')
  35 + if os.path.exists(dylib):
  36 + br = cdll.LoadLibrary(dylib)
  37 + found = True
  38 + break
  39 + elif os.path.exists(so):
  40 + br = cdll.LoadLibrary(so)
  41 + found = True
  42 + break
  43 +
  44 + if not found:
31 45 raise ValueError('Neither .so nor .dylib libopenbr found in %s' % br_loc)
32 46  
33 47 plot_args = _var_string_args(1) + [c_bool]
... ... @@ -44,7 +58,7 @@ def init_brpy(br_loc=&#39;/usr/local/lib&#39;):
44 58 br.br_eval.argtypes = _string_args(3)
45 59 br.br_eval.restype = c_float
46 60 br.br_eval_classification.argtypes = _string_args(4)
47   - br.br_eval_clustering.argtypes = _string_args(2)
  61 + br.br_eval_clustering.argtypes = _string_args(3)
48 62 br.br_eval_detection.argtypes = _string_args(3)
49 63 br.br_eval_detection.restype = c_float
50 64 br.br_eval_landmarking.argtypes = _string_args(3) + [c_int, c_int]
... ... @@ -129,7 +143,8 @@ def init_brpy(br_loc=&#39;/usr/local/lib&#39;):
129 143 br.br_make_gallery.restype = c_void_p
130 144 br.br_load_from_gallery.argtypes = [c_void_p]
131 145 br.br_load_from_gallery.restype = c_void_p
132   - br.br_add_to_gallery.argtypes = [c_void_p, c_void_p]
  146 + br.br_add_template_to_gallery.argtypes = [c_void_p, c_void_p]
  147 + br.br_add_template_list_to_gallery.argtypes = [c_void_p, c_void_p]
133 148 br.br_close_gallery.argtypes = [c_void_p]
134 149  
135 150 return br
... ...