diff --git a/.gitignore b/.gitignore index 6baacca..de489d6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ 3rdparty/LatentSDK* 3rdparty/pittpatt* data/*/img +data/*/vid data/PCSO/* build* scripts/results diff --git a/app/br/br.cpp b/app/br/br.cpp index 7528393..8615274 100644 --- a/app/br/br.cpp +++ b/app/br/br.cpp @@ -135,11 +135,14 @@ public: check(parc == 2, "Incorrect parameter count for 'evalClustering'."); br_eval_clustering(parv[0], parv[1]); } else if (!strcmp(fun, "evalDetection")) { - check(parc == 2, "Incorrect parameter count for 'evalDetection'."); - br_eval_detection(parv[0], parv[1]); + check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'evalDetection'."); + br_eval_detection(parv[0], parv[1], parc == 3 ? parv[2] : ""); } else if (!strcmp(fun, "evalRegression")) { check(parc == 2, "Incorrect parameter count for 'evalRegression'."); br_eval_regression(parv[0], parv[1]); + } else if (!strcmp(fun, "plotDetection")) { + check(parc >= 2, "Incorrect parameter count for 'plotDetection'."); + br_plot_detection(parc-1, parv, parv[parc-1], true); } else if (!strcmp(fun, "plotMetadata")) { check(parc >= 2, "Incorrect parameter count for 'plotMetadata'."); br_plot_metadata(parc-1, parv, parv[parc-1], true); @@ -214,8 +217,9 @@ private: "-convert (Format|Gallery|Output) {output_file}\n" "-evalClassification \n" "-evalClustering \n" - "-evalDetection \n" + "-evalDetection [{csv}]\n" "-evalRegression \n" + "-plotDetection ... {destination}\n" "-plotMetadata ... \n" "-getHeader \n" "-setHeader {} \n" diff --git a/openbr/core/eval.cpp b/openbr/core/eval.cpp index 2f13e66..8f3e419 100644 --- a/openbr/core/eval.cpp +++ b/openbr/core/eval.cpp @@ -23,6 +23,8 @@ using namespace cv; namespace br { +static const int Max_Points = 500; // Maximum number of points to render on plots + struct Comparison { float score; @@ -100,7 +102,6 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv) qFatal("Similarity matrix (%ix%i) differs in size from mask matrix (%ix%i).", simmat.rows, simmat.cols, mask.rows, mask.cols); - const int Max_Points = 500; float result = -1; // Make comparisons @@ -237,7 +238,7 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv) if (i == Report_Retrieval) reportRetrievalRate = retrievalRate; } - if (!csv.isEmpty()) QtUtils::writeFile(csv, lines); + QtUtils::writeFile(csv, lines); qDebug("TAR @ FAR = 0.01: %.3f\nRetrieval Rate @ Rank = %d: %.3f", result, Report_Retrieval, reportRetrievalRate); return result; } @@ -325,7 +326,7 @@ struct Detection float overlap(const Detection &other) const { const Detection intersection(boundingBox.intersected(other.boundingBox)); - return intersection.area() / (area() + other.area() - 2*intersection.area()); + return intersection.area() / (area() + other.area() - intersection.area()); } }; @@ -334,14 +335,53 @@ struct Detections QList predicted, truth; }; -struct DetectionOperatingPoint +struct ResolvedDetection { float confidence, overlap; - DetectionOperatingPoint() : confidence(-1), overlap(-1) {} - DetectionOperatingPoint(float confidence_, float overlap_) : confidence(confidence_), overlap(overlap_) {} - inline bool operator<(const DetectionOperatingPoint &other) const { return confidence > other.confidence; } + ResolvedDetection() : confidence(-1), overlap(-1) {} + ResolvedDetection(float confidence_, float overlap_) : confidence(confidence_), overlap(overlap_) {} + inline bool operator<(const ResolvedDetection &other) const { return confidence > other.confidence; } +}; + +struct DetectionOperatingPoint +{ + float Recall, FalsePositives, Precision; + DetectionOperatingPoint() : Recall(-1), FalsePositives(-1), Precision(-1) {} + DetectionOperatingPoint(float TP, float FP, float totalPositives) + : Recall(TP/totalPositives), FalsePositives(FP), Precision(TP/(TP+FP)) {} }; +static QStringList computeDetectionResults(const QList &detections, int totalPositives, bool discrete) +{ + QList points; + float TP = 0, FP = 0, prevFP = 0; + for (int i=0; i= 0.5) TP++; + else FP++; + } else { + TP += detection.overlap; + FP += 1 - detection.overlap; + } + if ((i == detections.size()-1) || (detection.confidence > detections[i+1].confidence)) { + if (FP > prevFP) { + points.append(DetectionOperatingPoint(TP, FP, totalPositives)); + prevFP = FP; + } + } + } + + const int keep = qMin(points.size(), Max_Points); + QStringList lines; lines.reserve(keep); + for (int i=0; i allDetections; // Organized by file + QMap allDetections; // Organized by file, QMap used to preserve order foreach (const Template &t, predicted) allDetections[t.file.baseName()].predicted.append(Detection(t.file.get(detectKey), t.file.get("Confidence", -1))); foreach (const Template &t, truth) allDetections[t.file.baseName()].truth.append(Detection(t.file.get(detectKey))); - QList points; + QList resolvedDetections, falseNegativeDetections; foreach (Detections detections, allDetections.values()) { while (!detections.truth.isEmpty() && !detections.predicted.isEmpty()) { - Detection truth = detections.truth.takeFirst(); + const Detection truth = detections.truth.takeFirst(); int bestIndex = -1; - float bestOverlap = -1; + float bestOverlap = -std::numeric_limits::max(); for (int i=0; i bestOverlap) { @@ -377,25 +417,40 @@ float EvalDetection(const QString &predictedInput, const QString &truthInput, co bestIndex = i; } } - Detection predicted = detections.predicted.takeAt(bestIndex); - points.append(DetectionOperatingPoint(predicted.confidence, bestOverlap)); + const Detection predicted = detections.predicted.takeAt(bestIndex); + resolvedDetections.append(ResolvedDetection(predicted.confidence, bestOverlap)); } foreach (const Detection &detection, detections.predicted) - points.append(DetectionOperatingPoint(detection.confidence, 0)); + resolvedDetections.append(ResolvedDetection(detection.confidence, 0)); for (int i=0; i::max(), 0)); + falseNegativeDetections.append(ResolvedDetection(-std::numeric_limits::max(), 0)); } - std::sort(points.begin(), points.end()); + std::sort(resolvedDetections.begin(), resolvedDetections.end()); QStringList lines; lines.append("Plot, X, Y"); + lines.append(computeDetectionResults(resolvedDetections, truth.size(), true)); + lines.append(computeDetectionResults(resolvedDetections, truth.size(), false)); + + float averageOverlap; + { // Overlap Density + QList allDetections; allDetections << resolvedDetections << falseNegativeDetections; + const int keep = qMin(allDetections.size(), Max_Points); + lines.reserve(lines.size() + keep); + float totalOverlap = 0; + for (int i=0; i.csv files. + * \brief Renders recognition performance figures for a set of .csv files created by \ref br_eval. * * In order of their output, the figures are: * -# Metadata table @@ -263,11 +262,17 @@ BR_EXPORT const char *br_objects(const char *abstractions = ".*", const char *im * \return Returns \c true on success. Returns false on a failure to compile the figures due to a missing, out of date, or incomplete \c R installation. * \note This function requires a current R installation with the following packages: * \code install.packages(c("ggplot2", "gplots", "reshape", "scales")) \endcode - * \see br_plot_metadata + * \see br_eval */ BR_EXPORT bool br_plot(int num_files, const char *files[], const char *destination, bool show = false); /*! + * \brief Renders detection performance figures for a set of .csv files created by \ref br_eval_detection. + * \see br_plot + */ +BR_EXPORT bool br_plot_detection(int num_files, const char *files[], const char *destination, bool show = false); + +/*! * \brief Renders metadata figures for a set of .csv files with specified columns. * * Several files will be created: diff --git a/openbr/openbr_export.cpp b/openbr/openbr_export.cpp index 8c26a90..0eccdb5 100644 --- a/openbr/openbr_export.cpp +++ b/openbr/openbr_export.cpp @@ -17,7 +17,7 @@ /*! * \mainpage * \section overview Overview - * OpenBR \cite openbr is a framework for investigating new modalities, improving existing algorithms, interfacing with commercial systems, measuring recognition performance, and deploying automated biometric systems. + * OpenBR \cite klontz2013open is a framework for investigating new modalities, improving existing algorithms, interfacing with commercial systems, measuring recognition performance, and deploying automated biometric systems. * The project is designed to facilitate rapid algorithm prototyping, and features a mature core framework, flexible plugin system, and support for open and closed source development. * Off-the-shelf algorithms are also available for specific modalities including \ref cpp_face_recognition, \ref cpp_age_estimation, and \ref cpp_gender_estimation. * @@ -27,14 +27,24 @@ * \image html "abstraction.svg" "The two principal software artifacts are the shared library 'openbr' and command line application 'br'." * * \section get_started Get Started - * - \ref installation - \copybrief installation - * - \ref qmake_integration - \copybrief qmake_integration + * - \ref introduction - A high-level technical overview of OpenBR. + * - \ref installation - A hacker's guide to building, editing, and running OpenBR. + * - \ref qmake_integration - Add OpenBR to your Qt .pro project. * * \section learn_more Learn More - * - \ref algorithm_grammar - \copybrief algorithm_grammar - * - \ref cli - \copybrief cli - * - \ref c_sdk - \copybrief c_sdk - * - \ref cpp_plugin_sdk - \copybrief cpp_plugin_sdk + * - \ref algorithm_grammar - How algorithms are constructed from string descriptions. + * - \ref cli - Command line wrapper of the \ref c_sdk. + * - \ref c_sdk - High-level API for running algorithms and evaluating results. + * - \ref cpp_plugin_sdk - Plugin API for extending OpenBR functionality. + * - \ref bee - A NIST standard for evaluating biometric algorithms. + */ + +/*! + * \page introduction Introduction + * \brief A high-level technical overview of OpenBR. + * + * We strongly encourage users new to OpenBR to read our publication for an introduction to the core concepts. + * Researchers incorporating OpenBR into their own work are kindly requested to cite this paper. */ /*! diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index 3a8aa85..4ae25a7 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -354,7 +354,7 @@ struct Template : public QList inline const cv::Mat &m() const { static const cv::Mat NullMatrix; return isEmpty() ? qFatal("Empty template."), NullMatrix : last(); } /*!< \brief Idiom to treat the template as a matrix. */ inline cv::Mat &m() { return isEmpty() ? append(cv::Mat()), last() : last(); } /*!< \brief Idiom to treat the template as a matrix. */ - inline const File &operator()() const { return file; } + inline operator const File &() const { return file; } inline cv::Mat &operator=(const cv::Mat &other) { return m() = other; } /*!< \brief Idiom to treat the template as a matrix. */ inline operator const cv::Mat&() const { return m(); } /*!< \brief Idiom to treat the template as a matrix. */ inline operator cv::Mat&() { return m(); } /*!< \brief Idiom to treat the template as a matrix. */ diff --git a/openbr/plugins/frames.cpp b/openbr/plugins/frames.cpp new file mode 100644 index 0000000..5076846 --- /dev/null +++ b/openbr/plugins/frames.cpp @@ -0,0 +1,49 @@ +#include "openbr_internal.h" + +namespace br +{ + +/*! + * \ingroup transforms + * \brief Passes along n sequential frames to the next transform. + * \author Josh Klontz \cite jklontz + * + * For a video with m frames, AggregateFrames would create a total of m-n+1 sequences ([0,n] ... [m-n+1, m]). + */ +class AggregateFrames : public TimeVaryingTransform +{ + Q_OBJECT + Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false) + BR_PROPERTY(int, n, 1) + + TemplateList buffer; + + void train(const TemplateList &data) + { + (void) data; + } + + void projectUpdate(const Template &src, Template &dst) + { + buffer.append(src); + if (buffer.size() < n) return; + foreach (const Template &t, buffer) dst.append(t); + dst.file = buffer.takeFirst().file; + } + + void store(QDataStream &stream) const + { + (void) stream; + } + + void load(QDataStream &stream) + { + (void) stream; + } +}; + +BR_REGISTER(Transform, AggregateFrames) + +} // namespace br + +#include "frames.moc" diff --git a/openbr/plugins/gallery.cpp b/openbr/plugins/gallery.cpp index 03e45ab..7bb77ef 100644 --- a/openbr/plugins/gallery.cpp +++ b/openbr/plugins/gallery.cpp @@ -269,67 +269,6 @@ class matrixGallery : public Gallery BR_REGISTER(Gallery, matrixGallery) /*! - * \ingroup galleries - * \brief Treat a video as a gallery, making a single template from each frame - * \author Charles Otto \cite caotto - */ -class aviGallery : public Gallery -{ - Q_OBJECT - - TemplateList output_set; - QScopedPointer videoOut; - - ~aviGallery() - { - if (videoOut && videoOut->isOpened()) videoOut->release(); - } - - TemplateList readBlock(bool * done) - { - std::string fname = file.name.toStdString(); - *done = true; - - TemplateList output; - if (!file.exists()) - return output; - - cv::VideoCapture videoReader(file.name.toStdString()); - - bool open = videoReader.isOpened(); - - while (open) { - cv::Mat frame; - - open = videoReader.read(frame); - if (!open) break; - output.append(Template()); - output.back() = frame.clone(); - } - - return TemplateList(); - } - - void write(const Template & t) - { - if (videoOut.isNull() || !videoOut->isOpened()) { - int fourcc = OpenCVUtils::getFourcc(); - videoOut.reset(new cv::VideoWriter(qPrintable(file.name), fourcc, 30, t.m().size())); - } - - if (!videoOut->isOpened()) { - qWarning("Failed to open %s for writing\n", qPrintable(file.name)); - return; - } - - foreach(const cv::Mat & m, t) { - videoOut->write(m); - } - } -}; -BR_REGISTER(Gallery, aviGallery) - -/*! * \ingroup initializers * \brief Initialization support for memGallery. * \author Josh Klontz \cite jklontz diff --git a/openbr/plugins/stream.cpp b/openbr/plugins/stream.cpp index 5470f51..884176a 100644 --- a/openbr/plugins/stream.cpp +++ b/openbr/plugins/stream.cpp @@ -284,8 +284,11 @@ public: { qDebug("Video not open!"); } + } else { + // Yes, we should specify absolute path: + // http://stackoverflow.com/questions/9396459/loading-a-video-in-opencv-in-python + video.open(QFileInfo(input.file.name).absoluteFilePath().toStdString()); } - else video.open(input.file.name.toStdString()); return video.isOpened(); } diff --git a/scripts/downloadDatasets.sh b/scripts/downloadDatasets.sh index 62020ab..f966994 100755 --- a/scripts/downloadDatasets.sh +++ b/scripts/downloadDatasets.sh @@ -63,4 +63,6 @@ if [ ! -d ../data/KTH/vid ]; then unzip ${vidclass}.zip -d ../data/KTH/vid/${vidclass} rm ${vidclass}.zip done + # this file is corrupted + rm ../data/KTH/vid/boxing/person01_boxing_d4_uncomp.avi fi diff --git a/share/openbr/Doxyfile.in b/share/openbr/Doxyfile.in index 26151d7..4d0b7d2 100644 --- a/share/openbr/Doxyfile.in +++ b/share/openbr/Doxyfile.in @@ -1,8 +1,10 @@ -# Doxyfile 1.8.2 +# Doxyfile 1.8.4 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # +# All text after a double hash (##) is considered a comment and is placed +# in front of the TAG it is preceding . # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] @@ -70,9 +72,9 @@ CREATE_SUBDIRS = NO # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, +# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, +# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English @@ -252,10 +254,10 @@ EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES -# When enabled doxygen tries to link words that correspond to documented classes, -# or namespaces to their corresponding documentation. Such a link can be -# prevented in individual cases by by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. AUTOLINK_SUPPORT = YES @@ -279,7 +281,12 @@ CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO. +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES @@ -306,11 +313,11 @@ SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). +# unions with only public data fields or simple typedef fields will be shown +# inline in the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO (the default), structs, classes, and unions are shown on a separate +# page (for HTML and Man pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO @@ -324,30 +331,14 @@ INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can +# be an expensive process and often the same symbol appear multiple times in +# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too +# small doxygen will become slower. If the cache is too large, memory is wasted. +# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid +# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 +# symbols. LOOKUP_CACHE_SIZE = 0 @@ -358,7 +349,7 @@ LOOKUP_CACHE_SIZE = 0 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES @@ -539,7 +530,8 @@ GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = @@ -597,7 +589,8 @@ LAYOUT_FILE = # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = ${BR_SHARE_DIR}/openbr.bib @@ -680,7 +673,8 @@ INPUT_ENCODING = UTF-8 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl -FILE_PATTERNS = *.h *.cpp +FILE_PATTERNS = *.h \ + *.cpp # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. @@ -763,8 +757,10 @@ IMAGE_PATH = ${CMAKE_SOURCE_DIR}/share/openbr # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. +# If FILTER_PATTERNS is specified, this tag will be ignored. +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. INPUT_FILTER = @@ -793,6 +789,13 @@ FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- @@ -934,7 +937,7 @@ HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. @@ -1202,6 +1205,13 @@ FORMULA_TRANSPARENT = YES USE_MATHJAX = NO +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT = HTML-CSS + # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax @@ -1219,6 +1229,11 @@ MATHJAX_RELPATH = http://www.mathjax.org/mathjax MATHJAX_EXTENSIONS = +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript +# pieces of code that will be used on startup of the MathJax code. + +MATHJAX_CODEFILE = + # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using @@ -1230,15 +1245,55 @@ MATHJAX_EXTENSIONS = SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. SERVER_BASED_SEARCH = NO +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search +# engine library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id +# of to a relative location where the documentation can be found. +# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... + +EXTRA_SEARCH_MAPPINGS = + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- @@ -1276,7 +1331,7 @@ COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and -# executive. If left blank a4wide will be used. +# executive. If left blank a4 will be used. PAPER_TYPE = a4 @@ -1299,6 +1354,13 @@ LATEX_HEADER = LATEX_FOOTER = +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images +# or other source files which should be copied to the LaTeX output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. + +LATEX_EXTRA_FILES = + # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references @@ -1444,6 +1506,21 @@ XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- +# configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files +# that can be used to generate PDF. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. If left blank docbook will be used as the default path. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- @@ -1539,7 +1616,8 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = BR_EXPORT= __cplusplus +PREDEFINED = BR_EXPORT= \ + __cplusplus # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. @@ -1592,6 +1670,12 @@ ALLEXTERNALS = NO EXTERNAL_GROUPS = YES +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed +# in the related pages index. If set to NO, only the current project's +# pages will be listed. + +EXTERNAL_PAGES = YES + # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). @@ -1688,7 +1772,7 @@ UML_LOOK = NO # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more -# managable. Set this to 0 for no limit. Note that the threshold may be +# manageable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 diff --git a/share/openbr/openbr.bib b/share/openbr/openbr.bib index ea27eb9..b07abd7 100644 --- a/share/openbr/openbr.bib +++ b/share/openbr/openbr.bib @@ -30,16 +30,11 @@ Title = {ottochar at gmail.com}} @misc{lbestrowden, - Author = {Lacey S. Best-Rowden}, + Author = {{Lacey S. Best-Rowden}}, Howpublished = {https://github.com/lbestrowden}, Title = {bestrow1 at msu.edu}} % Software -@misc{OpenBR, - Author = {Joshua C. Klontz and Dr. Mark J. Burge}, - Title = {{OpenBR} - {Open} {Biometric} {Recognition}}, - Year = {2012}} - @misc{libface, Howpublished = {http://libface.sourceforge.net/file/Home.html}, Title = {libface}, @@ -227,6 +222,14 @@ pages={1--8}, } +@inproceedings{klontz2013open, + title={{Open Source Biometric Recognition}}, + author={Klontz et al.}, + booktitle={Biometrics: Theory, Applications and Systems (BTAS), 2013 IEEE Sixth International Conference on}, + year={2013}, + organization={IEEE} +} + @inproceedings{li2009hfb, title={The {HFB} face database for heterogeneous face biometrics research}, author={Li, Stan Z and Lei, Zhen and Ao, Meng},