用opencv+dlib做一个简单的人脸考勤功能

简单介绍一下,最近在做人脸识别,发现一个非常好的,效果不错的人脸识别项目,现在用来做了一个简单的人脸打开功能的项目,特此记录下.

Fps 5-10 之间,基本可以实时识别,有兴趣的话可以fork,自定义一些功能.

工程比较简单,采用opcecv进行图像获取,采用dlib进行人脸比对,得到人脸进行记录,并且持久化到文件中,以供历史查询.没有打卡机,可以采用笔记本电脑做一个人脸考勤也是不错的选择.不过没做出来的时候,是弹性时间,有了之后,就固定时间了怎么破.


附上github地址: https://github.com/matiji66/face-attendance-machine.git

#capture.py  图像采集模块

# !/usr/bin/python3.6
# -*- coding: utf-8 -*-
# @author breeze

import cv2
import os

"""
下面是从摄像头捕捉实时流,以及采集照片,并将其写入文件的Python实现。

运行程序后:
1. 现在命令行输入采集照片人的姓名(拼音),如me
2. 选中摄像头框,并切换到英文输入法,按键Q推出,按键C 进行拍照并保存到指定的路径,
   此处avi文件保存在当前路径,每个人的照片保存在dataset单独的文件夹中
3. 当捕获的照片数量大于size(8),重复步骤1

"""

# Create a VideoCapture object
cap = cv2.VideoCapture(0)

# Check if camera opened successfully
if not cap.isOpened():
    print("Unable to read camera feed")

# Default resolutions of the frame are obtained.The default resolutions are system dependent.
# We convert the resolutions from float to integer.
# 默认分辨率取决于系统。
# 我们将分辨率从float转换为整数。
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))

# Define the codec and create VideoWriter object.The output is stored in 'outpy.avi' file.
# 定义编解码器并创建VideoWriter对象。输出存储在“outpy.avi”文件中。

name = "me"
image_base_path = "./dataset"
out = cv2.VideoWriter(image_base_path +'/outpy.avi', cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (frame_width, frame_height))
if not os.path.exists(image_base_path ):
    os.makedirs(image_base_path)

index = 0  #
size = 8  # record 8 different image from different direction
flag = True


while True:
    ret, frame = cap.read()
    if ret:
        # Write the frame into the file 'output.avi'
        out.write(frame)
        if flag and index == 0:  # or index % size == 0
            flag = False
            name = input("############please input a name and then press enter key to continue ############:")

        # Display the resulting frame
        cv2.imshow('frame', frame)

        key = cv2.waitKey(1)
        # Press Q on keyboard to stop recordingqc
        if key & 0xFF == ord('q'):
            break
        if key & 0xFF == ord('c'):
            index += 1
            if not os.path.exists(image_base_path + "/" + name):
                os.makedirs(image_base_path + "/" + name)
            cv2.imwrite("{}/{}/{}_{}.jpg".format(image_base_path, name, name, index), frame)
            if index == size:
                index = 0
                flag = True

    # Break the loop
    else:
        break

# When everything done, release the video capture and video write objects
cap.release()
out.release()

# Closes all the frames
cv2.destroyAllWindows()


# 2. 图像编码 encoding_images.py

# !/usr/bin/python3.6
# -*- coding: utf-8 -*-
# @author breeze

import os

import face_recognition
import numpy as np

# This is a demo of running face recognition on live video from your webcam. It's a little more complicated than the
# other example, but it includes some basic performance tweaks to make things run a lot faster:
#   1. Process each video frame at 1/4 resolution (though still display it at full resolution)
#   2. Only detect faces in every other frame of video.
# PLEASE NOTE: This example requires OpenCV (the `cv2` library) to be installed only to read from your webcam.
# OpenCV is *not* required to use the face_recognition library. It's only required if you want to run this
# specific demo. If you have trouble installing it, try any of the other demos that don't require it instead.
# Get a reference to webcam #0 (the default one)
# Load a sample picture and learn how to recognize it.
# face_recognition.api.batch_face_locations(images, number_of_times_to_upsample=1, batch_size=128)[source]
# face_recognition.api.compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)
# face_recognition.api.face_distance(face_encodings, face_to_compare)[source]
# face_recognition.api.face_encodings(face_image, known_face_locations=None, num_jitters=1)[source]
# face_recognition.api.face_landmarks(face_image, face_locations=None)[source]
# face_recognition.api.face_locations(img, number_of_times_to_upsample=1, model='hog')[source]
# face_recognition.api.load_image_file(file, mode='RGB')[source]

data_path = "./dataset"  # 相关文件保存路径
KNOWN_FACE_ENCODINGS = "./dataset/known_face_encodings.npy"  # 已知人脸向量
KNOWN_FACE_NANE = "./dataset/known_face_name.npy"  # 已知人脸名称

known_face_names = []
known_face_encodings = []
name_and_encoding = "./dataset/face_encodings.txt"


def encoding_images(path):
    """
    对path路径下的子文件夹中的图片进行编码
    :param path:
    :return:
    """
    with open(name_and_encoding, 'w') as f:
        subdirs = [os.path.join(path, x) for x in os.listdir(path) if
                   os.path.isdir(os.path.join(path, x))]
        for subdir in subdirs:
            print('---name :', subdir)
            for y in os.listdir(subdir):
                print("image name is ", y)
                _image = face_recognition.load_image_file(os.path.join(subdir, y))
                face_encodings = face_recognition.face_encodings(_image)
                name = os.path.split(subdir)[-1]
                if face_encodings and len(face_encodings) == 1:
                    face_encoding = face_recognition.face_encodings(_image)[0]
                    known_face_encodings.append(face_encoding)
                    known_face_names.append(name)
                f.write(name + ":" + str(face_encoding) + "\n")
    # save im binary format
    # np.array(known_face_encodings).tofile("./dataset/known_face_encodings.bin")
    # np.array(known_face_names).tofile("./dataset/known_face_names.bin")

    # save im numpy format https://www.cnblogs.com/dmir/p/5009075.html
    np.save(KNOWN_FACE_ENCODINGS, known_face_encodings)
    np.save(KNOWN_FACE_NANE, known_face_names)


def load_encodings():
    """
    加载保存的历史人脸向量,以及name向量,并返回
    :return:
    """
    if not os.path.exists(KNOWN_FACE_NANE) or not os.path.exists(KNOWN_FACE_ENCODINGS):
        encoding_images(data_path)
    return np.load(KNOWN_FACE_ENCODINGS), np.load(KNOWN_FACE_NANE)


def test_load():
    face_encodings, face_names = load_encodings()
    print("===========face_encodings================")
    print(face_encodings)
    print("===========================")
    print(face_names)
    print("===========face_names================")


if __name__ == '__main__':
    try:
        encoding_images(data_path)  # encoding all images in data_path sub dir
    except Exception as e:
        print("ERROR : create image encoding failed ! ")

    # 测试加载数据库
    test_load()

# 3. 人脸考勤环节  facerec_from_webcam_faster.py

# !/usr/bin/python3.6
# -*- coding: utf-8 -*-
# @author breeze

import time

import cv2
import face_recognition
import win32com.client

import encoding_images

# This is a demo of running face recognition on live video from your webcam. It's a little more complicated than the
# other example, but it includes some basic performance tweaks to make things run a lot faster:
#   1. Process each video frame at 1/4 resolution (though still display it at full resolution)
#   2. Only detect faces in every other frame of video.

# PLEASE NOTE: This example requires OpenCV (the `cv2` library) to be installed only to read from your webcam.
# OpenCV is *not* required to use the face_recognition library. It's only required if you want to run this
# specific demo. If you have trouble installing it, try any of the other demos that don't require it instead.


# Load a sample picture and learn how to recognize it.
# face_recognition.api.batch_face_locations(images, number_of_times_to_upsample=1, batch_size=128)[source]
# face_recognition.api.compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)
# face_recognition.api.face_distance(face_encodings, face_to_compare)[source]
# face_recognition.api.face_encodings(face_image, known_face_locations=None, num_jitters=1)[source]
# face_recognition.api.face_landmarks(face_image, face_locations=None)[source]
# face_recognition.api.face_locations(img, number_of_times_to_upsample=1, model='hog')[source]
# face_recognition.api.load_image_file(file, mode='RGB')[source]


# Get a reference to webcam #0 (the default one)
video_capture = cv2.VideoCapture(0)

# 语音模块 voice model
speaker = win32com.client.Dispatch("SAPI.SpVoice")

name = "Unknown"
current_names = []
last_time = time.time()
known_face_names = []
known_face_encodings = []
known_face_encodings, known_face_names = encoding_images.load_encodings()

# Initialize some variables
face_locations = []
face_encodings = []
face_names = []
process_this_frame = True  #
TIME_DIFF = 20  # 持久化的时间间隔,当设置为 0 时候,每次识别的结果直接进行保存.
name_record = "./dataset/face_record.txt"  # 持久化识别出的人脸结果


def process_face_records(name):
    """
    处理每一条识别的记录 ,并在一定时间之后将数据持久化到文件中
    :param name:
    :return:
    """
    global current_names, last_time
    print("global current_names {}, last_time {}".format( current_names, last_time))

    # 判断是不是在识别的列表中,不在的话就进行问候
    if name not in current_names:
        print("ts ====", last_time, time.time())
        current_names.append(name)
        print("Hello {}, nice to meet you! ".format(name))
        speaker.Speak("Hello {}, nice to meet you! ".format(name))
    # 在一定时间内,清空已经识别的人, 并进行
    if last_time < time.time() - TIME_DIFF:  # 每隔一段时间清空一下检测到的人
        last_time = time.time()
        time_format = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        print(time_format + " update last_time and clear current_names.")
        with open(name_record, 'a') as f:
            if len(current_names) > 0:
                f.writelines("{}:{} \n".format(time_format, str(current_names)))
        # print("======", current_names)
        current_names.clear()


while True:
    # Grab a single frame of video
    ret, frame = video_capture.read()

    # Resize frame of video to 1/4 size for faster face recognition processing
    small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

    # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
    rgb_small_frame = small_frame[:, :, ::-1]

    # Only process every other frame of video to save time
    if process_this_frame:
        # Find all the faces and face encodings in the current frame of video
        # face_locations = face_recognition.face_locations(rgb_small_frame, model="cnn")
        face_locations = face_recognition.face_locations(rgb_small_frame, model="hog")
        face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

        face_names = []
        for face_encoding in face_encodings:
            # See if the face is a match for the known face(s)

            ts1 = (int(round(time.time() * 1000)))
            matches = face_recognition.compare_faces( \
                known_face_encodings=known_face_encodings, face_encoding_to_check=face_encoding, tolerance=0.3)
            ts2 = (int(round(time.time() * 1000)))
            print("matches ts1 {} ts2{} cost {}ms".format(ts1, ts2, ts2 - ts1))  # matches
            # If a match was found in known_face_encodings, just use the first one.
            if True in matches:
                first_match_index = matches.index(True)
                name = known_face_names[first_match_index]
            face_names.append(name)
    process_this_frame = not process_this_frame

    # Display the results
    for (top, right, bottom, left), name in zip(face_locations, face_names):
        # Scale back up face locations since the frame we detected in was scaled to 1/4 size
        top *= 4
        right *= 4
        bottom *= 4
        left *= 4
        # Draw a box around the face
        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
        # Draw a label with a name below the face
        cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
        font = cv2.FONT_HERSHEY_DUPLEX
        cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
        print("process_face_records====")
        # say hello
        process_face_records(name)

    # Display the resulting image
    cv2.imshow('Video', frame)
    # Hit 'q' on the keyboard to quit!
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Release handle to the webcam
video_capture.release()
cv2.destroyAllWindows()



猜你喜欢

转载自blog.csdn.net/mtj66/article/details/80228210
今日推荐