Commit 101231ab8f08b28a0ff41e1e65b37c6062fd8d30
1 parent
8073b56a
Better support for serializing algorithms in memory
Expand on Object::description to get a workable string that reflects the current state of the properties of Objects in memory. With this, we can conceive of serializing Transforms/Distances without having prior knowledge of the string used to construct them, and also to serialize them in cases where alterations have been made to their state in memory. Also introduce an option to force complete serialization of a transform tree (i.e. bypass LoadStore blocks), this allows us to do things like serialize an algorithm in memory, and transmit it to another process without requiring that the other process read part of the algorithm from disk. Refactor ProcessWrapper to directly transmit its current Transform to child processes, rather than requiring the child processes to read its state from disk. This allows for far more uniform treatment of multiProcess and non-multiProcess jobs in AlgorithmCore, leading to substantial simplification of AlgorithmCore::compare.
Showing
24 changed files
with
387 additions
and
246 deletions
openbr/core/core.cpp
| @@ -26,21 +26,20 @@ namespace br { | @@ -26,21 +26,20 @@ namespace br { | ||
| 26 | struct AlgorithmCore | 26 | struct AlgorithmCore |
| 27 | { | 27 | { |
| 28 | QSharedPointer<Transform> transform; | 28 | QSharedPointer<Transform> transform; |
| 29 | + QSharedPointer<Transform> comparison; | ||
| 29 | QSharedPointer<Distance> distance; | 30 | QSharedPointer<Distance> distance; |
| 30 | - QString galleryCompareString; | ||
| 31 | - | ||
| 32 | - QString transformString; | ||
| 33 | - QString distanceString; | 31 | + QSharedPointer<Transform> progressCounter; |
| 34 | 32 | ||
| 35 | AlgorithmCore(const QString &name) | 33 | AlgorithmCore(const QString &name) |
| 36 | { | 34 | { |
| 37 | this->name = name; | 35 | this->name = name; |
| 38 | init(name); | 36 | init(name); |
| 37 | + progressCounter = QSharedPointer<Transform>(Transform::make("ProgressCounter", NULL)); | ||
| 39 | } | 38 | } |
| 40 | 39 | ||
| 41 | bool isClassifier() const | 40 | bool isClassifier() const |
| 42 | { | 41 | { |
| 43 | - return distance.isNull(); | 42 | + return comparison.isNull(); |
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | void train(const File &input, const QString &model) | 45 | void train(const File &input, const QString &model) |
| @@ -116,7 +115,9 @@ struct AlgorithmCore | @@ -116,7 +115,9 @@ struct AlgorithmCore | ||
| 116 | in >> name; init(Globals->abbreviations.contains(name) ? Globals->abbreviations[name] : name); | 115 | in >> name; init(Globals->abbreviations.contains(name) ? Globals->abbreviations[name] : name); |
| 117 | transform->load(in); | 116 | transform->load(in); |
| 118 | bool hasDistance; in >> hasDistance; | 117 | bool hasDistance; in >> hasDistance; |
| 119 | - if (hasDistance) distance->load(in); | 118 | + |
| 119 | + if (hasDistance) | ||
| 120 | + distance->load(in); | ||
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | File getMemoryGallery(const File &file) const | 123 | File getMemoryGallery(const File &file) const |
| @@ -148,54 +149,37 @@ struct AlgorithmCore | @@ -148,54 +149,37 @@ struct AlgorithmCore | ||
| 148 | Gallery *temp = Gallery::make(input); | 149 | Gallery *temp = Gallery::make(input); |
| 149 | qint64 total = temp->totalSize(); | 150 | qint64 total = temp->totalSize(); |
| 150 | 151 | ||
| 151 | - QScopedPointer<Transform> basePipe; | ||
| 152 | - | ||
| 153 | - QString pipeDesc = "GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(total)+")+Discard"; | ||
| 154 | - | ||
| 155 | - if (!multiProcess) { | ||
| 156 | - basePipe.reset(Transform::make(pipeDesc,NULL)); | ||
| 157 | - CompositeTransform *downcast = dynamic_cast<CompositeTransform *>(basePipe.data()); | ||
| 158 | - | ||
| 159 | - if (downcast == NULL) qFatal("downcast failed?"); | 152 | + Transform * enroll = this->transform.data(); |
| 153 | + if (multiProcess) | ||
| 154 | + enroll = wrapTransform(enroll, "ProcessWrapper"); | ||
| 160 | 155 | ||
| 161 | - downcast->transforms.prepend(this->transform.data()); | ||
| 162 | - if (fileExclusion) { | ||
| 163 | - Transform *temp = Transform::make("FileExclusion(" + gallery.flat() + ")", downcast); | ||
| 164 | - downcast->transforms.prepend(temp); | ||
| 165 | - } | ||
| 166 | - | ||
| 167 | - // call init on the pipe to collapse the algorithm (if its top level is a pipe) | ||
| 168 | - downcast->init(); | ||
| 169 | - } | ||
| 170 | - else { | ||
| 171 | - pipeDesc = "ProcessWrapper("+transformString+")+"+pipeDesc; | ||
| 172 | - if (fileExclusion) | ||
| 173 | - pipeDesc = "FileExclusion(" + gallery.flat() +")+" + pipeDesc; | 156 | + QList<Transform *> stages; |
| 157 | + stages.append(enroll); | ||
| 174 | 158 | ||
| 175 | - basePipe.reset(Transform::make(pipeDesc,NULL)); | ||
| 176 | - } | 159 | + QString outputDesc; |
| 160 | + if (fileExclusion) | ||
| 161 | + outputDesc = "FileExclusion(" + gallery.flat() + ")+"; | ||
| 162 | + outputDesc.append("GalleryOutput("+gallery.flat()+")"); | ||
| 163 | + QScopedPointer<Transform> outputTform(Transform::make(outputDesc, NULL)); | ||
| 164 | + stages.append(outputTform.data()); | ||
| 165 | + stages.append(progressCounter.data()); | ||
| 166 | + QScopedPointer<Transform> discard(Transform::make("Discard",NULL)); | ||
| 167 | + stages.append(discard.data()); | ||
| 177 | 168 | ||
| 178 | - // Next, we make a Stream (with placeholder transform) | ||
| 179 | - QString streamDesc = "Stream(readMode=StreamGallery)"; | ||
| 180 | - QScopedPointer<Transform> baseStream(Transform::make(streamDesc, NULL)); | ||
| 181 | - WrapperTransform *wrapper = dynamic_cast<WrapperTransform *> (baseStream.data()); | 169 | + QScopedPointer<Transform> pipeline(br::pipeTransforms(stages)); |
| 182 | 170 | ||
| 183 | - // replace that placeholder with the pipe we built | ||
| 184 | - wrapper->transform = basePipe.data(); | ||
| 185 | - | ||
| 186 | - // and get the final stream's stages by reinterpreting the pipe. Perfectly straightforward. | ||
| 187 | - wrapper->init(); | ||
| 188 | - | ||
| 189 | - Globals->startTime.start(); | ||
| 190 | - Globals->currentStep = 0; | ||
| 191 | - Globals->totalSteps = total; | 171 | + QScopedPointer<Transform> stream(br::wrapTransform(pipeline.data(), "Stream(readMode=StreamGallery)")); |
| 192 | 172 | ||
| 193 | TemplateList data, output; | 173 | TemplateList data, output; |
| 194 | data.append(input); | 174 | data.append(input); |
| 195 | - wrapper->projectUpdate(data, output); | 175 | + progressCounter->setPropertyRecursive("totalProgress", QString::number(total)); |
| 176 | + stream->projectUpdate(data, output); | ||
| 196 | 177 | ||
| 197 | files.append(output.files()); | 178 | files.append(output.files()); |
| 198 | 179 | ||
| 180 | + if (multiProcess) | ||
| 181 | + delete enroll; | ||
| 182 | + | ||
| 199 | return files; | 183 | return files; |
| 200 | } | 184 | } |
| 201 | 185 | ||
| @@ -389,12 +373,12 @@ struct AlgorithmCore | @@ -389,12 +373,12 @@ struct AlgorithmCore | ||
| 389 | // simple make sure the enrolled data is stored in a memGallery, but in multi-process mode we save the enrolled | 373 | // simple make sure the enrolled data is stored in a memGallery, but in multi-process mode we save the enrolled |
| 390 | // data to disk (as a .gal file) so that each worker process can read it without re-doing enrollment. | 374 | // data to disk (as a .gal file) so that each worker process can read it without re-doing enrollment. |
| 391 | File colEnrolledGallery = colGallery; | 375 | File colEnrolledGallery = colGallery; |
| 392 | - QString targetExtension = multiProcess ? "gal" : "mem"; | 376 | + QString targetExtension = "mem"; |
| 393 | 377 | ||
| 394 | // If the column gallery is not already of the appropriate type, we need to do something | 378 | // If the column gallery is not already of the appropriate type, we need to do something |
| 395 | if (colGallery.suffix() != targetExtension) { | 379 | if (colGallery.suffix() != targetExtension) { |
| 396 | // Build the name of a gallery containing the enrolled data, of the appropriate type. | 380 | // Build the name of a gallery containing the enrolled data, of the appropriate type. |
| 397 | - colEnrolledGallery = colGallery.baseName() + colGallery.hash() + (multiProcess ? ".gal" : ".mem"); | 381 | + colEnrolledGallery = colGallery.baseName() + colGallery.hash() + '.' + targetExtension; |
| 398 | 382 | ||
| 399 | // Check if we have to do real enrollment, and not just convert the gallery's type. | 383 | // Check if we have to do real enrollment, and not just convert the gallery's type. |
| 400 | if (!(QStringList() << "gal" << "template" << "mem").contains(colGallery.suffix())) | 384 | if (!(QStringList() << "gal" << "template" << "mem").contains(colGallery.suffix())) |
| @@ -435,37 +419,23 @@ struct AlgorithmCore | @@ -435,37 +419,23 @@ struct AlgorithmCore | ||
| 435 | // The actual comparison step is done by a GalleryCompare transform, which has a Distance, and a gallery as data. | 419 | // The actual comparison step is done by a GalleryCompare transform, which has a Distance, and a gallery as data. |
| 436 | // Incoming templates are compared against the templates in the gallery, and the output is the resulting score | 420 | // Incoming templates are compared against the templates in the gallery, and the output is the resulting score |
| 437 | // vector. | 421 | // vector. |
| 422 | + TemplateList tlist = TemplateList::fromGallery(colEnrolledGallery); | ||
| 423 | + comparison->train(tlist); | ||
| 424 | + comparison->setPropertyRecursive("galleryName",""); | ||
| 425 | + | ||
| 438 | QString compareRegionDesc; | 426 | QString compareRegionDesc; |
| 427 | + QList<Transform *> enrollCompare; | ||
| 428 | + enrollCompare.append(comparison.data()); | ||
| 429 | + // if we have to enroll the row gallery, add that transform to the list | ||
| 430 | + if (needEnrollRows) | ||
| 431 | + enrollCompare.prepend(this->transform.data()); | ||
| 439 | 432 | ||
| 440 | - if (this->galleryCompareString.isEmpty() ) | ||
| 441 | - compareRegionDesc = "Pipe([GalleryCompare("+Globals->algorithm+",galleryName="+colEnrolledGallery.flat()+")])"; | ||
| 442 | - else | ||
| 443 | - compareRegionDesc = "Pipe(["+galleryCompareString+"(galleryName="+colEnrolledGallery.flat()+")])"; | ||
| 444 | - | ||
| 445 | - QScopedPointer<Transform> compareRegion; | ||
| 446 | - // If we need to enroll the row set, we add the current algorithm's enrollment transform before the | ||
| 447 | - // GalleryCompare in a pipe. | ||
| 448 | - if (needEnrollRows) { | ||
| 449 | - if (!multiProcess) { | ||
| 450 | - compareRegionDesc = compareRegionDesc; | ||
| 451 | - compareRegion.reset(Transform::make(compareRegionDesc,NULL)); | ||
| 452 | - CompositeTransform *downcast = dynamic_cast<CompositeTransform *> (compareRegion.data()); | ||
| 453 | - if (downcast == NULL) | ||
| 454 | - qFatal("Pipe downcast failed in compare"); | ||
| 455 | - | ||
| 456 | - downcast->transforms.prepend(this->transform.data()); | ||
| 457 | - downcast->init(); | ||
| 458 | - } | ||
| 459 | - else { | ||
| 460 | - compareRegionDesc = "ProcessWrapper(" + this->transformString + "+" + compareRegionDesc + ")"; | ||
| 461 | - compareRegion.reset(Transform::make(compareRegionDesc, NULL)); | ||
| 462 | - } | ||
| 463 | - } | ||
| 464 | - else { | ||
| 465 | - if (multiProcess) | ||
| 466 | - compareRegionDesc = "ProcessWrapper(" + compareRegionDesc + ")"; | ||
| 467 | - compareRegion.reset(Transform::make(compareRegionDesc,NULL)); | ||
| 468 | - } | 433 | + Transform * compareRegionBase = pipeTransforms(enrollCompare); |
| 434 | + // If in multi-process mode, wrap the enroll+compare structure in a ProcessWrapper. | ||
| 435 | + if (multiProcess) | ||
| 436 | + compareRegionBase = wrapTransform(compareRegionBase, "ProcessWrapper"); | ||
| 437 | + | ||
| 438 | + QScopedPointer<Transform> compareRegion(compareRegionBase); | ||
| 469 | 439 | ||
| 470 | // At this point, compareRegion is a transform, which optionally does enrollment, then compares the row | 440 | // At this point, compareRegion is a transform, which optionally does enrollment, then compares the row |
| 471 | // set against the column set. If in multi-process mode, the enrollment and comparison are wrapped in a | 441 | // set against the column set. If in multi-process mode, the enrollment and comparison are wrapped in a |
| @@ -473,47 +443,36 @@ struct AlgorithmCore | @@ -473,47 +443,36 @@ struct AlgorithmCore | ||
| 473 | 443 | ||
| 474 | // We also need to add Output and progress counting to the algorithm we are building, so we will assign them to | 444 | // We also need to add Output and progress counting to the algorithm we are building, so we will assign them to |
| 475 | // two stages of a pipe. | 445 | // two stages of a pipe. |
| 476 | - QString joinDesc = "Pipe()"; | ||
| 477 | - QScopedPointer<Transform> join(Transform::make(joinDesc, NULL)); | 446 | + QList<Transform *> compareOutput; |
| 447 | + compareOutput.append(compareRegion.data()); | ||
| 478 | 448 | ||
| 479 | // The output transform takes the metadata memGalleries we set up previously as input, along with the | 449 | // The output transform takes the metadata memGalleries we set up previously as input, along with the |
| 480 | // output specification we were passed. Gallery metadata is necessary for some Outputs to function correctly. | 450 | // output specification we were passed. Gallery metadata is necessary for some Outputs to function correctly. |
| 481 | QString outputString = output.flat().isEmpty() ? "Empty" : output.flat(); | 451 | QString outputString = output.flat().isEmpty() ? "Empty" : output.flat(); |
| 482 | QString outputRegionDesc = "Output("+ outputString +"," + targetGallery.flat() +"," + queryGallery.flat() + ","+ QString::number(transposeMode ? 1 : 0) + ")"; | 452 | QString outputRegionDesc = "Output("+ outputString +"," + targetGallery.flat() +"," + queryGallery.flat() + ","+ QString::number(transposeMode ? 1 : 0) + ")"; |
| 483 | - // The ProgressCounter transform will simply provide a display about the number of rows completed. | ||
| 484 | - outputRegionDesc += "+ProgressCounter("+QString::number(rowSize)+")+Discard"; | ||
| 485 | - QScopedPointer<Transform> outputTform(Transform::make(outputRegionDesc, NULL)); | 453 | + QScopedPointer<Transform> outputTForm(Transform::make(outputRegionDesc,NULL)); |
| 454 | + compareOutput.append(outputTForm.data()); | ||
| 486 | 455 | ||
| 487 | - // Assign the comparison transform we previously built, and the output transform we just built to | ||
| 488 | - // two stages of a pipe. | ||
| 489 | - CompositeTransform *downcast = dynamic_cast<CompositeTransform *> (join.data()); | ||
| 490 | - downcast->transforms.append(compareRegion.data()); | ||
| 491 | - downcast->transforms.append(outputTform.data()); | 456 | + // The ProgressCounter transform will simply provide a display about the number of rows completed. |
| 457 | + compareOutput.append(progressCounter.data()); | ||
| 458 | + QScopedPointer<Transform> discard(Transform::make("Discard",NULL)); | ||
| 459 | + compareOutput.append(discard.data()); | ||
| 492 | 460 | ||
| 493 | // With this, we have set up a transform which (optionally) enrolls templates, compares them | 461 | // With this, we have set up a transform which (optionally) enrolls templates, compares them |
| 494 | // against a gallery, and outputs them. | 462 | // against a gallery, and outputs them. |
| 495 | - join->init(); | 463 | + Transform * pipeline = br::pipeTransforms(compareOutput); |
| 496 | 464 | ||
| 497 | // Now, we will give that base transform to a stream, which will incrementally read the row gallery | 465 | // Now, we will give that base transform to a stream, which will incrementally read the row gallery |
| 498 | // and pass the transforms it reads through the base algorithm. | 466 | // and pass the transforms it reads through the base algorithm. |
| 499 | - QString streamDesc = "Stream(readMode=StreamGallery)"; | ||
| 500 | - QScopedPointer<Transform> streamBase(Transform::make(streamDesc, NULL)); | ||
| 501 | - WrapperTransform *streamWrapper = dynamic_cast<WrapperTransform *> (streamBase.data()); | ||
| 502 | - streamWrapper->transform = join.data(); | ||
| 503 | - | ||
| 504 | - // The transform we will use is now complete. | ||
| 505 | - streamWrapper->init(); | 467 | + QScopedPointer<Transform> streamWrapper(br::wrapTransform(pipeline, "Stream(readMode=StreamGallery)")); |
| 506 | 468 | ||
| 507 | // We set up a template containing the rowGallery we want to compare. | 469 | // We set up a template containing the rowGallery we want to compare. |
| 508 | TemplateList rowGalleryTemplate; | 470 | TemplateList rowGalleryTemplate; |
| 509 | rowGalleryTemplate.append(Template(rowGallery)); | 471 | rowGalleryTemplate.append(Template(rowGallery)); |
| 510 | TemplateList outputGallery; | 472 | TemplateList outputGallery; |
| 511 | 473 | ||
| 512 | - // Set up progress counting variables | ||
| 513 | - Globals->currentStep = 0; | ||
| 514 | - Globals->currentProgress = 0; | ||
| 515 | - Globals->totalSteps = rowSize; | ||
| 516 | - Globals->startTime.start(); | 474 | + // initialize the progress counter |
| 475 | + progressCounter->setPropertyRecursive("totalProgress", QString::number(rowSize)); | ||
| 517 | 476 | ||
| 518 | // Do the actual comparisons | 477 | // Do the actual comparisons |
| 519 | streamWrapper->projectUpdate(rowGalleryTemplate, outputGallery); | 478 | streamWrapper->projectUpdate(rowGalleryTemplate, outputGallery); |
| @@ -557,27 +516,22 @@ private: | @@ -557,27 +516,22 @@ private: | ||
| 557 | return; | 516 | return; |
| 558 | } | 517 | } |
| 559 | 518 | ||
| 519 | + //! [Parsing the algorithm description] | ||
| 560 | const bool compareTransform = description.contains('!'); | 520 | const bool compareTransform = description.contains('!'); |
| 561 | QStringList words = QtUtils::parse(description, compareTransform ? '!' : ':'); | 521 | QStringList words = QtUtils::parse(description, compareTransform ? '!' : ':'); |
| 562 | 522 | ||
| 563 | if ((words.size() < 1) || (words.size() > 2)) qFatal("Invalid algorithm format."); | 523 | if ((words.size() < 1) || (words.size() > 2)) qFatal("Invalid algorithm format."); |
| 564 | 524 | ||
| 565 | - //! [Parsing the algorithm description] | ||
| 566 | - transformString = words[0]; | ||
| 567 | - | ||
| 568 | //! [Creating the template generation and comparison methods] | 525 | //! [Creating the template generation and comparison methods] |
| 569 | transform = QSharedPointer<Transform>(Transform::make(words[0], NULL)); | 526 | transform = QSharedPointer<Transform>(Transform::make(words[0], NULL)); |
| 570 | if (words.size() > 1) { | 527 | if (words.size() > 1) { |
| 571 | if (!compareTransform) { | 528 | if (!compareTransform) { |
| 572 | distance = QSharedPointer<Distance>(Distance::make(words[1], NULL)); | 529 | distance = QSharedPointer<Distance>(Distance::make(words[1], NULL)); |
| 573 | - distanceString = words[1]; | ||
| 574 | - galleryCompareString.clear(); | ||
| 575 | - } | ||
| 576 | - else { | ||
| 577 | - galleryCompareString = words[1]; | ||
| 578 | - distanceString.clear(); | 530 | + comparison = QSharedPointer<Transform>(Transform::make("GalleryCompare", NULL)); |
| 531 | + comparison->setPropertyRecursive("distance", QVariant::fromValue(distance.data())); | ||
| 579 | } | 532 | } |
| 580 | - | 533 | + else |
| 534 | + comparison = QSharedPointer<Transform>(Transform::make(words[1], NULL)); | ||
| 581 | } | 535 | } |
| 582 | //! [Creating the template generation and comparison methods] | 536 | //! [Creating the template generation and comparison methods] |
| 583 | } | 537 | } |
openbr/openbr_plugin.cpp
| @@ -577,16 +577,31 @@ QStringList Object::parameters() const | @@ -577,16 +577,31 @@ QStringList Object::parameters() const | ||
| 577 | return parameters; | 577 | return parameters; |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | -QStringList Object::arguments() const | 580 | +QStringList Object::arguments(bool expanded) |
| 581 | { | 581 | { |
| 582 | QStringList arguments; | 582 | QStringList arguments; |
| 583 | - for (int i=metaObject()->propertyOffset(); i<metaObject()->propertyCount(); i++) | ||
| 584 | - arguments.append(argument(i)); | 583 | + |
| 584 | + for (int i=firstAvailablePropertyIdx; i<metaObject()->propertyCount(); i++) { | ||
| 585 | + const char *name = metaObject()->property(i).name(); | ||
| 586 | + | ||
| 587 | + QVariant oldVal = property(name); | ||
| 588 | + QVariant defaultVal = oldVal; | ||
| 589 | + | ||
| 590 | + if (metaObject()->property(i).isResettable()) { | ||
| 591 | + metaObject()->property(i).reset(this); | ||
| 592 | + defaultVal = property(name); | ||
| 593 | + } | ||
| 594 | + | ||
| 595 | + if (defaultVal != oldVal) { | ||
| 596 | + metaObject()->property(i).write(this, oldVal); | ||
| 597 | + arguments.append(name + QString("=") + argument(i, expanded)); | ||
| 598 | + } | ||
| 599 | + } | ||
| 585 | 600 | ||
| 586 | return arguments; | 601 | return arguments; |
| 587 | } | 602 | } |
| 588 | 603 | ||
| 589 | -QString Object::argument(int index) const | 604 | +QString Object::argument(int index, bool expanded) const |
| 590 | { | 605 | { |
| 591 | if ((index < 0) || (index > metaObject()->propertyCount())) return ""; | 606 | if ((index < 0) || (index > metaObject()->propertyCount())) return ""; |
| 592 | const QMetaProperty property = metaObject()->property(index); | 607 | const QMetaProperty property = metaObject()->property(index); |
| @@ -604,19 +619,19 @@ QString Object::argument(int index) const | @@ -604,19 +619,19 @@ QString Object::argument(int index) const | ||
| 604 | strings.append(QString::number(value)); | 619 | strings.append(QString::number(value)); |
| 605 | } else if (type == "QList<br::Transform*>") { | 620 | } else if (type == "QList<br::Transform*>") { |
| 606 | foreach (Transform *transform, variant.value< QList<Transform*> >()) | 621 | foreach (Transform *transform, variant.value< QList<Transform*> >()) |
| 607 | - strings.append(transform->description()); | 622 | + strings.append(transform->description(expanded)); |
| 608 | } else if (type == "QList<br::Distance*>") { | 623 | } else if (type == "QList<br::Distance*>") { |
| 609 | foreach (Distance *distance, variant.value< QList<Distance*> >()) | 624 | foreach (Distance *distance, variant.value< QList<Distance*> >()) |
| 610 | - strings.append(distance->description()); | 625 | + strings.append(distance->description(expanded)); |
| 611 | } else { | 626 | } else { |
| 612 | qFatal("Unrecognized type: %s", qPrintable(type)); | 627 | qFatal("Unrecognized type: %s", qPrintable(type)); |
| 613 | } | 628 | } |
| 614 | 629 | ||
| 615 | return "[" + strings.join(",") + "]"; | 630 | return "[" + strings.join(",") + "]"; |
| 616 | } else if (type == "br::Transform*") { | 631 | } else if (type == "br::Transform*") { |
| 617 | - return variant.value<Transform*>()->description(); | 632 | + return variant.value<Transform*>()->description(expanded); |
| 618 | } else if (type == "br::Distance*") { | 633 | } else if (type == "br::Distance*") { |
| 619 | - return variant.value<Distance*>()->description(); | 634 | + return variant.value<Distance*>()->description(expanded); |
| 620 | } else if (type == "QStringList") { | 635 | } else if (type == "QStringList") { |
| 621 | return "[" + variant.toStringList().join(",") + "]"; | 636 | return "[" + variant.toStringList().join(",") + "]"; |
| 622 | } | 637 | } |
| @@ -624,13 +639,17 @@ QString Object::argument(int index) const | @@ -624,13 +639,17 @@ QString Object::argument(int index) const | ||
| 624 | return variant.toString(); | 639 | return variant.toString(); |
| 625 | } | 640 | } |
| 626 | 641 | ||
| 627 | -QString Object::description() const | 642 | +QString Object::description(bool expanded) |
| 628 | { | 643 | { |
| 629 | - QString argumentString = arguments().join(","); | 644 | + (void) expanded; |
| 645 | + QString argumentString = arguments(expanded).join(","); | ||
| 646 | + if (argumentString.endsWith(",")) | ||
| 647 | + argumentString.chop(1); | ||
| 648 | + | ||
| 630 | return objectName() + (argumentString.isEmpty() ? "" : ("(" + argumentString + ")")); | 649 | return objectName() + (argumentString.isEmpty() ? "" : ("(" + argumentString + ")")); |
| 631 | } | 650 | } |
| 632 | 651 | ||
| 633 | -void Object::store(QDataStream &stream) const | 652 | +void Object::store(QDataStream &stream, bool force) const |
| 634 | { | 653 | { |
| 635 | // Start from 1 to skip QObject::objectName | 654 | // Start from 1 to skip QObject::objectName |
| 636 | for (int i=1; i<metaObject()->propertyCount(); i++) { | 655 | for (int i=1; i<metaObject()->propertyCount(); i++) { |
| @@ -641,14 +660,14 @@ void Object::store(QDataStream &stream) const | @@ -641,14 +660,14 @@ void Object::store(QDataStream &stream) const | ||
| 641 | const QString type = property.typeName(); | 660 | const QString type = property.typeName(); |
| 642 | if (type == "QList<br::Transform*>") { | 661 | if (type == "QList<br::Transform*>") { |
| 643 | foreach (Transform *transform, property.read(this).value< QList<Transform*> >()) | 662 | foreach (Transform *transform, property.read(this).value< QList<Transform*> >()) |
| 644 | - transform->store(stream); | 663 | + transform->store(stream, force); |
| 645 | } else if (type == "QList<br::Distance*>") { | 664 | } else if (type == "QList<br::Distance*>") { |
| 646 | foreach (Distance *distance, property.read(this).value< QList<Distance*> >()) | 665 | foreach (Distance *distance, property.read(this).value< QList<Distance*> >()) |
| 647 | - distance->store(stream); | 666 | + distance->store(stream, force); |
| 648 | } else if (type == "br::Transform*") { | 667 | } else if (type == "br::Transform*") { |
| 649 | - property.read(this).value<Transform*>()->store(stream); | 668 | + property.read(this).value<Transform*>()->store(stream, force); |
| 650 | } else if (type == "br::Distance*") { | 669 | } else if (type == "br::Distance*") { |
| 651 | - property.read(this).value<Distance*>()->store(stream); | 670 | + property.read(this).value<Distance*>()->store(stream, force); |
| 652 | } else if (type == "bool") { | 671 | } else if (type == "bool") { |
| 653 | stream << property.read(this).toBool(); | 672 | stream << property.read(this).toBool(); |
| 654 | } else if (type == "int") { | 673 | } else if (type == "int") { |
| @@ -1284,7 +1303,8 @@ Transform *Transform::make(QString str, QObject *parent) | @@ -1284,7 +1303,8 @@ Transform *Transform::make(QString str, QObject *parent) | ||
| 1284 | 1303 | ||
| 1285 | Transform *Transform::clone() const | 1304 | Transform *Transform::clone() const |
| 1286 | { | 1305 | { |
| 1287 | - Transform *clone = Factory<Transform>::make(file.flat()); | 1306 | + Transform * temp = (Transform *) this; |
| 1307 | + Transform *clone = Factory<Transform>::make("."+temp->description(false)); | ||
| 1288 | return clone; | 1308 | return clone; |
| 1289 | } | 1309 | } |
| 1290 | 1310 | ||
| @@ -1453,3 +1473,17 @@ void br::applyAdditionalProperties(const File &temp, Transform *target) | @@ -1453,3 +1473,17 @@ void br::applyAdditionalProperties(const File &temp, Transform *target) | ||
| 1453 | target->setPropertyRecursive(i.key(), i.value() ); | 1473 | target->setPropertyRecursive(i.key(), i.value() ); |
| 1454 | } | 1474 | } |
| 1455 | } | 1475 | } |
| 1476 | + | ||
| 1477 | +Transform *br::wrapTransform(Transform *base, const QString &target) | ||
| 1478 | +{ | ||
| 1479 | + Transform *res = Transform::make(target, NULL); | ||
| 1480 | + res->setPropertyRecursive("transform", QVariant::fromValue(base)); | ||
| 1481 | + return res; | ||
| 1482 | +} | ||
| 1483 | + | ||
| 1484 | +Transform *br::pipeTransforms(QList<Transform *> &transforms) | ||
| 1485 | +{ | ||
| 1486 | + Transform *res = Transform::make("Pipe",NULL); | ||
| 1487 | + res->setPropertyRecursive("transforms", QVariant::fromValue(transforms)); | ||
| 1488 | + return res; | ||
| 1489 | +} |
openbr/openbr_plugin.h
| @@ -589,13 +589,20 @@ public: | @@ -589,13 +589,20 @@ public: | ||
| 589 | File file; /*!< \brief The file used to construct the plugin. */ | 589 | File file; /*!< \brief The file used to construct the plugin. */ |
| 590 | 590 | ||
| 591 | virtual void init() {} /*!< \brief Overload this function instead of the default constructor to initialize the derived class. It should be safe to call this function multiple times. */ | 591 | virtual void init() {} /*!< \brief Overload this function instead of the default constructor to initialize the derived class. It should be safe to call this function multiple times. */ |
| 592 | - virtual void store(QDataStream &stream) const; /*!< \brief Serialize the object. */ | 592 | + virtual void store(QDataStream &stream, bool force = false) const; /*!< \brief Serialize the object. */ |
| 593 | virtual void load(QDataStream &stream); /*!< \brief Deserialize the object. Default implementation calls init() after deserialization. */ | 593 | virtual void load(QDataStream &stream); /*!< \brief Deserialize the object. Default implementation calls init() after deserialization. */ |
| 594 | 594 | ||
| 595 | + virtual void serialize(QDataStream & stream, bool force) | ||
| 596 | + { | ||
| 597 | + stream << description(force); | ||
| 598 | + store(stream, force); | ||
| 599 | + } | ||
| 600 | + | ||
| 595 | QStringList parameters() const; /*!< \brief A string describing the parameters the object takes. */ | 601 | QStringList parameters() const; /*!< \brief A string describing the parameters the object takes. */ |
| 596 | - QStringList arguments() const; /*!< \brief A string describing the values the object has. */ | ||
| 597 | - QString argument(int index) const; /*!< \brief A string value for the argument at the specified index. */ | ||
| 598 | - QString description() const; /*!< \brief Returns a string description of the object. */ | 602 | + QStringList arguments(bool expanded = false); /*!< \brief A string describing the values the object has. */ |
| 603 | + QString argument(int index, bool expanded) const; /*!< \brief A string value for the argument at the specified index. */ | ||
| 604 | + virtual QString description(bool expanded = false); /*!< \brief Returns a string description of the object. */ | ||
| 605 | + | ||
| 599 | void setProperty(const QString &name, QVariant value); /*!< \brief Overload of QObject::setProperty to handle OpenBR data types. */ | 606 | void setProperty(const QString &name, QVariant value); /*!< \brief Overload of QObject::setProperty to handle OpenBR data types. */ |
| 600 | virtual bool setPropertyRecursive(const QString &name, QVariant value); /*!< \brief Recursive version of setProperty, try to set the property on this object, or its children, returns true if successful. */ | 607 | virtual bool setPropertyRecursive(const QString &name, QVariant value); /*!< \brief Recursive version of setProperty, try to set the property on this object, or its children, returns true if successful. */ |
| 601 | 608 | ||
| @@ -1273,6 +1280,15 @@ public: | @@ -1273,6 +1280,15 @@ public: | ||
| 1273 | */ | 1280 | */ |
| 1274 | QList<Transform *> getChildren() const; | 1281 | QList<Transform *> getChildren() const; |
| 1275 | 1282 | ||
| 1283 | + static Transform *deserialize(QDataStream &stream) | ||
| 1284 | + { | ||
| 1285 | + QString desc; | ||
| 1286 | + stream >> desc; | ||
| 1287 | + Transform *res = Transform::make(desc, NULL); | ||
| 1288 | + res->load(stream); | ||
| 1289 | + return res; | ||
| 1290 | + } | ||
| 1291 | + | ||
| 1276 | protected: | 1292 | protected: |
| 1277 | Transform(bool independent = true, bool trainable = true); /*!< \brief Construct a transform. */ | 1293 | Transform(bool independent = true, bool trainable = true); /*!< \brief Construct a transform. */ |
| 1278 | inline Transform *make(const QString &description) { return make(description, this); } /*!< \brief Make a subtransform. */ | 1294 | inline Transform *make(const QString &description) { return make(description, this); } /*!< \brief Make a subtransform. */ |
openbr/plugins/cascade.cpp
| @@ -415,7 +415,7 @@ class CascadeTransform : public MetaTransform | @@ -415,7 +415,7 @@ class CascadeTransform : public MetaTransform | ||
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | // TODO: Remove this code when ready to break binary compatibility | 417 | // TODO: Remove this code when ready to break binary compatibility |
| 418 | - void store(QDataStream &stream) const | 418 | + void store(QDataStream &stream, bool force) const |
| 419 | { | 419 | { |
| 420 | int size = 1; | 420 | int size = 1; |
| 421 | stream << size; | 421 | stream << size; |
openbr/plugins/cluster.cpp
| @@ -69,7 +69,7 @@ class KMeansTransform : public Transform | @@ -69,7 +69,7 @@ class KMeansTransform : public Transform | ||
| 69 | reindex(); | 69 | reindex(); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | - void store(QDataStream &stream) const | 72 | + void store(QDataStream &stream, bool force) const |
| 73 | { | 73 | { |
| 74 | stream << centers; | 74 | stream << centers; |
| 75 | } | 75 | } |
| @@ -131,7 +131,7 @@ class KNNTransform : public Transform | @@ -131,7 +131,7 @@ class KNNTransform : public Transform | ||
| 131 | dst.file.set("Nearest", gallery[sortedScores[0].second].file.name); | 131 | dst.file.set("Nearest", gallery[sortedScores[0].second].file.name); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | - void store(QDataStream &stream) const | 134 | + void store(QDataStream &stream, bool force) const |
| 135 | { | 135 | { |
| 136 | stream << gallery; | 136 | stream << gallery; |
| 137 | } | 137 | } |
| @@ -196,7 +196,7 @@ class RandomCentroidsTransform : public Transform | @@ -196,7 +196,7 @@ class RandomCentroidsTransform : public Transform | ||
| 196 | reindex(); | 196 | reindex(); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | - void store(QDataStream &stream) const | 199 | + void store(QDataStream &stream, bool force) const |
| 200 | { | 200 | { |
| 201 | stream << centers; | 201 | stream << centers; |
| 202 | } | 202 | } |
openbr/plugins/distance.cpp
| @@ -253,11 +253,11 @@ private: | @@ -253,11 +253,11 @@ private: | ||
| 253 | } | 253 | } |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | - void store(QDataStream &stream) const | 256 | + void store(QDataStream &stream, bool force) const |
| 257 | { | 257 | { |
| 258 | stream << distances.size(); | 258 | stream << distances.size(); |
| 259 | foreach (Distance *distance, distances) | 259 | foreach (Distance *distance, distances) |
| 260 | - distance->store(stream); | 260 | + distance->store(stream, force); |
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | void load(QDataStream &stream) | 263 | void load(QDataStream &stream) |
| @@ -328,9 +328,9 @@ class NegativeLogPlusOneDistance : public Distance | @@ -328,9 +328,9 @@ class NegativeLogPlusOneDistance : public Distance | ||
| 328 | return -log(distance->compare(a,b)+1); | 328 | return -log(distance->compare(a,b)+1); |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | - void store(QDataStream &stream) const | 331 | + void store(QDataStream &stream, bool force) const |
| 332 | { | 332 | { |
| 333 | - distance->store(stream); | 333 | + distance->store(stream, force); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | void load(QDataStream &stream) | 336 | void load(QDataStream &stream) |
| @@ -460,13 +460,12 @@ BR_REGISTER(Distance, SumDistance) | @@ -460,13 +460,12 @@ BR_REGISTER(Distance, SumDistance) | ||
| 460 | class GalleryCompareTransform : public Transform | 460 | class GalleryCompareTransform : public Transform |
| 461 | { | 461 | { |
| 462 | Q_OBJECT | 462 | Q_OBJECT |
| 463 | - Q_PROPERTY(QString distanceAlgorithm READ get_distanceAlgorithm WRITE set_distanceAlgorithm RESET reset_distanceAlgorithm STORED false) | 463 | + Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED true) |
| 464 | Q_PROPERTY(QString galleryName READ get_galleryName WRITE set_galleryName RESET reset_galleryName STORED false) | 464 | Q_PROPERTY(QString galleryName READ get_galleryName WRITE set_galleryName RESET reset_galleryName STORED false) |
| 465 | - BR_PROPERTY(QString, distanceAlgorithm, "") | 465 | + BR_PROPERTY(br::Distance*, distance, NULL) |
| 466 | BR_PROPERTY(QString, galleryName, "") | 466 | BR_PROPERTY(QString, galleryName, "") |
| 467 | 467 | ||
| 468 | TemplateList gallery; | 468 | TemplateList gallery; |
| 469 | - QSharedPointer<Distance> distance; | ||
| 470 | 469 | ||
| 471 | void project(const Template &src, Template &dst) const | 470 | void project(const Template &src, Template &dst) const |
| 472 | { | 471 | { |
| @@ -480,16 +479,29 @@ class GalleryCompareTransform : public Transform | @@ -480,16 +479,29 @@ class GalleryCompareTransform : public Transform | ||
| 480 | 479 | ||
| 481 | void init() | 480 | void init() |
| 482 | { | 481 | { |
| 483 | - if (!galleryName.isEmpty()) { | 482 | + if (!galleryName.isEmpty()) |
| 484 | gallery = TemplateList::fromGallery(galleryName); | 483 | gallery = TemplateList::fromGallery(galleryName); |
| 485 | - } | ||
| 486 | - if (!distanceAlgorithm.isEmpty()) | ||
| 487 | - { | ||
| 488 | - distance = Distance::fromAlgorithm(distanceAlgorithm); | ||
| 489 | - } | ||
| 490 | } | 484 | } |
| 485 | + | ||
| 486 | + void train(const TemplateList & data) | ||
| 487 | + { | ||
| 488 | + gallery = data; | ||
| 489 | + } | ||
| 490 | + | ||
| 491 | + void store(QDataStream &stream, bool force) const | ||
| 492 | + { | ||
| 493 | + br::Object::store(stream, force); | ||
| 494 | + stream << gallery; | ||
| 495 | + } | ||
| 496 | + | ||
| 497 | + void load(QDataStream &stream) | ||
| 498 | + { | ||
| 499 | + br::Object::load(stream); | ||
| 500 | + stream >> gallery; | ||
| 501 | + } | ||
| 502 | + | ||
| 491 | public: | 503 | public: |
| 492 | - GalleryCompareTransform() : Transform(false, false) {} | 504 | + GalleryCompareTransform() : Transform(false, true) {} |
| 493 | }; | 505 | }; |
| 494 | 506 | ||
| 495 | BR_REGISTER(Transform, GalleryCompareTransform) | 507 | BR_REGISTER(Transform, GalleryCompareTransform) |
openbr/plugins/eigen3.cpp
| @@ -119,7 +119,7 @@ private: | @@ -119,7 +119,7 @@ private: | ||
| 119 | outMap = eVecs.transpose() * (inMap - mean); | 119 | outMap = eVecs.transpose() * (inMap - mean); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | - void store(QDataStream &stream) const | 122 | + void store(QDataStream &stream, bool force) const |
| 123 | { | 123 | { |
| 124 | stream << keep << drop << whiten << originalRows << mean << eVals << eVecs; | 124 | stream << keep << drop << whiten << originalRows << mean << eVals << eVecs; |
| 125 | } | 125 | } |
| @@ -295,9 +295,9 @@ class DFFSTransform : public Transform | @@ -295,9 +295,9 @@ class DFFSTransform : public Transform | ||
| 295 | dst.file.set("DFFS", sqrt(pca.residualReconstructionError((*cvtFloat)(src)))); | 295 | dst.file.set("DFFS", sqrt(pca.residualReconstructionError((*cvtFloat)(src)))); |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | - void store(QDataStream &stream) const | 298 | + void store(QDataStream &stream, bool force) const |
| 299 | { | 299 | { |
| 300 | - pca.store(stream); | 300 | + pca.store(stream, force); |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | void load(QDataStream &stream) | 303 | void load(QDataStream &stream) |
| @@ -525,7 +525,7 @@ class LDATransform : public Transform | @@ -525,7 +525,7 @@ class LDATransform : public Transform | ||
| 525 | dst.m().at<float>(0,0) = dst.m().at<float>(0,0) / stdDev; | 525 | dst.m().at<float>(0,0) = dst.m().at<float>(0,0) / stdDev; |
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | - void store(QDataStream &stream) const | 528 | + void store(QDataStream &stream, bool force) const |
| 529 | { | 529 | { |
| 530 | stream << pcaKeep; | 530 | stream << pcaKeep; |
| 531 | stream << directLDA; | 531 | stream << directLDA; |
| @@ -631,10 +631,10 @@ class SparseLDATransform : public Transform | @@ -631,10 +631,10 @@ class SparseLDATransform : public Transform | ||
| 631 | ldaSparse.project(Template(src.file, inSelect), dst); | 631 | ldaSparse.project(Template(src.file, inSelect), dst); |
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | - void store(QDataStream &stream) const | 634 | + void store(QDataStream &stream, bool force) const |
| 635 | { | 635 | { |
| 636 | stream << pcaKeep; | 636 | stream << pcaKeep; |
| 637 | - stream << ldaSparse; | 637 | + ldaSparse.store(stream, force); |
| 638 | stream << dimsOut; | 638 | stream << dimsOut; |
| 639 | stream << selections; | 639 | stream << selections; |
| 640 | } | 640 | } |
openbr/plugins/frames.cpp
openbr/plugins/independent.cpp
| @@ -126,6 +126,10 @@ class IndependentTransform : public MetaTransform | @@ -126,6 +126,10 @@ class IndependentTransform : public MetaTransform | ||
| 126 | 126 | ||
| 127 | QList<Transform*> transforms; | 127 | QList<Transform*> transforms; |
| 128 | 128 | ||
| 129 | + QString description(bool expanded) | ||
| 130 | + { | ||
| 131 | + return transform->description(expanded); | ||
| 132 | + } | ||
| 129 | 133 | ||
| 130 | bool setPropertyRecursive(const QString &name, QVariant value) | 134 | bool setPropertyRecursive(const QString &name, QVariant value) |
| 131 | { | 135 | { |
| @@ -226,12 +230,12 @@ class IndependentTransform : public MetaTransform | @@ -226,12 +230,12 @@ class IndependentTransform : public MetaTransform | ||
| 226 | } | 230 | } |
| 227 | } | 231 | } |
| 228 | 232 | ||
| 229 | - void store(QDataStream &stream) const | 233 | + void store(QDataStream &stream, bool force) const |
| 230 | { | 234 | { |
| 231 | const int size = transforms.size(); | 235 | const int size = transforms.size(); |
| 232 | stream << size; | 236 | stream << size; |
| 233 | for (int i=0; i<size; i++) | 237 | for (int i=0; i<size; i++) |
| 234 | - transforms[i]->store(stream); | 238 | + transforms[i]->store(stream, force); |
| 235 | } | 239 | } |
| 236 | 240 | ||
| 237 | void load(QDataStream &stream) | 241 | void load(QDataStream &stream) |
| @@ -292,10 +296,10 @@ class SingletonTransform : public MetaTransform | @@ -292,10 +296,10 @@ class SingletonTransform : public MetaTransform | ||
| 292 | transform->project(src, dst); | 296 | transform->project(src, dst); |
| 293 | } | 297 | } |
| 294 | 298 | ||
| 295 | - void store(QDataStream &stream) const | 299 | + void store(QDataStream &stream, bool force) const |
| 296 | { | 300 | { |
| 297 | if (transform->parent() == this) | 301 | if (transform->parent() == this) |
| 298 | - transform->store(stream); | 302 | + transform->store(stream, force); |
| 299 | } | 303 | } |
| 300 | 304 | ||
| 301 | void load(QDataStream &stream) | 305 | void load(QDataStream &stream) |
openbr/plugins/integral.cpp
| @@ -251,12 +251,12 @@ class RecursiveIntegralSamplerTransform : public Transform | @@ -251,12 +251,12 @@ class RecursiveIntegralSamplerTransform : public Transform | ||
| 251 | } | 251 | } |
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | - void store(QDataStream &stream) const | 254 | + void store(QDataStream &stream, bool force) const |
| 255 | { | 255 | { |
| 256 | - transform->store(stream); | 256 | + transform->store(stream, force); |
| 257 | stream << (subTransform != NULL); | 257 | stream << (subTransform != NULL); |
| 258 | if (subTransform != NULL) | 258 | if (subTransform != NULL) |
| 259 | - subTransform->store(stream); | 259 | + subTransform->store(stream, force); |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | void load(QDataStream &stream) | 262 | void load(QDataStream &stream) |
openbr/plugins/landmarks.cpp
| @@ -125,7 +125,7 @@ class ProcrustesTransform : public Transform | @@ -125,7 +125,7 @@ class ProcrustesTransform : public Transform | ||
| 125 | } | 125 | } |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | - void store(QDataStream &stream) const | 128 | + void store(QDataStream &stream, bool force) const |
| 129 | { | 129 | { |
| 130 | stream << meanShape; | 130 | stream << meanShape; |
| 131 | } | 131 | } |
| @@ -299,7 +299,7 @@ class ProcrustesAlignTransform : public Transform | @@ -299,7 +299,7 @@ class ProcrustesAlignTransform : public Transform | ||
| 299 | dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); | 299 | dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | - void store(QDataStream &stream) const | 302 | + void store(QDataStream &stream, bool force) const |
| 303 | { | 303 | { |
| 304 | stream << referenceShape; | 304 | stream << referenceShape; |
| 305 | stream << minX; | 305 | stream << minX; |
openbr/plugins/meta.cpp
| @@ -482,9 +482,9 @@ BR_REGISTER(Transform, CacheTransform) | @@ -482,9 +482,9 @@ BR_REGISTER(Transform, CacheTransform) | ||
| 482 | class LoadStoreTransform : public MetaTransform | 482 | class LoadStoreTransform : public MetaTransform |
| 483 | { | 483 | { |
| 484 | Q_OBJECT | 484 | Q_OBJECT |
| 485 | - Q_PROPERTY(QString description READ get_description WRITE set_description RESET reset_description STORED false) | 485 | + Q_PROPERTY(QString description2 READ get_description2 WRITE set_description2 RESET reset_description2 STORED false) |
| 486 | Q_PROPERTY(QString fileName READ get_fileName WRITE set_fileName RESET reset_fileName STORED false) | 486 | Q_PROPERTY(QString fileName READ get_fileName WRITE set_fileName RESET reset_fileName STORED false) |
| 487 | - BR_PROPERTY(QString, description, "Identity") | 487 | + BR_PROPERTY(QString, description2, "Identity") |
| 488 | BR_PROPERTY(QString, fileName, QString()) | 488 | BR_PROPERTY(QString, fileName, QString()) |
| 489 | 489 | ||
| 490 | Transform *transform; | 490 | Transform *transform; |
| @@ -493,6 +493,13 @@ class LoadStoreTransform : public MetaTransform | @@ -493,6 +493,13 @@ class LoadStoreTransform : public MetaTransform | ||
| 493 | public: | 493 | public: |
| 494 | LoadStoreTransform() : transform(NULL) {} | 494 | LoadStoreTransform() : transform(NULL) {} |
| 495 | 495 | ||
| 496 | + QString description(bool expanded = false) | ||
| 497 | + { | ||
| 498 | + if (expanded) | ||
| 499 | + return transform->description(expanded); | ||
| 500 | + return br::Object::description(expanded); | ||
| 501 | + } | ||
| 502 | + | ||
| 496 | bool setPropertyRecursive(const QString &name, QVariant value) | 503 | bool setPropertyRecursive(const QString &name, QVariant value) |
| 497 | { | 504 | { |
| 498 | if (br::Object::setPropertyRecursive(name, value)) | 505 | if (br::Object::setPropertyRecursive(name, value)) |
| @@ -500,12 +507,22 @@ public: | @@ -500,12 +507,22 @@ public: | ||
| 500 | return transform->setPropertyRecursive(name, value); | 507 | return transform->setPropertyRecursive(name, value); |
| 501 | } | 508 | } |
| 502 | private: | 509 | private: |
| 510 | + | ||
| 511 | + virtual void store(QDataStream &stream, bool force = false) const | ||
| 512 | + { | ||
| 513 | + if (force) { | ||
| 514 | + transform->store(stream, force); | ||
| 515 | + } | ||
| 516 | + | ||
| 517 | + br::Object::store(stream, false); | ||
| 518 | + } | ||
| 519 | + | ||
| 503 | void init() | 520 | void init() |
| 504 | { | 521 | { |
| 505 | if (transform != NULL) return; | 522 | if (transform != NULL) return; |
| 506 | - if (fileName.isEmpty()) baseName = QRegExp("^[a-zA-Z0-9]+$").exactMatch(description) ? description : QtUtils::shortTextHash(description); | 523 | + if (fileName.isEmpty()) baseName = QRegExp("^[a-zA-Z0-9]+$").exactMatch(description2) ? description2 : QtUtils::shortTextHash(description2); |
| 507 | else baseName = fileName; | 524 | else baseName = fileName; |
| 508 | - if (!tryLoad()) transform = make(description); | 525 | + if (!tryLoad()) transform = make(description2); |
| 509 | else trainable = false; | 526 | else trainable = false; |
| 510 | } | 527 | } |
| 511 | 528 | ||
| @@ -524,7 +541,7 @@ private: | @@ -524,7 +541,7 @@ private: | ||
| 524 | qDebug("Storing %s", qPrintable(baseName)); | 541 | qDebug("Storing %s", qPrintable(baseName)); |
| 525 | QByteArray byteArray; | 542 | QByteArray byteArray; |
| 526 | QDataStream stream(&byteArray, QFile::WriteOnly); | 543 | QDataStream stream(&byteArray, QFile::WriteOnly); |
| 527 | - stream << description; | 544 | + stream << description2; |
| 528 | transform->store(stream); | 545 | transform->store(stream); |
| 529 | QtUtils::writeFile(baseName, byteArray, -1); | 546 | QtUtils::writeFile(baseName, byteArray, -1); |
| 530 | } | 547 | } |
| @@ -570,8 +587,8 @@ private: | @@ -570,8 +587,8 @@ private: | ||
| 570 | QByteArray data; | 587 | QByteArray data; |
| 571 | QtUtils::readFile(file, data, true); | 588 | QtUtils::readFile(file, data, true); |
| 572 | QDataStream stream(&data, QFile::ReadOnly); | 589 | QDataStream stream(&data, QFile::ReadOnly); |
| 573 | - stream >> description; | ||
| 574 | - transform = Transform::make(description); | 590 | + stream >> description2; |
| 591 | + transform = Transform::make(description2); | ||
| 575 | transform->load(stream); | 592 | transform->load(stream); |
| 576 | return true; | 593 | return true; |
| 577 | } | 594 | } |
openbr/plugins/misc.cpp
| @@ -617,8 +617,8 @@ class ProgressCounterTransform : public TimeVaryingTransform | @@ -617,8 +617,8 @@ class ProgressCounterTransform : public TimeVaryingTransform | ||
| 617 | { | 617 | { |
| 618 | Q_OBJECT | 618 | Q_OBJECT |
| 619 | 619 | ||
| 620 | - Q_PROPERTY(int totalTemplates READ get_totalTemplates WRITE set_totalTemplates RESET reset_totalTemplates STORED false) | ||
| 621 | - BR_PROPERTY(int, totalTemplates, 1) | 620 | + Q_PROPERTY(int totalProgress READ get_totalProgress WRITE set_totalProgress RESET reset_totalProgress STORED false) |
| 621 | + BR_PROPERTY(int, totalProgress, 1) | ||
| 622 | 622 | ||
| 623 | void projectUpdate(const TemplateList &src, TemplateList &dst) | 623 | void projectUpdate(const TemplateList &src, TemplateList &dst) |
| 624 | { | 624 | { |
| @@ -658,16 +658,20 @@ class ProgressCounterTransform : public TimeVaryingTransform | @@ -658,16 +658,20 @@ class ProgressCounterTransform : public TimeVaryingTransform | ||
| 658 | (void) data; | 658 | (void) data; |
| 659 | float p = br_progress(); | 659 | float p = br_progress(); |
| 660 | qDebug("\r%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(0).toStdString().c_str(), Globals->currentStep); | 660 | qDebug("\r%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(0).toStdString().c_str(), Globals->currentStep); |
| 661 | + timer.start(); | ||
| 662 | + Globals->startTime.start(); | ||
| 661 | Globals->currentStep = 0; | 663 | Globals->currentStep = 0; |
| 662 | Globals->currentProgress = 0; | 664 | Globals->currentProgress = 0; |
| 663 | - Globals->totalSteps = 0; | 665 | + Globals->totalSteps = totalProgress; |
| 664 | } | 666 | } |
| 665 | 667 | ||
| 666 | void init() | 668 | void init() |
| 667 | { | 669 | { |
| 668 | timer.start(); | 670 | timer.start(); |
| 671 | + Globals->startTime.start(); | ||
| 669 | Globals->currentStep = 0; | 672 | Globals->currentStep = 0; |
| 670 | Globals->currentProgress = 0; | 673 | Globals->currentProgress = 0; |
| 674 | + Globals->totalSteps = totalProgress; | ||
| 671 | } | 675 | } |
| 672 | 676 | ||
| 673 | public: | 677 | public: |
openbr/plugins/normalize.cpp
| @@ -167,7 +167,7 @@ private: | @@ -167,7 +167,7 @@ private: | ||
| 167 | divide(dst, a, dst); | 167 | divide(dst, a, dst); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | - void store(QDataStream &stream) const | 170 | + void store(QDataStream &stream, bool force) const |
| 171 | { | 171 | { |
| 172 | stream << a << b; | 172 | stream << a << b; |
| 173 | } | 173 | } |
| @@ -256,7 +256,7 @@ class RowWiseMeanCenterTransform : public Transform | @@ -256,7 +256,7 @@ class RowWiseMeanCenterTransform : public Transform | ||
| 256 | dst = m; | 256 | dst = m; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | - void store(QDataStream &stream) const | 259 | + void store(QDataStream &stream, bool force) const |
| 260 | { | 260 | { |
| 261 | stream << mean; | 261 | stream << mean; |
| 262 | } | 262 | } |
openbr/plugins/openbr_internal.h
| @@ -19,7 +19,7 @@ protected: | @@ -19,7 +19,7 @@ protected: | ||
| 19 | private: | 19 | private: |
| 20 | Transform *clone() const { return const_cast<UntrainableTransform*>(this); } | 20 | Transform *clone() const { return const_cast<UntrainableTransform*>(this); } |
| 21 | void train(const TemplateList &data) { (void) data; } | 21 | void train(const TemplateList &data) { (void) data; } |
| 22 | - void store(QDataStream &stream) const { (void) stream; } | 22 | + void store(QDataStream &stream, bool force) const { (void) stream; (void) force; } |
| 23 | void load(QDataStream &stream) { (void) stream; } | 23 | void load(QDataStream &stream) { (void) stream; } |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| @@ -212,6 +212,45 @@ public: | @@ -212,6 +212,45 @@ public: | ||
| 212 | } | 212 | } |
| 213 | return false; | 213 | return false; |
| 214 | } | 214 | } |
| 215 | + | ||
| 216 | + Transform * smartCopy(bool & newTransform) | ||
| 217 | + { | ||
| 218 | + if (!timeVarying()) { | ||
| 219 | + newTransform = false; | ||
| 220 | + return this; | ||
| 221 | + } | ||
| 222 | + newTransform = true; | ||
| 223 | + | ||
| 224 | + QString name = metaObject()->className(); | ||
| 225 | + name.replace("Transform",""); | ||
| 226 | + name += "(Identity"; | ||
| 227 | + | ||
| 228 | + QStringList arguments = this->arguments(); | ||
| 229 | + if (!arguments.isEmpty()) { | ||
| 230 | + name += ","; | ||
| 231 | + name += this->arguments().join(","); | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + name += ")"; | ||
| 235 | + name.replace("br::",""); | ||
| 236 | + | ||
| 237 | + WrapperTransform *output = dynamic_cast<WrapperTransform *>(Transform::make(name, NULL)); | ||
| 238 | + | ||
| 239 | + if (output == NULL) | ||
| 240 | + qFatal("Dynamic cast failed!"); | ||
| 241 | + | ||
| 242 | + bool newItem = false; | ||
| 243 | + Transform * maybe_copy = transform->smartCopy(newItem); | ||
| 244 | + if (newItem) | ||
| 245 | + maybe_copy->setParent(output); | ||
| 246 | + output->transform = maybe_copy; | ||
| 247 | + | ||
| 248 | + output->file = this->file; | ||
| 249 | + output->init(); | ||
| 250 | + | ||
| 251 | + return output; | ||
| 252 | + } | ||
| 253 | + | ||
| 215 | }; | 254 | }; |
| 216 | 255 | ||
| 217 | /*! | 256 | /*! |
| @@ -388,6 +427,10 @@ public: | @@ -388,6 +427,10 @@ public: | ||
| 388 | 427 | ||
| 389 | void applyAdditionalProperties(const File &temp, Transform *target); | 428 | void applyAdditionalProperties(const File &temp, Transform *target); |
| 390 | 429 | ||
| 430 | +Transform *wrapTransform(Transform *base, const QString &target); | ||
| 431 | + | ||
| 432 | +Transform *pipeTransforms(QList<Transform *> &transforms); | ||
| 433 | + | ||
| 391 | } | 434 | } |
| 392 | 435 | ||
| 393 | #endif // OPENBR_INTERNAL_H | 436 | #endif // OPENBR_INTERNAL_H |
openbr/plugins/pp5.cpp
| @@ -450,6 +450,7 @@ class PP5GalleryTransform: public UntrainableMetaTransform | @@ -450,6 +450,7 @@ class PP5GalleryTransform: public UntrainableMetaTransform | ||
| 450 | 450 | ||
| 451 | ppr_gallery_type target; | 451 | ppr_gallery_type target; |
| 452 | QList<int> targetIDs; | 452 | QList<int> targetIDs; |
| 453 | + TemplateList gallery; | ||
| 453 | 454 | ||
| 454 | void project(const Template & src, Template & dst) const | 455 | void project(const Template & src, Template & dst) const |
| 455 | { | 456 | { |
| @@ -495,11 +496,33 @@ class PP5GalleryTransform: public UntrainableMetaTransform | @@ -495,11 +496,33 @@ class PP5GalleryTransform: public UntrainableMetaTransform | ||
| 495 | 496 | ||
| 496 | void init() | 497 | void init() |
| 497 | { | 498 | { |
| 498 | - // set up the gallery | ||
| 499 | - ppr_create_gallery(context, &target); | ||
| 500 | - TemplateList templates = TemplateList::fromGallery(galleryName); | ||
| 501 | - enroll(templates,&target, targetIDs); | 499 | + if (!galleryName.isEmpty() || !gallery.isEmpty()) { |
| 500 | + // set up the gallery | ||
| 501 | + ppr_create_gallery(context, &target); | ||
| 502 | + if (gallery.isEmpty() ) | ||
| 503 | + gallery = TemplateList::fromGallery(galleryName); | ||
| 504 | + enroll(gallery, &target, targetIDs); | ||
| 505 | + } | ||
| 506 | + } | ||
| 507 | + | ||
| 508 | + void train(const TemplateList & data) | ||
| 509 | + { | ||
| 510 | + gallery = data; | ||
| 502 | } | 511 | } |
| 512 | + | ||
| 513 | + void store(QDataStream &stream, bool force) const | ||
| 514 | + { | ||
| 515 | + br::Object::store(stream, force); | ||
| 516 | + stream << gallery; | ||
| 517 | + } | ||
| 518 | + | ||
| 519 | + void load(QDataStream &stream) | ||
| 520 | + { | ||
| 521 | + br::Object::load(stream); | ||
| 522 | + stream >> gallery; | ||
| 523 | + init(); | ||
| 524 | + } | ||
| 525 | + | ||
| 503 | }; | 526 | }; |
| 504 | 527 | ||
| 505 | BR_REGISTER(Transform, PP5GalleryTransform) | 528 | BR_REGISTER(Transform, PP5GalleryTransform) |
openbr/plugins/process.cpp
| @@ -305,9 +305,7 @@ public: | @@ -305,9 +305,7 @@ public: | ||
| 305 | while (!inbound || inbound->state() != QLocalSocket::ConnectedState) { | 305 | while (!inbound || inbound->state() != QLocalSocket::ConnectedState) { |
| 306 | bool res = receivedWait.wait(&receivedLock,30*1000); | 306 | bool res = receivedWait.wait(&receivedLock,30*1000); |
| 307 | if (!res) | 307 | if (!res) |
| 308 | - { | ||
| 309 | qDebug() << key << " " << QThread::currentThread() << " waiting timed out, server thread is " << server.thread() << " base thread " << basis; | 308 | qDebug() << key << " " << QThread::currentThread() << " waiting timed out, server thread is " << server.thread() << " base thread " << basis; |
| 310 | - } | ||
| 311 | } | 309 | } |
| 312 | } | 310 | } |
| 313 | 311 | ||
| @@ -338,6 +336,16 @@ public: | @@ -338,6 +336,16 @@ public: | ||
| 338 | return true; | 336 | return true; |
| 339 | } | 337 | } |
| 340 | 338 | ||
| 339 | + Transform * readTForm() | ||
| 340 | + { | ||
| 341 | + emit pulseReadSerialized(); | ||
| 342 | + | ||
| 343 | + QByteArray data = readArray; | ||
| 344 | + QDataStream deserializer(data); | ||
| 345 | + Transform * res = Transform::deserialize(deserializer); | ||
| 346 | + return res; | ||
| 347 | + } | ||
| 348 | + | ||
| 341 | template<typename T> | 349 | template<typename T> |
| 342 | bool sendData(const T & output) | 350 | bool sendData(const T & output) |
| 343 | { | 351 | { |
| @@ -401,6 +409,8 @@ public: | @@ -401,6 +409,8 @@ public: | ||
| 401 | comm->connectToRemote(baseName+"_master"); | 409 | comm->connectToRemote(baseName+"_master"); |
| 402 | 410 | ||
| 403 | comm->waitForInbound(); | 411 | comm->waitForInbound(); |
| 412 | + | ||
| 413 | + transform = comm->readTForm(); | ||
| 404 | } | 414 | } |
| 405 | 415 | ||
| 406 | void workerLoop() | 416 | void workerLoop() |
| @@ -428,7 +438,7 @@ public: | @@ -428,7 +438,7 @@ public: | ||
| 428 | void WorkerProcess::mainLoop() | 438 | void WorkerProcess::mainLoop() |
| 429 | { | 439 | { |
| 430 | processInterface = new EnrollmentWorker(); | 440 | processInterface = new EnrollmentWorker(); |
| 431 | - processInterface->transform = Transform::make(this->transform,NULL); | 441 | + processInterface->transform = NULL; |
| 432 | processInterface->connections(baseName); | 442 | processInterface->connections(baseName); |
| 433 | processInterface->workerLoop(); | 443 | processInterface->workerLoop(); |
| 434 | delete processInterface; | 444 | delete processInterface; |
| @@ -478,63 +488,98 @@ protected slots: | @@ -478,63 +488,98 @@ protected slots: | ||
| 478 | } | 488 | } |
| 479 | }; | 489 | }; |
| 480 | 490 | ||
| 491 | +struct ProcessData | ||
| 492 | +{ | ||
| 493 | + CommunicationManager comm; | ||
| 494 | + ProcessInterface proc; | ||
| 495 | + bool initialized; | ||
| 496 | + ProcessData() | ||
| 497 | + { | ||
| 498 | + initialized = false; | ||
| 499 | + } | ||
| 500 | + | ||
| 501 | + ~ProcessData() | ||
| 502 | + { | ||
| 503 | + comm.sendSignal(CommunicationManager::SHOULD_END); | ||
| 504 | + proc.endProcess(); | ||
| 505 | + comm.shutdown(); | ||
| 506 | + comm.shutDownThread(); | ||
| 507 | + } | ||
| 508 | +}; | ||
| 509 | + | ||
| 510 | + | ||
| 481 | /*! | 511 | /*! |
| 482 | * \ingroup transforms | 512 | * \ingroup transforms |
| 483 | * \brief Interface to a separate process | 513 | * \brief Interface to a separate process |
| 484 | * \author Charles Otto \cite caotto | 514 | * \author Charles Otto \cite caotto |
| 485 | */ | 515 | */ |
| 486 | -class ProcessWrapperTransform : public TimeVaryingTransform | 516 | +class ProcessWrapperTransform : public WrapperTransform |
| 487 | { | 517 | { |
| 488 | Q_OBJECT | 518 | Q_OBJECT |
| 489 | 519 | ||
| 490 | - Q_PROPERTY(QString transform READ get_transform WRITE set_transform RESET reset_transform) | ||
| 491 | - BR_PROPERTY(QString, transform, "") | ||
| 492 | - | ||
| 493 | QString baseKey; | 520 | QString baseKey; |
| 494 | 521 | ||
| 495 | - ProcessInterface workerProcess; | ||
| 496 | - CommunicationManager * comm; | 522 | + Resource<ProcessData> processes; |
| 523 | + | ||
| 524 | + Transform * smartCopy(bool & newTransform) | ||
| 525 | + { | ||
| 526 | + newTransform = false; | ||
| 527 | + return this; | ||
| 528 | + } | ||
| 497 | 529 | ||
| 498 | - void projectUpdate(const TemplateList &src, TemplateList &dst) | 530 | + void project(const TemplateList &src, TemplateList &dst) const |
| 499 | { | 531 | { |
| 500 | if (src.empty()) | 532 | if (src.empty()) |
| 501 | return; | 533 | return; |
| 534 | + | ||
| 535 | + ProcessData *data = processes.acquire(); | ||
| 536 | + if (!data->initialized) | ||
| 537 | + activateProcess(data); | ||
| 502 | 538 | ||
| 503 | - if (!processActive) | ||
| 504 | - { | ||
| 505 | - activateProcess(); | ||
| 506 | - } | ||
| 507 | - comm->sendSignal(CommunicationManager::INPUT_AVAILABLE); | ||
| 508 | - | ||
| 509 | - comm->sendData(src); | 539 | + CommunicationManager * localComm = &(data->comm); |
| 540 | + localComm->sendSignal(CommunicationManager::INPUT_AVAILABLE); | ||
| 510 | 541 | ||
| 511 | - comm->readData(dst); | 542 | + localComm->sendData(src); |
| 543 | + localComm->readData(dst); | ||
| 544 | + processes.release(data); | ||
| 512 | } | 545 | } |
| 513 | 546 | ||
| 514 | - | ||
| 515 | void train(const TemplateList& data) | 547 | void train(const TemplateList& data) |
| 516 | { | 548 | { |
| 517 | (void) data; | 549 | (void) data; |
| 518 | } | 550 | } |
| 519 | 551 | ||
| 520 | - // create the process | ||
| 521 | void init() | 552 | void init() |
| 522 | { | 553 | { |
| 523 | processActive = false; | 554 | processActive = false; |
| 555 | + serialized.clear(); | ||
| 556 | + if (transform) { | ||
| 557 | + QDataStream out(&serialized, QFile::WriteOnly); | ||
| 558 | + transform->serialize(out, true); | ||
| 559 | + } | ||
| 524 | } | 560 | } |
| 525 | 561 | ||
| 526 | - void activateProcess() | 562 | + QByteArray serialized; |
| 563 | + void transmitTForm(CommunicationManager * localComm) const | ||
| 527 | { | 564 | { |
| 528 | - comm = new CommunicationManager(); | ||
| 529 | - processActive = true; | 565 | + if (serialized.isEmpty() ) |
| 566 | + qFatal("Trying to transmit empty transform!"); | ||
| 567 | + | ||
| 568 | + localComm->writeArray = serialized; | ||
| 569 | + emit localComm->pulseSendSerialized(); | ||
| 570 | + } | ||
| 530 | 571 | ||
| 572 | + void activateProcess(ProcessData * data) const | ||
| 573 | + { | ||
| 574 | + data->initialized = true; | ||
| 531 | // generate a uuid for our local servers | 575 | // generate a uuid for our local servers |
| 532 | QUuid id = QUuid::createUuid(); | 576 | QUuid id = QUuid::createUuid(); |
| 533 | - baseKey = id.toString(); | 577 | + QString baseKey = id.toString(); |
| 534 | 578 | ||
| 535 | QStringList argumentList; | 579 | QStringList argumentList; |
| 580 | + // We serialize and transmit the transform directly, so algorithm doesn't matter. | ||
| 536 | argumentList.append("-algorithm"); | 581 | argumentList.append("-algorithm"); |
| 537 | - argumentList.append(transform); | 582 | + argumentList.append("Identity"); |
| 538 | if (!Globals->path.isEmpty()) { | 583 | if (!Globals->path.isEmpty()) { |
| 539 | argumentList.append("-path"); | 584 | argumentList.append("-path"); |
| 540 | argumentList.append(Globals->path); | 585 | argumentList.append(Globals->path); |
| @@ -544,36 +589,25 @@ class ProcessWrapperTransform : public TimeVaryingTransform | @@ -544,36 +589,25 @@ class ProcessWrapperTransform : public TimeVaryingTransform | ||
| 544 | argumentList.append("-slave"); | 589 | argumentList.append("-slave"); |
| 545 | argumentList.append(baseKey); | 590 | argumentList.append(baseKey); |
| 546 | 591 | ||
| 547 | - comm->key = "master_"+baseKey.mid(1,5); | 592 | + data->comm.key = "master_"+baseKey.mid(1,5); |
| 548 | 593 | ||
| 549 | - comm->startServer(baseKey+"_master"); | ||
| 550 | - workerProcess.startProcess(argumentList); | ||
| 551 | - comm->waitForInbound(); | ||
| 552 | - comm->connectToRemote(baseKey+"_worker"); | ||
| 553 | - } | 594 | + data->comm.startServer(baseKey+"_master"); |
| 554 | 595 | ||
| 555 | - bool timeVarying() const { | ||
| 556 | - return false; | 596 | + data->proc.startProcess(argumentList); |
| 597 | + data->comm.waitForInbound(); | ||
| 598 | + data->comm.connectToRemote(baseKey+"_worker"); | ||
| 599 | + | ||
| 600 | + transmitTForm(&(data->comm)); | ||
| 557 | } | 601 | } |
| 558 | 602 | ||
| 559 | - ~ProcessWrapperTransform() | 603 | + bool timeVarying() const |
| 560 | { | 604 | { |
| 561 | - // end the process | ||
| 562 | - if (this->processActive) { | ||
| 563 | - comm->sendSignal(CommunicationManager::SHOULD_END); | ||
| 564 | - | ||
| 565 | - workerProcess.endProcess(); | ||
| 566 | - processActive = false; | ||
| 567 | - comm->shutdown(); | ||
| 568 | - comm->shutDownThread(); | ||
| 569 | - | ||
| 570 | - delete comm; | ||
| 571 | - } | 605 | + return false; |
| 572 | } | 606 | } |
| 573 | 607 | ||
| 574 | public: | 608 | public: |
| 575 | bool processActive; | 609 | bool processActive; |
| 576 | - ProcessWrapperTransform() : TimeVaryingTransform(false,false) { processActive = false; } | 610 | + ProcessWrapperTransform() : WrapperTransform(false) { processActive = false; } |
| 577 | }; | 611 | }; |
| 578 | 612 | ||
| 579 | BR_REGISTER(Transform, ProcessWrapperTransform) | 613 | BR_REGISTER(Transform, ProcessWrapperTransform) |
openbr/plugins/quality.cpp
| @@ -62,9 +62,9 @@ class ImpostorUniquenessMeasureTransform : public Transform | @@ -62,9 +62,9 @@ class ImpostorUniquenessMeasureTransform : public Transform | ||
| 62 | dst.file.set("Impostor_Uniqueness_Measure_Bin", ium < mean-stddev ? 0 : (ium < mean+stddev ? 1 : 2)); | 62 | dst.file.set("Impostor_Uniqueness_Measure_Bin", ium < mean-stddev ? 0 : (ium < mean+stddev ? 1 : 2)); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | - void store(QDataStream &stream) const | 65 | + void store(QDataStream &stream, bool force) const |
| 66 | { | 66 | { |
| 67 | - distance->store(stream); | 67 | + distance->store(stream, force); |
| 68 | stream << mean << stddev << impostors; | 68 | stream << mean << stddev << impostors; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| @@ -199,9 +199,9 @@ class MatchProbabilityDistance : public Distance | @@ -199,9 +199,9 @@ class MatchProbabilityDistance : public Distance | ||
| 199 | return mp(score, gaussian); | 199 | return mp(score, gaussian); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | - void store(QDataStream &stream) const | 202 | + void store(QDataStream &stream, bool force) const |
| 203 | { | 203 | { |
| 204 | - distance->store(stream); | 204 | + distance->store(stream, force); |
| 205 | stream << mp; | 205 | stream << mp; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| @@ -264,9 +264,9 @@ class ZScoreDistance : public Distance | @@ -264,9 +264,9 @@ class ZScoreDistance : public Distance | ||
| 264 | return score; | 264 | return score; |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | - void store(QDataStream &stream) const | 267 | + void store(QDataStream &stream, bool force) const |
| 268 | { | 268 | { |
| 269 | - distance->store(stream); | 269 | + distance->store(stream, force); |
| 270 | stream << min << max << mean << stddev; | 270 | stream << min << max << mean << stddev; |
| 271 | } | 271 | } |
| 272 | 272 | ||
| @@ -335,11 +335,11 @@ class HeatMapDistance : public Distance | @@ -335,11 +335,11 @@ class HeatMapDistance : public Distance | ||
| 335 | } | 335 | } |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | - void store(QDataStream &stream) const | 338 | + void store(QDataStream &stream, bool force) const |
| 339 | { | 339 | { |
| 340 | stream << distances.size(); | 340 | stream << distances.size(); |
| 341 | foreach (Distance *distance, distances) | 341 | foreach (Distance *distance, distances) |
| 342 | - distance->store(stream); | 342 | + distance->store(stream, force); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | void load(QDataStream &stream) | 345 | void load(QDataStream &stream) |
openbr/plugins/quantize.cpp
| @@ -99,7 +99,7 @@ class HistEqQuantizationTransform : public Transform | @@ -99,7 +99,7 @@ class HistEqQuantizationTransform : public Transform | ||
| 99 | } | 99 | } |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | - void store(QDataStream &stream) const | 102 | + void store(QDataStream &stream, bool force) const |
| 103 | { | 103 | { |
| 104 | stream << thresholds; | 104 | stream << thresholds; |
| 105 | } | 105 | } |
| @@ -174,7 +174,7 @@ class BayesianQuantizationDistance : public Distance | @@ -174,7 +174,7 @@ class BayesianQuantizationDistance : public Distance | ||
| 174 | return likelihood; | 174 | return likelihood; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | - void store(QDataStream &stream) const | 177 | + void store(QDataStream &stream, bool force) const |
| 178 | { | 178 | { |
| 179 | stream << loglikelihoods; | 179 | stream << loglikelihoods; |
| 180 | } | 180 | } |
| @@ -527,7 +527,7 @@ private: | @@ -527,7 +527,7 @@ private: | ||
| 527 | dst.m().at<uchar>(0,sizeof(quint16)+i) = getIndex(m.colRange(max(0, i*step-offset), (i+1)*step-offset), centers[i]); | 527 | dst.m().at<uchar>(0,sizeof(quint16)+i) = getIndex(m.colRange(max(0, i*step-offset), (i+1)*step-offset), centers[i]); |
| 528 | } | 528 | } |
| 529 | 529 | ||
| 530 | - void store(QDataStream &stream) const | 530 | + void store(QDataStream &stream, bool force) const |
| 531 | { | 531 | { |
| 532 | stream << index << centers << ProductQuantizationLUTs[index]; | 532 | stream << index << centers << ProductQuantizationLUTs[index]; |
| 533 | } | 533 | } |
openbr/plugins/quantize2.cpp
| @@ -104,7 +104,7 @@ class BayesianQuantizationTransform : public Transform | @@ -104,7 +104,7 @@ class BayesianQuantizationTransform : public Transform | ||
| 104 | } | 104 | } |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | - void store(QDataStream &stream) const | 107 | + void store(QDataStream &stream, bool force) const |
| 108 | { | 108 | { |
| 109 | stream << thresholds; | 109 | stream << thresholds; |
| 110 | } | 110 | } |
openbr/plugins/random.cpp
| @@ -78,7 +78,7 @@ class RndSubspaceTransform : public Transform | @@ -78,7 +78,7 @@ class RndSubspaceTransform : public Transform | ||
| 78 | remap(src, dst, map, Mat(), INTER_NEAREST); | 78 | remap(src, dst, map, Mat(), INTER_NEAREST); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | - void store(QDataStream &stream) const | 81 | + void store(QDataStream &stream, bool force) const |
| 82 | { | 82 | { |
| 83 | stream << fraction << weighted << map; | 83 | stream << fraction << weighted << map; |
| 84 | } | 84 | } |
openbr/plugins/slidingwindow.cpp
| @@ -79,9 +79,9 @@ private: | @@ -79,9 +79,9 @@ private: | ||
| 79 | } | 79 | } |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | - void store(QDataStream &stream) const | 82 | + void store(QDataStream &stream, bool force) const |
| 83 | { | 83 | { |
| 84 | - transform->store(stream); | 84 | + transform->store(stream, force); |
| 85 | stream << windowHeight; | 85 | stream << windowHeight; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| @@ -289,9 +289,9 @@ private: | @@ -289,9 +289,9 @@ private: | ||
| 289 | } | 289 | } |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | - void store(QDataStream &stream) const | 292 | + void store(QDataStream &stream, bool force) const |
| 293 | { | 293 | { |
| 294 | - transform->store(stream); | 294 | + transform->store(stream, force); |
| 295 | stream << aspectRatio << windowHeight; | 295 | stream << aspectRatio << windowHeight; |
| 296 | } | 296 | } |
| 297 | void load(QDataStream &stream) | 297 | void load(QDataStream &stream) |
openbr/plugins/svm.cpp
| @@ -172,7 +172,7 @@ private: | @@ -172,7 +172,7 @@ private: | ||
| 172 | dst.file.set(outputVariable, reverseLookup[prediction]); | 172 | dst.file.set(outputVariable, reverseLookup[prediction]); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | - void store(QDataStream &stream) const | 175 | + void store(QDataStream &stream, bool force) const |
| 176 | { | 176 | { |
| 177 | storeSVM(svm, stream); | 177 | storeSVM(svm, stream); |
| 178 | stream << labelMap << reverseLookup; | 178 | stream << labelMap << reverseLookup; |
| @@ -270,7 +270,7 @@ private: | @@ -270,7 +270,7 @@ private: | ||
| 270 | return svm.predict(delta.reshape(1, 1)); | 270 | return svm.predict(delta.reshape(1, 1)); |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | - void store(QDataStream &stream) const | 273 | + void store(QDataStream &stream, bool force) const |
| 274 | { | 274 | { |
| 275 | storeSVM(svm, stream); | 275 | storeSVM(svm, stream); |
| 276 | } | 276 | } |
openbr/plugins/validate.cpp
| @@ -114,11 +114,11 @@ class CrossValidateTransform : public MetaTransform | @@ -114,11 +114,11 @@ class CrossValidateTransform : public MetaTransform | ||
| 114 | transforms[partition]->project(src, dst); | 114 | transforms[partition]->project(src, dst); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | - void store(QDataStream &stream) const | 117 | + void store(QDataStream &stream, bool force) const |
| 118 | { | 118 | { |
| 119 | stream << transforms.size(); | 119 | stream << transforms.size(); |
| 120 | foreach (Transform *transform, transforms) | 120 | foreach (Transform *transform, transforms) |
| 121 | - transform->store(stream); | 121 | + transform->store(stream, force); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | void load(QDataStream &stream) | 124 | void load(QDataStream &stream) |