OpenCV学习(40) 人脸识别(4)
在人脸识别模式类中,还实现了一种基于LBP直方图的人脸识别方法。LBP图的原理参照:http://www.cnblogs.com/mikewolf2002/p/3438698.html
在代码中,我们只要使用 Ptr<FaceRecognizer> model = createLBPHFaceRecognizer(); 就创建了一个基于LBPH的人脸识别类,其它代码和前面两种人脸识别方法一样。
在train函数中,会计算每个样本的LBP图像,并求出该图像的二维直方图,把直方图保存在_histograms中,以便在predict函数调用这些直方图进行匹配。
for(size_t sampleIdx = 0; sampleIdx < src.size(); sampleIdx++)
{
// 计算LBP图
Mat lbp_image = elbp(src[sampleIdx], _radius, _neighbors);
// 得到直方图
Mat p = spatial_histogram(
lbp_image, /* lbp_image */
static_cast<int>(std::pow(2.0, static_cast<double>(_neighbors))), //可能的模式数
_grid_x, /* grid size x */
_grid_y, /* grid size y */
true);
// 把直方图加到匹配模版中
_histograms.push_back(p);
}
在预测函数中,会先求出输入图像的LBPH图,然后和保存的样本LBPH进行比较,距离最今即为匹配的人脸。
Mat lbp_image = elbp(src, _radius, _neighbors);
Mat query = spatial_histogram(
lbp_image, /* lbp_image */
static_cast<int>(std::pow(2.0, static_cast<double>(_neighbors))), /* number of possible patterns */
_grid_x, /* grid size x */
_grid_y, /* grid size y */
true /* normed histograms */);
// 查找最近的匹配者
minDist = DBL_MAX;
minClass = -1;
for(size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++)
{
double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR);
if((dist < minDist) && (dist < _threshold))
{
minDist = dist;
minClass = _labels.at<int>((int) sampleIdx);
}
}
代码:
#include "opencv2/core/core.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/highgui/highgui.hpp" #include <iostream>
#include <fstream>
#include <sstream> using namespace cv;
using namespace std; static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') {
std::ifstream file(filename.c_str(), ifstream::in);
if (!file) {
string error_message = "No valid input file was given, please check the given filename.";
CV_Error(CV_StsBadArg, error_message);
}
string line, path, classlabel;
while (getline(file, line)) {
stringstream liness(line);
getline(liness, path, separator);
getline(liness, classlabel);
if(!path.empty() && !classlabel.empty()) {
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));
}
}
} int main(int argc, const char *argv[])
{ // Get the path to your CSV.
string fn_csv = string("facerec_at_t.txt");
// These vectors hold the images and corresponding labels.
vector<Mat> images;
vector<int> labels;
// Read in the data. This can fail if no valid
// input filename is given.
try {
read_csv(fn_csv, images, labels);
} catch (cv::Exception& e) {
cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl;
// nothing more we can do
exit(1);
}
// Quit if there are not enough images for this demo.
if(images.size() <= 1) {
string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
CV_Error(CV_StsError, error_message);
}
// Get the height from the first image. We'll need this
// later in code to reshape the images to their original
// size:
int height = images[0].rows;
// The following lines simply get the last images from
// your dataset and remove it from the vector. This is
// done, so that the training data (which we learn the
// cv::FaceRecognizer on) and the test data we test
// the model with, do not overlap.
Mat testSample = images[images.size() - 1];
int testLabel = labels[labels.size() - 1];
images.pop_back();
labels.pop_back();
// The following lines create an LBPH model for
// face recognition and train it with the images and
// labels read from the given CSV file.
//
// The LBPHFaceRecognizer uses Extended Local Binary Patterns
// (it's probably configurable with other operators at a later
// point), and has the following default values
//
// radius = 1
// neighbors = 8
// grid_x = 8
// grid_y = 8
//
// So if you want a LBPH FaceRecognizer using a radius of
// 2 and 16 neighbors, call the factory method with:
//
// cv::createLBPHFaceRecognizer(2, 16);
//
// And if you want a threshold (e.g. 123.0) call it with its default values:
//
// cv::createLBPHFaceRecognizer(1,8,8,8,123.0)
//
Ptr<FaceRecognizer> model = createLBPHFaceRecognizer();
model->train(images, labels);
// The following line predicts the label of a given
// test image:
int predictedLabel = model->predict(testSample);
//
// To get the confidence of a prediction call the model with:
//
// int predictedLabel = -1;
// double confidence = 0.0;
// model->predict(testSample, predictedLabel, confidence);
//
string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel);
cout << result_message << endl;
// Sometimes you'll need to get/set internal model data,
// which isn't exposed by the public cv::FaceRecognizer.
// Since each cv::FaceRecognizer is derived from a
// cv::Algorithm, you can query the data.
//
// First we'll use it to set the threshold of the FaceRecognizer
// to 0.0 without retraining the model. This can be useful if
// you are evaluating the model:
//
model->set("threshold", 0.0);
// Now the threshold of this model is set to 0.0. A prediction
// now returns -1, as it's impossible to have a distance below
// it
predictedLabel = model->predict(testSample);
cout << "Predicted class = " << predictedLabel << endl;
// Show some informations about the model, as there's no cool
// Model data to display as in Eigenfaces/Fisherfaces.
// Due to efficiency reasons the LBP images are not stored
// within the model:
cout << "Model Information:" << endl;
string model_info = format("\tLBPH(radius=%i, neighbors=%i, grid_x=%i, grid_y=%i, threshold=%.2f)",
model->getInt("radius"),
model->getInt("neighbors"),
model->getInt("grid_x"),
model->getInt("grid_y"),
model->getDouble("threshold"));
cout << model_info << endl;
// We could get the histograms for example:
vector<Mat> histograms = model->getMatVector("histograms");
// But should I really visualize it? Probably the length is interesting:
cout << "Size of the histograms: " << histograms[0].total() << endl;
return 0;
}
程序代码:工程FirstOpenCV35
OpenCV学习(40) 人脸识别(4)的更多相关文章
- OpenCV学习(38) 人脸识别(3)
前面我们学习了基于特征脸的人脸识别,现在我们学习一下基于Fisher脸的人脸识别,Fisher人脸识别基于LDA(线性判别算法)算法,算法的详细介绍可以参考下面两篇教程内容: ...
- OpenCV学习(37) 人脸识别(2)
在前面一篇教程中,我们学习了OpenCV中基于特征脸的人脸识别的代码实现,我们通过代码 Ptr<FaceRecognizer> model = createEigenFaceR ...
- OpenCV学习(36) 人脸识别(1)
本文主要参考OpenCV人脸识别教程:http://docs.opencv.org/modules/contrib/doc/facerec/facerec_tutorial.html 1.OpenCV ...
- 【从零学习openCV】IOS7人脸识别实战
前言 接着上篇<IOS7下的人脸检測>,我们顺藤摸瓜的学习怎样在IOS7下用openCV的进行人脸识别,实际上非常easy,因为人脸检測部分已经完毕,剩下的无非调用openCV的方法对採集 ...
- 基于深度学习的人脸识别系统(Caffe+OpenCV+Dlib)【一】如何配置caffe属性表
前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...
- 基于深度学习的人脸识别系统(Caffe+OpenCV+Dlib)【三】VGG网络进行特征提取
前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...
- 基于深度学习的人脸识别系统(Caffe+OpenCV+Dlib)【二】人脸预处理
前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...
- 基于深度学习的人脸识别系统系列(Caffe+OpenCV+Dlib)——【四】使用CUBLAS加速计算人脸向量的余弦距离
前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...
- 基于Opencv快速实现人脸识别(完整版)
无耻收藏网页链接: 基于OpenCV快速实现人脸识别:https://blog.csdn.net/beyond9305/article/details/92844258 基于Opencv快速实现人脸识 ...
随机推荐
- 004 爬虫(最初的爬虫方式,以及urllib2)
一:最初的爬取方式 1.代码示例 # coding=utf-8 import urllib2 request=urllib2.Request("http://www.baidu.com&qu ...
- jump game(贪心算法)
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- 2017-2018-1 20179202《Linux内核原理与分析》第八周作业
一 .可执行程序的装载 1. 预处理.编译.链接 gcc –e –o hello.cpp hello.c //预处理 gcc -x cpp-output -S -o hello.s hello.cpp ...
- Matlab 也很强大!
一.实时编辑器 所创建的脚本不仅可以捕获代码,还可以讲述与人分享的故事.自动化的上下文提示可让您在编程时快速推进,并且将结果与可视化内容和您的代码一起显示. 一般以 .mlx 为后缀. 二.App D ...
- 深入理解ajax系列第九篇
前面的话 jQuery提供了一些日常开发中需要的快捷操作,例如load.ajax.get和post等,使用jQuery开发ajax将变得极其简单.这样开发人员就可以将程序开发集中在业务和用户体验上,而 ...
- BZOJ3207 花神的嘲讽计划
hash值建主席树. 垃圾题面没有熟虑范围害我MLE——>RE. By:大奕哥 #include<bits/stdc++.h> #define unll unsigned long ...
- hashmap的遍历方法
How to iterate over the entries of a Map? What is the order of iteration - if you are just using Map ...
- BZOJ5137[Usaco2017 Dec]Standing Out from the Herd
看了半天题 不知道怎么用SAM维护 于是借(chao)鉴(xi)的一发神犇的 只要判断这个子串之前被标记的记号(也就是他属于第几个串)和这次转移到的是否相同 如果不同就说明该子串属于多个串 直接标记- ...
- ZOJ 2970 Faster, Higher, Stronger
F - Faster, Higher, Stronger Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld &am ...
- wikioi 3130 CYD刷题(背包)
题目描述 Description 下午,CYD要刷题了,已知CYD有N题可刷,但他只有M分钟的时间,而且他的智慧值为Q,也就是说他只能做出难度小于等于Q的题目.已知每题可得积分Ai,需花费时间Bi,难 ...