diff --git a/openbr/core/bee.cpp b/openbr/core/bee.cpp index 9639657..9428b34 100644 --- a/openbr/core/bee.cpp +++ b/openbr/core/bee.cpp @@ -287,8 +287,8 @@ cv::Mat BEE::makeMask(const br::FileList &targets, const br::FileList &queries, Mask_t val; if (fileA == fileB) val = DontCare; - else if (labelA == "-1") val = DontCare; - else if (labelB == "-1") val = DontCare; + else if (labelA == "-1") val = DontCare; + else if (labelB == "-1") val = DontCare; else if (partitionA != partition) val = DontCare; else if (partitionB == -1) val = NonMatch; else if (partitionB != partition) val = DontCare; diff --git a/openbr/openbr_plugin.cpp b/openbr/openbr_plugin.cpp index d1ee53a..d66b5d7 100644 --- a/openbr/openbr_plugin.cpp +++ b/openbr/openbr_plugin.cpp @@ -388,23 +388,31 @@ TemplateList TemplateList::fromGallery(const br::File &gallery) const int crossValidate = gallery.get("crossValidate"); if (gallery.getBool("leaveOneOut")) { - QStringList subjects; - for (int i = 0; i < newTemplates.size(); i++) { - QString subject = newTemplates.at(i).file.get("Label"); + QStringList labels; + for (int i=newTemplates.size()-1; i>=0; i--) { + newTemplates[i].file.set("Index", i+templates.size()); + newTemplates[i].file.set("Gallery", gallery.name); + + QString label = newTemplates.at(i).file.get("Label"); // Have we seen this subject before? - if (subjects.contains(subject)) { - subjects.append(subject); + if (!labels.contains(label)) { + labels.append(label); // Get indices belonging to this subject - QList subjectIndices = newTemplates.find("Label",subject); - for (int j = 0; j < subjectIndices.size(); j++) { + QList labelIndices = newTemplates.find("Label",label); + for (int j = 0; j < labelIndices.size(); j++) { // Set subject partitions - newTemplates[subjectIndices[j]].file.set("Partition",j); + newTemplates[labelIndices[j]].file.set("Partition",j%crossValidate); } - // Generate more templates if necessary - for (int j=0; j("Partition")) { + leaveOneOutTemplate.file.set("Partition", k); + leaveOneOutTemplate.file.set("testOnly", true); + newTemplates.insert(i+1,leaveOneOutTemplate); + } + } } } } diff --git a/openbr/plugins/stasm4.cpp b/openbr/plugins/stasm4.cpp index 9c9dd41..fa7f271 100644 --- a/openbr/plugins/stasm4.cpp +++ b/openbr/plugins/stasm4.cpp @@ -36,8 +36,8 @@ class StasmInitializer : public Initializer void initialize() const { - Globals->abbreviations.insert("RectFromStasmEyes","RectFromPoints([29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],0.125,6.0)+Resize(44,164)"); - Globals->abbreviations.insert("RectFromStasmBrow","RectFromPoints([17, 18, 19, 20, 21, 22, 23, 24],0.15,6)+Resize(28,132)"); + Globals->abbreviations.insert("RectFromStasmEyes","RectFromPoints([29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],0.125,6.0)"); + Globals->abbreviations.insert("RectFromStasmBrow","RectFromPoints([16,17,18,19,20,21,22,23,24,25,26,27],0.15,5)"); Globals->abbreviations.insert("RectFromStasmNose","RectFromPoints([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58],0.15,1.25)"); Globals->abbreviations.insert("RectFromStasmMouth","RectFromPoints([59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76],0.3,2.5)"); } diff --git a/openbr/plugins/validate.cpp b/openbr/plugins/validate.cpp index 4f33d58..49ad04f 100644 --- a/openbr/plugins/validate.cpp +++ b/openbr/plugins/validate.cpp @@ -11,6 +11,7 @@ namespace br * \ingroup transforms * \brief Cross validate a trainable transform. * \author Josh Klontz \cite jklontz + * \author Scott Klum \cite sklum * \note To use an extended gallery, add an allPartitions="true" flag to the gallery sigset for those images that should be compared * against for all testing partitions. */ @@ -43,22 +44,46 @@ class CrossValidateTransform : public MetaTransform QFutureSynchronizer futures; for (int i=0; i partitionsBuffer = partitions; TemplateList partitionedData = data; - QList removed; - for (int j=partitionedData.size()-1; j>=0; j--) + int j = partitionedData.size()-1; + while (j>=0) { // Remove all templates belonging to partition i // if leaveOneOut is true, // and i is greater than the number of images for a particular subject // even if the partitions are different if (leaveOneOut) { - QList subjectIndices = partitionedData.find("Subject",partitionedData.at(j).file.get("Subject")); - if (i > subjectIndices.size()) removed.append(subjectIndices[i%subjectIndices.size()]); - } else if (partitions[j] == i) - removed.append(j); - typedef QPair Pair; - foreach (const Pair &pair, Common::Sort(removed,true)) partitionedData.removeAt(pair.first); + const QString label = partitionedData.at(j).file.get("Label"); + QList subjectIndices = partitionedData.find("Label",label); + QList removed; + // Remove test only data + for (int k=subjectIndices.size()-1; k>=0; k--) + if (partitionedData[subjectIndices[k]].file.getBool("testOnly")) { + removed.append(subjectIndices[k]); + subjectIndices.removeAt(k); + } + // Remove template that was repeated to make the testOnly template + if (subjectIndices.size() > 1 && subjectIndices.size() <= i) { + removed.append(subjectIndices[i%subjectIndices.size()]); + } + else if (partitionsBuffer[j] == i) { + removed.append(j); + } + + if (!removed.empty()) { + typedef QPair Pair; + foreach (Pair pair, Common::Sort(removed,true)) { + partitionedData.removeAt(pair.first); partitionsBuffer.removeAt(pair.first); j--; + } + } else { + j--; + } + } else if (partitions[j] == i) { + partitionedData.removeAt(j); + } else j--; + } // Train on the remaining templates - foreach (const Template &t, partitionedData) qDebug() << "Remaining data for partition " << i << ": " << t.file.baseName(); + foreach (const Template &t, partitionedData) qDebug() << "Remaining data for partition " << i << t.file.baseName() << t.file.get("Label") << t.file.get("Partition"); futures.addFuture(QtConcurrent::run(transforms[i], &Transform::train, partitionedData)); } futures.waitForFinished();