基于Flask/Opencv/Dlib课堂人脸签到系统

简介

基于Flask/Opencv/Dlib课堂人脸签到系统_第1张图片

 

        本项目主要采用了Python语言基于Flask框架开发,利用Dlib库中68特征点检测器和深度残差网络模型,欧氏距离,目标跟踪方法实现了人脸识别,采用MySQL数据库记录系统相关数据,并用Bootstrap框架进行页面美化。最后完成的系统可以适用于具有带摄像头的联网设备的教学场所。

系统角色与功能设计

        基于Flask/Opencv/Dlib课堂人脸签到系统_第2张图片

 基于Flask/Opencv/Dlib课堂人脸签到系统_第3张图片基于Flask/Opencv/Dlib课堂人脸签到系统_第4张图片

 数据库

        基于Flask/Opencv/Dlib课堂人脸签到系统_第5张图片

技术框架 

        基于Flask/Opencv/Dlib课堂人脸签到系统_第6张图片

 系统源码截图 

         基于Flask/Opencv/Dlib课堂人脸签到系统_第7张图片

人脸识别功能实现代码

# Copyright (C) 2020 coneypo
# SPDX-License-Identifier: MIT

# 从人脸图像文件中提取人脸特征存入 "features_all.csv" / Extract features from images and save into "features_all.csv"

import os
import dlib
from skimage import io
import csv
import numpy as np

# 要读取人脸图像文件的路径 / Path of cropped faces
path_images_from_camera = "static/data/data_faces_from_camera/"

# Dlib 正向人脸检测器 / Use frontal face detector of Dlib
detector = dlib.get_frontal_face_detector()

# Dlib 人脸 landmark 特征点检测器 / Get face landmarks
predictor = dlib.shape_predictor('app/static/data_dlib/shape_predictor_68_face_landmarks.dat')

# Dlib Resnet 人脸识别模型,提取 128D 的特征矢量 / Use Dlib resnet50 model to get 128D face descriptor
face_reco_model = dlib.face_recognition_model_v1("app/static/data_dlib/dlib_face_recognition_resnet_model_v1.dat")


# 返回单张图像的 128D 特征 / Return 128D features for single image
# Input:    path_img           
# Output:   face_descriptor    
def return_128d_features(path_img):
    img_rd = io.imread(path_img)
    faces = detector(img_rd, 1)

    print("%-40s %-20s" % (" >> 检测到人脸的图像 / Image with faces detected:", path_img), '\n')

    # 因为有可能截下来的人脸再去检测,检测不出来人脸了, 所以要确保是 检测到人脸的人脸图像拿去算特征
    # For photos of faces saved, we need to make sure that we can detect faces from the cropped images
    if len(faces) != 0:
        shape = predictor(img_rd, faces[0])
        face_descriptor = face_reco_model.compute_face_descriptor(img_rd, shape)
    else:
        face_descriptor = 0
        print("no face")
    return face_descriptor


# 返回 personX 的 128D 特征均值 / Return the mean value of 128D face descriptor for person X
# Input:    path_faces_personX       
# Output:   features_mean_personX    
def return_features_mean_personX(path_faces_personX):
    features_list_personX = []
    photos_list = os.listdir(path_faces_personX)
    if photos_list:
        for i in range(len(photos_list)):
            # 调用 return_128d_features() 得到 128D 特征 / Get 128D features for single image of personX
            print("%-40s %-20s" % (" >> 正在读的人脸图像 / Reading image:", path_faces_personX + "/" + photos_list[i]))
            features_128d = return_128d_features(path_faces_personX + "/" + photos_list[i])
            # 遇到没有检测出人脸的图片跳过 / Jump if no face detected from image
            if features_128d == 0:
                i += 1
            else:
                features_list_personX.append(features_128d)
    else:
        print(" >> 文件夹内图像文件为空 / Warning: No images in " + path_faces_personX + '/', '\n')

    # 计算 128D 特征的均值 / Compute the mean
    # personX 的 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 = np.zeros(128, dtype=int, order='C')
    return features_mean_personX


人脸录入代码

        

# 进行人脸录入

# import dlib
import numpy as np
import cv2
import os
from skimage import io
import dlib

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


class Face_Register:
    def __init__(self):
        pass


    #将录入的图片进行人脸检测,分截取人脸部分
    def process(self, path):
        photos_list = os.listdir(path)
        if photos_list:
            for i in range(len(photos_list)):
                # 调用 return_128d_features() 得到 128D 特征
                current_face_path = path + photos_list[i]
                print("%-40s %-20s" % (" >> 正在检测的人脸图像 / Reading image:", current_face_path))
                img_rd = cv2.imread(current_face_path)
                faces = detector(img_rd, 0)  # detector = dlib.get_frontal_face_detector() & Dlib人脸检测器
                # 遇到没有检测出人脸的图片跳过
                if len(faces) == 0:
                    i += 1
                else:
                    for k, d in enumerate(faces):
                        # 计算人脸区域矩形框大小
                        height = (d.bottom() - d.top())
                        width = (d.right() - d.left())
                        hh = int(height / 2)
                        ww = int(width / 2)

                        # 判断人脸矩形框是否超出 480x640
                        if (d.right() + ww) > 640 or (d.bottom() + hh > 480) or (d.left() - ww < 0) or (
                                d.top() - hh < 0):
                            print("%-40s %-20s" % (" >>超出范围,该图作废", current_face_path))

                        else:
                            img_blank = np.zeros((int(height * 2), width * 2, 3), np.uint8)
                            for ii in range(height * 2):
                                for jj in range(width * 2):
                                    img_blank[ii][jj] = img_rd[d.top() - hh + ii][d.left() - ww + jj]
                            cv2.imwrite(path +  str(i+1) + ".jpg", img_blank)
                            print("写入本地 / Save into:", str(path) + str(i+1) + ".jpg")
        else:
            print(" >> 文件夹内图像文件为空 / Warning: No images in " + path , '\n')

    def single_pocess(self,path):
        #读取人脸图像
        img_rd = cv2.imread(path)
        # Dlib的人脸检测器
        faces = detector(img_rd, 0)
        # 遇到没有检测出人脸的图片跳过
        if len(faces) == 0:
               return "none"
        else:
             for k, d in enumerate(faces):
                # 计算人脸区域矩形框大小
                 height = (d.bottom() - d.top())
                 width = (d.right() - d.left())
                 hh = int(height / 2)
                 ww = int(width / 2)

                 # 6. 判断人脸矩形框是否超出 480x640 / If the size of ROI > 480x640
                 if (d.right() + ww) > 640 or (d.bottom() + hh > 480) or (d.left() - ww < 0) or (
                     d.top() - hh < 0):
                     print("%-40s %-20s" % (" >>超出范围,该图作废", path))
                     return "big"

                 else:
                     img_blank = np.zeros((int(height * 2), width * 2, 3), np.uint8)
                     for ii in range(height * 2):
                         for jj in range(width * 2):
                             img_blank[ii][jj] = img_rd[d.top() - hh + ii][d.left() - ww + jj]
                     cv2.imwrite(path , img_blank)
                     print("写入本地 / Save into:", path)
                     return "right"

 系统视频介绍

        系统设计视频介绍

Python/Flask/Bootstrap/Opencv/Dlib/实现的《课堂人脸签到系统》

      系统运行视频介绍

Python/Flask/Bootstrap/Opencv/Dlib/实现的《课堂人脸签到系统》

总结  

        利用Python语言、Flask框架、Dlib库、MySQL数据库等工具设计并实现一套基于Web端的刷脸签到系统。

        学生可以在闲暇时在系统录入人脸,等到上课签到时,只需在网页上刷脸即可完成签到,签到页实时显示签到人信息,整个过程简便流畅。同时,也实现了与考勤相关的一系列功能,满足用户需求。

 

你可能感兴趣的:(计算机毕业设计,python,开发语言,个人开发,人工智能)