当前位置:   article > 正文

Python使用OpenCV实现人脸识别_用python代码进行人脸识别完整代码

用python代码进行人脸识别完整代码

Python使用OpenCV实现人脸识别

环境准备:opencv 以及 opencv拓展模块,numpy

pip install opencv-python
pip install opencv-contrib-python安装扩展模块
  • 1
  • 2

整体流程

在这里插入图片描述

面部检测函数

face_detect_demo函数接收一张图片作为输入,将其转换为灰度图像,并使用Haar级联分类器在图像中检测面部。

def face_detect_demo(image):
    # 将图像转换为灰度图像
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # 使用OpenCV的级联分类器加载Haar级联文件
    face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    
    # 使用detectMultiScale方法检测图像中的面部
    faces = face_detector.detectMultiScale(gray, 1.2, 6)
    
    # 如果未检测到面部,则返回None
    if (len(faces) == 0):
        return None, None
    
    # 假设只有一张脸,获取面部的坐标和宽度高度
    (x, y, w, h) = faces[0]
    
    # 返回图像的面部部分和面部的坐标
    return gray[y:y + w, x:x + h], faces[0]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

如果检测到面部,它会返回灰度面部和其边界框。如果未检测到面部,则返回None。

文件处理函数

ReFileName函数读取给定目录中的图片,对每张图片进行面部检测,将检测到的面部调整为固定大小,并返回这些面部的列表。

def ReFileName(dirPath):
    # 初始化一个空列表来存储面部
    faces=[]
    
    # 遍历给定目录中的文件
    for file in os.listdir(dirPath):
        # 检查是否是文件
        if os.path.isfile(os.path.join(dirPath, file)) == True:
            # 获取文件的基本名称
            c= os.path.basename(file)
            # 构造文件的完整路径名
            name = dirPath + '\\' + c
            # 读取图像文件
            img = cv2.imread(name)
            # 在图像中检测面部
            face, rect = face_detect_demo(img)
            # 如果检测到面部,将其添加到面部列表中
            if face is not None:
                # 将检测到的面部调整为固定大小
                face=cv2.resize(face,(300,300),interpolation = cv2.INTER_AREA)
                faces.append(face)
    # 返回面部列表
    return faces
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

训练识别器

最后,我们从两个不同的目录读取两个人(杨幂和刘亦菲)的图片。我们为这些图片分配标签(0代表杨幂,1代表刘亦菲),将它们合并成训练数据和标签,然后打乱它们。然后我们使用这些数据训练一个LBPH(Local Binary Patterns Histograms)面部识别器,并将训练好的模型保存到’train.yml’。

# 杨幂的照片路径
dirPathyangmi = r"D:\\PythonProject\\Face_Recognition\\yangmi"
# 调用ReFileName函数处理杨幂的照片,并获取面部列表
yangmi=ReFileName(dirPathyangmi)
# 为杨幂的照片创建标签,全部标记为0
labelyangmi=np.array([0 for i in range(len(yangmi))])

# 刘亦菲的照片路径
dirPathliuyifei = r"D:\\PythonProject\\Face_Recognition\\liuyifei"
# 调用ReFileName函数处理刘亦菲的照片,并获取面部列表
liuyifei=ReFileName(dirPathliuyifei)
# 为刘亦菲的照片创建标签,全部标记为1
labelliuyifei=np.array([1 for i in range(len(liuyifei))])

# 将两个人的面部列表合并成一个数组
x=np.concatenate((yangmi,liuyifei),axis=0)
# 将两个人的标签列表合并成一个数组
y=np.concatenate((labelyangmi,labelliuyifei),axis=0)

# 创建一个索引列表,长度与标签数组相同
index = [i for i in range(len(y))]
# 设置随机数种子,确保每次打乱索引的结果都一样
np.random.seed(1)
# 打乱索引列表
np.random.shuffle(index)
# 根据打乱的索引重新排列训练数据和标签
train_data = x[index]
train_label = y[index]

# 创建一个LBPH面部识别器对象
recognizer = cv2.face.LBPHFaceRecognizer_create()
# 使用训练数据和标签训练识别器
recognizer.train(train_data, train_label)
# 将训练好的识别器保存到文件'train.yml'
recognizer.write('train.yml')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

导入训练结果

我们导入训练结果,并读取前文训练的结果。

# 创建一个LBPH面部识别器对象
recognizer = cv2.face.LBPHFaceRecognizer_create()

# 从文件'train.yml'中读取训练好的识别器
recognizer.read('train.yml')
  • 1
  • 2
  • 3
  • 4
  • 5

绘制矩形和文本

我们定义了两个函数来在图像上绘制矩形和文本。draw_rectangle函数根据给定的人脸(x,y)坐标和宽度高度在图像上绘制矩形,而draw_text函数则在给定的人脸(x,y)坐标处写出人名。

def draw_rectangle(img, rect):
    (x, y, w, h) = rect
    cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 0), 2)

def draw_text(img, text, x, y):
    cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

预测函数

最后,我们定义了一个预测函数。这个函数接收一张图片作为输入,检测图片中的人脸,并预测人脸的标签。然后,它在检测到的脸部周围画一个矩形,并标出预测的人名。

# 定义人物标签
facelabel = ["yangmi", "liuyifei"]

def predict(image):
    # 创建图像的副本,以保留原始图像
    img = image.copy()
    # 在图像中检测人脸
    face, rect = face_detect_demo(img)
    # 将检测到的人脸调整为固定大小
    face=cv2.resize(face,(300,300),interpolation = cv2.INTER_AREA)
    # 预测人脸的标签和可信度
    label = recognizer.predict(face)
    # 如果可信度小于等于50
    if label[1]<=50:
        # 获取对应标签的人名
        label_text = facelabel[label[0]]
        # 在检测到的人脸周围画一个矩形
        draw_rectangle(img, rect)
        # 标出预测的人名
        draw_text(img, label_text, rect[0], rect[1])
        # 返回预测后的图像
        return img
    else:
        # 在检测到的人脸周围画一个矩形
        draw_rectangle(img, rect)
        # 标出"not find"
        draw_text(img, "not find", rect[0], rect[1])
        # 返回预测后的图像
        return img
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

如果识别器对预测结果的可信度大于50,则我们假设没有找到匹配的人脸,并在图片上标注"not find"。

最后,我们读取一张测试图片,对其进行预测,并显示预测结果。

test_img = cv2.imread("test.jpg")
pred_img = predict(test_img)
cv2.imshow('result', pred_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

完整代码:

train.py

import os
from pickletools import uint8
import numpy as np
import cv2

#脸部检测函数
def face_detect_demo(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    faces = face_detector.detectMultiScale(gray, 1.2, 6) #图像缩放大小  影响检测质量
    # 如果未检测到面部,则返回原始图像
    if (len(faces) == 0):
        return None, None
    # 目前假设只有一张脸,xy为左上角坐标,wh为矩形的宽高
    (x, y, w, h) = faces[0]
    # 返回图像的脸部部分
    return gray[y:y + w, x:x + h], faces[0]

def ReFileName(dirPath):
    # 对目录下的文件进行遍历
    faces=[]
    for file in os.listdir(dirPath):
        # 判断是否是文件
        if os.path.isfile(os.path.join(dirPath, file)) == True:
           c= os.path.basename(file)
           name = dirPath + '\\' + c
           img = cv2.imread(name)
           # 检测脸部
           face, rect = face_detect_demo(img)
           # 我们忽略未检测到的脸部
           if face is not None:
               face=cv2.resize(face,(300,300),interpolation = cv2.INTER_AREA)#修改识别面部为固定大小,与后面检测面部大小一致
               # 将脸添加到脸部列表并添加相应的标签
               faces.append(face)
    return faces

#杨幂照读取
dirPathyangmi = r"D:\\PythonProject\\Face_Recognition\\yangmi"#文件路径
yangmi=ReFileName(dirPathyangmi)#调用函数
labelyangmi=np.array([0 for i in range(len(yangmi))])#标签处理
#刘亦菲照读取
dirPathliuyifei = r"D:\\PythonProject\\Face_Recognition\\liuyifei"#文件路径
liuyifei=ReFileName(dirPathliuyifei)#调用函数
labelliuyifei=np.array([1 for i in range(len(liuyifei))])#标签处理
#拼接并打乱数据特征和标签
x=np.concatenate((yangmi,liuyifei),axis=0)
y=np.concatenate((labelyangmi,labelliuyifei),axis=0)

index = [i for i in range(len(y))] # test_data为测试数据
np.random.seed(1)
np.random.shuffle(index) # 打乱索引
train_data = x[index]
train_label = y[index]

#分类器
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.train(train_data, train_label)
# 保存训练数据
recognizer.write('train.yml')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

match.py

import cv2
#人脸检测函数
def face_detect_demo(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    faces = face_detector.detectMultiScale(gray, 1.2, 6)
    # 如果未检测到面部,则返回原始图像
    if (len(faces) == 0):
        return None, None
    # 目前假设只有一张脸,xy为左上角坐标,wh为矩形的宽高
    (x, y, w, h) = faces[0]
    # 返回图像的脸部部分
    return gray[y:y + w, x:x + h], faces[0]


#导入训练结果
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('train.yml')#读取前文训练的结果


# 根据给定的人脸(x,y)坐标和宽度高度在图像上绘制矩形
def draw_rectangle(img, rect):
    (x, y, w, h) = rect#矩形框
    cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 0), 2)

# 根据给定的人脸(x,y)坐标写出人名
def draw_text(img, text, x, y):
    cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)

# 此函数识别图像中的人物并在脸部周围绘制一个矩形及其人名
facelabel = ["yangmi", "liuyifei"]#人物名
def predict(image):
    # 生成图像的副本,保留原始图像
    img = image.copy()
    # 检测人脸区域
    face, rect = face_detect_demo(img)#face_detect_demo前面的人脸检测函数
    #print(rect)=[x,y,w,h]
    # 预测人脸名字
    face=cv2.resize(face,(300,300),interpolation = cv2.INTER_AREA)

    label = recognizer.predict(face)
    print(label)#label[0]为名字,label[1]可信度数值越低,可信度越高(
    if label[1]<=50:
        # 获取由人脸识别器返回的相应标签的人名
        label_text = facelabel[label[0]]

        # 在检测到的脸部周围画一个矩形
        draw_rectangle(img, rect)
        # 标出预测的人名
        draw_text(img, label_text, rect[0], rect[1])
        # 返回预测的图像
        return img
    else:
        # 在检测到的脸部周围画一个矩形
        draw_rectangle(img, rect)
        # 标出预测的人名
        draw_text(img, "not find", rect[0], rect[1])
        # 返回预测的图像
        return img

test_img = cv2.imread("test.jpg")
#执行预测
pred_img = predict(test_img)
cv2.imshow('result', pred_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/116060?site
推荐阅读
相关标签
  

闽ICP备14008679号