Commit 5b3c7a8e3f84b7b1a74e239aac740aed90c9b1dc

Authored by Scott Klum
2 parents b173ffc4 207bab56

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

openbr/plugins/gui.cpp
@@ -70,6 +70,7 @@ public: @@ -70,6 +70,7 @@ public:
70 70
71 DisplayWindow(QWidget * parent = NULL) : QLabel(parent) 71 DisplayWindow(QWidget * parent = NULL) : QLabel(parent)
72 { 72 {
  73 + setFixedSize(200,200);
73 QApplication::instance()->installEventFilter(this); 74 QApplication::instance()->installEventFilter(this);
74 } 75 }
75 76
@@ -80,7 +81,13 @@ public slots: @@ -80,7 +81,13 @@ public slots:
80 81
81 show(); 82 show();
82 setPixmap(pixmap); 83 setPixmap(pixmap);
83 - setFixedSize(input.size()); 84 +
  85 + // We appear to get a warning on windows if we set window width < 104. This is of course not
  86 + // reflected in the Qt min size settings, and I don't know how to query it.
  87 + QSize temp = input.size();
  88 + if (temp.width() < 104)
  89 + temp.setWidth(104);
  90 + setFixedSize(temp);
84 } 91 }
85 92
86 93
openbr/plugins/misc.cpp
@@ -354,27 +354,31 @@ BR_REGISTER(Transform, AsTransform) @@ -354,27 +354,31 @@ BR_REGISTER(Transform, AsTransform)
354 354
355 /*! 355 /*!
356 * \ingroup transforms 356 * \ingroup transforms
357 - * \brief Change the template subject using a regular expresion matched to the file's base name.  
358 - * \author Josh Klontz \cite jklontz 357 + * \brief Apply the input regular expression to the value of inputProperty, store the matched portion in outputProperty.
  358 + * \author Charles Otto \cite caotto
359 */ 359 */
360 -class SubjectTransform : public UntrainableMetaTransform 360 +class RegexPropertyTransform : public UntrainableMetaTransform
361 { 361 {
362 Q_OBJECT 362 Q_OBJECT
363 Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false) 363 Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false)
  364 + Q_PROPERTY(QString inputProperty READ get_inputProperty WRITE set_inputProperty RESET reset_inputProperty STORED false)
  365 + Q_PROPERTY(QString outputProperty READ get_outputProperty WRITE set_outputProperty RESET reset_outputProperty STORED false)
364 BR_PROPERTY(QString, regexp, "(.*)") 366 BR_PROPERTY(QString, regexp, "(.*)")
  367 + BR_PROPERTY(QString, inputProperty, "name")
  368 + BR_PROPERTY(QString, outputProperty, "Label")
365 369
366 void project(const Template &src, Template &dst) const 370 void project(const Template &src, Template &dst) const
367 { 371 {
368 dst = src; 372 dst = src;
369 QRegularExpression re(regexp); 373 QRegularExpression re(regexp);
370 - QRegularExpressionMatch match = re.match(dst.file.baseName()); 374 + QRegularExpressionMatch match = re.match(dst.file.get<QString>(inputProperty));
371 if (!match.hasMatch()) 375 if (!match.hasMatch())
372 - qFatal("Unable to match regular expression \"%s\" to base name \"%s\"!", qPrintable(regexp), qPrintable(dst.file.baseName()));  
373 - dst.file.set("Subject", match.captured(match.lastCapturedIndex())); 376 + qFatal("Unable to match regular expression \"%s\" to base name \"%s\"!", qPrintable(regexp), qPrintable(dst.file.get<QString>(inputProperty)));
  377 + dst.file.set(outputProperty, match.captured(match.lastCapturedIndex()));
374 } 378 }
375 }; 379 };
376 380
377 -BR_REGISTER(Transform, SubjectTransform) 381 +BR_REGISTER(Transform, RegexPropertyTransform)
378 382
379 /*! 383 /*!
380 * \ingroup transforms 384 * \ingroup transforms
@@ -470,6 +474,73 @@ class RestoreMatTransform : public UntrainableMetaTransform @@ -470,6 +474,73 @@ class RestoreMatTransform : public UntrainableMetaTransform
470 BR_REGISTER(Transform, RestoreMatTransform) 474 BR_REGISTER(Transform, RestoreMatTransform)
471 475
472 476
  477 +/*!
  478 + * \ingroup transforms
  479 + * \brief Incrementally output templates received to a gallery, based on the current filename
  480 + * When a template is received in projectUpdate for the first time since a finalize, open a new gallery based on the
  481 + * template's filename, and the galleryFormat property.
  482 + * Templates received in projectUpdate will be output to the gallery with a filename combining their original filename and
  483 + * their FrameNumber property, with the file extension specified by the fileFormat property.
  484 + * \author Charles Otto \cite caotto
  485 + */
  486 +class IncrementalOutputTransform : public TimeVaryingTransform
  487 +{
  488 + Q_OBJECT
  489 +
  490 + Q_PROPERTY(QString galleryFormat READ get_galleryFormat WRITE set_galleryFormat RESET reset_galleryFormat STORED false)
  491 + Q_PROPERTY(QString fileFormat READ get_fileFormat WRITE set_fileFormat RESET reset_fileFormat STORED false)
  492 + BR_PROPERTY(QString, galleryFormat, "")
  493 + BR_PROPERTY(QString, fileFormat, ".png")
  494 +
  495 + bool galleryUp;
  496 +
  497 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  498 + {
  499 + if (src.empty())
  500 + return;
  501 +
  502 + if (!galleryUp) {
  503 + QFileInfo finfo(src[0].file.name);
  504 + QString galleryName = finfo.baseName() + galleryFormat;
  505 +
  506 + writer = QSharedPointer<Gallery> (Factory<Gallery>::make(galleryName));
  507 + galleryUp = true;
  508 + }
  509 +
  510 + dst = src;
  511 + foreach(const Template & t, src) {
  512 + if (t.empty())
  513 + continue;
  514 +
  515 + // Build the output filename for this template
  516 + QFileInfo finfo(t.file.name);
  517 + QString outputName = finfo.baseName() +"_" + t.file.get<QString>("FrameNumber") + fileFormat;
  518 +
  519 + Template out = t;
  520 + out.file.name = outputName;
  521 + writer->write(out);
  522 + }
  523 + }
  524 +
  525 + void train(const TemplateList& data)
  526 + {
  527 + (void) data;
  528 + }
  529 +
  530 + // Drop the current gallery.
  531 + void finalize(TemplateList & data)
  532 + {
  533 + (void) data;
  534 + galleryUp = false;
  535 + }
  536 +
  537 + QSharedPointer<Gallery> writer;
  538 +public:
  539 + IncrementalOutputTransform() : TimeVaryingTransform(false,false) {galleryUp = false;}
  540 +};
  541 +
  542 +BR_REGISTER(Transform, IncrementalOutputTransform)
  543 +
473 class EventTransform : public UntrainableMetaTransform 544 class EventTransform : public UntrainableMetaTransform
474 { 545 {
475 Q_OBJECT 546 Q_OBJECT
openbr/plugins/stream.cpp
@@ -364,6 +364,7 @@ protected: @@ -364,6 +364,7 @@ protected:
364 QMutex last_frame_update; 364 QMutex last_frame_update;
365 }; 365 };
366 366
  367 +static QMutex openLock;
367 // Read a video frame by frame using cv::VideoCapture 368 // Read a video frame by frame using cv::VideoCapture
368 class VideoDataSource : public DataSource 369 class VideoDataSource : public DataSource
369 { 370 {
@@ -396,6 +397,8 @@ public: @@ -396,6 +397,8 @@ public:
396 // Yes, we should specify absolute path: 397 // Yes, we should specify absolute path:
397 // http://stackoverflow.com/questions/9396459/loading-a-video-in-opencv-in-python 398 // http://stackoverflow.com/questions/9396459/loading-a-video-in-opencv-in-python
398 QString fileName = (Globals->path.isEmpty() ? "" : Globals->path + "/") + input.file.name; 399 QString fileName = (Globals->path.isEmpty() ? "" : Globals->path + "/") + input.file.name;
  400 + // On windows, this appears to not be thread-safe
  401 + QMutexLocker lock(&openLock);
399 video.open(QFileInfo(fileName).absoluteFilePath().toStdString()); 402 video.open(QFileInfo(fileName).absoluteFilePath().toStdString());
400 } 403 }
401 404
@@ -1057,7 +1060,10 @@ public: @@ -1057,7 +1060,10 @@ public:
1057 dst = src; 1060 dst = src;
1058 1061
1059 bool res = readStage->dataSource.open(dst); 1062 bool res = readStage->dataSource.open(dst);
1060 - if (!res) return; 1063 + if (!res) {
  1064 + qDebug("stream failed to open %s", qPrintable(dst[0].file.name));
  1065 + return;
  1066 + }
1061 1067
1062 // Start the first thread in the stream. 1068 // Start the first thread in the stream.
1063 QWriteLocker lock(&readStage->statusLock); 1069 QWriteLocker lock(&readStage->statusLock);