Commit 0fb1cef2dfc9eea657ee80b6730aba9a54e07994
1 parent
4b34805a
finished IUM draft
Showing
3 changed files
with
115 additions
and
46 deletions
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 &target, const Template &query) const | @@ -1336,7 +1298,7 @@ float Distance::compare(const Template &target, const Template &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" |