cv2 EigenFace(特征脸)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/github_39611196/article/details/85055581

本文主要介绍cv2模块中EigenFace(特征脸),EigenFace可用来实现人脸识别。

参考自:https://blog.csdn.net/loveliuzz/article/details/73810334

cv2中face子模块目前支持的算法有:

        (1)主成分分析(PCA)——Eigenfaces(特征脸)——函数:cv2.face.EigenFaceRecognizer_create()

PCA:低维子空间是使用主元分析找到的,找具有最大方差的哪个轴。

缺点:若变化基于外部(光照),最大方差轴不一定包括鉴别信息,不能实行分类。

        (2)线性判别分析(LDA)——Fisherfaces(特征脸)——函数: cv2.face.FisherFaceRecognizer_create()

LDA:线性鉴别的特定类投影方法,目标:实现类内方差最小,类间方差最大。

        (3)局部二值模式(LBP)——LocalBinary Patterns Histograms——函数:cv2.face.LBPHFaceRecognizer_create()

PCA和LDA采用整体方法进行人脸辨别,LBP采用局部特征提取,除此之外,还有的局部特征提取方法为:

盖伯小波(Gabor Waelets)和离散傅里叶变换(DCT)。

示例代码:

import cv2
import sys
import os
import numpy as np


# 从图像列表创建数据矩阵
def createDataMatrix(images):
    print('Creating data matrix', end='...')
    '''
    在一个数据矩阵中为所有图像分配空间。
   数据矩阵的大小是
  
   (w * h * 3,numImages)
     其中:
   w:数据集中图像的宽度。
   h:数据集中图像的高度。
   3:3颜色通道。
    '''
    numImages = len(images)
    sz = images[0].shape
    data = np.zeros((numImages, sz[0] * sz[1] * sz[2]), dtype=np.float32)

    for i in range(0, numImages):
        image = images[i].flatten()
        data[i, :] = image

    print('DONE')
    return data


# 从文件目录读取图片
def readImages(path):
    print('Reading images from ' + path, end='...')
    # 创建一个图片数组
    images = []
    # 列出目录中的所有文件,逐个从文本文件中读取点
    for filePath in sorted(os.listdir(path)):
        fileExt = os.path.splitext(filePath)[1]
        if fileExt in ['.jpg', '.jpeg']:
            # 将读取的图片添加到图片数组
            imagePath = os.path.join(path, filePath)
            im = cv2.imread(imagePath)

            if im is None:
                print('image:{} not read properly'.format(imagePath))
            else:
                # 将图片转换为浮点类型
                im = np.float32(im) / 255.0
                # 将图片添加到数组中
                images.append(im)
                # 翻转图片
                imFlip = cv2.flip(im, 1)
                # 将翻转后的图片添加到数组中
                images.append(imFlip)

    numImages = len(images) / 2
    # 当没有图片时退出
    if numImages == 0:
        print('No images found')
        sys.exit(0)

    print(str(numImages) + ' files read.')
    return images


# 将加权的eigen faces添加到mean faces
def createNewFace(*args):
    # 从mean image开始
    output = averageFace

    # 将权值添加到Eigen Faces
    for i in range(0, NUM_EIGEN_FACES):
        '''
        OpenCV不允许滑块值为负数。
        所以使用weight = sliderValue  -  MAX_SLIDER_VALUE / 2
        '''
        sliderValues[i] = cv2.getTrackbarPos("Weight" + str(i), 'Trackbars')
        weight = sliderValues[i] - MAX_SLIDER_VALUE / 2
        output = np.add(output, eigenFaces[i] * weight)

    # 用2x大小显示结果
    output = cv2.resize(output, (0, 0), fx=2, fy=2)
    cv2.imshow('Result', output)


#     cv2.imwrite('result.jpg', output)


def resetSliderValues(*args):
    for i in range(0, NUM_EIGEN_FACES):
        cv2.setTrackbarPos('Weight' + str(i), 'Trackbars', int(MAX_SLIDER_VALUE / 2))
    createNewFace()


# EigenFaces的数量
NUM_EIGEN_FACES = 10

# 最大的权值
MAX_SLIDER_VALUE = 255

# 图片路径
dirName = 'images'

# 读取图片
images = readImages(dirName)

# 为PCA创建数组矩阵
data = createDataMatrix(images)

# 从创建的图像堆栈中计算特征向量(eigenvectors)
print('Calculating PCA ', end='...')
mean, eigenVectors = cv2.PCACompute(data, mean=None, maxComponents=NUM_EIGEN_FACES)
print('DONE')

#  images 的大小
sz = images[0].shape
averageFace = mean.reshape(sz)

eigenFaces = []

for eigenVector in eigenVectors:
    eigenFace = eigenVector.reshape(sz)
    eigenFaces.append(eigenFace)

# 创建一个窗口用于显示mean face
cv2.namedWindow("Result", cv2.WINDOW_AUTOSIZE)
# 显示结果
output = cv2.resize(averageFace, (0, 0), fx=2, fy=2)
cv2.imshow('Result', output)
# cv2.imwrite('result1.jpg', output)

sliderValues = []
# 创建Trackbars
for i in range(0, NUM_EIGEN_FACES):
    sliderValues.append(MAX_SLIDER_VALUE / 2)
    cv2.createTrackbar('Weight' + str(i), 'Trackbars', int(MAX_SLIDER_VALUE / 2), MAX_SLIDER_VALUE, createNewFace)

# 通过鼠标点击事件重置slider
cv2.setMouseCallback('Result', resetSliderValues)
print('''Usage:
Change the weights using the sliders
Click on the result window to reset sliders
Hit ESC to terminate program.''')

cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

猜你喜欢

转载自blog.csdn.net/github_39611196/article/details/85055581
今日推荐