Commit 7f3e496917b7e7d08b0386d8d52203f128801e33

Authored by Brendan Klare
2 parents cfd0326c de040f81

trying to merge

.gitignore
@@ -20,6 +20,7 @@ scripts/results @@ -20,6 +20,7 @@ scripts/results
20 20
21 ### QtCreator ### 21 ### QtCreator ###
22 *CMakeLists.txt.user* 22 *CMakeLists.txt.user*
  23 +*.autosave
23 24
24 ### R ### 25 ### R ###
25 *.RData 26 *.RData
README.md
1 -www.openbiometrics.org 1 +**www.openbiometrics.org**
2 2
3 $ git clone https://github.com/biometrics/openbr.git 3 $ git clone https://github.com/biometrics/openbr.git
4 $ cd openbr 4 $ cd openbr
5 $ git submodule init 5 $ git submodule init
6 $ git submodule update 6 $ git submodule update
  7 +
  8 +To optionally check out a particular [tagged release](https://github.com/biometrics/openbr/releases):
7 9
8 -[Build Instructions](http://openbiometrics.org/doxygen/latest/installation.html) 10 + $ git checkout <tag>
  11 + $ git submodule update
  12 +
  13 +**[Build Instructions](http://openbiometrics.org/doxygen/latest/installation.html)**
app/br/br.cpp
@@ -129,17 +129,20 @@ public: @@ -129,17 +129,20 @@ public:
129 check(parc == 3, "Incorrect parameter count for 'convert'."); 129 check(parc == 3, "Incorrect parameter count for 'convert'.");
130 br_convert(parv[0], parv[1], parv[2]); 130 br_convert(parv[0], parv[1], parv[2]);
131 } else if (!strcmp(fun, "evalClassification")) { 131 } else if (!strcmp(fun, "evalClassification")) {
132 - check(parc == 2, "Incorrect parameter count for 'evalClassification'.");  
133 - br_eval_classification(parv[0], parv[1]); 132 + check(parc >= 2 && parc <= 4, "Incorrect parameter count for 'evalClassification'.");
  133 + br_eval_classification(parv[0], parv[1], parc >= 3 ? parv[2] : "", parc >= 4 ? parv[3] : "");
134 } else if (!strcmp(fun, "evalClustering")) { 134 } else if (!strcmp(fun, "evalClustering")) {
135 check(parc == 2, "Incorrect parameter count for 'evalClustering'."); 135 check(parc == 2, "Incorrect parameter count for 'evalClustering'.");
136 br_eval_clustering(parv[0], parv[1]); 136 br_eval_clustering(parv[0], parv[1]);
137 } else if (!strcmp(fun, "evalDetection")) { 137 } else if (!strcmp(fun, "evalDetection")) {
138 check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'evalDetection'."); 138 check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'evalDetection'.");
139 br_eval_detection(parv[0], parv[1], parc == 3 ? parv[2] : ""); 139 br_eval_detection(parv[0], parv[1], parc == 3 ? parv[2] : "");
  140 + } else if (!strcmp(fun, "evalLandmarking")) {
  141 + check((parc >= 2) && (parc <= 5), "Incorrect parameter count for 'evalLandmarking'.");
  142 + br_eval_landmarking(parv[0], parv[1], parc >= 3 ? parv[2] : "", parc >= 4 ? atoi(parv[3]) : 0, parc >= 5 ? atoi(parv[4]) : 1);
140 } else if (!strcmp(fun, "evalRegression")) { 143 } else if (!strcmp(fun, "evalRegression")) {
141 - check(parc == 2, "Incorrect parameter count for 'evalRegression'.");  
142 - br_eval_regression(parv[0], parv[1]); 144 + check(parc >= 2 && parc <= 4, "Incorrect parameter count for 'evalRegression'.");
  145 + br_eval_regression(parv[0], parv[1], parc >= 3 ? parv[2] : "", parc >= 4 ? parv[3] : "");
143 } else if (!strcmp(fun, "plotDetection")) { 146 } else if (!strcmp(fun, "plotDetection")) {
144 check(parc >= 2, "Incorrect parameter count for 'plotDetection'."); 147 check(parc >= 2, "Incorrect parameter count for 'plotDetection'.");
145 br_plot_detection(parc-1, parv, parv[parc-1], true); 148 br_plot_detection(parc-1, parv, parv[parc-1], true);
@@ -215,10 +218,11 @@ private: @@ -215,10 +218,11 @@ private:
215 "-combineMasks <mask> ... <mask> {mask} (And|Or)\n" 218 "-combineMasks <mask> ... <mask> {mask} (And|Or)\n"
216 "-cat <gallery> ... <gallery> {gallery}\n" 219 "-cat <gallery> ... <gallery> {gallery}\n"
217 "-convert (Format|Gallery|Output) <input_file> {output_file}\n" 220 "-convert (Format|Gallery|Output) <input_file> {output_file}\n"
218 - "-evalClassification <predicted_gallery> <truth_gallery>\n" 221 + "-evalClassification <predicted_gallery> <truth_gallery> <predicted property name> <ground truth proprty name>\n"
219 "-evalClustering <clusters> <gallery>\n" 222 "-evalClustering <clusters> <gallery>\n"
220 "-evalDetection <predicted_gallery> <truth_gallery> [{csv}]\n" 223 "-evalDetection <predicted_gallery> <truth_gallery> [{csv}]\n"
221 - "-evalRegression <predicted_gallery> <truth_gallery>\n" 224 + "-evalLandmarking <predicted_gallery> <truth_gallery> [{csv} [<normalization_index_a> <normalization_index_b>]]\n"
  225 + "-evalRegression <predicted_gallery> <truth_gallery> <predicted property name> <ground truth property name>\n"
222 "-plotDetection <file> ... <file> {destination}\n" 226 "-plotDetection <file> ... <file> {destination}\n"
223 "-plotMetadata <file> ... <file> <columns>\n" 227 "-plotMetadata <file> ... <file> <columns>\n"
224 "-getHeader <matrix>\n" 228 "-getHeader <matrix>\n"
app/examples/age_estimation.cpp
@@ -29,7 +29,7 @@ @@ -29,7 +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", qPrintable(t.file.fileName()), int(t.file.get<float>("Subject"))); 32 + printf("%s age: %d\n", qPrintable(t.file.fileName()), int(t.file.get<float>("Age")));
33 } 33 }
34 34
35 int main(int argc, char *argv[]) 35 int main(int argc, char *argv[])
app/examples/face_recognition_evaluation.cpp
@@ -25,8 +25,7 @@ @@ -25,8 +25,7 @@
25 * -compare target.gal query.gal scores.mtx \ 25 * -compare target.gal query.gal scores.mtx \
26 * -makeMask ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml MEDS.mask \ 26 * -makeMask ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml MEDS.mask \
27 * -eval scores.mtx MEDS.mask Algorithm_Dataset/FaceRecognition_MEDS.csv \ 27 * -eval scores.mtx MEDS.mask Algorithm_Dataset/FaceRecognition_MEDS.csv \
28 - * -eval ../data/MEDS/simmat/COTS_MEDS.mtx MEDS.mask Algorithm_Dataset/COTS_MEDS.csv \  
29 - * -plot Algorithm_Dataset/FaceRecognition_MEDS.csv Algorithm_Dataset/COTS_MEDS.csv MEDS 28 + * -plot Algorithm_Dataset/FaceRecognition_MEDS.csv MEDS
30 * \endcode 29 * \endcode
31 */ 30 */
32 31
app/examples/gender_estimation.cpp
@@ -29,7 +29,7 @@ @@ -29,7 +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", qPrintable(t.file.fileName()), qPrintable(t.file.get<QString>("Subject"))); 32 + printf("%s gender: %s\n", qPrintable(t.file.fileName()), qPrintable(t.file.get<QString>("Gender")));
33 } 33 }
34 34
35 int main(int argc, char *argv[]) 35 int main(int argc, char *argv[])
data/KTH/test_9ppl.xml 0 โ†’ 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<biometric-signature-set>
  3 + <biometric-signature name="boxing17-1">
  4 + <presentation Label="boxing" file-name="boxing/person17_boxing_d1_uncomp.avi" />
  5 + </biometric-signature>
  6 + <biometric-signature name="boxing17-2">
  7 + <presentation Label="boxing" file-name="boxing/person17_boxing_d2_uncomp.avi" />
  8 + </biometric-signature>
  9 + <biometric-signature name="boxing17-3">
  10 + <presentation Label="boxing" file-name="boxing/person17_boxing_d3_uncomp.avi" />
  11 + </biometric-signature>
  12 + <biometric-signature name="boxing17-4">
  13 + <presentation Label="boxing" file-name="boxing/person17_boxing_d4_uncomp.avi" />
  14 + </biometric-signature>
  15 + <biometric-signature name="boxing18-1">
  16 + <presentation Label="boxing" file-name="boxing/person18_boxing_d1_uncomp.avi" />
  17 + </biometric-signature>
  18 + <biometric-signature name="boxing18-2">
  19 + <presentation Label="boxing" file-name="boxing/person18_boxing_d2_uncomp.avi" />
  20 + </biometric-signature>
  21 + <biometric-signature name="boxing18-3">
  22 + <presentation Label="boxing" file-name="boxing/person18_boxing_d3_uncomp.avi" />
  23 + </biometric-signature>
  24 + <biometric-signature name="boxing18-4">
  25 + <presentation Label="boxing" file-name="boxing/person18_boxing_d4_uncomp.avi" />
  26 + </biometric-signature>
  27 + <biometric-signature name="boxing19-1">
  28 + <presentation Label="boxing" file-name="boxing/person19_boxing_d1_uncomp.avi" />
  29 + </biometric-signature>
  30 + <biometric-signature name="boxing19-2">
  31 + <presentation Label="boxing" file-name="boxing/person19_boxing_d2_uncomp.avi" />
  32 + </biometric-signature>
  33 + <biometric-signature name="boxing19-3">
  34 + <presentation Label="boxing" file-name="boxing/person19_boxing_d3_uncomp.avi" />
  35 + </biometric-signature>
  36 + <biometric-signature name="boxing19-4">
  37 + <presentation Label="boxing" file-name="boxing/person19_boxing_d4_uncomp.avi" />
  38 + </biometric-signature>
  39 + <biometric-signature name="boxing20-1">
  40 + <presentation Label="boxing" file-name="boxing/person20_boxing_d1_uncomp.avi" />
  41 + </biometric-signature>
  42 + <biometric-signature name="boxing20-2">
  43 + <presentation Label="boxing" file-name="boxing/person20_boxing_d2_uncomp.avi" />
  44 + </biometric-signature>
  45 + <biometric-signature name="boxing20-3">
  46 + <presentation Label="boxing" file-name="boxing/person20_boxing_d3_uncomp.avi" />
  47 + </biometric-signature>
  48 + <biometric-signature name="boxing20-4">
  49 + <presentation Label="boxing" file-name="boxing/person20_boxing_d4_uncomp.avi" />
  50 + </biometric-signature>
  51 + <biometric-signature name="boxing21-1">
  52 + <presentation Label="boxing" file-name="boxing/person21_boxing_d1_uncomp.avi" />
  53 + </biometric-signature>
  54 + <biometric-signature name="boxing21-2">
  55 + <presentation Label="boxing" file-name="boxing/person21_boxing_d2_uncomp.avi" />
  56 + </biometric-signature>
  57 + <biometric-signature name="boxing21-3">
  58 + <presentation Label="boxing" file-name="boxing/person21_boxing_d3_uncomp.avi" />
  59 + </biometric-signature>
  60 + <biometric-signature name="boxing21-4">
  61 + <presentation Label="boxing" file-name="boxing/person21_boxing_d4_uncomp.avi" />
  62 + </biometric-signature>
  63 + <biometric-signature name="boxing22-1">
  64 + <presentation Label="boxing" file-name="boxing/person22_boxing_d1_uncomp.avi" />
  65 + </biometric-signature>
  66 + <biometric-signature name="boxing22-2">
  67 + <presentation Label="boxing" file-name="boxing/person22_boxing_d2_uncomp.avi" />
  68 + </biometric-signature>
  69 + <biometric-signature name="boxing22-3">
  70 + <presentation Label="boxing" file-name="boxing/person22_boxing_d3_uncomp.avi" />
  71 + </biometric-signature>
  72 + <biometric-signature name="boxing22-4">
  73 + <presentation Label="boxing" file-name="boxing/person22_boxing_d4_uncomp.avi" />
  74 + </biometric-signature>
  75 + <biometric-signature name="boxing23-1">
  76 + <presentation Label="boxing" file-name="boxing/person23_boxing_d1_uncomp.avi" />
  77 + </biometric-signature>
  78 + <biometric-signature name="boxing23-2">
  79 + <presentation Label="boxing" file-name="boxing/person23_boxing_d2_uncomp.avi" />
  80 + </biometric-signature>
  81 + <biometric-signature name="boxing23-3">
  82 + <presentation Label="boxing" file-name="boxing/person23_boxing_d3_uncomp.avi" />
  83 + </biometric-signature>
  84 + <biometric-signature name="boxing23-4">
  85 + <presentation Label="boxing" file-name="boxing/person23_boxing_d4_uncomp.avi" />
  86 + </biometric-signature>
  87 + <biometric-signature name="boxing24-1">
  88 + <presentation Label="boxing" file-name="boxing/person24_boxing_d1_uncomp.avi" />
  89 + </biometric-signature>
  90 + <biometric-signature name="boxing24-2">
  91 + <presentation Label="boxing" file-name="boxing/person24_boxing_d2_uncomp.avi" />
  92 + </biometric-signature>
  93 + <biometric-signature name="boxing24-3">
  94 + <presentation Label="boxing" file-name="boxing/person24_boxing_d3_uncomp.avi" />
  95 + </biometric-signature>
  96 + <biometric-signature name="boxing24-4">
  97 + <presentation Label="boxing" file-name="boxing/person24_boxing_d4_uncomp.avi" />
  98 + </biometric-signature>
  99 + <biometric-signature name="boxing25-1">
  100 + <presentation Label="boxing" file-name="boxing/person25_boxing_d1_uncomp.avi" />
  101 + </biometric-signature>
  102 + <biometric-signature name="boxing25-2">
  103 + <presentation Label="boxing" file-name="boxing/person25_boxing_d2_uncomp.avi" />
  104 + </biometric-signature>
  105 + <biometric-signature name="boxing25-3">
  106 + <presentation Label="boxing" file-name="boxing/person25_boxing_d3_uncomp.avi" />
  107 + </biometric-signature>
  108 + <biometric-signature name="boxing25-4">
  109 + <presentation Label="boxing" file-name="boxing/person25_boxing_d4_uncomp.avi" />
  110 + </biometric-signature>
  111 + <biometric-signature name="handclapping17-1">
  112 + <presentation Label="handclapping" file-name="handclapping/person17_handclapping_d1_uncomp.avi" />
  113 + </biometric-signature>
  114 + <biometric-signature name="handclapping17-2">
  115 + <presentation Label="handclapping" file-name="handclapping/person17_handclapping_d2_uncomp.avi" />
  116 + </biometric-signature>
  117 + <biometric-signature name="handclapping17-3">
  118 + <presentation Label="handclapping" file-name="handclapping/person17_handclapping_d3_uncomp.avi" />
  119 + </biometric-signature>
  120 + <biometric-signature name="handclapping17-4">
  121 + <presentation Label="handclapping" file-name="handclapping/person17_handclapping_d4_uncomp.avi" />
  122 + </biometric-signature>
  123 + <biometric-signature name="handclapping18-1">
  124 + <presentation Label="handclapping" file-name="handclapping/person18_handclapping_d1_uncomp.avi" />
  125 + </biometric-signature>
  126 + <biometric-signature name="handclapping18-2">
  127 + <presentation Label="handclapping" file-name="handclapping/person18_handclapping_d2_uncomp.avi" />
  128 + </biometric-signature>
  129 + <biometric-signature name="handclapping18-3">
  130 + <presentation Label="handclapping" file-name="handclapping/person18_handclapping_d3_uncomp.avi" />
  131 + </biometric-signature>
  132 + <biometric-signature name="handclapping18-4">
  133 + <presentation Label="handclapping" file-name="handclapping/person18_handclapping_d4_uncomp.avi" />
  134 + </biometric-signature>
  135 + <biometric-signature name="handclapping19-1">
  136 + <presentation Label="handclapping" file-name="handclapping/person19_handclapping_d1_uncomp.avi" />
  137 + </biometric-signature>
  138 + <biometric-signature name="handclapping19-2">
  139 + <presentation Label="handclapping" file-name="handclapping/person19_handclapping_d2_uncomp.avi" />
  140 + </biometric-signature>
  141 + <biometric-signature name="handclapping19-3">
  142 + <presentation Label="handclapping" file-name="handclapping/person19_handclapping_d3_uncomp.avi" />
  143 + </biometric-signature>
  144 + <biometric-signature name="handclapping19-4">
  145 + <presentation Label="handclapping" file-name="handclapping/person19_handclapping_d4_uncomp.avi" />
  146 + </biometric-signature>
  147 + <biometric-signature name="handclapping20-1">
  148 + <presentation Label="handclapping" file-name="handclapping/person20_handclapping_d1_uncomp.avi" />
  149 + </biometric-signature>
  150 + <biometric-signature name="handclapping20-2">
  151 + <presentation Label="handclapping" file-name="handclapping/person20_handclapping_d2_uncomp.avi" />
  152 + </biometric-signature>
  153 + <biometric-signature name="handclapping20-3">
  154 + <presentation Label="handclapping" file-name="handclapping/person20_handclapping_d3_uncomp.avi" />
  155 + </biometric-signature>
  156 + <biometric-signature name="handclapping20-4">
  157 + <presentation Label="handclapping" file-name="handclapping/person20_handclapping_d4_uncomp.avi" />
  158 + </biometric-signature>
  159 + <biometric-signature name="handclapping21-1">
  160 + <presentation Label="handclapping" file-name="handclapping/person21_handclapping_d1_uncomp.avi" />
  161 + </biometric-signature>
  162 + <biometric-signature name="handclapping21-2">
  163 + <presentation Label="handclapping" file-name="handclapping/person21_handclapping_d2_uncomp.avi" />
  164 + </biometric-signature>
  165 + <biometric-signature name="handclapping21-3">
  166 + <presentation Label="handclapping" file-name="handclapping/person21_handclapping_d3_uncomp.avi" />
  167 + </biometric-signature>
  168 + <biometric-signature name="handclapping21-4">
  169 + <presentation Label="handclapping" file-name="handclapping/person21_handclapping_d4_uncomp.avi" />
  170 + </biometric-signature>
  171 + <biometric-signature name="handclapping22-1">
  172 + <presentation Label="handclapping" file-name="handclapping/person22_handclapping_d1_uncomp.avi" />
  173 + </biometric-signature>
  174 + <biometric-signature name="handclapping22-2">
  175 + <presentation Label="handclapping" file-name="handclapping/person22_handclapping_d2_uncomp.avi" />
  176 + </biometric-signature>
  177 + <biometric-signature name="handclapping22-3">
  178 + <presentation Label="handclapping" file-name="handclapping/person22_handclapping_d3_uncomp.avi" />
  179 + </biometric-signature>
  180 + <biometric-signature name="handclapping22-4">
  181 + <presentation Label="handclapping" file-name="handclapping/person22_handclapping_d4_uncomp.avi" />
  182 + </biometric-signature>
  183 + <biometric-signature name="handclapping23-1">
  184 + <presentation Label="handclapping" file-name="handclapping/person23_handclapping_d1_uncomp.avi" />
  185 + </biometric-signature>
  186 + <biometric-signature name="handclapping23-2">
  187 + <presentation Label="handclapping" file-name="handclapping/person23_handclapping_d2_uncomp.avi" />
  188 + </biometric-signature>
  189 + <biometric-signature name="handclapping23-3">
  190 + <presentation Label="handclapping" file-name="handclapping/person23_handclapping_d3_uncomp.avi" />
  191 + </biometric-signature>
  192 + <biometric-signature name="handclapping23-4">
  193 + <presentation Label="handclapping" file-name="handclapping/person23_handclapping_d4_uncomp.avi" />
  194 + </biometric-signature>
  195 + <biometric-signature name="handclapping24-1">
  196 + <presentation Label="handclapping" file-name="handclapping/person24_handclapping_d1_uncomp.avi" />
  197 + </biometric-signature>
  198 + <biometric-signature name="handclapping24-2">
  199 + <presentation Label="handclapping" file-name="handclapping/person24_handclapping_d2_uncomp.avi" />
  200 + </biometric-signature>
  201 + <biometric-signature name="handclapping24-3">
  202 + <presentation Label="handclapping" file-name="handclapping/person24_handclapping_d3_uncomp.avi" />
  203 + </biometric-signature>
  204 + <biometric-signature name="handclapping24-4">
  205 + <presentation Label="handclapping" file-name="handclapping/person24_handclapping_d4_uncomp.avi" />
  206 + </biometric-signature>
  207 + <biometric-signature name="handclapping25-1">
  208 + <presentation Label="handclapping" file-name="handclapping/person25_handclapping_d1_uncomp.avi" />
  209 + </biometric-signature>
  210 + <biometric-signature name="handclapping25-2">
  211 + <presentation Label="handclapping" file-name="handclapping/person25_handclapping_d2_uncomp.avi" />
  212 + </biometric-signature>
  213 + <biometric-signature name="handclapping25-3">
  214 + <presentation Label="handclapping" file-name="handclapping/person25_handclapping_d3_uncomp.avi" />
  215 + </biometric-signature>
  216 + <biometric-signature name="handclapping25-4">
  217 + <presentation Label="handclapping" file-name="handclapping/person25_handclapping_d4_uncomp.avi" />
  218 + </biometric-signature>
  219 + <biometric-signature name="handwaving17-1">
  220 + <presentation Label="handwaving" file-name="handwaving/person17_handwaving_d1_uncomp.avi" />
  221 + </biometric-signature>
  222 + <biometric-signature name="handwaving17-2">
  223 + <presentation Label="handwaving" file-name="handwaving/person17_handwaving_d2_uncomp.avi" />
  224 + </biometric-signature>
  225 + <biometric-signature name="handwaving17-3">
  226 + <presentation Label="handwaving" file-name="handwaving/person17_handwaving_d3_uncomp.avi" />
  227 + </biometric-signature>
  228 + <biometric-signature name="handwaving17-4">
  229 + <presentation Label="handwaving" file-name="handwaving/person17_handwaving_d4_uncomp.avi" />
  230 + </biometric-signature>
  231 + <biometric-signature name="handwaving18-1">
  232 + <presentation Label="handwaving" file-name="handwaving/person18_handwaving_d1_uncomp.avi" />
  233 + </biometric-signature>
  234 + <biometric-signature name="handwaving18-2">
  235 + <presentation Label="handwaving" file-name="handwaving/person18_handwaving_d2_uncomp.avi" />
  236 + </biometric-signature>
  237 + <biometric-signature name="handwaving18-3">
  238 + <presentation Label="handwaving" file-name="handwaving/person18_handwaving_d3_uncomp.avi" />
  239 + </biometric-signature>
  240 + <biometric-signature name="handwaving18-4">
  241 + <presentation Label="handwaving" file-name="handwaving/person18_handwaving_d4_uncomp.avi" />
  242 + </biometric-signature>
  243 + <biometric-signature name="handwaving19-1">
  244 + <presentation Label="handwaving" file-name="handwaving/person19_handwaving_d1_uncomp.avi" />
  245 + </biometric-signature>
  246 + <biometric-signature name="handwaving19-2">
  247 + <presentation Label="handwaving" file-name="handwaving/person19_handwaving_d2_uncomp.avi" />
  248 + </biometric-signature>
  249 + <biometric-signature name="handwaving19-3">
  250 + <presentation Label="handwaving" file-name="handwaving/person19_handwaving_d3_uncomp.avi" />
  251 + </biometric-signature>
  252 + <biometric-signature name="handwaving19-4">
  253 + <presentation Label="handwaving" file-name="handwaving/person19_handwaving_d4_uncomp.avi" />
  254 + </biometric-signature>
  255 + <biometric-signature name="handwaving20-1">
  256 + <presentation Label="handwaving" file-name="handwaving/person20_handwaving_d1_uncomp.avi" />
  257 + </biometric-signature>
  258 + <biometric-signature name="handwaving20-2">
  259 + <presentation Label="handwaving" file-name="handwaving/person20_handwaving_d2_uncomp.avi" />
  260 + </biometric-signature>
  261 + <biometric-signature name="handwaving20-3">
  262 + <presentation Label="handwaving" file-name="handwaving/person20_handwaving_d3_uncomp.avi" />
  263 + </biometric-signature>
  264 + <biometric-signature name="handwaving20-4">
  265 + <presentation Label="handwaving" file-name="handwaving/person20_handwaving_d4_uncomp.avi" />
  266 + </biometric-signature>
  267 + <biometric-signature name="handwaving21-1">
  268 + <presentation Label="handwaving" file-name="handwaving/person21_handwaving_d1_uncomp.avi" />
  269 + </biometric-signature>
  270 + <biometric-signature name="handwaving21-2">
  271 + <presentation Label="handwaving" file-name="handwaving/person21_handwaving_d2_uncomp.avi" />
  272 + </biometric-signature>
  273 + <biometric-signature name="handwaving21-3">
  274 + <presentation Label="handwaving" file-name="handwaving/person21_handwaving_d3_uncomp.avi" />
  275 + </biometric-signature>
  276 + <biometric-signature name="handwaving21-4">
  277 + <presentation Label="handwaving" file-name="handwaving/person21_handwaving_d4_uncomp.avi" />
  278 + </biometric-signature>
  279 + <biometric-signature name="handwaving22-1">
  280 + <presentation Label="handwaving" file-name="handwaving/person22_handwaving_d1_uncomp.avi" />
  281 + </biometric-signature>
  282 + <biometric-signature name="handwaving22-2">
  283 + <presentation Label="handwaving" file-name="handwaving/person22_handwaving_d2_uncomp.avi" />
  284 + </biometric-signature>
  285 + <biometric-signature name="handwaving22-3">
  286 + <presentation Label="handwaving" file-name="handwaving/person22_handwaving_d3_uncomp.avi" />
  287 + </biometric-signature>
  288 + <biometric-signature name="handwaving22-4">
  289 + <presentation Label="handwaving" file-name="handwaving/person22_handwaving_d4_uncomp.avi" />
  290 + </biometric-signature>
  291 + <biometric-signature name="handwaving23-1">
  292 + <presentation Label="handwaving" file-name="handwaving/person23_handwaving_d1_uncomp.avi" />
  293 + </biometric-signature>
  294 + <biometric-signature name="handwaving23-2">
  295 + <presentation Label="handwaving" file-name="handwaving/person23_handwaving_d2_uncomp.avi" />
  296 + </biometric-signature>
  297 + <biometric-signature name="handwaving23-3">
  298 + <presentation Label="handwaving" file-name="handwaving/person23_handwaving_d3_uncomp.avi" />
  299 + </biometric-signature>
  300 + <biometric-signature name="handwaving23-4">
  301 + <presentation Label="handwaving" file-name="handwaving/person23_handwaving_d4_uncomp.avi" />
  302 + </biometric-signature>
  303 + <biometric-signature name="handwaving24-1">
  304 + <presentation Label="handwaving" file-name="handwaving/person24_handwaving_d1_uncomp.avi" />
  305 + </biometric-signature>
  306 + <biometric-signature name="handwaving24-2">
  307 + <presentation Label="handwaving" file-name="handwaving/person24_handwaving_d2_uncomp.avi" />
  308 + </biometric-signature>
  309 + <biometric-signature name="handwaving24-3">
  310 + <presentation Label="handwaving" file-name="handwaving/person24_handwaving_d3_uncomp.avi" />
  311 + </biometric-signature>
  312 + <biometric-signature name="handwaving24-4">
  313 + <presentation Label="handwaving" file-name="handwaving/person24_handwaving_d4_uncomp.avi" />
  314 + </biometric-signature>
  315 + <biometric-signature name="handwaving25-1">
  316 + <presentation Label="handwaving" file-name="handwaving/person25_handwaving_d1_uncomp.avi" />
  317 + </biometric-signature>
  318 + <biometric-signature name="handwaving25-2">
  319 + <presentation Label="handwaving" file-name="handwaving/person25_handwaving_d2_uncomp.avi" />
  320 + </biometric-signature>
  321 + <biometric-signature name="handwaving25-3">
  322 + <presentation Label="handwaving" file-name="handwaving/person25_handwaving_d3_uncomp.avi" />
  323 + </biometric-signature>
  324 + <biometric-signature name="handwaving25-4">
  325 + <presentation Label="handwaving" file-name="handwaving/person25_handwaving_d4_uncomp.avi" />
  326 + </biometric-signature>
  327 + <biometric-signature name="jogging17-1">
  328 + <presentation Label="jogging" file-name="jogging/person17_jogging_d1_uncomp.avi" />
  329 + </biometric-signature>
  330 + <biometric-signature name="jogging17-2">
  331 + <presentation Label="jogging" file-name="jogging/person17_jogging_d2_uncomp.avi" />
  332 + </biometric-signature>
  333 + <biometric-signature name="jogging17-3">
  334 + <presentation Label="jogging" file-name="jogging/person17_jogging_d3_uncomp.avi" />
  335 + </biometric-signature>
  336 + <biometric-signature name="jogging17-4">
  337 + <presentation Label="jogging" file-name="jogging/person17_jogging_d4_uncomp.avi" />
  338 + </biometric-signature>
  339 + <biometric-signature name="jogging18-1">
  340 + <presentation Label="jogging" file-name="jogging/person18_jogging_d1_uncomp.avi" />
  341 + </biometric-signature>
  342 + <biometric-signature name="jogging18-2">
  343 + <presentation Label="jogging" file-name="jogging/person18_jogging_d2_uncomp.avi" />
  344 + </biometric-signature>
  345 + <biometric-signature name="jogging18-3">
  346 + <presentation Label="jogging" file-name="jogging/person18_jogging_d3_uncomp.avi" />
  347 + </biometric-signature>
  348 + <biometric-signature name="jogging18-4">
  349 + <presentation Label="jogging" file-name="jogging/person18_jogging_d4_uncomp.avi" />
  350 + </biometric-signature>
  351 + <biometric-signature name="jogging19-1">
  352 + <presentation Label="jogging" file-name="jogging/person19_jogging_d1_uncomp.avi" />
  353 + </biometric-signature>
  354 + <biometric-signature name="jogging19-2">
  355 + <presentation Label="jogging" file-name="jogging/person19_jogging_d2_uncomp.avi" />
  356 + </biometric-signature>
  357 + <biometric-signature name="jogging19-3">
  358 + <presentation Label="jogging" file-name="jogging/person19_jogging_d3_uncomp.avi" />
  359 + </biometric-signature>
  360 + <biometric-signature name="jogging19-4">
  361 + <presentation Label="jogging" file-name="jogging/person19_jogging_d4_uncomp.avi" />
  362 + </biometric-signature>
  363 + <biometric-signature name="jogging20-1">
  364 + <presentation Label="jogging" file-name="jogging/person20_jogging_d1_uncomp.avi" />
  365 + </biometric-signature>
  366 + <biometric-signature name="jogging20-2">
  367 + <presentation Label="jogging" file-name="jogging/person20_jogging_d2_uncomp.avi" />
  368 + </biometric-signature>
  369 + <biometric-signature name="jogging20-3">
  370 + <presentation Label="jogging" file-name="jogging/person20_jogging_d3_uncomp.avi" />
  371 + </biometric-signature>
  372 + <biometric-signature name="jogging20-4">
  373 + <presentation Label="jogging" file-name="jogging/person20_jogging_d4_uncomp.avi" />
  374 + </biometric-signature>
  375 + <biometric-signature name="jogging21-1">
  376 + <presentation Label="jogging" file-name="jogging/person21_jogging_d1_uncomp.avi" />
  377 + </biometric-signature>
  378 + <biometric-signature name="jogging21-2">
  379 + <presentation Label="jogging" file-name="jogging/person21_jogging_d2_uncomp.avi" />
  380 + </biometric-signature>
  381 + <biometric-signature name="jogging21-3">
  382 + <presentation Label="jogging" file-name="jogging/person21_jogging_d3_uncomp.avi" />
  383 + </biometric-signature>
  384 + <biometric-signature name="jogging21-4">
  385 + <presentation Label="jogging" file-name="jogging/person21_jogging_d4_uncomp.avi" />
  386 + </biometric-signature>
  387 + <biometric-signature name="jogging22-1">
  388 + <presentation Label="jogging" file-name="jogging/person22_jogging_d1_uncomp.avi" />
  389 + </biometric-signature>
  390 + <biometric-signature name="jogging22-2">
  391 + <presentation Label="jogging" file-name="jogging/person22_jogging_d2_uncomp.avi" />
  392 + </biometric-signature>
  393 + <biometric-signature name="jogging22-3">
  394 + <presentation Label="jogging" file-name="jogging/person22_jogging_d3_uncomp.avi" />
  395 + </biometric-signature>
  396 + <biometric-signature name="jogging22-4">
  397 + <presentation Label="jogging" file-name="jogging/person22_jogging_d4_uncomp.avi" />
  398 + </biometric-signature>
  399 + <biometric-signature name="jogging23-1">
  400 + <presentation Label="jogging" file-name="jogging/person23_jogging_d1_uncomp.avi" />
  401 + </biometric-signature>
  402 + <biometric-signature name="jogging23-2">
  403 + <presentation Label="jogging" file-name="jogging/person23_jogging_d2_uncomp.avi" />
  404 + </biometric-signature>
  405 + <biometric-signature name="jogging23-3">
  406 + <presentation Label="jogging" file-name="jogging/person23_jogging_d3_uncomp.avi" />
  407 + </biometric-signature>
  408 + <biometric-signature name="jogging23-4">
  409 + <presentation Label="jogging" file-name="jogging/person23_jogging_d4_uncomp.avi" />
  410 + </biometric-signature>
  411 + <biometric-signature name="jogging24-1">
  412 + <presentation Label="jogging" file-name="jogging/person24_jogging_d1_uncomp.avi" />
  413 + </biometric-signature>
  414 + <biometric-signature name="jogging24-2">
  415 + <presentation Label="jogging" file-name="jogging/person24_jogging_d2_uncomp.avi" />
  416 + </biometric-signature>
  417 + <biometric-signature name="jogging24-3">
  418 + <presentation Label="jogging" file-name="jogging/person24_jogging_d3_uncomp.avi" />
  419 + </biometric-signature>
  420 + <biometric-signature name="jogging24-4">
  421 + <presentation Label="jogging" file-name="jogging/person24_jogging_d4_uncomp.avi" />
  422 + </biometric-signature>
  423 + <biometric-signature name="jogging25-1">
  424 + <presentation Label="jogging" file-name="jogging/person25_jogging_d1_uncomp.avi" />
  425 + </biometric-signature>
  426 + <biometric-signature name="jogging25-2">
  427 + <presentation Label="jogging" file-name="jogging/person25_jogging_d2_uncomp.avi" />
  428 + </biometric-signature>
  429 + <biometric-signature name="jogging25-3">
  430 + <presentation Label="jogging" file-name="jogging/person25_jogging_d3_uncomp.avi" />
  431 + </biometric-signature>
  432 + <biometric-signature name="jogging25-4">
  433 + <presentation Label="jogging" file-name="jogging/person25_jogging_d4_uncomp.avi" />
  434 + </biometric-signature>
  435 + <biometric-signature name="running17-1">
  436 + <presentation Label="running" file-name="running/person17_running_d1_uncomp.avi" />
  437 + </biometric-signature>
  438 + <biometric-signature name="running17-2">
  439 + <presentation Label="running" file-name="running/person17_running_d2_uncomp.avi" />
  440 + </biometric-signature>
  441 + <biometric-signature name="running17-3">
  442 + <presentation Label="running" file-name="running/person17_running_d3_uncomp.avi" />
  443 + </biometric-signature>
  444 + <biometric-signature name="running17-4">
  445 + <presentation Label="running" file-name="running/person17_running_d4_uncomp.avi" />
  446 + </biometric-signature>
  447 + <biometric-signature name="running18-1">
  448 + <presentation Label="running" file-name="running/person18_running_d1_uncomp.avi" />
  449 + </biometric-signature>
  450 + <biometric-signature name="running18-2">
  451 + <presentation Label="running" file-name="running/person18_running_d2_uncomp.avi" />
  452 + </biometric-signature>
  453 + <biometric-signature name="running18-3">
  454 + <presentation Label="running" file-name="running/person18_running_d3_uncomp.avi" />
  455 + </biometric-signature>
  456 + <biometric-signature name="running18-4">
  457 + <presentation Label="running" file-name="running/person18_running_d4_uncomp.avi" />
  458 + </biometric-signature>
  459 + <biometric-signature name="running19-1">
  460 + <presentation Label="running" file-name="running/person19_running_d1_uncomp.avi" />
  461 + </biometric-signature>
  462 + <biometric-signature name="running19-2">
  463 + <presentation Label="running" file-name="running/person19_running_d2_uncomp.avi" />
  464 + </biometric-signature>
  465 + <biometric-signature name="running19-3">
  466 + <presentation Label="running" file-name="running/person19_running_d3_uncomp.avi" />
  467 + </biometric-signature>
  468 + <biometric-signature name="running19-4">
  469 + <presentation Label="running" file-name="running/person19_running_d4_uncomp.avi" />
  470 + </biometric-signature>
  471 + <biometric-signature name="running20-1">
  472 + <presentation Label="running" file-name="running/person20_running_d1_uncomp.avi" />
  473 + </biometric-signature>
  474 + <biometric-signature name="running20-2">
  475 + <presentation Label="running" file-name="running/person20_running_d2_uncomp.avi" />
  476 + </biometric-signature>
  477 + <biometric-signature name="running20-3">
  478 + <presentation Label="running" file-name="running/person20_running_d3_uncomp.avi" />
  479 + </biometric-signature>
  480 + <biometric-signature name="running20-4">
  481 + <presentation Label="running" file-name="running/person20_running_d4_uncomp.avi" />
  482 + </biometric-signature>
  483 + <biometric-signature name="running21-1">
  484 + <presentation Label="running" file-name="running/person21_running_d1_uncomp.avi" />
  485 + </biometric-signature>
  486 + <biometric-signature name="running21-2">
  487 + <presentation Label="running" file-name="running/person21_running_d2_uncomp.avi" />
  488 + </biometric-signature>
  489 + <biometric-signature name="running21-3">
  490 + <presentation Label="running" file-name="running/person21_running_d3_uncomp.avi" />
  491 + </biometric-signature>
  492 + <biometric-signature name="running21-4">
  493 + <presentation Label="running" file-name="running/person21_running_d4_uncomp.avi" />
  494 + </biometric-signature>
  495 + <biometric-signature name="running22-1">
  496 + <presentation Label="running" file-name="running/person22_running_d1_uncomp.avi" />
  497 + </biometric-signature>
  498 + <biometric-signature name="running22-2">
  499 + <presentation Label="running" file-name="running/person22_running_d2_uncomp.avi" />
  500 + </biometric-signature>
  501 + <biometric-signature name="running22-3">
  502 + <presentation Label="running" file-name="running/person22_running_d3_uncomp.avi" />
  503 + </biometric-signature>
  504 + <biometric-signature name="running22-4">
  505 + <presentation Label="running" file-name="running/person22_running_d4_uncomp.avi" />
  506 + </biometric-signature>
  507 + <biometric-signature name="running23-1">
  508 + <presentation Label="running" file-name="running/person23_running_d1_uncomp.avi" />
  509 + </biometric-signature>
  510 + <biometric-signature name="running23-2">
  511 + <presentation Label="running" file-name="running/person23_running_d2_uncomp.avi" />
  512 + </biometric-signature>
  513 + <biometric-signature name="running23-3">
  514 + <presentation Label="running" file-name="running/person23_running_d3_uncomp.avi" />
  515 + </biometric-signature>
  516 + <biometric-signature name="running23-4">
  517 + <presentation Label="running" file-name="running/person23_running_d4_uncomp.avi" />
  518 + </biometric-signature>
  519 + <biometric-signature name="running24-1">
  520 + <presentation Label="running" file-name="running/person24_running_d1_uncomp.avi" />
  521 + </biometric-signature>
  522 + <biometric-signature name="running24-2">
  523 + <presentation Label="running" file-name="running/person24_running_d2_uncomp.avi" />
  524 + </biometric-signature>
  525 + <biometric-signature name="running24-3">
  526 + <presentation Label="running" file-name="running/person24_running_d3_uncomp.avi" />
  527 + </biometric-signature>
  528 + <biometric-signature name="running24-4">
  529 + <presentation Label="running" file-name="running/person24_running_d4_uncomp.avi" />
  530 + </biometric-signature>
  531 + <biometric-signature name="running25-1">
  532 + <presentation Label="running" file-name="running/person25_running_d1_uncomp.avi" />
  533 + </biometric-signature>
  534 + <biometric-signature name="running25-2">
  535 + <presentation Label="running" file-name="running/person25_running_d2_uncomp.avi" />
  536 + </biometric-signature>
  537 + <biometric-signature name="running25-3">
  538 + <presentation Label="running" file-name="running/person25_running_d3_uncomp.avi" />
  539 + </biometric-signature>
  540 + <biometric-signature name="running25-4">
  541 + <presentation Label="running" file-name="running/person25_running_d4_uncomp.avi" />
  542 + </biometric-signature>
  543 + <biometric-signature name="walking17-1">
  544 + <presentation Label="walking" file-name="walking/person17_walking_d1_uncomp.avi" />
  545 + </biometric-signature>
  546 + <biometric-signature name="walking17-2">
  547 + <presentation Label="walking" file-name="walking/person17_walking_d2_uncomp.avi" />
  548 + </biometric-signature>
  549 + <biometric-signature name="walking17-3">
  550 + <presentation Label="walking" file-name="walking/person17_walking_d3_uncomp.avi" />
  551 + </biometric-signature>
  552 + <biometric-signature name="walking17-4">
  553 + <presentation Label="walking" file-name="walking/person17_walking_d4_uncomp.avi" />
  554 + </biometric-signature>
  555 + <biometric-signature name="walking18-1">
  556 + <presentation Label="walking" file-name="walking/person18_walking_d1_uncomp.avi" />
  557 + </biometric-signature>
  558 + <biometric-signature name="walking18-2">
  559 + <presentation Label="walking" file-name="walking/person18_walking_d2_uncomp.avi" />
  560 + </biometric-signature>
  561 + <biometric-signature name="walking18-3">
  562 + <presentation Label="walking" file-name="walking/person18_walking_d3_uncomp.avi" />
  563 + </biometric-signature>
  564 + <biometric-signature name="walking18-4">
  565 + <presentation Label="walking" file-name="walking/person18_walking_d4_uncomp.avi" />
  566 + </biometric-signature>
  567 + <biometric-signature name="walking19-1">
  568 + <presentation Label="walking" file-name="walking/person19_walking_d1_uncomp.avi" />
  569 + </biometric-signature>
  570 + <biometric-signature name="walking19-2">
  571 + <presentation Label="walking" file-name="walking/person19_walking_d2_uncomp.avi" />
  572 + </biometric-signature>
  573 + <biometric-signature name="walking19-3">
  574 + <presentation Label="walking" file-name="walking/person19_walking_d3_uncomp.avi" />
  575 + </biometric-signature>
  576 + <biometric-signature name="walking19-4">
  577 + <presentation Label="walking" file-name="walking/person19_walking_d4_uncomp.avi" />
  578 + </biometric-signature>
  579 + <biometric-signature name="walking20-1">
  580 + <presentation Label="walking" file-name="walking/person20_walking_d1_uncomp.avi" />
  581 + </biometric-signature>
  582 + <biometric-signature name="walking20-2">
  583 + <presentation Label="walking" file-name="walking/person20_walking_d2_uncomp.avi" />
  584 + </biometric-signature>
  585 + <biometric-signature name="walking20-3">
  586 + <presentation Label="walking" file-name="walking/person20_walking_d3_uncomp.avi" />
  587 + </biometric-signature>
  588 + <biometric-signature name="walking20-4">
  589 + <presentation Label="walking" file-name="walking/person20_walking_d4_uncomp.avi" />
  590 + </biometric-signature>
  591 + <biometric-signature name="walking21-1">
  592 + <presentation Label="walking" file-name="walking/person21_walking_d1_uncomp.avi" />
  593 + </biometric-signature>
  594 + <biometric-signature name="walking21-2">
  595 + <presentation Label="walking" file-name="walking/person21_walking_d2_uncomp.avi" />
  596 + </biometric-signature>
  597 + <biometric-signature name="walking21-3">
  598 + <presentation Label="walking" file-name="walking/person21_walking_d3_uncomp.avi" />
  599 + </biometric-signature>
  600 + <biometric-signature name="walking21-4">
  601 + <presentation Label="walking" file-name="walking/person21_walking_d4_uncomp.avi" />
  602 + </biometric-signature>
  603 + <biometric-signature name="walking22-1">
  604 + <presentation Label="walking" file-name="walking/person22_walking_d1_uncomp.avi" />
  605 + </biometric-signature>
  606 + <biometric-signature name="walking22-2">
  607 + <presentation Label="walking" file-name="walking/person22_walking_d2_uncomp.avi" />
  608 + </biometric-signature>
  609 + <biometric-signature name="walking22-3">
  610 + <presentation Label="walking" file-name="walking/person22_walking_d3_uncomp.avi" />
  611 + </biometric-signature>
  612 + <biometric-signature name="walking22-4">
  613 + <presentation Label="walking" file-name="walking/person22_walking_d4_uncomp.avi" />
  614 + </biometric-signature>
  615 + <biometric-signature name="walking23-1">
  616 + <presentation Label="walking" file-name="walking/person23_walking_d1_uncomp.avi" />
  617 + </biometric-signature>
  618 + <biometric-signature name="walking23-2">
  619 + <presentation Label="walking" file-name="walking/person23_walking_d2_uncomp.avi" />
  620 + </biometric-signature>
  621 + <biometric-signature name="walking23-3">
  622 + <presentation Label="walking" file-name="walking/person23_walking_d3_uncomp.avi" />
  623 + </biometric-signature>
  624 + <biometric-signature name="walking23-4">
  625 + <presentation Label="walking" file-name="walking/person23_walking_d4_uncomp.avi" />
  626 + </biometric-signature>
  627 + <biometric-signature name="walking24-1">
  628 + <presentation Label="walking" file-name="walking/person24_walking_d1_uncomp.avi" />
  629 + </biometric-signature>
  630 + <biometric-signature name="walking24-2">
  631 + <presentation Label="walking" file-name="walking/person24_walking_d2_uncomp.avi" />
  632 + </biometric-signature>
  633 + <biometric-signature name="walking24-3">
  634 + <presentation Label="walking" file-name="walking/person24_walking_d3_uncomp.avi" />
  635 + </biometric-signature>
  636 + <biometric-signature name="walking24-4">
  637 + <presentation Label="walking" file-name="walking/person24_walking_d4_uncomp.avi" />
  638 + </biometric-signature>
  639 + <biometric-signature name="walking25-1">
  640 + <presentation Label="walking" file-name="walking/person25_walking_d1_uncomp.avi" />
  641 + </biometric-signature>
  642 + <biometric-signature name="walking25-2">
  643 + <presentation Label="walking" file-name="walking/person25_walking_d2_uncomp.avi" />
  644 + </biometric-signature>
  645 + <biometric-signature name="walking25-3">
  646 + <presentation Label="walking" file-name="walking/person25_walking_d3_uncomp.avi" />
  647 + </biometric-signature>
  648 + <biometric-signature name="walking25-4">
  649 + <presentation Label="walking" file-name="walking/person25_walking_d4_uncomp.avi" />
  650 + </biometric-signature>
  651 +</biometric-signature-set>
data/KTH/train_16ppl.xml 0 โ†’ 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<biometric-signature-set>
  3 + <biometric-signature name="boxing1-1">
  4 + <presentation Label="boxing" file-name="boxing/person01_boxing_d1_uncomp.avi" />
  5 + </biometric-signature>
  6 + <biometric-signature name="boxing1-2">
  7 + <presentation Label="boxing" file-name="boxing/person01_boxing_d2_uncomp.avi" />
  8 + </biometric-signature>
  9 + <biometric-signature name="boxing1-3">
  10 + <presentation Label="boxing" file-name="boxing/person01_boxing_d3_uncomp.avi" />
  11 + </biometric-signature>
  12 + <biometric-signature name="boxing2-1">
  13 + <presentation Label="boxing" file-name="boxing/person02_boxing_d1_uncomp.avi" />
  14 + </biometric-signature>
  15 + <biometric-signature name="boxing2-2">
  16 + <presentation Label="boxing" file-name="boxing/person02_boxing_d2_uncomp.avi" />
  17 + </biometric-signature>
  18 + <biometric-signature name="boxing2-3">
  19 + <presentation Label="boxing" file-name="boxing/person02_boxing_d3_uncomp.avi" />
  20 + </biometric-signature>
  21 + <biometric-signature name="boxing2-4">
  22 + <presentation Label="boxing" file-name="boxing/person02_boxing_d4_uncomp.avi" />
  23 + </biometric-signature>
  24 + <biometric-signature name="boxing3-1">
  25 + <presentation Label="boxing" file-name="boxing/person03_boxing_d1_uncomp.avi" />
  26 + </biometric-signature>
  27 + <biometric-signature name="boxing3-2">
  28 + <presentation Label="boxing" file-name="boxing/person03_boxing_d2_uncomp.avi" />
  29 + </biometric-signature>
  30 + <biometric-signature name="boxing3-3">
  31 + <presentation Label="boxing" file-name="boxing/person03_boxing_d3_uncomp.avi" />
  32 + </biometric-signature>
  33 + <biometric-signature name="boxing3-4">
  34 + <presentation Label="boxing" file-name="boxing/person03_boxing_d4_uncomp.avi" />
  35 + </biometric-signature>
  36 + <biometric-signature name="boxing4-1">
  37 + <presentation Label="boxing" file-name="boxing/person04_boxing_d1_uncomp.avi" />
  38 + </biometric-signature>
  39 + <biometric-signature name="boxing4-2">
  40 + <presentation Label="boxing" file-name="boxing/person04_boxing_d2_uncomp.avi" />
  41 + </biometric-signature>
  42 + <biometric-signature name="boxing4-3">
  43 + <presentation Label="boxing" file-name="boxing/person04_boxing_d3_uncomp.avi" />
  44 + </biometric-signature>
  45 + <biometric-signature name="boxing4-4">
  46 + <presentation Label="boxing" file-name="boxing/person04_boxing_d4_uncomp.avi" />
  47 + </biometric-signature>
  48 + <biometric-signature name="boxing5-1">
  49 + <presentation Label="boxing" file-name="boxing/person05_boxing_d1_uncomp.avi" />
  50 + </biometric-signature>
  51 + <biometric-signature name="boxing5-2">
  52 + <presentation Label="boxing" file-name="boxing/person05_boxing_d2_uncomp.avi" />
  53 + </biometric-signature>
  54 + <biometric-signature name="boxing5-3">
  55 + <presentation Label="boxing" file-name="boxing/person05_boxing_d3_uncomp.avi" />
  56 + </biometric-signature>
  57 + <biometric-signature name="boxing5-4">
  58 + <presentation Label="boxing" file-name="boxing/person05_boxing_d4_uncomp.avi" />
  59 + </biometric-signature>
  60 + <biometric-signature name="boxing6-1">
  61 + <presentation Label="boxing" file-name="boxing/person06_boxing_d1_uncomp.avi" />
  62 + </biometric-signature>
  63 + <biometric-signature name="boxing6-2">
  64 + <presentation Label="boxing" file-name="boxing/person06_boxing_d2_uncomp.avi" />
  65 + </biometric-signature>
  66 + <biometric-signature name="boxing6-3">
  67 + <presentation Label="boxing" file-name="boxing/person06_boxing_d3_uncomp.avi" />
  68 + </biometric-signature>
  69 + <biometric-signature name="boxing6-4">
  70 + <presentation Label="boxing" file-name="boxing/person06_boxing_d4_uncomp.avi" />
  71 + </biometric-signature>
  72 + <biometric-signature name="boxing7-1">
  73 + <presentation Label="boxing" file-name="boxing/person07_boxing_d1_uncomp.avi" />
  74 + </biometric-signature>
  75 + <biometric-signature name="boxing7-2">
  76 + <presentation Label="boxing" file-name="boxing/person07_boxing_d2_uncomp.avi" />
  77 + </biometric-signature>
  78 + <biometric-signature name="boxing7-3">
  79 + <presentation Label="boxing" file-name="boxing/person07_boxing_d3_uncomp.avi" />
  80 + </biometric-signature>
  81 + <biometric-signature name="boxing7-4">
  82 + <presentation Label="boxing" file-name="boxing/person07_boxing_d4_uncomp.avi" />
  83 + </biometric-signature>
  84 + <biometric-signature name="boxing8-1">
  85 + <presentation Label="boxing" file-name="boxing/person08_boxing_d1_uncomp.avi" />
  86 + </biometric-signature>
  87 + <biometric-signature name="boxing8-2">
  88 + <presentation Label="boxing" file-name="boxing/person08_boxing_d2_uncomp.avi" />
  89 + </biometric-signature>
  90 + <biometric-signature name="boxing8-3">
  91 + <presentation Label="boxing" file-name="boxing/person08_boxing_d3_uncomp.avi" />
  92 + </biometric-signature>
  93 + <biometric-signature name="boxing8-4">
  94 + <presentation Label="boxing" file-name="boxing/person08_boxing_d4_uncomp.avi" />
  95 + </biometric-signature>
  96 + <biometric-signature name="boxing9-1">
  97 + <presentation Label="boxing" file-name="boxing/person09_boxing_d1_uncomp.avi" />
  98 + </biometric-signature>
  99 + <biometric-signature name="boxing9-2">
  100 + <presentation Label="boxing" file-name="boxing/person09_boxing_d2_uncomp.avi" />
  101 + </biometric-signature>
  102 + <biometric-signature name="boxing9-3">
  103 + <presentation Label="boxing" file-name="boxing/person09_boxing_d3_uncomp.avi" />
  104 + </biometric-signature>
  105 + <biometric-signature name="boxing9-4">
  106 + <presentation Label="boxing" file-name="boxing/person09_boxing_d4_uncomp.avi" />
  107 + </biometric-signature>
  108 + <biometric-signature name="boxing10-1">
  109 + <presentation Label="boxing" file-name="boxing/person10_boxing_d1_uncomp.avi" />
  110 + </biometric-signature>
  111 + <biometric-signature name="boxing10-2">
  112 + <presentation Label="boxing" file-name="boxing/person10_boxing_d2_uncomp.avi" />
  113 + </biometric-signature>
  114 + <biometric-signature name="boxing10-3">
  115 + <presentation Label="boxing" file-name="boxing/person10_boxing_d3_uncomp.avi" />
  116 + </biometric-signature>
  117 + <biometric-signature name="boxing10-4">
  118 + <presentation Label="boxing" file-name="boxing/person10_boxing_d4_uncomp.avi" />
  119 + </biometric-signature>
  120 + <biometric-signature name="boxing11-1">
  121 + <presentation Label="boxing" file-name="boxing/person11_boxing_d1_uncomp.avi" />
  122 + </biometric-signature>
  123 + <biometric-signature name="boxing11-2">
  124 + <presentation Label="boxing" file-name="boxing/person11_boxing_d2_uncomp.avi" />
  125 + </biometric-signature>
  126 + <biometric-signature name="boxing11-3">
  127 + <presentation Label="boxing" file-name="boxing/person11_boxing_d3_uncomp.avi" />
  128 + </biometric-signature>
  129 + <biometric-signature name="boxing11-4">
  130 + <presentation Label="boxing" file-name="boxing/person11_boxing_d4_uncomp.avi" />
  131 + </biometric-signature>
  132 + <biometric-signature name="boxing12-1">
  133 + <presentation Label="boxing" file-name="boxing/person12_boxing_d1_uncomp.avi" />
  134 + </biometric-signature>
  135 + <biometric-signature name="boxing12-2">
  136 + <presentation Label="boxing" file-name="boxing/person12_boxing_d2_uncomp.avi" />
  137 + </biometric-signature>
  138 + <biometric-signature name="boxing12-3">
  139 + <presentation Label="boxing" file-name="boxing/person12_boxing_d3_uncomp.avi" />
  140 + </biometric-signature>
  141 + <biometric-signature name="boxing12-4">
  142 + <presentation Label="boxing" file-name="boxing/person12_boxing_d4_uncomp.avi" />
  143 + </biometric-signature>
  144 + <biometric-signature name="boxing13-1">
  145 + <presentation Label="boxing" file-name="boxing/person13_boxing_d1_uncomp.avi" />
  146 + </biometric-signature>
  147 + <biometric-signature name="boxing13-2">
  148 + <presentation Label="boxing" file-name="boxing/person13_boxing_d2_uncomp.avi" />
  149 + </biometric-signature>
  150 + <biometric-signature name="boxing13-3">
  151 + <presentation Label="boxing" file-name="boxing/person13_boxing_d3_uncomp.avi" />
  152 + </biometric-signature>
  153 + <biometric-signature name="boxing13-4">
  154 + <presentation Label="boxing" file-name="boxing/person13_boxing_d4_uncomp.avi" />
  155 + </biometric-signature>
  156 + <biometric-signature name="boxing14-1">
  157 + <presentation Label="boxing" file-name="boxing/person14_boxing_d1_uncomp.avi" />
  158 + </biometric-signature>
  159 + <biometric-signature name="boxing14-2">
  160 + <presentation Label="boxing" file-name="boxing/person14_boxing_d2_uncomp.avi" />
  161 + </biometric-signature>
  162 + <biometric-signature name="boxing14-3">
  163 + <presentation Label="boxing" file-name="boxing/person14_boxing_d3_uncomp.avi" />
  164 + </biometric-signature>
  165 + <biometric-signature name="boxing14-4">
  166 + <presentation Label="boxing" file-name="boxing/person14_boxing_d4_uncomp.avi" />
  167 + </biometric-signature>
  168 + <biometric-signature name="boxing15-1">
  169 + <presentation Label="boxing" file-name="boxing/person15_boxing_d1_uncomp.avi" />
  170 + </biometric-signature>
  171 + <biometric-signature name="boxing15-2">
  172 + <presentation Label="boxing" file-name="boxing/person15_boxing_d2_uncomp.avi" />
  173 + </biometric-signature>
  174 + <biometric-signature name="boxing15-3">
  175 + <presentation Label="boxing" file-name="boxing/person15_boxing_d3_uncomp.avi" />
  176 + </biometric-signature>
  177 + <biometric-signature name="boxing15-4">
  178 + <presentation Label="boxing" file-name="boxing/person15_boxing_d4_uncomp.avi" />
  179 + </biometric-signature>
  180 + <biometric-signature name="boxing16-1">
  181 + <presentation Label="boxing" file-name="boxing/person16_boxing_d1_uncomp.avi" />
  182 + </biometric-signature>
  183 + <biometric-signature name="boxing16-2">
  184 + <presentation Label="boxing" file-name="boxing/person16_boxing_d2_uncomp.avi" />
  185 + </biometric-signature>
  186 + <biometric-signature name="boxing16-3">
  187 + <presentation Label="boxing" file-name="boxing/person16_boxing_d3_uncomp.avi" />
  188 + </biometric-signature>
  189 + <biometric-signature name="boxing16-4">
  190 + <presentation Label="boxing" file-name="boxing/person16_boxing_d4_uncomp.avi" />
  191 + </biometric-signature>
  192 + <biometric-signature name="handclapping1-1">
  193 + <presentation Label="handclapping" file-name="handclapping/person01_handclapping_d1_uncomp.avi" />
  194 + </biometric-signature>
  195 + <biometric-signature name="handclapping1-2">
  196 + <presentation Label="handclapping" file-name="handclapping/person01_handclapping_d2_uncomp.avi" />
  197 + </biometric-signature>
  198 + <biometric-signature name="handclapping1-3">
  199 + <presentation Label="handclapping" file-name="handclapping/person01_handclapping_d3_uncomp.avi" />
  200 + </biometric-signature>
  201 + <biometric-signature name="handclapping1-4">
  202 + <presentation Label="handclapping" file-name="handclapping/person01_handclapping_d4_uncomp.avi" />
  203 + </biometric-signature>
  204 + <biometric-signature name="handclapping2-1">
  205 + <presentation Label="handclapping" file-name="handclapping/person02_handclapping_d1_uncomp.avi" />
  206 + </biometric-signature>
  207 + <biometric-signature name="handclapping2-2">
  208 + <presentation Label="handclapping" file-name="handclapping/person02_handclapping_d2_uncomp.avi" />
  209 + </biometric-signature>
  210 + <biometric-signature name="handclapping2-3">
  211 + <presentation Label="handclapping" file-name="handclapping/person02_handclapping_d3_uncomp.avi" />
  212 + </biometric-signature>
  213 + <biometric-signature name="handclapping2-4">
  214 + <presentation Label="handclapping" file-name="handclapping/person02_handclapping_d4_uncomp.avi" />
  215 + </biometric-signature>
  216 + <biometric-signature name="handclapping3-1">
  217 + <presentation Label="handclapping" file-name="handclapping/person03_handclapping_d1_uncomp.avi" />
  218 + </biometric-signature>
  219 + <biometric-signature name="handclapping3-2">
  220 + <presentation Label="handclapping" file-name="handclapping/person03_handclapping_d2_uncomp.avi" />
  221 + </biometric-signature>
  222 + <biometric-signature name="handclapping3-3">
  223 + <presentation Label="handclapping" file-name="handclapping/person03_handclapping_d3_uncomp.avi" />
  224 + </biometric-signature>
  225 + <biometric-signature name="handclapping3-4">
  226 + <presentation Label="handclapping" file-name="handclapping/person03_handclapping_d4_uncomp.avi" />
  227 + </biometric-signature>
  228 + <biometric-signature name="handclapping4-1">
  229 + <presentation Label="handclapping" file-name="handclapping/person04_handclapping_d1_uncomp.avi" />
  230 + </biometric-signature>
  231 + <biometric-signature name="handclapping4-2">
  232 + <presentation Label="handclapping" file-name="handclapping/person04_handclapping_d2_uncomp.avi" />
  233 + </biometric-signature>
  234 + <biometric-signature name="handclapping4-3">
  235 + <presentation Label="handclapping" file-name="handclapping/person04_handclapping_d3_uncomp.avi" />
  236 + </biometric-signature>
  237 + <biometric-signature name="handclapping4-4">
  238 + <presentation Label="handclapping" file-name="handclapping/person04_handclapping_d4_uncomp.avi" />
  239 + </biometric-signature>
  240 + <biometric-signature name="handclapping5-1">
  241 + <presentation Label="handclapping" file-name="handclapping/person05_handclapping_d1_uncomp.avi" />
  242 + </biometric-signature>
  243 + <biometric-signature name="handclapping5-2">
  244 + <presentation Label="handclapping" file-name="handclapping/person05_handclapping_d2_uncomp.avi" />
  245 + </biometric-signature>
  246 + <biometric-signature name="handclapping5-3">
  247 + <presentation Label="handclapping" file-name="handclapping/person05_handclapping_d3_uncomp.avi" />
  248 + </biometric-signature>
  249 + <biometric-signature name="handclapping5-4">
  250 + <presentation Label="handclapping" file-name="handclapping/person05_handclapping_d4_uncomp.avi" />
  251 + </biometric-signature>
  252 + <biometric-signature name="handclapping6-1">
  253 + <presentation Label="handclapping" file-name="handclapping/person06_handclapping_d1_uncomp.avi" />
  254 + </biometric-signature>
  255 + <biometric-signature name="handclapping6-2">
  256 + <presentation Label="handclapping" file-name="handclapping/person06_handclapping_d2_uncomp.avi" />
  257 + </biometric-signature>
  258 + <biometric-signature name="handclapping6-3">
  259 + <presentation Label="handclapping" file-name="handclapping/person06_handclapping_d3_uncomp.avi" />
  260 + </biometric-signature>
  261 + <biometric-signature name="handclapping6-4">
  262 + <presentation Label="handclapping" file-name="handclapping/person06_handclapping_d4_uncomp.avi" />
  263 + </biometric-signature>
  264 + <biometric-signature name="handclapping7-1">
  265 + <presentation Label="handclapping" file-name="handclapping/person07_handclapping_d1_uncomp.avi" />
  266 + </biometric-signature>
  267 + <biometric-signature name="handclapping7-2">
  268 + <presentation Label="handclapping" file-name="handclapping/person07_handclapping_d2_uncomp.avi" />
  269 + </biometric-signature>
  270 + <biometric-signature name="handclapping7-3">
  271 + <presentation Label="handclapping" file-name="handclapping/person07_handclapping_d3_uncomp.avi" />
  272 + </biometric-signature>
  273 + <biometric-signature name="handclapping7-4">
  274 + <presentation Label="handclapping" file-name="handclapping/person07_handclapping_d4_uncomp.avi" />
  275 + </biometric-signature>
  276 + <biometric-signature name="handclapping8-1">
  277 + <presentation Label="handclapping" file-name="handclapping/person08_handclapping_d1_uncomp.avi" />
  278 + </biometric-signature>
  279 + <biometric-signature name="handclapping8-2">
  280 + <presentation Label="handclapping" file-name="handclapping/person08_handclapping_d2_uncomp.avi" />
  281 + </biometric-signature>
  282 + <biometric-signature name="handclapping8-3">
  283 + <presentation Label="handclapping" file-name="handclapping/person08_handclapping_d3_uncomp.avi" />
  284 + </biometric-signature>
  285 + <biometric-signature name="handclapping8-4">
  286 + <presentation Label="handclapping" file-name="handclapping/person08_handclapping_d4_uncomp.avi" />
  287 + </biometric-signature>
  288 + <biometric-signature name="handclapping9-1">
  289 + <presentation Label="handclapping" file-name="handclapping/person09_handclapping_d1_uncomp.avi" />
  290 + </biometric-signature>
  291 + <biometric-signature name="handclapping9-2">
  292 + <presentation Label="handclapping" file-name="handclapping/person09_handclapping_d2_uncomp.avi" />
  293 + </biometric-signature>
  294 + <biometric-signature name="handclapping9-3">
  295 + <presentation Label="handclapping" file-name="handclapping/person09_handclapping_d3_uncomp.avi" />
  296 + </biometric-signature>
  297 + <biometric-signature name="handclapping9-4">
  298 + <presentation Label="handclapping" file-name="handclapping/person09_handclapping_d4_uncomp.avi" />
  299 + </biometric-signature>
  300 + <biometric-signature name="handclapping10-1">
  301 + <presentation Label="handclapping" file-name="handclapping/person10_handclapping_d1_uncomp.avi" />
  302 + </biometric-signature>
  303 + <biometric-signature name="handclapping10-2">
  304 + <presentation Label="handclapping" file-name="handclapping/person10_handclapping_d2_uncomp.avi" />
  305 + </biometric-signature>
  306 + <biometric-signature name="handclapping10-3">
  307 + <presentation Label="handclapping" file-name="handclapping/person10_handclapping_d3_uncomp.avi" />
  308 + </biometric-signature>
  309 + <biometric-signature name="handclapping10-4">
  310 + <presentation Label="handclapping" file-name="handclapping/person10_handclapping_d4_uncomp.avi" />
  311 + </biometric-signature>
  312 + <biometric-signature name="handclapping11-1">
  313 + <presentation Label="handclapping" file-name="handclapping/person11_handclapping_d1_uncomp.avi" />
  314 + </biometric-signature>
  315 + <biometric-signature name="handclapping11-2">
  316 + <presentation Label="handclapping" file-name="handclapping/person11_handclapping_d2_uncomp.avi" />
  317 + </biometric-signature>
  318 + <biometric-signature name="handclapping11-3">
  319 + <presentation Label="handclapping" file-name="handclapping/person11_handclapping_d3_uncomp.avi" />
  320 + </biometric-signature>
  321 + <biometric-signature name="handclapping11-4">
  322 + <presentation Label="handclapping" file-name="handclapping/person11_handclapping_d4_uncomp.avi" />
  323 + </biometric-signature>
  324 + <biometric-signature name="handclapping12-1">
  325 + <presentation Label="handclapping" file-name="handclapping/person12_handclapping_d1_uncomp.avi" />
  326 + </biometric-signature>
  327 + <biometric-signature name="handclapping12-2">
  328 + <presentation Label="handclapping" file-name="handclapping/person12_handclapping_d2_uncomp.avi" />
  329 + </biometric-signature>
  330 + <biometric-signature name="handclapping12-3">
  331 + <presentation Label="handclapping" file-name="handclapping/person12_handclapping_d3_uncomp.avi" />
  332 + </biometric-signature>
  333 + <biometric-signature name="handclapping12-4">
  334 + <presentation Label="handclapping" file-name="handclapping/person12_handclapping_d4_uncomp.avi" />
  335 + </biometric-signature>
  336 + <biometric-signature name="handclapping13-1">
  337 + <presentation Label="handclapping" file-name="handclapping/person13_handclapping_d1_uncomp.avi" />
  338 + </biometric-signature>
  339 + <biometric-signature name="handclapping13-2">
  340 + <presentation Label="handclapping" file-name="handclapping/person13_handclapping_d2_uncomp.avi" />
  341 + </biometric-signature>
  342 + <biometric-signature name="handclapping13-4">
  343 + <presentation Label="handclapping" file-name="handclapping/person13_handclapping_d4_uncomp.avi" />
  344 + </biometric-signature>
  345 + <biometric-signature name="handclapping14-1">
  346 + <presentation Label="handclapping" file-name="handclapping/person14_handclapping_d1_uncomp.avi" />
  347 + </biometric-signature>
  348 + <biometric-signature name="handclapping14-2">
  349 + <presentation Label="handclapping" file-name="handclapping/person14_handclapping_d2_uncomp.avi" />
  350 + </biometric-signature>
  351 + <biometric-signature name="handclapping14-3">
  352 + <presentation Label="handclapping" file-name="handclapping/person14_handclapping_d3_uncomp.avi" />
  353 + </biometric-signature>
  354 + <biometric-signature name="handclapping14-4">
  355 + <presentation Label="handclapping" file-name="handclapping/person14_handclapping_d4_uncomp.avi" />
  356 + </biometric-signature>
  357 + <biometric-signature name="handclapping15-1">
  358 + <presentation Label="handclapping" file-name="handclapping/person15_handclapping_d1_uncomp.avi" />
  359 + </biometric-signature>
  360 + <biometric-signature name="handclapping15-2">
  361 + <presentation Label="handclapping" file-name="handclapping/person15_handclapping_d2_uncomp.avi" />
  362 + </biometric-signature>
  363 + <biometric-signature name="handclapping15-3">
  364 + <presentation Label="handclapping" file-name="handclapping/person15_handclapping_d3_uncomp.avi" />
  365 + </biometric-signature>
  366 + <biometric-signature name="handclapping15-4">
  367 + <presentation Label="handclapping" file-name="handclapping/person15_handclapping_d4_uncomp.avi" />
  368 + </biometric-signature>
  369 + <biometric-signature name="handclapping16-1">
  370 + <presentation Label="handclapping" file-name="handclapping/person16_handclapping_d1_uncomp.avi" />
  371 + </biometric-signature>
  372 + <biometric-signature name="handclapping16-2">
  373 + <presentation Label="handclapping" file-name="handclapping/person16_handclapping_d2_uncomp.avi" />
  374 + </biometric-signature>
  375 + <biometric-signature name="handclapping16-3">
  376 + <presentation Label="handclapping" file-name="handclapping/person16_handclapping_d3_uncomp.avi" />
  377 + </biometric-signature>
  378 + <biometric-signature name="handclapping16-4">
  379 + <presentation Label="handclapping" file-name="handclapping/person16_handclapping_d4_uncomp.avi" />
  380 + </biometric-signature>
  381 + <biometric-signature name="handwaving1-1">
  382 + <presentation Label="handwaving" file-name="handwaving/person01_handwaving_d1_uncomp.avi" />
  383 + </biometric-signature>
  384 + <biometric-signature name="handwaving1-2">
  385 + <presentation Label="handwaving" file-name="handwaving/person01_handwaving_d2_uncomp.avi" />
  386 + </biometric-signature>
  387 + <biometric-signature name="handwaving1-3">
  388 + <presentation Label="handwaving" file-name="handwaving/person01_handwaving_d3_uncomp.avi" />
  389 + </biometric-signature>
  390 + <biometric-signature name="handwaving1-4">
  391 + <presentation Label="handwaving" file-name="handwaving/person01_handwaving_d4_uncomp.avi" />
  392 + </biometric-signature>
  393 + <biometric-signature name="handwaving2-1">
  394 + <presentation Label="handwaving" file-name="handwaving/person02_handwaving_d1_uncomp.avi" />
  395 + </biometric-signature>
  396 + <biometric-signature name="handwaving2-2">
  397 + <presentation Label="handwaving" file-name="handwaving/person02_handwaving_d2_uncomp.avi" />
  398 + </biometric-signature>
  399 + <biometric-signature name="handwaving2-3">
  400 + <presentation Label="handwaving" file-name="handwaving/person02_handwaving_d3_uncomp.avi" />
  401 + </biometric-signature>
  402 + <biometric-signature name="handwaving2-4">
  403 + <presentation Label="handwaving" file-name="handwaving/person02_handwaving_d4_uncomp.avi" />
  404 + </biometric-signature>
  405 + <biometric-signature name="handwaving3-1">
  406 + <presentation Label="handwaving" file-name="handwaving/person03_handwaving_d1_uncomp.avi" />
  407 + </biometric-signature>
  408 + <biometric-signature name="handwaving3-2">
  409 + <presentation Label="handwaving" file-name="handwaving/person03_handwaving_d2_uncomp.avi" />
  410 + </biometric-signature>
  411 + <biometric-signature name="handwaving3-3">
  412 + <presentation Label="handwaving" file-name="handwaving/person03_handwaving_d3_uncomp.avi" />
  413 + </biometric-signature>
  414 + <biometric-signature name="handwaving3-4">
  415 + <presentation Label="handwaving" file-name="handwaving/person03_handwaving_d4_uncomp.avi" />
  416 + </biometric-signature>
  417 + <biometric-signature name="handwaving4-1">
  418 + <presentation Label="handwaving" file-name="handwaving/person04_handwaving_d1_uncomp.avi" />
  419 + </biometric-signature>
  420 + <biometric-signature name="handwaving4-2">
  421 + <presentation Label="handwaving" file-name="handwaving/person04_handwaving_d2_uncomp.avi" />
  422 + </biometric-signature>
  423 + <biometric-signature name="handwaving4-3">
  424 + <presentation Label="handwaving" file-name="handwaving/person04_handwaving_d3_uncomp.avi" />
  425 + </biometric-signature>
  426 + <biometric-signature name="handwaving4-4">
  427 + <presentation Label="handwaving" file-name="handwaving/person04_handwaving_d4_uncomp.avi" />
  428 + </biometric-signature>
  429 + <biometric-signature name="handwaving5-1">
  430 + <presentation Label="handwaving" file-name="handwaving/person05_handwaving_d1_uncomp.avi" />
  431 + </biometric-signature>
  432 + <biometric-signature name="handwaving5-2">
  433 + <presentation Label="handwaving" file-name="handwaving/person05_handwaving_d2_uncomp.avi" />
  434 + </biometric-signature>
  435 + <biometric-signature name="handwaving5-3">
  436 + <presentation Label="handwaving" file-name="handwaving/person05_handwaving_d3_uncomp.avi" />
  437 + </biometric-signature>
  438 + <biometric-signature name="handwaving5-4">
  439 + <presentation Label="handwaving" file-name="handwaving/person05_handwaving_d4_uncomp.avi" />
  440 + </biometric-signature>
  441 + <biometric-signature name="handwaving6-1">
  442 + <presentation Label="handwaving" file-name="handwaving/person06_handwaving_d1_uncomp.avi" />
  443 + </biometric-signature>
  444 + <biometric-signature name="handwaving6-2">
  445 + <presentation Label="handwaving" file-name="handwaving/person06_handwaving_d2_uncomp.avi" />
  446 + </biometric-signature>
  447 + <biometric-signature name="handwaving6-3">
  448 + <presentation Label="handwaving" file-name="handwaving/person06_handwaving_d3_uncomp.avi" />
  449 + </biometric-signature>
  450 + <biometric-signature name="handwaving6-4">
  451 + <presentation Label="handwaving" file-name="handwaving/person06_handwaving_d4_uncomp.avi" />
  452 + </biometric-signature>
  453 + <biometric-signature name="handwaving7-1">
  454 + <presentation Label="handwaving" file-name="handwaving/person07_handwaving_d1_uncomp.avi" />
  455 + </biometric-signature>
  456 + <biometric-signature name="handwaving7-2">
  457 + <presentation Label="handwaving" file-name="handwaving/person07_handwaving_d2_uncomp.avi" />
  458 + </biometric-signature>
  459 + <biometric-signature name="handwaving7-3">
  460 + <presentation Label="handwaving" file-name="handwaving/person07_handwaving_d3_uncomp.avi" />
  461 + </biometric-signature>
  462 + <biometric-signature name="handwaving7-4">
  463 + <presentation Label="handwaving" file-name="handwaving/person07_handwaving_d4_uncomp.avi" />
  464 + </biometric-signature>
  465 + <biometric-signature name="handwaving8-1">
  466 + <presentation Label="handwaving" file-name="handwaving/person08_handwaving_d1_uncomp.avi" />
  467 + </biometric-signature>
  468 + <biometric-signature name="handwaving8-2">
  469 + <presentation Label="handwaving" file-name="handwaving/person08_handwaving_d2_uncomp.avi" />
  470 + </biometric-signature>
  471 + <biometric-signature name="handwaving8-3">
  472 + <presentation Label="handwaving" file-name="handwaving/person08_handwaving_d3_uncomp.avi" />
  473 + </biometric-signature>
  474 + <biometric-signature name="handwaving8-4">
  475 + <presentation Label="handwaving" file-name="handwaving/person08_handwaving_d4_uncomp.avi" />
  476 + </biometric-signature>
  477 + <biometric-signature name="handwaving9-1">
  478 + <presentation Label="handwaving" file-name="handwaving/person09_handwaving_d1_uncomp.avi" />
  479 + </biometric-signature>
  480 + <biometric-signature name="handwaving9-2">
  481 + <presentation Label="handwaving" file-name="handwaving/person09_handwaving_d2_uncomp.avi" />
  482 + </biometric-signature>
  483 + <biometric-signature name="handwaving9-3">
  484 + <presentation Label="handwaving" file-name="handwaving/person09_handwaving_d3_uncomp.avi" />
  485 + </biometric-signature>
  486 + <biometric-signature name="handwaving9-4">
  487 + <presentation Label="handwaving" file-name="handwaving/person09_handwaving_d4_uncomp.avi" />
  488 + </biometric-signature>
  489 + <biometric-signature name="handwaving10-1">
  490 + <presentation Label="handwaving" file-name="handwaving/person10_handwaving_d1_uncomp.avi" />
  491 + </biometric-signature>
  492 + <biometric-signature name="handwaving10-2">
  493 + <presentation Label="handwaving" file-name="handwaving/person10_handwaving_d2_uncomp.avi" />
  494 + </biometric-signature>
  495 + <biometric-signature name="handwaving10-3">
  496 + <presentation Label="handwaving" file-name="handwaving/person10_handwaving_d3_uncomp.avi" />
  497 + </biometric-signature>
  498 + <biometric-signature name="handwaving10-4">
  499 + <presentation Label="handwaving" file-name="handwaving/person10_handwaving_d4_uncomp.avi" />
  500 + </biometric-signature>
  501 + <biometric-signature name="handwaving11-1">
  502 + <presentation Label="handwaving" file-name="handwaving/person11_handwaving_d1_uncomp.avi" />
  503 + </biometric-signature>
  504 + <biometric-signature name="handwaving11-2">
  505 + <presentation Label="handwaving" file-name="handwaving/person11_handwaving_d2_uncomp.avi" />
  506 + </biometric-signature>
  507 + <biometric-signature name="handwaving11-3">
  508 + <presentation Label="handwaving" file-name="handwaving/person11_handwaving_d3_uncomp.avi" />
  509 + </biometric-signature>
  510 + <biometric-signature name="handwaving11-4">
  511 + <presentation Label="handwaving" file-name="handwaving/person11_handwaving_d4_uncomp.avi" />
  512 + </biometric-signature>
  513 + <biometric-signature name="handwaving12-1">
  514 + <presentation Label="handwaving" file-name="handwaving/person12_handwaving_d1_uncomp.avi" />
  515 + </biometric-signature>
  516 + <biometric-signature name="handwaving12-2">
  517 + <presentation Label="handwaving" file-name="handwaving/person12_handwaving_d2_uncomp.avi" />
  518 + </biometric-signature>
  519 + <biometric-signature name="handwaving12-3">
  520 + <presentation Label="handwaving" file-name="handwaving/person12_handwaving_d3_uncomp.avi" />
  521 + </biometric-signature>
  522 + <biometric-signature name="handwaving12-4">
  523 + <presentation Label="handwaving" file-name="handwaving/person12_handwaving_d4_uncomp.avi" />
  524 + </biometric-signature>
  525 + <biometric-signature name="handwaving13-1">
  526 + <presentation Label="handwaving" file-name="handwaving/person13_handwaving_d1_uncomp.avi" />
  527 + </biometric-signature>
  528 + <biometric-signature name="handwaving13-2">
  529 + <presentation Label="handwaving" file-name="handwaving/person13_handwaving_d2_uncomp.avi" />
  530 + </biometric-signature>
  531 + <biometric-signature name="handwaving13-3">
  532 + <presentation Label="handwaving" file-name="handwaving/person13_handwaving_d3_uncomp.avi" />
  533 + </biometric-signature>
  534 + <biometric-signature name="handwaving13-4">
  535 + <presentation Label="handwaving" file-name="handwaving/person13_handwaving_d4_uncomp.avi" />
  536 + </biometric-signature>
  537 + <biometric-signature name="handwaving14-1">
  538 + <presentation Label="handwaving" file-name="handwaving/person14_handwaving_d1_uncomp.avi" />
  539 + </biometric-signature>
  540 + <biometric-signature name="handwaving14-2">
  541 + <presentation Label="handwaving" file-name="handwaving/person14_handwaving_d2_uncomp.avi" />
  542 + </biometric-signature>
  543 + <biometric-signature name="handwaving14-3">
  544 + <presentation Label="handwaving" file-name="handwaving/person14_handwaving_d3_uncomp.avi" />
  545 + </biometric-signature>
  546 + <biometric-signature name="handwaving14-4">
  547 + <presentation Label="handwaving" file-name="handwaving/person14_handwaving_d4_uncomp.avi" />
  548 + </biometric-signature>
  549 + <biometric-signature name="handwaving15-1">
  550 + <presentation Label="handwaving" file-name="handwaving/person15_handwaving_d1_uncomp.avi" />
  551 + </biometric-signature>
  552 + <biometric-signature name="handwaving15-2">
  553 + <presentation Label="handwaving" file-name="handwaving/person15_handwaving_d2_uncomp.avi" />
  554 + </biometric-signature>
  555 + <biometric-signature name="handwaving15-3">
  556 + <presentation Label="handwaving" file-name="handwaving/person15_handwaving_d3_uncomp.avi" />
  557 + </biometric-signature>
  558 + <biometric-signature name="handwaving15-4">
  559 + <presentation Label="handwaving" file-name="handwaving/person15_handwaving_d4_uncomp.avi" />
  560 + </biometric-signature>
  561 + <biometric-signature name="handwaving16-1">
  562 + <presentation Label="handwaving" file-name="handwaving/person16_handwaving_d1_uncomp.avi" />
  563 + </biometric-signature>
  564 + <biometric-signature name="handwaving16-2">
  565 + <presentation Label="handwaving" file-name="handwaving/person16_handwaving_d2_uncomp.avi" />
  566 + </biometric-signature>
  567 + <biometric-signature name="handwaving16-3">
  568 + <presentation Label="handwaving" file-name="handwaving/person16_handwaving_d3_uncomp.avi" />
  569 + </biometric-signature>
  570 + <biometric-signature name="handwaving16-4">
  571 + <presentation Label="handwaving" file-name="handwaving/person16_handwaving_d4_uncomp.avi" />
  572 + </biometric-signature>
  573 + <biometric-signature name="jogging1-1">
  574 + <presentation Label="jogging" file-name="jogging/person01_jogging_d1_uncomp.avi" />
  575 + </biometric-signature>
  576 + <biometric-signature name="jogging1-2">
  577 + <presentation Label="jogging" file-name="jogging/person01_jogging_d2_uncomp.avi" />
  578 + </biometric-signature>
  579 + <biometric-signature name="jogging1-3">
  580 + <presentation Label="jogging" file-name="jogging/person01_jogging_d3_uncomp.avi" />
  581 + </biometric-signature>
  582 + <biometric-signature name="jogging1-4">
  583 + <presentation Label="jogging" file-name="jogging/person01_jogging_d4_uncomp.avi" />
  584 + </biometric-signature>
  585 + <biometric-signature name="jogging2-1">
  586 + <presentation Label="jogging" file-name="jogging/person02_jogging_d1_uncomp.avi" />
  587 + </biometric-signature>
  588 + <biometric-signature name="jogging2-2">
  589 + <presentation Label="jogging" file-name="jogging/person02_jogging_d2_uncomp.avi" />
  590 + </biometric-signature>
  591 + <biometric-signature name="jogging2-3">
  592 + <presentation Label="jogging" file-name="jogging/person02_jogging_d3_uncomp.avi" />
  593 + </biometric-signature>
  594 + <biometric-signature name="jogging2-4">
  595 + <presentation Label="jogging" file-name="jogging/person02_jogging_d4_uncomp.avi" />
  596 + </biometric-signature>
  597 + <biometric-signature name="jogging3-1">
  598 + <presentation Label="jogging" file-name="jogging/person03_jogging_d1_uncomp.avi" />
  599 + </biometric-signature>
  600 + <biometric-signature name="jogging3-2">
  601 + <presentation Label="jogging" file-name="jogging/person03_jogging_d2_uncomp.avi" />
  602 + </biometric-signature>
  603 + <biometric-signature name="jogging3-3">
  604 + <presentation Label="jogging" file-name="jogging/person03_jogging_d3_uncomp.avi" />
  605 + </biometric-signature>
  606 + <biometric-signature name="jogging3-4">
  607 + <presentation Label="jogging" file-name="jogging/person03_jogging_d4_uncomp.avi" />
  608 + </biometric-signature>
  609 + <biometric-signature name="jogging4-1">
  610 + <presentation Label="jogging" file-name="jogging/person04_jogging_d1_uncomp.avi" />
  611 + </biometric-signature>
  612 + <biometric-signature name="jogging4-2">
  613 + <presentation Label="jogging" file-name="jogging/person04_jogging_d2_uncomp.avi" />
  614 + </biometric-signature>
  615 + <biometric-signature name="jogging4-3">
  616 + <presentation Label="jogging" file-name="jogging/person04_jogging_d3_uncomp.avi" />
  617 + </biometric-signature>
  618 + <biometric-signature name="jogging4-4">
  619 + <presentation Label="jogging" file-name="jogging/person04_jogging_d4_uncomp.avi" />
  620 + </biometric-signature>
  621 + <biometric-signature name="jogging5-1">
  622 + <presentation Label="jogging" file-name="jogging/person05_jogging_d1_uncomp.avi" />
  623 + </biometric-signature>
  624 + <biometric-signature name="jogging5-2">
  625 + <presentation Label="jogging" file-name="jogging/person05_jogging_d2_uncomp.avi" />
  626 + </biometric-signature>
  627 + <biometric-signature name="jogging5-3">
  628 + <presentation Label="jogging" file-name="jogging/person05_jogging_d3_uncomp.avi" />
  629 + </biometric-signature>
  630 + <biometric-signature name="jogging5-4">
  631 + <presentation Label="jogging" file-name="jogging/person05_jogging_d4_uncomp.avi" />
  632 + </biometric-signature>
  633 + <biometric-signature name="jogging6-1">
  634 + <presentation Label="jogging" file-name="jogging/person06_jogging_d1_uncomp.avi" />
  635 + </biometric-signature>
  636 + <biometric-signature name="jogging6-2">
  637 + <presentation Label="jogging" file-name="jogging/person06_jogging_d2_uncomp.avi" />
  638 + </biometric-signature>
  639 + <biometric-signature name="jogging6-3">
  640 + <presentation Label="jogging" file-name="jogging/person06_jogging_d3_uncomp.avi" />
  641 + </biometric-signature>
  642 + <biometric-signature name="jogging6-4">
  643 + <presentation Label="jogging" file-name="jogging/person06_jogging_d4_uncomp.avi" />
  644 + </biometric-signature>
  645 + <biometric-signature name="jogging7-1">
  646 + <presentation Label="jogging" file-name="jogging/person07_jogging_d1_uncomp.avi" />
  647 + </biometric-signature>
  648 + <biometric-signature name="jogging7-2">
  649 + <presentation Label="jogging" file-name="jogging/person07_jogging_d2_uncomp.avi" />
  650 + </biometric-signature>
  651 + <biometric-signature name="jogging7-3">
  652 + <presentation Label="jogging" file-name="jogging/person07_jogging_d3_uncomp.avi" />
  653 + </biometric-signature>
  654 + <biometric-signature name="jogging7-4">
  655 + <presentation Label="jogging" file-name="jogging/person07_jogging_d4_uncomp.avi" />
  656 + </biometric-signature>
  657 + <biometric-signature name="jogging8-1">
  658 + <presentation Label="jogging" file-name="jogging/person08_jogging_d1_uncomp.avi" />
  659 + </biometric-signature>
  660 + <biometric-signature name="jogging8-2">
  661 + <presentation Label="jogging" file-name="jogging/person08_jogging_d2_uncomp.avi" />
  662 + </biometric-signature>
  663 + <biometric-signature name="jogging8-3">
  664 + <presentation Label="jogging" file-name="jogging/person08_jogging_d3_uncomp.avi" />
  665 + </biometric-signature>
  666 + <biometric-signature name="jogging8-4">
  667 + <presentation Label="jogging" file-name="jogging/person08_jogging_d4_uncomp.avi" />
  668 + </biometric-signature>
  669 + <biometric-signature name="jogging9-1">
  670 + <presentation Label="jogging" file-name="jogging/person09_jogging_d1_uncomp.avi" />
  671 + </biometric-signature>
  672 + <biometric-signature name="jogging9-2">
  673 + <presentation Label="jogging" file-name="jogging/person09_jogging_d2_uncomp.avi" />
  674 + </biometric-signature>
  675 + <biometric-signature name="jogging9-3">
  676 + <presentation Label="jogging" file-name="jogging/person09_jogging_d3_uncomp.avi" />
  677 + </biometric-signature>
  678 + <biometric-signature name="jogging9-4">
  679 + <presentation Label="jogging" file-name="jogging/person09_jogging_d4_uncomp.avi" />
  680 + </biometric-signature>
  681 + <biometric-signature name="jogging10-1">
  682 + <presentation Label="jogging" file-name="jogging/person10_jogging_d1_uncomp.avi" />
  683 + </biometric-signature>
  684 + <biometric-signature name="jogging10-2">
  685 + <presentation Label="jogging" file-name="jogging/person10_jogging_d2_uncomp.avi" />
  686 + </biometric-signature>
  687 + <biometric-signature name="jogging10-3">
  688 + <presentation Label="jogging" file-name="jogging/person10_jogging_d3_uncomp.avi" />
  689 + </biometric-signature>
  690 + <biometric-signature name="jogging10-4">
  691 + <presentation Label="jogging" file-name="jogging/person10_jogging_d4_uncomp.avi" />
  692 + </biometric-signature>
  693 + <biometric-signature name="jogging11-1">
  694 + <presentation Label="jogging" file-name="jogging/person11_jogging_d1_uncomp.avi" />
  695 + </biometric-signature>
  696 + <biometric-signature name="jogging11-2">
  697 + <presentation Label="jogging" file-name="jogging/person11_jogging_d2_uncomp.avi" />
  698 + </biometric-signature>
  699 + <biometric-signature name="jogging11-3">
  700 + <presentation Label="jogging" file-name="jogging/person11_jogging_d3_uncomp.avi" />
  701 + </biometric-signature>
  702 + <biometric-signature name="jogging11-4">
  703 + <presentation Label="jogging" file-name="jogging/person11_jogging_d4_uncomp.avi" />
  704 + </biometric-signature>
  705 + <biometric-signature name="jogging12-1">
  706 + <presentation Label="jogging" file-name="jogging/person12_jogging_d1_uncomp.avi" />
  707 + </biometric-signature>
  708 + <biometric-signature name="jogging12-2">
  709 + <presentation Label="jogging" file-name="jogging/person12_jogging_d2_uncomp.avi" />
  710 + </biometric-signature>
  711 + <biometric-signature name="jogging12-3">
  712 + <presentation Label="jogging" file-name="jogging/person12_jogging_d3_uncomp.avi" />
  713 + </biometric-signature>
  714 + <biometric-signature name="jogging12-4">
  715 + <presentation Label="jogging" file-name="jogging/person12_jogging_d4_uncomp.avi" />
  716 + </biometric-signature>
  717 + <biometric-signature name="jogging13-1">
  718 + <presentation Label="jogging" file-name="jogging/person13_jogging_d1_uncomp.avi" />
  719 + </biometric-signature>
  720 + <biometric-signature name="jogging13-2">
  721 + <presentation Label="jogging" file-name="jogging/person13_jogging_d2_uncomp.avi" />
  722 + </biometric-signature>
  723 + <biometric-signature name="jogging13-3">
  724 + <presentation Label="jogging" file-name="jogging/person13_jogging_d3_uncomp.avi" />
  725 + </biometric-signature>
  726 + <biometric-signature name="jogging13-4">
  727 + <presentation Label="jogging" file-name="jogging/person13_jogging_d4_uncomp.avi" />
  728 + </biometric-signature>
  729 + <biometric-signature name="jogging14-1">
  730 + <presentation Label="jogging" file-name="jogging/person14_jogging_d1_uncomp.avi" />
  731 + </biometric-signature>
  732 + <biometric-signature name="jogging14-2">
  733 + <presentation Label="jogging" file-name="jogging/person14_jogging_d2_uncomp.avi" />
  734 + </biometric-signature>
  735 + <biometric-signature name="jogging14-3">
  736 + <presentation Label="jogging" file-name="jogging/person14_jogging_d3_uncomp.avi" />
  737 + </biometric-signature>
  738 + <biometric-signature name="jogging14-4">
  739 + <presentation Label="jogging" file-name="jogging/person14_jogging_d4_uncomp.avi" />
  740 + </biometric-signature>
  741 + <biometric-signature name="jogging15-1">
  742 + <presentation Label="jogging" file-name="jogging/person15_jogging_d1_uncomp.avi" />
  743 + </biometric-signature>
  744 + <biometric-signature name="jogging15-2">
  745 + <presentation Label="jogging" file-name="jogging/person15_jogging_d2_uncomp.avi" />
  746 + </biometric-signature>
  747 + <biometric-signature name="jogging15-3">
  748 + <presentation Label="jogging" file-name="jogging/person15_jogging_d3_uncomp.avi" />
  749 + </biometric-signature>
  750 + <biometric-signature name="jogging15-4">
  751 + <presentation Label="jogging" file-name="jogging/person15_jogging_d4_uncomp.avi" />
  752 + </biometric-signature>
  753 + <biometric-signature name="jogging16-1">
  754 + <presentation Label="jogging" file-name="jogging/person16_jogging_d1_uncomp.avi" />
  755 + </biometric-signature>
  756 + <biometric-signature name="jogging16-2">
  757 + <presentation Label="jogging" file-name="jogging/person16_jogging_d2_uncomp.avi" />
  758 + </biometric-signature>
  759 + <biometric-signature name="jogging16-3">
  760 + <presentation Label="jogging" file-name="jogging/person16_jogging_d3_uncomp.avi" />
  761 + </biometric-signature>
  762 + <biometric-signature name="jogging16-4">
  763 + <presentation Label="jogging" file-name="jogging/person16_jogging_d4_uncomp.avi" />
  764 + </biometric-signature>
  765 + <biometric-signature name="running1-1">
  766 + <presentation Label="running" file-name="running/person01_running_d1_uncomp.avi" />
  767 + </biometric-signature>
  768 + <biometric-signature name="running1-2">
  769 + <presentation Label="running" file-name="running/person01_running_d2_uncomp.avi" />
  770 + </biometric-signature>
  771 + <biometric-signature name="running1-3">
  772 + <presentation Label="running" file-name="running/person01_running_d3_uncomp.avi" />
  773 + </biometric-signature>
  774 + <biometric-signature name="running1-4">
  775 + <presentation Label="running" file-name="running/person01_running_d4_uncomp.avi" />
  776 + </biometric-signature>
  777 + <biometric-signature name="running2-1">
  778 + <presentation Label="running" file-name="running/person02_running_d1_uncomp.avi" />
  779 + </biometric-signature>
  780 + <biometric-signature name="running2-2">
  781 + <presentation Label="running" file-name="running/person02_running_d2_uncomp.avi" />
  782 + </biometric-signature>
  783 + <biometric-signature name="running2-3">
  784 + <presentation Label="running" file-name="running/person02_running_d3_uncomp.avi" />
  785 + </biometric-signature>
  786 + <biometric-signature name="running2-4">
  787 + <presentation Label="running" file-name="running/person02_running_d4_uncomp.avi" />
  788 + </biometric-signature>
  789 + <biometric-signature name="running3-1">
  790 + <presentation Label="running" file-name="running/person03_running_d1_uncomp.avi" />
  791 + </biometric-signature>
  792 + <biometric-signature name="running3-2">
  793 + <presentation Label="running" file-name="running/person03_running_d2_uncomp.avi" />
  794 + </biometric-signature>
  795 + <biometric-signature name="running3-3">
  796 + <presentation Label="running" file-name="running/person03_running_d3_uncomp.avi" />
  797 + </biometric-signature>
  798 + <biometric-signature name="running3-4">
  799 + <presentation Label="running" file-name="running/person03_running_d4_uncomp.avi" />
  800 + </biometric-signature>
  801 + <biometric-signature name="running4-1">
  802 + <presentation Label="running" file-name="running/person04_running_d1_uncomp.avi" />
  803 + </biometric-signature>
  804 + <biometric-signature name="running4-2">
  805 + <presentation Label="running" file-name="running/person04_running_d2_uncomp.avi" />
  806 + </biometric-signature>
  807 + <biometric-signature name="running4-3">
  808 + <presentation Label="running" file-name="running/person04_running_d3_uncomp.avi" />
  809 + </biometric-signature>
  810 + <biometric-signature name="running4-4">
  811 + <presentation Label="running" file-name="running/person04_running_d4_uncomp.avi" />
  812 + </biometric-signature>
  813 + <biometric-signature name="running5-1">
  814 + <presentation Label="running" file-name="running/person05_running_d1_uncomp.avi" />
  815 + </biometric-signature>
  816 + <biometric-signature name="running5-2">
  817 + <presentation Label="running" file-name="running/person05_running_d2_uncomp.avi" />
  818 + </biometric-signature>
  819 + <biometric-signature name="running5-3">
  820 + <presentation Label="running" file-name="running/person05_running_d3_uncomp.avi" />
  821 + </biometric-signature>
  822 + <biometric-signature name="running5-4">
  823 + <presentation Label="running" file-name="running/person05_running_d4_uncomp.avi" />
  824 + </biometric-signature>
  825 + <biometric-signature name="running6-1">
  826 + <presentation Label="running" file-name="running/person06_running_d1_uncomp.avi" />
  827 + </biometric-signature>
  828 + <biometric-signature name="running6-2">
  829 + <presentation Label="running" file-name="running/person06_running_d2_uncomp.avi" />
  830 + </biometric-signature>
  831 + <biometric-signature name="running6-3">
  832 + <presentation Label="running" file-name="running/person06_running_d3_uncomp.avi" />
  833 + </biometric-signature>
  834 + <biometric-signature name="running6-4">
  835 + <presentation Label="running" file-name="running/person06_running_d4_uncomp.avi" />
  836 + </biometric-signature>
  837 + <biometric-signature name="running7-1">
  838 + <presentation Label="running" file-name="running/person07_running_d1_uncomp.avi" />
  839 + </biometric-signature>
  840 + <biometric-signature name="running7-2">
  841 + <presentation Label="running" file-name="running/person07_running_d2_uncomp.avi" />
  842 + </biometric-signature>
  843 + <biometric-signature name="running7-3">
  844 + <presentation Label="running" file-name="running/person07_running_d3_uncomp.avi" />
  845 + </biometric-signature>
  846 + <biometric-signature name="running7-4">
  847 + <presentation Label="running" file-name="running/person07_running_d4_uncomp.avi" />
  848 + </biometric-signature>
  849 + <biometric-signature name="running8-1">
  850 + <presentation Label="running" file-name="running/person08_running_d1_uncomp.avi" />
  851 + </biometric-signature>
  852 + <biometric-signature name="running8-2">
  853 + <presentation Label="running" file-name="running/person08_running_d2_uncomp.avi" />
  854 + </biometric-signature>
  855 + <biometric-signature name="running8-3">
  856 + <presentation Label="running" file-name="running/person08_running_d3_uncomp.avi" />
  857 + </biometric-signature>
  858 + <biometric-signature name="running8-4">
  859 + <presentation Label="running" file-name="running/person08_running_d4_uncomp.avi" />
  860 + </biometric-signature>
  861 + <biometric-signature name="running9-1">
  862 + <presentation Label="running" file-name="running/person09_running_d1_uncomp.avi" />
  863 + </biometric-signature>
  864 + <biometric-signature name="running9-2">
  865 + <presentation Label="running" file-name="running/person09_running_d2_uncomp.avi" />
  866 + </biometric-signature>
  867 + <biometric-signature name="running9-3">
  868 + <presentation Label="running" file-name="running/person09_running_d3_uncomp.avi" />
  869 + </biometric-signature>
  870 + <biometric-signature name="running9-4">
  871 + <presentation Label="running" file-name="running/person09_running_d4_uncomp.avi" />
  872 + </biometric-signature>
  873 + <biometric-signature name="running10-1">
  874 + <presentation Label="running" file-name="running/person10_running_d1_uncomp.avi" />
  875 + </biometric-signature>
  876 + <biometric-signature name="running10-2">
  877 + <presentation Label="running" file-name="running/person10_running_d2_uncomp.avi" />
  878 + </biometric-signature>
  879 + <biometric-signature name="running10-3">
  880 + <presentation Label="running" file-name="running/person10_running_d3_uncomp.avi" />
  881 + </biometric-signature>
  882 + <biometric-signature name="running10-4">
  883 + <presentation Label="running" file-name="running/person10_running_d4_uncomp.avi" />
  884 + </biometric-signature>
  885 + <biometric-signature name="running11-1">
  886 + <presentation Label="running" file-name="running/person11_running_d1_uncomp.avi" />
  887 + </biometric-signature>
  888 + <biometric-signature name="running11-2">
  889 + <presentation Label="running" file-name="running/person11_running_d2_uncomp.avi" />
  890 + </biometric-signature>
  891 + <biometric-signature name="running11-3">
  892 + <presentation Label="running" file-name="running/person11_running_d3_uncomp.avi" />
  893 + </biometric-signature>
  894 + <biometric-signature name="running11-4">
  895 + <presentation Label="running" file-name="running/person11_running_d4_uncomp.avi" />
  896 + </biometric-signature>
  897 + <biometric-signature name="running12-1">
  898 + <presentation Label="running" file-name="running/person12_running_d1_uncomp.avi" />
  899 + </biometric-signature>
  900 + <biometric-signature name="running12-2">
  901 + <presentation Label="running" file-name="running/person12_running_d2_uncomp.avi" />
  902 + </biometric-signature>
  903 + <biometric-signature name="running12-3">
  904 + <presentation Label="running" file-name="running/person12_running_d3_uncomp.avi" />
  905 + </biometric-signature>
  906 + <biometric-signature name="running12-4">
  907 + <presentation Label="running" file-name="running/person12_running_d4_uncomp.avi" />
  908 + </biometric-signature>
  909 + <biometric-signature name="running13-1">
  910 + <presentation Label="running" file-name="running/person13_running_d1_uncomp.avi" />
  911 + </biometric-signature>
  912 + <biometric-signature name="running13-2">
  913 + <presentation Label="running" file-name="running/person13_running_d2_uncomp.avi" />
  914 + </biometric-signature>
  915 + <biometric-signature name="running13-3">
  916 + <presentation Label="running" file-name="running/person13_running_d3_uncomp.avi" />
  917 + </biometric-signature>
  918 + <biometric-signature name="running13-4">
  919 + <presentation Label="running" file-name="running/person13_running_d4_uncomp.avi" />
  920 + </biometric-signature>
  921 + <biometric-signature name="running14-1">
  922 + <presentation Label="running" file-name="running/person14_running_d1_uncomp.avi" />
  923 + </biometric-signature>
  924 + <biometric-signature name="running14-2">
  925 + <presentation Label="running" file-name="running/person14_running_d2_uncomp.avi" />
  926 + </biometric-signature>
  927 + <biometric-signature name="running14-3">
  928 + <presentation Label="running" file-name="running/person14_running_d3_uncomp.avi" />
  929 + </biometric-signature>
  930 + <biometric-signature name="running14-4">
  931 + <presentation Label="running" file-name="running/person14_running_d4_uncomp.avi" />
  932 + </biometric-signature>
  933 + <biometric-signature name="running15-1">
  934 + <presentation Label="running" file-name="running/person15_running_d1_uncomp.avi" />
  935 + </biometric-signature>
  936 + <biometric-signature name="running15-2">
  937 + <presentation Label="running" file-name="running/person15_running_d2_uncomp.avi" />
  938 + </biometric-signature>
  939 + <biometric-signature name="running15-3">
  940 + <presentation Label="running" file-name="running/person15_running_d3_uncomp.avi" />
  941 + </biometric-signature>
  942 + <biometric-signature name="running15-4">
  943 + <presentation Label="running" file-name="running/person15_running_d4_uncomp.avi" />
  944 + </biometric-signature>
  945 + <biometric-signature name="running16-1">
  946 + <presentation Label="running" file-name="running/person16_running_d1_uncomp.avi" />
  947 + </biometric-signature>
  948 + <biometric-signature name="running16-2">
  949 + <presentation Label="running" file-name="running/person16_running_d2_uncomp.avi" />
  950 + </biometric-signature>
  951 + <biometric-signature name="running16-3">
  952 + <presentation Label="running" file-name="running/person16_running_d3_uncomp.avi" />
  953 + </biometric-signature>
  954 + <biometric-signature name="running16-4">
  955 + <presentation Label="running" file-name="running/person16_running_d4_uncomp.avi" />
  956 + </biometric-signature>
  957 + <biometric-signature name="walking1-1">
  958 + <presentation Label="walking" file-name="walking/person01_walking_d1_uncomp.avi" />
  959 + </biometric-signature>
  960 + <biometric-signature name="walking1-2">
  961 + <presentation Label="walking" file-name="walking/person01_walking_d2_uncomp.avi" />
  962 + </biometric-signature>
  963 + <biometric-signature name="walking1-3">
  964 + <presentation Label="walking" file-name="walking/person01_walking_d3_uncomp.avi" />
  965 + </biometric-signature>
  966 + <biometric-signature name="walking1-4">
  967 + <presentation Label="walking" file-name="walking/person01_walking_d4_uncomp.avi" />
  968 + </biometric-signature>
  969 + <biometric-signature name="walking2-1">
  970 + <presentation Label="walking" file-name="walking/person02_walking_d1_uncomp.avi" />
  971 + </biometric-signature>
  972 + <biometric-signature name="walking2-2">
  973 + <presentation Label="walking" file-name="walking/person02_walking_d2_uncomp.avi" />
  974 + </biometric-signature>
  975 + <biometric-signature name="walking2-3">
  976 + <presentation Label="walking" file-name="walking/person02_walking_d3_uncomp.avi" />
  977 + </biometric-signature>
  978 + <biometric-signature name="walking2-4">
  979 + <presentation Label="walking" file-name="walking/person02_walking_d4_uncomp.avi" />
  980 + </biometric-signature>
  981 + <biometric-signature name="walking3-1">
  982 + <presentation Label="walking" file-name="walking/person03_walking_d1_uncomp.avi" />
  983 + </biometric-signature>
  984 + <biometric-signature name="walking3-2">
  985 + <presentation Label="walking" file-name="walking/person03_walking_d2_uncomp.avi" />
  986 + </biometric-signature>
  987 + <biometric-signature name="walking3-3">
  988 + <presentation Label="walking" file-name="walking/person03_walking_d3_uncomp.avi" />
  989 + </biometric-signature>
  990 + <biometric-signature name="walking3-4">
  991 + <presentation Label="walking" file-name="walking/person03_walking_d4_uncomp.avi" />
  992 + </biometric-signature>
  993 + <biometric-signature name="walking4-1">
  994 + <presentation Label="walking" file-name="walking/person04_walking_d1_uncomp.avi" />
  995 + </biometric-signature>
  996 + <biometric-signature name="walking4-2">
  997 + <presentation Label="walking" file-name="walking/person04_walking_d2_uncomp.avi" />
  998 + </biometric-signature>
  999 + <biometric-signature name="walking4-3">
  1000 + <presentation Label="walking" file-name="walking/person04_walking_d3_uncomp.avi" />
  1001 + </biometric-signature>
  1002 + <biometric-signature name="walking4-4">
  1003 + <presentation Label="walking" file-name="walking/person04_walking_d4_uncomp.avi" />
  1004 + </biometric-signature>
  1005 + <biometric-signature name="walking5-1">
  1006 + <presentation Label="walking" file-name="walking/person05_walking_d1_uncomp.avi" />
  1007 + </biometric-signature>
  1008 + <biometric-signature name="walking5-2">
  1009 + <presentation Label="walking" file-name="walking/person05_walking_d2_uncomp.avi" />
  1010 + </biometric-signature>
  1011 + <biometric-signature name="walking5-3">
  1012 + <presentation Label="walking" file-name="walking/person05_walking_d3_uncomp.avi" />
  1013 + </biometric-signature>
  1014 + <biometric-signature name="walking5-4">
  1015 + <presentation Label="walking" file-name="walking/person05_walking_d4_uncomp.avi" />
  1016 + </biometric-signature>
  1017 + <biometric-signature name="walking6-1">
  1018 + <presentation Label="walking" file-name="walking/person06_walking_d1_uncomp.avi" />
  1019 + </biometric-signature>
  1020 + <biometric-signature name="walking6-2">
  1021 + <presentation Label="walking" file-name="walking/person06_walking_d2_uncomp.avi" />
  1022 + </biometric-signature>
  1023 + <biometric-signature name="walking6-3">
  1024 + <presentation Label="walking" file-name="walking/person06_walking_d3_uncomp.avi" />
  1025 + </biometric-signature>
  1026 + <biometric-signature name="walking6-4">
  1027 + <presentation Label="walking" file-name="walking/person06_walking_d4_uncomp.avi" />
  1028 + </biometric-signature>
  1029 + <biometric-signature name="walking7-1">
  1030 + <presentation Label="walking" file-name="walking/person07_walking_d1_uncomp.avi" />
  1031 + </biometric-signature>
  1032 + <biometric-signature name="walking7-2">
  1033 + <presentation Label="walking" file-name="walking/person07_walking_d2_uncomp.avi" />
  1034 + </biometric-signature>
  1035 + <biometric-signature name="walking7-3">
  1036 + <presentation Label="walking" file-name="walking/person07_walking_d3_uncomp.avi" />
  1037 + </biometric-signature>
  1038 + <biometric-signature name="walking7-4">
  1039 + <presentation Label="walking" file-name="walking/person07_walking_d4_uncomp.avi" />
  1040 + </biometric-signature>
  1041 + <biometric-signature name="walking8-1">
  1042 + <presentation Label="walking" file-name="walking/person08_walking_d1_uncomp.avi" />
  1043 + </biometric-signature>
  1044 + <biometric-signature name="walking8-2">
  1045 + <presentation Label="walking" file-name="walking/person08_walking_d2_uncomp.avi" />
  1046 + </biometric-signature>
  1047 + <biometric-signature name="walking8-3">
  1048 + <presentation Label="walking" file-name="walking/person08_walking_d3_uncomp.avi" />
  1049 + </biometric-signature>
  1050 + <biometric-signature name="walking8-4">
  1051 + <presentation Label="walking" file-name="walking/person08_walking_d4_uncomp.avi" />
  1052 + </biometric-signature>
  1053 + <biometric-signature name="walking9-1">
  1054 + <presentation Label="walking" file-name="walking/person09_walking_d1_uncomp.avi" />
  1055 + </biometric-signature>
  1056 + <biometric-signature name="walking9-2">
  1057 + <presentation Label="walking" file-name="walking/person09_walking_d2_uncomp.avi" />
  1058 + </biometric-signature>
  1059 + <biometric-signature name="walking9-3">
  1060 + <presentation Label="walking" file-name="walking/person09_walking_d3_uncomp.avi" />
  1061 + </biometric-signature>
  1062 + <biometric-signature name="walking9-4">
  1063 + <presentation Label="walking" file-name="walking/person09_walking_d4_uncomp.avi" />
  1064 + </biometric-signature>
  1065 + <biometric-signature name="walking10-1">
  1066 + <presentation Label="walking" file-name="walking/person10_walking_d1_uncomp.avi" />
  1067 + </biometric-signature>
  1068 + <biometric-signature name="walking10-2">
  1069 + <presentation Label="walking" file-name="walking/person10_walking_d2_uncomp.avi" />
  1070 + </biometric-signature>
  1071 + <biometric-signature name="walking10-3">
  1072 + <presentation Label="walking" file-name="walking/person10_walking_d3_uncomp.avi" />
  1073 + </biometric-signature>
  1074 + <biometric-signature name="walking10-4">
  1075 + <presentation Label="walking" file-name="walking/person10_walking_d4_uncomp.avi" />
  1076 + </biometric-signature>
  1077 + <biometric-signature name="walking11-1">
  1078 + <presentation Label="walking" file-name="walking/person11_walking_d1_uncomp.avi" />
  1079 + </biometric-signature>
  1080 + <biometric-signature name="walking11-2">
  1081 + <presentation Label="walking" file-name="walking/person11_walking_d2_uncomp.avi" />
  1082 + </biometric-signature>
  1083 + <biometric-signature name="walking11-3">
  1084 + <presentation Label="walking" file-name="walking/person11_walking_d3_uncomp.avi" />
  1085 + </biometric-signature>
  1086 + <biometric-signature name="walking11-4">
  1087 + <presentation Label="walking" file-name="walking/person11_walking_d4_uncomp.avi" />
  1088 + </biometric-signature>
  1089 + <biometric-signature name="walking12-1">
  1090 + <presentation Label="walking" file-name="walking/person12_walking_d1_uncomp.avi" />
  1091 + </biometric-signature>
  1092 + <biometric-signature name="walking12-2">
  1093 + <presentation Label="walking" file-name="walking/person12_walking_d2_uncomp.avi" />
  1094 + </biometric-signature>
  1095 + <biometric-signature name="walking12-3">
  1096 + <presentation Label="walking" file-name="walking/person12_walking_d3_uncomp.avi" />
  1097 + </biometric-signature>
  1098 + <biometric-signature name="walking12-4">
  1099 + <presentation Label="walking" file-name="walking/person12_walking_d4_uncomp.avi" />
  1100 + </biometric-signature>
  1101 + <biometric-signature name="walking13-1">
  1102 + <presentation Label="walking" file-name="walking/person13_walking_d1_uncomp.avi" />
  1103 + </biometric-signature>
  1104 + <biometric-signature name="walking13-2">
  1105 + <presentation Label="walking" file-name="walking/person13_walking_d2_uncomp.avi" />
  1106 + </biometric-signature>
  1107 + <biometric-signature name="walking13-3">
  1108 + <presentation Label="walking" file-name="walking/person13_walking_d3_uncomp.avi" />
  1109 + </biometric-signature>
  1110 + <biometric-signature name="walking13-4">
  1111 + <presentation Label="walking" file-name="walking/person13_walking_d4_uncomp.avi" />
  1112 + </biometric-signature>
  1113 + <biometric-signature name="walking14-1">
  1114 + <presentation Label="walking" file-name="walking/person14_walking_d1_uncomp.avi" />
  1115 + </biometric-signature>
  1116 + <biometric-signature name="walking14-2">
  1117 + <presentation Label="walking" file-name="walking/person14_walking_d2_uncomp.avi" />
  1118 + </biometric-signature>
  1119 + <biometric-signature name="walking14-3">
  1120 + <presentation Label="walking" file-name="walking/person14_walking_d3_uncomp.avi" />
  1121 + </biometric-signature>
  1122 + <biometric-signature name="walking14-4">
  1123 + <presentation Label="walking" file-name="walking/person14_walking_d4_uncomp.avi" />
  1124 + </biometric-signature>
  1125 + <biometric-signature name="walking15-1">
  1126 + <presentation Label="walking" file-name="walking/person15_walking_d1_uncomp.avi" />
  1127 + </biometric-signature>
  1128 + <biometric-signature name="walking15-2">
  1129 + <presentation Label="walking" file-name="walking/person15_walking_d2_uncomp.avi" />
  1130 + </biometric-signature>
  1131 + <biometric-signature name="walking15-3">
  1132 + <presentation Label="walking" file-name="walking/person15_walking_d3_uncomp.avi" />
  1133 + </biometric-signature>
  1134 + <biometric-signature name="walking15-4">
  1135 + <presentation Label="walking" file-name="walking/person15_walking_d4_uncomp.avi" />
  1136 + </biometric-signature>
  1137 + <biometric-signature name="walking16-1">
  1138 + <presentation Label="walking" file-name="walking/person16_walking_d1_uncomp.avi" />
  1139 + </biometric-signature>
  1140 + <biometric-signature name="walking16-2">
  1141 + <presentation Label="walking" file-name="walking/person16_walking_d2_uncomp.avi" />
  1142 + </biometric-signature>
  1143 + <biometric-signature name="walking16-3">
  1144 + <presentation Label="walking" file-name="walking/person16_walking_d3_uncomp.avi" />
  1145 + </biometric-signature>
  1146 + <biometric-signature name="walking16-4">
  1147 + <presentation Label="walking" file-name="walking/person16_walking_d4_uncomp.avi" />
  1148 + </biometric-signature>
  1149 +</biometric-signature-set>
openbr/core/bee.cpp
@@ -99,10 +99,10 @@ void BEE::writeSigset(const QString &amp;sigset, const br::FileList &amp;files, bool ign @@ -99,10 +99,10 @@ void BEE::writeSigset(const QString &amp;sigset, const br::FileList &amp;files, bool ign
99 QStringList metadata; 99 QStringList metadata;
100 if (!ignoreMetadata) 100 if (!ignoreMetadata)
101 foreach (const QString &key, file.localKeys()) { 101 foreach (const QString &key, file.localKeys()) {
102 - if ((key == "Index") || (key == "Subject")) continue; 102 + if ((key == "Index") || (key == "Label")) continue;
103 metadata.append(key+"=\""+QtUtils::toString(file.value(key))+"\""); 103 metadata.append(key+"=\""+QtUtils::toString(file.value(key))+"\"");
104 } 104 }
105 - lines.append("\t<biometric-signature name=\"" + file.get<QString>("Subject",file.fileName()) +"\">"); 105 + lines.append("\t<biometric-signature name=\"" + file.get<QString>("Label",file.fileName()) +"\">");
106 lines.append("\t\t<presentation file-name=\"" + file.name + "\" " + metadata.join(" ") + "/>"); 106 lines.append("\t\t<presentation file-name=\"" + file.name + "\" " + metadata.join(" ") + "/>");
107 lines.append("\t</biometric-signature>"); 107 lines.append("\t</biometric-signature>");
108 } 108 }
@@ -266,10 +266,11 @@ void BEE::makeMask(const QString &amp;targetInput, const QString &amp;queryInput, const @@ -266,10 +266,11 @@ void BEE::makeMask(const QString &amp;targetInput, const QString &amp;queryInput, const
266 266
267 cv::Mat BEE::makeMask(const br::FileList &targets, const br::FileList &queries, int partition) 267 cv::Mat BEE::makeMask(const br::FileList &targets, const br::FileList &queries, int partition)
268 { 268 {
269 - // Would like to use indexProperty for this, but didn't make a version of that for Filelist yet  
270 - // -cao  
271 - QList<QString> targetLabels = File::get<QString>(targets, "Subject", "-1");  
272 - QList<QString> queryLabels = File::get<QString>(queries, "Subject", "-1"); 269 + // Direct use of "Label" isn't general, also would prefer to use indexProperty, rather than
  270 + // doing string comparisons (but that isn't implemented yet for FileList) -cao
  271 + QList<QString> targetLabels = File::get<QString>(targets, "Label", "-1");
  272 + QList<QString> queryLabels = File::get<QString>(queries, "Label", "-1");
  273 +
273 QList<int> targetPartitions = targets.crossValidationPartitions(); 274 QList<int> targetPartitions = targets.crossValidationPartitions();
274 QList<int> queryPartitions = queries.crossValidationPartitions(); 275 QList<int> queryPartitions = queries.crossValidationPartitions();
275 276
openbr/core/cluster.cpp
@@ -279,8 +279,8 @@ void br::EvalClustering(const QString &amp;csv, const QString &amp;input) @@ -279,8 +279,8 @@ void br::EvalClustering(const QString &amp;csv, const QString &amp;input)
279 qDebug("Evaluating %s against %s", qPrintable(csv), qPrintable(input)); 279 qDebug("Evaluating %s against %s", qPrintable(csv), qPrintable(input));
280 280
281 // We assume clustering algorithms store assigned cluster labels as integers (since the clusters are 281 // We assume clustering algorithms store assigned cluster labels as integers (since the clusters are
282 - // not named).  
283 - QList<int> labels = File::get<int>(TemplateList::fromGallery(input), "Subject"); 282 + // not named). Direct use of ClusterID is not general -cao
  283 + QList<int> labels = File::get<int>(TemplateList::fromGallery(input), "ClusterID");
284 284
285 QHash<int, int> labelToIndex; 285 QHash<int, int> labelToIndex;
286 int nClusters = 0; 286 int nClusters = 0;
openbr/core/common.cpp
@@ -15,11 +15,15 @@ @@ -15,11 +15,15 @@
15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16
17 #include "common.h" 17 #include "common.h"
  18 +#include <QMutex>
18 19
19 using namespace std; 20 using namespace std;
20 21
21 /**** GLOBAL ****/ 22 /**** GLOBAL ****/
22 void Common::seedRNG() { 23 void Common::seedRNG() {
  24 + static QMutex seedControl;
  25 + QMutexLocker lock(&seedControl);
  26 +
23 static bool seeded = false; 27 static bool seeded = false;
24 if (!seeded) { 28 if (!seeded) {
25 srand(0); // We seed with 0 instead of time(NULL) to have reproducible randomness 29 srand(0); // We seed with 0 instead of time(NULL) to have reproducible randomness
@@ -29,8 +33,6 @@ void Common::seedRNG() { @@ -29,8 +33,6 @@ void Common::seedRNG() {
29 33
30 QList<int> Common::RandSample(int n, int max, int min, bool unique) 34 QList<int> Common::RandSample(int n, int max, int min, bool unique)
31 { 35 {
32 - seedRNG();  
33 -  
34 QList<int> samples; samples.reserve(n); 36 QList<int> samples; samples.reserve(n);
35 int range = max-min; 37 int range = max-min;
36 if (range <= 0) qFatal("Non-positive range."); 38 if (range <= 0) qFatal("Non-positive range.");
@@ -50,8 +52,6 @@ QList&lt;int&gt; Common::RandSample(int n, int max, int min, bool unique) @@ -50,8 +52,6 @@ QList&lt;int&gt; Common::RandSample(int n, int max, int min, bool unique)
50 52
51 QList<int> Common::RandSample(int n, const QSet<int> &values, bool unique) 53 QList<int> Common::RandSample(int n, const QSet<int> &values, bool unique)
52 { 54 {
53 - seedRNG();  
54 -  
55 QList<int> valueList = values.toList(); 55 QList<int> valueList = values.toList();
56 if (unique && (values.size() <= n)) return valueList; 56 if (unique && (values.size() <= n)) return valueList;
57 57
openbr/core/eval.cpp
@@ -255,11 +255,22 @@ struct Counter @@ -255,11 +255,22 @@ struct Counter
255 } 255 }
256 }; 256 };
257 257
258 -void EvalClassification(const QString &predictedInput, const QString &truthInput) 258 +void EvalClassification(const QString &predictedGallery, const QString &truthGallery, QString predictedProperty, QString truthProperty)
259 { 259 {
260 - qDebug("Evaluating classification of %s against %s", qPrintable(predictedInput), qPrintable(truthInput));  
261 - TemplateList predicted(TemplateList::fromGallery(predictedInput));  
262 - TemplateList truth(TemplateList::fromGallery(truthInput)); 260 + qDebug("Evaluating classification of %s against %s", qPrintable(predictedGallery), qPrintable(truthGallery));
  261 +
  262 + if (predictedProperty.isEmpty())
  263 + predictedProperty = "Label";
  264 + // If predictedProperty is specified, but truthProperty isn't, copy over the value from
  265 + // predicted property
  266 + else if (truthProperty.isEmpty())
  267 + truthProperty = predictedProperty;
  268 +
  269 + if (truthProperty.isEmpty())
  270 + truthProperty = "Label";
  271 +
  272 + TemplateList predicted(TemplateList::fromGallery(predictedGallery));
  273 + TemplateList truth(TemplateList::fromGallery(truthGallery));
263 if (predicted.size() != truth.size()) qFatal("Input size mismatch."); 274 if (predicted.size() != truth.size()) qFatal("Input size mismatch.");
264 275
265 QHash<QString, Counter> counters; 276 QHash<QString, Counter> counters;
@@ -267,9 +278,8 @@ void EvalClassification(const QString &amp;predictedInput, const QString &amp;truthInput @@ -267,9 +278,8 @@ void EvalClassification(const QString &amp;predictedInput, const QString &amp;truthInput
267 if (predicted[i].file.name != truth[i].file.name) 278 if (predicted[i].file.name != truth[i].file.name)
268 qFatal("Input order mismatch."); 279 qFatal("Input order mismatch.");
269 280
270 - // Typically these lists will be of length one, but this generalization allows measuring multi-class labeling accuracy.  
271 - QString predictedSubject = predicted[i].file.get<QString>("Subject");  
272 - QString trueSubject = truth[i].file.get<QString>("Subject"); 281 + QString predictedSubject = predicted[i].file.get<QString>(predictedProperty);
  282 + QString trueSubject = truth[i].file.get<QString>(truthProperty);
273 283
274 QStringList predictedSubjects(predictedSubject); 284 QStringList predictedSubjects(predictedSubject);
275 QStringList trueSubjects(trueSubject); 285 QStringList trueSubjects(trueSubject);
@@ -393,11 +403,11 @@ QString getDetectKey(const TemplateList &amp;templates) @@ -393,11 +403,11 @@ QString getDetectKey(const TemplateList &amp;templates)
393 return ""; 403 return "";
394 } 404 }
395 405
396 -float EvalDetection(const QString &predictedInput, const QString &truthInput, const QString &csv) 406 +float EvalDetection(const QString &predictedGallery, const QString &truthGallery, const QString &csv)
397 { 407 {
398 - qDebug("Evaluating detection of %s against %s", qPrintable(predictedInput), qPrintable(truthInput));  
399 - const TemplateList predicted(TemplateList::fromGallery(predictedInput));  
400 - const TemplateList truth(TemplateList::fromGallery(truthInput)); 408 + qDebug("Evaluating detection of %s against %s", qPrintable(predictedGallery), qPrintable(truthGallery));
  409 + const TemplateList predicted(TemplateList::fromGallery(predictedGallery));
  410 + const TemplateList truth(TemplateList::fromGallery(truthGallery));
401 411
402 // Figure out which metadata field contains a bounding box 412 // Figure out which metadata field contains a bounding box
403 QString truthDetectKey = getDetectKey(truth); 413 QString truthDetectKey = getDetectKey(truth);
@@ -466,21 +476,48 @@ float EvalDetection(const QString &amp;predictedInput, const QString &amp;truthInput, co @@ -466,21 +476,48 @@ float EvalDetection(const QString &amp;predictedInput, const QString &amp;truthInput, co
466 return averageOverlap; 476 return averageOverlap;
467 } 477 }
468 478
469 -void EvalRegression(const QString &predictedInput, const QString &truthInput) 479 +float EvalLandmarking(const QString &predictedGallery, const QString &truthGallery, const QString &csv, int normalizationIndexA, int normalizationIndexB)
  480 +{
  481 + (void) predictedGallery;
  482 + (void) truthGallery;
  483 + (void) csv;
  484 + (void) normalizationIndexA;
  485 + (void) normalizationIndexB;
  486 +
  487 + return 0;
  488 +}
  489 +
  490 +void EvalRegression(const QString &predictedGallery, const QString &truthGallery, QString predictedProperty, QString truthProperty)
470 { 491 {
471 - qDebug("Evaluating regression of %s against %s", qPrintable(predictedInput), qPrintable(truthInput));  
472 - const TemplateList predicted(TemplateList::fromGallery(predictedInput));  
473 - const TemplateList truth(TemplateList::fromGallery(truthInput)); 492 + qDebug("Evaluating regression of %s against %s", qPrintable(predictedGallery), qPrintable(truthGallery));
  493 +
  494 + if (predictedProperty.isEmpty())
  495 + predictedProperty = "Regressor";
  496 + // If predictedProperty is specified, but truthProperty isn't, copy the value over
  497 + // rather than using the default for truthProperty
  498 + else if (truthProperty.isEmpty())
  499 + truthProperty = predictedProperty;
  500 +
  501 + if (truthProperty.isEmpty())
  502 + predictedProperty = "Regressand";
  503 +
  504 + const TemplateList predicted(TemplateList::fromGallery(predictedGallery));
  505 + const TemplateList truth(TemplateList::fromGallery(truthGallery));
474 if (predicted.size() != truth.size()) qFatal("Input size mismatch."); 506 if (predicted.size() != truth.size()) qFatal("Input size mismatch.");
475 507
476 float rmsError = 0; 508 float rmsError = 0;
  509 + float maeError = 0;
477 QStringList truthValues, predictedValues; 510 QStringList truthValues, predictedValues;
478 for (int i=0; i<predicted.size(); i++) { 511 for (int i=0; i<predicted.size(); i++) {
479 if (predicted[i].file.name != truth[i].file.name) 512 if (predicted[i].file.name != truth[i].file.name)
480 qFatal("Input order mismatch."); 513 qFatal("Input order mismatch.");
481 - rmsError += pow(predicted[i].file.get<float>("Subject")-truth[i].file.get<float>("Subject"), 2.f);  
482 - truthValues.append(QString::number(truth[i].file.get<float>("Subject")));  
483 - predictedValues.append(QString::number(predicted[i].file.get<float>("Subject"))); 514 +
  515 + float difference = predicted[i].file.get<float>(predictedProperty) - truth[i].file.get<float>(truthProperty);
  516 +
  517 + rmsError += pow(difference, 2.f);
  518 + maeError += fabsf(difference);
  519 + truthValues.append(QString::number(truth[i].file.get<float>(truthProperty)));
  520 + predictedValues.append(QString::number(predicted[i].file.get<float>(predictedProperty)));
484 } 521 }
485 522
486 QStringList rSource; 523 QStringList rSource;
@@ -500,6 +537,7 @@ void EvalRegression(const QString &amp;predictedInput, const QString &amp;truthInput) @@ -500,6 +537,7 @@ void EvalRegression(const QString &amp;predictedInput, const QString &amp;truthInput)
500 if (success) QtUtils::showFile("EvalRegression.pdf"); 537 if (success) QtUtils::showFile("EvalRegression.pdf");
501 538
502 qDebug("RMS Error = %f", sqrt(rmsError/predicted.size())); 539 qDebug("RMS Error = %f", sqrt(rmsError/predicted.size()));
  540 + qDebug("MAE = %f", maeError/predicted.size());
503 } 541 }
504 542
505 } // namespace br 543 } // namespace br
openbr/core/eval.h
@@ -26,9 +26,10 @@ namespace br @@ -26,9 +26,10 @@ namespace br
26 float Evaluate(const QString &simmat, const QString &mask = "", const QString &csv = ""); // Returns TAR @ FAR = 0.001 26 float Evaluate(const QString &simmat, const QString &mask = "", const QString &csv = ""); // Returns TAR @ FAR = 0.001
27 float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const QString &csv = "", int parition = 0); 27 float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const QString &csv = "", int parition = 0);
28 float Evaluate(const cv::Mat &scores, const cv::Mat &masks, const QString &csv = ""); 28 float Evaluate(const cv::Mat &scores, const cv::Mat &masks, const QString &csv = "");
29 - void EvalClassification(const QString &predictedInput, const QString &truthInput);  
30 - float EvalDetection(const QString &predictedInput, const QString &truthInput, const QString &csv = ""); // Return average overlap  
31 - void EvalRegression(const QString &predictedInput, const QString &truthInput); 29 + void EvalClassification(const QString &predictedGallery, const QString &truthGallery, QString predictedProperty = "", QString truthProperty = "");
  30 + float EvalDetection(const QString &predictedGallery, const QString &truthGallery, const QString &csv = ""); // Return average overlap
  31 + float EvalLandmarking(const QString &predictedGallery, const QString &truthGallery, const QString &csv = "", int normalizationIndexA = 0, int normalizationIndexB = 1); // Return average error
  32 + void EvalRegression(const QString &predictedGallery, const QString &truthGallery, QString predictedProperty = "", QString truthProperty = "");
32 } 33 }
33 34
34 #endif // __EVAL_H 35 #endif // __EVAL_H
openbr/frvt2012.cpp
@@ -132,7 +132,7 @@ int32_t SdkEstimator::estimate_age(const ONEFACE &amp;input_face, int32_t &amp;age) @@ -132,7 +132,7 @@ int32_t SdkEstimator::estimate_age(const ONEFACE &amp;input_face, int32_t &amp;age)
132 TemplateList templates; 132 TemplateList templates;
133 templates.append(templateFromONEFACE(input_face)); 133 templates.append(templateFromONEFACE(input_face));
134 templates >> *frvt2012_age_transform.data(); 134 templates >> *frvt2012_age_transform.data();
135 - age = templates.first().file.get<float>("Subject"); 135 + age = templates.first().file.get<float>("Age");
136 return templates.first().file.failed() ? 4 : 0; 136 return templates.first().file.failed() ? 4 : 0;
137 } 137 }
138 138
@@ -141,6 +141,6 @@ int32_t SdkEstimator::estimate_gender(const ONEFACE &amp;input_face, int8_t &amp;gender, @@ -141,6 +141,6 @@ int32_t SdkEstimator::estimate_gender(const ONEFACE &amp;input_face, int8_t &amp;gender,
141 TemplateList templates; 141 TemplateList templates;
142 templates.append(templateFromONEFACE(input_face)); 142 templates.append(templateFromONEFACE(input_face));
143 templates >> *frvt2012_gender_transform.data(); 143 templates >> *frvt2012_gender_transform.data();
144 - mf = gender = templates.first().file.get<QString>("Subject") == "Male" ? 0 : 1; 144 + mf = gender = templates.first().file.get<QString>("Gender") == "Male" ? 0 : 1;
145 return templates.first().file.failed() ? 4 : 0; 145 return templates.first().file.failed() ? 4 : 0;
146 } 146 }
openbr/gui/classifier.cpp
@@ -39,19 +39,23 @@ void Classifier::_classify(File file) @@ -39,19 +39,23 @@ void Classifier::_classify(File file)
39 { 39 {
40 QString key, value; 40 QString key, value;
41 foreach (const File &f, Enroll(file.flat(), File("[algorithm=" + algorithm + "]"))) { 41 foreach (const File &f, Enroll(file.flat(), File("[algorithm=" + algorithm + "]"))) {
42 - if (!f.contains("Label"))  
43 - continue;  
44 42
45 if (algorithm == "GenderClassification") { 43 if (algorithm == "GenderClassification") {
46 key = "Gender"; 44 key = "Gender";
47 - value = (f.get<QString>("Subject"));  
48 } else if (algorithm == "AgeRegression") { 45 } else if (algorithm == "AgeRegression") {
49 key = "Age"; 46 key = "Age";
50 - value = QString::number(int(f.get<float>("Subject")+0.5)) + " Years";  
51 } else { 47 } else {
52 key = algorithm; 48 key = algorithm;
53 - value = f.get<QString>("Subject");  
54 } 49 }
  50 +
  51 + if (!f.contains(key))
  52 + continue;
  53 +
  54 + if (algorithm == "AgeRegression")
  55 + value = QString::number(int(f.get<float>(key)+0.5)) + " Years";
  56 + else
  57 + value = f.get<QString>(key);
  58 +
55 break; 59 break;
56 } 60 }
57 61
openbr/openbr.cpp
@@ -72,9 +72,9 @@ float br_eval(const char *simmat, const char *mask, const char *csv) @@ -72,9 +72,9 @@ float br_eval(const char *simmat, const char *mask, const char *csv)
72 return Evaluate(simmat, mask, csv); 72 return Evaluate(simmat, mask, csv);
73 } 73 }
74 74
75 -void br_eval_classification(const char *predicted_gallery, const char *truth_gallery) 75 +void br_eval_classification(const char *predicted_gallery, const char *truth_gallery, const char *predicted_property, const char * truth_property)
76 { 76 {
77 - EvalClassification(predicted_gallery, truth_gallery); 77 + EvalClassification(predicted_gallery, truth_gallery, predicted_property, truth_property);
78 } 78 }
79 79
80 void br_eval_clustering(const char *csv, const char *gallery) 80 void br_eval_clustering(const char *csv, const char *gallery)
@@ -87,9 +87,14 @@ float br_eval_detection(const char *predicted_gallery, const char *truth_gallery @@ -87,9 +87,14 @@ float br_eval_detection(const char *predicted_gallery, const char *truth_gallery
87 return EvalDetection(predicted_gallery, truth_gallery, csv); 87 return EvalDetection(predicted_gallery, truth_gallery, csv);
88 } 88 }
89 89
90 -void br_eval_regression(const char *predicted_gallery, const char *truth_gallery) 90 +float br_eval_landmarking(const char *predicted_gallery, const char *truth_gallery, const char *csv, int normalization_index_a, int normalization_index_b)
91 { 91 {
92 - EvalRegression(predicted_gallery, truth_gallery); 92 + return EvalLandmarking(predicted_gallery, truth_gallery, csv, normalization_index_a, normalization_index_b);
  93 +}
  94 +
  95 +void br_eval_regression(const char *predicted_gallery, const char *truth_gallery, const char * predicted_property, const char * truth_property)
  96 +{
  97 + EvalRegression(predicted_gallery, truth_gallery, predicted_property, truth_property);
93 } 98 }
94 99
95 void br_finalize() 100 void br_finalize()
openbr/openbr.h
@@ -149,7 +149,7 @@ BR_EXPORT float br_eval(const char *simmat, const char *mask, const char *csv = @@ -149,7 +149,7 @@ BR_EXPORT float br_eval(const char *simmat, const char *mask, const char *csv =
149 * \param predicted_gallery The predicted br::Gallery. 149 * \param predicted_gallery The predicted br::Gallery.
150 * \param truth_gallery The ground truth br::Gallery. 150 * \param truth_gallery The ground truth br::Gallery.
151 */ 151 */
152 -BR_EXPORT void br_eval_classification(const char *predicted_gallery, const char *truth_gallery); 152 +BR_EXPORT void br_eval_classification(const char *predicted_gallery, const char *truth_gallery, const char * predicted_property="", const char * truth_property="");
153 153
154 /*! 154 /*!
155 * \brief Evaluates and prints clustering accuracy to the terminal. 155 * \brief Evaluates and prints clustering accuracy to the terminal.
@@ -169,11 +169,21 @@ BR_EXPORT void br_eval_clustering(const char *csv, const char *gallery); @@ -169,11 +169,21 @@ BR_EXPORT void br_eval_clustering(const char *csv, const char *gallery);
169 BR_EXPORT float br_eval_detection(const char *predicted_gallery, const char *truth_gallery, const char *csv = ""); 169 BR_EXPORT float br_eval_detection(const char *predicted_gallery, const char *truth_gallery, const char *csv = "");
170 170
171 /*! 171 /*!
  172 + * \brief Evaluates and prints landmarking accuracy to terminal.
  173 + * \param predicted_gallery The predicted br::Gallery.
  174 + * \param truth_gallery The ground truth br::Gallery.
  175 + * \param csv Optional \c .csv file to contain performance metrics.
  176 + * \param normalization_index_a Optional first index in the list of points to use for normalization.
  177 + * \param normalization_index_b Optional second index in the list of points to use for normalization.
  178 + */
  179 +BR_EXPORT float br_eval_landmarking(const char *predicted_gallery, const char *truth_gallery, const char *csv = "", int normalization_index_a = 0, int normalization_index_b = 1);
  180 +
  181 +/*!
172 * \brief Evaluates regression accuracy to disk. 182 * \brief Evaluates regression accuracy to disk.
173 * \param predicted_gallery The predicted br::Gallery. 183 * \param predicted_gallery The predicted br::Gallery.
174 * \param truth_gallery The ground truth br::Gallery. 184 * \param truth_gallery The ground truth br::Gallery.
175 */ 185 */
176 -BR_EXPORT void br_eval_regression(const char *predicted_gallery, const char *truth_gallery); 186 +BR_EXPORT void br_eval_regression(const char *predicted_gallery, const char *truth_gallery, const char * predicted_property="", const char * truth_property="");
177 187
178 /*! 188 /*!
179 * \brief Wraps br::Context::finalize() 189 * \brief Wraps br::Context::finalize()
openbr/openbr_export.cpp
@@ -69,7 +69,6 @@ @@ -69,7 +69,6 @@
69 $ cd bin 69 $ cd bin
70 $ export LD_LIBRARY_PATH=../lib:${LD_LIBRARY_PATH} 70 $ export LD_LIBRARY_PATH=../lib:${LD_LIBRARY_PATH}
71 $ sudo ldconfig 71 $ sudo ldconfig
72 -$ sudo cp ../share/openbr/70-yubikey.rules /etc/udev/rules.d # Only needed if you were given a license dongle.  
73 \endverbatim 72 \endverbatim
74 * \par OS X 73 * \par OS X
75 \verbatim 74 \verbatim
@@ -80,10 +79,6 @@ $ export DYLD_FRAMEWORK_PATH=../lib:${DYLD_FRAMEWORK_PATH} @@ -80,10 +79,6 @@ $ export DYLD_FRAMEWORK_PATH=../lib:${DYLD_FRAMEWORK_PATH}
80 * \par Windows 79 * \par Windows
81 * No configuration is necessary! 80 * No configuration is necessary!
82 * 81 *
83 - * \section installation_license_dongle License Dongle  
84 - * In the unlikely event that you were given a USB License Dongle, then dongle must be in the computer in order to use the SDK.  
85 - * No configuration of the dongle is needed.  
86 - *  
87 * \section installation_done Start Working 82 * \section installation_done Start Working
88 * To test for successful installation: 83 * To test for successful installation:
89 \verbatim 84 \verbatim
openbr/openbr_plugin.cpp
@@ -412,7 +412,8 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery) @@ -412,7 +412,8 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery)
412 // of target images to every partition 412 // of target images to every partition
413 newTemplates[i].file.set("Partition", -1); 413 newTemplates[i].file.set("Partition", -1);
414 } else { 414 } else {
415 - const QByteArray md5 = QCryptographicHash::hash(newTemplates[i].file.get<QString>("Subject").toLatin1(), QCryptographicHash::Md5); 415 + // Direct use of "Label" is not general -cao
  416 + const QByteArray md5 = QCryptographicHash::hash(newTemplates[i].file.get<QString>("Label").toLatin1(), QCryptographicHash::Md5);
416 // Select the right 8 hex characters so that it can be represented as a 64 bit integer without overflow 417 // Select the right 8 hex characters so that it can be represented as a 64 bit integer without overflow
417 newTemplates[i].file.set("Partition", md5.toHex().right(8).toULongLong(0, 16) % crossValidate); 418 newTemplates[i].file.set("Partition", md5.toHex().right(8).toULongLong(0, 16) % crossValidate);
418 } 419 }
@@ -890,6 +891,8 @@ void br::Context::initialize(int &amp;argc, char *argv[], QString sdkPath, bool use_ @@ -890,6 +891,8 @@ void br::Context::initialize(int &amp;argc, char *argv[], QString sdkPath, bool use_
890 891
891 qInstallMessageHandler(messageHandler); 892 qInstallMessageHandler(messageHandler);
892 893
  894 + Common::seedRNG();
  895 +
893 // Search for SDK 896 // Search for SDK
894 if (sdkPath.isEmpty()) { 897 if (sdkPath.isEmpty()) {
895 QStringList checkPaths; checkPaths << QDir::currentPath() << QCoreApplication::applicationDirPath(); 898 QStringList checkPaths; checkPaths << QDir::currentPath() << QCoreApplication::applicationDirPath();
@@ -1082,9 +1085,6 @@ Transform::Transform(bool _independent, bool _trainable) @@ -1082,9 +1085,6 @@ Transform::Transform(bool _independent, bool _trainable)
1082 { 1085 {
1083 independent = _independent; 1086 independent = _independent;
1084 trainable = _trainable; 1087 trainable = _trainable;
1085 - classes = std::numeric_limits<int>::max();  
1086 - instances = std::numeric_limits<int>::max();  
1087 - fraction = 1;  
1088 } 1088 }
1089 1089
1090 Transform *Transform::make(QString str, QObject *parent) 1090 Transform *Transform::make(QString str, QObject *parent)
@@ -1140,9 +1140,6 @@ Transform *Transform::make(QString str, QObject *parent) @@ -1140,9 +1140,6 @@ Transform *Transform::make(QString str, QObject *parent)
1140 Transform *Transform::clone() const 1140 Transform *Transform::clone() const
1141 { 1141 {
1142 Transform *clone = Factory<Transform>::make(file.flat()); 1142 Transform *clone = Factory<Transform>::make(file.flat());
1143 - clone->classes = classes;  
1144 - clone->instances = instances;  
1145 - clone->fraction = fraction;  
1146 return clone; 1143 return clone;
1147 } 1144 }
1148 1145
openbr/openbr_plugin.h
@@ -130,13 +130,6 @@ void reset_##NAME() { NAME = DEFAULT; } @@ -130,13 +130,6 @@ void reset_##NAME() { NAME = DEFAULT; }
130 * -# If the value is convertable to a floating point number then it is represented with \c float. 130 * -# If the value is convertable to a floating point number then it is represented with \c float.
131 * -# Otherwise, it is represented with \c QString. 131 * -# Otherwise, it is represented with \c QString.
132 * 132 *
133 - * The metadata keys \c Subject and \c Label have special significance in the system.  
134 - * \c Subject is a string specifying a unique identifier used to determine ground truth match/non-match.  
135 - * \c Label is a floating point value used for supervised learning.  
136 - * When the system needs labels for training, but only subjects are provided in the file metadata, the rule for generating labels is as follows.  
137 - * If the subject value can be converted to a float then do so and consider that the label.  
138 - * Otherwise, generate a unique integer ID for the string starting from zero and incrementing by one everytime another ID is needed.  
139 - *  
140 * Metadata keys fall into one of two categories: 133 * Metadata keys fall into one of two categories:
141 * - \c camelCaseKeys are inputs that specify how to process the file. 134 * - \c camelCaseKeys are inputs that specify how to process the file.
142 * - \c Capitalized_Underscored_Keys are outputs computed from processing the file. 135 * - \c Capitalized_Underscored_Keys are outputs computed from processing the file.
@@ -147,8 +140,6 @@ void reset_##NAME() { NAME = DEFAULT; } @@ -147,8 +140,6 @@ void reset_##NAME() { NAME = DEFAULT; }
147 * --- | ---- | ----------- 140 * --- | ---- | -----------
148 * separator | QString | Seperate #name into multiple files 141 * separator | QString | Seperate #name into multiple files
149 * Index | int | Index of a template in a template list 142 * Index | int | Index of a template in a template list
150 - * Subject | QString | Class name  
151 - * Label | float | Class value  
152 * Confidence | float | Classification/Regression quality 143 * Confidence | float | Classification/Regression quality
153 * FTE | bool | Failure to enroll 144 * FTE | bool | Failure to enroll
154 * FTO | bool | Failure to open 145 * FTO | bool | Failure to open
@@ -157,13 +148,15 @@ void reset_##NAME() { NAME = DEFAULT; } @@ -157,13 +148,15 @@ void reset_##NAME() { NAME = DEFAULT; }
157 * *_Width | float | Size 148 * *_Width | float | Size
158 * *_Height | float | Size 149 * *_Height | float | Size
159 * *_Radius | float | Size 150 * *_Radius | float | Size
  151 + * Label | QString | Class label
160 * Theta | float | Pose 152 * Theta | float | Pose
161 * Roll | float | Pose 153 * Roll | float | Pose
162 * Pitch | float | Pose 154 * Pitch | float | Pose
163 * Yaw | float | Pose 155 * Yaw | float | Pose
164 * Points | QList<QPointF> | List of unnamed points 156 * Points | QList<QPointF> | List of unnamed points
165 * Rects | QList<Rect> | List of unnamed rects 157 * Rects | QList<Rect> | List of unnamed rects
166 - * Age | QString | Age used for demographic filtering 158 + * Age | float | Age used for demographic filtering
  159 + * Gender | QString | Subject gender
167 * _* | * | Reserved for internal use 160 * _* | * | Reserved for internal use
168 */ 161 */
169 struct BR_EXPORT File 162 struct BR_EXPORT File
@@ -172,7 +165,7 @@ struct BR_EXPORT File @@ -172,7 +165,7 @@ struct BR_EXPORT File
172 165
173 File() {} 166 File() {}
174 File(const QString &file) { init(file); } /*!< \brief Construct a file from a string. */ 167 File(const QString &file) { init(file); } /*!< \brief Construct a file from a string. */
175 - File(const QString &file, const QVariant &subject) { init(file); set("Subject", subject); } /*!< \brief Construct a file from a string and assign a label. */ 168 + File(const QString &file, const QVariant &label) { init(file); set("Label", label); } /*!< \brief Construct a file from a string and assign a label. */
176 File(const char *file) { init(file); } /*!< \brief Construct a file from a c-style string. */ 169 File(const char *file) { init(file); } /*!< \brief Construct a file from a c-style string. */
177 inline operator QString() const { return name; } /*!< \brief Returns #name. */ 170 inline operator QString() const { return name; } /*!< \brief Returns #name. */
178 QString flat() const; /*!< \brief A stringified version of the file with metadata. */ 171 QString flat() const; /*!< \brief A stringified version of the file with metadata. */
@@ -1058,12 +1051,6 @@ class BR_EXPORT Transform : public Object @@ -1058,12 +1051,6 @@ class BR_EXPORT Transform : public Object
1058 Q_OBJECT 1051 Q_OBJECT
1059 1052
1060 public: 1053 public:
1061 - Q_PROPERTY(int classes READ get_classes WRITE set_classes RESET reset_classes STORED false)  
1062 - Q_PROPERTY(int instances READ get_instances WRITE set_instances RESET reset_instances STORED false)  
1063 - Q_PROPERTY(float fraction READ get_fraction WRITE set_fraction RESET reset_fraction STORED false)  
1064 - BR_PROPERTY(int, classes, std::numeric_limits<int>::max())  
1065 - BR_PROPERTY(int, instances, std::numeric_limits<int>::max())  
1066 - BR_PROPERTY(float, fraction, 1)  
1067 bool independent, trainable; 1054 bool independent, trainable;
1068 1055
1069 virtual ~Transform() {} 1056 virtual ~Transform() {}
openbr/plugins/algorithms.cpp
@@ -48,7 +48,10 @@ class AlgorithmsInitializer : public Initializer @@ -48,7 +48,10 @@ class AlgorithmsInitializer : public Initializer
48 // Video 48 // Video
49 Globals->abbreviations.insert("DisplayVideo", "Stream([FPSLimit(30)+Show(false,[FrameNumber])+Discard])"); 49 Globals->abbreviations.insert("DisplayVideo", "Stream([FPSLimit(30)+Show(false,[FrameNumber])+Discard])");
50 Globals->abbreviations.insert("PerFrameDetection", "Stream([SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true),Show(false,[FrameNumber])+Discard])"); 50 Globals->abbreviations.insert("PerFrameDetection", "Stream([SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true),Show(false,[FrameNumber])+Discard])");
51 - Globals->abbreviations.insert("AgeGenderDemo", "Stream([SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+Expand+<FaceClassificationRegistration>+<FaceClassificationExtraction>+(<AgeRegressor>+Rename(Subject,Age)+Discard)/(<GenderClassifier>+Rename(Subject,Gender)+Discard)+RestoreMat(original)+Draw(inPlace=true)+DrawPropertiesPoint([Age,Gender],Affine_0,inPlace=true)+SaveMat(original)+Discard+Contract,RestoreMat(original)+FPSCalc+Show(false,[AvgFPS,Age,Gender])+Discard])"); 51 + Globals->abbreviations.insert("AgeGenderDemo", "Stream([SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+Expand+<FaceClassificationRegistration>+<FaceClassificationExtraction>+<AgeRegressor>/<GenderClassifier>+Discard+RestoreMat(original)+Draw(inPlace=true)+DrawPropertiesPoint([Age,Gender],Affine_0,inPlace=true)+SaveMat(original)+Discard+Contract,RestoreMat(original)+FPSCalc+Show(false,[AvgFPS,Age,Gender])+Discard])");
  52 + Globals->abbreviations.insert("HOG", "Stream([DropFrames(5)+Cvt(Gray)+KeyPointDetector(SIFT)+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat])+Contract+CatRows+KMeans(500)+Hist(500)+SVM");
  53 + Globals->abbreviations.insert("HOF", "Stream([DropFrames(5)+KeyPointDetector(SIFT),AggregateFrames(2),OpticalFlow+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat])+Contract+CatRows+KMeans(500)+Hist(500)");
  54 + Globals->abbreviations.insert("HOGHOF", "Stream([DropFrames(5)+Cvt(Gray),KeyPointDetector(SIFT),AggregateFrames(2),(OpticalFlow+Gradient+Bin(0,360,8)+ROI+Hist(8))/(First+Gradient+Bin(0,360,8)+ROI+Hist(8)),CatCols])+Contract+CatRows+KMeans(500)+Hist(500)");
52 55
53 // Generic Image Processing 56 // Generic Image Processing
54 Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)"); 57 Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)");
@@ -74,14 +77,14 @@ class AlgorithmsInitializer : public Initializer @@ -74,14 +77,14 @@ class AlgorithmsInitializer : public Initializer
74 Globals->abbreviations.insert("FaceDetection", "(Open+Cvt(Gray)+Cascade(FrontalFace))"); 77 Globals->abbreviations.insert("FaceDetection", "(Open+Cvt(Gray)+Cascade(FrontalFace))");
75 Globals->abbreviations.insert("DenseLBP", "(Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+RectRegions(8,8,6,6)+Hist(59))"); 78 Globals->abbreviations.insert("DenseLBP", "(Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+RectRegions(8,8,6,6)+Hist(59))");
76 Globals->abbreviations.insert("DenseSIFT", "(Grid(10,10)+SIFTDescriptor(12)+ByRow)"); 79 Globals->abbreviations.insert("DenseSIFT", "(Grid(10,10)+SIFTDescriptor(12)+ByRow)");
77 - Globals->abbreviations.insert("FaceRecognitionRegistration", "(ASEFEyes+Affine(88,88,0.25,0.35)+FTE(DFFS,instances=1))");  
78 - Globals->abbreviations.insert("FaceRecognitionExtraction", "(Mask+DenseSIFT/DenseLBP+PCA(0.95,instances=1)+Normalize(L2)+Cat)");  
79 - Globals->abbreviations.insert("FaceRecognitionEmbedding", "(Dup(12)+RndSubspace(0.05,1)+LDA(0.98,instances=-2)+Cat+PCA(768,instances=1))"); 80 + Globals->abbreviations.insert("FaceRecognitionRegistration", "(ASEFEyes+Affine(88,88,0.25,0.35)+DownsampleTraining(FTE(DFFS),instances=1))");
  81 + Globals->abbreviations.insert("FaceRecognitionExtraction", "(Mask+DenseSIFT/DenseLBP+DownsampleTraining(PCA(0.95),instances=1)+Normalize(L2)+Cat)");
  82 + Globals->abbreviations.insert("FaceRecognitionEmbedding", "(Dup(12)+RndSubspace(0.05,1)+DownsampleTraining(LDA(0.98),instances=-2)+Cat+DownsampleTraining(PCA(768),instances=1))");
80 Globals->abbreviations.insert("FaceRecognitionQuantization", "(Normalize(L1)+Quantize)"); 83 Globals->abbreviations.insert("FaceRecognitionQuantization", "(Normalize(L1)+Quantize)");
81 Globals->abbreviations.insert("FaceClassificationRegistration", "(ASEFEyes+Affine(56,72,0.33,0.45)+FTE(DFFS))"); 84 Globals->abbreviations.insert("FaceClassificationRegistration", "(ASEFEyes+Affine(56,72,0.33,0.45)+FTE(DFFS))");
82 - Globals->abbreviations.insert("FaceClassificationExtraction", "((Grid(7,7)+SIFTDescriptor(8)+ByRow)/DenseLBP+PCA(0.95,instances=-1)+Cat)");  
83 - Globals->abbreviations.insert("AgeRegressor", "Center(Range,instances=-1)+SVM(RBF,EPS_SVR,instances=100)");  
84 - Globals->abbreviations.insert("GenderClassifier", "Center(Range,instances=-1)+SVM(RBF,C_SVC,instances=4000)"); 85 + Globals->abbreviations.insert("FaceClassificationExtraction", "((Grid(7,7)+SIFTDescriptor(8)+ByRow)/DenseLBP+DownsampleTraining(PCA(0.95),instances=-1, inputVariable=Gender)+Cat)");
  86 + Globals->abbreviations.insert("AgeRegressor", "DownsampleTraining(Center(Range),instances=-1, inputVariable=Age)+DownsampleTraining(SVM(RBF,EPS_SVR,inputVariable=Age),instances=100, inputVariable=Age)");
  87 + Globals->abbreviations.insert("GenderClassifier", "DownsampleTraining(Center(Range),instances=-1, inputVariable=Gender)+DownsampleTraining(SVM(RBF,C_SVC,inputVariable=Gender),instances=4000, inputVariable=Gender)");
85 Globals->abbreviations.insert("UCharL1", "Unit(ByteL1)"); 88 Globals->abbreviations.insert("UCharL1", "Unit(ByteL1)");
86 } 89 }
87 }; 90 };
openbr/plugins/cluster.cpp
@@ -89,10 +89,14 @@ class KNNTransform : public Transform @@ -89,10 +89,14 @@ class KNNTransform : public Transform
89 Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED false) 89 Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
90 Q_PROPERTY(bool weighted READ get_weighted WRITE set_weighted RESET reset_weighted STORED false) 90 Q_PROPERTY(bool weighted READ get_weighted WRITE set_weighted RESET reset_weighted STORED false)
91 Q_PROPERTY(int numSubjects READ get_numSubjects WRITE set_numSubjects RESET reset_numSubjects STORED false) 91 Q_PROPERTY(int numSubjects READ get_numSubjects WRITE set_numSubjects RESET reset_numSubjects STORED false)
  92 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  93 + Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)
92 BR_PROPERTY(int, k, 1) 94 BR_PROPERTY(int, k, 1)
93 BR_PROPERTY(br::Distance*, distance, NULL) 95 BR_PROPERTY(br::Distance*, distance, NULL)
94 BR_PROPERTY(bool, weighted, false) 96 BR_PROPERTY(bool, weighted, false)
95 BR_PROPERTY(int, numSubjects, 1) 97 BR_PROPERTY(int, numSubjects, 1)
  98 + BR_PROPERTY(QString, inputVariable, "Label")
  99 + BR_PROPERTY(QString, outputVariable, "KNN")
96 100
97 TemplateList gallery; 101 TemplateList gallery;
98 102
@@ -111,17 +115,17 @@ class KNNTransform : public Transform @@ -111,17 +115,17 @@ class KNNTransform : public Transform
111 QHash<QString, float> votes; 115 QHash<QString, float> votes;
112 const int max = (k < 1) ? sortedScores.size() : std::min(k, sortedScores.size()); 116 const int max = (k < 1) ? sortedScores.size() : std::min(k, sortedScores.size());
113 for (int j=0; j<max; j++) 117 for (int j=0; j<max; j++)
114 - votes[gallery[sortedScores[j].second].file.get<QString>("Subject")] += (weighted ? sortedScores[j].first : 1); 118 + votes[gallery[sortedScores[j].second].file.get<QString>(inputVariable)] += (weighted ? sortedScores[j].first : 1);
115 subjects.append(votes.keys()[votes.values().indexOf(Common::Max(votes.values()))]); 119 subjects.append(votes.keys()[votes.values().indexOf(Common::Max(votes.values()))]);
116 120
117 // Remove subject from consideration 121 // Remove subject from consideration
118 if (subjects.size() < numSubjects) 122 if (subjects.size() < numSubjects)
119 for (int j=sortedScores.size()-1; j>=0; j--) 123 for (int j=sortedScores.size()-1; j>=0; j--)
120 - if (gallery[sortedScores[j].second].file.get<QString>("Subject") == subjects.last()) 124 + if (gallery[sortedScores[j].second].file.get<QString>(inputVariable) == subjects.last())
121 sortedScores.removeAt(j); 125 sortedScores.removeAt(j);
122 } 126 }
123 127
124 - dst.file.set("KNN", subjects.size() > 1 ? "[" + subjects.join(",") + "]" : subjects.first()); 128 + dst.file.set(outputVariable, subjects.size() > 1 ? "[" + subjects.join(",") + "]" : subjects.first());
125 } 129 }
126 130
127 void store(QDataStream &stream) const 131 void store(QDataStream &stream) const
openbr/plugins/eigen3.cpp
@@ -303,10 +303,12 @@ class LDATransform : public Transform @@ -303,10 +303,12 @@ class LDATransform : public Transform
303 Q_PROPERTY(bool pcaWhiten READ get_pcaWhiten WRITE set_pcaWhiten RESET reset_pcaWhiten STORED false) 303 Q_PROPERTY(bool pcaWhiten READ get_pcaWhiten WRITE set_pcaWhiten RESET reset_pcaWhiten STORED false)
304 Q_PROPERTY(int directLDA READ get_directLDA WRITE set_directLDA RESET reset_directLDA STORED false) 304 Q_PROPERTY(int directLDA READ get_directLDA WRITE set_directLDA RESET reset_directLDA STORED false)
305 Q_PROPERTY(float directDrop READ get_directDrop WRITE set_directDrop RESET reset_directDrop STORED false) 305 Q_PROPERTY(float directDrop READ get_directDrop WRITE set_directDrop RESET reset_directDrop STORED false)
  306 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
306 BR_PROPERTY(float, pcaKeep, 0.98) 307 BR_PROPERTY(float, pcaKeep, 0.98)
307 BR_PROPERTY(bool, pcaWhiten, false) 308 BR_PROPERTY(bool, pcaWhiten, false)
308 BR_PROPERTY(int, directLDA, 0) 309 BR_PROPERTY(int, directLDA, 0)
309 BR_PROPERTY(float, directDrop, 0.1) 310 BR_PROPERTY(float, directDrop, 0.1)
  311 + BR_PROPERTY(QString, inputVariable, "Label")
310 312
311 int dimsOut; 313 int dimsOut;
312 Eigen::VectorXf mean; 314 Eigen::VectorXf mean;
@@ -315,7 +317,7 @@ class LDATransform : public Transform @@ -315,7 +317,7 @@ class LDATransform : public Transform
315 void train(const TemplateList &_trainingSet) 317 void train(const TemplateList &_trainingSet)
316 { 318 {
317 // creates "Label" 319 // creates "Label"
318 - TemplateList trainingSet = TemplateList::relabel(_trainingSet, "Subject"); 320 + TemplateList trainingSet = TemplateList::relabel(_trainingSet, inputVariable);
319 321
320 int instances = trainingSet.size(); 322 int instances = trainingSet.size();
321 323
openbr/plugins/frames.cpp
@@ -19,7 +19,7 @@ class AggregateFrames : public TimeVaryingTransform @@ -19,7 +19,7 @@ class AggregateFrames : public TimeVaryingTransform
19 TemplateList buffer; 19 TemplateList buffer;
20 20
21 public: 21 public:
22 - AggregateFrames() : TimeVaryingTransform(false) {} 22 + AggregateFrames() : TimeVaryingTransform(false, false) {}
23 23
24 private: 24 private:
25 void train(const TemplateList &data) 25 void train(const TemplateList &data)
@@ -35,6 +35,12 @@ private: @@ -35,6 +35,12 @@ private:
35 dst.file = buffer.takeFirst().file; 35 dst.file = buffer.takeFirst().file;
36 } 36 }
37 37
  38 + void finalize(TemplateList & output)
  39 + {
  40 + (void) output;
  41 + buffer.clear();
  42 + }
  43 +
38 void store(QDataStream &stream) const 44 void store(QDataStream &stream) const
39 { 45 {
40 (void) stream; 46 (void) stream;
@@ -48,6 +54,33 @@ private: @@ -48,6 +54,33 @@ private:
48 54
49 BR_REGISTER(Transform, AggregateFrames) 55 BR_REGISTER(Transform, AggregateFrames)
50 56
  57 +/*!
  58 + * \ingroup transforms
  59 + * \brief Only use one frame every n frames.
  60 + * \author Austin Blanton \cite imaus10
  61 + *
  62 + * For a video with m frames, DropFrames will pass on m/n frames.
  63 + */
  64 +class DropFrames : public UntrainableMetaTransform
  65 +{
  66 + Q_OBJECT
  67 + Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
  68 + BR_PROPERTY(int, n, 1)
  69 +
  70 + void project(const TemplateList &src, TemplateList &dst) const
  71 + {
  72 + if (src.first().file.get<int>("FrameNumber") % n != 0) return;
  73 + dst = src;
  74 + }
  75 +
  76 + void project(const Template &src, Template &dst) const
  77 + {
  78 + (void) src; (void) dst; qFatal("shouldn't be here");
  79 + }
  80 +};
  81 +
  82 +BR_REGISTER(Transform, DropFrames)
  83 +
51 } // namespace br 84 } // namespace br
52 85
53 #include "frames.moc" 86 #include "frames.moc"
openbr/plugins/gallery.cpp
@@ -71,7 +71,7 @@ class arffGallery : public Gallery @@ -71,7 +71,7 @@ class arffGallery : public Gallery
71 } 71 }
72 72
73 arffFile.write(qPrintable(OpenCVUtils::matrixToStringList(t).join(','))); 73 arffFile.write(qPrintable(OpenCVUtils::matrixToStringList(t).join(',')));
74 - arffFile.write(qPrintable(",'" + t.file.get<QString>("Subject") + "'\n")); 74 + arffFile.write(qPrintable(",'" + t.file.get<QString>("Label") + "'\n"));
75 } 75 }
76 }; 76 };
77 77
@@ -643,11 +643,16 @@ class dbGallery : public Gallery @@ -643,11 +643,16 @@ class dbGallery : public Gallery
643 query = query.mid(1, query.size()-2); 643 query = query.mid(1, query.size()-2);
644 if (!q.exec(query)) 644 if (!q.exec(query))
645 qFatal("%s.", qPrintable(q.lastError().text())); 645 qFatal("%s.", qPrintable(q.lastError().text()));
  646 +
646 if ((q.record().count() == 0) || (q.record().count() > 3)) 647 if ((q.record().count() == 0) || (q.record().count() > 3))
647 qFatal("Query record expected one to three fields, got %d.", q.record().count()); 648 qFatal("Query record expected one to three fields, got %d.", q.record().count());
648 const bool hasMetadata = (q.record().count() >= 2); 649 const bool hasMetadata = (q.record().count() >= 2);
649 const bool hasFilter = (q.record().count() >= 3); 650 const bool hasFilter = (q.record().count() >= 3);
650 651
  652 + QString labelName = "Label";
  653 + if (q.record().count() >= 2)
  654 + labelName = q.record().fieldName(1);
  655 +
651 // subset = seed:subjectMaxSize:numSubjects:subjectMinSize or 656 // subset = seed:subjectMaxSize:numSubjects:subjectMinSize or
652 // subset = seed:{Metadata,...,Metadata}:numSubjects 657 // subset = seed:{Metadata,...,Metadata}:numSubjects
653 int seed = 0, subjectMaxSize = std::numeric_limits<int>::max(), numSubjects = std::numeric_limits<int>::max(), subjectMinSize = 0; 658 int seed = 0, subjectMaxSize = std::numeric_limits<int>::max(), numSubjects = std::numeric_limits<int>::max(), subjectMinSize = 0;
@@ -673,6 +678,7 @@ class dbGallery : public Gallery @@ -673,6 +678,7 @@ class dbGallery : public Gallery
673 QHash<QString, QList<Entry> > entries; // QHash<Label, QList<Entry> > 678 QHash<QString, QList<Entry> > entries; // QHash<Label, QList<Entry> >
674 while (q.next()) { 679 while (q.next()) {
675 if (hasFilter && (seed >= 0) && (qHash(q.value(2).toString()) % 2 != (uint)seed % 2)) continue; // Ensures training and testing filters don't overlap 680 if (hasFilter && (seed >= 0) && (qHash(q.value(2).toString()) % 2 != (uint)seed % 2)) continue; // Ensures training and testing filters don't overlap
  681 +
676 if (metadataFields.isEmpty()) 682 if (metadataFields.isEmpty())
677 entries[hasMetadata ? q.value(1).toString() : ""].append(QPair<QString,QString>(q.value(0).toString(), hasFilter ? q.value(2).toString() : "")); 683 entries[hasMetadata ? q.value(1).toString() : ""].append(QPair<QString,QString>(q.value(0).toString(), hasFilter ? q.value(2).toString() : ""));
678 else 684 else
@@ -707,8 +713,10 @@ class dbGallery : public Gallery @@ -707,8 +713,10 @@ class dbGallery : public Gallery
707 713
708 if (entryList.size() > subjectMaxSize) 714 if (entryList.size() > subjectMaxSize)
709 std::random_shuffle(entryList.begin(), entryList.end()); 715 std::random_shuffle(entryList.begin(), entryList.end());
710 - foreach (const Entry &entry, entryList.mid(0, subjectMaxSize))  
711 - templates.append(File(entry.first, label)); 716 + foreach (const Entry &entry, entryList.mid(0, subjectMaxSize)) {
  717 + templates.append(File(entry.first));
  718 + templates.last().file.set(labelName, label);
  719 + }
712 numSubjects--; 720 numSubjects--;
713 } 721 }
714 } 722 }
@@ -816,7 +824,7 @@ class statGallery : public Gallery @@ -816,7 +824,7 @@ class statGallery : public Gallery
816 824
817 void write(const Template &t) 825 void write(const Template &t)
818 { 826 {
819 - subjects.insert(t.file.get<QString>("Subject")); 827 + subjects.insert(t.file.get<QString>("Label"));
820 bytes.append(t.bytes()); 828 bytes.append(t.bytes());
821 } 829 }
822 }; 830 };
@@ -862,6 +870,50 @@ class FDDBGallery : public Gallery @@ -862,6 +870,50 @@ class FDDBGallery : public Gallery
862 870
863 BR_REGISTER(Gallery, FDDBGallery) 871 BR_REGISTER(Gallery, FDDBGallery)
864 872
  873 +/*!
  874 + * \ingroup galleries
  875 + * \brief Text format for associating anonymous landmarks with images.
  876 + * \author Josh Klontz \cite jklontz
  877 + *
  878 + * \code
  879 + * file_name:x1,y1,x2,y2,...,xn,yn
  880 + * file_name:x1,y1,x2,y2,...,xn,yn
  881 + * ...
  882 + * file_name:x1,y1,x2,y2,...,xn,yn
  883 + * \endcode
  884 + */
  885 +class landmarksGallery : public Gallery
  886 +{
  887 + Q_OBJECT
  888 +
  889 + TemplateList readBlock(bool *done)
  890 + {
  891 + *done = true;
  892 + TemplateList templates;
  893 + foreach (const QString &line, QtUtils::readLines(file)) {
  894 + const QStringList words = line.split(':');
  895 + if (words.size() != 2) qFatal("Expected exactly one ':' in: %s.", qPrintable(line));
  896 + File file(words[0]);
  897 + const QList<float> vals = QtUtils::toFloats(words[1].split(','));
  898 + if (vals.size() % 2 != 0) qFatal("Expected an even number of comma-separated values.");
  899 + QList<QPointF> points; points.reserve(vals.size()/2);
  900 + for (int i=0; i<vals.size(); i+=2)
  901 + points.append(QPointF(vals[i], vals[i+1]));
  902 + file.setPoints(points);
  903 + templates.append(file);
  904 + }
  905 + return templates;
  906 + }
  907 +
  908 + void write(const Template &t)
  909 + {
  910 + (void) t;
  911 + qFatal("Not implemented.");
  912 + }
  913 +};
  914 +
  915 +BR_REGISTER(Gallery, landmarksGallery)
  916 +
865 } // namespace br 917 } // namespace br
866 918
867 #include "gallery.moc" 919 #include "gallery.moc"
openbr/plugins/gui.cpp
@@ -52,26 +52,33 @@ QImage toQImage(const Mat &amp;mat) @@ -52,26 +52,33 @@ QImage toQImage(const Mat &amp;mat)
52 return QImage(mat8uc3.data, mat8uc3.cols, mat8uc3.rows, 3*mat8uc3.cols, QImage::Format_RGB888).copy(); 52 return QImage(mat8uc3.data, mat8uc3.cols, mat8uc3.rows, 3*mat8uc3.cols, QImage::Format_RGB888).copy();
53 } 53 }
54 54
55 -  
56 -// Provides slots for manipulating a QLabel, but does not inherit from QWidget.  
57 -// Therefore, it can be moved to the main thread if not created there initially  
58 -// since god forbid you create a QWidget subclass in not the main thread.  
59 -class GUIProxy : public QObject 55 +class DisplayWindow : public QLabel
60 { 56 {
61 Q_OBJECT 57 Q_OBJECT
  58 +
  59 +protected:
62 QMutex lock; 60 QMutex lock;
63 QWaitCondition wait; 61 QWaitCondition wait;
  62 + QPixmap pixmap;
64 63
65 public: 64 public:
66 65
67 - QLabel *window;  
68 - QPixmap pixmap; 66 + DisplayWindow(QWidget * parent = NULL) : QLabel(parent)
  67 + {
  68 + QApplication::instance()->installEventFilter(this);
  69 + }
69 70
70 - GUIProxy() 71 +public slots:
  72 + void showImage(const QPixmap & input)
71 { 73 {
72 - window = NULL; 74 + pixmap = input;
  75 +
  76 + show();
  77 + setPixmap(pixmap);
  78 + setFixedSize(input.size());
73 } 79 }
74 80
  81 +
75 bool eventFilter(QObject * obj, QEvent * event) 82 bool eventFilter(QObject * obj, QEvent * event)
76 { 83 {
77 if (event->type() == QEvent::KeyPress) 84 if (event->type() == QEvent::KeyPress)
@@ -92,41 +99,10 @@ public: @@ -92,41 +99,10 @@ public:
92 99
93 return QList<QPointF>(); 100 return QList<QPointF>();
94 } 101 }
95 -  
96 -public slots:  
97 -  
98 - void showImage(const QPixmap & input)  
99 - {  
100 - pixmap = input;  
101 -  
102 - window->show();  
103 - window->setPixmap(pixmap);  
104 - window->setFixedSize(input.size());  
105 - }  
106 -  
107 - void createWindow()  
108 - {  
109 - delete window;  
110 - QApplication::instance()->removeEventFilter(this);  
111 -  
112 - window = new QLabel();  
113 - window->setVisible(true);  
114 -  
115 - QApplication::instance()->installEventFilter(this);  
116 - Qt::WindowFlags flags = window->windowFlags();  
117 -  
118 - flags = flags & ~Qt::WindowCloseButtonHint;  
119 - window->setWindowFlags(flags);  
120 - }  
121 -  
122 }; 102 };
123 103
124 -class LandmarkProxy : public GUIProxy 104 +class PointMarkingWindow : public DisplayWindow
125 { 105 {
126 - Q_OBJECT  
127 -  
128 -public:  
129 -  
130 bool eventFilter(QObject *obj, QEvent *event) 106 bool eventFilter(QObject *obj, QEvent *event)
131 { 107 {
132 if (event->type() == QEvent::MouseButtonPress) 108 if (event->type() == QEvent::MouseButtonPress)
@@ -144,11 +120,11 @@ public: @@ -144,11 +120,11 @@ public:
144 painter.setBrush(Qt::red); 120 painter.setBrush(Qt::red);
145 foreach(const QPointF &point, points) painter.drawEllipse(point, 4, 4); 121 foreach(const QPointF &point, points) painter.drawEllipse(point, 4, 4);
146 122
147 - window->setPixmap(pixmapBuffer); 123 + setPixmap(pixmapBuffer);
148 124
149 return true; 125 return true;
150 } else { 126 } else {
151 - return GUIProxy::eventFilter(obj, event); 127 + return DisplayWindow::eventFilter(obj, event);
152 } 128 }
153 } 129 }
154 130
@@ -156,14 +132,130 @@ public: @@ -156,14 +132,130 @@ public:
156 { 132 {
157 points.clear(); 133 points.clear();
158 134
159 - GUIProxy::waitForKey(); 135 + DisplayWindow::waitForKey();
160 136
161 return points; 137 return points;
162 } 138 }
163 139
164 private: 140 private:
165 -  
166 QList<QPointF> points; 141 QList<QPointF> points;
  142 +
  143 +
  144 +};
  145 +
  146 +class PromptWindow : public DisplayWindow
  147 +{
  148 + bool eventFilter(QObject * obj, QEvent * event)
  149 + {
  150 + if (event->type() == QEvent::KeyPress)
  151 + {
  152 + event->accept();
  153 +
  154 + QKeyEvent * key_event = dynamic_cast<QKeyEvent *> (event);
  155 + if (key_event == NULL) {
  156 + qDebug("failed to donwcast key event");
  157 + return true;
  158 + }
  159 +
  160 + QString text = key_event->text();
  161 +
  162 + text =text.toLower();
  163 + if (text == "y" || text == "n")
  164 + {
  165 + gotString = key_event->text();
  166 + wait.wakeAll();
  167 + }
  168 + else qDebug("Please answer y/n");
  169 +
  170 + return true;
  171 + } else {
  172 + return QObject::eventFilter(obj, event);
  173 + }
  174 + }
  175 +
  176 +public:
  177 + QString waitForKeyPress()
  178 + {
  179 + QMutexLocker locker(&lock);
  180 + wait.wait(&lock);
  181 +
  182 + return gotString;
  183 + }
  184 +
  185 +private:
  186 + QString gotString;
  187 +
  188 +
  189 +};
  190 +
  191 +
  192 +// I want a template class that doesn't look like a template class
  193 +class NominalCreation
  194 +{
  195 +public:
  196 + virtual ~NominalCreation() {}
  197 + virtual void creation()=0;
  198 +};
  199 +
  200 +// Putting the template on a subclass means we can maintain a pointer that
  201 +// doesn't include T in its type.
  202 +template<typename T>
  203 +class ActualCreation : public NominalCreation
  204 +{
  205 +public:
  206 + T * basis;
  207 +
  208 + void creation()
  209 + {
  210 + basis = new T();
  211 + }
  212 +};
  213 +
  214 +// We want to create a QLabel subclass on the main thread, but are running in another thread.
  215 +// We cannot move QWidget subclasses to a different thread (obviously that would be crazy), but
  216 +// we can create one of these, and move it to the main thread, and then use it to create the object
  217 +// we want.
  218 +// Additional fact: QObject subclasses cannot be template classes.
  219 +class MainThreadCreator : public QObject
  220 +{
  221 + Q_OBJECT
  222 +public:
  223 +
  224 + MainThreadCreator()
  225 + {
  226 + this->moveToThread(QApplication::instance()->thread());
  227 +
  228 + connect(this, SIGNAL(needCreation()), this, SLOT(createThing()), Qt::BlockingQueuedConnection);
  229 + }
  230 +
  231 + // While this cannot be a template class, it can still have a template method.
  232 + template<typename T>
  233 + T * getItem()
  234 + {
  235 + if (QThread::currentThread() == QApplication::instance()->thread())
  236 + return new T();
  237 +
  238 + ActualCreation<T> * actualWorker;
  239 + actualWorker = new ActualCreation<T> ();
  240 + worker = actualWorker;
  241 +
  242 + emit needCreation();
  243 +
  244 + T * output = actualWorker->basis;
  245 + delete actualWorker;
  246 + return output;
  247 + }
  248 +
  249 + NominalCreation * worker;
  250 +
  251 +signals:
  252 + void needCreation();
  253 +
  254 +public slots:
  255 + void createThing()
  256 + {
  257 + worker->creation();
  258 + }
167 }; 259 };
168 260
169 /*! 261 /*!
@@ -184,14 +276,14 @@ public: @@ -184,14 +276,14 @@ public:
184 276
185 ShowTransform() : TimeVaryingTransform(false, false) 277 ShowTransform() : TimeVaryingTransform(false, false)
186 { 278 {
187 - gui = NULL;  
188 displayBuffer = NULL; 279 displayBuffer = NULL;
  280 + window = NULL;
189 } 281 }
190 282
191 ~ShowTransform() 283 ~ShowTransform()
192 { 284 {
193 - delete gui;  
194 delete displayBuffer; 285 delete displayBuffer;
  286 + delete window;
195 } 287 }
196 288
197 void train(const TemplateList &data) { (void) data; } 289 void train(const TemplateList &data) { (void) data; }
@@ -235,7 +327,7 @@ public: @@ -235,7 +327,7 @@ public:
235 327
236 // Blocking wait for a key-press 328 // Blocking wait for a key-press
237 if (this->waitInput) 329 if (this->waitInput)
238 - gui->waitForKey(); 330 + window->waitForKey();
239 331
240 } 332 }
241 } 333 }
@@ -249,33 +341,36 @@ public: @@ -249,33 +341,36 @@ public:
249 341
250 void init() 342 void init()
251 { 343 {
  344 + initActual<DisplayWindow>();
  345 + }
  346 +
  347 + template<typename WindowType>
  348 + void initActual()
  349 + {
252 if (!Globals->useGui) 350 if (!Globals->useGui)
253 return; 351 return;
254 352
  353 + if (displayBuffer)
  354 + delete displayBuffer;
255 displayBuffer = new QPixmap(); 355 displayBuffer = new QPixmap();
256 356
257 - // Create our GUI proxy  
258 - gui = new GUIProxy();  
259 - // Move it to the main thread, this means signals we send to it will  
260 - // be run in the main thread, which is hopefully in an event loop  
261 - gui->moveToThread(QApplication::instance()->thread()); 357 + if (window)
  358 + delete window;
262 359
263 - // Connect our signals to the proxy's slots  
264 - connect(this, SIGNAL(needWindow()), gui, SLOT(createWindow()), Qt::BlockingQueuedConnection);  
265 - connect(this, SIGNAL(updateImage(QPixmap)), gui,SLOT(showImage(QPixmap)));  
266 -  
267 - emit needWindow();  
268 - connect(this, SIGNAL(changeTitle(QString)), gui->window, SLOT(setWindowTitle(QString)));  
269 - connect(this, SIGNAL(hideWindow()), gui->window, SLOT(hide())); 360 + window = creator.getItem<WindowType>();
  361 + // Connect our signals to the window's slots
  362 + connect(this, SIGNAL(updateImage(QPixmap)), window,SLOT(showImage(QPixmap)));
  363 + connect(this, SIGNAL(changeTitle(QString)), window, SLOT(setWindowTitle(QString)));
  364 + connect(this, SIGNAL(hideWindow()), window, SLOT(hide()));
270 } 365 }
271 366
272 protected: 367 protected:
273 - GUIProxy * gui; 368 + MainThreadCreator creator;
  369 + DisplayWindow * window;
274 QImage qImageBuffer; 370 QImage qImageBuffer;
275 QPixmap * displayBuffer; 371 QPixmap * displayBuffer;
276 372
277 signals: 373 signals:
278 - void needWindow();  
279 void updateImage(const QPixmap & input); 374 void updateImage(const QPixmap & input);
280 void changeTitle(const QString & input); 375 void changeTitle(const QString & input);
281 void hideWindow(); 376 void hideWindow();
@@ -312,7 +407,7 @@ public: @@ -312,7 +407,7 @@ public:
312 407
313 // Blocking wait for a key-press 408 // Blocking wait for a key-press
314 if (this->waitInput) { 409 if (this->waitInput) {
315 - QList<QPointF> points = gui->waitForKey(); 410 + QList<QPointF> points = window->waitForKey();
316 if (keys.isEmpty()) dst[i].file.appendPoints(points); 411 if (keys.isEmpty()) dst[i].file.appendPoints(points);
317 else { 412 else {
318 if (keys.size() == points.size()) 413 if (keys.size() == points.size())
@@ -326,28 +421,73 @@ public: @@ -326,28 +421,73 @@ public:
326 421
327 void init() 422 void init()
328 { 423 {
329 - if (!Globals->useGui) 424 + initActual<PointMarkingWindow>();
  425 + }
  426 +};
  427 +
  428 +BR_REGISTER(Transform, ManualTransform)
  429 +
  430 +
  431 +/*!
  432 + * \ingroup transforms
  433 + * \brief Display an image, and asks a yes/no question about it
  434 + * \author Charles Otto \cite caotto
  435 + */
  436 +class SurveyTransform : public ShowTransform
  437 +{
  438 + Q_OBJECT
  439 +
  440 +public:
  441 + Q_PROPERTY(QString question READ get_question WRITE set_question RESET reset_question STORED false)
  442 + BR_PROPERTY(QString, question, "Yes/No")
  443 +
  444 + Q_PROPERTY(QString propertyName READ get_propertyName WRITE set_propertyName RESET reset_propertyName STORED false)
  445 + BR_PROPERTY(QString, propertyName, "answer")
  446 +
  447 +
  448 + void projectUpdate(const TemplateList &src, TemplateList &dst)
  449 + {
  450 + if (Globals->parallelism > 1)
  451 + qFatal("SurveyTransform cannot execute in parallel.");
  452 +
  453 + dst = src;
  454 +
  455 + if (src.empty())
330 return; 456 return;
331 457
332 - displayBuffer = new QPixmap(); 458 + for (int i = 0; i < dst.size(); i++) {
  459 + foreach(const cv::Mat &m, dst[i]) {
  460 + qImageBuffer = toQImage(m);
  461 + displayBuffer->convertFromImage(qImageBuffer);
333 462
334 - // Create our GUI proxy  
335 - gui = new LandmarkProxy(); 463 + emit updateImage(displayBuffer->copy(displayBuffer->rect()));
336 464
337 - // Move it to the main thread, this means signals we send to it will  
338 - // be run in the main thread, which is hopefully in an event loop  
339 - gui->moveToThread(QApplication::instance()->thread()); 465 + // Blocking wait for a key-press
  466 + if (this->waitInput) {
  467 + QString answer = p_window->waitForKeyPress();
340 468
341 - // Connect our signals to the proxy's slots  
342 - connect(this, SIGNAL(needWindow()), gui, SLOT(createWindow()), Qt::BlockingQueuedConnection);  
343 - connect(this, SIGNAL(updateImage(QPixmap)), gui,SLOT(showImage(QPixmap))); 469 + dst[i].file.set(this->propertyName, answer);
  470 + }
  471 + }
  472 + }
  473 + }
  474 + PromptWindow * p_window;
344 475
345 - emit needWindow();  
346 - connect(this, SIGNAL(hideWindow()), gui->window, SLOT(hide())); 476 +
  477 + void init()
  478 + {
  479 + if (!Globals->useGui)
  480 + return;
  481 +
  482 + initActual<PromptWindow>();
  483 + p_window = (PromptWindow *) window;
  484 +
  485 + emit changeTitle(this->question);
347 } 486 }
348 }; 487 };
349 488
350 -BR_REGISTER(Transform, ManualTransform) 489 +BR_REGISTER(Transform, SurveyTransform)
  490 +
351 491
352 class FPSLimit : public TimeVaryingTransform 492 class FPSLimit : public TimeVaryingTransform
353 { 493 {
openbr/plugins/hist.cpp
@@ -52,8 +52,11 @@ class HistTransform : public UntrainableTransform @@ -52,8 +52,11 @@ class HistTransform : public UntrainableTransform
52 int histSize[] = {dims}; 52 int histSize[] = {dims};
53 float range[] = {min, max}; 53 float range[] = {min, max};
54 const float* ranges[] = {range}; 54 const float* ranges[] = {range};
55 - Mat hist;  
56 - calcHist(&mv[i], 1, channels, Mat(), hist, 1, histSize, ranges); 55 + Mat hist, chan = mv[i];
  56 + // calcHist requires F or U, might as well convert just in case
  57 + if (mv[i].depth() != CV_8U || mv[i].depth() == CV_32F)
  58 + mv[i].convertTo(chan, CV_32F);
  59 + calcHist(&chan, 1, channels, Mat(), hist, 1, histSize, ranges);
57 memcpy(m.ptr(i), hist.ptr(), dims * sizeof(float)); 60 memcpy(m.ptr(i), hist.ptr(), dims * sizeof(float));
58 } 61 }
59 62
openbr/plugins/independent.cpp
@@ -9,37 +9,36 @@ using namespace cv; @@ -9,37 +9,36 @@ using namespace cv;
9 namespace br 9 namespace br
10 { 10 {
11 11
12 -static TemplateList Downsample(const TemplateList &templates, const Transform *transform) 12 +static TemplateList Downsample(const TemplateList &templates, int classes, int instances, float fraction, const QString & inputVariable)
13 { 13 {
14 // Return early when no downsampling is required 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)) 15 + if ((classes == std::numeric_limits<int>::max()) &&
  16 + (instances == std::numeric_limits<int>::max()) &&
  17 + (fraction >= 1))
18 return templates; 18 return templates;
19 19
20 - const bool atLeast = transform->instances < 0;  
21 - const int instances = abs(transform->instances); 20 + const bool atLeast = instances < 0;
  21 + instances = abs(instances);
22 22
23 - QList<QString> allLabels = File::get<QString>(templates, "Subject"); 23 + QList<QString> allLabels = File::get<QString>(templates, inputVariable);
24 QList<QString> uniqueLabels = allLabels.toSet().toList(); 24 QList<QString> uniqueLabels = allLabels.toSet().toList();
25 qSort(uniqueLabels); 25 qSort(uniqueLabels);
26 26
27 - QMap<QString,int> counts = templates.countValues<QString>("Subject", instances != std::numeric_limits<int>::max()); 27 + QMap<QString,int> counts = templates.countValues<QString>(inputVariable, instances != std::numeric_limits<int>::max());
28 28
29 - if ((instances != std::numeric_limits<int>::max()) && (transform->classes != std::numeric_limits<int>::max())) 29 + if ((instances != std::numeric_limits<int>::max()) && (classes != std::numeric_limits<int>::max()))
30 foreach (const QString & label, counts.keys()) 30 foreach (const QString & label, counts.keys())
31 if (counts[label] < instances) 31 if (counts[label] < instances)
32 counts.remove(label); 32 counts.remove(label);
33 33
34 uniqueLabels = counts.keys(); 34 uniqueLabels = counts.keys();
35 - if ((transform->classes != std::numeric_limits<int>::max()) && (uniqueLabels.size() < transform->classes))  
36 - qWarning("Downsample requested %d classes but only %d are available.", transform->classes, uniqueLabels.size()); 35 + if ((classes != std::numeric_limits<int>::max()) && (uniqueLabels.size() < classes))
  36 + qWarning("Downsample requested %d classes but only %d are available.", classes, uniqueLabels.size());
37 37
38 - Common::seedRNG();  
39 QList<QString> selectedLabels = uniqueLabels; 38 QList<QString> selectedLabels = uniqueLabels;
40 - if (transform->classes < uniqueLabels.size()) { 39 + if (classes < uniqueLabels.size()) {
41 std::random_shuffle(selectedLabels.begin(), selectedLabels.end()); 40 std::random_shuffle(selectedLabels.begin(), selectedLabels.end());
42 - selectedLabels = selectedLabels.mid(0, transform->classes); 41 + selectedLabels = selectedLabels.mid(0, classes);
43 } 42 }
44 43
45 TemplateList downsample; 44 TemplateList downsample;
@@ -56,14 +55,45 @@ static TemplateList Downsample(const TemplateList &amp;templates, const Transform *t @@ -56,14 +55,45 @@ static TemplateList Downsample(const TemplateList &amp;templates, const Transform *t
56 downsample.append(templates.value(indices[j])); 55 downsample.append(templates.value(indices[j]));
57 } 56 }
58 57
59 - if (transform->fraction < 1) { 58 + if (fraction < 1) {
60 std::random_shuffle(downsample.begin(), downsample.end()); 59 std::random_shuffle(downsample.begin(), downsample.end());
61 - downsample = downsample.mid(0, downsample.size()*transform->fraction); 60 + downsample = downsample.mid(0, downsample.size()*fraction);
62 } 61 }
63 62
64 return downsample; 63 return downsample;
65 } 64 }
66 65
  66 +class DownsampleTrainingTransform : public Transform
  67 +{
  68 + Q_OBJECT
  69 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform STORED true)
  70 + Q_PROPERTY(int classes READ get_classes WRITE set_classes RESET reset_classes STORED false)
  71 + Q_PROPERTY(int instances READ get_instances WRITE set_instances RESET reset_instances STORED false)
  72 + Q_PROPERTY(float fraction READ get_fraction WRITE set_fraction RESET reset_fraction STORED false)
  73 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  74 + BR_PROPERTY(br::Transform*, transform, NULL)
  75 + BR_PROPERTY(int, classes, std::numeric_limits<int>::max())
  76 + BR_PROPERTY(int, instances, std::numeric_limits<int>::max())
  77 + BR_PROPERTY(float, fraction, 1)
  78 + BR_PROPERTY(QString, inputVariable, "Label")
  79 +
  80 + void project(const Template & src, Template & dst) const
  81 + {
  82 + transform->project(src,dst);
  83 + }
  84 +
  85 +
  86 + void train(const TemplateList &data)
  87 + {
  88 + if (!transform || !transform->trainable)
  89 + return;
  90 +
  91 + TemplateList downsampled = Downsample(data, classes, instances, fraction, inputVariable);
  92 + transform->train(downsampled);
  93 + }
  94 +};
  95 +BR_REGISTER(Transform, DownsampleTrainingTransform)
  96 +
67 /*! 97 /*!
68 * \ingroup transforms 98 * \ingroup transforms
69 * \brief Clones the transform so that it can be applied independently. 99 * \brief Clones the transform so that it can be applied independently.
@@ -124,13 +154,10 @@ class IndependentTransform : public MetaTransform @@ -124,13 +154,10 @@ class IndependentTransform : public MetaTransform
124 while (transforms.size() < templatesList.size()) 154 while (transforms.size() < templatesList.size())
125 transforms.append(transform->clone()); 155 transforms.append(transform->clone());
126 156
127 - for (int i=0; i<templatesList.size(); i++)  
128 - templatesList[i] = Downsample(templatesList[i], transforms[i]);  
129 -  
130 QFutureSynchronizer<void> futures; 157 QFutureSynchronizer<void> futures;
131 for (int i=0; i<templatesList.size(); i++) 158 for (int i=0; i<templatesList.size(); i++)
132 - futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i]));  
133 - futures.waitForFinished(); 159 + futures.addFuture(QtConcurrent::run(_train, transforms[i], &templatesList[i]));
  160 + futures.waitForFinished();
134 } 161 }
135 162
136 void project(const Template &src, Template &dst) const 163 void project(const Template &src, Template &dst) const
openbr/plugins/keypoint.cpp
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16
17 #include <opencv2/features2d/features2d.hpp> 17 #include <opencv2/features2d/features2d.hpp>
  18 +#include <opencv2/objdetect/objdetect.hpp>
18 #include <opencv2/nonfree/nonfree.hpp> 19 #include <opencv2/nonfree/nonfree.hpp>
19 #include "openbr_internal.h" 20 #include "openbr_internal.h"
20 #include "openbr/core/opencvutils.h" 21 #include "openbr/core/opencvutils.h"
@@ -178,6 +179,33 @@ BR_REGISTER(Transform, SIFTDescriptorTransform) @@ -178,6 +179,33 @@ BR_REGISTER(Transform, SIFTDescriptorTransform)
178 179
179 /*! 180 /*!
180 * \ingroup transforms 181 * \ingroup transforms
  182 + * \brief OpenCV HOGDescriptor wrapper
  183 + * \author Austin Blanton \cite imaus10
  184 + */
  185 +class HoGDescriptorTransform : public UntrainableTransform
  186 +{
  187 + Q_OBJECT
  188 +
  189 + HOGDescriptor hog;
  190 +
  191 + void project(const Template &src, Template &dst) const
  192 + {
  193 + std::vector<float> descriptorVals;
  194 + std::vector<Point> locations;
  195 + Size winStride = Size(0,0);
  196 + Size padding = Size(0,0);
  197 + foreach (const Mat &rect, src) {
  198 + hog.compute(rect, descriptorVals, winStride, padding, locations);
  199 + Mat HoGFeats(descriptorVals, true);
  200 + dst += HoGFeats;
  201 + }
  202 + }
  203 +};
  204 +
  205 +BR_REGISTER(Transform, HoGDescriptorTransform)
  206 +
  207 +/*!
  208 + * \ingroup transforms
181 * \brief Add landmarks to the template in a grid layout 209 * \brief Add landmarks to the template in a grid layout
182 * \author Josh Klontz \cite jklontz 210 * \author Josh Klontz \cite jklontz
183 */ 211 */
openbr/plugins/mask.cpp
@@ -158,6 +158,9 @@ class LargestConvexAreaTransform : public UntrainableTransform @@ -158,6 +158,9 @@ class LargestConvexAreaTransform : public UntrainableTransform
158 { 158 {
159 Q_OBJECT 159 Q_OBJECT
160 160
  161 + Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)
  162 + BR_PROPERTY(QString, outputVariable, "Label")
  163 +
161 void project(const Template &src, Template &dst) const 164 void project(const Template &src, Template &dst) const
162 { 165 {
163 std::vector< std::vector<Point> > contours; 166 std::vector< std::vector<Point> > contours;
@@ -171,7 +174,7 @@ class LargestConvexAreaTransform : public UntrainableTransform @@ -171,7 +174,7 @@ class LargestConvexAreaTransform : public UntrainableTransform
171 if (area / hullArea > 0.98) 174 if (area / hullArea > 0.98)
172 maxArea = std::max(maxArea, area); 175 maxArea = std::max(maxArea, area);
173 } 176 }
174 - dst.file.set("Label", maxArea); 177 + dst.file.set(outputVariable, maxArea);
175 } 178 }
176 }; 179 };
177 180
openbr/plugins/meta.cpp
@@ -105,6 +105,24 @@ class PipeTransform : public CompositeTransform @@ -105,6 +105,24 @@ class PipeTransform : public CompositeTransform
105 transforms[i]->train(copy); 105 transforms[i]->train(copy);
106 } 106 }
107 107
  108 + // if the transform is time varying, we can't project it in parallel
  109 + if (transforms[i]->timeVarying()) {
  110 + fprintf(stderr, "\n%s projecting...", qPrintable(transforms[i]->objectName()));
  111 + for (int j=0; j < singleItemLists.size();j++)
  112 + transforms[i]->projectUpdate(singleItemLists[j], singleItemLists[j]);
  113 +
  114 + // advance i since we already projected for this stage.
  115 + i++;
  116 +
  117 + // set up copy again
  118 + copy.clear();
  119 + for (int j=0; j < singleItemLists.size(); j++)
  120 + copy.append(singleItemLists[j]);
  121 +
  122 + // the next stage might be trainable, so continue to evaluate it.
  123 + continue;
  124 + }
  125 +
108 // We project through any subsequent untrainable transforms at once 126 // We project through any subsequent untrainable transforms at once
109 // as a memory optimization in case any of these intermediate 127 // as a memory optimization in case any of these intermediate
110 // transforms allocate a lot of memory (like OpenTransform) 128 // transforms allocate a lot of memory (like OpenTransform)
@@ -112,7 +130,8 @@ class PipeTransform : public CompositeTransform @@ -112,7 +130,8 @@ class PipeTransform : public CompositeTransform
112 // by that transform at once if we can avoid it. 130 // by that transform at once if we can avoid it.
113 int nextTrainableTransform = i+1; 131 int nextTrainableTransform = i+1;
114 while ((nextTrainableTransform < transforms.size()) && 132 while ((nextTrainableTransform < transforms.size()) &&
115 - !transforms[nextTrainableTransform]->trainable) 133 + !transforms[nextTrainableTransform]->trainable &&
  134 + !transforms[nextTrainableTransform]->timeVarying())
116 nextTrainableTransform++; 135 nextTrainableTransform++;
117 136
118 fprintf(stderr, " projecting..."); 137 fprintf(stderr, " projecting...");
openbr/plugins/misc.cpp
@@ -179,6 +179,10 @@ class FirstTransform : public UntrainableMetaTransform @@ -179,6 +179,10 @@ class FirstTransform : public UntrainableMetaTransform
179 179
180 void project(const Template &src, Template &dst) const 180 void project(const Template &src, Template &dst) const
181 { 181 {
  182 + // AggregateFrames will leave the Template empty
  183 + // if it hasn't filled up the buffer
  184 + // so we gotta anticipate an empty Template
  185 + if (src.empty()) return;
182 dst.file = src.file; 186 dst.file = src.file;
183 dst = src.m(); 187 dst = src.m();
184 } 188 }
openbr/plugins/normalize.cpp
@@ -97,6 +97,7 @@ class CenterTransform : public Transform @@ -97,6 +97,7 @@ class CenterTransform : public Transform
97 Q_OBJECT 97 Q_OBJECT
98 Q_ENUMS(Method) 98 Q_ENUMS(Method)
99 Q_PROPERTY(Method method READ get_method WRITE set_method RESET reset_method STORED false) 99 Q_PROPERTY(Method method READ get_method WRITE set_method RESET reset_method STORED false)
  100 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
100 101
101 public: 102 public:
102 /*!< */ 103 /*!< */
@@ -107,6 +108,7 @@ public: @@ -107,6 +108,7 @@ public:
107 108
108 private: 109 private:
109 BR_PROPERTY(Method, method, Mean) 110 BR_PROPERTY(Method, method, Mean)
  111 + BR_PROPERTY(QString, inputVariable, "Label")
110 112
111 Mat a, b; // dst = (src - b) / a 113 Mat a, b; // dst = (src - b) / a
112 114
@@ -127,7 +129,7 @@ private: @@ -127,7 +129,7 @@ private:
127 Mat m; 129 Mat m;
128 OpenCVUtils::toMat(data.data()).convertTo(m, CV_64F); 130 OpenCVUtils::toMat(data.data()).convertTo(m, CV_64F);
129 131
130 - const QList<int> labels = data.indexProperty("Subject"); 132 + const QList<int> labels = data.indexProperty(inputVariable);
131 const int dims = m.cols; 133 const int dims = m.cols;
132 134
133 vector<Mat> mv, av, bv; 135 vector<Mat> mv, av, bv;
openbr/plugins/openbr_internal.h
@@ -170,14 +170,8 @@ public: @@ -170,14 +170,8 @@ public:
170 virtual void project(const TemplateList &src, TemplateList &dst) const 170 virtual void project(const TemplateList &src, TemplateList &dst) const
171 { 171 {
172 if (timeVarying()) { 172 if (timeVarying()) {
173 - if (!this->timeInvariantAlias) {  
174 - QMutexLocker lock(&aliasLock);  
175 - CompositeTransform * non_const = const_cast<CompositeTransform *>(this);  
176 - non_const->timeInvariantAlias = non_const->smartCopy();  
177 - non_const->timeInvariantAlias->setParent(non_const);  
178 - lock.unlock();  
179 - }  
180 - timeInvariantAlias->projectUpdate(src,dst); 173 + CompositeTransform * non_const = const_cast<CompositeTransform *>(this);
  174 + non_const->projectUpdate(src,dst);
181 return; 175 return;
182 } 176 }
183 _project(src, dst); 177 _project(src, dst);
@@ -225,10 +219,6 @@ public: @@ -225,10 +219,6 @@ public:
225 } 219 }
226 220
227 output->file = this->file; 221 output->file = this->file;
228 - output->classes = classes;  
229 - output->instances = instances;  
230 - output->fraction = fraction;  
231 -  
232 output->init(); 222 output->init();
233 223
234 return output; 224 return output;
@@ -237,13 +227,10 @@ public: @@ -237,13 +227,10 @@ public:
237 protected: 227 protected:
238 bool isTimeVarying; 228 bool isTimeVarying;
239 229
240 - mutable QMutex aliasLock;  
241 - Transform * timeInvariantAlias;  
242 -  
243 virtual void _project(const Template & src, Template & dst) const = 0; 230 virtual void _project(const Template & src, Template & dst) const = 0;
244 virtual void _project(const TemplateList & src, TemplateList & dst) const = 0; 231 virtual void _project(const TemplateList & src, TemplateList & dst) const = 0;
245 232
246 - CompositeTransform() : TimeVaryingTransform(false) { timeInvariantAlias = NULL; } 233 + CompositeTransform() : TimeVaryingTransform(false) {}
247 }; 234 };
248 235
249 } 236 }
openbr/plugins/opticalflow.cpp 0 โ†’ 100644
  1 +#include <opencv2/video/tracking.hpp>
  2 +#include "openbr_internal.h"
  3 +#include "openbr/core/opencvutils.h"
  4 +
  5 +using namespace cv;
  6 +
  7 +namespace br
  8 +{
  9 +
  10 +/*!
  11 + * \ingroup transforms
  12 + * \brief Gets a one-channel dense optical flow from two images
  13 + * \author Austin Blanton \cite imaus10
  14 + */
  15 +class OpticalFlowTransform : public UntrainableMetaTransform
  16 +{
  17 + Q_OBJECT
  18 + Q_PROPERTY(double pyr_scale READ get_pyr_scale WRITE set_pyr_scale RESET reset_pyr_scale STORED false)
  19 + Q_PROPERTY(int levels READ get_levels WRITE set_levels RESET reset_levels STORED false)
  20 + Q_PROPERTY(int winsize READ get_winsize WRITE set_winsize RESET reset_winsize STORED false)
  21 + Q_PROPERTY(int iterations READ get_iterations WRITE set_iterations RESET reset_iterations STORED false)
  22 + Q_PROPERTY(int poly_n READ get_poly_n WRITE set_poly_n RESET reset_poly_n STORED false)
  23 + Q_PROPERTY(double poly_sigma READ get_poly_sigma WRITE set_poly_sigma RESET reset_poly_sigma STORED false)
  24 + Q_PROPERTY(int flags READ get_flags WRITE set_flags RESET reset_flags STORED false)
  25 + // these defaults are optimized for KTH
  26 + BR_PROPERTY(double, pyr_scale, 0.1)
  27 + BR_PROPERTY(int, levels, 1)
  28 + BR_PROPERTY(int, winsize, 5)
  29 + BR_PROPERTY(int, iterations, 10)
  30 + BR_PROPERTY(int, poly_n, 7)
  31 + BR_PROPERTY(double, poly_sigma, 1.1)
  32 + BR_PROPERTY(int, flags, 0)
  33 +
  34 + void project(const Template &src, Template &dst) const
  35 + {
  36 + // get the two images put there by AggregateFrames
  37 + if (src.size() < 2) return;
  38 + Mat prevImg = src[0], nextImg = src[1], flow, flowOneCh;
  39 + if (src[0].channels() != 1) OpenCVUtils::cvtGray(src[0], prevImg);
  40 + if (src[1].channels() != 1) OpenCVUtils::cvtGray(src[1], nextImg);
  41 + calcOpticalFlowFarneback(prevImg, nextImg, flow, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags);
  42 +
  43 + // the result is two channels
  44 + std::vector<Mat> channels(2);
  45 + split(flow, channels);
  46 + magnitude(channels[0], channels[1], flowOneCh);
  47 +
  48 + dst += flowOneCh;
  49 + dst.file = src.file;
  50 + }
  51 +};
  52 +
  53 +BR_REGISTER(Transform, OpticalFlowTransform)
  54 +
  55 +} // namespace br
  56 +
  57 +#include "opticalflow.moc"
openbr/plugins/output.cpp
@@ -146,8 +146,8 @@ class meltOutput : public MatrixOutput @@ -146,8 +146,8 @@ class meltOutput : public MatrixOutput
146 QStringList lines; 146 QStringList lines;
147 if (file.baseName() != "terminal") lines.append(QString("Query,Target,Mask,Similarity%1").arg(keys)); 147 if (file.baseName() != "terminal") lines.append(QString("Query,Target,Mask,Similarity%1").arg(keys));
148 148
149 - QList<QString> queryLabels = File::get<QString>(queryFiles, "Subject");  
150 - QList<QString> targetLabels = File::get<QString>(targetFiles, "Subject"); 149 + QList<QString> queryLabels = File::get<QString>(queryFiles, "Label");
  150 + QList<QString> targetLabels = File::get<QString>(targetFiles, "Label");
151 151
152 for (int i=0; i<queryFiles.size(); i++) { 152 for (int i=0; i<queryFiles.size(); i++) {
153 for (int j=(selfSimilar ? i+1 : 0); j<targetFiles.size(); j++) { 153 for (int j=(selfSimilar ? i+1 : 0); j<targetFiles.size(); j++) {
@@ -298,7 +298,7 @@ class txtOutput : public MatrixOutput @@ -298,7 +298,7 @@ class txtOutput : public MatrixOutput
298 if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return; 298 if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return;
299 QStringList lines; 299 QStringList lines;
300 foreach (const File &file, queryFiles) 300 foreach (const File &file, queryFiles)
301 - lines.append(file.name + " " + file.get<QString>("Subject")); 301 + lines.append(file.name + " " + file.get<QString>("Label"));
302 QtUtils::writeFile(file, lines); 302 QtUtils::writeFile(file, lines);
303 } 303 }
304 }; 304 };
@@ -428,7 +428,7 @@ class rankOutput : public MatrixOutput @@ -428,7 +428,7 @@ class rankOutput : public MatrixOutput
428 foreach (const Pair &pair, Common::Sort(OpenCVUtils::matrixToVector<float>(data.row(i)), true)) { 428 foreach (const Pair &pair, Common::Sort(OpenCVUtils::matrixToVector<float>(data.row(i)), true)) {
429 if (Globals->crossValidate > 0 ? (targetFiles[pair.second].get<int>("Partition",-1) == queryFiles[i].get<int>("Partition",-1)) : true) { 429 if (Globals->crossValidate > 0 ? (targetFiles[pair.second].get<int>("Partition",-1) == queryFiles[i].get<int>("Partition",-1)) : true) {
430 if (QString(targetFiles[pair.second]) != QString(queryFiles[i])) { 430 if (QString(targetFiles[pair.second]) != QString(queryFiles[i])) {
431 - if (targetFiles[pair.second].get<QString>("Subject") == queryFiles[i].get<QString>("Subject")) { 431 + if (targetFiles[pair.second].get<QString>("Label") == queryFiles[i].get<QString>("Label")) {
432 ranks.append(rank); 432 ranks.append(rank);
433 positions.append(pair.second); 433 positions.append(pair.second);
434 scores.append(pair.first); 434 scores.append(pair.first);
openbr/plugins/quality.cpp
@@ -19,17 +19,20 @@ class ImpostorUniquenessMeasureTransform : public Transform @@ -19,17 +19,20 @@ class ImpostorUniquenessMeasureTransform : public Transform
19 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false) 19 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
20 Q_PROPERTY(double mean READ get_mean WRITE set_mean RESET reset_mean) 20 Q_PROPERTY(double mean READ get_mean WRITE set_mean RESET reset_mean)
21 Q_PROPERTY(double stddev READ get_stddev WRITE set_stddev RESET reset_stddev) 21 Q_PROPERTY(double stddev READ get_stddev WRITE set_stddev RESET reset_stddev)
  22 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
22 BR_PROPERTY(br::Distance*, distance, Distance::make("Dist(L2)", this)) 23 BR_PROPERTY(br::Distance*, distance, Distance::make("Dist(L2)", this))
23 BR_PROPERTY(double, mean, 0) 24 BR_PROPERTY(double, mean, 0)
24 BR_PROPERTY(double, stddev, 1) 25 BR_PROPERTY(double, stddev, 1)
  26 + BR_PROPERTY(QString, inputVariable, "Label")
  27 +
25 TemplateList impostors; 28 TemplateList impostors;
26 29
27 float calculateIUM(const Template &probe, const TemplateList &gallery) const 30 float calculateIUM(const Template &probe, const TemplateList &gallery) const
28 { 31 {
29 - const QString probeLabel = probe.file.get<QString>("Subject"); 32 + const QString probeLabel = probe.file.get<QString>(inputVariable);
30 TemplateList subset = gallery; 33 TemplateList subset = gallery;
31 for (int j=subset.size()-1; j>=0; j--) 34 for (int j=subset.size()-1; j>=0; j--)
32 - if (subset[j].file.get<QString>("Subject") == probeLabel) 35 + if (subset[j].file.get<QString>(inputVariable) == probeLabel)
33 subset.removeAt(j); 36 subset.removeAt(j);
34 37
35 QList<float> scores = distance->compare(subset, probe); 38 QList<float> scores = distance->compare(subset, probe);
@@ -151,6 +154,7 @@ class MatchProbabilityDistance : public Distance @@ -151,6 +154,7 @@ class MatchProbabilityDistance : public Distance
151 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false) 154 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
152 Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false) 155 Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false)
153 Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false) 156 Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false)
  157 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
154 158
155 MP mp; 159 MP mp;
156 160
@@ -158,7 +162,7 @@ class MatchProbabilityDistance : public Distance @@ -158,7 +162,7 @@ class MatchProbabilityDistance : public Distance
158 { 162 {
159 distance->train(src); 163 distance->train(src);
160 164
161 - const QList<int> labels = src.indexProperty("Subject"); 165 + const QList<int> labels = src.indexProperty(inputVariable);
162 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size()))); 166 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));
163 distance->compare(src, src, matrixOutput.data()); 167 distance->compare(src, src, matrixOutput.data());
164 168
@@ -201,6 +205,7 @@ protected: @@ -201,6 +205,7 @@ protected:
201 BR_PROPERTY(br::Distance*, distance, make("Dist(L2)")) 205 BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
202 BR_PROPERTY(bool, gaussian, true) 206 BR_PROPERTY(bool, gaussian, true)
203 BR_PROPERTY(bool, crossModality, false) 207 BR_PROPERTY(bool, crossModality, false)
  208 + BR_PROPERTY(QString, inputVariable, "Label")
204 }; 209 };
205 210
206 BR_REGISTER(Distance, MatchProbabilityDistance) 211 BR_REGISTER(Distance, MatchProbabilityDistance)
@@ -217,10 +222,12 @@ class HeatMapDistance : public Distance @@ -217,10 +222,12 @@ class HeatMapDistance : public Distance
217 Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false) 222 Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false)
218 Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false) 223 Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false)
219 Q_PROPERTY(int step READ get_step WRITE set_step RESET reset_step STORED false) 224 Q_PROPERTY(int step READ get_step WRITE set_step RESET reset_step STORED false)
  225 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
220 BR_PROPERTY(br::Distance*, distance, make("Dist(L2)")) 226 BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
221 BR_PROPERTY(bool, gaussian, true) 227 BR_PROPERTY(bool, gaussian, true)
222 BR_PROPERTY(bool, crossModality, false) 228 BR_PROPERTY(bool, crossModality, false)
223 BR_PROPERTY(int, step, 1) 229 BR_PROPERTY(int, step, 1)
  230 + BR_PROPERTY(QString, inputVariable, "Label")
224 231
225 QList<MP> mp; 232 QList<MP> mp;
226 233
@@ -228,7 +235,7 @@ class HeatMapDistance : public Distance @@ -228,7 +235,7 @@ class HeatMapDistance : public Distance
228 { 235 {
229 distance->train(src); 236 distance->train(src);
230 237
231 - const QList<int> labels = src.indexProperty("Subject"); 238 + const QList<int> labels = src.indexProperty(inputVariable);
232 239
233 QList<TemplateList> patches; 240 QList<TemplateList> patches;
234 241
@@ -307,14 +314,16 @@ class UnitDistance : public Distance @@ -307,14 +314,16 @@ class UnitDistance : public Distance
307 Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance) 314 Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance)
308 Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a) 315 Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a)
309 Q_PROPERTY(float b READ get_b WRITE set_b RESET reset_b) 316 Q_PROPERTY(float b READ get_b WRITE set_b RESET reset_b)
  317 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
310 BR_PROPERTY(br::Distance*, distance, make("Dist(L2)")) 318 BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
311 BR_PROPERTY(float, a, 1) 319 BR_PROPERTY(float, a, 1)
312 BR_PROPERTY(float, b, 0) 320 BR_PROPERTY(float, b, 0)
  321 + BR_PROPERTY(QString, inputVariable, "Label")
313 322
314 void train(const TemplateList &templates) 323 void train(const TemplateList &templates)
315 { 324 {
316 const TemplateList samples = templates.mid(0, 2000); 325 const TemplateList samples = templates.mid(0, 2000);
317 - const QList<int> sampleLabels = samples.indexProperty("Subject"); 326 + const QList<int> sampleLabels = samples.indexProperty(inputVariable);
318 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(samples.size()), FileList(samples.size()))); 327 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(samples.size()), FileList(samples.size())));
319 Distance::compare(samples, samples, matrixOutput.data()); 328 Distance::compare(samples, samples, matrixOutput.data());
320 329
openbr/plugins/quantize.cpp
@@ -120,6 +120,10 @@ BR_REGISTER(Transform, HistEqQuantizationTransform) @@ -120,6 +120,10 @@ BR_REGISTER(Transform, HistEqQuantizationTransform)
120 class BayesianQuantizationDistance : public Distance 120 class BayesianQuantizationDistance : public Distance
121 { 121 {
122 Q_OBJECT 122 Q_OBJECT
  123 +
  124 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  125 + BR_PROPERTY(QString, inputVariable, "Label")
  126 +
123 QVector<float> loglikelihoods; 127 QVector<float> loglikelihoods;
124 128
125 static void computeLogLikelihood(const Mat &data, const QList<int> &labels, float *loglikelihood) 129 static void computeLogLikelihood(const Mat &data, const QList<int> &labels, float *loglikelihood)
@@ -150,7 +154,7 @@ class BayesianQuantizationDistance : public Distance @@ -150,7 +154,7 @@ class BayesianQuantizationDistance : public Distance
150 qFatal("Expected sigle matrix templates of type CV_8UC1!"); 154 qFatal("Expected sigle matrix templates of type CV_8UC1!");
151 155
152 const Mat data = OpenCVUtils::toMat(src.data()); 156 const Mat data = OpenCVUtils::toMat(src.data());
153 - const QList<int> templateLabels = src.indexProperty("Subject"); 157 + const QList<int> templateLabels = src.indexProperty(inputVariable);
154 loglikelihoods = QVector<float>(data.cols*256, 0); 158 loglikelihoods = QVector<float>(data.cols*256, 0);
155 159
156 QFutureSynchronizer<void> futures; 160 QFutureSynchronizer<void> futures;
@@ -343,9 +347,11 @@ class ProductQuantizationTransform : public Transform @@ -343,9 +347,11 @@ class ProductQuantizationTransform : public Transform
343 Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false) 347 Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false)
344 Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED false) 348 Q_PROPERTY(br::Distance *distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
345 Q_PROPERTY(bool bayesian READ get_bayesian WRITE set_bayesian RESET reset_bayesian STORED false) 349 Q_PROPERTY(bool bayesian READ get_bayesian WRITE set_bayesian RESET reset_bayesian STORED false)
  350 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
346 BR_PROPERTY(int, n, 2) 351 BR_PROPERTY(int, n, 2)
347 BR_PROPERTY(br::Distance*, distance, Distance::make("L2", this)) 352 BR_PROPERTY(br::Distance*, distance, Distance::make("L2", this))
348 BR_PROPERTY(bool, bayesian, false) 353 BR_PROPERTY(bool, bayesian, false)
  354 + BR_PROPERTY(QString, inputVariable, "Label")
349 355
350 quint16 index; 356 quint16 index;
351 QList<Mat> centers; 357 QList<Mat> centers;
@@ -474,7 +480,7 @@ private: @@ -474,7 +480,7 @@ private:
474 Mat data = OpenCVUtils::toMat(src.data()); 480 Mat data = OpenCVUtils::toMat(src.data());
475 const int step = getStep(data.cols); 481 const int step = getStep(data.cols);
476 482
477 - const QList<int> labels = src.indexProperty("Subject"); 483 + const QList<int> labels = src.indexProperty(inputVariable);
478 484
479 Mat &lut = ProductQuantizationLUTs[index]; 485 Mat &lut = ProductQuantizationLUTs[index];
480 lut = Mat(getDims(data.cols), 256*(256+1)/2, CV_32FC1); 486 lut = Mat(getDims(data.cols), 256*(256+1)/2, CV_32FC1);
openbr/plugins/quantize2.cpp
@@ -19,6 +19,10 @@ namespace br @@ -19,6 +19,10 @@ namespace br
19 class BayesianQuantizationTransform : public Transform 19 class BayesianQuantizationTransform : public Transform
20 { 20 {
21 Q_OBJECT 21 Q_OBJECT
  22 +
  23 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  24 + BR_PROPERTY(QString, inputVariable, "Label")
  25 +
22 QVector<float> thresholds; 26 QVector<float> thresholds;
23 27
24 static void computeThresholdsRecursive(const QVector<int> &cumulativeGenuines, const QVector<int> &cumulativeImpostors, 28 static void computeThresholdsRecursive(const QVector<int> &cumulativeGenuines, const QVector<int> &cumulativeImpostors,
@@ -77,7 +81,7 @@ class BayesianQuantizationTransform : public Transform @@ -77,7 +81,7 @@ class BayesianQuantizationTransform : public Transform
77 void train(const TemplateList &src) 81 void train(const TemplateList &src)
78 { 82 {
79 const Mat data = OpenCVUtils::toMat(src.data()); 83 const Mat data = OpenCVUtils::toMat(src.data());
80 - const QList<int> labels = src.indexProperty("Subject"); 84 + const QList<int> labels = src.indexProperty(inputVariable);
81 85
82 thresholds = QVector<float>(256*data.cols); 86 thresholds = QVector<float>(256*data.cols);
83 87
openbr/plugins/regions.cpp
@@ -114,7 +114,7 @@ BR_REGISTER(Transform, CatTransform) @@ -114,7 +114,7 @@ BR_REGISTER(Transform, CatTransform)
114 /*! 114 /*!
115 * \ingroup transforms 115 * \ingroup transforms
116 * \brief Concatenates all input matrices by row into a single matrix. 116 * \brief Concatenates all input matrices by row into a single matrix.
117 - * All matricies must have the same row counts. 117 + * All matricies must have the same column counts.
118 * \author Josh Klontz \cite jklontz 118 * \author Josh Klontz \cite jklontz
119 */ 119 */
120 class CatRowsTransform : public UntrainableMetaTransform 120 class CatRowsTransform : public UntrainableMetaTransform
@@ -131,6 +131,31 @@ BR_REGISTER(Transform, CatRowsTransform) @@ -131,6 +131,31 @@ BR_REGISTER(Transform, CatRowsTransform)
131 131
132 /*! 132 /*!
133 * \ingroup transforms 133 * \ingroup transforms
  134 + * \brief Concatenates all input matrices by column into a single matrix.
  135 + * Use after a fork to concatenate two feature matrices by column.
  136 + * \author Austin Blanton \cite imaus10
  137 + */
  138 +class CatColsTransform : public UntrainableMetaTransform
  139 +{
  140 + Q_OBJECT
  141 +
  142 + void project(const Template &src, Template &dst) const
  143 + {
  144 + if (src.empty()) return;
  145 + dst.file = src.file;
  146 + Mat m = OpenCVUtils::toMatByRow(src);
  147 + // right now this just splits src in half and joins them horizontally
  148 + // TODO: add partitions parameter for more than a single split
  149 + Mat first = m.rowRange(Range(0, m.rows/2));
  150 + Mat second = m.rowRange(Range(m.rows/2, m.rows));
  151 + hconcat(first, second, dst);
  152 + }
  153 +};
  154 +
  155 +BR_REGISTER(Transform, CatColsTransform)
  156 +
  157 +/*!
  158 + * \ingroup transforms
134 * \brief Reshape the each matrix to the specified number of rows. 159 * \brief Reshape the each matrix to the specified number of rows.
135 * \author Josh Klontz \cite jklontz 160 * \author Josh Klontz \cite jklontz
136 */ 161 */
openbr/plugins/stream.cpp
@@ -31,8 +31,10 @@ public: @@ -31,8 +31,10 @@ public:
31 virtual ~SharedBuffer() {} 31 virtual ~SharedBuffer() {}
32 32
33 virtual void addItem(FrameData * input)=0; 33 virtual void addItem(FrameData * input)=0;
  34 + virtual void reset()=0;
34 35
35 virtual FrameData * tryGetItem()=0; 36 virtual FrameData * tryGetItem()=0;
  37 + virtual int size()=0;
36 }; 38 };
37 39
38 // for n - 1 boundaries, multiple threads call addItem, the frames are 40 // for n - 1 boundaries, multiple threads call addItem, the frames are
@@ -74,6 +76,21 @@ public: @@ -74,6 +76,21 @@ public:
74 return output; 76 return output;
75 } 77 }
76 78
  79 + virtual int size()
  80 + {
  81 + QMutexLocker lock(&bufferGuard);
  82 + return buffer.size();
  83 + }
  84 + virtual void reset()
  85 + {
  86 + if (size() != 0)
  87 + qDebug("Sequencing buffer has non-zero size during reset!");
  88 +
  89 + QMutexLocker lock(&bufferGuard);
  90 + next_target = 0;
  91 + }
  92 +
  93 +
77 private: 94 private:
78 QMutex bufferGuard; 95 QMutex bufferGuard;
79 int next_target; 96 int next_target;
@@ -95,6 +112,11 @@ public: @@ -95,6 +112,11 @@ public:
95 outputBuffer = &buffer2; 112 outputBuffer = &buffer2;
96 } 113 }
97 114
  115 + int size()
  116 + {
  117 + QReadLocker readLock(&bufferGuard);
  118 + return inputBuffer->size() + outputBuffer->size();
  119 + }
98 120
99 // called from the producer thread 121 // called from the producer thread
100 void addItem(FrameData * input) 122 void addItem(FrameData * input)
@@ -133,6 +155,13 @@ public: @@ -133,6 +155,13 @@ public:
133 return output; 155 return output;
134 } 156 }
135 157
  158 + virtual void reset()
  159 + {
  160 + if (this->size() != 0)
  161 + qDebug("Shared buffer has non-zero size during reset!");
  162 + }
  163 +
  164 +
136 private: 165 private:
137 // The read-write lock. The thread adding to this buffer can add 166 // The read-write lock. The thread adding to this buffer can add
138 // to the current input buffer if it has a read lock. The thread 167 // to the current input buffer if it has a read lock. The thread
@@ -194,14 +223,10 @@ public: @@ -194,14 +223,10 @@ public:
194 // Try to get a FrameData from the pool, if we can't it means too many 223 // Try to get a FrameData from the pool, if we can't it means too many
195 // frames are already out, and we will return NULL to indicate failure 224 // frames are already out, and we will return NULL to indicate failure
196 FrameData * aFrame = allFrames.tryGetItem(); 225 FrameData * aFrame = allFrames.tryGetItem();
197 - if (aFrame == NULL) { 226 + if (aFrame == NULL)
198 return NULL; 227 return NULL;
199 - }  
200 228
201 - aFrame->data.clear();  
202 - aFrame->sequenceNumber = -1;  
203 -  
204 - // Try to read a frame, if this returns false the data source is broken 229 + // Try to actually read a frame, if this returns false the data source is broken
205 bool res = getNext(*aFrame); 230 bool res = getNext(*aFrame);
206 231
207 // The datasource broke, update final_frame 232 // The datasource broke, update final_frame
@@ -211,12 +236,15 @@ public: @@ -211,12 +236,15 @@ public:
211 final_frame = lookAhead.back()->sequenceNumber; 236 final_frame = lookAhead.back()->sequenceNumber;
212 allFrames.addItem(aFrame); 237 allFrames.addItem(aFrame);
213 } 238 }
214 - else lookAhead.push_back(aFrame); 239 + else {
  240 + lookAhead.push_back(aFrame);
  241 + }
215 242
  243 + // we will return the first frame on the lookAhead buffer
216 FrameData * rVal = lookAhead.first(); 244 FrameData * rVal = lookAhead.first();
217 lookAhead.pop_front(); 245 lookAhead.pop_front();
218 246
219 - 247 + // If this is the last frame, say so
220 if (rVal->sequenceNumber == final_frame) { 248 if (rVal->sequenceNumber == final_frame) {
221 last_frame = true; 249 last_frame = true;
222 is_broken = true; 250 is_broken = true;
@@ -231,6 +259,8 @@ public: @@ -231,6 +259,8 @@ public:
231 { 259 {
232 int frameNumber = inputFrame->sequenceNumber; 260 int frameNumber = inputFrame->sequenceNumber;
233 261
  262 + inputFrame->data.clear();
  263 + inputFrame->sequenceNumber = -1;
234 allFrames.addItem(inputFrame); 264 allFrames.addItem(inputFrame);
235 265
236 bool rval = false; 266 bool rval = false;
@@ -239,6 +269,7 @@ public: @@ -239,6 +269,7 @@ public:
239 269
240 if (frameNumber == final_frame) { 270 if (frameNumber == final_frame) {
241 // We just received the last frame, better pulse 271 // We just received the last frame, better pulse
  272 + allReturned = true;
242 lastReturned.wakeAll(); 273 lastReturned.wakeAll();
243 rval = true; 274 rval = true;
244 } 275 }
@@ -246,15 +277,24 @@ public: @@ -246,15 +277,24 @@ public:
246 return rval; 277 return rval;
247 } 278 }
248 279
249 - void waitLast() 280 + bool waitLast()
250 { 281 {
251 QMutexLocker lock(&last_frame_update); 282 QMutexLocker lock(&last_frame_update);
252 - lastReturned.wait(&last_frame_update); 283 +
  284 + while (!allReturned)
  285 + {
  286 + // This would be a safer wait if we used a timeout, but
  287 + // theoretically that should never matter.
  288 + lastReturned.wait(&last_frame_update);
  289 + }
  290 + return true;
253 } 291 }
254 292
255 bool open(Template & output, int start_index = 0) 293 bool open(Template & output, int start_index = 0)
256 { 294 {
257 is_broken = false; 295 is_broken = false;
  296 + allReturned = false;
  297 +
258 // The last frame isn't initialized yet 298 // The last frame isn't initialized yet
259 final_frame = -1; 299 final_frame = -1;
260 // Start our sequence numbers from the input index 300 // Start our sequence numbers from the input index
@@ -282,19 +322,34 @@ public: @@ -282,19 +322,34 @@ public:
282 bool res = getNext(*firstFrame); 322 bool res = getNext(*firstFrame);
283 323
284 // the data source broke already, we couldn't even get one frame 324 // the data source broke already, we couldn't even get one frame
285 - // from it. 325 + // from it even though it claimed to have opened successfully.
286 if (!res) { 326 if (!res) {
287 is_broken = true; 327 is_broken = true;
288 return false; 328 return false;
289 } 329 }
290 330
  331 + // We read one frame ahead of the last one returned, this allows
  332 + // us to know which frame is the final frame when we return it.
291 lookAhead.append(firstFrame); 333 lookAhead.append(firstFrame);
292 return true; 334 return true;
293 } 335 }
294 336
  337 + /*
  338 + * Pure virtual methods
  339 + */
  340 +
  341 + // isOpen doesn't appear to particularly work when used on opencv
  342 + // VideoCaptures, so we don't use it for anything important.
295 virtual bool isOpen()=0; 343 virtual bool isOpen()=0;
  344 + // Called from open, open the data source specified by the input
  345 + // template, don't worry about setting any of the state variables
  346 + // set in open.
296 virtual bool concreteOpen(Template & output) = 0; 347 virtual bool concreteOpen(Template & output) = 0;
  348 + // Get the next frame from the data source, store the results in
  349 + // FrameData (including the actual frame and appropriate sequence
  350 + // number).
297 virtual bool getNext(FrameData & input) = 0; 351 virtual bool getNext(FrameData & input) = 0;
  352 + // close the currently open data source.
298 virtual void close() = 0; 353 virtual void close() = 0;
299 354
300 int next_sequence_number; 355 int next_sequence_number;
@@ -302,6 +357,7 @@ protected: @@ -302,6 +357,7 @@ protected:
302 DoubleBuffer allFrames; 357 DoubleBuffer allFrames;
303 int final_frame; 358 int final_frame;
304 bool is_broken; 359 bool is_broken;
  360 + bool allReturned;
305 QList<FrameData *> lookAhead; 361 QList<FrameData *> lookAhead;
306 362
307 QWaitCondition lastReturned; 363 QWaitCondition lastReturned;
@@ -317,6 +373,11 @@ public: @@ -317,6 +373,11 @@ public:
317 bool concreteOpen(Template &input) 373 bool concreteOpen(Template &input)
318 { 374 {
319 basis = input; 375 basis = input;
  376 +
  377 + // We can open either files (well actually this includes addresses of ip cameras
  378 + // through ffmpeg), or webcams. Webcam VideoCaptures are created through a separate
  379 + // overload of open that takes an integer, not a string.
  380 + // So, does this look like an integer?
320 bool is_int = false; 381 bool is_int = false;
321 int anInt = input.file.name.toInt(&is_int); 382 int anInt = input.file.name.toInt(&is_int);
322 if (is_int) 383 if (is_int)
@@ -334,7 +395,8 @@ public: @@ -334,7 +395,8 @@ public:
334 } else { 395 } else {
335 // Yes, we should specify absolute path: 396 // Yes, we should specify absolute path:
336 // http://stackoverflow.com/questions/9396459/loading-a-video-in-opencv-in-python 397 // http://stackoverflow.com/questions/9396459/loading-a-video-in-opencv-in-python
337 - video.open(QFileInfo(input.file.name).absoluteFilePath().toStdString()); 398 + QString fileName = (Globals->path.isEmpty() ? "" : Globals->path + "/") + input.file.name;
  399 + video.open(QFileInfo(fileName).absoluteFilePath().toStdString());
338 } 400 }
339 401
340 return video.isOpened(); 402 return video.isOpened();
@@ -349,8 +411,10 @@ public: @@ -349,8 +411,10 @@ public:
349 private: 411 private:
350 bool getNext(FrameData & output) 412 bool getNext(FrameData & output)
351 { 413 {
352 - if (!isOpen()) 414 + if (!isOpen()) {
  415 + qDebug("video source is not open");
353 return false; 416 return false;
  417 + }
354 418
355 output.data.append(Template(basis.file)); 419 output.data.append(Template(basis.file));
356 output.data.last().m() = cv::Mat(); 420 output.data.last().m() = cv::Mat();
@@ -362,6 +426,7 @@ private: @@ -362,6 +426,7 @@ private:
362 bool res = video.read(temp); 426 bool res = video.read(temp);
363 427
364 if (!res) { 428 if (!res) {
  429 + // The video capture broke, return false.
365 output.data.last().m() = cv::Mat(); 430 output.data.last().m() = cv::Mat();
366 close(); 431 close();
367 return false; 432 return false;
@@ -391,6 +456,8 @@ public: @@ -391,6 +456,8 @@ public:
391 data_ok = false; 456 data_ok = false;
392 } 457 }
393 458
  459 + // To "open" it we just set appropriate indices, we assume that if this
  460 + // is an image, it is already loaded into memory.
394 bool concreteOpen(Template &input) 461 bool concreteOpen(Template &input)
395 { 462 {
396 basis = input; 463 basis = input;
@@ -440,7 +507,7 @@ private: @@ -440,7 +507,7 @@ private:
440 class DataSourceManager : public DataSource 507 class DataSourceManager : public DataSource
441 { 508 {
442 public: 509 public:
443 - DataSourceManager() : DataSource(500) 510 + DataSourceManager(int activeFrames=100) : DataSource(activeFrames)
444 { 511 {
445 actualSource = NULL; 512 actualSource = NULL;
446 } 513 }
@@ -450,6 +517,11 @@ public: @@ -450,6 +517,11 @@ public:
450 close(); 517 close();
451 } 518 }
452 519
  520 + int size()
  521 + {
  522 + return this->allFrames.size();
  523 + }
  524 +
453 void close() 525 void close()
454 { 526 {
455 if (actualSource) { 527 if (actualSource) {
@@ -459,29 +531,40 @@ public: @@ -459,29 +531,40 @@ public:
459 } 531 }
460 } 532 }
461 533
  534 + // We are used through a call to open(TemplateList)
462 bool open(TemplateList & input) 535 bool open(TemplateList & input)
463 { 536 {
  537 + // Set up variables specific to us
464 current_template_idx = 0; 538 current_template_idx = 0;
465 templates = input; 539 templates = input;
466 540
  541 + // Call datasourece::open on the first template to set up
  542 + // state variables
467 return DataSource::open(templates[current_template_idx]); 543 return DataSource::open(templates[current_template_idx]);
468 } 544 }
469 545
  546 + // Create an actual data source of appropriate type for this template
  547 + // (initially called via the call to DataSource::open, called later
  548 + // as we run out of frames on our templates).
470 bool concreteOpen(Template & input) 549 bool concreteOpen(Template & input)
471 { 550 {
472 close(); 551 close();
473 552
  553 + bool open_res = false;
474 // Input has no matrices? Its probably a video that hasn't been loaded yet 554 // Input has no matrices? Its probably a video that hasn't been loaded yet
475 if (input.empty()) { 555 if (input.empty()) {
476 actualSource = new VideoDataSource(0); 556 actualSource = new VideoDataSource(0);
477 - actualSource->concreteOpen(input); 557 + open_res = actualSource->concreteOpen(input);
478 } 558 }
  559 + // If the input is not empty, we assume it is a set of frames already
  560 + // in memory.
479 else { 561 else {
480 - // create frame dealer  
481 actualSource = new TemplateDataSource(0); 562 actualSource = new TemplateDataSource(0);
482 - actualSource->concreteOpen(input); 563 + open_res = actualSource->concreteOpen(input);
483 } 564 }
484 - if (!isOpen()) { 565 +
  566 + // The data source failed to open
  567 + if (!open_res) {
485 delete actualSource; 568 delete actualSource;
486 actualSource = NULL; 569 actualSource = NULL;
487 return false; 570 return false;
@@ -497,12 +580,16 @@ protected: @@ -497,12 +580,16 @@ protected:
497 580
498 TemplateList templates; 581 TemplateList templates;
499 DataSource * actualSource; 582 DataSource * actualSource;
  583 + // Get the next frame, if we run out of frames on the current template
  584 + // move on to the next one.
500 bool getNext(FrameData & output) 585 bool getNext(FrameData & output)
501 { 586 {
502 bool res = actualSource->getNext(output); 587 bool res = actualSource->getNext(output);
503 output.sequenceNumber = next_sequence_number; 588 output.sequenceNumber = next_sequence_number;
504 589
  590 + // OK we got a frame
505 if (res) { 591 if (res) {
  592 + // Override the sequence number set by actualSource
506 output.data.last().file.set("FrameNumber", output.sequenceNumber); 593 output.data.last().file.set("FrameNumber", output.sequenceNumber);
507 next_sequence_number++; 594 next_sequence_number++;
508 if (output.data.last().last().empty()) 595 if (output.data.last().last().empty())
@@ -510,7 +597,7 @@ protected: @@ -510,7 +597,7 @@ protected:
510 return true; 597 return true;
511 } 598 }
512 599
513 - 600 + // We didn't get a frame, try to move on to the next template.
514 while(!res) { 601 while(!res) {
515 output.data.clear(); 602 output.data.clear();
516 current_template_idx++; 603 current_template_idx++;
@@ -521,12 +608,16 @@ protected: @@ -521,12 +608,16 @@ protected:
521 608
522 // open the next data source 609 // open the next data source
523 bool open_res = concreteOpen(templates[current_template_idx]); 610 bool open_res = concreteOpen(templates[current_template_idx]);
  611 + // We couldn't open it, give up? We could maybe continue here
  612 + // but don't currently.
524 if (!open_res) 613 if (!open_res)
525 return false; 614 return false;
526 615
527 - // get a frame from it 616 + // get a frame from the newly opened data source, if that fails
  617 + // we continue to open the next one.
528 res = actualSource->getNext(output); 618 res = actualSource->getNext(output);
529 } 619 }
  620 + // Finally, set the sequence number for the frame we actually return.
530 output.sequenceNumber = next_sequence_number++; 621 output.sequenceNumber = next_sequence_number++;
531 output.data.last().file.set("FrameNumber", output.sequenceNumber); 622 output.data.last().file.set("FrameNumber", output.sequenceNumber);
532 623
@@ -573,6 +664,9 @@ public: @@ -573,6 +664,9 @@ public:
573 int stage_id; 664 int stage_id;
574 665
575 virtual void reset()=0; 666 virtual void reset()=0;
  667 +
  668 + virtual void status()=0;
  669 +
576 protected: 670 protected:
577 int thread_count; 671 int thread_count;
578 672
@@ -606,7 +700,8 @@ class MultiThreadStage : public ProcessingStage @@ -606,7 +700,8 @@ class MultiThreadStage : public ProcessingStage
606 public: 700 public:
607 MultiThreadStage(int _input) : ProcessingStage(_input) {} 701 MultiThreadStage(int _input) : ProcessingStage(_input) {}
608 702
609 - 703 + // Not much to worry about here, we will project the input
  704 + // and try to continue to the next stage.
610 FrameData * run(FrameData * input, bool & should_continue) 705 FrameData * run(FrameData * input, bool & should_continue)
611 { 706 {
612 if (input == NULL) { 707 if (input == NULL) {
@@ -620,7 +715,8 @@ public: @@ -620,7 +715,8 @@ public:
620 return input; 715 return input;
621 } 716 }
622 717
623 - // Called from a different thread than run 718 + // Called from a different thread than run. Nothing to worry about
  719 + // we offer no restrictions on when loops may enter this stage.
624 virtual bool tryAcquireNextStage(FrameData *& input) 720 virtual bool tryAcquireNextStage(FrameData *& input)
625 { 721 {
626 (void) input; 722 (void) input;
@@ -631,6 +727,9 @@ public: @@ -631,6 +727,9 @@ public:
631 { 727 {
632 // nothing to do. 728 // nothing to do.
633 } 729 }
  730 + void status(){
  731 + qDebug("multi thread stage %d, nothing to worry about", this->stage_id);
  732 + }
634 }; 733 };
635 734
636 class SingleThreadStage : public ProcessingStage 735 class SingleThreadStage : public ProcessingStage
@@ -640,13 +739,18 @@ public: @@ -640,13 +739,18 @@ public:
640 { 739 {
641 currentStatus = STOPPING; 740 currentStatus = STOPPING;
642 next_target = 0; 741 next_target = 0;
  742 + // If the previous stage is single-threaded, queued inputs
  743 + // are stored in a double buffer
643 if (input_variance) { 744 if (input_variance) {
644 this->inputBuffer = new DoubleBuffer(); 745 this->inputBuffer = new DoubleBuffer();
645 } 746 }
  747 + // If it's multi-threaded we need to put the inputs back in order
  748 + // before we can use them, so we use a sequencing buffer.
646 else { 749 else {
647 this->inputBuffer = new SequencingBuffer(); 750 this->inputBuffer = new SequencingBuffer();
648 } 751 }
649 } 752 }
  753 +
650 ~SingleThreadStage() 754 ~SingleThreadStage()
651 { 755 {
652 delete inputBuffer; 756 delete inputBuffer;
@@ -657,6 +761,7 @@ public: @@ -657,6 +761,7 @@ public:
657 QWriteLocker writeLock(&statusLock); 761 QWriteLocker writeLock(&statusLock);
658 currentStatus = STOPPING; 762 currentStatus = STOPPING;
659 next_target = 0; 763 next_target = 0;
  764 + inputBuffer->reset();
660 } 765 }
661 766
662 767
@@ -706,7 +811,13 @@ public: @@ -706,7 +811,13 @@ public:
706 next->stages = stages; 811 next->stages = stages;
707 next->start_idx = this->stage_id; 812 next->start_idx = this->stage_id;
708 next->startItem = newItem; 813 next->startItem = newItem;
709 - this->threads->start(next, stages->size() - stage_id); 814 +
  815 + // We start threads with priority equal to their stage id
  816 + // This is intended to ensure progression, we do queued late stage
  817 + // jobs before queued early stage jobs, and so tend to finish frames
  818 + // rather than go stage by stage. In Qt 5.1, priorities are priorities
  819 + // so we use the stage_id directly.
  820 + this->threads->start(next, stage_id);
710 } 821 }
711 822
712 823
@@ -741,45 +852,50 @@ public: @@ -741,45 +852,50 @@ public:
741 852
742 return true; 853 return true;
743 } 854 }
  855 +
  856 + void status(){
  857 + qDebug("single thread stage %d, status starting? %d, next %d buffer size %d", this->stage_id, this->currentStatus == SingleThreadStage::STARTING, this->next_target, this->inputBuffer->size());
  858 + }
  859 +
744 }; 860 };
745 861
746 -// No input buffer, instead we draw templates from some data source  
747 -// Will be operated by the main thread for the stream. starts threads 862 +// This stage reads new frames from the data source.
748 class FirstStage : public SingleThreadStage 863 class FirstStage : public SingleThreadStage
749 { 864 {
750 public: 865 public:
751 - FirstStage() : SingleThreadStage(true) {} 866 + FirstStage(int activeFrames = 100) : SingleThreadStage(true), dataSource(activeFrames){ }
752 867
753 DataSourceManager dataSource; 868 DataSourceManager dataSource;
754 869
  870 + void reset()
  871 + {
  872 + dataSource.close();
  873 + SingleThreadStage::reset();
  874 + }
  875 +
755 FrameData * run(FrameData * input, bool & should_continue) 876 FrameData * run(FrameData * input, bool & should_continue)
756 { 877 {
757 - // Try to get a frame from the datasource 878 + if (input == NULL)
  879 + qFatal("NULL frame in input stage");
  880 +
  881 + // Can we enter the next stage?
  882 + should_continue = nextStage->tryAcquireNextStage(input);
  883 +
  884 + // Try to get a frame from the datasource, we keep working on
  885 + // the frame we have, but we will queue another job for the next
  886 + // frame if a frame is currently available.
758 QWriteLocker lock(&statusLock); 887 QWriteLocker lock(&statusLock);
759 bool last_frame = false; 888 bool last_frame = false;
760 - input = dataSource.tryGetFrame(last_frame); 889 + FrameData * newFrame = dataSource.tryGetFrame(last_frame);
761 890
762 - // Datasource broke, or is currently out of frames?  
763 - if (!input || last_frame)  
764 - {  
765 - // We will just stop and not continue. 891 + // Were we able to get a frame?
  892 + if (newFrame) startThread(newFrame);
  893 + // If not this stage will enter a stopped state.
  894 + else {
766 currentStatus = STOPPING; 895 currentStatus = STOPPING;
767 - if (!input) {  
768 - should_continue = false;  
769 - return NULL;  
770 - }  
771 } 896 }
772 - lock.unlock();  
773 - // Can we enter the next stage?  
774 - should_continue = nextStage->tryAcquireNextStage(input);  
775 897
776 - // We are exiting leaving this stage, should we start another  
777 - // thread here? Normally we will always re-queue a thread on  
778 - // the first stage, but if we received the last frame there is  
779 - // no need to.  
780 - if (!last_frame) {  
781 - startThread(NULL);  
782 - } 898 + lock.unlock();
783 899
784 return input; 900 return input;
785 } 901 }
@@ -797,31 +913,48 @@ public: @@ -797,31 +913,48 @@ public:
797 } 913 }
798 914
799 QReadLocker lock(&statusLock); 915 QReadLocker lock(&statusLock);
800 - // A thread is already in the first stage,  
801 - // we should just return 916 + // If the first stage is already active we will just end.
802 if (currentStatus == STARTING) 917 if (currentStatus == STARTING)
803 { 918 {
804 return false; 919 return false;
805 } 920 }
806 - // Have to change to a write lock to modify currentStatus 921 +
  922 + // Otherwise we will try to continue, but to do so we have to
  923 + // escalate the lock, and sadly there is no way to do so without
  924 + // releasing the read-mode lock, and getting a new write-mode lock.
807 lock.unlock(); 925 lock.unlock();
808 926
809 QWriteLocker writeLock(&statusLock); 927 QWriteLocker writeLock(&statusLock);
810 - // But someone else might have started a thread in the meantime 928 + // currentStatus might have changed in the gap between releasing the read
  929 + // lock and getting the write lock.
811 if (currentStatus == STARTING) 930 if (currentStatus == STARTING)
812 { 931 {
813 return false; 932 return false;
814 } 933 }
815 - // Ok we'll start a thread 934 +
  935 + bool last_frame = false;
  936 + // Try to get a frame from the data source, if we get one we will
  937 + // continue to the first stage.
  938 + input = dataSource.tryGetFrame(last_frame);
  939 +
  940 + if (!input) {
  941 + return false;
  942 + }
  943 +
816 currentStatus = STARTING; 944 currentStatus = STARTING;
817 945
818 - // We always start a readstage thread with null input, so nothing to do here  
819 return true; 946 return true;
820 } 947 }
821 948
  949 + void status(){
  950 + qDebug("Read stage %d, status starting? %d, next frame %d buffer size %d", this->stage_id, this->currentStatus == SingleThreadStage::STARTING, this->next_target, this->dataSource.size());
  951 + }
  952 +
  953 +
822 }; 954 };
823 955
824 -// starts threads 956 +// Appened to the end of a Stream's transform sequence. Collects the output
  957 +// from each frame on a single templatelist
825 class LastStage : public SingleThreadStage 958 class LastStage : public SingleThreadStage
826 { 959 {
827 public: 960 public:
@@ -834,6 +967,7 @@ public: @@ -834,6 +967,7 @@ public:
834 private: 967 private:
835 TemplateList collectedOutput; 968 TemplateList collectedOutput;
836 public: 969 public:
  970 +
837 void reset() 971 void reset()
838 { 972 {
839 collectedOutput.clear(); 973 collectedOutput.clear();
@@ -873,6 +1007,11 @@ public: @@ -873,6 +1007,11 @@ public:
873 1007
874 return input; 1008 return input;
875 } 1009 }
  1010 +
  1011 + void status(){
  1012 + qDebug("Collection stage %d, status starting? %d, next %d buffer size %d", this->stage_id, this->currentStatus == SingleThreadStage::STARTING, this->next_target, this->inputBuffer->size());
  1013 + }
  1014 +
876 }; 1015 };
877 1016
878 1017
@@ -880,9 +1019,12 @@ class StreamTransform : public CompositeTransform @@ -880,9 +1019,12 @@ class StreamTransform : public CompositeTransform
880 { 1019 {
881 Q_OBJECT 1020 Q_OBJECT
882 public: 1021 public:
  1022 + Q_PROPERTY(int activeFrames READ get_activeFrames WRITE set_activeFrames RESET reset_activeFrames)
  1023 + BR_PROPERTY(int, activeFrames, 100)
883 1024
884 void train(const TemplateList & data) 1025 void train(const TemplateList & data)
885 { 1026 {
  1027 + qFatal("Stream train is currently not implemented.");
886 foreach(Transform * transform, transforms) { 1028 foreach(Transform * transform, transforms) {
887 transform->train(data); 1029 transform->train(data);
888 } 1030 }
@@ -902,7 +1044,8 @@ public: @@ -902,7 +1044,8 @@ public:
902 qFatal("whatever"); 1044 qFatal("whatever");
903 } 1045 }
904 1046
905 - // start processing 1047 + // start processing, consider all templates in src a continuous
  1048 + // 'video'
906 void projectUpdate(const TemplateList & src, TemplateList & dst) 1049 void projectUpdate(const TemplateList & src, TemplateList & dst)
907 { 1050 {
908 dst = src; 1051 dst = src;
@@ -911,12 +1054,22 @@ public: @@ -911,12 +1054,22 @@ public:
911 if (!res) return; 1054 if (!res) return;
912 1055
913 // Start the first thread in the stream. 1056 // Start the first thread in the stream.
  1057 + QWriteLocker lock(&readStage->statusLock);
914 readStage->currentStatus = SingleThreadStage::STARTING; 1058 readStage->currentStatus = SingleThreadStage::STARTING;
915 - readStage->startThread(NULL);  
916 1059
917 - // Wait for the stream to reach the last frame available from 1060 + // We have to get a frame before starting the thread
  1061 + bool last_frame = false;
  1062 + FrameData * firstFrame = readStage->dataSource.tryGetFrame(last_frame);
  1063 + if (firstFrame == NULL)
  1064 + qFatal("Failed to read first frame of video");
  1065 +
  1066 + readStage->startThread(firstFrame);
  1067 + lock.unlock();
  1068 +
  1069 + // Wait for the stream to process the last frame available from
918 // the data source. 1070 // the data source.
919 - readStage->dataSource.waitLast(); 1071 + bool wait_res = false;
  1072 + wait_res = readStage->dataSource.waitLast();
920 1073
921 // Now that there are no more incoming frames, call finalize 1074 // Now that there are no more incoming frames, call finalize
922 // on each transform in turn to collect any last templates 1075 // on each transform in turn to collect any last templates
@@ -958,6 +1111,10 @@ public: @@ -958,6 +1111,10 @@ public:
958 { 1111 {
959 if (transforms.isEmpty()) return; 1112 if (transforms.isEmpty()) return;
960 1113
  1114 + // call CompositeTransform::init so that trainable is set
  1115 + // correctly.
  1116 + CompositeTransform::init();
  1117 +
961 // We share a thread pool across streams attached to the same 1118 // We share a thread pool across streams attached to the same
962 // parent tranform, retrieve or create a thread pool based 1119 // parent tranform, retrieve or create a thread pool based
963 // on our parent transform. 1120 // on our parent transform.
@@ -971,24 +1128,31 @@ public: @@ -971,24 +1128,31 @@ public:
971 threads = it.value(); 1128 threads = it.value();
972 poolLock.unlock(); 1129 poolLock.unlock();
973 1130
  1131 + // Are our children time varying or not? This decides whether
  1132 + // we run them in single threaded or multi threaded stages
974 stage_variance.reserve(transforms.size()); 1133 stage_variance.reserve(transforms.size());
975 foreach (const br::Transform *transform, transforms) { 1134 foreach (const br::Transform *transform, transforms) {
976 stage_variance.append(transform->timeVarying()); 1135 stage_variance.append(transform->timeVarying());
977 } 1136 }
978 1137
979 - readStage = new FirstStage(); 1138 + // Additionally, we have a separate stage responsible for reading
  1139 + // frames from the data source
  1140 + readStage = new FirstStage(activeFrames);
980 1141
981 processingStages.push_back(readStage); 1142 processingStages.push_back(readStage);
982 readStage->stage_id = 0; 1143 readStage->stage_id = 0;
983 readStage->stages = &this->processingStages; 1144 readStage->stages = &this->processingStages;
984 readStage->threads = this->threads; 1145 readStage->threads = this->threads;
985 1146
  1147 + // Initialize and link a processing stage for each of our child
  1148 + // transforms.
986 int next_stage_id = 1; 1149 int next_stage_id = 1;
987 -  
988 bool prev_stage_variance = true; 1150 bool prev_stage_variance = true;
989 for (int i =0; i < transforms.size(); i++) 1151 for (int i =0; i < transforms.size(); i++)
990 { 1152 {
991 if (stage_variance[i]) 1153 if (stage_variance[i])
  1154 + // Whether or not the previous stage is multi-threaded controls
  1155 + // the type of input buffer we need in a single threaded stage.
992 processingStages.append(new SingleThreadStage(prev_stage_variance)); 1156 processingStages.append(new SingleThreadStage(prev_stage_variance));
993 else 1157 else
994 processingStages.append(new MultiThreadStage(Globals->parallelism)); 1158 processingStages.append(new MultiThreadStage(Globals->parallelism));
@@ -1006,20 +1170,25 @@ public: @@ -1006,20 +1170,25 @@ public:
1006 prev_stage_variance = stage_variance[i]; 1170 prev_stage_variance = stage_variance[i];
1007 } 1171 }
1008 1172
  1173 + // We also have the last stage, which just puts the output of the
  1174 + // previous stages on a template list.
1009 collectionStage = new LastStage(prev_stage_variance); 1175 collectionStage = new LastStage(prev_stage_variance);
1010 processingStages.append(collectionStage); 1176 processingStages.append(collectionStage);
1011 collectionStage->stage_id = next_stage_id; 1177 collectionStage->stage_id = next_stage_id;
1012 collectionStage->stages = &this->processingStages; 1178 collectionStage->stages = &this->processingStages;
1013 collectionStage->threads = this->threads; 1179 collectionStage->threads = this->threads;
1014 1180
  1181 + // the last transform stage points to collection stage
1015 processingStages[processingStages.size() - 2]->nextStage = collectionStage; 1182 processingStages[processingStages.size() - 2]->nextStage = collectionStage;
1016 1183
1017 - // It's a ring buffer, get it? 1184 + // And the collection stage points to the read stage, because this is
  1185 + // a ring buffer.
1018 collectionStage->nextStage = readStage; 1186 collectionStage->nextStage = readStage;
1019 } 1187 }
1020 1188
1021 ~StreamTransform() 1189 ~StreamTransform()
1022 { 1190 {
  1191 + // Delete all the stages
1023 for (int i = 0; i < processingStages.size(); i++) { 1192 for (int i = 0; i < processingStages.size(); i++) {
1024 delete processingStages[i]; 1193 delete processingStages[i];
1025 } 1194 }
@@ -1033,6 +1202,21 @@ protected: @@ -1033,6 +1202,21 @@ protected:
1033 1202
1034 QList<ProcessingStage *> processingStages; 1203 QList<ProcessingStage *> processingStages;
1035 1204
  1205 + // This is a map from parent transforms (of Streams) to thread pools. Rather
  1206 + // than starting threads on the global thread pool, Stream uses separate thread pools
  1207 + // keyed on their parent transform. This is necessary because stream's project starts
  1208 + // threads, then enters an indefinite wait for them to finish. Since we are starting
  1209 + // threads using thread pools, threads themselves are a limited resource. Therefore,
  1210 + // the type of hold and wait done by stream project can lead to deadlock unless
  1211 + // resources are ordered in such a way that a circular wait will not occur. The points
  1212 + // of this hash is to introduce a resource ordering (on threads) that mirrors the structure
  1213 + // of the algorithm. So, as long as the structure of the algorithm is a DAG, the wait done
  1214 + // by stream project will not be circular, since every thread in stream project is waiting
  1215 + // for threads at a lower level to do the work.
  1216 + // This issue doesn't come up in distribute, since a thread waiting on a QFutureSynchronizer
  1217 + // will steal work from those jobs, so in that sense distribute isn't doing a hold and wait.
  1218 + // Waiting for a QFutureSynchronzier isn't really possible here since stream runs an indeteriminate
  1219 + // number of jobs.
1036 static QHash<QObject *, QThreadPool *> pools; 1220 static QHash<QObject *, QThreadPool *> pools;
1037 static QMutex poolsAccess; 1221 static QMutex poolsAccess;
1038 QThreadPool * threads; 1222 QThreadPool * threads;
openbr/plugins/svm.cpp
@@ -101,6 +101,8 @@ class SVMTransform : public Transform @@ -101,6 +101,8 @@ class SVMTransform : public Transform
101 Q_PROPERTY(Type type READ get_type WRITE set_type RESET reset_type STORED false) 101 Q_PROPERTY(Type type READ get_type WRITE set_type RESET reset_type STORED false)
102 Q_PROPERTY(float C READ get_C WRITE set_C RESET reset_C STORED false) 102 Q_PROPERTY(float C READ get_C WRITE set_C RESET reset_C STORED false)
103 Q_PROPERTY(float gamma READ get_gamma WRITE set_gamma RESET reset_gamma STORED false) 103 Q_PROPERTY(float gamma READ get_gamma WRITE set_gamma RESET reset_gamma STORED false)
  104 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  105 + Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)
104 106
105 public: 107 public:
106 enum Kernel { Linear = CvSVM::LINEAR, 108 enum Kernel { Linear = CvSVM::LINEAR,
@@ -119,6 +121,9 @@ private: @@ -119,6 +121,9 @@ private:
119 BR_PROPERTY(Type, type, C_SVC) 121 BR_PROPERTY(Type, type, C_SVC)
120 BR_PROPERTY(float, C, -1) 122 BR_PROPERTY(float, C, -1)
121 BR_PROPERTY(float, gamma, -1) 123 BR_PROPERTY(float, gamma, -1)
  124 + BR_PROPERTY(QString, inputVariable, "")
  125 + BR_PROPERTY(QString, outputVariable, "")
  126 +
122 127
123 SVM svm; 128 SVM svm;
124 QHash<QString, int> labelMap; 129 QHash<QString, int> labelMap;
@@ -128,14 +133,15 @@ private: @@ -128,14 +133,15 @@ private:
128 { 133 {
129 Mat data = OpenCVUtils::toMat(_data.data()); 134 Mat data = OpenCVUtils::toMat(_data.data());
130 Mat lab; 135 Mat lab;
131 - // If we are doing regression, assume subject has float values 136 + // If we are doing regression, the input variable should have float
  137 + // values
132 if (type == EPS_SVR || type == NU_SVR) { 138 if (type == EPS_SVR || type == NU_SVR) {
133 - lab = OpenCVUtils::toMat(File::get<float>(_data, "Subject")); 139 + lab = OpenCVUtils::toMat(File::get<float>(_data, inputVariable));
134 } 140 }
135 - // If we are doing classification, assume subject has discrete values, map them  
136 - // and store the mapping data 141 + // If we are doing classification, we should be dealing with discrete
  142 + // values. Map them and store the mapping data
137 else { 143 else {
138 - QList<int> dataLabels = _data.indexProperty("Subject", labelMap, reverseLookup); 144 + QList<int> dataLabels = _data.indexProperty(inputVariable, labelMap, reverseLookup);
139 lab = OpenCVUtils::toMat(dataLabels); 145 lab = OpenCVUtils::toMat(dataLabels);
140 } 146 }
141 trainSVM(svm, data, lab, kernel, type, C, gamma); 147 trainSVM(svm, data, lab, kernel, type, C, gamma);
@@ -146,9 +152,9 @@ private: @@ -146,9 +152,9 @@ private:
146 dst = src; 152 dst = src;
147 float prediction = svm.predict(src.m().reshape(1, 1)); 153 float prediction = svm.predict(src.m().reshape(1, 1));
148 if (type == EPS_SVR || type == NU_SVR) 154 if (type == EPS_SVR || type == NU_SVR)
149 - dst.file.set("Subject", prediction); 155 + dst.file.set(outputVariable, prediction);
150 else 156 else
151 - dst.file.set("Subject", reverseLookup[prediction]); 157 + dst.file.set(outputVariable, reverseLookup[prediction]);
152 } 158 }
153 159
154 void store(QDataStream &stream) const 160 void store(QDataStream &stream) const
@@ -162,6 +168,24 @@ private: @@ -162,6 +168,24 @@ private:
162 loadSVM(svm, stream); 168 loadSVM(svm, stream);
163 stream >> labelMap >> reverseLookup; 169 stream >> labelMap >> reverseLookup;
164 } 170 }
  171 +
  172 + void init()
  173 + {
  174 + // Since SVM can do regression or classification, we have to check the problem type before
  175 + // specifying target variable names
  176 + if (inputVariable.isEmpty())
  177 + {
  178 + if (type == EPS_SVR || type == NU_SVR) {
  179 + inputVariable = "Regressor";
  180 + if (outputVariable.isEmpty())
  181 + outputVariable = "Regressand";
  182 + }
  183 + else
  184 + inputVariable = "Label";
  185 + }
  186 + if (outputVariable.isEmpty())
  187 + outputVariable = inputVariable;
  188 + }
165 }; 189 };
166 190
167 BR_REGISTER(Transform, SVMTransform) 191 BR_REGISTER(Transform, SVMTransform)
@@ -178,6 +202,8 @@ class SVMDistance : public Distance @@ -178,6 +202,8 @@ class SVMDistance : public Distance
178 Q_ENUMS(Type) 202 Q_ENUMS(Type)
179 Q_PROPERTY(Kernel kernel READ get_kernel WRITE set_kernel RESET reset_kernel STORED false) 203 Q_PROPERTY(Kernel kernel READ get_kernel WRITE set_kernel RESET reset_kernel STORED false)
180 Q_PROPERTY(Type type READ get_type WRITE set_type RESET reset_type STORED false) 204 Q_PROPERTY(Type type READ get_type WRITE set_type RESET reset_type STORED false)
  205 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  206 +
181 207
182 public: 208 public:
183 enum Kernel { Linear = CvSVM::LINEAR, 209 enum Kernel { Linear = CvSVM::LINEAR,
@@ -194,13 +220,14 @@ public: @@ -194,13 +220,14 @@ public:
194 private: 220 private:
195 BR_PROPERTY(Kernel, kernel, Linear) 221 BR_PROPERTY(Kernel, kernel, Linear)
196 BR_PROPERTY(Type, type, EPS_SVR) 222 BR_PROPERTY(Type, type, EPS_SVR)
  223 + BR_PROPERTY(QString, inputVariable, "Label")
197 224
198 SVM svm; 225 SVM svm;
199 226
200 void train(const TemplateList &src) 227 void train(const TemplateList &src)
201 { 228 {
202 const Mat data = OpenCVUtils::toMat(src.data()); 229 const Mat data = OpenCVUtils::toMat(src.data());
203 - const QList<int> lab = src.indexProperty("Subject"); 230 + const QList<int> lab = src.indexProperty(inputVariable);
204 231
205 const int instances = data.rows * (data.rows+1) / 2; 232 const int instances = data.rows * (data.rows+1) / 2;
206 Mat deltaData(instances, data.cols, data.type()); 233 Mat deltaData(instances, data.cols, data.type());
openbr/plugins/validate.cpp
@@ -147,26 +147,29 @@ class MetadataDistance : public Distance @@ -147,26 +147,29 @@ class MetadataDistance : public Distance
147 float compare(const Template &a, const Template &b) const 147 float compare(const Template &a, const Template &b) const
148 { 148 {
149 foreach (const QString &key, filters) { 149 foreach (const QString &key, filters) {
  150 + QString aValue = a.file.get<QString>(key, QString());
  151 + QString bValue = b.file.get<QString>(key, QString());
150 152
151 - const QString aValue = a.file.get<QString>(key, "");  
152 - const QString bValue = b.file.get<QString>(key, ""); 153 + // The query value may be a range. Let's check.
  154 + if (bValue.isEmpty()) bValue = QtUtils::toString(b.file.get<QPointF>(key, QPointF()));
153 155
154 if (aValue.isEmpty() || bValue.isEmpty()) continue; 156 if (aValue.isEmpty() || bValue.isEmpty()) continue;
155 157
156 bool keep = false; 158 bool keep = false;
  159 + bool ok;
157 160
158 - if (aValue[0] == '(') /* Range */ {  
159 - QStringList values = aValue.split(','); 161 + QPointF range = QtUtils::toPoint(bValue,&ok);
160 162
161 - int value = values[0].mid(1).toInt();  
162 - values[1].chop(1);  
163 - int upperBound = values[1].toInt(); 163 + if (ok) /* Range */ {
  164 + int value = range.x();
  165 + int upperBound = range.y();
164 166
165 while (value <= upperBound) { 167 while (value <= upperBound) {
166 - if (aValue == bValue) { 168 + if (aValue == QString::number(value)) {
167 keep = true; 169 keep = true;
168 break; 170 break;
169 } 171 }
  172 + value++;
170 } 173 }
171 } 174 }
172 else if (aValue == bValue) keep = true; 175 else if (aValue == bValue) keep = true;
scripts/evalAgeRegression-PCSO.sh
@@ -4,8 +4,12 @@ if [ ! -f evalAgeRegression-PCSO.sh ]; then @@ -4,8 +4,12 @@ if [ ! -f evalAgeRegression-PCSO.sh ]; then
4 exit 4 exit
5 fi 5 fi
6 6
  7 +export BR="../build/app/br/br -useGui 0"
  8 +export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/
  9 +export ageAlg=AgeRegression
  10 +
7 # Create a file list by querying the database 11 # Create a file list by querying the database
8 -br -quiet -algorithm Identity -enroll "../data/PCSO/PCSO.db[query='SELECT File,Age,PersonID FROM PCSO WHERE Age >= 15 AND AGE <= 75', subset=1:200]" terminal.txt > Input.txt 12 +$BR -quiet -algorithm Identity -enroll "$PCSO_DIR/PCSO.db[query='SELECT File,Age,PersonID FROM PCSO WHERE Age >= 17 AND AGE <= 68', subset=1:200]" terminal.txt > Input.txt
9 13
10 # Enroll the file list and evaluate performance 14 # Enroll the file list and evaluate performance
11 -br -algorithm AgeRegression -path ../data/PCSO/img -enroll Input.txt Output.txt -evalRegression Output.txt Input.txt 15 +$BR -algorithm $ageAlg -path $PCSO_DIR/Images -enroll Input.txt Output.txt -evalRegression Output.txt Input.txt Age
scripts/evalFaceRecognition-MEDS.sh
@@ -20,11 +20,11 @@ if [ ! -e Algorithm_Dataset ]; then @@ -20,11 +20,11 @@ if [ ! -e Algorithm_Dataset ]; then
20 fi 20 fi
21 21
22 if [ ! -e MEDS.mask ]; then 22 if [ ! -e MEDS.mask ]; then
23 - br -makeMask ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml MEDS.mask 23 + br -useGui 0 -makeMask ../data/MEDS/sigset/MEDS_frontal_target.xml ../data/MEDS/sigset/MEDS_frontal_query.xml MEDS.mask
24 fi 24 fi
25 25
26 # Run Algorithm on MEDS 26 # Run Algorithm on MEDS
27 -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 27 +br -useGui 0 -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
28 28
29 # Plot results 29 # Plot results
30 -br -plot Algorithm_Dataset/*_MEDS.csv MEDS 30 +br -useGui 0 -plot Algorithm_Dataset/*_MEDS.csv MEDS
scripts/evalGenderClassification-PCSO.sh
@@ -4,8 +4,13 @@ if [ ! -f evalGenderClassification-PCSO.sh ]; then @@ -4,8 +4,13 @@ if [ ! -f evalGenderClassification-PCSO.sh ]; then
4 exit 4 exit
5 fi 5 fi
6 6
  7 +export BR=../build/app/br/br
  8 +export genderAlg=GenderClassification
  9 +
  10 +export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/
  11 +
7 # Create a file list by querying the database 12 # Create a file list by querying the database
8 -br -quiet -algorithm Identity -enroll "../data/PCSO/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=1:8000]" terminal.txt > Input.txt 13 +$BR -useGui 0 -quiet -algorithm Identity -enroll "$PCSO_DIR/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=1:8000]" terminal.txt > Input.txt
9 14
10 # Enroll the file list and evaluate performance 15 # Enroll the file list and evaluate performance
11 -br -algorithm GenderClassification -path ../data/PCSO/img -enroll Input.txt Output.txt -evalClassification Output.txt Input.txt 16 +$BR -useGui 0 -algorithm $genderAlg -path $PCSO_DIR/Images -enroll Input.txt Output.txt -evalClassification Output.txt Input.txt Gender
12 \ No newline at end of file 17 \ No newline at end of file
scripts/trainAgeRegression-PCSO.sh
@@ -6,6 +6,11 @@ fi @@ -6,6 +6,11 @@ fi
6 6
7 #rm -f ../share/openbr/models/features/FaceClassificationRegistration 7 #rm -f ../share/openbr/models/features/FaceClassificationRegistration
8 #rm -f ../share/openbr/models/features/FaceClassificationExtraction 8 #rm -f ../share/openbr/models/features/FaceClassificationExtraction
9 -rm -f ../share/openbr/models/algorithms/AgeRegression 9 +#rm -f ../share/openbr/models/algorithms/AgeRegression
10 10
11 -br -algorithm AgeRegression -path ../data/PCSO/Images -train "../data/PCSO/PCSO.db[query='SELECT File,Age,PersonID FROM PCSO WHERE Age >= 15 AND AGE <= 75', subset=0:200]" ../share/openbr/models/algorithms/AgeRegression 11 +export BR=../build/app/br/br
  12 +export ageAlg=AgeRegression
  13 +
  14 +export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/
  15 +
  16 +$BR -useGui 0 -algorithm $ageAlg -path $PCSO_DIR/Images -train "$PCSO_DIR/PCSO.db[query='SELECT File,Age,PersonID FROM PCSO WHERE Age >= 17 AND AGE <= 68', subset=0:200]" ../share/openbr/models/algorithms/AgeRegression
scripts/trainFaceRecognition-PCSO.sh
@@ -8,6 +8,13 @@ fi @@ -8,6 +8,13 @@ fi
8 #rm -f ../share/openbr/models/features/FaceRecognitionExtraction 8 #rm -f ../share/openbr/models/features/FaceRecognitionExtraction
9 #rm -f ../share/openbr/models/features/FaceRecognitionEmbedding 9 #rm -f ../share/openbr/models/features/FaceRecognitionEmbedding
10 #rm -f ../share/openbr/models/features/FaceRecognitionQuantization 10 #rm -f ../share/openbr/models/features/FaceRecognitionQuantization
11 -rm -f ../share/openbr/models/algorithms/FaceRecognition 11 +#rm -f ../share/openbr/models/algorithms/FaceRecognition
  12 +
  13 +export BR=../build/app/br/br
  14 +
  15 +export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/
  16 +
  17 +
  18 +
  19 +$BR -useGui 0 -algorithm FaceRecognition -path "$PCSO_DIR/Images/" -train "$PCSO_DIR/PCSO.db[query='SELECT File,PersonID as Label,PersonID FROM PCSO', subset=0:5:6000]" ../share/openbr/models/algorithms/FaceRecognition
12 20
13 -br -algorithm FaceRecognition -path ../data/PCSO/img -train "../data/PCSO/PCSO.db[query='SELECT File,'S'||PersonID,PersonID FROM PCSO', subset=0:5:6000]" ../share/openbr/models/algorithms/FaceRecognition  
scripts/trainGenderClassification-PCSO.sh
@@ -6,6 +6,11 @@ fi @@ -6,6 +6,11 @@ fi
6 6
7 #rm -f ../share/openbr/models/features/FaceClassificationRegistration 7 #rm -f ../share/openbr/models/features/FaceClassificationRegistration
8 #rm -f ../share/openbr/models/features/FaceClassificationExtraction 8 #rm -f ../share/openbr/models/features/FaceClassificationExtraction
9 -rm -f ../share/openbr/models/algorithms/GenderClassification 9 +#rm -f ../share/openbr/models/algorithms/GenderClassification
10 10
11 -br -algorithm GenderClassification -path ../data/PCSO/Images -train "../data/PCSO/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=0:8000]" ../share/openbr/models/algorithms/GenderClassification 11 +export BR=../build/app/br/br
  12 +export genderAlg=GenderClassification
  13 +
  14 +export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/
  15 +
  16 +$BR -useGui 0 -algorithm $genderAlg -path $PCSO_DIR/Images -train "$PCSO_DIR/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=0:8000]" ../share/openbr/models/algorithms/GenderClassification