Commit 3d52092c9ef07ff6767afdbf50011fc476ce1bc9

Authored by Scott Klum
1 parent 3ad2361a

Heat map output based on match probability

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  
... ... @@ -160,6 +159,7 @@ class MatchProbabilityDistance : public Distance
160 159 distance->train(src);
161 160  
162 161 const QList<int> labels = src.labels<int>();
  162 +
163 163 QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));
164 164 distance->compare(src, src, matrixOutput.data());
165 165  
... ... @@ -170,6 +170,7 @@ class MatchProbabilityDistance : public Distance
170 170 for (int j=0; j<i; j++) {
171 171 const float score = matrixOutput.data()->data.at<float>(i, j);
172 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 174 if (labels[i] == labels[j]) genuineScores.append(score);
174 175 else impostorScores.append(score);
175 176 }
... ... @@ -196,12 +197,108 @@ class MatchProbabilityDistance : public Distance
196 197 distance->load(stream);
197 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 207 BR_REGISTER(Distance, MatchProbabilityDistance)
202 208  
203 209 /*!
204 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 +
  274 + // Switch this to template list version, use compare(template, template) in
  275 + // heat map distance, and index into the proper match probability
  276 + void compare(const TemplateList &target, const TemplateList &query, Output *output) const
  277 + {
  278 + for (int i=0; i<step; i++) {
  279 + float rawScore = distance->compare(target[i],query[i]);
  280 + if (rawScore == -std::numeric_limits<float>::max()) output->setRelative(rawScore, i, 0);
  281 + else output->setRelative(mp[i](rawScore, gaussian), i, 0);
  282 + }
  283 + }
  284 +
  285 + void store(QDataStream &stream) const
  286 + {
  287 + distance->store(stream);
  288 + stream << mp;
  289 + }
  290 +
  291 + void load(QDataStream &stream)
  292 + {
  293 + distance->load(stream);
  294 + stream >> mp;
  295 + }
  296 +};
  297 +
  298 +BR_REGISTER(Distance, HeatMapDistance)
  299 +
  300 +/*!
  301 + * \ingroup distances
205 302 * \brief Linear normalizes of a distance so the mean impostor score is 0 and the mean genuine score is 1.
206 303 * \author Josh Klontz \cite jklontz
207 304 */
... ...