目录

简介

一、人脸识别

二、LBPH 算法

1.步骤1

2.步骤2

三、EigenFaces算法

四、FisherFaces算法


简介

人脸识别是计算机视觉领域中聚焦 “人脸” 这一生物特征的核心技术,通过计算机算法自动提取人脸图像中的关键特征(如五官轮廓、纹理等),并与数据库中的人脸信息进行匹配,实现身份识别与验证。​

其核心流程可概括为三步:人脸检测(从图像 / 视频中定位人脸区域)、特征提取(将人脸转化为可计算的数字特征向量)、特征匹配(对比特征向量判断身份是否一致)。​

该技术已广泛应用于安防监控(如人脸门禁)、移动终端(如手机解锁)、公共服务(如身份核验)等场景,是生物识别技术中落地最成熟、应用最广泛的方向之一,也是计算机视觉进阶学习中连接理论与实际应用的重要模块。

一、人脸识别

实现人脸识别主要流程:

特征识别器

Opencv提供了三种用于识别人脸的特征提取算法。分别是 LBPH 算法、EigenFaces 算法、FisherFaces 算法。下面将详细介绍一下这三种方法。

二、LBPH 算法

LBPH(Local Binary Patterns Histogram,局部二值模式直方图)算法使用的模型基于LBP(Local Binary Pattern,局部二值模式)算法。LBP 算法最早是被作为一种有效的纹理描述算提出的,因在表述图像局部纹理特征方面效果出众而得到广泛应。

LBPH 实现步骤

1、以每个像素为中心,判断与周围像素灰度值大小关系,对其进行二进制编码,从而获得整幅图像的LBP编码图像;

2、再将LBP图像分为n个区域,获取每个区域的LBP编码直方图,继而得到整幅图像的LBP编码直方图。 通过比较不同人脸图像LBP编码直方图达到人脸识别的目的,其优点是不会受到光照、缩放、旋转和平移的影响。

1.步骤1

缩放

为了得到不同尺度下的纹理结构,可以使用圆形邻域,将计算扩大到任意大小的邻域内。圆形邻域可以用(P,R)表示,其中,P表示圆形邻域内参与运算的像素点个数,R 表示圆形邻域的半径。

旋转和平移

1、将中心点像素作为圆心,将周围的像素点按照顺时针方向依次移动一个位置。

2、再计算所有图像的LBP值,取其中最小值作为最终的值  

2.步骤2

将LBP图像分为个n区域,获取每个区域的LBP编码直方图,继而得到整幅图像的LBP编码直方图。

LBP特征与Haar特征很相似,都是图像的灰度变化特征。

步骤1计算后的值:

代码实现


import cv2
import numpy as np
# 提前训练的人脸照片
images = []
images.append(cv2.imread(filename='zms1.png', flags=cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread(filename='zms2.png', flags=cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread(filename='zms3.png', flags=cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread(filename='nm1.png', flags=cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread(filename='nm2.png', flags=cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread(filename='nm3.png', flags=cv2.IMREAD_GRAYSCALE))
labels = [0, 0, 0, 1, 1, 1]
dic = {0: '詹姆斯', 1: '浓眉', -1: '无法识别'}
predict_image = cv2.imread(filename='zms4.png', flags=cv2.IMREAD_GRAYSCALE)  # 待识别人脸
# cv2.face.LBPHFaceRecognizer_create(radius=None, neighbors=None, grid_x=None, grid_y=None, threshold=None)
# 功能: 创建一个LBPH的人脸特征识别器
# radius: 可选参数 圆形局部二进制模式的半径, 建议使用默认值
# neighbors: 可选参数, 圆形局部二进制模式的采样点数目, 建议使用默认值
# grid_x: 可选参数 水平方向上的的单元格数, 默认值为8, 即将LB特征图在水平方向上划分为8个单元。
# grid_y: 可选参数 垂直方向上的的单元格数, 默认值为8, 建议使用默认值, 若grid_x和grid_y都为默认值
# 则表示特征图划分为8*8大小, 统计8*8大小的直方图。
# threshold: 可选参数 人脸识别时使用的阈值, 建议使用默认值
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=80)
# 函数train用给定的数据和相关标签训练生成的实例模型。该函数的语法格式为
# None = 识别器对象.train( src, labels )
# 其中, 各参数的含义如下:
# 。src: 训练图像, 用来学习的人脸图像
# 。labels: 标签, 人脸图像对应的标签。
recognizer.train(images, np.array(labels))
# 函数predict()对一个待识别人脸图像进行判断, 寻找与当前图像距离最近的人脸图像。
# 与哪幅人脸图像距离最近, 就将当前待测图像标注为该人脸图像对应的标签。
# 若待识别人脸图像与所有人脸图像的距离都大于特定的距离值(阈值), 则认为没有找到对应的结果,
# 参数与返回值的含义如下:
# ·src: 需要识别的人脸图像
# label: 返回的识别结果标签, 返回-1表示无法识别当前人脸。
# confidence: 返回的置信度评分, 用来衡量识别结果与原有模型之间的距离,
# 评分越小表示匹配越高, 但是若高于80, 则认为识别结果与原有模型差距大。
label, confidence = recognizer.predict(predict_image)
print('这人是:', dic[label])
print('置信度:', confidence)

三、EigenFaces算法

Eigenfaces是在人脸识别的计算机视觉问题中使用的一组特征向量的名称,Eigenfaces是基于PCA(主成分分析)算法实现的。

PCA(主成分分析)算法

主成分分析(PCA)是一种矩阵的压缩算法,在减少矩阵维数的同时尽可能的保留原矩阵的信息,简单来说就是将 n×m的矩阵转换成n×k的矩阵,仅保留矩阵中所存在的主要特性,从而可以大大节省空间和数据量。

机器学习之PCA降维

代码实现

import cv2
import numpy as np
images=[]  # 读取训练图像, 注意:图片大小需要一致
a=cv2.imread('zms4.png', 0)
a=cv2.resize(a, (120,180))
b=cv2.imread('zms3.png', 0)
b=cv2.resize(b, (120,180))
c=cv2.imread('nm1.png', 0)
c=cv2.resize(c, (120,180))
d=cv2.imread('nm2.png', 0)
d=cv2.resize(d, (120,180))
images.append(a)
images.append(b)
images.append(c)
images.append(d)

labels=[0, 0, 1, 1]

pre_image=cv2.imread('zms1.png', 0)
pre_image=cv2.resize(pre_image, (120,180))

# 创建Eigenfaces人脸识别器
# cv2.face.EigenFaceRecognizer_create(num_components=None, threshold=None)
# 作用:创建一个EigenFace的人脸特征识别器
# num_components: 在PCA中要保留的分量个数。当然,该参数值通常要根据输入数据来具体确定,
#                 并没有一定取值。一般程序中,取80即可 (降维成多少个特征)
# threshold: 进行人脸识别所采用的阈值
recognizer = cv2.face.EigenFaceRecognizer_create(threshold=5000)  # threshold=5000  4000
# 使用训练数据(images和labels)来训练识别器
# 函数FaceRecognizertrain用给定的数据和相关标签训练生成的实例模型。该函数的语法格式为
#None = cv2.faceFaceRecognizer.train(src, labels )
#参数的含义如下:
#   src: 训练图像,用来学习的人脸图像
#   labels: 标签,人脸图像对应的标签。
recognizer.train(images, np.array(labels))
# 对预测图像(pre_image)进行人脸识别预测
# confidence: 大小介于0到20000,只要低于5000都被认为是可靠的结果。
label,confidence = recognizer.predict(pre_image)
dic={0: '詹姆斯', 1: '浓眉'}
print('这人是:', dic[label])
print('置信度为:', confidence)
aa=cv2.putText(cv2.imread('zms1.png').copy(), dic[label], (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
    0.9, (0, 0, 255), 2)
cv2.imshow('xx',aa)
cv2.waitKey(0)

我们都知道在opencv中对于中文不太友好,有时候会出现乱码现象,而在puttext函数也是如此,我们想在图片上加上图片人物的识别名称,中文的话也会乱码,但是是有解决办法的。然后我们对这个代码进行修改让其能显示中文。


import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont

images=[]  # 读取训练图像, 注意:图片大小需要一致
a=cv2.imread('zms4.png', 0)
a=cv2.resize(a, (120,180))
b=cv2.imread('zms3.png', 0)
b=cv2.resize(b, (120,180))
c=cv2.imread('nm1.png', 0)
c=cv2.resize(c, (120,180))
d=cv2.imread('nm2.png', 0)
d=cv2.resize(d, (120,180))
images.append(a)
images.append(b)
images.append(c)
images.append(d)

labels=[0, 0, 1, 1]

pre_image=cv2.imread('zms1.png', 0)
pre_image=cv2.resize(pre_image, (120,180))

# 创建Eigenfaces人脸识别器
recognizer = cv2.face.EigenFaceRecognizer_create(threshold=5000)
recognizer.train(images, np.array(labels))
label,confidence = recognizer.predict(pre_image)
dic={0: '詹姆斯', 1: '浓眉'}
print('这人是:', dic[label])
print('置信度为:', confidence)

# 读取图像并转换为PIL格式以显示中文
img = cv2.imread('zms1.png')
# 转换颜色空间(BGR转RGB)
pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# 创建绘制对象
draw = ImageDraw.Draw(pil_img)
# 加载中文字体(根据系统调整路径)
font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 24)  # Windows系统

# 绘制中文
draw.text((10, 30), dic[label], font=font, fill=(255, 0, 0))  # 红色文字
# 转换回OpenCV格式
aa = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)

cv2.imshow('xx', aa)
cv2.waitKey(0)
cv2.destroyAllWindows()

四、FisherFaces算法

PCA方法是EigenFaces人脸识别的核心,但是其具有明显的缺点,在操作过程中会损失许多人脸的特征信息。因此在某些特殊的情况下,如果损失的信息刚好是用于分类的关键信息,必然导致结果预测错误。

Fisherfaces采用LDA(Linear Discriminant Analysis,线性判别分析)实现人脸识别。 其基本原理:在低维表示下,首先将训练集样本集投影到一条直线A上,让投影后的点满足: 同类间的点尽可能地靠近 异类间的点尽可能地远离

import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont


def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
    """向图片中添加中文"""
    if (isinstance(img, np.ndarray)):  # 判断是否OpenCV图片类型
        img = Image.fromarray(
            cv2.cvtColor(
                img,
                cv2.COLOR_BGR2RGB))  # 实现array到image的转换
    draw = ImageDraw.Draw(img)  # 在img图片上创建一个绘图的对象
    # 字体的格式
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
    draw.text(position, text, textColor, font=fontStyle)  # 绘制文本
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)  # 转换回OpenCV格式


def image_re(image):
    a = cv2.imread(image, flags=0)
    a = cv2.resize(a, dsize=(120, 180))
    images.append(a)


images = []
image_re('zms1.png')
image_re('zms2.png')
image_re('nm1.png')
image_re('nm2.png')

labels = [0, 0, 1, 1]

pre_image = cv2.imread(filename='zms3.png', flags=0)  # 读取待识别图像
pre_image = cv2.resize(pre_image, dsize=(120, 180))

# cv2.face.FisherFaceRecognizer_create( [, num_components[, threshold]] )
# 作用:创建一个FisherFace的人脸特征识别器
# num_components: 进行线性判别分析时保留的成分数量。可以采用默认值"0",让函数自动设置合适的成分数量。
# threshold: 进行识别时所用的阈值。如果最近的距离比设定的阈值threshold还要大,函数会返回"-1"。
recognizer = cv2.face.FisherFaceRecognizer_create(threshold=5000)
# 函数FaceRecognizertrain用给定的数据和相关标签训练生成的实例模型。该函数的语法格式为
# None = cv2.faceFaceRecognizer.train(src, labels )
# 参数的含义如下:
#  src: 训练图像,用来学习的人脸图像
#  labels: 标签,人脸图像对应的标签。
recognizer.train(images, np.array(labels))
# confidence: 大小介于0到20000,只要低于5000都被认为是可靠的结果。
label, confidence = recognizer.predict(pre_image)
dic = {0: '詹姆斯', 1: '浓眉', -1: '无法识别'}
print('这人是:', dic[label])
print('置信度为:', confidence)
image = cv2AddChineseText(
    cv2.imread('zms3.png').copy(), dic[label], position=(
        30, 10), textColor=(
            255, 0, 0))  # 输出中文
cv2.imshow('xx', image)
cv2.waitKey(0)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐