人脸识别数据集的建立及应用

一、相关文件下载及配置

  1. dlib 的配置 参考python3+opencv3.4+dlib库(人脸识别)
  2. shape_predictor_68_face_landmarks.dat和dlib_face_recognition_resnet_model_v1.dat
    链接:https://pan.baidu.com/s/1r2ZesDtsfjQvk1gEqnxCyQ
    提取码:0614

二、数据集的建立

1.录入图片

1.代码
get_from_camera.py


# 通过电脑摄像头实现对自己人脸的抓取,并储存在个人人脸数据库中,以备后面进行识别
import os
import shutil

import dlib  # 人脸识别的库dlib

import numpy as np  # 数据处理的库numpy

import cv2  # 图像处理的库OpenCv

# dlib预测器

detector = dlib.get_frontal_face_detector()

predictor = dlib.shape_predictor('./file/shape_predictor_68_face_landmarks.dat')

# 创建cv2摄像头对象

cap = cv2.VideoCapture(0)

# cap.set(propId, value)

# 设置视频参数,propId设置的视频参数,value设置的参数值

cap.set(3, 480)

# 截图screenshoot的计数器

cnt_ss = 0

# 人脸截图的计数器

cnt_p = 0

# 保存

path = "./dataset/faces/"
name = input('my name:')
    # 如果路径存在则删除路径
path_save = os.path.join(path, name)
# 如果路径存在则删除路径
if os.path.isdir(path_save):
    shutil.rmtree(path_save)
# 创建文件夹
os.mkdir(path_save)


# cap.isOpened() 返回true/false 检查初始化是否成功
while cap.isOpened():

    # cap.read()

    # 返回两个值:

    #    一个布尔值true/false,用来判断读取视频是否成功/是否到视频末尾

    #    图像对象,图像的三维矩阵q

    flag, im_rd = cap.read()

    # 每帧数据延时1ms,延时为0读取的是静态帧

    kk = cv2.waitKey(1)

    # 取灰度

    img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY)

    # 人脸数rects

    rects = detector(img_gray, 0)

    # print(len(rects))

    # 待会要写的字体

    font = cv2.FONT_HERSHEY_SIMPLEX

    if len(rects) != 0:

        # 检测到人脸

        # 矩形框

        for k, d in enumerate(rects):

            # 计算矩形大小

            # (x,y), (宽度width, 高度height)

            pos_start = tuple([d.left(), d.top()])

            pos_end = tuple([d.right(), d.bottom()])

            # 计算矩形框大小

            height = d.bottom() - d.top()

            width = d.right() - d.left()

            # 根据人脸大小生成空的图像

            cv2.rectangle(im_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]), (0, 255, 255), 2)

            im_blank = np.zeros((height, width, 3), np.uint8)

            # 按下's'保存摄像头中的人脸到本地

            if kk == ord('s'):

                cnt_p += 1

                for ii in range(height):

                    for jj in range(width):
                        im_blank[ii][jj] = im_rd[d.top() + ii][d.left() + jj]

                # 存储人脸图像文件

                cv2.imwrite(path_save + "/img_face_" + str(cnt_p) + ".jpg", im_blank)

                print("写入本地:", path_save + "/img_face_" + str(cnt_p) + ".jpg")

        # 显示人脸数

        cv2.putText(im_rd, "faces: " + str(len(rects)), (20, 50), font, 1, (0, 0, 255), 1, cv2.LINE_AA)



    else:

        # 没有检测到人脸

        cv2.putText(im_rd, "no face", (20, 50), font, 1, (0, 0, 255), 1, cv2.LINE_AA)

    # 添加说明

    im_rd = cv2.putText(im_rd, "s: save face", (20, 400), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)

    im_rd = cv2.putText(im_rd, "q: quit", (20, 450), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)

    # 按下q键退出

    if kk == ord('q'):
        break

    # 窗口显示

    # cv2.namedWindow("camera", 0) # 如果需要摄像头窗口大小可调

    cv2.imshow("camera", im_rd)

# 释放摄像头

cap.release()

# 删除建立的窗口

cv2.destroyAllWindows()

  1. 运行:
    在这里插入图片描述
    输入标识(姓名等),以此为文件名,将录入的图片保存至该目录下。
    如以学号命名。
    在这里插入图片描述
    现在该目录下已经保存了我的20张图片。

2. 提取每张图片的特征值和特征均值

  1. 代码
    get_features.py
# 从人脸图像文件中提取人脸特征存入 CSV
# Features extraction from images and save into features_all.csv

# return_128d_features()          获取某张图像的128D特征
# compute_the_mean()              计算128D特征均值

import cv2
import os
import dlib
from skimage import io
import csv
import numpy as np
# 要读取人脸图像文件的路径
path_images_from_camera = "./dataset/faces/"

# Dlib 正向人脸检测器
detector = dlib.get_frontal_face_detector()

# Dlib 人脸预测器
predictor = dlib.shape_predictor("./file/shape_predictor_68_face_landmarks.dat")

# Dlib 人脸识别模型
# Face recognition model, the object maps human faces into 128D vectors
face_rec = dlib.face_recognition_model_v1("./file/dlib_face_recognition_resnet_model_v1.dat")

# 返回单张图像的 128D 特征

def return_128d_features(path_img, exc=None):
    img_rd = io.imread(path_img)
    img_gray = cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB)
    faces = detector(img_gray, 1)

    print("%-40s %-20s" % ("检测到人脸的图像 / image with faces detected:", path_img))
    # 因为有可能截下来的人脸再去检测,检测不出来人脸了
    # 所以要确保是 检测到人脸的人脸图像 拿去算特征
    if len(faces) != 0:
        shape = predictor(img_gray, faces[0])
        face_descriptor = face_rec.compute_face_descriptor(img_gray, shape)
        # 将每张图片识别的特征值保存
        # 全部保存至一个csv
        # with open("./dataset/csvs/face_features.csv", "a", newline="") as cfile:
        # 一张图一个csv
        with open("./dataset/csvs/img_face_" + str(exc) + ".csv", "a", newline="") as cfile:
            writer = csv.writer(cfile)
            writer.writerow(face_descriptor)

            print("特征值 / The features:", list(face_descriptor), '\n')

    else:
        face_descriptor = 0
        print("no face", '\n')

    return face_descriptor


# 将文件夹中照片特征提取出来, 写入 CSV
def return_features_mean_personX(path_faces_personX):
    features_list_personX = []
    exc=1
    photos_list = os.listdir(path_faces_personX)
    if photos_list:
        for i in range(len(photos_list)):
            # 调用return_128d_features()得到128d特征
            print("%-40s %-20s" % ("正在读的人脸图像 / image to read:", path_faces_personX + "/" + photos_list[i]))
            features_128d = return_128d_features(path_faces_personX + "/" + photos_list[i],exc)
            exc+=1
            #  print(features_128d)
            # 遇到没有检测出人脸的图片跳过
            if features_128d == 0:
                i += 1
            else:
                features_list_personX.append(features_128d)
    else:
        print("文件夹内图像文件为空 / Warning: No images in " + path_faces_personX + '/', '\n')

    # 计算 128D 特征的均值
    # N x 128D -> 1 x 128D
    if features_list_personX:
        features_mean_personX = np.array(features_list_personX).mean(axis=0)
    else:
        features_mean_personX = '0'

    return features_mean_personX


# 读取某人所有的人脸图像的数据
people = os.listdir(path_images_from_camera)
people.sort()

with open("./dataset/csvs/face_mean_features.csv", "w", newline="") as csvfile:
    writer = csv.writer(csvfile)
    for person in people:
        print("##### " + person + " #####")
        # Get the mean/average features of face/personX, it will be a list with a length of 128D
        features_mean_personX = return_features_mean_personX(path_images_from_camera + person)
        writer.writerow(features_mean_personX)
        print("特征均值 / The mean of features:", list(features_mean_personX))
        print('\n')
    print("所有录入人脸数据存入 / Save all the features of faces registered into: ./file/features_all2.csv")

  1. 结果
    在这里插入图片描述

在这里插入图片描述

三、应用

  1. 代码
    face_face.py
# 摄像头实时人脸识别
import os
import winsound  # 系统音效
# from playsound import playsound  # 音频播放
import dlib  # 人脸处理的库 Dlib
import csv  # 存入表格
import time
import sys
import numpy as np  # 数据处理的库 numpy
import cv2   # 图像处理的库 OpenCv
import pandas as pd  # 数据处理的库 Pandas

# 人脸识别模型,提取128D的特征矢量
# face recognition model, the object maps human faces into 128D vectors
# Refer this tutorial: http://dlib.net/python/index.html#dlib.face_recognition_model_v1
facerec = dlib.face_recognition_model_v1("./file/dlib_face_recognition_resnet_model_v1.dat")


# 计算两个128D向量间的欧式距离
# compute the e-distance between two 128D features
def return_euclidean_distance(feature_1, feature_2):
    feature_1 = np.array(feature_1)
    feature_2 = np.array(feature_2)
    dist = np.sqrt(np.sum(np.square(feature_1 - feature_2)))
    return dist


# 处理存放所有人脸特征的 csv
path_features_known_csv = "./dataset/csvs/face_mean_features.csv"
csv_rd = pd.read_csv(path_features_known_csv, header=None)

# 用来存放所有录入人脸特征的数组
# the array to save the features of faces in the database
features_known_arr = []

# 读取已知人脸数据
# print known faces
for i in range(csv_rd.shape[0]):
    features_someone_arr = []
    for j in range(0, len(csv_rd.loc[i, :])):
        features_someone_arr.append(csv_rd.loc[i, :][j])
    features_known_arr.append(features_someone_arr)
print("Faces in Database:", len(features_known_arr))

# Dlib 检测器和预测器
# The detector and predictor will be used
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('./file/shape_predictor_68_face_landmarks.dat')

# 创建 cv2 摄像头对象
# cv2.VideoCapture(0) to use the default camera of PC,
# and you can use local video name by use cv2.VideoCapture(filename)
cap = cv2.VideoCapture(0)

# cap.set(propId, value)
# 设置视频参数,propId 设置的视频参数,value 设置的参数值
cap.set(3, 480)

# cap.isOpened() 返回 true/false 检查初始化是否成功
# when the camera is open
while cap.isOpened():

    flag, img_rd = cap.read()
    kk = cv2.waitKey(1)

    # 取灰度
    img_gray = cv2.cvtColor(img_rd, cv2.COLOR_RGB2GRAY)

    # 人脸数 faces
    faces = detector(img_gray, 0)

    # 待会要写的字体 font to write later
    font = cv2.FONT_HERSHEY_COMPLEX

    # 存储当前摄像头中捕获到的所有人脸的坐标/名字
    # the list to save the positions and names of current faces captured
    pos_namelist = []
    name_namelist = []

    # 按下 q 键退出
    # press 'q' to exit
    if kk == ord('q'):
        break
    else:
        # 检测到人脸 when face detected
        if len(faces) != 0:
            # 获取当前捕获到的图像的所有人脸的特征,存储到 features_cap_arr
            # get the features captured and save into features_cap_arr
            features_cap_arr = []
            for i in range(len(faces)):
                shape = predictor(img_rd, faces[i])
                features_cap_arr.append(facerec.compute_face_descriptor(img_rd, shape))

            # 遍历捕获到的图像中所有的人脸
            # traversal all the faces in the database
            for k in range(len(faces)):
                print("##### camera person", k + 1, "#####")
                # 让人名跟随在矩形框的下方
                # 确定人名的位置坐标
                # 先默认所有人不认识,是 unknown
                # set the default names of faces with "unknown"
                name_namelist.append("unknown")

                # 每个捕获人脸的名字坐标 the positions of faces captured
                pos_namelist.append(
                    tuple([faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top()) / 4)]))

                # 对于某张人脸,遍历所有存储的人脸特征
                # for every faces detected, compare the faces in the database
                e_distance_list = []
                for i in range(len(features_known_arr)):
                    # 如果 person_X 数据不为空
                    if str(features_known_arr[i][0]) != '0.0':
                        print("with person", str(i + 1), "the e distance: ", end='')
                        e_distance_tmp = return_euclidean_distance(features_cap_arr[k], features_known_arr[i])
                        print(e_distance_tmp)
                        e_distance_list.append(e_distance_tmp)
                    else:
                        # 空数据 person_X
                        e_distance_list.append(999999999)
                # 找出最接近的一个人脸数据是第几个
                # Find the one with minimum e distance
                similar_person_num = e_distance_list.index(min(e_distance_list))
                print("Minimum e distance with person", int(similar_person_num) + 1)

                # 计算人脸识别特征与数据集特征的欧氏距离
                # 距离小于0.4则标出为可识别人物
                if min(e_distance_list) < 0.4:
                    # 这里可以修改摄像头中标出的人名
                    # Here you can modify the names shown on the camera
                    # 1、遍历文件夹目录
                    folder_name = './dataset/faces'
                    # 最接近的人脸
                    sum = similar_person_num + 1
                    key_id = 1  # 从第一个人脸数据文件夹进行对比
                    # 获取文件夹中的文件名:1wang、2zhou、3...
                    file_names = os.listdir(folder_name)
                    for name in file_names:
                        # print(name+'->'+str(key_id))
                        if sum == key_id:
                            # winsound.Beep(300,500)# 响铃:300频率,500持续时间
                            name_namelist[k] = name[:]  # 人名删去第一个数字(用于视频输出标识)
                        key_id += 1
                  
                # 矩形框
                # draw rectangle
                for kk, d in enumerate(faces):
                    # 绘制矩形框
                    cv2.rectangle(img_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]), (0, 255, 255), 2)
                print('\n')

            # 在人脸框下面写人脸名字
            # write names under rectangle
            for i in range(len(faces)):
                cv2.putText(img_rd, name_namelist[i], pos_namelist[i], font, 0.8, (0, 255, 255), 1, cv2.LINE_AA)

    print("Faces in camera now:", name_namelist, "\n")

    # cv2.putText(img_rd, "Press 'q': Quit", (20, 450), font, 0.8, (84, 255, 159), 1, cv2.LINE_AA)
    cv2.putText(img_rd, "Face Recognition", (20, 40), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
    cv2.putText(img_rd, "Visitors: " + str(len(faces)), (20, 100), font, 1, (0, 0, 255), 1, cv2.LINE_AA)

    # 窗口显示 show with opencv
    cv2.imshow("camera", img_rd)

# 释放摄像头 release camera
cap.release()

# 删除建立的窗口 delete all the windows
cv2.destroyAllWindows()

  1. 检测结果:
    运行即可,不做演示。

四、参考

Dlib模型实现人脸识别
人脸识别Dlib_face_recognize

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值