Commit 0fb1cef2dfc9eea657ee80b6730aba9a54e07994

Authored by Josh Klontz
1 parent 4b34805a

finished IUM draft

sdk/openbr_plugin.cpp
@@ -1270,44 +1270,6 @@ void Transform::backProject(const TemplateList &dst, TemplateList &src) const @@ -1270,44 +1270,6 @@ void Transform::backProject(const TemplateList &dst, TemplateList &src) const
1270 } 1270 }
1271 1271
1272 /* Distance - public methods */ 1272 /* Distance - public methods */
1273 -void Distance::train(const TemplateList &templates)  
1274 -{  
1275 - const TemplateList samples = templates.mid(0, 2000);  
1276 - const QList<float> sampleLabels = samples.labels<float>();  
1277 - QScopedPointer<MatrixOutput> memoryOutput(dynamic_cast<MatrixOutput*>(Output::make(".Matrix", FileList(samples.size()), FileList(samples.size()))));  
1278 - compare(samples, samples, memoryOutput.data());  
1279 -  
1280 - double genuineAccumulator, impostorAccumulator;  
1281 - int genuineCount, impostorCount;  
1282 - genuineAccumulator = impostorAccumulator = genuineCount = impostorCount = 0;  
1283 -  
1284 - for (int i=0; i<samples.size(); i++) {  
1285 - for (int j=0; j<i; j++) {  
1286 - const float val = memoryOutput.data()->data.at<float>(i, j);  
1287 - if (sampleLabels[i] == sampleLabels[j]) {  
1288 - genuineAccumulator += val;  
1289 - genuineCount++;  
1290 - } else {  
1291 - impostorAccumulator += val;  
1292 - impostorCount++;  
1293 - }  
1294 - }  
1295 - }  
1296 -  
1297 - if (genuineCount == 0) { qWarning("No genuine matches."); return; }  
1298 - if (impostorCount == 0) { qWarning("No impostor matches."); return; }  
1299 -  
1300 - double genuineMean = genuineAccumulator / genuineCount;  
1301 - double impostorMean = impostorAccumulator / impostorCount;  
1302 -  
1303 - if (genuineMean == impostorMean) { qWarning("Genuines and impostors are indistinguishable."); return; }  
1304 -  
1305 - a = 1.0/(genuineMean-impostorMean);  
1306 - b = impostorMean;  
1307 -  
1308 - qDebug("a = %f, b = %f", a, b);  
1309 -}  
1310 -  
1311 void Distance::compare(const TemplateList &target, const TemplateList &query, Output *output) const 1273 void Distance::compare(const TemplateList &target, const TemplateList &query, Output *output) const
1312 { 1274 {
1313 const bool stepTarget = target.size() > query.size(); 1275 const bool stepTarget = target.size() > query.size();
@@ -1336,7 +1298,7 @@ float Distance::compare(const Template &amp;target, const Template &amp;query) const @@ -1336,7 +1298,7 @@ float Distance::compare(const Template &amp;target, const Template &amp;query) const
1336 return -std::numeric_limits<float>::max(); 1298 return -std::numeric_limits<float>::max();
1337 } 1299 }
1338 1300
1339 - return a * (_compare(target, query) - b); 1301 + return _compare(target, query);
1340 } 1302 }
1341 1303
1342 QList<float> Distance::compare(const TemplateList &targets, const Template &query) const 1304 QList<float> Distance::compare(const TemplateList &targets, const Template &query) const
sdk/openbr_plugin.h
@@ -1065,15 +1065,9 @@ class BR_EXPORT Distance : public Object @@ -1065,15 +1065,9 @@ class BR_EXPORT Distance : public Object
1065 { 1065 {
1066 Q_OBJECT 1066 Q_OBJECT
1067 1067
1068 - // Score normalization  
1069 - Q_PROPERTY(float a READ get_a WRITE set_a RESET reset_a)  
1070 - Q_PROPERTY(float b READ get_b WRITE set_b RESET reset_b)  
1071 - BR_PROPERTY(float, a, 1)  
1072 - BR_PROPERTY(float, b, 0)  
1073 -  
1074 public: 1068 public:
1075 static QSharedPointer<Distance> fromAlgorithm(const QString &algorithm); /*!< \brief Retrieve an algorithm's distance. */ 1069 static QSharedPointer<Distance> fromAlgorithm(const QString &algorithm); /*!< \brief Retrieve an algorithm's distance. */
1076 - virtual void train(const TemplateList &src); /*!< \brief Train the distance. */ 1070 + virtual void train(const TemplateList &src) { (void) src; } /*!< \brief Train the distance. */
1077 virtual void compare(const TemplateList &target, const TemplateList &query, Output *output) const; /*!< \brief Compare two template lists. */ 1071 virtual void compare(const TemplateList &target, const TemplateList &query, Output *output) const; /*!< \brief Compare two template lists. */
1078 float compare(const Template &target, const Template &query) const; /*!< \brief Compute the normalized distance between two templates. */ 1072 float compare(const Template &target, const Template &query) const; /*!< \brief Compute the normalized distance between two templates. */
1079 QList<float> compare(const TemplateList &targets, const Template &query) const; /*!< \brief Compute the normalized distance between a template and a template list. */ 1073 QList<float> compare(const TemplateList &targets, const Template &query) const; /*!< \brief Compute the normalized distance between a template and a template list. */
sdk/plugins/quality.cpp
@@ -74,6 +74,119 @@ class IUMTransform : public Transform @@ -74,6 +74,119 @@ class IUMTransform : public Transform
74 74
75 BR_REGISTER(Transform, IUMTransform) 75 BR_REGISTER(Transform, IUMTransform)
76 76
  77 +/* Kernel Density Estimator */
  78 +struct KDE
  79 +{
  80 + float min, max;
  81 + QList<float> bins;
  82 +
  83 + KDE() : min(0), max(1) {}
  84 + KDE(const QList<float> &scores)
  85 + {
  86 + Common::MinMax(scores, &min, &max);
  87 + double h = Common::KernelDensityBandwidth(scores);
  88 + const int size = 255;
  89 + bins.reserve(size);
  90 + for (int i=0; i<size; i++)
  91 + bins.append(Common::KernelDensityEstimation(scores, min + (max-min)*i/(size-1), h));
  92 + }
  93 +
  94 + float operator()(float score) const
  95 + {
  96 + if (score <= min) return bins.first();
  97 + if (score >= max) return bins.last();
  98 + const float x = (score-min)/(max-min)*bins.size();
  99 + const float y1 = bins[floor(x)];
  100 + const float y2 = bins[ceil(x)];
  101 + return y1 + (y2-y1)*(x-floor(x));
  102 + }
  103 +};
  104 +
  105 +QDataStream &operator<<(QDataStream &stream, const KDE &kde)
  106 +{
  107 + return stream << kde.min << kde.max << kde.bins;
  108 +}
  109 +
  110 +QDataStream &operator>>(QDataStream &stream, KDE &kde)
  111 +{
  112 + return stream >> kde.min >> kde.max >> kde.bins;
  113 +}
  114 +
  115 +/* Non-match Probability */
  116 +struct NMP
  117 +{
  118 + KDE genuine, impostor;
  119 + NMP() {}
  120 + NMP(const QList<float> &genuineScores, const QList<float> &impostorScores)
  121 + : genuine(genuineScores), impostor(impostorScores) {}
  122 + float operator()(float score) const { float g = genuine(score); return g / (impostor(score) + g); }
  123 +};
  124 +
  125 +QDataStream &operator<<(QDataStream &stream, const NMP &nmp)
  126 +{
  127 + return stream << nmp.genuine << nmp.impostor;
  128 +}
  129 +
  130 +QDataStream &operator>>(QDataStream &stream, NMP &nmp)
  131 +{
  132 + return stream >> nmp.genuine >> nmp.impostor;
  133 +}
  134 +
  135 +/*!
  136 + * \ingroup distances
  137 + * \brief Impostor Uniqueness Distance \cite klare12
  138 + * \author Josh Klontz \cite jklontz
  139 + */
  140 +class IUMDistance : public Distance
  141 +{
  142 + Q_OBJECT
  143 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
  144 + BR_PROPERTY(br::Distance*, distance, Factory<Distance>::make(".Dist(L2)"))
  145 +
  146 + QList<NMP> nmps;
  147 +
  148 + void train(const TemplateList &src)
  149 + {
  150 + distance->train(src);
  151 +
  152 + const QList<float> labels = src.labels<float>();
  153 + QScopedPointer<MatrixOutput> memoryOutput(dynamic_cast<MatrixOutput*>(Output::make(".Matrix", FileList(src.size()), FileList(src.size()))));
  154 + distance->compare(src, src, memoryOutput.data());
  155 +
  156 + const int IUM_Bins = 3;
  157 + QVector< QList<float> > genuineScores(IUM_Bins), impostorScores(IUM_Bins);
  158 + for (int i=0; i<src.size(); i++)
  159 + for (int j=0; j<i; j++) {
  160 + const float score = memoryOutput.data()->data.at<float>(i, j);
  161 + const int bin = src[i].file.getInt("IUM_Bin");
  162 + if (labels[i] == labels[j]) genuineScores[bin].append(score);
  163 + else impostorScores[bin].append(score);
  164 + }
  165 +
  166 + for (int i=0; i<IUM_Bins; i++)
  167 + nmps.append(NMP(genuineScores[i], impostorScores[i]));
  168 + }
  169 +
  170 + float _compare(const Template &target, const Template &query) const
  171 + {
  172 + return nmps[query.file.getInt("IUM_Bin")](distance->compare(target, query));
  173 + }
  174 +
  175 + void store(QDataStream &stream) const
  176 + {
  177 + distance->store(stream);
  178 + stream << nmps;
  179 + }
  180 +
  181 + void load(QDataStream &stream)
  182 + {
  183 + distance->load(stream);
  184 + stream >> nmps;
  185 + }
  186 +};
  187 +
  188 +BR_REGISTER(Distance, IUMDistance)
  189 +
77 } // namespace br 190 } // namespace br
78 191
79 #include "quality.moc" 192 #include "quality.moc"