Commit 09dc49393895dc48a7fee6e3f6070af72b49f117
1 parent
d953599d
FaceRecognition now uses MatchProbabilityDistance
Showing
6 changed files
with
20 additions
and
19 deletions
CHANGELOG.md
app/examples/face_recognition.cpp
| ... | ... | @@ -62,8 +62,9 @@ int main(int argc, char *argv[]) |
| 62 | 62 | float comparisonA = distance->compare(target, queryA); |
| 63 | 63 | float comparisonB = distance->compare(target, queryB); |
| 64 | 64 | |
| 65 | - printf("Genuine match score: %.3f\n", comparisonA); // Scores above 1 are strong matches | |
| 66 | - printf("Impostor match score: %.3f\n", comparisonB); // Scores below 0.5 are strong non-matches | |
| 65 | + // Scores range from 0 to 1 and represent match probability | |
| 66 | + printf("Genuine match score: %.3f\n", comparisonA); | |
| 67 | + printf("Impostor match score: %.3f\n", comparisonB); | |
| 67 | 68 | |
| 68 | 69 | br::Context::finalize(); |
| 69 | 70 | return 0; | ... | ... |
sdk/plugins/algorithms.cpp
| ... | ... | @@ -31,7 +31,7 @@ class AlgorithmsInitializer : public Initializer |
| 31 | 31 | void initialize() const |
| 32 | 32 | { |
| 33 | 33 | // Face |
| 34 | - Globals->abbreviations.insert("FaceRecognition", "FaceDetection!<FaceRecognitionRegistration>!<FaceRecognitionExtraction>+<FaceRecognitionEmbedding>+<FaceRecognitionQuantization>:UCharL1"); | |
| 34 | + Globals->abbreviations.insert("FaceRecognition", "FaceDetection!<FaceRecognitionRegistration>!<FaceRecognitionExtraction>+<FaceRecognitionEmbedding>+<FaceRecognitionQuantization>:MatchProbability(ByteL1)"); | |
| 35 | 35 | Globals->abbreviations.insert("FaceRecognitionNoTraining", "FaceDetection!ASEFEyes+Affine(86,86,0.25,0.35)!Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+Mask+LBP(1,2)+RectRegions(8,8,6,6)+Hist(59)+Cat:ChiSquared"); |
| 36 | 36 | Globals->abbreviations.insert("GenderClassification", "FaceDetection!<FaceClassificationRegistration>!<FaceClassificationExtraction>+<GenderClassifier>+Discard"); |
| 37 | 37 | Globals->abbreviations.insert("AgeRegression", "FaceDetection!<FaceClassificationRegistration>!<FaceClassificationExtraction>+<AgeRegressor>+Discard"); | ... | ... |
sdk/plugins/format.cpp
| ... | ... | @@ -222,7 +222,6 @@ class DefaultFormat : public Format |
| 222 | 222 | fileName = file.fileName(); |
| 223 | 223 | if (!QFileInfo(fileName).exists()) { |
| 224 | 224 | fileName = file.getString("path") + "/" + file.fileName(); |
| 225 | - qDebug() << fileName; | |
| 226 | 225 | if (!QFileInfo(fileName).exists()) return t; |
| 227 | 226 | } |
| 228 | 227 | } | ... | ... |
sdk/plugins/quality.cpp
| ... | ... | @@ -147,13 +147,11 @@ class MatchProbabilityDistance : public Distance |
| 147 | 147 | { |
| 148 | 148 | Q_OBJECT |
| 149 | 149 | Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false) |
| 150 | - Q_PROPERTY(QString binKey READ get_binKey WRITE set_binKey RESET reset_binKey STORED false) | |
| 151 | 150 | Q_PROPERTY(bool gaussian READ get_gaussian WRITE set_gaussian RESET reset_gaussian STORED false) |
| 152 | 151 | BR_PROPERTY(br::Distance*, distance, make("Dist(L2)")) |
| 153 | - BR_PROPERTY(QString, binKey, "") | |
| 154 | 152 | BR_PROPERTY(bool, gaussian, true) |
| 155 | 153 | |
| 156 | - QHash<QString, MP> mps; | |
| 154 | + MP mp; | |
| 157 | 155 | |
| 158 | 156 | void train(const TemplateList &src) |
| 159 | 157 | { |
| ... | ... | @@ -163,37 +161,38 @@ class MatchProbabilityDistance : public Distance |
| 163 | 161 | QScopedPointer<MatrixOutput> memoryOutput(dynamic_cast<MatrixOutput*>(Output::make(".Matrix", FileList(src.size()), FileList(src.size())))); |
| 164 | 162 | distance->compare(src, src, memoryOutput.data()); |
| 165 | 163 | |
| 166 | - QHash< QString, QList<float> > genuineScores, impostorScores; | |
| 167 | - for (int i=0; i<src.size(); i++) | |
| 164 | + QList<float> genuineScores, impostorScores; | |
| 165 | + genuineScores.reserve(labels.size()); | |
| 166 | + impostorScores.reserve(labels.size()*labels.size()); | |
| 167 | + for (int i=0; i<src.size(); i++) { | |
| 168 | 168 | for (int j=0; j<i; j++) { |
| 169 | 169 | const float score = memoryOutput.data()->data.at<float>(i, j); |
| 170 | 170 | if (score == -std::numeric_limits<float>::max()) continue; |
| 171 | - const QString bin = src[i].file.getString(binKey, ""); | |
| 172 | - if (labels[i] == labels[j]) genuineScores[bin].append(score); | |
| 173 | - else impostorScores[bin].append(score); | |
| 171 | + if (labels[i] == labels[j]) genuineScores.append(score); | |
| 172 | + else impostorScores.append(score); | |
| 174 | 173 | } |
| 174 | + } | |
| 175 | 175 | |
| 176 | - foreach (const QString &key, genuineScores.keys()) | |
| 177 | - mps.insert(key, MP(genuineScores[key], impostorScores[key])); | |
| 176 | + mp = MP(genuineScores, impostorScores); | |
| 178 | 177 | } |
| 179 | 178 | |
| 180 | 179 | float compare(const Template &target, const Template &query) const |
| 181 | 180 | { |
| 182 | 181 | float rawScore = distance->compare(target, query); |
| 183 | 182 | if (rawScore == -std::numeric_limits<float>::max()) return rawScore; |
| 184 | - return mps[query.file.getString(binKey, "")](rawScore, gaussian); | |
| 183 | + return mp(rawScore, gaussian); | |
| 185 | 184 | } |
| 186 | 185 | |
| 187 | 186 | void store(QDataStream &stream) const |
| 188 | 187 | { |
| 189 | 188 | distance->store(stream); |
| 190 | - stream << mps; | |
| 189 | + stream << mp; | |
| 191 | 190 | } |
| 192 | 191 | |
| 193 | 192 | void load(QDataStream &stream) |
| 194 | 193 | { |
| 195 | 194 | distance->load(stream); |
| 196 | - stream >> mps; | |
| 195 | + stream >> mp; | |
| 197 | 196 | } |
| 198 | 197 | }; |
| 199 | 198 | ... | ... |