Commit 5167426420d4084cbe1301c63ae18989efef5dd6

Authored by Josh Klontz
2 parents 41325f10 fec9f047

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

openbr/gui/imageviewer.cpp
@@ -36,7 +36,8 @@ void br::ImageViewer::setDefaultText(const QString &text) @@ -36,7 +36,8 @@ void br::ImageViewer::setDefaultText(const QString &text)
36 36
37 void br::ImageViewer::setImage(const QString &file, bool async) 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 updatePixmap(async); 41 updatePixmap(async);
41 } 42 }
42 43
openbr/plugins/distance.cpp
@@ -298,46 +298,6 @@ class IdenticalDistance : public Distance @@ -298,46 +298,6 @@ class IdenticalDistance : public Distance
298 298
299 BR_REGISTER(Distance, IdenticalDistance) 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 } // namespace br 301 } // namespace br
342 302
343 #include "distance.moc" 303 #include "distance.moc"
openbr/plugins/output.cpp
@@ -97,33 +97,25 @@ BR_REGISTER(Output, csvOutput) @@ -97,33 +97,25 @@ BR_REGISTER(Output, csvOutput)
97 class heatOutput : public MatrixOutput 97 class heatOutput : public MatrixOutput
98 { 98 {
99 Q_OBJECT 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 ~heatOutput() 103 ~heatOutput()
106 { 104 {
107 if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return; 105 if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return;
108 106
109 - if (rows*cols > targetFiles.size()) qFatal("Incompatible heatmap output dimensionality");  
110 -  
111 QStringList lines; 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 QtUtils::writeFile(file, lines); 111 QtUtils::writeFile(file, lines);
119 } 112 }
120 113
121 void initialize(const FileList &targetFiles, const FileList &queryFiles) 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 Output::initialize(targetFiles, queryFiles); 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,8 +150,7 @@ class MatchProbabilityDistance : public Distance
150 Q_OBJECT 150 Q_OBJECT
151 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false) 151 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
152 Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false) 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 MP mp; 155 MP mp;
157 156
@@ -160,6 +159,7 @@ class MatchProbabilityDistance : public Distance @@ -160,6 +159,7 @@ class MatchProbabilityDistance : public Distance
160 distance->train(src); 159 distance->train(src);
161 160
162 const QList<int> labels = src.labels<int>(); 161 const QList<int> labels = src.labels<int>();
  162 +
163 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size()))); 163 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));
164 distance->compare(src, src, matrixOutput.data()); 164 distance->compare(src, src, matrixOutput.data());
165 165
@@ -170,6 +170,7 @@ class MatchProbabilityDistance : public Distance @@ -170,6 +170,7 @@ class MatchProbabilityDistance : public Distance
170 for (int j=0; j<i; j++) { 170 for (int j=0; j<i; j++) {
171 const float score = matrixOutput.data()->data.at<float>(i, j); 171 const float score = matrixOutput.data()->data.at<float>(i, j);
172 if (score == -std::numeric_limits<float>::max()) continue; 172 if (score == -std::numeric_limits<float>::max()) continue;
  173 + if (crossModality) if(src[i].file.get<QString>("Modality") == src[j].file.get<QString>("Modality")) continue;
173 if (labels[i] == labels[j]) genuineScores.append(score); 174 if (labels[i] == labels[j]) genuineScores.append(score);
174 else impostorScores.append(score); 175 else impostorScores.append(score);
175 } 176 }
@@ -196,12 +197,110 @@ class MatchProbabilityDistance : public Distance @@ -196,12 +197,110 @@ class MatchProbabilityDistance : public Distance
196 distance->load(stream); 197 distance->load(stream);
197 stream >> mp; 198 stream >> mp;
198 } 199 }
  200 +
  201 +protected:
  202 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  203 + BR_PROPERTY(bool, gaussian, true)
  204 + BR_PROPERTY(bool, crossModality, false)
199 }; 205 };
200 206
201 BR_REGISTER(Distance, MatchProbabilityDistance) 207 BR_REGISTER(Distance, MatchProbabilityDistance)
202 208
203 /*! 209 /*!
204 * \ingroup distances 210 * \ingroup distances
  211 + * \brief Match Probability modification for heat maps \cite klare12
  212 + * \author Scott Klum \cite sklum
  213 + */
  214 +class HeatMapDistance : public Distance
  215 +{
  216 + Q_OBJECT
  217 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  218 + Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false)
  219 + Q_PROPERTY(bool crossModality READ get_crossModality WRITE set_crossModality RESET reset_crossModality STORED false)
  220 + Q_PROPERTY(int step READ get_step WRITE set_step RESET reset_step STORED false)
  221 + BR_PROPERTY(br::Distance*, distance, make("Dist(L2)"))
  222 + BR_PROPERTY(bool, gaussian, true)
  223 + BR_PROPERTY(bool, crossModality, false)
  224 + BR_PROPERTY(int, step, 1)
  225 +
  226 + QList<MP> mp;
  227 +
  228 + void train(const TemplateList &src)
  229 + {
  230 + distance->train(src);
  231 +
  232 + const QList<int> labels = src.labels<int>();
  233 +
  234 + QList<TemplateList> patches;
  235 +
  236 + // Split src into list of TemplateLists of corresponding patches across all Templates
  237 + for (int i=0; i<step; i++) {
  238 + TemplateList patchBuffer;
  239 + for (int j=i; j<src.size(); j+=step) {
  240 + patchBuffer.append(src[j]);
  241 + }
  242 + patches.append(patchBuffer);
  243 + patchBuffer.clear();
  244 + }
  245 +
  246 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(patches[0].size()), FileList(patches[0].size())));
  247 +
  248 + for (int i=0; i<step; i++) {
  249 + distance->compare(patches[i], patches[i], matrixOutput.data());
  250 + QList<float> genuineScores, impostorScores;
  251 + genuineScores.reserve(step);
  252 + impostorScores.reserve(step);
  253 + for (int j=0; j<matrixOutput.data()->data.rows; j++) {
  254 + for (int k=0; k<j; k++) {
  255 + const float score = matrixOutput.data()->data.at<float>(j, k);
  256 + if (score == -std::numeric_limits<float>::max()) continue;
  257 + if (crossModality) if(src[j*step].file.get<QString>("MODALITY") == src[k*step].file.get<QString>("MODALITY")) continue;
  258 + if (labels[j*step] == labels[k*step]) genuineScores.append(score);
  259 + else impostorScores.append(score);
  260 + }
  261 + }
  262 +
  263 + mp.append(MP(genuineScores, impostorScores));
  264 + }
  265 + }
  266 +
  267 + float compare(const Template &target, const Template &query) const
  268 + {
  269 + (void) target;
  270 + (void) query;
  271 + qFatal("You did this wrong");
  272 +
  273 + return 0;
  274 + }
  275 +
  276 + // Switch this to template list version, use compare(template, template) in
  277 + // heat map distance, and index into the proper match probability
  278 + void compare(const TemplateList &target, const TemplateList &query, Output *output) const
  279 + {
  280 + for (int i=0; i<step; i++) {
  281 + float rawScore = distance->compare(target[i],query[i]);
  282 + if (rawScore == -std::numeric_limits<float>::max()) output->setRelative(rawScore, i, 0);
  283 + else output->setRelative(mp[i](rawScore, gaussian), i, 0);
  284 + }
  285 + }
  286 +
  287 + void store(QDataStream &stream) const
  288 + {
  289 + distance->store(stream);
  290 + stream << mp;
  291 + }
  292 +
  293 + void load(QDataStream &stream)
  294 + {
  295 + distance->load(stream);
  296 + stream >> mp;
  297 + }
  298 +};
  299 +
  300 +BR_REGISTER(Distance, HeatMapDistance)
  301 +
  302 +/*!
  303 + * \ingroup distances
205 * \brief Linear normalizes of a distance so the mean impostor score is 0 and the mean genuine score is 1. 304 * \brief Linear normalizes of a distance so the mean impostor score is 0 and the mean genuine score is 1.
206 * \author Josh Klontz \cite jklontz 305 * \author Josh Klontz \cite jklontz
207 */ 306 */