Commit ee6f9bbc83867fb79710659035f4bff6dadc2f10
1 parent
8a207670
Preliminary work on not loading complete galleries during enrollment
The basic idea is to read galleries incrementally, but there are some complications especially related to progress counting--if we don't read a gallery we don't know how many templates are stored in it since gallery formats aren't nice enough to provide headers with that information. One solution to the progress counting problem is to measure progress based on the position of a file pointer in the gallery file (i.e. measure the current position in the gallery file, divide by the total size of the gallery file). This is supported by expanding the Gallery API to include a totalSize method indicating the total size of the gallery file (or total number of templates if that is known), and then as templates are read, their position is stored in metadata (using the "p" key). Several galleries are updated to respect readBlockSize, and also to store position data in read templates. Support for filtering out already enrolled templates in read-mode was maintained by making the filtering an online process (part of the enrollment pipeline) rather than a batch process done before enrollment-proper starts.
Showing
7 changed files
with
291 additions
and
90 deletions
openbr/core/core.cpp
| ... | ... | @@ -134,55 +134,51 @@ struct AlgorithmCore |
| 134 | 134 | if (input.name.isEmpty()) return FileList(); |
| 135 | 135 | else gallery = getMemoryGallery(input); |
| 136 | 136 | } |
| 137 | - TemplateList data(TemplateList::fromGallery(input)); | |
| 138 | 137 | |
| 139 | 138 | bool multiProcess = Globals->file.getBool("multiProcess", false); |
| 139 | + bool fileExclusion = false; | |
| 140 | 140 | |
| 141 | - if (gallery.contains("append")) | |
| 142 | - { | |
| 143 | - // Remove any templates which are already in the gallery | |
| 144 | - QScopedPointer<Gallery> g(Gallery::make(gallery)); | |
| 145 | - files = g->files(); | |
| 146 | - QSet<QString> nameSet = QSet<QString>::fromList(files.names()); | |
| 147 | - for (int i = data.size() - 1; i>=0; i--) { | |
| 148 | - if (nameSet.contains(data[i].file.name)) | |
| 149 | - { | |
| 150 | - data.removeAt(i); | |
| 151 | - } | |
| 152 | - } | |
| 141 | + // In append mode, we will exclude any templates with filenames already present in the output gallery | |
| 142 | + if (gallery.contains("append") && gallery.exists() ) { | |
| 143 | + FileList::fromGallery(gallery,true); | |
| 144 | + fileExclusion = true; | |
| 153 | 145 | } |
| 154 | 146 | |
| 155 | - if (data.empty()) | |
| 156 | - return files; | |
| 147 | + Gallery * temp = Gallery::make(input); | |
| 148 | + qint64 total = temp->totalSize(); | |
| 157 | 149 | |
| 158 | - // Store steps for ProgressCounter | |
| 159 | 150 | Globals->currentStep = 0; |
| 160 | - Globals->totalSteps = data.length(); | |
| 151 | + Globals->totalSteps = total; | |
| 161 | 152 | |
| 162 | 153 | QScopedPointer<Transform> basePipe; |
| 163 | 154 | |
| 164 | - if (!multiProcess) | |
| 165 | - { | |
| 166 | - QString pipeDesc = "GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(data.length())+")+Discard"; | |
| 155 | + QString pipeDesc = "GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(total)+")+Discard"; | |
| 156 | + | |
| 157 | + if (!multiProcess) { | |
| 167 | 158 | basePipe.reset(Transform::make(pipeDesc,NULL)); |
| 168 | 159 | CompositeTransform * downcast = dynamic_cast<CompositeTransform *>(basePipe.data()); |
| 169 | - if (downcast == NULL) | |
| 170 | - qFatal("downcast failed?"); | |
| 171 | 160 | |
| 172 | - // replace that placeholder with the current algorithm | |
| 161 | + if (downcast == NULL) qFatal("downcast failed?"); | |
| 162 | + | |
| 173 | 163 | downcast->transforms.prepend(this->transform.data()); |
| 164 | + if (fileExclusion) { | |
| 165 | + Transform * temp = Transform::make("FileExclusion(" + gallery.flat() + ")", downcast); | |
| 166 | + downcast->transforms.prepend(temp); | |
| 167 | + } | |
| 174 | 168 | |
| 175 | 169 | // call init on the pipe to collapse the algorithm (if its top level is a pipe) |
| 176 | 170 | downcast->init(); |
| 177 | 171 | } |
| 178 | - else | |
| 179 | - { | |
| 180 | - QString pipeDesc = "ProcessWrapper("+transformString+")"+"+GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(data.length())+")+Discard"; | |
| 172 | + else { | |
| 173 | + pipeDesc = "ProcessWrapper("+transformString+")"+pipeDesc; | |
| 174 | + if (fileExclusion) | |
| 175 | + pipeDesc = "FileExclusion(" + gallery.flat() +")" + pipeDesc; | |
| 176 | + | |
| 181 | 177 | basePipe.reset(Transform::make(pipeDesc,NULL)); |
| 182 | 178 | } |
| 183 | 179 | |
| 184 | 180 | // Next, we make a Stream (with placeholder transform) |
| 185 | - QString streamDesc = "Stream(readMode=DistributeFrames)"; | |
| 181 | + QString streamDesc = "Stream(readMode=StreamGallery)"; | |
| 186 | 182 | QScopedPointer<Transform> baseStream(Transform::make(streamDesc, NULL)); |
| 187 | 183 | WrapperTransform * wrapper = dynamic_cast<WrapperTransform *> (baseStream.data()); |
| 188 | 184 | |
| ... | ... | @@ -194,9 +190,11 @@ struct AlgorithmCore |
| 194 | 190 | |
| 195 | 191 | Globals->startTime.start(); |
| 196 | 192 | |
| 197 | - wrapper->projectUpdate(data,data); | |
| 193 | + TemplateList data, output; | |
| 194 | + data.append(input); | |
| 195 | + wrapper->projectUpdate(data, output); | |
| 198 | 196 | |
| 199 | - files.append(data.files()); | |
| 197 | + files.append(output.files()); | |
| 200 | 198 | |
| 201 | 199 | return files; |
| 202 | 200 | } |
| ... | ... | @@ -337,13 +335,9 @@ struct AlgorithmCore |
| 337 | 335 | // comparison against the smaller gallery (which will be enrolled, and stored in memory). |
| 338 | 336 | bool needEnrollRows = false; |
| 339 | 337 | |
| 340 | - | |
| 341 | - | |
| 342 | - | |
| 343 | 338 | if (output.exists() && output.get<bool>("cache", false)) return; |
| 344 | 339 | if (queryGallery == ".") queryGallery = targetGallery; |
| 345 | 340 | |
| 346 | - | |
| 347 | 341 | // To decide which gallery is larger, we need to read both, but at this point we just want the |
| 348 | 342 | // metadata, and don't need the enrolled matrices. |
| 349 | 343 | FileList targetMetadata; |
| ... | ... | @@ -359,15 +353,21 @@ struct AlgorithmCore |
| 359 | 353 | |
| 360 | 354 | File rowGallery = queryGallery; |
| 361 | 355 | File colGallery = targetGallery; |
| 362 | - int rowSize = queryMetadata.size(); | |
| 356 | + qint64 rowSize; | |
| 363 | 357 | |
| 358 | + Gallery * temp; | |
| 364 | 359 | if (transposeMode) |
| 365 | 360 | { |
| 366 | 361 | rowGallery = targetGallery; |
| 367 | 362 | colGallery = queryGallery; |
| 368 | - rowSize = targetMetadata.size(); | |
| 363 | + temp = Gallery::make(targetGallery); | |
| 369 | 364 | } |
| 370 | - | |
| 365 | + else | |
| 366 | + { | |
| 367 | + temp = Gallery::make(queryGallery); | |
| 368 | + } | |
| 369 | + rowSize = temp->totalSize(); | |
| 370 | + delete temp; | |
| 371 | 371 | |
| 372 | 372 | // Is the column gallery already enrolled? We keep the enrolled column gallery in memory, and in multi-process |
| 373 | 373 | // mode, every worker process retains a copy of this gallery in memory. When not in multi-process mode, we can |
| ... | ... | @@ -423,8 +423,6 @@ struct AlgorithmCore |
| 423 | 423 | // progress counting step. |
| 424 | 424 | // After the base algorithm is built, the whole thing will be run in a stream, so that I/O can be handled sequentially. |
| 425 | 425 | |
| 426 | - | |
| 427 | - | |
| 428 | 426 | // The actual comparison step is done by a GalleryCompare transform, which has a Distance, and a gallery as data. |
| 429 | 427 | // Incoming templates are compared against the templates in the gallery, and the output is the resulting score |
| 430 | 428 | // vector. | ... | ... |
openbr/openbr_plugin.cpp
| ... | ... | @@ -865,14 +865,14 @@ void br::Context::printStatus() |
| 865 | 865 | const float p = progress(); |
| 866 | 866 | if (p < 1) { |
| 867 | 867 | int s = timeRemaining(); |
| 868 | - fprintf(stderr, "%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g/%g \r", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(s).toStdString().c_str(), Globals->currentStep, Globals->totalSteps); | |
| 868 | + fprintf(stderr,"%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g \r", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(s).toStdString().c_str(), Globals->currentStep); | |
| 869 | 869 | } |
| 870 | 870 | } |
| 871 | 871 | |
| 872 | 872 | float br::Context::progress() const |
| 873 | 873 | { |
| 874 | 874 | if (totalSteps == 0) return -1; |
| 875 | - return currentStep / totalSteps; | |
| 875 | + return currentProgress / totalSteps; | |
| 876 | 876 | } |
| 877 | 877 | |
| 878 | 878 | void br::Context::setProperty(const QString &key, const QString &value) | ... | ... |
openbr/openbr_plugin.h
| ... | ... | @@ -687,6 +687,10 @@ public: |
| 687 | 687 | Q_PROPERTY(double currentStep READ get_currentStep WRITE set_currentStep RESET reset_currentStep) |
| 688 | 688 | BR_PROPERTY(double, currentStep, 0) |
| 689 | 689 | |
| 690 | + Q_PROPERTY(double currentProgress READ get_currentProgress WRITE set_currentProgress RESET reset_currentProgress) | |
| 691 | + BR_PROPERTY(double, currentProgress, 0) | |
| 692 | + | |
| 693 | + | |
| 690 | 694 | /*! |
| 691 | 695 | * \brief Used internally to compute progress() and timeRemaining(). |
| 692 | 696 | */ |
| ... | ... | @@ -1095,6 +1099,9 @@ public: |
| 1095 | 1099 | static Gallery *make(const File &file); /*!< \brief Make a gallery to/from a file on disk. */ |
| 1096 | 1100 | void init(); |
| 1097 | 1101 | |
| 1102 | + virtual qint64 totalSize() { return std::numeric_limits<qint64>::max(); } | |
| 1103 | + virtual qint64 position() { return 0; } | |
| 1104 | + | |
| 1098 | 1105 | private: |
| 1099 | 1106 | QSharedPointer<Gallery> next; |
| 1100 | 1107 | }; | ... | ... |
openbr/plugins/gallery.cpp
| ... | ... | @@ -23,6 +23,7 @@ |
| 23 | 23 | #include <QSqlError> |
| 24 | 24 | #include <QSqlQuery> |
| 25 | 25 | #include <QSqlRecord> |
| 26 | +#include <QXmlStreamReader> | |
| 26 | 27 | #endif // BR_EMBEDDED |
| 27 | 28 | #include <opencv2/highgui/highgui.hpp> |
| 28 | 29 | #include "openbr_internal.h" |
| ... | ... | @@ -127,6 +128,7 @@ class galGallery : public Gallery |
| 127 | 128 | Template m; |
| 128 | 129 | stream >> m; |
| 129 | 130 | templates.append(m); |
| 131 | + templates.last().file.set("p", totalSize()); | |
| 130 | 132 | } |
| 131 | 133 | |
| 132 | 134 | *done = stream.atEnd(); |
| ... | ... | @@ -140,6 +142,17 @@ class galGallery : public Gallery |
| 140 | 142 | |
| 141 | 143 | stream << t; |
| 142 | 144 | } |
| 145 | + | |
| 146 | + qint64 totalSize() | |
| 147 | + { | |
| 148 | + return gallery.size(); | |
| 149 | + } | |
| 150 | + | |
| 151 | + qint64 position() | |
| 152 | + { | |
| 153 | + return gallery.pos(); | |
| 154 | + } | |
| 155 | + | |
| 143 | 156 | }; |
| 144 | 157 | |
| 145 | 158 | BR_REGISTER(Gallery, galGallery) |
| ... | ... | @@ -328,6 +341,7 @@ class memGallery : public Gallery |
| 328 | 341 | { |
| 329 | 342 | Q_OBJECT |
| 330 | 343 | int block; |
| 344 | + qint64 gallerySize; | |
| 331 | 345 | |
| 332 | 346 | void init() |
| 333 | 347 | { |
| ... | ... | @@ -338,6 +352,7 @@ class memGallery : public Gallery |
| 338 | 352 | MemoryGalleries::galleries[file] = gallery->read(); |
| 339 | 353 | align(MemoryGalleries::galleries[file]); |
| 340 | 354 | MemoryGalleries::aligned[file] = true; |
| 355 | + gallerySize = MemoryGalleries::galleries[file].size(); | |
| 341 | 356 | } |
| 342 | 357 | } |
| 343 | 358 | |
| ... | ... | @@ -349,6 +364,10 @@ class memGallery : public Gallery |
| 349 | 364 | } |
| 350 | 365 | |
| 351 | 366 | TemplateList templates = MemoryGalleries::galleries[file].mid(block*readBlockSize, readBlockSize); |
| 367 | + for (qint64 i = 0; i < templates.size();i++) { | |
| 368 | + templates[i].file.set("p", i + block * readBlockSize); | |
| 369 | + } | |
| 370 | + | |
| 352 | 371 | *done = (templates.size() < readBlockSize); |
| 353 | 372 | block = *done ? 0 : block+1; |
| 354 | 373 | return templates; |
| ... | ... | @@ -389,6 +408,16 @@ class memGallery : public Gallery |
| 389 | 408 | templates.alignedData = alignedData; |
| 390 | 409 | } |
| 391 | 410 | |
| 411 | + qint64 totalSize() | |
| 412 | + { | |
| 413 | + return gallerySize; | |
| 414 | + } | |
| 415 | + | |
| 416 | + qint64 position() | |
| 417 | + { | |
| 418 | + return block * readBlockSize; | |
| 419 | + } | |
| 420 | + | |
| 392 | 421 | }; |
| 393 | 422 | |
| 394 | 423 | BR_REGISTER(Gallery, memGallery) |
| ... | ... | @@ -449,16 +478,19 @@ FileList FileList::fromGallery(const File & file, bool cache) |
| 449 | 478 | * |
| 450 | 479 | * \see txtGallery |
| 451 | 480 | */ |
| 452 | -class csvGallery : public Gallery | |
| 481 | +class csvGallery : public FileGallery | |
| 453 | 482 | { |
| 454 | 483 | Q_OBJECT |
| 455 | 484 | Q_PROPERTY(int fileIndex READ get_fileIndex WRITE set_fileIndex RESET reset_fileIndex) |
| 456 | 485 | BR_PROPERTY(int, fileIndex, 0) |
| 457 | 486 | |
| 458 | 487 | FileList files; |
| 488 | + QStringList headers; | |
| 459 | 489 | |
| 460 | 490 | ~csvGallery() |
| 461 | 491 | { |
| 492 | + f.close(); | |
| 493 | + | |
| 462 | 494 | if (files.isEmpty()) return; |
| 463 | 495 | |
| 464 | 496 | QMap<QString,QVariant> samples; |
| ... | ... | @@ -496,25 +528,37 @@ class csvGallery : public Gallery |
| 496 | 528 | |
| 497 | 529 | TemplateList readBlock(bool *done) |
| 498 | 530 | { |
| 499 | - *done = true; | |
| 531 | + *done = false; | |
| 500 | 532 | TemplateList templates; |
| 501 | - if (!file.exists()) return templates; | |
| 502 | - | |
| 503 | - QStringList lines = QtUtils::readLines(file); | |
| 533 | + if (!file.exists()) { | |
| 534 | + *done = true; | |
| 535 | + return templates; | |
| 536 | + } | |
| 504 | 537 | QRegExp regexp("\\s*,\\s*"); |
| 505 | - QStringList headers; | |
| 506 | - if (!lines.isEmpty()) headers = lines.takeFirst().split(regexp); | |
| 507 | 538 | |
| 508 | - foreach (const QString &line, lines) { | |
| 539 | + if (f.pos() == 0) | |
| 540 | + { | |
| 541 | + // read a line | |
| 542 | + QByteArray lineBytes = f.readLine(); | |
| 543 | + QString line = QString::fromLocal8Bit(lineBytes).trimmed(); | |
| 544 | + headers = line.split(regexp); | |
| 545 | + } | |
| 546 | + | |
| 547 | + for (qint64 i = 0; i < this->readBlockSize && !f.atEnd(); i++){ | |
| 548 | + QByteArray lineBytes = f.readLine(); | |
| 549 | + QString line = QString::fromLocal8Bit(lineBytes).trimmed(); | |
| 550 | + | |
| 509 | 551 | QStringList words = line.split(regexp); |
| 510 | 552 | if (words.size() != headers.size()) continue; |
| 511 | - File f; | |
| 512 | - for (int i=0; i<words.size(); i++) { | |
| 513 | - if (i == 0) f.name = words[i]; | |
| 514 | - else f.set(headers[i], words[i]); | |
| 553 | + File fi; | |
| 554 | + for (int j=0; j<words.size(); j++) { | |
| 555 | + if (j == 0) fi.name = words[j]; | |
| 556 | + else fi.set(headers[j], words[j]); | |
| 515 | 557 | } |
| 516 | - templates.append(f); | |
| 558 | + templates.append(fi); | |
| 559 | + templates.last().file.set("p", f.pos()); | |
| 517 | 560 | } |
| 561 | + *done = f.atEnd(); | |
| 518 | 562 | |
| 519 | 563 | return templates; |
| 520 | 564 | } |
| ... | ... | @@ -568,18 +612,12 @@ BR_REGISTER(Gallery, csvGallery) |
| 568 | 612 | \endverbatim |
| 569 | 613 | * \see csvGallery |
| 570 | 614 | */ |
| 571 | -class txtGallery : public Gallery | |
| 615 | +class txtGallery : public FileGallery | |
| 572 | 616 | { |
| 573 | 617 | Q_OBJECT |
| 574 | 618 | Q_PROPERTY(QString label READ get_label WRITE set_label RESET reset_label STORED false) |
| 575 | 619 | BR_PROPERTY(QString, label, "") |
| 576 | 620 | |
| 577 | - QFile f; | |
| 578 | - ~txtGallery() | |
| 579 | - { | |
| 580 | - f.close(); | |
| 581 | - } | |
| 582 | - | |
| 583 | 621 | TemplateList readBlock(bool *done) |
| 584 | 622 | { |
| 585 | 623 | *done = false; |
| ... | ... | @@ -597,6 +635,7 @@ class txtGallery : public Gallery |
| 597 | 635 | int splitIndex = line.lastIndexOf(' '); |
| 598 | 636 | if (splitIndex == -1) templates.append(File(line)); |
| 599 | 637 | else templates.append(File(line.mid(0, splitIndex), line.mid(splitIndex+1))); |
| 638 | + templates.last().file.set("p", this->position()); | |
| 600 | 639 | } |
| 601 | 640 | |
| 602 | 641 | if (f.atEnd()) { |
| ... | ... | @@ -608,14 +647,6 @@ class txtGallery : public Gallery |
| 608 | 647 | return templates; |
| 609 | 648 | } |
| 610 | 649 | |
| 611 | - void init() | |
| 612 | - { | |
| 613 | - f.setFileName(file); | |
| 614 | - QtUtils::touchDir(f); | |
| 615 | - if (!f.open(QFile::ReadWrite)) | |
| 616 | - qFatal("Failed to open %s for read/write.", qPrintable(file)); | |
| 617 | - } | |
| 618 | - | |
| 619 | 650 | void write(const Template &t) |
| 620 | 651 | { |
| 621 | 652 | QString line = t.file.name; |
| ... | ... | @@ -627,21 +658,16 @@ class txtGallery : public Gallery |
| 627 | 658 | }; |
| 628 | 659 | |
| 629 | 660 | BR_REGISTER(Gallery, txtGallery) |
| 661 | + | |
| 630 | 662 | /*! |
| 631 | 663 | * \ingroup galleries |
| 632 | 664 | * \brief Treats each line as a call to File::flat() |
| 633 | 665 | * \author Josh Klontz \cite jklontz |
| 634 | 666 | */ |
| 635 | -class flatGallery : public Gallery | |
| 667 | +class flatGallery : public FileGallery | |
| 636 | 668 | { |
| 637 | 669 | Q_OBJECT |
| 638 | 670 | |
| 639 | - QFile f; | |
| 640 | - ~flatGallery() | |
| 641 | - { | |
| 642 | - f.close(); | |
| 643 | - } | |
| 644 | - | |
| 645 | 671 | TemplateList readBlock(bool *done) |
| 646 | 672 | { |
| 647 | 673 | *done = false; |
| ... | ... | @@ -654,8 +680,10 @@ class flatGallery : public Gallery |
| 654 | 680 | { |
| 655 | 681 | QByteArray line = f.readLine(); |
| 656 | 682 | |
| 657 | - if (!line.isEmpty()) | |
| 683 | + if (!line.isEmpty()) { | |
| 658 | 684 | templates.append(File(QString::fromLocal8Bit(line).trimmed())); |
| 685 | + templates.last().file.set("p", this->position()); | |
| 686 | + } | |
| 659 | 687 | |
| 660 | 688 | if (f.atEnd()) { |
| 661 | 689 | *done=true; |
| ... | ... | @@ -666,15 +694,6 @@ class flatGallery : public Gallery |
| 666 | 694 | return templates; |
| 667 | 695 | } |
| 668 | 696 | |
| 669 | - void init() | |
| 670 | - { | |
| 671 | - f.setFileName(file); | |
| 672 | - QtUtils::touchDir(f); | |
| 673 | - if (!f.open(QFile::ReadWrite)) | |
| 674 | - qFatal("Failed to open %s for read/write.", qPrintable(file)); | |
| 675 | - | |
| 676 | - } | |
| 677 | - | |
| 678 | 697 | void write(const Template &t) |
| 679 | 698 | { |
| 680 | 699 | f.write((t.file.flat()+"\n").toLocal8Bit() ); |
| ... | ... | @@ -688,29 +707,140 @@ BR_REGISTER(Gallery, flatGallery) |
| 688 | 707 | * \brief A \ref sigset input. |
| 689 | 708 | * \author Josh Klontz \cite jklontz |
| 690 | 709 | */ |
| 691 | -class xmlGallery : public Gallery | |
| 710 | +class xmlGallery : public FileGallery | |
| 692 | 711 | { |
| 693 | 712 | Q_OBJECT |
| 694 | 713 | Q_PROPERTY(bool ignoreMetadata READ get_ignoreMetadata WRITE set_ignoreMetadata RESET reset_ignoreMetadata STORED false) |
| 695 | 714 | BR_PROPERTY(bool, ignoreMetadata, false) |
| 696 | 715 | FileList files; |
| 697 | 716 | |
| 717 | + QXmlStreamReader reader; | |
| 718 | + | |
| 719 | + QString currentSignatureName; | |
| 720 | + bool signatureActive; | |
| 721 | + | |
| 698 | 722 | ~xmlGallery() |
| 699 | 723 | { |
| 724 | + f.close(); | |
| 700 | 725 | if (!files.isEmpty()) |
| 701 | 726 | BEE::writeSigset(file, files, ignoreMetadata); |
| 702 | 727 | } |
| 703 | 728 | |
| 704 | 729 | TemplateList readBlock(bool *done) |
| 705 | 730 | { |
| 731 | + if (reader.atEnd()) | |
| 732 | + f.seek(0); | |
| 733 | + | |
| 734 | + TemplateList templates; | |
| 735 | + qint64 count = 0; | |
| 736 | + while (!reader.atEnd()) | |
| 737 | + { | |
| 738 | + // if an identity is active we try to read presentations | |
| 739 | + if (signatureActive) | |
| 740 | + { | |
| 741 | + while (signatureActive) | |
| 742 | + { | |
| 743 | + QXmlStreamReader::TokenType signatureToken = reader.readNext(); | |
| 744 | + | |
| 745 | + // did the signature end? | |
| 746 | + if (signatureToken == QXmlStreamReader::EndElement && reader.name() == "biometric-signature") { | |
| 747 | + signatureActive = false; | |
| 748 | + break; | |
| 749 | + } | |
| 750 | + // did we reach the end of the document? Theoretically this shoudln't happen without reaching the end of | |
| 751 | + if (signatureToken == QXmlStreamReader::EndDocument) | |
| 752 | + break; | |
| 753 | + | |
| 754 | + // a presentation! | |
| 755 | + if (signatureToken == QXmlStreamReader::StartElement && reader.name() == "presentation") { | |
| 756 | + templates.append(Template(File("",currentSignatureName))); | |
| 757 | + foreach (const QXmlStreamAttribute & attribute, reader.attributes()) { | |
| 758 | + // file-name is stored directly on file, not as a key/value pair | |
| 759 | + if (attribute.name() == "file-name") | |
| 760 | + templates.last().file.name = attribute.value().toString(); | |
| 761 | + // other values are directly set as metadata | |
| 762 | + else if (!ignoreMetadata) templates.last().file.set(attribute.name().toString(), attribute.value().toString()); | |
| 763 | + } | |
| 764 | + | |
| 765 | + // a presentation can have bounding boxes as child elements | |
| 766 | + bool signatureActive = true; | |
| 767 | + QList<QRectF> rects = templates.last().file.rects(); | |
| 768 | + while (signatureActive) | |
| 769 | + { | |
| 770 | + QXmlStreamReader::TokenType pToken = reader.readNext(); | |
| 771 | + if (pToken == QXmlStreamReader::EndElement && reader.name() == "presentation") | |
| 772 | + break; | |
| 773 | + | |
| 774 | + if (pToken == QXmlStreamReader::StartElement) | |
| 775 | + { | |
| 776 | + // get boudning box properties as attributes, just going to assume this all works | |
| 777 | + qreal x = reader.attributes().value("x").toDouble(); | |
| 778 | + qreal y = reader.attributes().value("y").toDouble(); | |
| 779 | + qreal width = reader.attributes().value("width").toDouble(); | |
| 780 | + qreal height = reader.attributes().value("height").toDouble(); | |
| 781 | + rects += QRectF(x, y, width, height); | |
| 782 | + } | |
| 783 | + } | |
| 784 | + templates.last().file.setRects(rects); | |
| 785 | + templates.last().file.set("p", f.pos()); | |
| 786 | + | |
| 787 | + count++; | |
| 788 | + if (count >= this->readBlockSize) { | |
| 789 | + *done = false; | |
| 790 | + return templates; | |
| 791 | + } | |
| 792 | + } | |
| 793 | + } | |
| 794 | + } | |
| 795 | + // otherwise, keep reading elements until the next identity is reacehed | |
| 796 | + else | |
| 797 | + { | |
| 798 | + QXmlStreamReader::TokenType token = reader.readNext(); | |
| 799 | + | |
| 800 | + // end of file? | |
| 801 | + if (token == QXmlStreamReader::EndDocument) | |
| 802 | + break; | |
| 803 | + | |
| 804 | + // we are only interested in new elements | |
| 805 | + if (token != QXmlStreamReader::StartElement) | |
| 806 | + continue; | |
| 807 | + | |
| 808 | + QStringRef elName = reader.name(); | |
| 809 | + | |
| 810 | + // biometric-signature-set is the root element | |
| 811 | + if (elName == "biometric-signature-set") | |
| 812 | + continue; | |
| 813 | + | |
| 814 | + // biometric-signature -- an identity | |
| 815 | + if (elName == "biometric-signature") | |
| 816 | + { | |
| 817 | + // read the name associated with the current signature | |
| 818 | + if (!reader.attributes().hasAttribute("name")) | |
| 819 | + { | |
| 820 | + qDebug() << "Biometric signature missing name"; | |
| 821 | + continue; | |
| 822 | + } | |
| 823 | + currentSignatureName = reader.attributes().value("name").toString(); | |
| 824 | + signatureActive = true; | |
| 825 | + } | |
| 826 | + } | |
| 827 | + | |
| 828 | + } | |
| 706 | 829 | *done = true; |
| 707 | - return TemplateList(BEE::readSigset(file, ignoreMetadata)); | |
| 830 | + | |
| 831 | + return templates; | |
| 708 | 832 | } |
| 709 | 833 | |
| 710 | 834 | void write(const Template &t) |
| 711 | 835 | { |
| 712 | 836 | files.append(t.file); |
| 713 | 837 | } |
| 838 | + | |
| 839 | + void init() | |
| 840 | + { | |
| 841 | + FileGallery::init(); | |
| 842 | + reader.setDevice(&f); | |
| 843 | + } | |
| 714 | 844 | }; |
| 715 | 845 | |
| 716 | 846 | BR_REGISTER(Gallery, xmlGallery) |
| ... | ... | @@ -1178,6 +1308,17 @@ BR_REGISTER(Gallery, vbbGallery) |
| 1178 | 1308 | |
| 1179 | 1309 | #endif |
| 1180 | 1310 | |
| 1311 | +void FileGallery::init() | |
| 1312 | +{ | |
| 1313 | + f.setFileName(file); | |
| 1314 | + QtUtils::touchDir(f); | |
| 1315 | + if (!f.open(QFile::ReadWrite)) | |
| 1316 | + qFatal("Failed to open %s for read/write.", qPrintable(file)); | |
| 1317 | + fileSize = f.size(); | |
| 1318 | + | |
| 1319 | + Gallery::init(); | |
| 1320 | +} | |
| 1321 | + | |
| 1181 | 1322 | } // namespace br |
| 1182 | 1323 | |
| 1183 | 1324 | #include "gallery.moc" | ... | ... |
openbr/plugins/misc.cpp
| ... | ... | @@ -517,14 +517,17 @@ class ProgressCounterTransform : public TimeVaryingTransform |
| 517 | 517 | |
| 518 | 518 | qint64 elapsed = timer.elapsed(); |
| 519 | 519 | |
| 520 | + if (!dst.empty()) { | |
| 521 | + Globals->currentProgress = dst.last().file.get<qint64>("p",0); | |
| 522 | + Globals->currentStep++; | |
| 523 | + } | |
| 524 | + | |
| 520 | 525 | // updated every second |
| 521 | 526 | if (elapsed > 1000) { |
| 522 | 527 | Globals->printStatus(); |
| 523 | 528 | timer.start(); |
| 524 | 529 | } |
| 525 | 530 | |
| 526 | - Globals->currentStep++; | |
| 527 | - | |
| 528 | 531 | return; |
| 529 | 532 | } |
| 530 | 533 | |
| ... | ... | @@ -537,12 +540,13 @@ class ProgressCounterTransform : public TimeVaryingTransform |
| 537 | 540 | { |
| 538 | 541 | (void) data; |
| 539 | 542 | float p = br_progress(); |
| 540 | - qDebug("%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g/%g \r", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(0).toStdString().c_str(), Globals->currentStep, Globals->totalSteps); | |
| 543 | + qDebug("%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g \r", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(0).toStdString().c_str(), Globals->currentStep); | |
| 541 | 544 | } |
| 542 | 545 | |
| 543 | 546 | void init() |
| 544 | 547 | { |
| 545 | 548 | timer.start(); |
| 549 | + Globals->currentStep = 0; | |
| 546 | 550 | } |
| 547 | 551 | |
| 548 | 552 | public: |
| ... | ... | @@ -689,6 +693,40 @@ public: |
| 689 | 693 | |
| 690 | 694 | BR_REGISTER(Transform, OutputTransform) |
| 691 | 695 | |
| 696 | +class FileExclusionTransform : public UntrainableMetaTransform | |
| 697 | +{ | |
| 698 | + Q_OBJECT | |
| 699 | + | |
| 700 | + Q_PROPERTY(QString exclusionGallery READ get_exclusionGallery WRITE set_exclusionGallery RESET reset_exclusionGallery STORED false) | |
| 701 | + BR_PROPERTY(QString, exclusionGallery, "") | |
| 702 | + | |
| 703 | + QSet<QString> excluded; | |
| 704 | + | |
| 705 | + void project(const Template & src, Template & dst) const | |
| 706 | + { | |
| 707 | + qFatal("FileExclusion can't do anything here"); | |
| 708 | + } | |
| 709 | + | |
| 710 | + void project(const TemplateList &src, TemplateList &dst) const | |
| 711 | + { | |
| 712 | + foreach(const Template & srcTemp, src) | |
| 713 | + { | |
| 714 | + if (!excluded.contains(srcTemp.file)) | |
| 715 | + dst.append(srcTemp); | |
| 716 | + } | |
| 717 | + } | |
| 718 | + | |
| 719 | + void init() | |
| 720 | + { | |
| 721 | + if (exclusionGallery.isEmpty()) | |
| 722 | + return; | |
| 723 | + FileList temp = FileList::fromGallery(exclusionGallery); | |
| 724 | + excluded = QSet<QString>::fromList(temp.names()); | |
| 725 | + } | |
| 726 | +}; | |
| 727 | + | |
| 728 | +BR_REGISTER(Transform, FileExclusionTransform) | |
| 729 | + | |
| 692 | 730 | } |
| 693 | 731 | |
| 694 | 732 | #include "misc.moc" | ... | ... |
openbr/plugins/openbr_internal.h
| ... | ... | @@ -345,6 +345,21 @@ protected: |
| 345 | 345 | UntrainableMetadataTransform() : MetadataTransform(false) {} |
| 346 | 346 | }; |
| 347 | 347 | |
| 348 | +class FileGallery : public Gallery | |
| 349 | +{ | |
| 350 | + Q_OBJECT | |
| 351 | +public: | |
| 352 | + QFile f; | |
| 353 | + qint64 fileSize; | |
| 354 | + | |
| 355 | + virtual ~FileGallery() { f.close(); } | |
| 356 | + | |
| 357 | + void init(); | |
| 358 | + | |
| 359 | + qint64 totalSize() { return fileSize; } | |
| 360 | + qint64 position() { return f.pos(); } | |
| 361 | +}; | |
| 362 | + | |
| 348 | 363 | } |
| 349 | 364 | |
| 350 | 365 | #endif // OPENBR_INTERNAL_H | ... | ... |
openbr/plugins/process.cpp