如何在 dlib 的一对一分类器中识别陌生人

How to identify stranger in dlib`s one vs one classifier

我正在使用 one_vs_one_trainerone_vs_one_decision_function 对 128D 面孔描述符进行分类,我想检测未知面孔。

我正在使用 OpenCV 和我的包装器检测人脸,然后我遵循 guide and computed the 128D face descriptors, that i stored in files. Next, i trained one_vs_one classifier following this tutorial。一切正常,但是当我尝试对未知面孔进行分类时,它 returns 一些标签。

我使用了指南中的代码,但如果您想查看我的代码 - 它是 here

有没有更好的人脸识别方法?也许,使用 OpenCV 的方法或 Dlib 中的其他方法更简单?

感谢Davis
Here 是 SourceForge 上的论坛帖子。
答案是:

Use a bunch of binary classifiers rather than one vs one. If all the binary classifiers say they don't match then you know the person doesn't match any of them.

我按如下方式实现:

#include <iostream>
#include <ctime>
#include <vector>

#include <dlib/svm.h>

using namespace std;
using namespace dlib;

int main() {
    typedef matrix<double, 128, 1> sample_type;

    typedef histogram_intersection_kernel<sample_type> kernel_type;

    typedef svm_c_trainer<kernel_type> trainer_type;

    typedef decision_function<kernel_type> classifier_type;

    std::vector<sample_type> samples;
    std::vector<double> labels;

    sample_type sample;

    // Samples ->

    sample = -0.104075,0.0353173,...,0.114782,-0.0360935;
    samples.emplace_back(sample);
    labels.emplace_back(0);
    sample = -0.0842,-0.0103397,...,0.0938285,0.010045;
    samples.emplace_back(sample);
    labels.emplace_back(0);
    sample = -0.0978358,0.0709425,...,0.052436,-0.0582029;
    samples.emplace_back(sample);
    labels.emplace_back(0);
    sample = -0.126522,0.0319873,...,0.12045,-0.0277105;
    samples.emplace_back(sample);
    labels.emplace_back(0);
    sample = -0.10335,-0.0261625,...,0.0600661,0.00703168,-8.67462e-05,-0.0598214,-0.104442,-0.046698,0.0553857,-0.0880691,0.0482511,0.0331484;
    samples.emplace_back(sample);
    labels.emplace_back(0);

    sample = -0.0747794,0.0599716,...,-0.0440207,-6.45183e-05;
    samples.emplace_back(sample);
    labels.emplace_back(1);
    sample = -0.0280804,0.0900723,...,-0.0267513,0.00824318;
    samples.emplace_back(sample);
    labels.emplace_back(1);
    sample = -0.0721213,0.00700722,...,-0.0128318,0.100784;
    samples.emplace_back(sample);
    labels.emplace_back(1);
    sample = -0.122747,0.0737782,0.0375799,...,0.0168201,-0.0246723;
    samples.emplace_back(sample);
    labels.emplace_back(1);
    sample = -0.0218071,0.118063,...,-0.0735178,0.04046;
    samples.emplace_back(sample);
    labels.emplace_back(1);

    sample = -0.0680787,0.0490121,-0.0228516,...,-0.0366242,0.0287891;
    samples.emplace_back(sample);
    labels.emplace_back(2);
    sample = 0.00152394,0.107174,...,-0.0479925,0.0182667;
    samples.emplace_back(sample);
    labels.emplace_back(2);
    sample = -0.0334521,0.165314,...,-0.0385227,-0.0215499;
    samples.emplace_back(sample);
    labels.emplace_back(2);
    sample = 0.0276394,0.106774,...,-0.0496831,-0.020857;
    samples.emplace_back(sample);
    labels.emplace_back(2);

    // <- Samples

    // Unique labels ->

    std::vector<double> total_labels;
    for(double &label : labels) {
        if(find(total_labels.begin(), total_labels.end(), label) == total_labels.end())
            total_labels.emplace_back(label);
    }

    // <- Unique labels

    // Init trainers ->

    std::vector<trainer_type> trainers;
    int num_trainers = total_labels.size() * (total_labels.size() - 1) / 2;
    cout << "Number of trainers is " << num_trainers << endl;

    for(int i = 0; i < num_trainers; i++) {
        trainers.emplace_back(trainer_type());
        trainers[i].set_kernel(kernel_type());
        trainers[i].set_c(10);
    }

    // <- Init trainers

    // Init classifiers ->

    std::vector<pair<double, double>> classifiersLabels;
    std::vector<classifier_type> classifiers;
    int label1 = 0, label2 = 1;
    for(trainer_type &trainer : trainers) {
        std::vector<sample_type> samples4pair;
        std::vector<double> labels4pair;

        for(int i = 0; i < samples.size(); i++) {
            if(labels[i] == total_labels[label1]) {
                samples4pair.emplace_back(samples[i]);
                labels4pair.emplace_back(-1);
            }
            if(labels[i] == total_labels[label2]) {
                samples4pair.emplace_back(samples[i]);
                labels4pair.emplace_back(+1);
            }
        }

        classifiers.emplace_back(trainer.train(samples4pair, labels4pair));
        classifiersLabels.emplace_back(make_pair(total_labels[label1],
                                                 total_labels[label2]));

        label2++;
        if(label2 == total_labels.size()) {
            label1++;
            label2 = label1 + 1;
        }
    }

    // <- Init classifiers

    double threshold = 0.3;
    auto classify = [&](){
        std::map<double, int> votes;
        for(int i = 0; i < classifiers.size(); i++) {
            cout << "Classifier #" << i << ":" << endl;

            double prediction = classifiers[i](sample);
            cout << prediction << ": ";

            if(abs(prediction) < threshold) {
                cout << "-1" << endl;
            } else if (prediction < 0) {
                votes[classifiersLabels[i].first]++;
                cout << classifiersLabels[i].first << endl;
            } else {
                votes[classifiersLabels[i].second]++;
                cout << classifiersLabels[i].second << endl;
            }
        }

        cout << "Votes: " << endl;
        for(auto &vote : votes) {
            cout << vote.first << ": " << vote.second << endl;
        }

        auto max = std::max_element(votes.begin(), votes.end(),
                                  [](const pair<double, int>& p1, const pair<double, int>& p2) {
                                      return p1.second < p2.second; });

        double label = votes.empty() ? -1 : max->first;
        cout << "Label is " << label << endl;
    };

    // Test ->

    cout << endl;

    sample = -0.0971093, ..., 0.123482, -0.0399552;
    cout << "True: 0 - " << endl;
    classify();

    cout << endl;

    sample = -0.0548414, ..., 0.0277335, 0.0460183;
    cout << "True: 1 - " << endl;
    classify();

    cout << endl;

    sample = -0.0456186,0.0617834,...,-0.0387607,0.0366309;
    cout << "True: 1 - " << endl;
    classify();

    cout << endl;

    sample = -0.0500396, 0.0947202, ..., -0.0540899, 0.0206803;
    cout << "True: 2 - " << endl;
    classify();

    cout << endl;

    sample = -0.0702862, 0.065316, ..., -0.0279446, 0.0453012;
    cout << "Unknown - " << endl;
    classify();

    cout << endl;

    sample = -0.0789684, 0.0632067, ..., 0.0330486, 0.0117508;
    cout << "Unknown - " << endl;
    classify();

    cout << endl;

    sample = -0.0941284, 0.0542927, ..., 0.00855513, 0.00840678;
    cout << "Unknown - " << endl;
    classify();

    // <- Test

    return 0;
}