如何在 dlib 的一对一分类器中识别陌生人
Posted
技术标签:
【中文标题】如何在 dlib 的一对一分类器中识别陌生人【英文标题】:How to identify stranger in dlib`s one vs one classifier 【发布时间】:2019-11-29 04:46:00 【问题描述】:我正在使用one_vs_one_trainer
和one_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 的一对一分类器中识别陌生人的主要内容,如果未能解决你的问题,请参考以下文章