Commit e443d2244ccddf56b2e60f0ea898bfa70db5575f

Authored by Scott Klum
2 parents 90961a27 30c65225

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

app/examples/age_estimation.cpp
@@ -29,9 +29,7 @@ @@ -29,9 +29,7 @@
29 29
30 static void printTemplate(const br::Template &t) 30 static void printTemplate(const br::Template &t)
31 { 31 {
32 - printf("%s age: %d\n",  
33 - qPrintable(t.file.fileName()),  
34 - t.file.get<int>("Label")); 32 + printf("%s age: %d\n", qPrintable(t.file.fileName()), int(t.file.label()));
35 } 33 }
36 34
37 int main(int argc, char *argv[]) 35 int main(int argc, char *argv[])
app/examples/face_recognition_evaluation.cpp
@@ -55,14 +55,12 @@ int main(int argc, char *argv[]) @@ -55,14 +55,12 @@ int main(int argc, char *argv[])
55 55
56 // Evaluate the performance of OpenBR's FaceRecognition and a COTS face recognition system. 56 // Evaluate the performance of OpenBR's FaceRecognition and a COTS face recognition system.
57 br_eval("FaceRecognition_MEDS.mtx", "MEDS.mask", "Algorithm_Dataset/FaceRecognition_MEDS.csv"); 57 br_eval("FaceRecognition_MEDS.mtx", "MEDS.mask", "Algorithm_Dataset/FaceRecognition_MEDS.csv");
58 - br_eval("../data/MEDS/simmat/COTS_MEDS.mtx", "MEDS.mask", "Algorithm_Dataset/COTS_MEDS.csv");  
59 58
60 // The '_' character has special significance and is used to populate plot legends. 59 // The '_' character has special significance and is used to populate plot legends.
61 // Requires R installation, see documentation of br_plot for details. 60 // Requires R installation, see documentation of br_plot for details.
62 - const char *files[2]; 61 + const char *files[1];
63 files[0] = "Algorithm_Dataset/FaceRecognition_MEDS.csv"; 62 files[0] = "Algorithm_Dataset/FaceRecognition_MEDS.csv";
64 - files[1] = "Algorithm_Dataset/COTS_MEDS.csv";  
65 - br_plot(2, files, "MEDS", true); 63 + br_plot(1, files, "MEDS", true);
66 64
67 br_finalize(); 65 br_finalize();
68 return 0; 66 return 0;
app/examples/gender_estimation.cpp
@@ -29,9 +29,7 @@ @@ -29,9 +29,7 @@
29 29
30 static void printTemplate(const br::Template &t) 30 static void printTemplate(const br::Template &t)
31 { 31 {
32 - printf("%s gender: %s\n",  
33 - qPrintable(t.file.fileName()),  
34 - t.file.get<int>("Label") == 1 ? "Female" : "Male"); 32 + printf("%s gender: %s\n", qPrintable(t.file.fileName()), t.file.label() == 1 ? "Female" : "Male");
35 } 33 }
36 34
37 int main(int argc, char *argv[]) 35 int main(int argc, char *argv[])
openbr/core/bee.cpp
@@ -58,24 +58,18 @@ FileList BEE::readSigset(const QString &amp;sigset, bool ignoreMetadata) @@ -58,24 +58,18 @@ FileList BEE::readSigset(const QString &amp;sigset, bool ignoreMetadata)
58 QString name = d.attribute("name"); 58 QString name = d.attribute("name");
59 while (!fileNode.isNull()) { 59 while (!fileNode.isNull()) {
60 // Looping through files 60 // Looping through files
61 - File file; 61 + File file("", name);
62 62
63 QDomElement e = fileNode.toElement(); 63 QDomElement e = fileNode.toElement();
64 QDomNamedNodeMap attributes = e.attributes(); 64 QDomNamedNodeMap attributes = e.attributes();
65 for (int i=0; i<attributes.length(); i++) { 65 for (int i=0; i<attributes.length(); i++) {
66 - QString key = attributes.item(i).nodeName();  
67 - QString value = attributes.item(i).nodeValue();  
68 -  
69 - if (key == "file-name") {  
70 - File newFile(value, name);  
71 - newFile.append(file);  
72 - file = newFile;  
73 - } else if (!ignoreMetadata) {  
74 - file.set(key, value);  
75 - } 66 + const QString key = attributes.item(i).nodeName();
  67 + const QString value = attributes.item(i).nodeValue();
  68 + if (key == "file-name") file.name = value;
  69 + else if (!ignoreMetadata) file.set(key, value);
76 } 70 }
77 71
78 - if (file.isNull()) qFatal("Empty file-name in %s.", qPrintable(sigset)); 72 + if (file.name.isEmpty()) qFatal("Missing file-name in %s.", qPrintable(sigset));
79 fileList.append(file); 73 fileList.append(file);
80 74
81 fileNode = fileNode.nextSibling(); 75 fileNode = fileNode.nextSibling();
@@ -99,7 +93,7 @@ void BEE::writeSigset(const QString &amp;sigset, const br::FileList &amp;files, bool ign @@ -99,7 +93,7 @@ void BEE::writeSigset(const QString &amp;sigset, const br::FileList &amp;files, bool ign
99 QStringList metadata; 93 QStringList metadata;
100 if (!ignoreMetadata) 94 if (!ignoreMetadata)
101 foreach (const QString &key, file.localKeys()) { 95 foreach (const QString &key, file.localKeys()) {
102 - if ((key == "Index") || (key == "Label")) continue; 96 + if ((key == "Index") || (key == "Subject")) continue;
103 metadata.append(key+"=\""+QtUtils::toString(file.value(key))+"\""); 97 metadata.append(key+"=\""+QtUtils::toString(file.value(key))+"\"");
104 } 98 }
105 lines.append("\t<biometric-signature name=\"" + file.subject() +"\">"); 99 lines.append("\t<biometric-signature name=\"" + file.subject() +"\">");
openbr/core/classify.cpp
@@ -56,7 +56,7 @@ void br::EvalClassification(const QString &amp;predictedInput, const QString &amp;truthI @@ -56,7 +56,7 @@ void br::EvalClassification(const QString &amp;predictedInput, const QString &amp;truthI
56 } 56 }
57 } 57 }
58 58
59 - QSharedPointer<Output> output(Output::make("", FileList() << "Label" << "Count" << "Precision" << "Recall" << "F-score", FileList(counters.size()))); 59 + QSharedPointer<Output> output(Output::make("", FileList() << "Subject" << "Count" << "Precision" << "Recall" << "F-score", FileList(counters.size())));
60 60
61 int tpc = 0; 61 int tpc = 0;
62 int fnc = 0; 62 int fnc = 0;
openbr/core/core.cpp
@@ -77,7 +77,7 @@ struct AlgorithmCore @@ -77,7 +77,7 @@ struct AlgorithmCore
77 const bool hasComparer = !distance.isNull(); 77 const bool hasComparer = !distance.isNull();
78 out << hasComparer; 78 out << hasComparer;
79 if (hasComparer) distance->store(out); 79 if (hasComparer) distance->store(out);
80 - out << Globals->classes; 80 + out << Globals->subjects;
81 81
82 // Compress and save to file 82 // Compress and save to file
83 QtUtils::writeFile(model, data, -1); 83 QtUtils::writeFile(model, data, -1);
@@ -97,7 +97,7 @@ struct AlgorithmCore @@ -97,7 +97,7 @@ struct AlgorithmCore
97 transform->load(in); 97 transform->load(in);
98 bool hasDistance; in >> hasDistance; 98 bool hasDistance; in >> hasDistance;
99 if (hasDistance) distance->load(in); 99 if (hasDistance) distance->load(in);
100 - in >> Globals->classes; 100 + in >> Globals->subjects;
101 } 101 }
102 102
103 File getMemoryGallery(const File &file) const 103 File getMemoryGallery(const File &file) const
openbr/gui/classifier.cpp
@@ -44,13 +44,13 @@ void Classifier::_classify(File file) @@ -44,13 +44,13 @@ void Classifier::_classify(File file)
44 44
45 if (algorithm == "GenderClassification") { 45 if (algorithm == "GenderClassification") {
46 key = "Gender"; 46 key = "Gender";
47 - value = (f.get<int>("Label", 0) == 0 ? "Male" : "Female"); 47 + value = (f.label() == 0 ? "Male" : "Female");
48 } else if (algorithm == "AgeRegression") { 48 } else if (algorithm == "AgeRegression") {
49 key = "Age"; 49 key = "Age";
50 - value = QString::number(int(f.get<float>("Label", 0)+0.5)) + " Years"; 50 + value = QString::number(int(f.label()+0.5)) + " Years";
51 } else { 51 } else {
52 key = algorithm; 52 key = algorithm;
53 - value = f.get<QString>("Label"); 53 + value = QString::number(f.label());
54 } 54 }
55 break; 55 break;
56 } 56 }
openbr/openbr_plugin.cpp
@@ -132,33 +132,11 @@ QVariant File::parse(const QString &amp;value) @@ -132,33 +132,11 @@ QVariant File::parse(const QString &amp;value)
132 if (ok) return point; 132 if (ok) return point;
133 const QRectF rect = QtUtils::toRect(value, &ok); 133 const QRectF rect = QtUtils::toRect(value, &ok);
134 if (ok) return rect; 134 if (ok) return rect;
135 -  
136 - /* We assume that if the value starts with '0'  
137 - then it was probably intended to be a string UID  
138 - and that it's numerical value is not relevant. */  
139 - if (!value.startsWith('0') || (value == "0")) {  
140 - const float f = value.toFloat(&ok);  
141 - if (ok) return f;  
142 - }  
143 - 135 + const float f = value.toFloat(&ok);
  136 + if (ok) return f;
144 return value; 137 return value;
145 } 138 }
146 139
147 -void File::set(const QString &key, const QVariant &value)  
148 -{  
149 - if (key == "Label") {  
150 - const QString valueString = value.toString();  
151 - if (!Globals->classes.contains(valueString)) {  
152 - static QMutex mutex;  
153 - QMutexLocker mutexLocker(&mutex);  
154 - if (!Globals->classes.contains(valueString))  
155 - Globals->classes.insert(valueString, Globals->classes.size());  
156 - }  
157 - }  
158 -  
159 - m_metadata.insert(key, value);  
160 -}  
161 -  
162 void File::set(const QString &key, const QString &value) 140 void File::set(const QString &key, const QString &value)
163 { 141 {
164 if (value.startsWith('[') && value.endsWith(']')) { 142 if (value.startsWith('[') && value.endsWith(']')) {
@@ -179,22 +157,27 @@ bool File::getBool(const QString &amp;key, bool defaultValue) const @@ -179,22 +157,27 @@ bool File::getBool(const QString &amp;key, bool defaultValue) const
179 return variant.value<bool>(); 157 return variant.value<bool>();
180 } 158 }
181 159
182 -QString File::subject(int label) 160 +QString File::subject() const
183 { 161 {
184 - return Globals->classes.key(label, QString::number(label)); 162 + const QVariant l = m_metadata.value("Label");
  163 + if (!l.isNull()) return Globals->subjects.key(l.toFloat(), l.toString());
  164 + return m_metadata.value("Subject").toString();
185 } 165 }
186 166
187 float File::label() const 167 float File::label() const
188 { 168 {
189 - const QVariant variant = value("Label");  
190 - if (variant.isNull()) return -1; 169 + const QVariant l = m_metadata.value("Label");
  170 + if (!l.isNull()) return l.toFloat();
191 171
192 - if (Globals->classes.contains(variant.toString()))  
193 - return Globals->classes.value(variant.toString()); 172 + const QVariant s = m_metadata.value("Subject");
  173 + if (s.isNull()) return -1;
194 174
195 - bool ok;  
196 - const float val = variant.toFloat(&ok);  
197 - return ok ? val : -1; 175 + const QString subject = s.toString();
  176 + static QMutex mutex;
  177 + QMutexLocker mutexLocker(&mutex);
  178 + if (!Globals->subjects.contains(subject))
  179 + Globals->subjects.insert(subject, Globals->subjects.size());
  180 + return Globals->subjects.value(subject);
198 } 181 }
199 182
200 QList<QPointF> File::namedPoints() const 183 QList<QPointF> File::namedPoints() const
@@ -310,8 +293,6 @@ QDataStream &amp;br::operator&lt;&lt;(QDataStream &amp;stream, const File &amp;file) @@ -310,8 +293,6 @@ QDataStream &amp;br::operator&lt;&lt;(QDataStream &amp;stream, const File &amp;file)
310 QDataStream &br::operator>>(QDataStream &stream, File &file) 293 QDataStream &br::operator>>(QDataStream &stream, File &file)
311 { 294 {
312 return stream >> file.name >> file.m_metadata; 295 return stream >> file.name >> file.m_metadata;
313 - const QVariant label = file.m_metadata.value("Label");  
314 - if (!label.isNull()) file.set("Label", label); // Trigger population of Globals->classes  
315 } 296 }
316 297
317 /* FileList - public methods */ 298 /* FileList - public methods */
@@ -464,14 +445,15 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery) @@ -464,14 +445,15 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery)
464 445
465 TemplateList TemplateList::relabel(const TemplateList &tl) 446 TemplateList TemplateList::relabel(const TemplateList &tl)
466 { 447 {
467 - QHash<int,int> labels;  
468 - foreach (int label, tl.labels<int>())  
469 - if (!labels.contains(label))  
470 - labels.insert(label, labels.size()); 448 + const QList<int> originalLabels = tl.labels<int>();
  449 + QHash<int,int> labelTable;
  450 + foreach (int label, originalLabels)
  451 + if (!labelTable.contains(label))
  452 + labelTable.insert(label, labelTable.size());
471 453
472 TemplateList result = tl; 454 TemplateList result = tl;
473 for (int i=0; i<result.size(); i++) 455 for (int i=0; i<result.size(); i++)
474 - result[i].file.setLabel(labels[result[i].file.label()]); 456 + result[i].file.set("Label", labelTable[originalLabels[i]]);
475 return result; 457 return result;
476 } 458 }
477 459
@@ -681,12 +663,17 @@ void Object::setProperty(const QString &amp;name, const QString &amp;value) @@ -681,12 +663,17 @@ void Object::setProperty(const QString &amp;name, const QString &amp;value)
681 variant = value; 663 variant = value;
682 } 664 }
683 665
684 - if (!QObject::setProperty(qPrintable(name), variant) && !type.isEmpty())  
685 - qFatal("Failed to set %s::%s to: %s %s",  
686 - metaObject()->className(), qPrintable(name), qPrintable(value), qPrintable(type)); 666 + setProperty(name, variant, !type.isEmpty());
  667 +}
  668 +
  669 +void Object::setProperty(const QString &name, const QVariant &value, bool failOnError)
  670 +{
  671 + if (!QObject::setProperty(qPrintable(name), value) && failOnError)
  672 + qFatal("Failed to set %s::%s to: %s",
  673 + metaObject()->className(), qPrintable(name), qPrintable(value.toString()));
687 } 674 }
688 675
689 -QStringList br::Object::parse(const QString &string, char split) 676 +QStringList Object::parse(const QString &string, char split)
690 { 677 {
691 return QtUtils::parse(string, split); 678 return QtUtils::parse(string, split);
692 } 679 }
@@ -738,19 +725,21 @@ void Object::init(const File &amp;file_) @@ -738,19 +725,21 @@ void Object::init(const File &amp;file_)
738 } 725 }
739 726
740 foreach (QString key, file.localKeys()) { 727 foreach (QString key, file.localKeys()) {
741 - const QString value = file.value(key).toString(); 728 + const QVariant value = file.value(key);
  729 + const QString valueString = value.toString();
742 730
743 if (key.startsWith(("_Arg"))) { 731 if (key.startsWith(("_Arg"))) {
744 - int argument_number = key.mid(4).toInt();  
745 - int target_idx = argument_number + firstAvailablePropertyIdx;  
746 -  
747 - if (target_idx >= metaObject()->propertyCount()) {  
748 - qWarning("too many arguments for transform, ignoring %s\n", qPrintable(value)); 732 + int argumentNumber = key.mid(4).toInt();
  733 + int targetIdx = argumentNumber + firstAvailablePropertyIdx;
  734 + if (targetIdx >= metaObject()->propertyCount()) {
  735 + qWarning("too many arguments for transform %s, ignoring %s", qPrintable(objectName()), qPrintable(valueString));
749 continue; 736 continue;
750 } 737 }
751 - key = metaObject()->property(target_idx).name(); 738 + key = metaObject()->property(targetIdx).name();
752 } 739 }
753 - setProperty(key, value); 740 +
  741 + if (valueString.isEmpty()) setProperty(key, value); // Set the property directly
  742 + else setProperty(key, valueString); // Parse the value first
754 } 743 }
755 744
756 init(); 745 init();
@@ -1038,8 +1027,10 @@ MatrixOutput *MatrixOutput::make(const FileList &amp;targetFiles, const FileList &amp;qu @@ -1038,8 +1027,10 @@ MatrixOutput *MatrixOutput::make(const FileList &amp;targetFiles, const FileList &amp;qu
1038 /* MatrixOutput - protected methods */ 1027 /* MatrixOutput - protected methods */
1039 QString MatrixOutput::toString(int row, int column) const 1028 QString MatrixOutput::toString(int row, int column) const
1040 { 1029 {
1041 - if (targetFiles[column] == "Label")  
1042 - return File::subject(data.at<float>(row,column)); 1030 + if (targetFiles[column] == "Label") {
  1031 + const int label = data.at<float>(row,column);
  1032 + return Globals->subjects.key(label, QString::number(label));
  1033 + }
1043 return QString::number(data.at<float>(row,column)); 1034 return QString::number(data.at<float>(row,column));
1044 } 1035 }
1045 1036
@@ -1085,153 +1076,6 @@ Gallery *Gallery::make(const File &amp;file) @@ -1085,153 +1076,6 @@ Gallery *Gallery::make(const File &amp;file)
1085 return gallery; 1076 return gallery;
1086 } 1077 }
1087 1078
1088 -static TemplateList Downsample(const TemplateList &templates, const Transform *transform)  
1089 -{  
1090 - // Return early when no downsampling is required  
1091 - if ((transform->classes == std::numeric_limits<int>::max()) &&  
1092 - (transform->instances == std::numeric_limits<int>::max()) &&  
1093 - (transform->fraction >= 1))  
1094 - return templates;  
1095 -  
1096 - const bool atLeast = transform->instances < 0;  
1097 - const int instances = abs(transform->instances);  
1098 -  
1099 - QList<int> allLabels = templates.labels<int>();  
1100 - QList<int> uniqueLabels = allLabels.toSet().toList();  
1101 - qSort(uniqueLabels);  
1102 -  
1103 - QMap<int,int> counts = templates.labelCounts(instances != std::numeric_limits<int>::max());  
1104 - if ((instances != std::numeric_limits<int>::max()) && (transform->classes != std::numeric_limits<int>::max()))  
1105 - foreach (int label, counts.keys())  
1106 - if (counts[label] < instances)  
1107 - counts.remove(label);  
1108 - uniqueLabels = counts.keys();  
1109 - if ((transform->classes != std::numeric_limits<int>::max()) && (uniqueLabels.size() < transform->classes))  
1110 - qWarning("Downsample requested %d classes but only %d are available.", transform->classes, uniqueLabels.size());  
1111 -  
1112 - Common::seedRNG();  
1113 - QList<int> selectedLabels = uniqueLabels;  
1114 - if (transform->classes < uniqueLabels.size()) {  
1115 - std::random_shuffle(selectedLabels.begin(), selectedLabels.end());  
1116 - selectedLabels = selectedLabels.mid(0, transform->classes);  
1117 - }  
1118 -  
1119 - TemplateList downsample;  
1120 - for (int i=0; i<selectedLabels.size(); i++) {  
1121 - const int selectedLabel = selectedLabels[i];  
1122 - QList<int> indices;  
1123 - for (int j=0; j<allLabels.size(); j++)  
1124 - if ((allLabels[j] == selectedLabel) && (!templates.value(j).file.get<bool>("FTE", false)))  
1125 - indices.append(j);  
1126 -  
1127 - std::random_shuffle(indices.begin(), indices.end());  
1128 - const int max = atLeast ? indices.size() : std::min(indices.size(), instances);  
1129 - for (int j=0; j<max; j++)  
1130 - downsample.append(templates.value(indices[j]));  
1131 - }  
1132 -  
1133 - if (transform->fraction < 1) {  
1134 - std::random_shuffle(downsample.begin(), downsample.end());  
1135 - downsample = downsample.mid(0, downsample.size()*transform->fraction);  
1136 - }  
1137 -  
1138 - return downsample;  
1139 -}  
1140 -  
1141 -/*!  
1142 - * \ingroup transforms  
1143 - * \brief Clones the transform so that it can be applied independently.  
1144 - *  
1145 - * \em Independent transforms expect single-matrix templates.  
1146 - */  
1147 -class Independent : public MetaTransform  
1148 -{  
1149 - Q_PROPERTY(QList<Transform*> transforms READ get_transforms WRITE set_transforms STORED false)  
1150 - BR_PROPERTY(QList<Transform*>, transforms, QList<Transform*>())  
1151 -  
1152 - public:  
1153 - /*!  
1154 - * \brief Independent  
1155 - * \param transform  
1156 - */  
1157 - Independent(Transform *transform)  
1158 - {  
1159 - transform->setParent(this);  
1160 - transforms.append(transform);  
1161 - file = transform->file;  
1162 - trainable = transform->trainable;  
1163 - setObjectName(transforms.first()->objectName());  
1164 - }  
1165 -  
1166 -private:  
1167 - Transform *clone() const  
1168 - {  
1169 - return new Independent(transforms.first()->clone());  
1170 - }  
1171 -  
1172 - static void _train(Transform *transform, const TemplateList *data)  
1173 - {  
1174 - transform->train(*data);  
1175 - }  
1176 -  
1177 - void train(const TemplateList &data)  
1178 - {  
1179 - // Don't bother if the transform is untrainable  
1180 - if (!trainable) return;  
1181 -  
1182 - QList<TemplateList> templatesList;  
1183 - foreach (const Template &t, data) {  
1184 - if ((templatesList.size() != t.size()) && !templatesList.isEmpty())  
1185 - qWarning("Independent::train template %s of size %d differs from expected size %d.", qPrintable(t.file.name), t.size(), templatesList.size());  
1186 - while (templatesList.size() < t.size())  
1187 - templatesList.append(TemplateList());  
1188 - for (int i=0; i<t.size(); i++)  
1189 - templatesList[i].append(Template(t.file, t[i]));  
1190 - }  
1191 -  
1192 - while (transforms.size() < templatesList.size())  
1193 - transforms.append(transforms.first()->clone());  
1194 -  
1195 - for (int i=0; i<templatesList.size(); i++)  
1196 - templatesList[i] = Downsample(templatesList[i], transforms[i]);  
1197 -  
1198 - QFutureSynchronizer<void> futures;  
1199 - for (int i=0; i<templatesList.size(); i++)  
1200 - futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i]));  
1201 - futures.waitForFinished();  
1202 - }  
1203 -  
1204 - void project(const Template &src, Template &dst) const  
1205 - {  
1206 - dst.file = src.file;  
1207 - QList<Mat> mats;  
1208 - for (int i=0; i<src.size(); i++) {  
1209 - transforms[i%transforms.size()]->project(Template(src.file, src[i]), dst);  
1210 - mats.append(dst);  
1211 - dst.clear();  
1212 - }  
1213 - dst.append(mats);  
1214 - }  
1215 -  
1216 - void store(QDataStream &stream) const  
1217 - {  
1218 - const int size = transforms.size();  
1219 - stream << size;  
1220 - for (int i=0; i<size; i++)  
1221 - transforms[i]->store(stream);  
1222 - }  
1223 -  
1224 - void load(QDataStream &stream)  
1225 - {  
1226 - int size;  
1227 - stream >> size;  
1228 - while (transforms.size() < size)  
1229 - transforms.append(transforms.first()->clone());  
1230 - for (int i=0; i<size; i++)  
1231 - transforms[i]->load(stream);  
1232 - }  
1233 -};  
1234 -  
1235 /* Transform - public methods */ 1079 /* Transform - public methods */
1236 Transform::Transform(bool _independent, bool _trainable) 1080 Transform::Transform(bool _independent, bool _trainable)
1237 { 1081 {
@@ -1279,8 +1123,17 @@ Transform *Transform::make(QString str, QObject *parent) @@ -1279,8 +1123,17 @@ Transform *Transform::make(QString str, QObject *parent)
1279 File f = "." + str; 1123 File f = "." + str;
1280 Transform *transform = Factory<Transform>::make(f); 1124 Transform *transform = Factory<Transform>::make(f);
1281 1125
1282 - if (transform->independent)  
1283 - transform = new Independent(transform); 1126 + if (transform->independent) {
  1127 +// Transform *independentTransform = Factory<Transform>::make(".Independent");
  1128 +// static_cast<QObject*>(independentTransform)->setProperty("transform", qVariantFromValue<void*>(transform));
  1129 +// independentTransform->init();
  1130 +// transform = independentTransform;
  1131 +
  1132 + File independent(".Independent");
  1133 + independent.set("transform", qVariantFromValue<void*>(transform));
  1134 + transform = Factory<Transform>::make(independent);
  1135 + }
  1136 +
1284 transform->setParent(parent); 1137 transform->setParent(parent);
1285 return transform; 1138 return transform;
1286 } 1139 }
openbr/openbr_plugin.h
@@ -107,11 +107,11 @@ void reset_##NAME() { NAME = DEFAULT; } @@ -107,11 +107,11 @@ void reset_##NAME() { NAME = DEFAULT; }
107 * 107 *
108 * The br::File is one of the workhorse classes in OpenBR. 108 * The br::File is one of the workhorse classes in OpenBR.
109 * It is typically used to store the path to a file on disk with associated metadata. 109 * It is typically used to store the path to a file on disk with associated metadata.
110 - * The ability to associate a hashtable of metadata with the file helps keep the API simple and stable while providing customizable behavior when appropriate. 110 + * The ability to associate a metadata map with the file helps keep the API simple and stable while providing customizable behavior when appropriate.
111 * 111 *
112 - * When querying the value of a metadata key, the value will first try to be resolved using the file's private metadata table.  
113 - * If the key does not exist in the local hashtable then it will be resolved using the properities in the global br::Context.  
114 - * This has the desirable effect that file metadata may optionally set globally using br::Context::set to operate on all files. 112 + * When querying the value of a metadata key, the value will first try to be resolved using the file's private metadata.
  113 + * If the key does not exist in the local map then it will be resolved using the properities in the global br::Context.
  114 + * This has the desirable effect that file metadata may optionally be set globally using br::Context::set to operate on all files.
115 * 115 *
116 * Files have a simple grammar that allow them to be converted to and from strings. 116 * Files have a simple grammar that allow them to be converted to and from strings.
117 * If a string ends with a \c ] or \c ) then the text within the final \c [] or \c () are parsed as comma sperated metadata fields. 117 * If a string ends with a \c ] or \c ) then the text within the final \c [] or \c () are parsed as comma sperated metadata fields.
@@ -119,6 +119,13 @@ void reset_##NAME() { NAME = DEFAULT; } @@ -119,6 +119,13 @@ void reset_##NAME() { NAME = DEFAULT; }
119 * Fields within \c () are expected to have the format <tt>(value1, value2, ..., valueN)</tt> with the keys determined from the order of \c Q_PROPERTY. 119 * Fields within \c () are expected to have the format <tt>(value1, value2, ..., valueN)</tt> with the keys determined from the order of \c Q_PROPERTY.
120 * The rest of the string is assigned to #name. 120 * The rest of the string is assigned to #name.
121 * 121 *
  122 + * The metadata keys \c Subject and \c Label have special significance in the system.
  123 + * \c Subject is a string specifying a unique identifier used to determine ground truth match/non-match.
  124 + * \c Label is a floating point value used for supervised learning.
  125 + * When the system needs labels for training, but only subjects are provided in the file metadata, the rule for generating labels is as follows.
  126 + * If the subject value can be converted to a float then do so and consider that the label.
  127 + * Otherwise, generate a unique integer ID for the string starting from zero and incrementing by one everytime another ID is needed.
  128 + *
122 * Metadata keys fall into one of two categories: 129 * Metadata keys fall into one of two categories:
123 * - \c camelCaseKeys are inputs that specify how to process the file. 130 * - \c camelCaseKeys are inputs that specify how to process the file.
124 * - \c Capitalized_Underscored_Keys are outputs computed from processing the file. 131 * - \c Capitalized_Underscored_Keys are outputs computed from processing the file.
@@ -129,7 +136,8 @@ void reset_##NAME() { NAME = DEFAULT; } @@ -129,7 +136,8 @@ void reset_##NAME() { NAME = DEFAULT; }
129 * --- | ---- | ----------- 136 * --- | ---- | -----------
130 * separator | QString | Seperate #name into multiple files 137 * separator | QString | Seperate #name into multiple files
131 * Index | int | Index of a template in a template list 138 * Index | int | Index of a template in a template list
132 - * Label | float | Classification/Regression class 139 + * Subject | QString | Class name
  140 + * Label | float | Class value
133 * Confidence | float | Classification/Regression quality 141 * Confidence | float | Classification/Regression quality
134 * FTE | bool | Failure to enroll 142 * FTE | bool | Failure to enroll
135 * FTO | bool | Failure to open 143 * FTO | bool | Failure to open
@@ -153,7 +161,7 @@ struct BR_EXPORT File @@ -153,7 +161,7 @@ struct BR_EXPORT File
153 161
154 File() {} 162 File() {}
155 File(const QString &file) { init(file); } /*!< \brief Construct a file from a string. */ 163 File(const QString &file) { init(file); } /*!< \brief Construct a file from a string. */
156 - File(const QString &file, const QVariant &label) { init(file); set("Label", label); } /*!< \brief Construct a file from a string and assign a label. */ 164 + File(const QString &file, const QVariant &subject) { init(file); set("Subject", subject); } /*!< \brief Construct a file from a string and assign a label. */
157 File(const char *file) { init(file); } /*!< \brief Construct a file from a c-style string. */ 165 File(const char *file) { init(file); } /*!< \brief Construct a file from a c-style string. */
158 inline operator QString() const { return name; } /*!< \brief Returns #name. */ 166 inline operator QString() const { return name; } /*!< \brief Returns #name. */
159 QString flat() const; /*!< \brief A stringified version of the file with metadata. */ 167 QString flat() const; /*!< \brief A stringified version of the file with metadata. */
@@ -195,7 +203,7 @@ struct BR_EXPORT File @@ -195,7 +203,7 @@ struct BR_EXPORT File
195 bool contains(const QString &key) const; /*!< \brief Returns \c true if the key has an associated value, \c false otherwise. */ 203 bool contains(const QString &key) const; /*!< \brief Returns \c true if the key has an associated value, \c false otherwise. */
196 QVariant value(const QString &key) const; /*!< \brief Returns the value for the specified key. */ 204 QVariant value(const QString &key) const; /*!< \brief Returns the value for the specified key. */
197 static QVariant parse(const QString &value); /*!< \brief Try to convert the QString to a QPointF or QRectF if possible. */ 205 static QVariant parse(const QString &value); /*!< \brief Try to convert the QString to a QPointF or QRectF if possible. */
198 - void set(const QString &key, const QVariant &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */ 206 + inline void set(const QString &key, const QVariant &value) { m_metadata.insert(key, value); } /*!< \brief Insert or overwrite the metadata key with the specified value. */
199 void set(const QString &key, const QString &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */ 207 void set(const QString &key, const QString &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */
200 inline void remove(const QString &key) { m_metadata.remove(key); } /*!< \brief Remove the metadata key. */ 208 inline void remove(const QString &key) { m_metadata.remove(key); } /*!< \brief Remove the metadata key. */
201 209
@@ -235,10 +243,8 @@ struct BR_EXPORT File @@ -235,10 +243,8 @@ struct BR_EXPORT File
235 return variant.value<T>(); 243 return variant.value<T>();
236 } 244 }
237 245
238 - static QString subject(int label); /*!< \brief Looks up the subject for the provided label. */  
239 - inline QString subject() const { return subject(label()); } /*!< \brief Looks up the subject from the file's label. */ 246 + QString subject() const; /*!< \brief Looks up the subject from the file's label. */
240 float label() const; /*!< \brief Convenience function for retrieving the file's \c Label. */ 247 float label() const; /*!< \brief Convenience function for retrieving the file's \c Label. */
241 - inline void setLabel(float label) { set("Label", label); } /*!< \brief Convenience function for setting the file's \c Label. */  
242 inline bool failed() const { return getBool("FTE") || getBool("FTO"); } /*!< \brief Returns \c true if the file failed to open or enroll, \c false otherwise. */ 248 inline bool failed() const { return getBool("FTE") || getBool("FTO"); } /*!< \brief Returns \c true if the file failed to open or enroll, \c false otherwise. */
243 249
244 QList<QPointF> namedPoints() const; /*!< \brief Returns points convertible from metadata keys. */ 250 QList<QPointF> namedPoints() const; /*!< \brief Returns points convertible from metadata keys. */
@@ -497,6 +503,7 @@ public: @@ -497,6 +503,7 @@ public:
497 QString argument(int index) const; /*!< \brief A string value for the argument at the specified index. */ 503 QString argument(int index) const; /*!< \brief A string value for the argument at the specified index. */
498 QString description() const; /*!< \brief Returns a string description of the object. */ 504 QString description() const; /*!< \brief Returns a string description of the object. */
499 void setProperty(const QString &name, const QString &value); /*!< \brief Overload of QObject::setProperty to handle OpenBR data types. */ 505 void setProperty(const QString &name, const QString &value); /*!< \brief Overload of QObject::setProperty to handle OpenBR data types. */
  506 + void setProperty(const QString &name, const QVariant &value, bool failOnError = false); /*!< \brief Overload of QObject::setProperty to handle OpenBR data types. */
500 static QStringList parse(const QString &string, char split = ','); /*!< \brief Splits the string while respecting lexical scoping of <tt>()</tt>, <tt>[]</tt>, <tt>\<\></tt>, and <tt>{}</tt>. */ 507 static QStringList parse(const QString &string, char split = ','); /*!< \brief Splits the string while respecting lexical scoping of <tt>()</tt>, <tt>[]</tt>, <tt>\<\></tt>, and <tt>{}</tt>. */
501 508
502 private: 509 private:
@@ -633,7 +640,7 @@ public: @@ -633,7 +640,7 @@ public:
633 BR_PROPERTY(int, crossValidate, 0) 640 BR_PROPERTY(int, crossValidate, 0)
634 641
635 QHash<QString,QString> abbreviations; /*!< \brief Used by br::Transform::make() to expand abbreviated algorithms into their complete definitions. */ 642 QHash<QString,QString> abbreviations; /*!< \brief Used by br::Transform::make() to expand abbreviated algorithms into their complete definitions. */
636 - QHash<QString,int> classes; /*!< \brief Used by classifiers to associate text class labels with unique integers IDs. */ 643 + QHash<QString,int> subjects; /*!< \brief Used by classifiers to associate text class labels with unique integers IDs. */
637 QTime startTime; /*!< \brief Used to estimate timeRemaining(). */ 644 QTime startTime; /*!< \brief Used to estimate timeRemaining(). */
638 645
639 /*! 646 /*!
openbr/plugins/gallery.cpp
@@ -37,6 +37,7 @@ namespace br @@ -37,6 +37,7 @@ namespace br
37 * \ingroup galleries 37 * \ingroup galleries
38 * \brief Weka ARFF file format. 38 * \brief Weka ARFF file format.
39 * \author Josh Klontz \cite jklontz 39 * \author Josh Klontz \cite jklontz
  40 + * http://weka.wikispaces.com/ARFF+%28stable+version%29
40 */ 41 */
41 class arffGallery : public Gallery 42 class arffGallery : public Gallery
42 { 43 {
@@ -59,19 +60,16 @@ class arffGallery : public Gallery @@ -59,19 +60,16 @@ class arffGallery : public Gallery
59 "@RELATION OpenBR\n" 60 "@RELATION OpenBR\n"
60 "\n"); 61 "\n");
61 62
62 - arffFile.write("@ATTRIBUTE filename STRING\n");  
63 - arffFile.write(qPrintable("@ATTRIBUTE class {" + QStringList(Globals->classes.keys()).join(',') + "}\n"));  
64 -  
65 const int dimensions = t.m().rows * t.m().cols; 63 const int dimensions = t.m().rows * t.m().cols;
66 for (int i=0; i<dimensions; i++) 64 for (int i=0; i<dimensions; i++)
67 - arffFile.write(qPrintable("@ATTRIBUTE v" + QString::number(i) + " NUMERIC\n")); 65 + arffFile.write(qPrintable("@ATTRIBUTE v" + QString::number(i) + " REAL\n"));
  66 + arffFile.write(qPrintable("@ATTRIBUTE class {" + QStringList(Globals->subjects.keys()).join(',') + "}\n"));
68 67
69 arffFile.write("\n@DATA\n"); 68 arffFile.write("\n@DATA\n");
70 } 69 }
71 70
72 - arffFile.write(qPrintable("'" + t.file.name + "',"));  
73 - arffFile.write(qPrintable("'" + t.file.subject() + "',"));  
74 - arffFile.write(qPrintable(OpenCVUtils::matrixToStringList(t).join(',')+"\n")); 71 + arffFile.write(qPrintable(OpenCVUtils::matrixToStringList(t).join(',')));
  72 + arffFile.write(qPrintable(",'" + t.file.subject() + "'\n"));
75 } 73 }
76 }; 74 };
77 75
@@ -117,6 +115,8 @@ class galGallery : public Gallery @@ -117,6 +115,8 @@ class galGallery : public Gallery
117 115
118 void write(const Template &t) 116 void write(const Template &t)
119 { 117 {
  118 + if (t.isEmpty() && t.file.isNull())
  119 + return;
120 stream << t; 120 stream << t;
121 } 121 }
122 }; 122 };
@@ -464,7 +464,7 @@ class csvGallery : public Gallery @@ -464,7 +464,7 @@ class csvGallery : public Gallery
464 static QString getCSVElement(const QString &key, const QVariant &value, bool header) 464 static QString getCSVElement(const QString &key, const QVariant &value, bool header)
465 { 465 {
466 if ((key == "Label") && !header) { 466 if ((key == "Label") && !header) {
467 - QString stringLabel = Globals->classes.key(value.value<int>()); 467 + QString stringLabel = Globals->subjects.key(value.value<int>());
468 if (stringLabel.isEmpty()) return value.value<QString>(); 468 if (stringLabel.isEmpty()) return value.value<QString>();
469 else return stringLabel; 469 else return stringLabel;
470 } else if (value.canConvert<QString>()) { 470 } else if (value.canConvert<QString>()) {
openbr/plugins/independent.cpp 0 โ†’ 100644
  1 +#include <QFutureSynchronizer>
  2 +#include <QtConcurrentRun>
  3 +
  4 +#include "openbr_internal.h"
  5 +#include "openbr/core/common.h"
  6 +
  7 +using namespace cv;
  8 +
  9 +namespace br
  10 +{
  11 +
  12 +static TemplateList Downsample(const TemplateList &templates, const Transform *transform)
  13 +{
  14 + // Return early when no downsampling is required
  15 + if ((transform->classes == std::numeric_limits<int>::max()) &&
  16 + (transform->instances == std::numeric_limits<int>::max()) &&
  17 + (transform->fraction >= 1))
  18 + return templates;
  19 +
  20 + const bool atLeast = transform->instances < 0;
  21 + const int instances = abs(transform->instances);
  22 +
  23 + QList<int> allLabels = templates.labels<int>();
  24 + QList<int> uniqueLabels = allLabels.toSet().toList();
  25 + qSort(uniqueLabels);
  26 +
  27 + QMap<int,int> counts = templates.labelCounts(instances != std::numeric_limits<int>::max());
  28 + if ((instances != std::numeric_limits<int>::max()) && (transform->classes != std::numeric_limits<int>::max()))
  29 + foreach (int label, counts.keys())
  30 + if (counts[label] < instances)
  31 + counts.remove(label);
  32 + uniqueLabels = counts.keys();
  33 + if ((transform->classes != std::numeric_limits<int>::max()) && (uniqueLabels.size() < transform->classes))
  34 + qWarning("Downsample requested %d classes but only %d are available.", transform->classes, uniqueLabels.size());
  35 +
  36 + Common::seedRNG();
  37 + QList<int> selectedLabels = uniqueLabels;
  38 + if (transform->classes < uniqueLabels.size()) {
  39 + std::random_shuffle(selectedLabels.begin(), selectedLabels.end());
  40 + selectedLabels = selectedLabels.mid(0, transform->classes);
  41 + }
  42 +
  43 + TemplateList downsample;
  44 + for (int i=0; i<selectedLabels.size(); i++) {
  45 + const int selectedLabel = selectedLabels[i];
  46 + QList<int> indices;
  47 + for (int j=0; j<allLabels.size(); j++)
  48 + if ((allLabels[j] == selectedLabel) && (!templates.value(j).file.get<bool>("FTE", false)))
  49 + indices.append(j);
  50 +
  51 + std::random_shuffle(indices.begin(), indices.end());
  52 + const int max = atLeast ? indices.size() : std::min(indices.size(), instances);
  53 + for (int j=0; j<max; j++)
  54 + downsample.append(templates.value(indices[j]));
  55 + }
  56 +
  57 + if (transform->fraction < 1) {
  58 + std::random_shuffle(downsample.begin(), downsample.end());
  59 + downsample = downsample.mid(0, downsample.size()*transform->fraction);
  60 + }
  61 +
  62 + return downsample;
  63 +}
  64 +
  65 +/*!
  66 + * \ingroup transforms
  67 + * \brief Clones the transform so that it can be applied independently.
  68 + * \author Josh Klontz \cite jklontz
  69 + * \em Independent transforms expect single-matrix templates.
  70 + */
  71 +class IndependentTransform : public MetaTransform
  72 +{
  73 + Q_OBJECT
  74 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform STORED false)
  75 + BR_PROPERTY(br::Transform*, transform, NULL)
  76 +
  77 + QList<Transform*> transforms;
  78 +
  79 + void init()
  80 + {
  81 + transforms.clear();
  82 + if (transform == NULL)
  83 + return;
  84 +
  85 + transform->setParent(this);
  86 + transforms.append(transform);
  87 + file = transform->file;
  88 + trainable = transform->trainable;
  89 + setObjectName(transform->objectName());
  90 + }
  91 +
  92 + Transform *clone() const
  93 + {
  94 + IndependentTransform *independentTransform = new IndependentTransform();
  95 + independentTransform->transform = transform->clone();
  96 + independentTransform->init();
  97 + return independentTransform;
  98 + }
  99 +
  100 + static void _train(Transform *transform, const TemplateList *data)
  101 + {
  102 + transform->train(*data);
  103 + }
  104 +
  105 + void train(const TemplateList &data)
  106 + {
  107 + // Don't bother if the transform is untrainable
  108 + if (!trainable) return;
  109 +
  110 + QList<TemplateList> templatesList;
  111 + foreach (const Template &t, data) {
  112 + if ((templatesList.size() != t.size()) && !templatesList.isEmpty())
  113 + qWarning("Independent::train template %s of size %d differs from expected size %d.", qPrintable(t.file.name), t.size(), templatesList.size());
  114 + while (templatesList.size() < t.size())
  115 + templatesList.append(TemplateList());
  116 + for (int i=0; i<t.size(); i++)
  117 + templatesList[i].append(Template(t.file, t[i]));
  118 + }
  119 +
  120 + while (transforms.size() < templatesList.size())
  121 + transforms.append(transform->clone());
  122 +
  123 + for (int i=0; i<templatesList.size(); i++)
  124 + templatesList[i] = Downsample(templatesList[i], transforms[i]);
  125 +
  126 + QFutureSynchronizer<void> futures;
  127 + for (int i=0; i<templatesList.size(); i++)
  128 + futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i]));
  129 + futures.waitForFinished();
  130 + }
  131 +
  132 + void project(const Template &src, Template &dst) const
  133 + {
  134 + dst.file = src.file;
  135 + QList<Mat> mats;
  136 + for (int i=0; i<src.size(); i++) {
  137 + transforms[i%transforms.size()]->project(Template(src.file, src[i]), dst);
  138 + mats.append(dst);
  139 + dst.clear();
  140 + }
  141 + dst.append(mats);
  142 + }
  143 +
  144 + void store(QDataStream &stream) const
  145 + {
  146 + const int size = transforms.size();
  147 + stream << size;
  148 + for (int i=0; i<size; i++)
  149 + transforms[i]->store(stream);
  150 + }
  151 +
  152 + void load(QDataStream &stream)
  153 + {
  154 + int size;
  155 + stream >> size;
  156 + while (transforms.size() < size)
  157 + transforms.append(transform->clone());
  158 + for (int i=0; i<size; i++)
  159 + transforms[i]->load(stream);
  160 + }
  161 +};
  162 +
  163 +BR_REGISTER(Transform, IndependentTransform)
  164 +
  165 +} // namespace br
  166 +
  167 +#include "independent.moc"
openbr/plugins/mask.cpp
@@ -171,7 +171,7 @@ class LargestConvexAreaTransform : public UntrainableTransform @@ -171,7 +171,7 @@ class LargestConvexAreaTransform : public UntrainableTransform
171 if (area / hullArea > 0.98) 171 if (area / hullArea > 0.98)
172 maxArea = std::max(maxArea, area); 172 maxArea = std::max(maxArea, area);
173 } 173 }
174 - dst.file.setLabel(maxArea); 174 + dst.file.set("Label", maxArea);
175 } 175 }
176 }; 176 };
177 177
openbr/plugins/meta.cpp
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16
17 #include <QFutureSynchronizer> 17 #include <QFutureSynchronizer>
  18 +#include <QRegularExpression>
18 #include <QtConcurrentRun> 19 #include <QtConcurrentRun>
19 #include "openbr_internal.h" 20 #include "openbr_internal.h"
20 #include "openbr/core/common.h" 21 #include "openbr/core/common.h"
@@ -440,7 +441,7 @@ private: @@ -440,7 +441,7 @@ private:
440 const QString &file = src.file; 441 const QString &file = src.file;
441 if (cache.contains(file)) { 442 if (cache.contains(file)) {
442 dst = cache[file]; 443 dst = cache[file];
443 - dst.file.setLabel(src.file.label()); 444 + dst.file.set("Label", src.file.label());
444 } else { 445 } else {
445 transform->project(src, dst); 446 transform->project(src, dst);
446 cacheLock.lock(); 447 cacheLock.lock();
openbr/plugins/misc.cpp
@@ -423,6 +423,51 @@ class RelabelTransform : public UntrainableMetaTransform @@ -423,6 +423,51 @@ class RelabelTransform : public UntrainableMetaTransform
423 423
424 BR_REGISTER(Transform, RelabelTransform) 424 BR_REGISTER(Transform, RelabelTransform)
425 425
  426 +/*!
  427 + * \ingroup transforms
  428 + * \brief Remove templates with the specified file extension.
  429 + * \author Josh Klontz \cite jklontz
  430 + */
  431 +class RemoveTemplatesTransform : public UntrainableMetaTransform
  432 +{
  433 + Q_OBJECT
  434 + Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false)
  435 + BR_PROPERTY(QString, regexp, "")
  436 +
  437 + void project(const Template &src, Template &dst) const
  438 + {
  439 + const QRegularExpression re(regexp);
  440 + const QRegularExpressionMatch match = re.match(src.file.suffix());
  441 + if (match.hasMatch()) dst = Template();
  442 + else dst = src;
  443 + }
  444 +};
  445 +
  446 +BR_REGISTER(Transform, RemoveTemplatesTransform)
  447 +
  448 +/*!
  449 + * \ingroup transforms
  450 + * \brief Remove template metadata with the specified key(s).
  451 + * \author Josh Klontz \cite jklontz
  452 + */
  453 +class RemoveMetadataTransform : public UntrainableMetaTransform
  454 +{
  455 + Q_OBJECT
  456 + Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false)
  457 + BR_PROPERTY(QString, regexp, "")
  458 +
  459 + void project(const Template &src, Template &dst) const
  460 + {
  461 + dst = src;
  462 + const QRegularExpression re(regexp);
  463 + foreach (const QString &key, dst.file.localKeys())
  464 + if (re.match(key).hasMatch())
  465 + dst.file.remove(key);
  466 + }
  467 +};
  468 +
  469 +BR_REGISTER(Transform, RemoveMetadataTransform)
  470 +
426 } 471 }
427 472
428 #include "misc.moc" 473 #include "misc.moc"
openbr/plugins/output.cpp
@@ -298,7 +298,7 @@ class rankOutput : public MatrixOutput @@ -298,7 +298,7 @@ class rankOutput : public MatrixOutput
298 typedef QPair<float,int> Pair; 298 typedef QPair<float,int> Pair;
299 int rank = 1; 299 int rank = 1;
300 foreach (const Pair &pair, Common::Sort(OpenCVUtils::matrixToVector<float>(data.row(i)), true)) { 300 foreach (const Pair &pair, Common::Sort(OpenCVUtils::matrixToVector<float>(data.row(i)), true)) {
301 - if(targetFiles[pair.second].get<QString>("Label") == queryFiles[i].get<QString>("Label")) { 301 + if (targetFiles[pair.second].get<QString>("Subject") == queryFiles[i].get<QString>("Subject")) {
302 ranks.append(rank); 302 ranks.append(rank);
303 positions.append(pair.second); 303 positions.append(pair.second);
304 scores.append(pair.first); 304 scores.append(pair.first);
openbr/plugins/pixel.cpp
@@ -122,7 +122,7 @@ class PerPixelClassifierTransform : public MetaTransform @@ -122,7 +122,7 @@ class PerPixelClassifierTransform : public MetaTransform
122 } 122 }
123 cv::Mat labelMat = src.file.value("labels").value<cv::Mat>(); 123 cv::Mat labelMat = src.file.value("labels").value<cv::Mat>();
124 uchar* plabel = labelMat.ptr(); 124 uchar* plabel = labelMat.ptr();
125 - temp.file.setLabel(plabel[index]); 125 + temp.file.set("Label", plabel[index]);
126 126
127 if (orient){ 127 if (orient){
128 Template rotated; 128 Template rotated;
openbr/plugins/svm.cpp
@@ -114,7 +114,7 @@ private: @@ -114,7 +114,7 @@ private:
114 void project(const Template &src, Template &dst) const 114 void project(const Template &src, Template &dst) const
115 { 115 {
116 dst = src; 116 dst = src;
117 - dst.file.setLabel((svm.predict(src.m().reshape(0, 1)) - b)/a); 117 + dst.file.set("Label", ((svm.predict(src.m().reshape(0, 1)) - b)/a));
118 } 118 }
119 119
120 void store(QDataStream &stream) const 120 void store(QDataStream &stream) const
scripts/evalFaceRecognition-MEDS.sh
@@ -18,14 +18,5 @@ fi @@ -18,14 +18,5 @@ fi
18 # Run Algorithm on MEDS 18 # Run Algorithm on MEDS
19 br -algorithm ${ALGORITHM} -path ../data/MEDS/img -compare ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml ${ALGORITHM}_MEDS.mtx -eval ${ALGORITHM}_MEDS.mtx MEDS.mask Algorithm_Dataset/${ALGORITHM}_MEDS.csv 19 br -algorithm ${ALGORITHM} -path ../data/MEDS/img -compare ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml ${ALGORITHM}_MEDS.mtx -eval ${ALGORITHM}_MEDS.mtx MEDS.mask Algorithm_Dataset/${ALGORITHM}_MEDS.csv
20 20
21 -# Evaluate other algorithms  
22 -for ALGORITHM in COTS  
23 -do  
24 - if [ ! -e Algorithm_Dataset/${ALGORITHM}_MEDS.csv ]; then  
25 - br -eval ../data/MEDS/simmat/${ALGORITHM}_MEDS.mtx MEDS.mask Algorithm_Dataset/${ALGORITHM}_MEDS.csv &  
26 - fi  
27 -done  
28 -wait  
29 -  
30 # Plot results 21 # Plot results
31 br -plot Algorithm_Dataset/*_MEDS.csv MEDS 22 br -plot Algorithm_Dataset/*_MEDS.csv MEDS
share/openbr/cmake/FindAlphanum.cmake
1 find_path(ALPHANUM_DIR alphanum.hpp ${CMAKE_SOURCE_DIR}/3rdparty/*) 1 find_path(ALPHANUM_DIR alphanum.hpp ${CMAKE_SOURCE_DIR}/3rdparty/*)
  2 +mark_as_advanced(ALPHANUM_DIR)
2 include_directories(${ALPHANUM_DIR}) 3 include_directories(${ALPHANUM_DIR})