Commit ca4e68e31759076392e5e78419dd6210c5a64661

Authored by Scott Klum
2 parents c8c71156 ead4a56a

Fixed some DisplayGUI logic

data/FDDB/README.md 0 → 100644
  1 +## FDDB Face Detection Data Set and Benchmark
  2 +Unconstrained face detection dataset containing 2845 images with 5171 annotated face locations. Contained in this directory are .FDDB files for train and test splits for FDDB. These are based on the `FDDB-folds` directory that comes with the original dataset, but organized as 10 different train/test splits instead of 10 folds. All splits are based on the original folds.
  3 +
  4 +Image data currently available online.
  5 +* [Website](http://vis-www.cs.umass.edu/fddb/)
... ...
data/README.md
... ... @@ -10,6 +10,7 @@
10 10 * [MNIST](MNIST/README.md)
11 11 * [PCSO](PCSO/README.md)
12 12 * [KTH](KTH/README.md)
  13 +* [FDDB](FDDB/README.md)
13 14  
14 15 For both practical and legal reasons we only include images for some of the datasets in this repository.
15 16 Researchers should contact the respective owners of the other datasets in order to obtain a copy.
... ...
openbr/plugins/gui.cpp
... ... @@ -18,6 +18,109 @@ using namespace cv;
18 18  
19 19 namespace br
20 20 {
  21 +// Generally speaking, Qt wants GUI objects to be on the main thread, and
  22 +// for the main thread to be in an event loop. We don't restrict transform
  23 +// creation to just the main thread, but in br we do compromise and put
  24 +// the main thread in an event loop (and so should any applications wanting to
  25 +// use GUI transforms). This does mean we need a way to make our QWidget subclasses
  26 +// on the main thread. We can't create them from an arbitrary thread, then move them
  27 +// (you know, since that would be crazy), so we need some tricks to get the main
  28 +// thread to make these objects.
  29 +
  30 +// Part 1. A generic interface for creating objects, the type of object
  31 +// created is not exposed in the interface.
  32 +class NominalCreation
  33 +{
  34 +public:
  35 + virtual ~NominalCreation() {}
  36 + virtual void creation()=0;
  37 +};
  38 +
  39 +// Part 2. A template class that creates an object of the specified type
  40 +// through the interface defined in part 1. The point of this is that the
  41 +// type of object created can be hidden by using a NominalCreation *.
  42 +template<typename T>
  43 +class ActualCreation : public NominalCreation
  44 +{
  45 +public:
  46 + T * basis;
  47 +
  48 + void creation()
  49 + {
  50 + basis = new T();
  51 + }
  52 +};
  53 +
  54 +// Part 3. A class that inherits from QObject, but not QWidget. This means
  55 +// we are free to move it to the main thread.
  56 +// If this object is on the main thread, and we signal one of its slots, then
  57 +// the slot will be executed by the main thread, which is what we need.
  58 +// Unfortunately, since it uses Q_OBJECT we cannot make it a template class, but
  59 +// we still want to be able to make objects of arbitrary type on the main thread,
  60 +// so that we don't need a different adaptor for every type of QWidget subclass we use.
  61 +class MainThreadCreator : public QObject
  62 +{
  63 + Q_OBJECT
  64 +public:
  65 +
  66 + MainThreadCreator()
  67 + {
  68 + this->moveToThread(QApplication::instance()->thread());
  69 + // We actually bind a signal on this object to one of its own slots.
  70 + // the signal will be emitted by a call to getItem from an abitrary
  71 + // thread.
  72 + connect(this, SIGNAL(needCreation()), this, SLOT(createThing()), Qt::BlockingQueuedConnection);
  73 + }
  74 +
  75 + // While this cannot be a template class, it can still have a template
  76 + // method. Which is useful, but the slot which will actually be executed
  77 + // by the main thread cannot be a template. So, we use the template method
  78 + // here (called from an arbitrary thread, to create an object of arbitrary type)
  79 + // to instantiate an ActualCreation object with matching type, then we hide
  80 + // the template with the NominalCreation interface, and call worker->creation
  81 + // in the slot.
  82 + template<typename T>
  83 + T * getItem()
  84 + {
  85 + // If this is called by the main thread, we can just create the object
  86 + // it's important to check, otherwise we will have problems trying to
  87 + // wait for a blocking connection that is supposed to be processed by
  88 + // the thread that is waiting.
  89 + if (QThread::currentThread() == QApplication::instance()->thread())
  90 + return new T();
  91 +
  92 + // Create the object creation interface
  93 + ActualCreation<T> * actualWorker;
  94 + actualWorker = new ActualCreation<T> ();
  95 + // hide it
  96 + worker = actualWorker;
  97 +
  98 + // emit the signal, we set up a blocking queued connection, so
  99 + // this is a blocking wait for the slot to finish being run.
  100 + emit needCreation();
  101 +
  102 + // collect the results, and return.
  103 + T * output = actualWorker->basis;
  104 + delete actualWorker;
  105 + return output;
  106 + }
  107 +
  108 + NominalCreation * worker;
  109 +
  110 +signals:
  111 + void needCreation();
  112 +
  113 +public slots:
  114 + // The actual slot, to be run by the main thread. The type
  115 + // of object being created is not, and indeed cannot, be exposed here
  116 + // since this cannot be a template method, and the class cannot be a
  117 + // template class.
  118 + void createThing()
  119 + {
  120 + worker->creation();
  121 + }
  122 +};
  123 +
21 124 QImage toQImage(const Mat &mat)
22 125 {
23 126 // Convert to 8U depth
... ... @@ -229,18 +332,14 @@ public:
229 332 public slots:
230 333 void showImage(const QPixmap & input)
231 334 {
232   - pixmap = input;
233   - foreach(const QString& label, keys) {
234   - QLineEdit *edit = new QLineEdit;
235   - fields.append(edit);
236   - QFormLayout *form = new QFormLayout;
237   - form->addRow(label, edit);
238   - inputLayout->addLayout(form);
239   - }
  335 + hide();
240 336  
241   - show();
  337 + createForm();
  338 + pixmap = input;
242 339 label.setPixmap(pixmap);
243 340 label.setFixedSize(input.size());
  341 +
  342 + show();
244 343 }
245 344  
246 345 QStringList waitForButtonPress()
... ... @@ -249,7 +348,10 @@ public slots:
249 348 wait.wait(&lock);
250 349  
251 350 QStringList values;
252   - for(int i = 0; i<fields.size(); i++) values.append(fields.at(i)->text());
  351 + for(int i = 0; i<fields.size(); i++) {
  352 + values.append(fields.at(i)->text());
  353 + fields[i]->clear();
  354 + }
253 355 return values;
254 356 }
255 357  
... ... @@ -267,6 +369,19 @@ public slots:
267 369  
268 370 private:
269 371  
  372 + void createForm()
  373 + {
  374 + if (fields.size() != keys.size()) {
  375 + foreach(const QString& label, keys) {
  376 + QLineEdit *edit = new QLineEdit;
  377 + fields.append(edit);
  378 + QFormLayout *form = new QFormLayout;
  379 + form->addRow(label, edit);
  380 + inputLayout->addLayout(form);
  381 + }
  382 + }
  383 + }
  384 +
270 385 QWidget *centralWidget;
271 386 QStringList keys;
272 387 QList<QLineEdit*> fields;
... ... @@ -280,75 +395,6 @@ private:
280 395  
281 396 };
282 397  
283   -// I want a template class that doesn't look like a template class
284   -class NominalCreation
285   -{
286   -public:
287   - virtual ~NominalCreation() {}
288   - virtual void creation()=0;
289   -};
290   -
291   -// Putting the template on a subclass means we can maintain a pointer that
292   -// doesn't include T in its type.
293   -template<typename T>
294   -class ActualCreation : public NominalCreation
295   -{
296   -public:
297   - T * basis;
298   -
299   - void creation()
300   - {
301   - basis = new T();
302   - }
303   -};
304   -
305   -// We want to create a QLabel subclass on the main thread, but are running in another thread.
306   -// We cannot move QWidget subclasses to a different thread (obviously that would be crazy), but
307   -// we can create one of these, and move it to the main thread, and then use it to create the object
308   -// we want.
309   -// Additional fact: QObject subclasses cannot be template classes.
310   -class MainThreadCreator : public QObject
311   -{
312   - Q_OBJECT
313   -public:
314   -
315   - MainThreadCreator()
316   - {
317   - this->moveToThread(QApplication::instance()->thread());
318   -
319   - connect(this, SIGNAL(needCreation()), this, SLOT(createThing()), Qt::BlockingQueuedConnection);
320   - }
321   -
322   - // While this cannot be a template class, it can still have a template method.
323   - template<typename T>
324   - T * getItem()
325   - {
326   - if (QThread::currentThread() == QApplication::instance()->thread())
327   - return new T();
328   -
329   - ActualCreation<T> * actualWorker;
330   - actualWorker = new ActualCreation<T> ();
331   - worker = actualWorker;
332   -
333   - emit needCreation();
334   -
335   - T * output = actualWorker->basis;
336   - delete actualWorker;
337   - return output;
338   - }
339   -
340   - NominalCreation * worker;
341   -
342   -signals:
343   - void needCreation();
344   -
345   -public slots:
346   - void createThing()
347   - {
348   - worker->creation();
349   - }
350   -};
351   -
352 398 /*!
353 399 * \ingroup transforms
354 400 * \brief Displays templates in a GUI pop-up window using QT.
... ... @@ -379,12 +425,6 @@ public:
379 425  
380 426 void train(const TemplateList &data) { (void) data; }
381 427  
382   - void project(const TemplateList &src, TemplateList &dst) const
383   - {
384   - Transform * non_const = (ShowTransform *) this;
385   - non_const->projectUpdate(src,dst);
386   - }
387   -
388 428 void projectUpdate(const TemplateList &src, TemplateList &dst)
389 429 {
390 430 dst = src;
... ... @@ -659,6 +699,11 @@ public:
659 699 BR_REGISTER(Transform, SurveyTransform)
660 700  
661 701  
  702 +/*!
  703 + * \ingroup transforms
  704 + * \brief Limits the frequency of projects going through this transform to the input targetFPS
  705 + * \author Charles Otto \cite caotto
  706 + */
662 707 class FPSLimit : public TimeVaryingTransform
663 708 {
664 709 Q_OBJECT
... ... @@ -709,6 +754,12 @@ protected:
709 754 };
710 755 BR_REGISTER(Transform, FPSLimit)
711 756  
  757 +/*!
  758 + * \ingroup transforms
  759 + * \brief Calculates the average FPS of projects going through this transform, stores the result in AvgFPS
  760 + * Reports an average FPS from the initialization of this transform onwards.
  761 + * \author Charles Otto \cite caotto
  762 + */
712 763 class FPSCalc : public TimeVaryingTransform
713 764 {
714 765 Q_OBJECT
... ...