Commit 71a036f54767b094aeed26e542d07ba5206c6209

Authored by Charles Otto
2 parents 72a5968a 7dd634b3

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

openbr/core/common.h
... ... @@ -153,11 +153,10 @@ void MeanStdDev(const V<T> &vals, double *mean, double *stddev)
153 153 template<template<typename> class C, typename T>
154 154 T Median(C<T> vals, T *q1 = 0, T *q3 = 0)
155 155 {
156   - if (vals.isEmpty()) return std::numeric_limits<float>::quiet_NaN();
157 156 qSort(vals);
158   - if (q1 != 0) *q1 = vals[1*vals.size()/4];
159   - if (q3 != 0) *q3 = vals[3*vals.size()/4];
160   - return vals[vals.size()/2];
  157 + if (q1 != 0) *q1 = vals.isEmpty() ? 0 : vals[1*vals.size()/4];
  158 + if (q3 != 0) *q3 = vals.isEmpty() ? 0 : vals[3*vals.size()/4];
  159 + return vals.isEmpty() ? 0 : vals[vals.size()/2];
161 160 }
162 161  
163 162 /*!
... ...
openbr/core/fuse.cpp
... ... @@ -14,7 +14,6 @@
14 14 * limitations under the License. *
15 15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 16  
17   -#include <QFile>
18 17 #include <QList>
19 18 #include <QStringList>
20 19 #include <limits>
... ...
openbr/gui/imageviewer.cpp
... ... @@ -36,7 +36,8 @@ void br::ImageViewer::setDefaultText(const QString &amp;text)
36 36  
37 37 void br::ImageViewer::setImage(const QString &file, bool async)
38 38 {
39   - src = QImage(file);
  39 + if(file.isNull()) src = QImage(); // Gets rid of runtime FileEngine::open warning
  40 + else src = QImage(file);
40 41 updatePixmap(async);
41 42 }
42 43  
... ...
openbr/openbr_export.cpp
... ... @@ -24,7 +24,7 @@
24 24 * OpenBR originated within The MITRE Corporation from a need to streamline the process of prototyping new algorithms.
25 25 * The project was later published as open source software under the <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache 2</a> license and is <i>free for academic and commercial use</i>.
26 26 *
27   - * \image html "share/openbr/abstraction.svg" "The two principal software artifacts are the shared library 'openbr' and command line application 'br'."
  27 + * \image html "abstraction.svg" "The two principal software artifacts are the shared library 'openbr' and command line application 'br'."
28 28 *
29 29 * \section get_started Get Started
30 30 * - \ref installation - \copybrief installation
... ... @@ -70,13 +70,13 @@ $ export DYLD_FRAMEWORK_PATH=../lib:${DYLD_FRAMEWORK_PATH}
70 70 * No configuration is necessary!
71 71 *
72 72 * \section installation_license_dongle License Dongle
73   - * If you were given a USB License Dongle, then dongle must be in the computer in order to use the SDK.
  73 + * 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.
74 74 * No configuration of the dongle is needed.
75 75 *
76 76 * \section installation_done Start Working
77 77 * To test for successful installation:
78 78 \verbatim
79   -$ cd bin/
  79 +$ cd bin
80 80 $ br -help
81 81 \endverbatim
82 82 */
... ... @@ -180,7 +180,7 @@ $ br -help
180 180 * $ cmake -G "MinGW Makefiles" -DBUILD_opencv_java=OFF -DBUILD_opencv_world=ON -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DWITH_FFMPEG=OFF -DCMAKE_BUILD_TYPE=Debug ..
181 181 * $ mingw32-make
182 182 * $ mingw32-make install
183   - * $ cmake -DCMAKE_BUILD_TYPE=Release
  183 + * $ cmake -DCMAKE_BUILD_TYPE=Release ..
184 184 * $ mingw32-make
185 185 * $ mingw32-make install
186 186 * $ mingw32-make clean
... ... @@ -244,7 +244,7 @@ $ br -help
244 244 /*!
245 245 * \page osx_clang OS X Mountain Lion - Clang/LLVM 3.1 - x64
246 246 * -# Download and install the latest "Xcode" and "Command Line Tools" from the <a href="https://developer.apple.com/downloads/index.action#">Apple Developer Downloads</a> page.
247   - * -# <a href="http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz">Download CMake 2.8.10.2</a>.
  247 + * -# <a href="http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz">Download CMake 2.8.10.2</a>
248 248 * \code
249 249 * $ cd ~/Downloads
250 250 * $ tar -xf cmake-2.8.10.2.tar.gz
... ... @@ -253,22 +253,22 @@ $ br -help
253 253 * $ make -j4
254 254 * $ sudo make install
255 255 * $ cd ..
256   - * $ rm -r cmake-2.8.10.2
  256 + * $ rm -rf cmake-2.8.10.2*
257 257 * \endcode
258   - * -# <a href="http://downloads.sourceforge.net/project/opencvlibrary/opencv-unix/2.4.4/OpenCV-2.4.4.tar.bz2">Download OpenCV 2.4.4</a>.
  258 + * -# <a href="http://downloads.sourceforge.net/project/opencvlibrary/opencv-unix/2.4.5/opencv-2.4.5.tar.gz">Download OpenCV 2.4.5</a>
259 259 * \code
260 260 * $ cd ~/Downloads
261   - * $ tar -xf OpenCV-2.4.4.tar.bz2
262   - * $ cd OpenCV-2.4.4
  261 + * $ tar -xf opencv-2.4.5.tar.gz
  262 + * $ cd opencv-2.4.5
263 263 * $ mkdir build
264 264 * $ cd build
265   - * $ cmake -DBUILD_opencv_java=OFF -DBUILD_opencv_world=OFF -DCMAKE_BUILD_TYPE=Release ..
  265 + * $ cmake -DCMAKE_BUILD_TYPE=Release ..
266 266 * $ make -j4
267 267 * $ sudo make install
268 268 * $ cd ../..
269   - * $ rm -r OpenCV-2.4.4
  269 + * $ rm -rf opencv-2.4.5*
270 270 * \endcode
271   - * -# <a href="http://releases.qt-project.org/qt5/5.0.1/qt-mac-opensource-5.0.1-clang-offline.dmg">Download Qt 5.0.1</a> and install.
  271 + * -# <a href="http://download.qt-project.org/official_releases/qt/5.0/5.0.2/qt-mac-opensource-5.0.2-clang-offline.dmg">Download and install Qt 5.0.2</a>
272 272 * -# Create a <a href="github.com">GitHub</a> account, follow their instructions for <a href="https://help.github.com/articles/set-up-git">setting up Git</a>.
273 273 * \code
274 274 * $ git clone https://github.com/biometrics/openbr.git
... ... @@ -281,27 +281,34 @@ $ br -help
281 281 * $ cd openbr
282 282 * $ mkdir build
283 283 * $ cd build
284   - * $ cmake -DCMAKE_PREFIX_PATH=~/Qt5.0.1/5.0.1/clang_64 -DCMAKE_BUILD_TYPE=Release ..
  284 + * $ cmake -DCMAKE_PREFIX_PATH=~/Qt5.0.2/5.0.2/clang_64 -DCMAKE_BUILD_TYPE=Release ..
285 285 * $ make -j4
286 286 * $ sudo make install
287 287 * \endcode
288 288 * -# Hack OpenBR!
289 289 * -# Open Qt Creator IDE
290 290 * \code
291   - * $ open ~/Qt5.0.1/Qt\ Creator.app
  291 + * $ open ~/Qt5.0.2/Qt\ Creator.app
292 292 * \endcode
293 293 * -# From the Qt Creator "File" menu select "Open File or Project...".
294   - * -# Select "~/openbr/CMakeLists.txt" then "Open".
295   - * -# Browse to your prexisting build directory "~/openbr/build" then select "Continue".
  294 + * -# Select "openbr/CMakeLists.txt" then "Open".
  295 + * -# Browse to your prexisting build directory "openbr/build" then select "Continue".
296 296 * -# Select "Run CMake" then "Done".
297 297 * -# You're all set! You can find more information on Qt Creator <a href="http://qt-project.org/doc/qtcreator">here</a> if you need.
  298 + * -# (Optional) Test OpenBR!
  299 + * \code
  300 + * $ cd openbr/scripts
  301 + * $ ./downloadDatasets.sh
  302 + * $ cd ../build
  303 + * $ make test
  304 + * \endcode
298 305 * -# (Optional) Package OpenBR!
299 306 * \code
300 307 * $ cd openbr/build
301   - * $ make package
  308 + * $ cpack -G TGZ
302 309 * \endcode
303 310 * -# (Optional) Build OpenBR documentation!
304   - * -# <a href="ftp://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.2.src.tar.gz">Download Doxygen 1.8.2</a> and install:
  311 + * -# <a href="ftp://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.2.src.tar.gz">Download Doxygen 1.8.2</a>
305 312 * \code
306 313 * $ cd ~/Downloads
307 314 * $ tar -xf doxygen-1.8.2.src.tar.gz
... ... @@ -310,9 +317,9 @@ $ br -help
310 317 * $ make -j4
311 318 * $ sudo make install
312 319 * $ cd ..
313   - * $ rm -r doxygen-1.8.2
  320 + * $ rm -rf doxygen-1.8.2*
314 321 * \endcode
315   - * -# Modify build settings and recompile:
  322 + * -# Modify build settings and recompile.
316 323 * \code
317 324 * $ cd openbr/build
318 325 * $ cmake -DBR_BUILD_DOCUMENTATION=ON ..
... ...
openbr/openbr_plugin.cpp
... ... @@ -389,8 +389,6 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery)
389 389 if (crossValidate > 0) srand(0);
390 390  
391 391 for (int i=newTemplates.size()-1; i>=0; i--) {
392   - newTemplates[i].file.append(gallery.localMetadata());
393   - newTemplates[i].file.append(file.localMetadata());
394 392 newTemplates[i].file.set("Index", i+templates.size());
395 393 newTemplates[i].file.set("Gallery", gallery.name);
396 394  
... ...
openbr/plugins/distance.cpp
... ... @@ -298,46 +298,6 @@ class IdenticalDistance : public Distance
298 298  
299 299 BR_REGISTER(Distance, IdenticalDistance)
300 300  
301   -class HeatMapDistance : public Distance
302   -{
303   - Q_OBJECT
304   - Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
305   - BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
306   - Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
307   - BR_PROPERTY(int, rows, -1)
308   - Q_PROPERTY(int cols READ get_cols WRITE set_cols RESET reset_cols STORED false)
309   - BR_PROPERTY(int, cols, -1)
310   -
311   - void train(const TemplateList &src)
312   - {
313   - distance->train(src);
314   - }
315   -
316   -
317   - float compare(const Template &a, const Template &b) const
318   - {
319   - qFatal("HeatMap expects a TemplateList");
320   -
321   - (void) a; (void) b;
322   - }
323   -
324   - void compare(const TemplateList &target, const TemplateList &query, Output *output) const
325   - {
326   - if (rows*cols > target.size()) qFatal("Incompatible heatmap comparison dimensionality");
327   -
328   - int index = 0;
329   - for (int col = 0; col < cols; col++) {
330   - for (int row = 0; row < rows; row++) {
331   - float score = distance->compare(target[index],query[index]);
332   - output->setRelative(score, row, col);
333   - index++;
334   - }
335   - }
336   - }
337   -};
338   -
339   -BR_REGISTER(Distance, HeatMapDistance)
340   -
341 301 } // namespace br
342 302  
343 303 #include "distance.moc"
... ...
openbr/plugins/output.cpp
... ... @@ -97,33 +97,25 @@ BR_REGISTER(Output, csvOutput)
97 97 class heatOutput : public MatrixOutput
98 98 {
99 99 Q_OBJECT
100   - Q_PROPERTY(int rows READ get_rows WRITE set_rows RESET reset_rows STORED false)
101   - BR_PROPERTY(int, rows, -1)
102   - Q_PROPERTY(int cols READ get_cols WRITE set_cols RESET reset_cols STORED false)
103   - BR_PROPERTY(int, cols, -1)
  100 + Q_PROPERTY(int patches READ get_patches WRITE set_patches RESET reset_patches STORED false)
  101 + BR_PROPERTY(int, patches, -1);
104 102  
105 103 ~heatOutput()
106 104 {
107 105 if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return;
108 106  
109   - if (rows*cols > targetFiles.size()) qFatal("Incompatible heatmap output dimensionality");
110   -
111 107 QStringList lines;
112   - for (int col = 0; col < cols; col++) {
113   - QStringList words;
114   - for (int row = 0; row < rows; row++)
115   - words.append(toString(row,col));
116   - lines.append(words.join(","));
  108 + for (int i=0; i<data.rows; i++) {
  109 + lines.append(toString(i,0));
117 110 }
118 111 QtUtils::writeFile(file, lines);
119 112 }
120 113  
121 114 void initialize(const FileList &targetFiles, const FileList &queryFiles)
122 115 {
123   - if (rows == -1 || cols == -1) qFatal("heatOutput requires dimensionality");
124   -
  116 + if (patches == -1) qFatal("Heat output requires the number of patches");
125 117 Output::initialize(targetFiles, queryFiles);
126   - data.create(rows, cols, CV_32FC1);
  118 + data.create(patches, 1, CV_32FC1);
127 119 }
128 120 };
129 121  
... ...
openbr/plugins/quality.cpp
... ... @@ -150,8 +150,7 @@ class MatchProbabilityDistance : public Distance
150 150 Q_OBJECT
151 151 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
152 152 Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false)
153   - BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
154   - BR_PROPERTY(bool, gaussian, true)
  153 + Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false)
155 154  
156 155 MP mp;
157 156  
... ... @@ -170,6 +169,7 @@ class MatchProbabilityDistance : public Distance
170 169 for (int j=0; j<i; j++) {
171 170 const float score = matrixOutput.data()->data.at<float>(i, j);
172 171 if (score == -std::numeric_limits<float>::max()) continue;
  172 + if (crossModality) if(src[i].file.get<QString>("Modality") == src[j].file.get<QString>("Modality")) continue;
173 173 if (labels[i] == labels[j]) genuineScores.append(score);
174 174 else impostorScores.append(score);
175 175 }
... ... @@ -181,9 +181,8 @@ class MatchProbabilityDistance : public Distance
181 181 float compare(const Template &target, const Template &query) const
182 182 {
183 183 float rawScore = distance->compare(target, query);
184   - return -log(rawScore+1);
185   - //if (rawScore == -std::numeric_limits<float>::max()) return rawScore;
186   - //return mp(rawScore, gaussian);
  184 + if (rawScore == -std::numeric_limits<float>::max()) return rawScore;
  185 + return mp(rawScore, gaussian);
187 186 }
188 187  
189 188 void store(QDataStream &stream) const
... ... @@ -197,12 +196,110 @@ class MatchProbabilityDistance : public Distance
197 196 distance->load(stream);
198 197 stream >> mp;
199 198 }
  199 +
  200 +protected:
  201 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  202 + BR_PROPERTY(bool, gaussian, true)
  203 + BR_PROPERTY(bool, crossModality, false)
200 204 };
201 205  
202 206 BR_REGISTER(Distance, MatchProbabilityDistance)
203 207  
204 208 /*!
205 209 * \ingroup distances
  210 + * \brief Match Probability modification for heat maps \cite klare12
  211 + * \author Scott Klum \cite sklum
  212 + */
  213 +class HeatMapDistance : public Distance
  214 +{
  215 + Q_OBJECT
  216 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  217 + 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)
  219 + Q_PROPERTY(int step READ get_step WRITE set_step RESET reset_step STORED false)
  220 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  221 + BR_PROPERTY(bool, gaussian, true)
  222 + BR_PROPERTY(bool, crossModality, false)
  223 + BR_PROPERTY(int, step, 1)
  224 +
  225 + QList<MP> mp;
  226 +
  227 + void train(const TemplateList &src)
  228 + {
  229 + distance->train(src);
  230 +
  231 + const QList<int> labels = src.indexProperty("Subject");
  232 +
  233 + QList<TemplateList> patches;
  234 +
  235 + // Split src into list of TemplateLists of corresponding patches across all Templates
  236 + for (int i=0; i<step; i++) {
  237 + TemplateList patchBuffer;
  238 + for (int j=i; j<src.size(); j+=step) {
  239 + patchBuffer.append(src[j]);
  240 + }
  241 + patches.append(patchBuffer);
  242 + patchBuffer.clear();
  243 + }
  244 +
  245 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(patches[0].size()), FileList(patches[0].size())));
  246 +
  247 + for (int i=0; i<step; i++) {
  248 + distance->compare(patches[i], patches[i], matrixOutput.data());
  249 + QList<float> genuineScores, impostorScores;
  250 + genuineScores.reserve(step);
  251 + impostorScores.reserve(step);
  252 + for (int j=0; j<matrixOutput.data()->data.rows; j++) {
  253 + for (int k=0; k<j; k++) {
  254 + const float score = matrixOutput.data()->data.at<float>(j, k);
  255 + if (score == -std::numeric_limits<float>::max()) continue;
  256 + if (crossModality) if(src[j*step].file.get<QString>("MODALITY") == src[k*step].file.get<QString>("MODALITY")) continue;
  257 + if (labels[j*step] == labels[k*step]) genuineScores.append(score);
  258 + else impostorScores.append(score);
  259 + }
  260 + }
  261 +
  262 + mp.append(MP(genuineScores, impostorScores));
  263 + }
  264 + }
  265 +
  266 + float compare(const Template &target, const Template &query) const
  267 + {
  268 + (void) target;
  269 + (void) query;
  270 + qFatal("You did this wrong");
  271 +
  272 + return 0;
  273 + }
  274 +
  275 + // Switch this to template list version, use compare(template, template) in
  276 + // heat map distance, and index into the proper match probability
  277 + void compare(const TemplateList &target, const TemplateList &query, Output *output) const
  278 + {
  279 + for (int i=0; i<step; i++) {
  280 + float rawScore = distance->compare(target[i],query[i]);
  281 + if (rawScore == -std::numeric_limits<float>::max()) output->setRelative(rawScore, i, 0);
  282 + else output->setRelative(mp[i](rawScore, gaussian), i, 0);
  283 + }
  284 + }
  285 +
  286 + void store(QDataStream &stream) const
  287 + {
  288 + distance->store(stream);
  289 + stream << mp;
  290 + }
  291 +
  292 + void load(QDataStream &stream)
  293 + {
  294 + distance->load(stream);
  295 + stream >> mp;
  296 + }
  297 +};
  298 +
  299 +BR_REGISTER(Distance, HeatMapDistance)
  300 +
  301 +/*!
  302 + * \ingroup distances
206 303 * \brief Linear normalizes of a distance so the mean impostor score is 0 and the mean genuine score is 1.
207 304 * \author Josh Klontz \cite jklontz
208 305 */
... ...
share/openbr/Doxyfile.in
... ... @@ -755,7 +755,7 @@ EXAMPLE_RECURSIVE = YES
755 755 # directories that contain image that are included in the documentation (see
756 756 # the \image command).
757 757  
758   -IMAGE_PATH = ${CMAKE_SOURCE_DIR}
  758 +IMAGE_PATH = ${CMAKE_SOURCE_DIR}/share/openbr
759 759  
760 760 # The INPUT_FILTER tag can be used to specify a program that doxygen should
761 761 # invoke to filter for each input file. Doxygen will invoke the filter program
... ...