人脸识别就是找到一个可以表征每个人脸特征的模型,在进行识别是先提取当人脸的特征,再从已有的特征集这种找到最为接近的人脸样本,从而得到当前人脸的标签。 在如今的世界,人脸识别也变得越来越重要,应用越来越广泛,比如人脸识别可用于身份认证、摄影、支付、视频等领域。 在Opencv中提供了LPBH、EigenFishfaces和FisherFace三种人脸识别方法。
一、LBPH算法
LBPH所使用的模型基于LBP算法,其基本原理是将图像(灰度图,如果是彩色图则先转为灰度图)中某个像素点的值与其最临近的3×3邻域8个像素点的值逐一比较,如果该点像素值大于其邻近点的像素值,则得到0,反之,如果该点像素值小于其临界点的像素值,则得到1,最后,将该像素点与其周围8个像素点比较所得到的0和1组合,并依次排列,得到一个8位的二进制序列,将该二进制序列转换为十进制数作为该像素点的LBP值。
上述是原始的LBPH 算法,后续又有人将其改进,将3×3邻域拓展到任意区域,并用圆形代替了正方形邻域,改进后的 LBP 算子允许在半径为 R 的圆形邻域内有任意多个像素点。从而得到了诸如半径为R的圆形区域内含有P个采样点的LBP算子。 以下是LBPH特征提取的C++代码:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <opencv2\imgproc\types_c.h>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat src, gray_src;
src = imread("E:\\picture\\1.png");
if (src.empty())
{
cout << "could not read image ... " << endl;
getchar();
return -1;
}
imshow("input image", src);
cvtColor(src, gray_src, CV_BGR2GRAY);
int width = gray_src.cols;
int height = gray_src.rows;
Mat lbpImage = Mat::zeros(height - 2, width - 2, CV_8SC1);
for (int row = 1; row < height - 1; row++)
{
for (int col = 1; col < width - 1; col++)
{
uchar c = gray_src.at<uchar>(row, col);
uchar code = 0;
code |= (gray_src.at<uchar>(row - 1, col - 1) > c) << 7;
code |= (gray_src.at<uchar>(row - 1, col ) > c) << 6;
code |= (gray_src.at<uchar>(row - 1, col + 1) > c) << 5;
code |= (gray_src.at<uchar>(row , col + 1) > c) << 4;
code |= (gray_src.at<uchar>(row + 1, col + 1) > c) << 3;
code |= (gray_src.at<uchar>(row + 1, col ) > c) << 2;
code |= (gray_src.at<uchar>(row + 1, col - 1) > c) << 1;
code |= (gray_src.at<uchar>(row , col - 1) > c) << 0;
lbpImage.at<uchar>(row - 1, col - 1) = code;
}
}
imshow("output image", gray_src);
waitKey(0);
return 0;
}
如果将以上得到的LBP图直接用于人脸识别,其实和不提取LBP特征没什么区别,在实际的LBP应用中一般采用LBPH特征谱的统计直方图作为特征向量进行分类识别,并且可以将一幅图片划分为若干的子区域,对每个子区域内的每个像素点都提取LBP特征,然后,在每个子区域内建立LBP特征的统计直方图。
如此一来,每个子区域,就可以用一个统计直方图来进行描述,整个图片就由若干个统计直方图组成,这样做的好处是在一定范围内减小图像没完全对准而产生的误差,分区的另外一个意义在于我们可以根据不同的子区域给予不同的权重,比如说我们认为中心部分分区的权重大于边缘部分分区的权重,意思就是说中心部分在进行图片匹配识别时的意义更为重大。
例如:一幅100×100像素大小的图片,划分为10×10=100个子区域(可以通过多种方式来划分区域),每个子区域的大小为10×10像素;在每个子区域内的每个像素点,提取其LBP特征,然后,建立统计直方图;这样,这幅图片就有10×10个子区域,也就有了10×10个统计直方图,利用这10×10个统计直方图,就可以描述这幅图片了。之后,我们利用各种相似性度量函数,就可以判断两幅图像之间的相似性了。关于相似度度量函数,跟人脸识别一样有很多方法,在这就不逐一分析了,知道LBPH的原理就可以。
以下是LBPH人脸识别的Python实现
import cv2 as cv
import numpy as np
images = []
images.append(cv.imread("E:/picture/11.png", cv.IMREAD_GRAYSCALE))
images.append(cv.imread("E:/picture/12.png", cv.IMREAD_GRAYSCALE))
images.append(cv.imread("E:/picture/13.png", cv.IMREAD_GRAYSCALE))
images.append(cv.imread("E:/picture/21.png", cv.IMREAD_GRAYSCALE))
images.append(cv.imread("E:/picture/22.png", cv.IMREAD_GRAYSCALE))
images.append(cv.imread("E:/picture/23.png", cv.IMREAD_GRAYSCALE))
labels = [0,0,0,1,1,1]
recognizer1 = cv.face.FisherFaceRecognizer_create()
recognizer2 = cv.face.EigenFaceRecognizer_create()
recognizer1.train(images,np.array(labels))
recognizer2.train(images,np.array(labels))
predict_image1 = cv.imread("E:/picture/1.png",cv.IMREAD_GRAYSCALE)
predict_image2 = cv.imread("E:/picture/2.png",cv.IMREAD_GRAYSCALE)
label1,configence1 = recognizer1.predict(predict_image1)
label2,configence2 = recognizer2.predict(predict_image2)
print("label1= ",label1)
print("confidence1= ",configence1)
print("label2= ",label2)
print("confidence2= ",configence2)
二、用FisherFace与EignFaces算法进行人脸识别
|