Commit e6ad9c2274ce1248cd833074296cfeea5200afb3

Authored by Scott Klum
2 parents a66afbe5 4c595c32

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

app/br/br.cpp
... ... @@ -167,6 +167,8 @@ public:
167 167 else if (!strcmp(fun, "help")) {
168 168 check(parc == 0, "No parameters expected for 'help'.");
169 169 help();
  170 + } else if (!strcmp(fun, "gui")) {
  171 + // Do nothing because we checked for this flag prior to initialization
170 172 } else if (!strcmp(fun, "objects")) {
171 173 check(parc <= 2, "Incorrect parameter count for 'objects'.");
172 174 printf("%s\n", br_objects(parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*"));
... ... @@ -180,11 +182,10 @@ public:
180 182 check(parc == 1, "Incorrect parameter count for 'daemon'.");
181 183 daemon = true;
182 184 daemon_pipe = parv[0];
183   - } else if (!strcmp(fun,"slave")) {
  185 + } else if (!strcmp(fun, "slave")) {
184 186 check(parc == 1, "Incorrect parameter count for 'slave'");
185 187 br_slave_process(parv[0]);
186   - }
187   - else if (!strcmp(fun, "exit")) {
  188 + } else if (!strcmp(fun, "exit")) {
188 189 check(parc == 0, "No parameters expected for 'exit'.");
189 190 daemon = false;
190 191 } else if (!strcmp(fun, "getHeader")) {
... ... @@ -248,6 +249,7 @@ private:
248 249 "\n"
249 250 "==== Miscellaneous ====\n"
250 251 "-help\n"
  252 + "-gui\n"
251 253 "-objects [abstraction [implementation]]\n"
252 254 "-about\n"
253 255 "-version\n"
... ... @@ -258,7 +260,7 @@ private:
258 260  
259 261 int main(int argc, char *argv[])
260 262 {
261   - br_initialize(argc, argv);
  263 + br_initialize(argc, argv, "", argc >= 2 && !strcmp(argv[1], "-gui"));
262 264  
263 265 FakeMain *fakeMain = new FakeMain(argc, argv);
264 266 QThreadPool::globalInstance()->start(fakeMain);
... ...
openbr/core/core.cpp
... ... @@ -65,6 +65,9 @@ struct AlgorithmCore
65 65 downcast->train(data);
66 66  
67 67 if (!distance.isNull()) {
  68 + if (Globals->crossValidate > 0)
  69 + for (int i=data.size()-1; i>=0; i--) if (data[i].file.get<bool>("allPartitions",false)) data.removeAt(i);
  70 +
68 71 qDebug("Projecting Enrollment");
69 72 downcast->projectUpdate(data,data);
70 73  
... ...
1   -Subproject commit 02fd545b2dbb8ea2ba10dbf67e429da598545d75
  1 +Subproject commit f8d9c869c821cc032d092ab1274da8f3cabf5eb7
... ...
openbr/janus.cpp
... ... @@ -13,7 +13,7 @@ static QSharedPointer&lt;Distance&gt; distance;
13 13  
14 14 size_t janus_max_template_size()
15 15 {
16   - return JANUS_MAX_TEMPLATE_SIZE_LIMIT;
  16 + return 33554432; // 32 MB
17 17 }
18 18  
19 19 janus_error janus_initialize(const char *sdk_path, const char *model_file)
... ...
openbr/openbr.cpp
... ... @@ -122,9 +122,9 @@ void br_fuse(int num_input_simmats, const char *input_simmats[],
122 122 Fuse(QtUtils::toStringList(num_input_simmats, input_simmats), normalization, fusion, output_simmat);
123 123 }
124 124  
125   -void br_initialize(int &argc, char *argv[], const char *sdk_path)
  125 +void br_initialize(int &argc, char *argv[], const char *sdk_path, bool use_gui)
126 126 {
127   - Context::initialize(argc, argv, sdk_path);
  127 + Context::initialize(argc, argv, sdk_path, use_gui);
128 128 }
129 129  
130 130 void br_initialize_default()
... ... @@ -382,10 +382,9 @@ bool br_img_is_empty(br_template tmpl)
382 382  
383 383 const char* br_get_filename(br_template tmpl)
384 384 {
385   - Template *t = reinterpret_cast<Template*>(tmpl);
386   - QByteArray s = t->file.name.toLocal8Bit();
387   - char *buffer = s.data();
388   - return buffer;
  385 + static QByteArray buffer;
  386 + buffer = reinterpret_cast<Template*>(tmpl)->file.name.toLocal8Bit();
  387 + return buffer.data();
389 388 }
390 389  
391 390 void br_set_filename(br_template tmpl, const char *filename)
... ...
openbr/openbr.h
... ... @@ -224,7 +224,7 @@ BR_EXPORT void br_fuse(int num_input_simmats, const char *input_simmats[],
224 224 * \brief Wraps br::Context::initialize()
225 225 * \see br_finalize
226 226 */
227   -BR_EXPORT void br_initialize(int &argc, char *argv[], const char *sdk_path = "");
  227 +BR_EXPORT void br_initialize(int &argc, char *argv[], const char *sdk_path = "", bool use_gui = false);
228 228 /*!
229 229 * \brief Wraps br::Context::initialize() with default arguments.
230 230 * \see br_finalize
... ...
openbr/openbr_plugin.cpp
... ... @@ -899,8 +899,12 @@ void br::Context::initialize(int &amp;argc, char *argv[], QString sdkPath, bool useG
899 899 {
900 900 qInstallMessageHandler(messageHandler);
901 901  
  902 + QString sep;
902 903 #ifndef _WIN32
903 904 useGui = useGui && (getenv("DISPLAY") != NULL);
  905 + sep = ":";
  906 +#else
  907 + sep = ";";
904 908 #endif // not _WIN32
905 909  
906 910 // We take in argc as a reference due to:
... ... @@ -944,6 +948,7 @@ void br::Context::initialize(int &amp;argc, char *argv[], QString sdkPath, bool useG
944 948 // Search for SDK
945 949 if (sdkPath.isEmpty()) {
946 950 QStringList checkPaths; checkPaths << QDir::currentPath() << QCoreApplication::applicationDirPath();
  951 + checkPaths << QString(getenv("PATH")).split(sep, QString::SkipEmptyParts);
947 952  
948 953 bool foundSDK = false;
949 954 foreach (const QString &path, checkPaths) {
... ...
openbr/plugins/gui.cpp
1 1 #include <QApplication>
2 2 #include <QLabel>
3 3 #include <QElapsedTimer>
  4 +#include <QInputDialog>
4 5 #include <QWaitCondition>
5 6 #include <QMutex>
6 7 #include <QMouseEvent>
... ... @@ -182,6 +183,149 @@ public slots:
182 183 }
183 184 };
184 185  
  186 +class RectMarkingWindow : public DisplayWindow
  187 +{
  188 +public:
  189 + RectMarkingWindow() : DisplayWindow()
  190 + {
  191 + drawingRect = false;
  192 + }
  193 +
  194 + bool drawingRect;
  195 + QVector<QRectF> rects;
  196 + QList<QString> rectLabels;
  197 +
  198 + QPointF rectOrigin;
  199 + QPointF currentEnd;
  200 + QRectF currentRect;
  201 + bool disableAccept;
  202 +
  203 + bool eventFilter(QObject *obj, QEvent *event)
  204 + {
  205 + if (disableAccept)
  206 + return QObject::eventFilter(obj, event);
  207 +
  208 +
  209 + if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseMove)
  210 + {
  211 + event->accept();
  212 +
  213 + QMouseEvent *mouseEvent = (QMouseEvent*)event;
  214 +
  215 + if (event->type() == QEvent::MouseButtonPress)
  216 + {
  217 +
  218 + if (mouseEvent->button() == Qt::LeftButton) {
  219 + if (!drawingRect)
  220 + {
  221 + drawingRect = true;
  222 + rectOrigin = mouseEvent->pos();
  223 + return true;
  224 + }
  225 + else
  226 + {
  227 + drawingRect = false;
  228 +
  229 + rects.append(QRectF(rectOrigin, mouseEvent->pos()));
  230 + rects.last() = rects.last().normalized();
  231 + // If no labels were provided, we store everything as anonymous rectangles
  232 + if (promptKeys.empty())
  233 + rectLabels.append("rects");
  234 + // otherwise, prompt the user to select a label
  235 + else
  236 + {
  237 + // get a label from the user
  238 + bool ok = false;
  239 +
  240 + // Don't intercept events while the sub-dialog is up (if we take the events, then it will not work correctly)
  241 + disableAccept = true;
  242 + QString res = QInputDialog::getItem(this, "Select a label", "", promptKeys, next_idx, false, &ok);
  243 +
  244 + disableAccept = false;
  245 + if (ok) {
  246 + rectLabels.append(res);
  247 + for (int i=0; i < promptKeys.size(); i++)
  248 + {
  249 + if (res == promptKeys[i]) {
  250 + next_idx = (i + 1) % promptKeys.size();
  251 + break;
  252 + }
  253 + }
  254 + }
  255 + else {
  256 + rects.removeLast();
  257 + }
  258 + }
  259 + }
  260 + }
  261 + // rclick -- reset state if drawing, remove last rect if done
  262 + else if (mouseEvent->button() == Qt::RightButton && (!rects.isEmpty() || drawingRect))
  263 + {
  264 + if(drawingRect)
  265 + drawingRect = false;
  266 + else
  267 + {
  268 + rects.removeLast();
  269 + rectLabels.removeLast();
  270 + }
  271 + }
  272 + }
  273 + else
  274 + currentEnd = mouseEvent->pos();
  275 + QPixmap pixmapBuffer = pixmap;
  276 +
  277 + QPainter painter(&pixmapBuffer);
  278 + painter.setPen(Qt::red);
  279 +
  280 + painter.drawRects(rects);
  281 +
  282 + if (drawingRect)
  283 + {
  284 + currentRect = QRectF(rectOrigin, currentEnd);
  285 + painter.setPen(Qt::green);
  286 + painter.drawRect(currentRect);
  287 + }
  288 +
  289 + setPixmap(pixmapBuffer);
  290 +
  291 + return true;
  292 + } else {
  293 + if (event->type() == QEvent::KeyPress)
  294 + {
  295 + QKeyEvent * kevent = (QKeyEvent *) event;
  296 + if (kevent->key() == Qt::Key_Enter || kevent->key() == Qt::Key_Return) {
  297 + event->accept();
  298 + return true;
  299 + }
  300 + }
  301 + return DisplayWindow::eventFilter(obj, event);
  302 + }
  303 + }
  304 +
  305 +
  306 + QList<QPointF> waitForKey()
  307 + {
  308 +
  309 + rects.clear();
  310 + drawingRect = false;
  311 + disableAccept = false;
  312 + next_idx = 0;
  313 + DisplayWindow::waitForKey();
  314 +
  315 + return QList<QPointF>();
  316 + }
  317 +
  318 + void setKeys(const QStringList & keys)
  319 + {
  320 + promptKeys = keys;
  321 + }
  322 +
  323 + int next_idx;
  324 +private:
  325 + QStringList promptKeys;
  326 +
  327 +};
  328 +
185 329 class PointMarkingWindow : public DisplayWindow
186 330 {
187 331 bool eventFilter(QObject *obj, QEvent *event)
... ... @@ -556,6 +700,87 @@ BR_REGISTER(Transform, ManualTransform)
556 700  
557 701 /*!
558 702 * \ingroup transforms
  703 + * \brief Manual select rectangular regions on an image.
  704 + * Stores marked rectangles as anonymous rectangles, or if a set of labels is provided, prompt the user
  705 + * to select one of those labels after drawing each rectangle.
  706 + * \author Charles Otto \cite caotto
  707 + */
  708 +class ManualRectsTransform : public ShowTransform
  709 +{
  710 + Q_OBJECT
  711 +
  712 +public:
  713 +
  714 + Q_PROPERTY(QStringList labels READ get_labels WRITE set_labels RESET reset_labels STORED false)
  715 + BR_PROPERTY(QStringList, labels, QStringList())
  716 +
  717 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  718 + {
  719 +
  720 + dst = src;
  721 +
  722 + if (src.empty())
  723 + return;
  724 +
  725 + for (int i = 0; i < dst.size(); i++) {
  726 + foreach(const cv::Mat &m, dst[i]) {
  727 + qImageBuffer = toQImage(m);
  728 + displayBuffer->convertFromImage(qImageBuffer);
  729 +
  730 + emit updateImage(displayBuffer->copy(displayBuffer->rect()));
  731 +
  732 + // Blocking wait for a key-press
  733 + if (this->waitInput) {
  734 + window->waitForKey();
  735 + QVector<QRectF> rectSet = trueWindow->rects;
  736 + QList<QString> labelSet= trueWindow->rectLabels;
  737 +
  738 + for (int idx = 0; idx < rectSet.size(); idx++)
  739 + {
  740 + if (dst[i].file.contains(labelSet[idx]))
  741 + {
  742 + QVariant currentProp = dst[i].file.value(labelSet[idx]);
  743 + QList<QVariant> currentPropList;
  744 +
  745 + if (currentProp.canConvert<QList<QVariant> >() )
  746 + {
  747 + currentPropList = currentProp.toList();
  748 + }
  749 + else if (currentProp.canConvert<QRectF>())
  750 + {
  751 + currentPropList.append(currentProp);
  752 + }
  753 + else
  754 + {
  755 + qFatal("Unknown type of property");
  756 + }
  757 +
  758 + currentPropList.append(rectSet[idx]);
  759 + dst[i].file.set(labelSet[idx], QVariant::fromValue(currentPropList));
  760 + }
  761 + else
  762 + {
  763 + dst[i].file.set(labelSet[idx], rectSet[idx]);
  764 + }
  765 + }
  766 + }
  767 +
  768 + }
  769 + }
  770 + }
  771 + RectMarkingWindow * trueWindow;
  772 + void init()
  773 + {
  774 + initActual<RectMarkingWindow>();
  775 + trueWindow = dynamic_cast<RectMarkingWindow *> (this->window);
  776 + trueWindow->setKeys(this->keys);
  777 + }
  778 +};
  779 +
  780 +BR_REGISTER(Transform, ManualRectsTransform)
  781 +
  782 +/*!
  783 + * \ingroup transforms
559 784 * \brief Elicits metadata for templates in a pretty GUI
560 785 * \author Scott Klum \cite sklum
561 786 */
... ...
openbr/plugins/output.cpp
... ... @@ -268,7 +268,7 @@ class rrOutput : public MatrixOutput
268 268  
269 269 for (int i=0; i<queryFiles.size(); i++) {
270 270 QStringList files;
271   - if (simple) files.append(queryFiles[i]);
  271 + if (simple) files.append(queryFiles[i].fileName());
272 272  
273 273 typedef QPair<float,int> Pair;
274 274 foreach (const Pair &pair, Common::Sort(OpenCVUtils::matrixToVector<float>(data.row(i)), true, limit)) {
... ... @@ -276,7 +276,7 @@ class rrOutput : public MatrixOutput
276 276 if (pair.first < threshold) break;
277 277 File target = targetFiles[pair.second];
278 278 target.set("Score", QString::number(pair.first));
279   - if (simple) files.append(target.baseName() + " " + QString::number(pair.first));
  279 + if (simple) files.append(target.fileName() + " " + QString::number(pair.first));
280 280 else files.append(target.flat());
281 281 }
282 282 }
... ...
openbr/plugins/validate.cpp
... ... @@ -108,6 +108,7 @@ class CrossValidateTransform : public MetaTransform
108 108 // If we want to duplicate templates but use the same training data
109 109 // for all partitions (i.e. transforms.size() == 1), we need to
110 110 // restrict the partition
  111 +
111 112 int partition = src.file.get<int>("Partition", 0);
112 113 partition = (partition >= transforms.size()) ? 0 : partition;
113 114 transforms[partition]->project(src, dst);
... ...