Commit ac4a861fd23c63b36cbb95d5c1812f3ee95ebde2

Authored by Jordan Cheney
1 parent 4cb426df

More docs work

docs/docs/docs/cpp_api.md
... ... @@ -24,11 +24,11 @@ Values are not necessarily stored as strings in the metadata table.
24 24 The system will attempt to infer and convert them to their "native" type.
25 25 The conversion logic is as follows:
26 26  
27   -1. If the value starts with **[** and ends with **]** then it is treated as a comma separated list and represented with <a href=http://doc.qt.io/qt-5/qvariant.html#QVariantList-typedef>QVariantList</a>. Each value in the list is parsed recursively.
28   -2. If the value starts with **(** and ends with **)** and contains four comma separated elements, each convertable to a floating point number, then it is represented with <a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a>.
29   -3. If the value starts with **(** and ends with **)** and contains two comma separated elements, each convertable to a floating point number, then it is represented with <a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a>.
  27 +1. If the value starts with **[** and ends with **]** then it is treated as a comma separated list and represented with [QVariantList](http://doc.qt.io/qt-5/qvariant.html#QVariantList-typedef). Each value in the list is parsed recursively.
  28 +2. If the value starts with **(** and ends with **)** and contains four comma separated elements, each convertable to a floating point number, then it is represented with [QRectF](http://doc.qt.io/qt-4.8/qrectf.html).
  29 +3. If the value starts with **(** and ends with **)** and contains two comma separated elements, each convertable to a floating point number, then it is represented with [QPointF](http://doc.qt.io/qt-4.8/qpointf.html).
30 30 4. If the value is convertable to a floating point number then it is represented with <tt>float</tt>.
31   -5. Otherwise, it is represented with <a href=http://doc.qt.io/qt-5/QString.html>QString</a>.
  31 +5. Otherwise, it is represented with [QString](http://doc.qt.io/qt-5/QString.html).
32 32  
33 33 Metadata keys fall into one of two categories:
34 34 * camelCaseKeys are inputs that specify how to process the file.
... ... @@ -44,11 +44,11 @@ Index | int | Index of a template in a template list
44 44 Confidence | float | Classification/Regression quality
45 45 FTE | bool | Failure to enroll
46 46 FTO | bool | Failure to open
47   -*_X | float | Position
48   -*_Y | float | Position
49   -*_Width | float | Size
50   -*_Height | float | Size
51   -*_Radius | float | Size
  47 +\*_X | float | Position
  48 +\*_Y | float | Position
  49 +\*_Width | float | Size
  50 +\*_Height | float | Size
  51 +\*_Radius | float | Size
52 52 Label | QString | Class label
53 53 Theta | float | Pose
54 54 Roll | float | Pose
... ... @@ -59,7 +59,7 @@ Rects | QList&lt;Rect&gt; | List of unnamed rects
59 59 Age | float | Age used for demographic filtering
60 60 Gender | QString | Subject gender
61 61 Train | bool | The data is for training, as opposed to enrollment
62   -_* | * | Reserved for internal use
  62 +_\* | \* | Reserved for internal use
63 63  
64 64 ---
65 65  
... ... @@ -75,7 +75,7 @@ Failed to enroll. If true this file failed to be processed somewhere in the temp
75 75  
76 76 ### m_metadata
77 77  
78   -Map for storing metadata. It is a <a href=http://doc.qt.io/qt-5/QString.html>QString</a>, <a href=http://doc.qt.io/qt-5/qvariant.html>QVariant</a> key value pairing.
  78 +Map for storing metadata. It is a [QString](http://doc.qt.io/qt-5/QString.html), [QVariant](http://doc.qt.io/qt-5/qvariant.html) key value pairing.
79 79  
80 80 ---
81 81  
... ... @@ -85,11 +85,11 @@ Map for storing metadata. It is a &lt;a href=http://doc.qt.io/qt-5/QString.html&gt;QSt
85 85  
86 86 Default constructor. Sets [FTE](#fte) to false.
87 87  
88   -### File(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &file)
  88 +### File(const [QString](http://doc.qt.io/qt-5/QString.html) &file)
89 89  
90 90 Initializes the file by calling the private function init.
91 91  
92   -### File(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &file, const <a href=http://doc.qt.io/qt-5/qvariant.html>QVariant</a> &label)
  92 +### File(const [QString](http://doc.qt.io/qt-5/QString.html) &file, const [QVariant](http://doc.qt.io/qt-5/qvariant.html) &label)
93 93  
94 94 Initializes the file by calling the private function init. Append label to the [metadata](#m_metadata) using the key "Label".
95 95  
... ... @@ -97,7 +97,7 @@ Initializes the file by calling the private function init. Append label to the [
97 97  
98 98 Initializes the file with a c-style string.
99 99  
100   -### File(const <a href=http://doc.qt.io/qt-5/qvariant.html#QVariantMap-typedef>QVariantMap</a> &metadata)
  100 +### File(const [QVariantMap](http://doc.qt.io/qt-5/qvariant.html#QVariantMap-typedef) &metadata)
101 101  
102 102 Sets [FTE](#file#fte) to false and sets the [file metadata](#m_metadata) to metadata.
103 103  
... ... @@ -106,9 +106,9 @@ Sets [FTE](#file#fte) to false and sets the [file metadata](#m_metadata) to meta
106 106 ## Static Functions
107 107  
108 108  
109   -### static <a href=http://doc.qt.io/qt-5/qvariant.html>QVariant</a> parse(<a href=http://doc.qt.io/qt-5/QString.html>QString</a> &value) const
  109 +### static [QVariant](http://doc.qt.io/qt-5/qvariant.html) parse([QString](http://doc.qt.io/qt-5/QString.html) &value) const
110 110  
111   -Try to convert value to a <a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a>, <a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a>, int or float. If a conversion is possible it returns the converted value, otherwise it returns the unconverted string.
  111 +Try to convert value to a [QPointF](http://doc.qt.io/qt-4.8/qpointf.html), [QRectF](http://doc.qt.io/qt-4.8/qrectf.html), int or float. If a conversion is possible it returns the converted value, otherwise it returns the unconverted string.
112 112  
113 113 QString point = "(1, 1)";
114 114 QString rect = "(1, 1, 5, 5)";
... ... @@ -122,9 +122,9 @@ Try to convert value to a &lt;a href=http://doc.qt.io/qt-4.8/qpointf.html&gt;QPointF&lt;/
122 122 File::parse(fp); // returns QVariant(float, 1.0f)
123 123 File::parse(string); // returns QVariant(QString, "Hello World")
124 124  
125   -### static <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-5/qvariant.html>QVariant</a>&gt; values(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;U&gt; &fileList, const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key)
  125 +### static [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QVariant](http://doc.qt.io/qt-5/qvariant.html)&gt; values(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;U&gt; &fileList, const [QString](http://doc.qt.io/qt-5/QString.html) &key)
126 126  
127   -This function requires a type specification in place of U. Valid types are [File](#file) and <a href=http://doc.qt.io/qt-5/QString.html>QString</a>. Returns a list of the values of the key in each of the given files.
  127 +This function requires a type specification in place of U. Valid types are [File](#file) and [QString](http://doc.qt.io/qt-5/QString.html). Returns a list of the values of the key in each of the given files.
128 128  
129 129 File f1, f2;
130 130 f1.set("Key1", QVariant::fromValue<float>(1));
... ... @@ -134,9 +134,9 @@ This function requires a type specification in place of U. Valid types are [File
134 134 File::values<File>(QList<File>() << f1 << f2, "Key1"); // returns [QVariant(float, 1),
135 135 // QVariant(float, 3)]
136 136  
137   -### static <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;T&gt; get(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;U&gt; &fileList, const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key)
  137 +### static [QList](http://doc.qt.io/qt-5/QList.html)&lt;T&gt; get(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;U&gt; &fileList, const [QString](http://doc.qt.io/qt-5/QString.html) &key)
138 138  
139   -This function requires a type specification in place of T and U. Valid types for U are [File](#file) and <a href=http://doc.qt.io/qt-5/QString.html>QString</a>. T can be any type. Returns a list of the values of the key in each of the given files. If the key doesn't exist in any of the files or the value cannot be converted to type T an error is thrown.
  139 +This function requires a type specification in place of T and U. Valid types for U are [File](#file) and [QString](http://doc.qt.io/qt-5/QString.html). T can be any type. Returns a list of the values of the key in each of the given files. If the key doesn't exist in any of the files or the value cannot be converted to type T an error is thrown.
140 140  
141 141 File f1, f2;
142 142 f1.set("Key1", QVariant::fromValue<float>(1));
... ... @@ -147,9 +147,9 @@ This function requires a type specification in place of T and U. Valid types for
147 147 File::get<float, File>(QList<File>() << f1 << f2, "Key2"); // Error: Key doesn't exist in f2
148 148 File::get<QRectF, File>(QList<File>() << f1 << f2, "Key1"); // Error: float is not convertable to QRectF
149 149  
150   -### static <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;T&gt; get(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;U&gt; &fileList, const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key, const T &defaultValue)
  150 +### static [QList](http://doc.qt.io/qt-5/QList.html)&lt;T&gt; get(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;U&gt; &fileList, const [QString](http://doc.qt.io/qt-5/QString.html) &key, const T &defaultValue)
151 151  
152   -This function requires a type specification in place of T and U. Valid types for U are [File](#file) and <a href=http://doc.qt.io/qt-5/QString.html>QString</a>. T can be any type. Returns a list of the values of the key in each of the given files. If the key doesn't exist in any of the files or the value cannot be converted to type T the given defaultValue is returned.
  152 +This function requires a type specification in place of T and U. Valid types for U are [File](#file) and [QString](http://doc.qt.io/qt-5/QString.html). T can be any type. Returns a list of the values of the key in each of the given files. If the key doesn't exist in any of the files or the value cannot be converted to type T the given defaultValue is returned.
153 153  
154 154 File f1, f2;
155 155 f1.set("Key1", QVariant::fromValue<float>(1));
... ... @@ -160,7 +160,7 @@ This function requires a type specification in place of T and U. Valid types for
160 160 File::get<float, File>(QList<File>() << f1 << f2, "Key2", QList<float>() << 1); // returns [1.]
161 161 File::get<QRectF, File>(QList<File>() << f1 << f2, "Key1, QList<QRectF>()"); // returns []
162 162  
163   -### <a href=http://doc.qt.io/qt-5/qdebug.html>QDebug</a> operator <<(<a href=http://doc.qt.io/qt-5/qdebug.html>QDebug</a> dbg, const [File](#file) &file)
  163 +### [QDebug](http://doc.qt.io/qt-5/qdebug.html) operator <<([QDebug](http://doc.qt.io/qt-5/qdebug.html) dbg, const [File](#file) &file)
164 164  
165 165 Calls [flat](#qstring-flat-const) on the given file and that streams that file to stderr.
166 166  
... ... @@ -169,7 +169,7 @@ Calls [flat](#qstring-flat-const) on the given file and that streams that file t
169 169  
170 170 qDebug() << file; // "../path/to/pictures/picture.jpg[Key=Value]" streams to stderr
171 171  
172   -### <a href=http://doc.qt.io/qt-5/qdatastream.html>QDataStream</a> &operator <<(<a href=http://doc.qt.io/qt-5/qdatastream.html>QDataStream</a> &stream, const [File](#file) &file)
  172 +### [QDataStream](http://doc.qt.io/qt-5/qdatastream.html) &operator <<([QDataStream](http://doc.qt.io/qt-5/qdatastream.html) &stream, const [File](#file) &file)
173 173  
174 174 Serialize a file to a data stream.
175 175  
... ... @@ -181,7 +181,7 @@ Serialize a file to a data stream.
181 181 stream << file; // "../path/to/pictures/picture.jpg[Key=Value]" serialized to the stream
182 182 }
183 183  
184   -### <a href=http://doc.qt.io/qt-5/qdatastream.html>QDataStream</a> &operator >>(<a href=http://doc.qt.io/qt-5/qdatastream.html>QDataStream</a> &stream, [File](#file) &file)
  184 +### [QDataStream](http://doc.qt.io/qt-5/qdatastream.html) &operator >>([QDataStream](http://doc.qt.io/qt-5/qdatastream.html) &stream, [File](#file) &file)
185 185  
186 186 Deserialize a file from a data stream.
187 187  
... ... @@ -203,11 +203,11 @@ Deserialize a file from a data stream.
203 203  
204 204 ## Functions
205 205  
206   -### Operator <a href=http://doc.qt.io/qt-5/QString.html>QString</a>() const
  206 +### Operator [QString](http://doc.qt.io/qt-5/QString.html)() const
207 207  
208   -returns [name](#name). Allows Files to be used as <a href=http://doc.qt.io/qt-5/QString.html>QString</a>.
  208 +returns [name](#name). Allows Files to be used as [QString](http://doc.qt.io/qt-5/QString.html).
209 209  
210   -### <a href=http://doc.qt.io/qt-5/QString.html>QString</a> flat() const
  210 +### [QString](http://doc.qt.io/qt-5/QString.html) flat() const
211 211  
212 212 Returns the [name](#name) and [metadata](#m_metadata) as string.
213 213  
... ... @@ -217,7 +217,7 @@ Returns the [name](#name) and [metadata](#m_metadata) as string.
217 217  
218 218 file.flat(); // returns "../path/to/pictures/picture.jpg[Key1=1,Key2=2]"
219 219  
220   -### <a href=http://doc.qt.io/qt-5/QString.html>QString</a> hash() const
  220 +### [QString](http://doc.qt.io/qt-5/QString.html) hash() const
221 221  
222 222 Returns a hash of the file.
223 223  
... ... @@ -227,7 +227,7 @@ Returns a hash of the file.
227 227  
228 228 file.hash(); // returns "kElVwY"
229 229  
230   -### <a href=http://doc.qt.io/qt-5/qstringlist.html>QStringList</a> localKeys() const
  230 +### [QStringList](http://doc.qt.io/qt-5/qstringlist.html) localKeys() const
231 231  
232 232 Returns an immutable version of the local metadata keys gotten by calling [metadata](#metadata).keys().
233 233  
... ... @@ -237,7 +237,7 @@ Returns an immutable version of the local metadata keys gotten by calling [metad
237 237  
238 238 file.localKeys(); // returns [Key1, Key2]
239 239  
240   -### <a href=http://doc.qt.io/qt-5/qvariant.html#QVariantMap-typedef>QVariantMap</a> localMetadata() const
  240 +### [QVariantMap](http://doc.qt.io/qt-5/qvariant.html#QVariantMap-typedef) localMetadata() const
241 241  
242 242 returns an immutable version of the local [metadata](#m_metadata).
243 243  
... ... @@ -247,7 +247,7 @@ returns an immutable version of the local [metadata](#m_metadata).
247 247  
248 248 file.localMetadata(); // return QMap(("Key1", QVariant(float, 1)) ("Key2", QVariant(float, 2)))
249 249  
250   -### void append(<a href=http://doc.qt.io/qt-5/qvariant.html#QVariantMap-typedef>QVariantMap</a> &localMetadata)
  250 +### void append([QVariantMap](http://doc.qt.io/qt-5/qvariant.html#QVariantMap-typedef) &localMetadata)
251 251  
252 252 Add new metadata fields to [metadata](#m_metadata).
253 253  
... ... @@ -277,7 +277,7 @@ Append another file using the **;** separator. The file names are combined with
277 277 f1.localKeys(); // returns "[Key1, Key2, Key3, separator]"
278 278  
279 279  
280   -### File &operator +=(const <a href=http://doc.qt.io/qt-5/qmap.html>QMap</a><<a href=http://doc.qt.io/qt-5/QString.html>QString</a>, <a href=http://doc.qt.io/qt-5/qvariant.html>QVariant</a>> &other)
  280 +### File &operator +=(const [QMap](http://doc.qt.io/qt-5/qmap.html)&lt;[QString](http://doc.qt.io/qt-5/QString.html), [QVariant](http://doc.qt.io/qt-5/qvariant.html)&gt; &other)
281 281  
282 282 Shortcut operator to call [append](#void-appendqvariantmap-localmetadata).
283 283  
... ... @@ -285,7 +285,7 @@ Shortcut operator to call [append](#void-appendqvariantmap-localmetadata).
285 285  
286 286 Shortcut operator to call [append](#void-appendconst-file-other).
287 287  
288   -### <a href=http://doc.qt.io/qt-5/qlist.html>QList</a><[File](#file)> split() const
  288 +### [QList](http://doc.qt.io/qt-5/qlist.html)&lt;[File](#file)&gt; split() const
289 289  
290 290 Parse [name](#name) and split on the **;** separator. Each split file has the same [metadata](#m_metadata) as the joined file.
291 291  
... ... @@ -302,7 +302,7 @@ Parse [name](#name) and split on the **;** separator. Each split file has the sa
302 302 f1.split(); // returns [../path/to/pictures/picture1.jpg[Key1=1, Key2=2, Key3=3, separator=;],
303 303 // ../path/to/pictures/picture2.jpg[Key1=1, Key2=2, Key3=3, separator=;]]
304 304  
305   -### <a href=http://doc.qt.io/qt-5/qlist.html>QList</a><[File](#file)> split(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &separator) const
  305 +### [QList](http://doc.qt.io/qt-5/qlist.html)&lt;[File](#file)&gt; split(const [QString](http://doc.qt.io/qt-5/QString.html) &separator) const
306 306  
307 307 Split the file on the given separator. Each split file has the same [metadata](#m_metadata) as the joined file.
308 308  
... ... @@ -313,7 +313,7 @@ Split the file on the given separator. Each split file has the same [metadata](#
313 313 f.split(","); // returns [../path/to/pictures/picture1.jpg[Key1=1, Key2=2],
314 314 ../path/to/pictures/picture2.jpg[Key1=1, Key2=2]]
315 315  
316   -### void setParameter(int index, const <a href=http://doc.qt.io/qt-5/qvariant.html>QVariant</a> &value)
  316 +### void setParameter(int index, const [QVariant](http://doc.qt.io/qt-5/qvariant.html) &value)
317 317  
318 318 Insert a keyless value into the [metadata](#m_metadata).
319 319  
... ... @@ -397,39 +397,39 @@ Returns true if [name](#name) equals &quot;Terminal&quot;.
397 397  
398 398 Returns true if the file at [name](#name) exists on disk.
399 399  
400   -### <a href=http://doc.qt.io/qt-5/QString.html>QString</a> fileName() const
  400 +### [QString](http://doc.qt.io/qt-5/QString.html) fileName() const
401 401  
402 402 Returns the file's base name and extension.
403 403  
404 404 File file("../path/to/pictures/picture.jpg");
405 405 file.fileName(); // returns "picture.jpg"
406 406  
407   -### <a href=http://doc.qt.io/qt-5/QString.html>QString</a> baseName() const
  407 +### [QString](http://doc.qt.io/qt-5/QString.html) baseName() const
408 408  
409 409 Returns the file's base name.
410 410  
411 411 File file("../path/to/pictures/picture.jpg");
412 412 file.baseName(); // returns "picture"
413 413  
414   -### <a href=http://doc.qt.io/qt-5/QString.html>QString</a> suffix() const
  414 +### [QString](http://doc.qt.io/qt-5/QString.html) suffix() const
415 415  
416 416 Returns the file's extension.
417 417  
418 418 File file("../path/to/pictures/picture.jpg");
419 419 file.suffix(); // returns "jpg"
420 420  
421   -### <a href=http://doc.qt.io/qt-5/QString.html>QString</a> path() const
  421 +### [QString](http://doc.qt.io/qt-5/QString.html) path() const
422 422  
423 423 Return's the path of the file, excluding the name.
424 424  
425 425 File file("../path/to/pictures/picture.jpg");
426 426 file.suffix(); // returns "../path/to/pictures"
427 427  
428   -### <a href=http://doc.qt.io/qt-5/QString.html>QString</a> resolved() const
  428 +### [QString](http://doc.qt.io/qt-5/QString.html) resolved() const
429 429  
430 430 Returns [name](#name). If name does not exist it prepends name with the path in Globals->path.
431 431  
432   -### bool contains(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key) const
  432 +### bool contains(const [QString](http://doc.qt.io/qt-5/QString.html) &key) const
433 433  
434 434 Returns True if the key is in the [metadata](#m_metadata) and False otherwise.
435 435  
... ... @@ -439,7 +439,7 @@ Returns True if the key is in the [metadata](#m_metadata) and False otherwise.
439 439 file.contains("Key1"); // returns true
440 440 file.contains("Key2"); // returns false
441 441  
442   -### bool contains(const <a href=http://doc.qt.io/qt-4.8/qstringlist.html>QStringList</a> &keys) const
  442 +### bool contains(const [QStringList](http://doc.qt.io/qt-4.8/qstringlist.html) &keys) const
443 443  
444 444 Returns True if all of the keys are in the [metadata](#m_metadata) and False otherwise.
445 445  
... ... @@ -451,7 +451,7 @@ Returns True if all of the keys are in the [metadata](#m_metadata) and False oth
451 451 file.contains(QStringList() << "Key1" << "Key2") // returns true
452 452 file.contains(QStringList() << "Key1" << "Key3"); // returns false
453 453  
454   -### <a href=http://doc.qt.io/qt-5/qvariant.html>QVariant</a> value(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key) const
  454 +### [QVariant](http://doc.qt.io/qt-5/qvariant.html) value(const [QString](http://doc.qt.io/qt-5/QString.html) &key) const
455 455  
456 456 Returns the value associated with key in the [metadata](#m_metadata).
457 457  
... ... @@ -459,7 +459,7 @@ Returns the value associated with key in the [metadata](#m_metadata).
459 459 file.set("Key1", QVariant::fromValue<float>(1));
460 460 file.value("Key1"); // returns QVariant(float, 1)
461 461  
462   -### void set(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key, const <a href=http://doc.qt.io/qt-5/qvariant.html>QVariant</a> &value)
  462 +### void set(const [QString](http://doc.qt.io/qt-5/QString.html) &key, const [QVariant](http://doc.qt.io/qt-5/qvariant.html) &value)
463 463  
464 464 Insert or overwrite the [metadata](#m_metadata) key with the given value.
465 465  
... ... @@ -469,7 +469,7 @@ Insert or overwrite the [metadata](#m_metadata) key with the given value.
469 469 f.set("Key1", QVariant::fromValue<float>(1));
470 470 f.flat(); // returns "[Key1=1]"
471 471  
472   -### void set(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key, const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &value)
  472 +### void set(const [QString](http://doc.qt.io/qt-5/QString.html) &key, const [QString](http://doc.qt.io/qt-5/QString.html) &value)
473 473  
474 474 Insert or overwrite the [metadata](#m_metadata) key with the given value.
475 475  
... ... @@ -479,7 +479,7 @@ Insert or overwrite the [metadata](#m_metadata) key with the given value.
479 479 f.set("Key1", QString("1"));
480 480 f.flat(); // returns "[Key1=1]"
481 481  
482   -### void setList(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key, const <a href=>QList</a><T> &value)
  482 +### void setList(const [QString](http://doc.qt.io/qt-5/QString.html) &key, const [QList](http://doc.qt.io/qt-5/qlist.html)&lt;T&gt; &value)
483 483  
484 484 This function requires a type specification in place of T. Insert or overwrite the [metadata](#m_metadata) key with the value. The value will remain a list and should be queried with the function [getList](#qlistt-getlistconst-qstring-key-const).
485 485  
... ... @@ -489,7 +489,7 @@ This function requires a type specification in place of T. Insert or overwrite t
489 489 file.setList<float>("List", list);
490 490 file.getList<float>("List"); // return [1., 2. 3.]
491 491  
492   -### void remove(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key)
  492 +### void remove(const [QString](http://doc.qt.io/qt-5/QString.html) &key)
493 493  
494 494 Remove the key value pair associated with the given key from the [metadata](#metadata)
495 495  
... ... @@ -502,7 +502,7 @@ Remove the key value pair associated with the given key from the [metadata](#met
502 502 f.remove("Key1");
503 503 f.flat(); // returns "[Key2=2]"
504 504  
505   -### T get(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key)
  505 +### T get(const [QString](http://doc.qt.io/qt-5/QString.html) &key)
506 506  
507 507 This function requires a type specification in place of T. Try and get the value associated with the given key in the [metadata](#m_metadata). If the key does not exist or cannot be converted to the given type an error is thrown.
508 508  
... ... @@ -513,7 +513,7 @@ This function requires a type specification in place of T. Try and get the value
513 513 f.get<float>("Key2"); // Error: Key2 is not in the metadata
514 514 f.get<QRectF>("Key1"); // Error: A float can't be converted to a QRectF
515 515  
516   -### T get(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key, const T &defaultValue)
  516 +### T get(const [QString](http://doc.qt.io/qt-5/QString.html) &key, const T &defaultValue)
517 517  
518 518 This function requires a type specification in place of T. Try and get the value associated with the given key in the [metadata](#m_metadata). If the key does not exist or cannot be converted to the given type the defaultValue is returned.
519 519  
... ... @@ -524,7 +524,7 @@ This function requires a type specification in place of T. Try and get the value
524 524 f.get<float>("Key2", 5); // returns 5
525 525 f.get<QRectF>("Key1", QRectF(0, 0, 10, 10)); // returns QRectF(0, 0, 10x10)
526 526  
527   -### bool getBool(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key, bool defaultValue = false)
  527 +### bool getBool(const [QString](http://doc.qt.io/qt-5/QString.html) &key, bool defaultValue = false)
528 528  
529 529 This is a specialization of [get](#t-getconst-qstring-key) for the boolean type. If the key is not in the [metadata](#m_metadata) the defaultValue is returned. If the key is in the metadata but the value cannot be converted to a bool **true** is returned. If the key is found and the value can be converted to a bool the value is returned.
530 530  
... ... @@ -537,9 +537,9 @@ This is a specialization of [get](#t-getconst-qstring-key) for the boolean type.
537 537 f.getBool("Key3"); // returns false (default value)
538 538 f.getBool("Key3", true); // returns true (default value)
539 539  
540   -### <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;T&gt; getList(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key) const
  540 +### [QList](http://doc.qt.io/qt-5/QList.html)&lt;T&gt; getList(const [QString](http://doc.qt.io/qt-5/QString.html) &key) const
541 541  
542   -This function requires a type specification in place of T. Similar to [get](#t-getconst-qstring-key) only this returns a list. If the key is not found or the value cannot be converted into a <a href=http://doc.qt.io/qt-5/QList.html>QList</a><T> an error is thrown.
  542 +This function requires a type specification in place of T. Similar to [get](#t-getconst-qstring-key) only this returns a list. If the key is not found or the value cannot be converted into a [QList](http://doc.qt.io/qt-5/QList.html)&lt;T&gt; an error is thrown.
543 543  
544 544 File file;
545 545  
... ... @@ -550,9 +550,9 @@ This function requires a type specification in place of T. Similar to [get](#t-g
550 550 file.getList<QRectF>("List"); // Error: float cannot be converted to QRectF
551 551 file.getList<float>("Key"); // Error: key doesn't exist
552 552  
553   -### <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;T&gt; getList(const <a href=http://doc.qt.io/qt-5/QString.html>QString</a> &key, const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;T&gt; &defaultValue) const
  553 +### [QList](http://doc.qt.io/qt-5/QList.html)&lt;T&gt; getList(const [QString](http://doc.qt.io/qt-5/QString.html) &key, const [QList](http://doc.qt.io/qt-5/QList.html)&lt;T&gt; &defaultValue) const
554 554  
555   -This function requires a type specification in place of T. Similar to [get](#t-getconst-qstring-key-const-t-defaultvalue) only this returns a list. If the key is not found or the value cannot be converted into a <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;T&gt; the supplied defaultValue is returned.
  555 +This function requires a type specification in place of T. Similar to [get](#t-getconst-qstring-key-const-t-defaultvalue) only this returns a list. If the key is not found or the value cannot be converted into a [QList](http://doc.qt.io/qt-5/QList.html)&lt;T&gt; the supplied defaultValue is returned.
556 556  
557 557 File file;
558 558  
... ... @@ -563,9 +563,9 @@ This function requires a type specification in place of T. Similar to [get](#t-g
563 563 file.getList<QRectF>("List", QList<QRectF>()); // return []
564 564 file.getList<float>("Key", QList<float>() << 1 << 2 << 3); // return [1., 2., 3.]
565 565  
566   -### <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a>&gt; namedPoints() const
  566 +### [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QPointF](http://doc.qt.io/qt-4.8/qpointf.html)&gt; namedPoints() const
567 567  
568   -Find all of the points that can be parsed from [metadata](#m_metadata) keys and return them. Only values that are convertable to <a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a> are found. Values that can be converted to <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a>&gt; are not included.
  568 +Find all of the points that can be parsed from [metadata](#m_metadata) keys and return them. Only values that are convertable to [QPointF](http://doc.qt.io/qt-4.8/qpointf.html) are found. Values that can be converted to [QList](http://doc.qt.io/qt-5/QList.html)>&lt;[QPointF](http://doc.qt.io/qt-4.8/qpointf.html)&gt; are not included.
569 569  
570 570 File file;
571 571 file.set("Key1", QVariant::fromValue<QPointF>(QPointF(1, 1)));
... ... @@ -577,7 +577,7 @@ Find all of the points that can be parsed from [metadata](#m_metadata) keys and
577 577 file.setPoints(QList<QPointF>() << QPointF(3, 3)); // changes metadata["Points"] to QList<QPointF>
578 578 f.namedPoints(); // returns [QPointF(1, 1), QPointF(2, 2)]
579 579  
580   -### <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a>&gt; points() const
  580 +### [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QPointf](http://doc.qt.io/qt-4.8/qpointf.html)>&gt; points() const
581 581  
582 582 Returns the list of points stored in [metadata](#m_metadata)["Points"]. A list is expected and a single point not in a list will not be returned. Convenience functions [appendPoint](#void-appendpointconst-qpointf-point), [appendPoints](#void-appendpointsconst-qlistqpointf-points), [clearPoints](#void-clearpoints) and [setPoints](#void-setpointsconst-qlistqpointf-points) have been provided to manipulate the internal points list.
583 583  
... ... @@ -588,7 +588,7 @@ Returns the list of points stored in [metadata](#m_metadata)[&quot;Points&quot;]. A list i
588 588 file.setPoints(QList<QPointF>() << QPointF(2, 2));
589 589 file.points(); // returns [QPointF(2, 2)]
590 590  
591   -### void appendPoint(const <a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a> &point)
  591 +### void appendPoint(const [QPointF](http://doc.qt.io/qt-4.8/qpointf.html) &point)
592 592  
593 593 Add a point to the file's points list stored in [metadata](#m_metadata)["Points"]
594 594  
... ... @@ -598,7 +598,7 @@ Add a point to the file&#39;s points list stored in [metadata](#m_metadata)[&quot;Points&quot;
598 598 file.appendPoint(QPointF(1, 1));
599 599 file.points(); // returns [QPointF(1, 1)]
600 600  
601   -### void appendPoints(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a>&gt; &points)
  601 +### void appendPoints(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QPointF](http://doc.qt.io/qt-4.8/qpointf.html)&gt; &points)
602 602  
603 603 Add a list of points to the file's points list stored in [metadata](#m_metadata)["Points"]
604 604  
... ... @@ -619,7 +619,7 @@ Clear the list of points stored in [metadata](#m_metadata)[&quot;Points&quot;].
619 619 file.clearPoints();
620 620 file.points(); // returns []
621 621  
622   -### void setPoints(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qpointf.html>QPointF</a>&gt; &points)
  622 +### void setPoints(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QPointF](http://doc.qt.io/qt-4.8/qpointf.html)&gt; &points)
623 623  
624 624 Clears the points stored in [metadata](#m_metadata) and replaces them with points.
625 625  
... ... @@ -630,9 +630,9 @@ Clears the points stored in [metadata](#m_metadata) and replaces them with point
630 630 file.setPoints(QList<QPointF>() << QPointF(3, 3) << QPointF(4, 4));
631 631 file.points(); // returns [QPointF(3, 3), QPointF(4, 4)]
632 632  
633   -### <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a>&gt; namedRects() const
  633 +### [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QRectF](http://doc.qt.io/qt-4.8/qrectf.html)&gt; namedRects() const
634 634  
635   -Find all of the rects that can be parsed from [metadata](#m_metadata) keys and return them. Only values that are convertable to <a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a> are found. Values that can be converted to <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a>&gt; are not included.
  635 +Find all of the rects that can be parsed from [metadata](#m_metadata) keys and return them. Only values that are convertable to [QRectF](http://doc.qt.io/qt-4.8/qrectf.html) are found. Values that can be converted to [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QRectF](http://doc.qt.io/qt-4.8/qrectf.html)&gt; are not included.
636 636  
637 637 File file;
638 638 file.set("Key1", QVariant::fromValue<QRectF>(QRectF(1, 1, 5, 5)));
... ... @@ -644,7 +644,7 @@ Find all of the rects that can be parsed from [metadata](#m_metadata) keys and r
644 644 file.setRects(QList<QRectF>() << QRectF(3, 3, 5x5)); // changes metadata["Rects"] to QList<QRectF>
645 645 f.namedRects(); // returns [QRectF(1, 1, 5x5), QRectF(2, 2, 5x5)]
646 646  
647   -### <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a>&gt; rects() const
  647 +### [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QRectF](http://doc.qt.io/qt-4.8/qrectf.html)&gt; rects() const
648 648  
649 649 Returns the list of points stored in [metadata](#m_metadata)["Rects"]. A list is expected and a single rect not in a list will not be returned. Convenience functions [appendRect](#void-appendrectconst-qrectf-rect), [appendRects](#void-appendrectsconst-qlistqrectf-rects), [clearRects](#void-clearrects) and [setRects](#void-setrectsconst-qlistqrectf-rects) have been provided to manipulate the internal points list.
650 650  
... ... @@ -655,7 +655,7 @@ Returns the list of points stored in [metadata](#m_metadata)[&quot;Rects&quot;]. A list is
655 655 file.setRects(QList<QRectF>() << QRectF(2, 2, 5, 5));
656 656 file.rects(); // returns [QRectF(2, 2, 5x5)]
657 657  
658   -### void appendRect(const <a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a> &rect)
  658 +### void appendRect(const [QRectF](http://doc.qt.io/qt-4.8/qrectf.html) &rect)
659 659  
660 660 Add a rect to the file's rects list stored in [metadata](#m_metadata)["Rects"].
661 661  
... ... @@ -665,7 +665,7 @@ Add a rect to the file&#39;s rects list stored in [metadata](#m_metadata)[&quot;Rects&quot;].
665 665 file.appendRect(QRectF(1, 1, 5, 5));
666 666 file.rects(); // returns [QRectF(1, 1, 5x5)]
667 667  
668   -### void appendRect(const <a href=http://docs.opencv.org/modules/core/doc/basic_structures.html#rect>Rect</a> &rect)
  668 +### void appendRect(const [Rect](http://docs.opencv.org/modules/core/doc/basic_structures.html#rect) &rect)
669 669  
670 670 Add a OpenCV style rect to the file's rects list stored in [metadata](#m_metadata)["Rects"]. The rect is automatically converted to a QRectF.
671 671  
... ... @@ -675,7 +675,7 @@ Add a OpenCV style rect to the file&#39;s rects list stored in [metadata](#m_metadat
675 675 file.appendRect(cv::Rect(1, 1, 5, 5)); // automatically converted to QRectF
676 676 file.rects(); // returns [QRectF(1, 1, 5x5)]
677 677  
678   -### void appendRects(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a>&gt; &rects)
  678 +### void appendRects(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QRectF](http://doc.qt.io/qt-4.8/qrectf.html)&gt; &rects)
679 679  
680 680 Add a list of rects to the file's rects list stored in [metadata](#m_metadata)["Rects"]
681 681  
... ... @@ -685,7 +685,7 @@ Add a list of rects to the file&#39;s rects list stored in [metadata](#m_metadata)[&quot;
685 685 file.appendRects(QList<QRectF>() << QRectF(1, 1, 5, 5) << QRectF(2, 2, 5, 5));
686 686 file.rects(); // returns [QRectF(1, 1, 5x5), QRectF(2, 2, 5x5)]
687 687  
688   -### void appendRects(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://docs.opencv.org/modules/core/doc/basic_structures.html#rect>Rect</a>&gt; &rects)
  688 +### void appendRects(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;[Rect](http://docs.opencv.org/modules/core/doc/basic_structures.html#rect)&gt; &rects)
689 689  
690 690 Add a list of OpenCV style rects to the file's rects list stored in [metadata](#m_metadata)["Rects"]. Each rect is automatically converted to a QRectF.
691 691  
... ... @@ -707,7 +707,7 @@ Clear the list of rects stored in [metadata](#m_metadata)[&quot;Rects&quot;].
707 707 file.clearRects();
708 708 file.rects(); // returns []
709 709  
710   -### void setRects(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://doc.qt.io/qt-4.8/qrectf.html>QRectF</a>&gt; &rects)
  710 +### void setRects(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;[QRectF](http://doc.qt.io/qt-4.8/qrectf.html)&gt; &rects)
711 711  
712 712 Clears the rects stored in [metadata](#m_metadata)["Rects"] and replaces them with the given rects.
713 713  
... ... @@ -718,7 +718,7 @@ Clears the rects stored in [metadata](#m_metadata)[&quot;Rects&quot;] and replaces them wi
718 718 file.setRects(QList<QRectF>() << QRectF(3, 3, 5, 5) << QRectF(4, 4, 5, 5));
719 719 file.rects(); // returns [QRectF(3, 3, 5x5), QRectF(4, 4, 5x5)]
720 720  
721   -### void setRects(const <a href=http://doc.qt.io/qt-5/QList.html>QList</a>&lt;<a href=http://docs.opencv.org/modules/core/doc/basic_structures.html#rect>Rect</a>&gt; &rects)
  721 +### void setRects(const [QList](http://doc.qt.io/qt-5/QList.html)&lt;[Rect](http://docs.opencv.org/modules/core/doc/basic_structures.html#rect)&gt; &rects)
722 722  
723 723 Clears the rects stored in [metadata](#m_metadata)["Rects"] and replaces them with the given OpenCV style rects.
724 724  
... ... @@ -745,11 +745,11 @@ Default constructor. Doesn&#39;t do anything
745 745  
746 746 Initialize the [FileList](#filelist) with n empty files
747 747  
748   -### FileList(const <a href=http://doc.qt.io/qt-4.8/qstringlist.html>QStringList</a> &files)
  748 +### FileList(const [QStringList](http://doc.qt.io/qt-4.8/qstringlist.html) &files)
749 749  
750 750 Initialize the [FileList](#filelist) from a list of strings. Each string should have the format "filename[key1=value1, key2=value2, ... keyN=valueN]"
751 751  
752   -### FileList(const <a href=http://doc.qt.io/qt-4.8/qlist.html>QList</a>&lt;[File](#file)&gt; &files)
  752 +### FileList(const [QList](http://doc.qt.io/qt-4.8/qlist.html)&lt;[File](#file)&gt; &files)
753 753  
754 754 Initialize the [FileList](#filelist) from a list of [files](#file).
755 755  
... ... @@ -767,9 +767,9 @@ Creates a [FileList](#filelist) from a [Gallery](#gallery). Galleries store one
767 767  
768 768 ## Functions
769 769  
770   -### <a href=http://doc.qt.io/qt-4.8/qstringlist.html>QStringList</a> flat() const
  770 +### [QStringList](http://doc.qt.io/qt-4.8/qstringlist.html) flat() const
771 771  
772   -Calls [flat](#qstring-flat-const) on every [File](#file) in the list and returns the resulting strings as a <a href=http://doc.qt.io/qt-4.8/qstringlist.html>QStringList</a>.
  772 +Calls [flat](#qstring-flat-const) on every [File](#file) in the list and returns the resulting strings as a [QStringList](http://doc.qt.io/qt-4.8/qstringlist.html).
773 773  
774 774 File f1("picture1.jpg"), f2("picture2.jpg");
775 775 f1.set("Key", QString("Value"));
... ... @@ -777,9 +777,9 @@ Calls [flat](#qstring-flat-const) on every [File](#file) in the list and returns
777 777 FileList fList(QList<File>() << f1 << f2);
778 778 fList.flat(); // returns ["picture1.jpg[Key=Value]", "picture2.jpg"]
779 779  
780   -### <a href=http://doc.qt.io/qt-4.8/qstringlist.html>QStringList</a> names() const
  780 +### [QStringList](http://doc.qt.io/qt-4.8/qstringlist.html) names() const
781 781  
782   -Stores the name of every [file](#file) in the list and returns the resulting strings as a <a href=http://doc.qt.io/qt-4.8/qstringlist.html>QStringList</a>.
  782 +Stores the name of every [file](#file) in the list and returns the resulting strings as a [QStringList](http://doc.qt.io/qt-4.8/qstringlist.html).
783 783  
784 784 File f1("picture1.jpg"), f2("picture2.jpg");
785 785 f1.set("Key", QString("Value"));
... ... @@ -787,7 +787,7 @@ Stores the name of every [file](#file) in the list and returns the resulting str
787 787 FileList fList(QList<File>() << f1 << f2);
788 788 fList.names(); // returns ["picture1.jpg", "picture2.jpg"]
789 789  
790   -### void sort(const <a href=http://doc.qt.io/qt-4.8/qstring.html>QString</a> &key)
  790 +### void sort(const [QString](http://doc.qt.io/qt-4.8/qstring.html) &key)
791 791  
792 792 Sorts the [FileList](#filelist) based on the value associated with the given key in each file.
793 793  
... ...
docs/docs/index.md
... ... @@ -34,22 +34,23 @@ OpenBR is supported on multiple operating systems. Please select yours from the
34 34  
35 35 We have created a few tutorials to help teach you the basic principles of the OpenBR system. If this is your first time using OpenBR you should look at these before moving on to the more technical descriptions below.
36 36  
37   -* [OpenBR in 10 minutes or less!](tutorials.md#openbr in 10 minutes or less!)
38   -* [Face Recognition](tutorials.md#face recognition)
39   -* [Age Estimation](tutorials.md#age estimation)
40   -* [Gender Estimation](tutorials.md#gender estimation)
  37 +* [Quick Start](tutorials.md#quick-start)
  38 +* [Training in OpenBR](tutorials.md#training-in-openbr)
  39 +* [Face Recognition](tutorials.md#face-recognition)
  40 +* [Age Estimation](tutorials.md#age-estimation)
  41 +* [Gender Estimation](tutorials.md#gender-estimation)
41 42  
42 43 ---
43 44  
44 45 ## Additional Materials
45 46  
46   -OpenBR has several parts. For a brief overview of the entire framework please see [OpenBR in 10 minutes or less!](tutorials.md#openbr in 10 minutes or less!). Below are several more technical descriptions of important parts of the system. Enjoy!
  47 +OpenBR has several parts. Below are several more technical descriptions of important parts of the system. Enjoy!
47 48  
48   -* [Algorithms in OpenBR](technical.md#algorithms in openbr)
49   -* [The Command Line Interface](technical.md#the command line interface)
50   -* [The C API](technical.md#the c api)
51   -* [The C++ Plugin API](technical.md#the c++ plugin api)
52   -* [The Evaluation Harness](technical.md#the evaluation harness)
  49 +* [Algorithms in OpenBR](technical.md#algorithms-in-openbr)
  50 +* [The C API](docs/c_api.md)
  51 +* [The Command Line Interface](docs/cl_api.md)
  52 +* [The C++ Plugin API](docs/cpp_api.md)
  53 +* [The Evaluation Harness](technical.md#the-evaluation-harness)
53 54  
54 55 ---
55 56  
... ...
docs/docs/technical.md
... ... @@ -74,3 +74,9 @@ If you are familiar with face recognition, you will likely recognize this as the
74 74  
75 75 As a final note, the Eigenfaces algorithms uses the Euclidean distance (or L2-norm) to compare templates.
76 76 Since OpenBR expects *similarity* values when comparing templates, and not *distances*, the [DistDistance](docs/plugins/distance.md#distdistance) will return *-log(distance+1)* so that larger values indicate more similarity.
  77 +
  78 +---
  79 +
  80 +# The Evaluation Harness
  81 +
  82 +---
... ...
docs/docs/tutorials.md
... ... @@ -3,33 +3,51 @@ Welcome to OpenBR! Here we have a series of tutorials designed to get you up to
3 3  
4 4 ---
5 5  
6   -# OpenBR in 10 minutes or less!
  6 +# Quick Start
7 7  
8 8 This tutorial is meant to familiarize you with the ideas, objects and motivations behind OpenBR using some fun examples. **Note:** parts of this tutorial require a webcam.
9 9  
10   -OpenBR is a C++ library built on top of QT and OpenCV. It can either be used from the command line using the **br** application, or from interfacing with the [C API](#c-api). The command line is the easiest and fastest way to get started and this tutorial will use it for all of the examples.
  10 +OpenBR is a C++ library built on top of QT and OpenCV. It can either be used from the command line using the **br** application, or from interfacing with the [C API](docs/c_api.md). The command line is the easiest and fastest way to get started and this tutorial will use it for all of the examples.
11 11  
12   -First, make sure that OpenBR has been installed on your system using the steps described in the [installation section](#install.md). Then open up your terminal or command prompt and enter:
  12 +First, make sure that OpenBR has been installed on your system using the steps described in the [installation section](install.md). Then open up your terminal or command prompt and enter:
13 13  
14   - $ br -gui -algorithm "Open+Show(false)" -enroll 0.webcam
  14 + $ br -gui -algorithm "Show(false)" -enroll 0.webcam
15 15  
16   -If everything goes well your webcam should have opened up and is streaming. Look you are using OpenBR! Let's talk about what's happening in this command. OpenBR expects flags to be prepended by a *-* and arguments to follow the flags and be separated by spaces. Flags normally require a specific number of flags. All of the possible flags and their values are [documented here](#docs/cl_api.md). Let's step through the individual arguments and values. **-gui** is the flag that tells OpenBR to open up a GUI window. Take a look at the [GUI plugins](#docs/plugins/gui.md) for other plugins that require the **-gui** flag. **-algorithm** is one of the most important flags in OpenBR. It expects one argument called the *algorithm string*. This string determines the pipeline that images and metadata propagate through. Finally, **-enroll** reads files from disk and *enrolls* them into the image pipeline. It takes one input argument (0.webcam in our example) and an optional output argument. OpenBR has a range of formats that can be enrolled into algorithms, some examples include .jpg, .png, .csv, and .xml. .webcam tells OpenBR to enroll frames from the computers webcam.
  16 +If everything goes well your webcam should have opened up and is streaming. Look you are using OpenBR! Let's talk about what's happening in this command. OpenBR expects flags to be prepended by a *-* and arguments to follow the flags and be separated by spaces. Flags normally require a specific number of flags. All of the possible flags and their values are [documented here](docs/cl_api.md). Let's step through the individual arguments and values. **-gui** is the flag that tells OpenBR to open up a GUI window. Take a look at the [GUI plugins](docs/plugins/gui.md) for other plugins that require the **-gui** flag. **-algorithm** is one of the most important flags in OpenBR. It expects one argument called the *algorithm string*. This string determines the pipeline that images and metadata propagate through. Finally, **-enroll** reads files from disk and *enrolls* them into the image pipeline. It takes one input argument (0.webcam in our example) and an optional output argument. OpenBR has a range of formats that can be enrolled into algorithms, some examples include .jpg, .png, .csv, and .xml. .webcam tells OpenBR to enroll frames from the computers webcam.
17 17  
18   -Let's try a slightly more complicated example, after all OpenBR can do way more then just open webcams! Face detection is normally the first step in a [face recognition](#face recognition) algorithm. Let's do face detection in OpenBR. Open up the terminal again and enter:
  18 +Let's try a slightly more complicated example, after all OpenBR can do way more then just open webcams! Fire up the terminal again and enter:
19 19  
20   - $ br -gui -algorithm "Open+Cvt(Gray)+Cascade(FrontalFace)+Draw+Show(false)" -enroll 0.webcam
  20 + $ br -gui -algorithm "Cvt(Gray)+Show(false)" -enroll 0.webcam
21 21  
  22 +Hey what happened? We took our normal BGR (OpenCV's alternative to RGB) image and converted it to a grayscale image. How did we do that? Simple, by adding "Cvt(Gray)" to the algorithm string. [Cvt](docs/plugins/imgproc.md#cvttransform), short for convert, is an example of an OpenBR *plugin*. [Show](docs/plugins/gui.md#showtransform) is a plugin as well. Every algorithm string in OpenBR is just a series of plugins joined together into a pipeline. In fact the **+** symbol is shorthand for a [Pipe](docs/plugins/core.md#pipetransform), another kind of OpenBR plugin. We specify **Gray** to [Cvt](docs/plugins/imgproc.md#cvttransform) as a runtime parameter to tell the plugin which color space to convert the image to. We also could have written **Cvt(HSV)** if we wanted to convert to the HSV color space or **Cvt(Luv)** if we wanted to convert to Luv. The arguments inside of the plugins are runtime parameters that can adjust the functionality. They can be provided as key-value pairs, **Cvt(Gray)** is equivalent to **Cvt(ColorSpace=Gray)**, or as keyless values. Make sure you are supplying parameters in the proper order if you are not using keys! Try and run the code with **Show(true)** and see how changing the parameters effect the output of the command (**Hint:** hit a key to cycle through the images).
22 23  
23   -It was built primarily as a platform for [face recognition](#face recognition) but has grown to do other things like [age recognition](#age recognition) and [gender recognition](#gender recognition). The different functionalities of OpenBR are specified by algorithms which are passed in as strings. The algorithm to do face recognition is
  24 +Let's make this example a little bit more exciting and relevant to OpenBR's biometric roots. Face detection is normally the first step in a [face recognition](#face-recognition) algorithm. Let's do face detection in OpenBR. Back in the terminal enter:
24 25  
25   - $ Open+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+Affine(88,88,0.25,0.35)+<Mask+DenseSIFT/DenseLBP+DownsampleTraining(PCA(0.95),instances=1)+Normalize(L2)+Cat>+<Dup(12)+RndSubspace(0.05,1)+DownsampleTraining(LDA(0.98),instances=-2)+Cat+DownsampleTraining(PCA(768),instances=1)>+<Normalize(L1)+Quantize)>+SetMetadata(AlgorithmID,-1):Unit(ByteL1)
  26 + $ br -gui -algorithm "Cvt(Gray)+Cascade(FrontalFace)+Draw(lineThickness=3)+Show(false)" -enroll 0.webcam
26 27  
27   -Woah, that's a lot! Face recognition is a pretty complicated process! We will break this whole string down in just a second, but first we can showcase one of the founding principles of OpenBR. In the face recognition algorithm there are a series of steps separated by +'s (and a few other symbols but they will all be explained); these steps are called plugins and they are the building blocks of all OpenBR algorithms. Each plugin is completely independent of all of the other plugins around it and each one can be swapped, inserted or removed at any time to form new algorithms. This makes it really easy to test new ideas as you come up with them!
  28 +You're webcam should be open again but this time a box should have appeared around your face! We added two new plugins to our string, [Cascade](docs/plugins/metadata.md#cascadetransform) and [Draw](docs/plugins/gui.md#drawtransform). Let's walk through this plugin by plugin and see how it works:
28 29  
29   -So, now lets talk about the basics of algorithms in OpenBR. We know that algorithms are just a series of plugins joined together using the + symbol. What about the : symbol right at the end of the algorithm however? :'s separate the processing part of the algorithm (also called enrollment or generation), from the evaluation part. OpenBR actually has different types of plugins to handle each part. Plugins to the left are called [transforms](docs/cpp_api.md#transform) and plugins to the right are called [distances](docs/cpp_api.md#distance). Transforms operate on the images as they pass through the algorithm and distances compare (or find the distance between) the images as they finish, usually constructing a similarity matrix in the process.
  30 +1. [Cvt(Gray)](docs/plugins/imgproc.md#cvttransform): Convert the image from BGR to grayscale. Grayscale is required for [Cascade](docs/plugins/metadata.md#cascadetransform) to work properly.
  31 +2. [Cascade(FrontalFace)](docs/plugins/metadata.md#cascadetransform): This is a wrapper on the OpenCV [Cascade Classification](http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html) framework. It detects frontal faces using the **FrontalFace** model.
  32 +3. [Draw(lineThickness=3)](docs/plugins/gui.md#drawtransform): Take the rects detected by [Cascade](docs/plugins/metadata.md#cascadetransform) and draw them onto the frame from the webcam. **lineThickness** determines the thickness of the drawn rect.
  33 +4. [Show(false)](docs/plugins/gui.md#showtransform): Show the image in a GUI window. **false** indicates the images should be shown in succession without waiting for a key press.
30 34  
31   -This leads us on a small tangent to discuss how images are handled in OpenBR. OpenBR has two structures dedicated to handling data as it passes through an algorithm, [Files](docs/cpp_api.md#file) and [Templates](docs/cpp_api.md#template). Files handle metadata, the text and other information that can be associated with an image, and templates act as a container for images (we use OpenCV mats) and files. These templates are passed from transform to transform through the algorithm and are *transformed* (see, the name makes sense!) as they go.
  35 +Pretty straightforward right? Each plugin completes one task and the passes the output on to the next plugin. You can pipe together as many plugins as you like as long as the output data from one can be the input data to the next. But wait! Output data? Input data? we haven't talked about data at all yet! How does OpenBR handle data? There are two objects that handle data is OpenBR; [Files](docs/cpp_api.md#file), which handle metadata, and [Templates](docs/cpp_api.md#template) which are containers for images and [Files](docs/cpp_api.md#file). Let's talk about [Files](docs/cpp_api.md#file) first. A file consists of file name, which is a path to a file on disk, and metadata which is a map of key-value pairs. The metadata can contain any textual information about the file. In the example above we use it to store the rectangles detected by [Cascade](docs/plugins/metadata.md#cascadetransform) and pass them along to [Draw](docs/plugins/metadata.md#drawtransform) for drawing. [Templates](docs/cpp_api.md#template) are containers for images, given as OpenCV [Mats](http://docs.opencv.org/modules/core/doc/basic_structures.html#mat), and [Files](docs/cpp_api.md#file). They can contain one image or a list of images. Plugins are either [Template](#docs/cpp_api.md#template) in, [Template](docs/cpp_api.md#template) out or [TemplateList](docs/cpp_api.md#templatelist) in, [TemplateList](docs/cpp_api.md#templatelist) out. [TemplateLists](docs/cpp_api.md#templatelist) are, of course, just a list of [Templates](docs/cpp_api.md#template) which a few functions added for your convenience.
32 36  
33   -Great, you now know how data is handled in OpenBR but we still have a lot to cover in that algorithm string! Next lets talk about all of the parentheses next to each plugin. Many plugins have parameters that can be set at runtime. For example, [Cvt](docs/plugins/imgproc.md#cvttransform) (short for convert) changes the colorspace of an image. For face recognition we want to change it to gray so we pass in Gray as the parameter to Cvt. Pretty simple right? Parameters can either be passed in in the order they appear in the code, or they can use a key-value pairing. Cvt(Gray) is equivalent to Cvt(ColorSpace=Gray), check out the docs for the properties of each plugin.
  37 +And there you go! You have gotten your quick start in OpenBR. We covered the [command line](docs/cl_api.md), plugins, and the key [data structures](docs/cpp_api.md) in OpenBR. If you want to learn more the next few tutorials will cover these fields with more depth. For even more information check out the technical overviews (#techical.md) and class documentation!
34 38  
35   -The last symbol we need to cover is <>. In OpenBR <> represents i/o. Transforms within these brackets will try and load their parameters from the hard drive if they can (they also still take parameters from the command line as you can see). Plugin i/o won't be covered here because it isn't critically important to making OpenBR work for you out of the gate. Stay tuned for a later tutorial on this.
  39 +---
  40 +
  41 +# Training in OpenBR
  42 +
  43 +---
  44 +
  45 +# Face Recognition
  46 +
  47 +---
  48 +
  49 +# Age Estimation
  50 +
  51 +---
  52 +
  53 +# Gender Estimation
... ...