Commit 27a5fc9bd8a19f313d9eaca35c1fdefa0ee6117e

Authored by Charles Otto
2 parents 9cf029b5 885c3ec1

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

Conflicts:
	openbr/core/core.cpp
app/br/br.cpp
@@ -171,7 +171,11 @@ public: @@ -171,7 +171,11 @@ public:
171 check(parc == 1, "Incorrect parameter count for 'daemon'."); 171 check(parc == 1, "Incorrect parameter count for 'daemon'.");
172 daemon = true; 172 daemon = true;
173 daemon_pipe = parv[0]; 173 daemon_pipe = parv[0];
174 - } else if (!strcmp(fun, "exit")) { 174 + } else if (!strcmp(fun,"slave")) {
  175 + check(parc == 1, "Incorrect parameter count for 'slave'");
  176 + br_slave_process(parv[0]);
  177 + }
  178 + else if (!strcmp(fun, "exit")) {
175 check(parc == 0, "No parameters expected for 'exit'."); 179 check(parc == 0, "No parameters expected for 'exit'.");
176 daemon = false; 180 daemon = false;
177 } else if (!strcmp(fun, "getHeader")) { 181 } else if (!strcmp(fun, "getHeader")) {
openbr/core/core.cpp
@@ -138,8 +138,6 @@ struct AlgorithmCore @@ -138,8 +138,6 @@ struct AlgorithmCore
138 138
139 downcast->transforms[0] = this->transform.data(); 139 downcast->transforms[0] = this->transform.data();
140 downcast->init(); 140 downcast->init();
141 -  
142 -  
143 downcast->projectUpdate(i,i); 141 downcast->projectUpdate(i,i);
144 142
145 return i.files(); 143 return i.files();
openbr/core/qtutils.cpp
@@ -399,33 +399,31 @@ void showFile(const QString &file) @@ -399,33 +399,31 @@ void showFile(const QString &file)
399 399
400 QString toString(const QVariant &variant) 400 QString toString(const QVariant &variant)
401 { 401 {
402 - if (variant.canConvert(QVariant::String))  
403 - return variant.toString();  
404 - else if(variant.canConvert(QVariant::PointF)) {  
405 - QPointF pt = qvariant_cast<QPointF>(variant);  
406 - return QString("(%1,%2)").arg(QString::number(pt.x()),  
407 - QString::number(pt.y()));  
408 - }  
409 - else if (variant.canConvert(QVariant::RectF)) { 402 + if (variant.canConvert(QVariant::List)) return toString(qvariant_cast<QVariantList>(variant));
  403 + else if (variant.canConvert(QVariant::String)) return variant.toString();
  404 + else if (variant.canConvert(QVariant::PointF)) {
  405 + QPointF point = qvariant_cast<QPointF>(variant);
  406 + return QString("(%1,%2)").arg(QString::number(point.x()),QString::number(point.y()));
  407 + } else if (variant.canConvert(QVariant::RectF)) {
410 QRectF rect = qvariant_cast<QRectF>(variant); 408 QRectF rect = qvariant_cast<QRectF>(variant);
411 return QString("(%1,%2,%3,%4)").arg(QString::number(rect.x()), 409 return QString("(%1,%2,%3,%4)").arg(QString::number(rect.x()),
412 QString::number(rect.y()), 410 QString::number(rect.y()),
413 QString::number(rect.width()), 411 QString::number(rect.width()),
414 QString::number(rect.height())); 412 QString::number(rect.height()));
415 } 413 }
416 - else if (variant.canConvert(QVariant::List)) {  
417 - QString ret = QString("[");  
418 - bool first = true;  
419 - foreach (const QVariant &i, variant.toList()) {  
420 - if (!first)  
421 - ret += ",";  
422 - else  
423 - first = false;  
424 - ret += toString(i);  
425 - }  
426 - ret += "]";  
427 - return ret;  
428 - } 414 +
  415 + return QString();
  416 +}
  417 +
  418 +QString toString(const QVariantList &variantList)
  419 +{
  420 + QStringList variants;
  421 +
  422 + foreach(const QVariant &variant, variantList)
  423 + variants.append(toString(variant));
  424 +
  425 + if (!variants.isEmpty()) return "[" + variants.join(", ") + "]";
  426 +
429 return QString(); 427 return QString();
430 } 428 }
431 429
openbr/core/qtutils.h
@@ -74,6 +74,7 @@ namespace QtUtils @@ -74,6 +74,7 @@ namespace QtUtils
74 74
75 /**** Variant Utilities ****/ 75 /**** Variant Utilities ****/
76 QString toString(const QVariant &variant); 76 QString toString(const QVariant &variant);
  77 + QString toString(const QVariantList &variantList);
77 78
78 template <typename T> 79 template <typename T>
79 QVariantList toVariantList(const QList<T> &list) 80 QVariantList toVariantList(const QList<T> &list)
openbr/openbr.cpp
@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 #include "core/fuse.h" 22 #include "core/fuse.h"
23 #include "core/plot.h" 23 #include "core/plot.h"
24 #include "core/qtutils.h" 24 #include "core/qtutils.h"
  25 +#include "plugins/openbr_internal.h"
25 26
26 using namespace br; 27 using namespace br;
27 28
@@ -279,3 +280,11 @@ const char *br_version() @@ -279,3 +280,11 @@ const char *br_version()
279 static QByteArray version = Context::version().toLocal8Bit(); 280 static QByteArray version = Context::version().toLocal8Bit();
280 return version.data(); 281 return version.data();
281 } 282 }
  283 +
  284 +void br_slave_process(const char * baseName)
  285 +{
  286 + WorkerProcess worker;
  287 + worker.transform = Globals->algorithm;
  288 + worker.baseName = baseName;
  289 + worker.mainLoop();
  290 +}
openbr/openbr.h
@@ -408,6 +408,12 @@ BR_EXPORT void br_train_n(int num_inputs, const char *inputs[], const char *mode @@ -408,6 +408,12 @@ BR_EXPORT void br_train_n(int num_inputs, const char *inputs[], const char *mode
408 */ 408 */
409 BR_EXPORT const char *br_version(); 409 BR_EXPORT const char *br_version();
410 410
  411 +
  412 +/*!
  413 + * \brief For internal use via ProcessWrapperTransform
  414 + */
  415 +BR_EXPORT void br_slave_process(const char * baseKey);
  416 +
411 /*! @}*/ 417 /*! @}*/
412 418
413 #ifdef __cplusplus 419 #ifdef __cplusplus
openbr/openbr_plugin.cpp
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include <QCoreApplication> 17 #include <QCoreApplication>
18 #include <QCryptographicHash> 18 #include <QCryptographicHash>
19 #include <QFutureSynchronizer> 19 #include <QFutureSynchronizer>
  20 +#include <QLocalSocket>
20 #include <QMetaProperty> 21 #include <QMetaProperty>
21 #include <QPointF> 22 #include <QPointF>
22 #include <QProcess> 23 #include <QProcess>
@@ -58,16 +59,7 @@ QString File::flat() const @@ -58,16 +59,7 @@ QString File::flat() const
58 foreach (const QString &key, keys) { 59 foreach (const QString &key, keys) {
59 const QVariant value = this->value(key); 60 const QVariant value = this->value(key);
60 if (value.isNull()) values.append(key); 61 if (value.isNull()) values.append(key);
61 - else {  
62 - if (QString(value.typeName()) == "QVariantList") {  
63 - QStringList variants;  
64 - foreach(const QVariant &variant, qvariant_cast<QVariantList>(value)) {  
65 - variants.append(QtUtils::toString(variant));  
66 - }  
67 - if (!variants.isEmpty()) values.append(key + "=[" + variants.join(", ") + "]");  
68 - }  
69 - else values.append(key + "=" + QtUtils::toString(value));  
70 - } 62 + else values.append(key + "=" + QtUtils::toString(value));
71 } 63 }
72 64
73 QString flat = name; 65 QString flat = name;
@@ -942,6 +934,8 @@ void br::Context::initialize(int &amp;argc, char *argv[], QString sdkPath, bool use_ @@ -942,6 +934,8 @@ void br::Context::initialize(int &amp;argc, char *argv[], QString sdkPath, bool use_
942 qRegisterMetaType< QList<float> >(); 934 qRegisterMetaType< QList<float> >();
943 qRegisterMetaType< QList<br::Transform*> >(); 935 qRegisterMetaType< QList<br::Transform*> >();
944 qRegisterMetaType< QList<br::Distance*> >(); 936 qRegisterMetaType< QList<br::Distance*> >();
  937 + qRegisterMetaType< QAbstractSocket::SocketState> ();
  938 +
945 939
946 Globals = new Context(); 940 Globals = new Context();
947 Globals->init(File()); 941 Globals->init(File());
openbr/plugins/eigen3.cpp
@@ -493,7 +493,7 @@ class LDATransform : public Transform @@ -493,7 +493,7 @@ class LDATransform : public Transform
493 outMap = projection.transpose() * (inMap - mean); 493 outMap = projection.transpose() * (inMap - mean);
494 494
495 if (isBinary) { 495 if (isBinary) {
496 - dst.file.set("conf",dst.m().at<float>(0,0)); 496 + dst.file.set("Confidence",dst.m().at<float>(0,0));
497 } 497 }
498 } 498 }
499 499
openbr/plugins/openbr_internal.h
@@ -240,6 +240,18 @@ protected: @@ -240,6 +240,18 @@ protected:
240 CompositeTransform() : TimeVaryingTransform(false) {} 240 CompositeTransform() : TimeVaryingTransform(false) {}
241 }; 241 };
242 242
  243 +class EnrollmentWorker;
  244 +
  245 +// Implemented in plugins/process.cpp
  246 +struct WorkerProcess
  247 +{
  248 + QString transform;
  249 + QString baseName;
  250 + EnrollmentWorker * processInterface;
  251 +
  252 + void mainLoop();
  253 +};
  254 +
243 } 255 }
244 256
245 #endif // OPENBR_INTERNAL_H 257 #endif // OPENBR_INTERNAL_H
openbr/plugins/process.cpp 0 โ†’ 100644
  1 +
  2 +#include <QBuffer>
  3 +#include <QLocalServer>
  4 +#include <QLocalSocket>
  5 +#include <QProcess>
  6 +#include <QUuid>
  7 +
  8 +#include <iostream>
  9 +#include <fstream>
  10 +
  11 +#include "openbr_internal.h"
  12 +#include "openbr/core/opencvutils.h"
  13 +
  14 +using namespace cv;
  15 +
  16 +namespace br
  17 +{
  18 +
  19 +enum SignalType
  20 +{
  21 + INPUT_AVAILABLE,
  22 + OUTPUT_AVAILABLE,
  23 + SHOULD_END
  24 +};
  25 +
  26 +class EnrollmentWorker
  27 +{
  28 +public:
  29 + QLocalServer inbound;
  30 + QLocalSocket outbound;
  31 + QLocalSocket * receiver;
  32 +
  33 + ~EnrollmentWorker()
  34 + {
  35 + delete transform;
  36 + }
  37 +
  38 + br::Transform * transform;
  39 +
  40 + void connections(const QString & baseName)
  41 + {
  42 + inbound.listen(baseName+"_worker");
  43 + outbound.connectToServer(baseName+"_master");
  44 + inbound.waitForNewConnection(-1);
  45 + receiver = inbound.nextPendingConnection();
  46 + outbound.waitForConnected(-1);
  47 + }
  48 +
  49 + void workerLoop()
  50 + {
  51 + SignalType signal;
  52 +
  53 + forever
  54 + {
  55 + while (receiver->bytesAvailable() < qint64(sizeof(signal))) {
  56 + receiver->waitForReadyRead(-1);
  57 + }
  58 + receiver->read((char *) &signal, sizeof(signal));
  59 +
  60 + if (signal == SHOULD_END) {
  61 + outbound.close();
  62 + inbound.close();
  63 + break;
  64 + }
  65 +
  66 + qint64 inBufferSize;
  67 + while (receiver->bytesAvailable() < qint64(sizeof(inBufferSize))) {
  68 + receiver->waitForReadyRead(-1);
  69 + }
  70 + receiver->read((char *) &inBufferSize, sizeof(inBufferSize));
  71 +
  72 + QByteArray inArray(inBufferSize,'0');
  73 +
  74 + qint64 arrayPosition = 0;
  75 + while (arrayPosition < inBufferSize) {
  76 + if (!receiver->bytesAvailable())
  77 + receiver->waitForReadyRead(-1);
  78 + arrayPosition += receiver->read(inArray.data()+arrayPosition, receiver->bytesAvailable());
  79 + }
  80 +
  81 + TemplateList inList;
  82 + TemplateList outList;
  83 + // deserialize the template list
  84 + QDataStream deserializer(inArray);
  85 + deserializer >> inList;
  86 +
  87 + // and project it
  88 + transform->projectUpdate(inList,outList);
  89 +
  90 + // serialize the output list
  91 + QBuffer outBuff;
  92 + outBuff.open(QBuffer::ReadWrite);
  93 + QDataStream serializer(&outBuff);
  94 + serializer << outList;
  95 +
  96 + // send the size of the buffer
  97 + //qint64 bufferSize = outBuff.size();
  98 + qint64 bufferSize = outBuff.data().size();
  99 + outbound.write((char *) &bufferSize, sizeof(bufferSize));
  100 +
  101 + outbound.write(outBuff.data().data(), bufferSize);
  102 + while (outbound.bytesToWrite() > 0) {
  103 + outbound.waitForBytesWritten(-1);
  104 + }
  105 + }
  106 + }
  107 +};
  108 +
  109 +void WorkerProcess::mainLoop()
  110 +{
  111 + processInterface = new EnrollmentWorker();
  112 + processInterface->transform = Transform::make(this->transform,NULL);
  113 + processInterface->connections(baseName);
  114 + processInterface->workerLoop();
  115 + delete processInterface;
  116 +}
  117 +
  118 +/*!
  119 + * \ingroup transforms
  120 + * \brief Interface to a separate process
  121 + * \author Charles Otto \cite caotto
  122 + */
  123 +class ProcessWrapperTransform : public TimeVaryingTransform
  124 +{
  125 + Q_OBJECT
  126 +
  127 + Q_PROPERTY(QString transform READ get_transform WRITE set_transform RESET reset_transform)
  128 + BR_PROPERTY(QString, transform, "")
  129 +
  130 + QString baseKey;
  131 + QProcess workerProcess;
  132 +
  133 + QLocalServer inbound;
  134 + QLocalSocket outbound;
  135 + QLocalSocket * receiver;
  136 +
  137 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  138 + {
  139 + if (!processActive)
  140 + {
  141 + activateProcess();
  142 + }
  143 +
  144 + SignalType signal = INPUT_AVAILABLE;
  145 + outbound.write((char *) &signal, sizeof(SignalType));
  146 +
  147 + QBuffer inBuffer;
  148 + inBuffer.open(QBuffer::ReadWrite);
  149 + QDataStream serializer(&inBuffer);
  150 + serializer << src;
  151 +
  152 + qint64 in_size = inBuffer.size();
  153 + outbound.write((char *) &in_size, sizeof(in_size));
  154 +
  155 + outbound.write(inBuffer.data(), in_size);
  156 +
  157 + while (outbound.bytesToWrite() > 0) {
  158 + outbound.waitForBytesWritten(-1);
  159 + }
  160 +
  161 + qint64 out_size;
  162 +
  163 + // read the size
  164 + receiver->waitForReadyRead(-1);
  165 + receiver->read((char *) &out_size, sizeof(out_size));
  166 + QByteArray outBuffer(out_size,'0');
  167 +
  168 + // read the (serialized) output templatelist
  169 + qint64 arrayPosition = 0;
  170 + while (arrayPosition < out_size) {
  171 + if (!receiver->bytesAvailable())
  172 + receiver->waitForReadyRead(-1);
  173 + arrayPosition += receiver->read(outBuffer.data()+arrayPosition, receiver->bytesAvailable());
  174 + }
  175 + // and deserialize it.
  176 + QDataStream deserialize(outBuffer);
  177 + deserialize >> dst;
  178 + }
  179 +
  180 +
  181 + void train(const TemplateList& data)
  182 + {
  183 + (void) data;
  184 + }
  185 +
  186 + // create the process
  187 + void init()
  188 + {
  189 + processActive = false;
  190 + }
  191 +
  192 + void activateProcess()
  193 + {
  194 + processActive = true;
  195 +
  196 + // generate a uuid for our local servers
  197 + QUuid id = QUuid::createUuid();
  198 + baseKey = id.toString();
  199 +
  200 + QStringList argumentList;
  201 + argumentList.append("-useGui");
  202 + argumentList.append("0");
  203 + argumentList.append("-algorithm");
  204 + argumentList.append(transform);
  205 + argumentList.append("-path");
  206 + argumentList.append(Globals->path);
  207 + argumentList.append("-parallelism");
  208 + argumentList.append(QString::number(0));
  209 + argumentList.append("-slave");
  210 + argumentList.append(baseKey);
  211 +
  212 + // start listening
  213 + inbound.listen(baseKey+"_master");
  214 +
  215 + workerProcess.setProcessChannelMode(QProcess::ForwardedChannels);
  216 + workerProcess.start("br", argumentList);
  217 + workerProcess.waitForStarted(-1);
  218 +
  219 + // blocking wait for the connection from the worker process
  220 + inbound.waitForNewConnection(-1);
  221 + receiver = inbound.nextPendingConnection();
  222 +
  223 + // Now, create our connection to the worker process.
  224 + outbound.connectToServer(baseKey+"_worker");
  225 + outbound.waitForConnected(-1);
  226 + }
  227 +
  228 + bool timeVarying() const {
  229 + return false;
  230 + }
  231 +
  232 + ~ProcessWrapperTransform()
  233 + {
  234 + // end the process
  235 + if (this->processActive) {
  236 +
  237 + SignalType signal = SHOULD_END;
  238 + outbound.write((char *) &signal, sizeof(SignalType));
  239 + outbound.waitForBytesWritten(-1);
  240 + outbound.close();
  241 +
  242 + workerProcess.waitForFinished(-1);
  243 + inbound.close();
  244 + processActive = false;
  245 + }
  246 + }
  247 +
  248 +public:
  249 + bool processActive;
  250 + ProcessWrapperTransform() : TimeVaryingTransform(false,false) { processActive = false; }
  251 +};
  252 +
  253 +BR_REGISTER(Transform, ProcessWrapperTransform)
  254 +
  255 +}
  256 +
  257 +#include "process.moc"
openbr/plugins/regions.cpp
@@ -345,9 +345,12 @@ class RectFromPointsTransform : public UntrainableTransform @@ -345,9 +345,12 @@ class RectFromPointsTransform : public UntrainableTransform
345 345
346 dst.file.setPoints(points); 346 dst.file.setPoints(points);
347 347
348 - if (crop) dst.m() = src.m()(Rect(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height))); 348 + const int x = std::max(0.0, minX - deltaWidth/2.0);
  349 + const int y = std::max(0.0, minY - deltaHeight/2.0);
  350 +
  351 + if (crop) dst.m() = src.m()(Rect(x, y, std::min((double)src.m().cols-x, width), std::min((double)src.m().rows-y, height)));
349 else { 352 else {
350 - dst.file.appendRect(QRectF(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height))); 353 + dst.file.appendRect(QRectF(x, y, std::min((double)src.m().cols-x, width), std::min((double)src.m().rows-y, height)));
351 dst.m() = src.m(); 354 dst.m() = src.m();
352 } 355 }
353 } 356 }
openbr/plugins/slidingwindow.cpp
@@ -8,12 +8,28 @@ @@ -8,12 +8,28 @@
8 8
9 using namespace cv; 9 using namespace cv;
10 10
11 -// Because MSVC doesn't provide a round() function in math.h  
12 -static int round(float x) { return (floor(x + 0.5)); }  
13 -  
14 namespace br 11 namespace br
15 { 12 {
16 13
  14 +// Find avg aspect ratio
  15 +static float getAspectRatio(const TemplateList &data)
  16 +{
  17 + double tempRatio = 0;
  18 + int ratioCnt = 0;
  19 +
  20 + foreach (const Template &tmpl, data) {
  21 + QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
  22 + foreach (const Rect &posRect, posRects) {
  23 + if (posRect.x + posRect.width >= tmpl.m().cols || posRect.y + posRect.height >= tmpl.m().rows || posRect.x < 0 || posRect.y < 0) {
  24 + continue;
  25 + }
  26 + tempRatio += (float)posRect.width / (float)posRect.height;
  27 + ratioCnt += 1;
  28 + }
  29 + }
  30 + return tempRatio / (double)ratioCnt;
  31 +}
  32 +
17 /*! 33 /*!
18 * \ingroup transforms 34 * \ingroup transforms
19 * \brief Applies a transform to a sliding window. 35 * \brief Applies a transform to a sliding window.
@@ -25,23 +41,19 @@ class SlidingWindowTransform : public Transform @@ -25,23 +41,19 @@ class SlidingWindowTransform : public Transform
25 Q_OBJECT 41 Q_OBJECT
26 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false) 42 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
27 Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false) 43 Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false)
28 - Q_PROPERTY(double scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)  
29 Q_PROPERTY(int stepSize READ get_stepSize WRITE set_stepSize RESET reset_stepSize STORED false) 44 Q_PROPERTY(int stepSize READ get_stepSize WRITE set_stepSize RESET reset_stepSize STORED false)
30 - Q_PROPERTY(bool takeLargestScale READ get_takeLargestScale WRITE set_takeLargestScale RESET reset_takeLargestScale STORED false) 45 + Q_PROPERTY(bool takeFirst READ get_takeFirst WRITE set_takeFirst RESET reset_takeFirst STORED false)
31 Q_PROPERTY(bool negSamples READ get_negSamples WRITE set_negSamples RESET reset_negSamples STORED false) 46 Q_PROPERTY(bool negSamples READ get_negSamples WRITE set_negSamples RESET reset_negSamples STORED false)
32 Q_PROPERTY(int negToPosRatio READ get_negToPosRatio WRITE set_negToPosRatio RESET reset_negToPosRatio STORED false) 47 Q_PROPERTY(int negToPosRatio READ get_negToPosRatio WRITE set_negToPosRatio RESET reset_negToPosRatio STORED false)
33 Q_PROPERTY(double maxOverlap READ get_maxOverlap WRITE set_maxOverlap RESET reset_maxOverlap STORED false) 48 Q_PROPERTY(double maxOverlap READ get_maxOverlap WRITE set_maxOverlap RESET reset_maxOverlap STORED false)
34 - Q_PROPERTY(float aspectRatio READ get_aspectRatio WRITE set_aspectRatio RESET reset_aspectRatio STORED true)  
35 Q_PROPERTY(int windowWidth READ get_windowWidth WRITE set_windowWidth RESET reset_windowWidth STORED false) 49 Q_PROPERTY(int windowWidth READ get_windowWidth WRITE set_windowWidth RESET reset_windowWidth STORED false)
36 BR_PROPERTY(br::Transform *, transform, NULL) 50 BR_PROPERTY(br::Transform *, transform, NULL)
37 BR_PROPERTY(int, minSize, 8) 51 BR_PROPERTY(int, minSize, 8)
38 - BR_PROPERTY(double, scaleFactor, 0.75)  
39 BR_PROPERTY(int, stepSize, 1) 52 BR_PROPERTY(int, stepSize, 1)
40 - BR_PROPERTY(bool, takeLargestScale, true) 53 + BR_PROPERTY(bool, takeFirst, false)
41 BR_PROPERTY(bool, negSamples, true) 54 BR_PROPERTY(bool, negSamples, true)
42 BR_PROPERTY(int, negToPosRatio, 1) 55 BR_PROPERTY(int, negToPosRatio, 1)
43 BR_PROPERTY(double, maxOverlap, 0) 56 BR_PROPERTY(double, maxOverlap, 0)
44 - BR_PROPERTY(float, aspectRatio, 1)  
45 BR_PROPERTY(int, windowWidth, 24) 57 BR_PROPERTY(int, windowWidth, 24)
46 58
47 public: 59 public:
@@ -50,24 +62,14 @@ private: @@ -50,24 +62,14 @@ private:
50 62
51 void train(const TemplateList &data) 63 void train(const TemplateList &data)
52 { 64 {
  65 + // only calculate if the work hasn't been done
  66 + aspectRatio = data.first().file.get<float>("aspectRatio", -1);
  67 + if (aspectRatio == -1)
  68 + aspectRatio = getAspectRatio(data);
  69 +
53 if (transform->trainable) { 70 if (transform->trainable) {
54 - double tempRatio = 0;  
55 - int ratioCnt = 0;  
56 TemplateList full; 71 TemplateList full;
57 72
58 - //First find avg aspect ratio  
59 - foreach (const Template &tmpl, data) {  
60 - QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());  
61 - foreach (const Rect &posRect, posRects) {  
62 - if (posRect.x + posRect.width >= tmpl.m().cols || posRect.y + posRect.height >= tmpl.m().rows || posRect.x < 0 || posRect.y < 0) {  
63 - continue;  
64 - }  
65 - tempRatio += (float)posRect.width / (float)posRect.height;  
66 - ratioCnt += 1;  
67 - }  
68 - }  
69 - aspectRatio = tempRatio / (double)ratioCnt;  
70 -  
71 foreach (const Template &tmpl, data) { 73 foreach (const Template &tmpl, data) {
72 QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects()); 74 QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
73 QList<Rect> negRects; 75 QList<Rect> negRects;
@@ -83,7 +85,7 @@ private: @@ -83,7 +85,7 @@ private:
83 } 85 }
84 86
85 Mat scaledImg; 87 Mat scaledImg;
86 - resize(Mat(tmpl, posRect), scaledImg, Size(windowWidth,round(windowWidth / aspectRatio))); 88 + resize(Mat(tmpl, posRect), scaledImg, Size(windowWidth,qRound(windowWidth / aspectRatio)));
87 Template pos(tmpl.file, scaledImg); 89 Template pos(tmpl.file, scaledImg);
88 full += pos; 90 full += pos;
89 91
@@ -132,43 +134,94 @@ private: @@ -132,43 +134,94 @@ private:
132 if (src.file.getBool("Train", false)) return; 134 if (src.file.getBool("Train", false)) return;
133 135
134 dst.file.clearRects(); 136 dst.file.clearRects();
  137 + int windowHeight = (int) qRound((float) windowWidth / aspectRatio);
  138 + int scale = src.file.get<float>("scale", 1);
  139 +
  140 + for (double y = 0; y + windowHeight < src.m().rows; y += stepSize) {
  141 + for (double x = 0; x + windowWidth < src.m().cols; x += stepSize) {
  142 + Rect window(x, y, windowWidth, windowHeight);
  143 + Template windowMat(src.file, Mat(src, window));
  144 + Template detect;
  145 + transform->project(windowMat, detect);
  146 + float conf = detect.file.get<float>("Confidence");
  147 +
  148 + // the result will be in the Label
  149 + if (conf > 0) {
  150 + dst.file.appendRect(QRectF((float) x * scale, (float) y * scale, (float) windowWidth * scale, (float) windowHeight * scale));
  151 + QList<float> confidences = dst.file.getList<float>("Confidences", QList<float>());
  152 + confidences.append(conf);
  153 + dst.file.setList<float>("Confidences", confidences);
  154 + if (takeFirst)
  155 + return;
  156 + }
  157 + }
  158 + }
  159 + }
  160 +
  161 + float aspectRatio;
  162 +};
  163 +
  164 +BR_REGISTER(Transform, SlidingWindowTransform)
  165 +
  166 +/*!
  167 + * \ingroup transforms
  168 + * \brief .
  169 + * \author Austin Blanton \cite imaus10
  170 + */
  171 +class BuildScalesTransform : public Transform
  172 +{
  173 + Q_OBJECT
  174 + Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
  175 + Q_PROPERTY(double scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
  176 + Q_PROPERTY(bool takeLargestScale READ get_takeLargestScale WRITE set_takeLargestScale RESET reset_takeLargestScale STORED false)
  177 + Q_PROPERTY(int windowWidth READ get_windowWidth WRITE set_windowWidth RESET reset_windowWidth STORED false)
  178 + BR_PROPERTY(br::Transform *, transform, NULL)
  179 + BR_PROPERTY(double, scaleFactor, 0.75)
  180 + BR_PROPERTY(bool, takeLargestScale, false)
  181 + BR_PROPERTY(int, windowWidth, 24)
  182 +
  183 +public:
  184 + BuildScalesTransform() : Transform(false, true) {}
  185 +private:
  186 +
  187 + void train(const TemplateList &data)
  188 + {
  189 + aspectRatio = getAspectRatio(data);
  190 + // have to make a copy b/c data is const
  191 + TemplateList cp = data;
  192 + cp.first().file.set("aspectRatio", aspectRatio);
  193 + if (transform->trainable)
  194 + transform->train(cp);
  195 + }
  196 +
  197 + void project(const Template &src, Template &dst) const
  198 + {
  199 + dst = src;
  200 + // do not scale images during training
  201 + if (src.file.getBool("Train", false)) return;
  202 +
135 int rows = src.m().rows; 203 int rows = src.m().rows;
136 int cols = src.m().cols; 204 int cols = src.m().cols;
137 - int windowHeight = (int) round((float) windowWidth / aspectRatio); 205 + int windowHeight = (int) qRound((float) windowWidth / aspectRatio);
138 float startScale; 206 float startScale;
139 if ((cols / rows) > aspectRatio) 207 if ((cols / rows) > aspectRatio)
140 - startScale = round((float) rows / (float) windowHeight); 208 + startScale = qRound((float) rows / (float) windowHeight);
141 else 209 else
142 - startScale = round((float) cols / (float) windowWidth);  
143 - 210 + startScale = qRound((float) cols / (float) windowWidth);
144 for (float scale = startScale; scale >= 1.0; scale -= (1.0 - scaleFactor)) { 211 for (float scale = startScale; scale >= 1.0; scale -= (1.0 - scaleFactor)) {
145 - Mat scaleImg;  
146 - resize(src, scaleImg, Size(round(cols / scale), round(rows / scale)));  
147 -  
148 - for (double y = 0; y + windowHeight < scaleImg.rows; y += stepSize) {  
149 - for (double x = 0; x + windowWidth < scaleImg.cols; x += stepSize) {  
150 - Rect window(x, y, windowWidth, windowHeight);  
151 - Template windowMat(src.file, Mat(scaleImg, window));  
152 - Template detect;  
153 - transform->project(windowMat, detect);  
154 - float conf = detect.file.get<float>("conf");  
155 -  
156 - // the result will be in the Label  
157 - if (conf > 0) {  
158 - dst.file.appendRect(QRectF((float) x * scale, (float) y * scale, (float) windowWidth * scale, (float) windowHeight * scale));  
159 - QList<float> confidences = dst.file.getList<float>("Confidences", QList<float>());  
160 - confidences.append(conf);  
161 - dst.file.setList<float>("Confidences", confidences);  
162 - if (takeLargestScale)  
163 - return;  
164 - }  
165 - }  
166 - } 212 + Template scaleImg(src.file, Mat());
  213 + scaleImg.file.set("scale", scale);
  214 + resize(src, scaleImg, Size(qRound(cols / scale), qRound(rows / scale)));
  215 + transform->project(scaleImg, dst);
  216 + if (takeLargestScale && !dst.file.rects().empty())
  217 + return;
167 } 218 }
168 } 219 }
  220 +
  221 + float aspectRatio;
169 }; 222 };
170 223
171 -BR_REGISTER(Transform, SlidingWindowTransform) 224 +BR_REGISTER(Transform, BuildScalesTransform)
172 225
173 /*! 226 /*!
174 * \ingroup transforms 227 * \ingroup transforms
openbr/plugins/stasm4.cpp
@@ -132,13 +132,16 @@ class StasmTransform : public UntrainableTransform @@ -132,13 +132,16 @@ class StasmTransform : public UntrainableTransform
132 132
133 if (!foundFace) { 133 if (!foundFace) {
134 qWarning("No face found in %s.", qPrintable(src.file.fileName())); 134 qWarning("No face found in %s.", qPrintable(src.file.fileName()));
  135 + dst.file.set("FTE",true);
135 } else { 136 } else {
  137 + QList<QPointF> points;
136 for (int i = 0; i < nLandmarks; i++) { 138 for (int i = 0; i < nLandmarks; i++) {
137 QPointF point(landmarks[2 * i], landmarks[2 * i + 1]); 139 QPointF point(landmarks[2 * i], landmarks[2 * i + 1]);
138 - dst.file.appendPoint(point);  
139 - if (i == 38) dst.file.set("StasmRightEye",point);  
140 - else if (i == 39) dst.file.set("StasmLeftEye", point); 140 + points.append(point);
141 } 141 }
  142 + dst.file.set("StasmRightEye", points[38]);
  143 + dst.file.set("StasmLeftEye", points[39]);
  144 + dst.file.appendPoints(points);
142 } 145 }
143 } 146 }
144 }; 147 };
openbr/plugins/svm.cpp
@@ -157,7 +157,7 @@ private: @@ -157,7 +157,7 @@ private:
157 dst = src; 157 dst = src;
158 float prediction = svm.predict(src.m().reshape(1, 1), returnDFVal); 158 float prediction = svm.predict(src.m().reshape(1, 1), returnDFVal);
159 if (returnDFVal) { 159 if (returnDFVal) {
160 - dst.file.set("conf", prediction); 160 + dst.file.set("Confidence", prediction);
161 // positive values ==> first class 161 // positive values ==> first class
162 // negative values ==> second class 162 // negative values ==> second class
163 prediction = prediction > 0 ? 0 : 1; 163 prediction = prediction > 0 ? 0 : 1;
openbr/plugins/template.cpp
@@ -9,7 +9,7 @@ namespace br @@ -9,7 +9,7 @@ namespace br
9 * \brief Retains only the values for the keys listed, to reduce template size 9 * \brief Retains only the values for the keys listed, to reduce template size
10 * \author Scott Klum \cite sklum 10 * \author Scott Klum \cite sklum
11 */ 11 */
12 -class RetainTransform : public UntrainableTransform 12 +class KeepMetadataTransform : public UntrainableTransform
13 { 13 {
14 Q_OBJECT 14 Q_OBJECT
15 Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false) 15 Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)
@@ -24,7 +24,7 @@ class RetainTransform : public UntrainableTransform @@ -24,7 +24,7 @@ class RetainTransform : public UntrainableTransform
24 } 24 }
25 }; 25 };
26 26
27 -BR_REGISTER(Transform, RetainTransform) 27 +BR_REGISTER(Transform, KeepMetadataTransform)
28 28
29 /*! 29 /*!
30 * \ingroup transforms 30 * \ingroup transforms
openbr/plugins/validate.cpp
@@ -255,7 +255,7 @@ class RejectDistance : public Distance @@ -255,7 +255,7 @@ class RejectDistance : public Distance
255 { 255 {
256 // We don't look at the query 256 // We don't look at the query
257 (void) b; 257 (void) b;
258 - 258 +
259 foreach (const QString &key, keys) 259 foreach (const QString &key, keys)
260 if ((rejectIfContains && a.file.contains(key)) || (!rejectIfContains && !a.file.contains(key))) 260 if ((rejectIfContains && a.file.contains(key)) || (!rejectIfContains && !a.file.contains(key)))
261 return -std::numeric_limits<float>::max(); 261 return -std::numeric_limits<float>::max();