人脸识别经典算法一 特征脸方法(Eigenface)

  • Post category:Python

人脸识别经典算法-特征脸方法(Eigenface)

简介

特征脸方法,也称为Eigenface,是一种常用的基于PCA的人脸识别算法。该算法的中心思想是:通过PCA降维,将人脸图像转换成一组基本特征向量,然后用这些特征向量来对输入图像进行表示与匹配,以实现人脸识别。特征脸方法是人脸识别领域的经典算法之一,具有结构简单、易于实现、识别准确度较高的优点。

实现过程

  1. 预处理

对训练集中的所有人脸图像进行预处理,包括:将所有的图像转换为灰度图像、去掉噪声、将每个图像缩放为相同大小。每个图像可以表示为一个$(m \times n)$的矩阵,其中$m$和$n$分别表示图像的宽度和高度。

  1. PCA降维

将预处理后的所有人脸图像按照一定顺序堆叠在一个大矩阵中,矩阵的每一列代表一个图像。对该大矩阵做PCA分解,得到一组特征向量,这些特征向量被称为特征脸,是一组基本人脸图像。通过保留部分主成分,可以实现对原始数据的降维。我们通常只保留最大的$k$个特征向量来进行降维。

  1. 训练模型

对于每个人脸图像,将其用$k$个特征向量进行表示并存储。每个人脸图像就可以表示成一个$k$维向量,这个向量就是该人脸的特征向量。对于训练集中的每个人,都可以得到其对应的特征向量。训练模型即将所有人的特征向量放到同一个矩阵中保存。

  1. 人脸识别

当新的图像输入时,将其先进行预处理,然后用与训练集中相同的方法,将输入图像表示为一个$k$维向量。然后计算该向量与训练集中每个人脸图像特征向量之间的欧几里得距离,找到最接近的那个人的特征向量,即可得到其识别结果。示例如下:

示例1

首先,我们在Python中载入所需库:

import numpy as np
import cv2
import os
import glob

然后,读入人脸图像并对其进行预处理:

# 读入图像并对其进行预处理
def readData(path):
    train_faces=[]
    ids=[]
    for image_path in glob.glob(path):
        image=cv2.imread(image_path,0)
        train_faces.append(cv2.resize(image,(64,64)))
        ids.append(int(os.path.split(image_path)[-1].split(".")[1]))
    return train_faces,np.array(ids),np.array(train_faces).shape[1:]

接下来,我们进行PCA降维:

# PCA降维
def pcaEigenface(train_faces,k):
    mean, eigenvectors=cv2.PCACompute(train_faces,np.array([]), maxComponents=k)
    face_space=[]
    for face in train_faces:
        face_projected=np.transpose(eigenvectors)*np.transpose(face.flatten()-mean.flatten())
        face_space.append(face_projected.flatten())
    face_space=np.asarray(face_space)
    return face_space, eigenvectors, mean

最后,我们用C++编写程序来进行人脸识别:

// 人脸图像预处理
cv::Mat preProcess(cv::Mat image)
{
    cv::Mat gray_image, resized_image;
    cv::cvtColor(image, gray_image, cv::COLOR_BGR2GRAY);
    cv::resize(gray_image, resized_image, cv::Size(64, 64));
    return resized_image;
}

// 人脸识别
int recognize(cv::Mat test_image, cv::Mat mean, cv::Mat eigenvectors, std::vector<int> labels, std::vector<cv::Mat> face_space)
{
    cv::Mat test_face=preProcess(test_image);
    cv::Mat test_projected=eigenvectors*(test_face-mean).t();
    test_projected=test_projected.t().reshape(1, 1);

    std::vector<double> distances;
    for(int i=0;i<face_space.size();i++)
    {
        double dist=cv::norm(face_space[i],test_projected);
        distances.push_back(dist);
    }

    int min_index=0;
    double min_value=distances[min_index];
    for(int i=1;i<distances.size();i++)
    {
        if(distances[i]<min_value)
        {
            min_index=i;
            min_value=distances[i];
        }
    }

    return labels[min_index];
}

示例2

我们可以将特征脸方法与Haar face detection技术结合起来,在图像中检测出人脸,然后判断其属于哪个人。示例如下:

首先,我们用Haar face detection技术在图像中检测出人脸:

face_cascade=cv2.CascadeClassifier('path/to/haarcascade_frontalface_default.xml')
image=cv2.imread('path/to/test-image.jpg')
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
faces=face_cascade.detectMultiScale(gray,1.1,4)

然后,对于每个检测出来的人脸,使用特征脸方法进行识别:

for (x,y,w,h) in faces:
    face_roi=image[y:y+h,x:x+w]
    id=recognize(face_roi,mean,eigenvectors,labels,face_space)
    cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
    font=cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(image,subjects[id-1],(x,y-5),font,0.8,(0,255,0),2)

结语

特征脸方法是一种经典的基于PCA的人脸识别算法。通过PCA降维,将人脸图像转换成一组基本特征向量,然后用这些特征向量来对输入图像进行表示与匹配,以实现人脸识别。特征脸方法具有结构简单、易于实现、识别准确度较高的优点。