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

Posted

技术标签:

【中文标题】如何在 dlib 的一对一分类器中识别陌生人【英文标题】:How to identify stranger in dlib`s one vs one classifier 【发布时间】:2019-11-29 04:46:00 【问题描述】:

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

我正在使用 OpenCV 和我的包装器检测人脸,然后我遵循guide 并计算了 128D 人脸描述符,并将其存储在文件中。接下来,我按照this tutorial 训练了 one_vs_one 分类器。一切正常,但是当我尝试对未知面孔进行分类时,它会返回一些标签。

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

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

【问题讨论】:

【参考方案1】:

感谢Davis!Here 是 SourceForge 上的论坛主题。 答案是:

使用一堆二元分类器,而不是一对一。如果所有的二进制 分类器说他们不匹配然后你知道这个人不匹配任何 其中。

我是这样实现的:

#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;

【讨论】:

以上是关于如何在 dlib 的一对一分类器中识别陌生人的主要内容,如果未能解决你的问题,请参考以下文章

dlib 19.6 多分类器训练数据

如何在 sklearn 的集成分类器中使用自定义分类器?

我如何从两个已经训练好的分类器中构建一个分类器?

如何在斯坦福分类器中使用朴素贝叶斯分类器、SVM 和最大熵

如何利用opencv进行样本训练

如何在 Weka 分类器中使用 svm?