国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

這篇具有很好參考價(jià)值的文章主要介紹了通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

目錄

一、準(zhǔn)備工作

1.1 需要的庫

1.2準(zhǔn)備需要的文件和圖片

1.3?測試程序

二、人臉識(shí)別開發(fā)

2.1 錄入自己的人臉信息

2.2 提取錄入的人臉特征

2.3 實(shí)時(shí)捕獲人臉并進(jìn)行識(shí)別

三、活體檢測

3.1 眨眼檢測

3.2 張嘴檢測

3.3 搖頭檢測


下面這些是我突發(fā)奇想想做來玩玩,就在github上下載了人臉識(shí)別的代碼(網(wǎng)址下面有附上),用了之后突然想試試照片的識(shí)別效果,發(fā)現(xiàn)照片也會(huì)被識(shí)別成我,就查閱了相關(guān)資料,一般都是通過活體檢測(比如眨眼、轉(zhuǎn)頭之類的),想通過算法實(shí)現(xiàn)實(shí)時(shí)視頻檢測,區(qū)分真人和照片。

一、準(zhǔn)備工作

開發(fā)環(huán)境:windows10+pycharm2022.1.3+python+3.9

1.1 需要的庫

opencv-python==4.5.5.64

numpy==1.23.3

dlib==19.24.0

pandas=1.5.0

枕頭=9.2.0

dlib庫安裝方法:

進(jìn)入虛擬環(huán)境后輸入:

anaconda search -t conda dlib

conda install -c https://conda.anaconda.org/conda-forge dlib

1.2準(zhǔn)備需要的文件和圖片

進(jìn)入網(wǎng)址:http://dlib.net/files/

下載文件:shape_predictor_68_face_landmarks.dat.bz2,解壓后存在data文件夾,該模型可以識(shí)別人臉68個(gè)關(guān)鍵點(diǎn)。網(wǎng)址中還含有5關(guān)鍵點(diǎn)模型文件。

準(zhǔn)備人臉照片,存于img文件夾。

1.3?測試程序

# -*- coding = utf-8 -*-
# @Time : 2022/9/20 9:11
# @Author : 李昊蕓
# @file : dlib_t.py
# @Software : PyCharm

import cv2
import dlib

path = "img/lhy_1.jpeg"
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#人臉分類器
detector = dlib.get_frontal_face_detector()
# 獲取人臉檢測器
predictor = dlib.shape_predictor(
    ".\\data\\shape_predictor_68_face_landmarks.dat"
)

dets = detector(gray, 1)
for face in dets:
    shape = predictor(img, face)  # 尋找人臉的68個(gè)標(biāo)定點(diǎn)
    # 遍歷所有點(diǎn),打印出其坐標(biāo),并圈出來
    for pt in shape.parts():
        pt_pos = (pt.x, pt.y)
        cv2.circle(img, pt_pos, 2, (0, 255, 0), 1)
    cv2.imshow("image", img)

cv2.waitKey(0)
cv2.destroyAllWindows()

68關(guān)鍵點(diǎn)分類器識(shí)別結(jié)果:

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

多人識(shí)別效果:

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

二、人臉識(shí)別開發(fā)

?原github地址:https://github.com/coneypo/Dlib_face_recognition_from_camera

2.1 錄入自己的人臉信息

get_faces_from_camera.py
# Copyright (C) 2018-2021 coneypo
# SPDX-License-Identifier: MIT

# Author:   coneypo
# Blog:     http://www.cnblogs.com/AdaminXie
# GitHub:   https://github.com/coneypo/Dlib_face_recognition_from_camera
# Mail:     coneypo@foxmail.com

# 進(jìn)行人臉錄入 / Face register

import dlib
import numpy as np
import cv2
import os
import shutil
import time
import logging

# Dlib 正向人臉檢測器 / Use frontal face detector of Dlib
detector = dlib.get_frontal_face_detector()


class Face_Register:
    def __init__(self):
        self.path_photos_from_camera = "data/data_faces_from_camera/"
        self.font = cv2.FONT_ITALIC

        self.existing_faces_cnt = 0         # 已錄入的人臉計(jì)數(shù)器 / cnt for counting saved faces
        self.ss_cnt = 0                     # 錄入 personX 人臉時(shí)圖片計(jì)數(shù)器 / cnt for screen shots
        self.current_frame_faces_cnt = 0    # 錄入人臉計(jì)數(shù)器 / cnt for counting faces in current frame

        self.save_flag = 1                  # 之后用來控制是否保存圖像的 flag / The flag to control if save
        self.press_n_flag = 0               # 之后用來檢查是否先按 'n' 再按 's' / The flag to check if press 'n' before 's'

        # FPS
        self.frame_time = 0
        self.frame_start_time = 0
        self.fps = 0
        self.fps_show = 0
        self.start_time = time.time()

    # 新建保存人臉圖像文件和數(shù)據(jù) CSV 文件夾 / Mkdir for saving photos and csv
    def pre_work_mkdir(self):
        # 新建文件夾 / Create folders to save face images and csv
        if os.path.isdir(self.path_photos_from_camera):
            pass
        else:
            os.mkdir(self.path_photos_from_camera)

    # 刪除之前存的人臉數(shù)據(jù)文件夾 / Delete old face folders
    def pre_work_del_old_face_folders(self):
        # 刪除之前存的人臉數(shù)據(jù)文件夾, 刪除 "/data_faces_from_camera/person_x/"...
        folders_rd = os.listdir(self.path_photos_from_camera)
        for i in range(len(folders_rd)):
            shutil.rmtree(self.path_photos_from_camera+folders_rd[i])
        if os.path.isfile("data/features_all.csv"):
            os.remove("data/features_all.csv")

    # 如果有之前錄入的人臉, 在之前 person_x 的序號(hào)按照 person_x+1 開始錄入 / Start from person_x+1
    def check_existing_faces_cnt(self):
        if os.listdir("data/data_faces_from_camera/"):
            # 獲取已錄入的最后一個(gè)人臉序號(hào) / Get the order of latest person
            person_list = os.listdir("data/data_faces_from_camera/")
            person_num_list = []
            for person in person_list:
                person_num_list.append(int(person.split('_')[-1]))
            self.existing_faces_cnt = max(person_num_list)

        # 如果第一次存儲(chǔ)或者沒有之前錄入的人臉, 按照 person_1 開始錄入 / Start from person_1
        else:
            self.existing_faces_cnt = 0

    # 更新 FPS / Update FPS of Video stream
    def update_fps(self):
        now = time.time()
        # 每秒刷新 fps / Refresh fps per second
        if str(self.start_time).split(".")[0] != str(now).split(".")[0]:
            self.fps_show = self.fps
        self.start_time = now
        self.frame_time = now - self.frame_start_time
        self.fps = 1.0 / self.frame_time
        self.frame_start_time = now

    # 生成的 cv2 window 上面添加說明文字 / PutText on cv2 window
    def draw_note(self, img_rd):
        # 添加說明 / Add some notes
        cv2.putText(img_rd, "Face Register", (20, 40), self.font, 1, (255, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(img_rd, "FPS:   " + str(self.fps_show.__round__(2)), (20, 100), self.font, 0.8, (0, 255, 0), 1,
                    cv2.LINE_AA)
        cv2.putText(img_rd, "Faces: " + str(self.current_frame_faces_cnt), (20, 140), self.font, 0.8, (0, 255, 0), 1, cv2.LINE_AA)
        cv2.putText(img_rd, "N: Create face folder", (20, 350), self.font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(img_rd, "S: Save current face", (20, 400), self.font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(img_rd, "Q: Quit", (20, 450), self.font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)

    # 獲取人臉 / Main process of face detection and saving
    def process(self, stream):
        # 1. 新建儲(chǔ)存人臉圖像文件目錄 / Create folders to save photos
        self.pre_work_mkdir()

        # 2. 刪除 "/data/data_faces_from_camera" 中已有人臉圖像文件
        # / Uncomment if want to delete the saved faces and start from person_1
        # if os.path.isdir(self.path_photos_from_camera):
        #     self.pre_work_del_old_face_folders()

        # 3. 檢查 "/data/data_faces_from_camera" 中已有人臉文件
        self.check_existing_faces_cnt()

        while stream.isOpened():
            flag, img_rd = stream.read()        # Get camera video stream
            kk = cv2.waitKey(1)
            faces = detector(img_rd, 0)         # Use Dlib face detector

            # 4. 按下 'n' 新建存儲(chǔ)人臉的文件夾 / Press 'n' to create the folders for saving faces
            if kk == ord('n'):
                self.existing_faces_cnt += 1
                current_face_dir = self.path_photos_from_camera + "person_" + str(self.existing_faces_cnt)
                os.makedirs(current_face_dir)
                logging.info("\n%-40s %s", "新建的人臉文件夾 / Create folders:", current_face_dir)

                self.ss_cnt = 0                 # 將人臉計(jì)數(shù)器清零 / Clear the cnt of screen shots
                self.press_n_flag = 1           # 已經(jīng)按下 'n' / Pressed 'n' already

            # 5. 檢測到人臉 / Face detected
            if len(faces) != 0:
                # 矩形框 / Show the ROI of faces
                for k, d in enumerate(faces):
                    # 計(jì)算矩形框大小 / Compute the size of rectangle box
                    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):
                        cv2.putText(img_rd, "OUT OF RANGE", (20, 300), self.font, 0.8, (0, 0, 255), 1, cv2.LINE_AA)
                        color_rectangle = (0, 0, 255)
                        save_flag = 0
                        if kk == ord('s'):
                            logging.warning("請調(diào)整位置 / Please adjust your position")
                    else:
                        color_rectangle = (255, 255, 255)
                        save_flag = 1

                    cv2.rectangle(img_rd,
                                  tuple([d.left() - ww, d.top() - hh]),
                                  tuple([d.right() + ww, d.bottom() + hh]),
                                  color_rectangle, 2)

                    # 7. 根據(jù)人臉大小生成空的圖像 / Create blank image according to the size of face detected
                    img_blank = np.zeros((int(height*2), width*2, 3), np.uint8)

                    if save_flag:
                        # 8. 按下 's' 保存攝像頭中的人臉到本地 / Press 's' to save faces into local images
                        if kk == ord('s'):
                            # 檢查有沒有先按'n'新建文件夾 / Check if you have pressed 'n'
                            if self.press_n_flag:
                                self.ss_cnt += 1
                                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(current_face_dir + "/img_face_" + str(self.ss_cnt) + ".jpg", img_blank)
                                logging.info("%-40s %s/img_face_%s.jpg", "寫入本地 / Save into:",
                                             str(current_face_dir), str(self.ss_cnt))
                            else:
                                logging.warning("請先按 'N' 來建文件夾, 按 'S' / Please press 'N' and press 'S'")

            self.current_frame_faces_cnt = len(faces)

            # 9. 生成的窗口添加說明文字 / Add note on cv2 window
            self.draw_note(img_rd)

            # 10. 按下 'q' 鍵退出 / Press 'q' to exit
            if kk == ord('q'):
                break

            # 11. Update FPS
            self.update_fps()

            cv2.namedWindow("camera", 1)
            cv2.imshow("camera", img_rd)

    def run(self):
        # cap = cv2.VideoCapture("video.mp4")   # Get video stream from video file
        cap = cv2.VideoCapture(0)               # Get video stream from camera
        self.process(cap)

        cap.release()
        cv2.destroyAllWindows()


def main():
    logging.basicConfig(level=logging.INFO)
    Face_Register_con = Face_Register()
    Face_Register_con.run()


if __name__ == '__main__':
    main()

2.2 提取錄入的人臉特征

features_extraction_to_csv.py
# Copyright (C) 2018-2021 coneypo
# SPDX-License-Identifier: MIT

# Author:   coneypo
# Blog:     http://www.cnblogs.com/AdaminXie
# GitHub:   https://github.com/coneypo/Dlib_face_recognition_from_camera
# Mail:     coneypo@foxmail.com

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

import os
import dlib
import csv
import numpy as np
import logging
import cv2

# 要讀取人臉圖像文件的路徑 / Path of cropped faces
path_images_from_camera = "data/data_faces_from_camera/"

# Dlib 正向人臉檢測器 / Use frontal face detector of Dlib
detector = dlib.get_frontal_face_detector()

# Dlib 人臉 landmark 特征點(diǎn)檢測器 / Get face landmarks
predictor = dlib.shape_predictor('data/data_dlib/shape_predictor_68_face_landmarks.dat')

# Dlib Resnet 人臉識(shí)別模型,提取 128D 的特征矢量 / Use Dlib resnet50 model to get 128D face descriptor
face_reco_model = dlib.face_recognition_model_v1("data/data_dlib/dlib_face_recognition_resnet_model_v1.dat")


# 返回單張圖像的 128D 特征 / Return 128D features for single image
# Input:    path_img           <class 'str'>
# Output:   face_descriptor    <class 'dlib.vector'>
def return_128d_features(path_img):
    img_rd = cv2.imread(path_img)
    faces = detector(img_rd, 1)

    logging.info("%-40s %-20s", "檢測到人臉的圖像 / Image with faces detected:", path_img)

    # 因?yàn)橛锌赡芙叵聛淼娜四樤偃z測,檢測不出來人臉了, 所以要確保是 檢測到人臉的人臉圖像拿去算特征
    # 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
        logging.warning("no face")
    return face_descriptor


# 返回 personX 的 128D 特征均值 / Return the mean value of 128D face descriptor for person X
# Input:    path_face_personX        <class 'str'>
# Output:   features_mean_personX    <class 'numpy.ndarray'>
def return_features_mean_personX(path_face_personX):
    features_list_personX = []
    photos_list = os.listdir(path_face_personX)
    if photos_list:
        for i in range(len(photos_list)):
            # 調(diào)用 return_128d_features() 得到 128D 特征 / Get 128D features for single image of personX
            logging.info("%-40s %-20s", "正在讀的人臉圖像 / Reading image:", path_face_personX + "/" + photos_list[i])
            features_128d = return_128d_features(path_face_personX + "/" + photos_list[i])
            # 遇到?jīng)]有檢測出人臉的圖片跳過 / Jump if no face detected from image
            if features_128d == 0:
                i += 1
            else:
                features_list_personX.append(features_128d)
    else:
        logging.warning("文件夾內(nèi)圖像文件為空 / Warning: No images in%s/", path_face_personX)

    # 計(jì)算 128D 特征的均值 / Compute the mean
    # personX 的 N 張圖像 x 128D -> 1 x 128D
    if features_list_personX:
        features_mean_personX = np.array(features_list_personX, dtype=object).mean(axis=0)
    else:
        features_mean_personX = np.zeros(128, dtype=object, order='C')
    return features_mean_personX


def main():
    logging.basicConfig(level=logging.INFO)
    # 獲取已錄入的最后一個(gè)人臉序號(hào) / Get the order of latest person
    person_list = os.listdir("data/data_faces_from_camera/")
    person_list.sort()

    with open("data/features_all.csv", "w", newline="") as csvfile:
        writer = csv.writer(csvfile)
        for person in person_list:
            # Get the mean/average features of face/personX, it will be a list with a length of 128D
            logging.info("%sperson_%s", path_images_from_camera, person)
            features_mean_personX = return_features_mean_personX(path_images_from_camera + person)

            if len(person.split('_', 2)) == 2:
                # "person_x"
                person_name = person
            else:
                # "person_x_tom"
                person_name = person.split('_', 2)[-1]
            features_mean_personX = np.insert(features_mean_personX, 0, person_name, axis=0)
            # features_mean_personX will be 129D, person name + 128 features
            writer.writerow(features_mean_personX)
            logging.info('\n')
        logging.info("所有錄入人臉數(shù)據(jù)存入 / Save all the features of faces registered into: data/features_all.csv")


if __name__ == '__main__':
    main()

2.3 實(shí)時(shí)捕獲人臉并進(jìn)行識(shí)別

face_reco_from_camera.py
# Copyright (C) 2018-2021 coneypo
# SPDX-License-Identifier: MIT

# Author:   coneypo
# Blog:     http://www.cnblogs.com/AdaminXie
# GitHub:   https://github.com/coneypo/Dlib_face_recognition_from_camera
# Mail:     coneypo@foxmail.com

# 攝像頭實(shí)時(shí)人臉識(shí)別 / Real-time face detection and recognition

import dlib
import numpy as np
import cv2
import pandas as pd
import os
import time
import logging
from PIL import Image, ImageDraw, ImageFont

# Dlib 正向人臉檢測器 / Use frontal face detector of Dlib
detector = dlib.get_frontal_face_detector()

# Dlib 人臉 landmark 特征點(diǎn)檢測器 / Get face landmarks
predictor = dlib.shape_predictor('data/data_dlib/shape_predictor_68_face_landmarks.dat')

# Dlib Resnet 人臉識(shí)別模型,提取 128D 的特征矢量 / Use Dlib resnet50 model to get 128D face descriptor
face_reco_model = dlib.face_recognition_model_v1("data/data_dlib/dlib_face_recognition_resnet_model_v1.dat")


class Face_Recognizer:
    def __init__(self):
        self.face_feature_known_list = []                # 用來存放所有錄入人臉特征的數(shù)組 / Save the features of faces in database
        self.face_name_known_list = []                   # 存儲(chǔ)錄入人臉名字 / Save the name of faces in database

        self.current_frame_face_cnt = 0                     # 存儲(chǔ)當(dāng)前攝像頭中捕獲到的人臉數(shù) / Counter for faces in current frame
        self.current_frame_face_feature_list = []           # 存儲(chǔ)當(dāng)前攝像頭中捕獲到的人臉特征 / Features of faces in current frame
        self.current_frame_face_name_list = []              # 存儲(chǔ)當(dāng)前攝像頭中捕獲到的所有人臉的名字 / Names of faces in current frame
        self.current_frame_face_name_position_list = []     # 存儲(chǔ)當(dāng)前攝像頭中捕獲到的所有人臉的名字坐標(biāo) / Positions of faces in current frame

        # Update FPS
        self.fps = 0                    # FPS of current frame
        self.fps_show = 0               # FPS per second
        self.frame_start_time = 0
        self.frame_cnt = 0
        self.start_time = time.time()

        self.font = cv2.FONT_ITALIC
        self.font_chinese = ImageFont.truetype("simsun.ttc", 30)

    # 從 "features_all.csv" 讀取錄入人臉特征 / Read known faces from "features_all.csv"
    def get_face_database(self):
        if os.path.exists("data/features_all.csv"):
            path_features_known_csv = "data/features_all.csv"
            csv_rd = pd.read_csv(path_features_known_csv, header=None)
            for i in range(csv_rd.shape[0]):
                features_someone_arr = []
                self.face_name_known_list.append(csv_rd.iloc[i][0])
                for j in range(1, 129):
                    if csv_rd.iloc[i][j] == '':
                        features_someone_arr.append('0')
                    else:
                        features_someone_arr.append(csv_rd.iloc[i][j])
                self.face_feature_known_list.append(features_someone_arr)
            logging.info("Faces in Database:%d", len(self.face_feature_known_list))
            return 1
        else:
            logging.warning("'features_all.csv' not found!")
            logging.warning("Please run 'get_faces_from_camera.py' "
                            "and 'features_extraction_to_csv.py' before 'face_reco_from_camera.py'")
            return 0

    # 計(jì)算兩個(gè)128D向量間的歐式距離 / Compute the e-distance between two 128D features
    @staticmethod
    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

    # 更新 FPS / Update FPS of Video stream
    def update_fps(self):
        now = time.time()
        # 每秒刷新 fps / Refresh fps per second
        if str(self.start_time).split(".")[0] != str(now).split(".")[0]:
            self.fps_show = self.fps
        self.start_time = now
        self.frame_time = now - self.frame_start_time
        self.fps = 1.0 / self.frame_time
        self.frame_start_time = now

    # 生成的 cv2 window 上面添加說明文字 / PutText on cv2 window
    def draw_note(self, img_rd):
        cv2.putText(img_rd, "Face Recognizer", (20, 40), self.font, 1, (255, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(img_rd, "Frame:  " + str(self.frame_cnt), (20, 100), self.font, 0.8, (0, 255, 0), 1,
                    cv2.LINE_AA)
        cv2.putText(img_rd, "FPS:    " + str(self.fps_show.__round__(2)), (20, 130), self.font, 0.8, (0, 255, 0), 1,
                    cv2.LINE_AA)
        cv2.putText(img_rd, "Faces:  " + str(self.current_frame_face_cnt), (20, 160), self.font, 0.8, (0, 255, 0), 1,
                    cv2.LINE_AA)
        cv2.putText(img_rd, "Q: Quit", (20, 450), self.font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)

    def draw_name(self, img_rd):
        # 在人臉框下面寫人臉名字 / Write names under rectangle
        img = Image.fromarray(cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB))
        draw = ImageDraw.Draw(img)
        for i in range(self.current_frame_face_cnt):
            # cv2.putText(img_rd, self.current_frame_face_name_list[i], self.current_frame_face_name_position_list[i], self.font, 0.8, (0, 255, 255), 1, cv2.LINE_AA)
            draw.text(xy=self.current_frame_face_name_position_list[i], text=self.current_frame_face_name_list[i], font=self.font_chinese,
                  fill=(255, 255, 0))
            img_rd = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        return img_rd

    # 修改顯示人名 / Show names in chinese
    def show_chinese_name(self):
        # Default known name: person_1, person_2, person_3
        if self.current_frame_face_cnt >= 1:
            # 修改錄入的人臉姓名 / Modify names in face_name_known_list to chinese name
            self.face_name_known_list[0] = '張三'.encode('utf-8').decode()
            # self.face_name_known_list[1] = '張四'.encode('utf-8').decode()

    # 處理獲取的視頻流,進(jìn)行人臉識(shí)別 / Face detection and recognition from input video stream
    def process(self, stream):
        # 1. 讀取存放所有人臉特征的 csv / Read known faces from "features.all.csv"
        if self.get_face_database():
            while stream.isOpened():
                self.frame_cnt += 1
                logging.debug("Frame %d starts", self.frame_cnt)
                flag, img_rd = stream.read()
                faces = detector(img_rd, 0)
                kk = cv2.waitKey(1)
                # 按下 q 鍵退出 / Press 'q' to quit
                if kk == ord('q'):
                    break
                else:
                    self.draw_note(img_rd)
                    self.current_frame_face_feature_list = []
                    self.current_frame_face_cnt = 0
                    self.current_frame_face_name_position_list = []
                    self.current_frame_face_name_list = []

                    # 2. 檢測到人臉 / Face detected in current frame
                    if len(faces) != 0:
                        # 3. 獲取當(dāng)前捕獲到的圖像的所有人臉的特征 / Compute the face descriptors for faces in current frame
                        for i in range(len(faces)):
                            shape = predictor(img_rd, faces[i])
                            self.current_frame_face_feature_list.append(face_reco_model.compute_face_descriptor(img_rd, shape))
                        # 4. 遍歷捕獲到的圖像中所有的人臉 / Traversal all the faces in the database
                        for k in range(len(faces)):
                            logging.debug("For face %d in camera:", k+1)
                            # 先默認(rèn)所有人不認(rèn)識(shí),是 unknown / Set the default names of faces with "unknown"
                            self.current_frame_face_name_list.append("unknown")

                            # 每個(gè)捕獲人臉的名字坐標(biāo) / Positions of faces captured
                            self.current_frame_face_name_position_list.append(tuple(
                                [faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top()) / 4)]))

                            # 5. 對于某張人臉,遍歷所有存儲(chǔ)的人臉特征
                            # For every faces detected, compare the faces in the database
                            current_frame_e_distance_list = []
                            for i in range(len(self.face_feature_known_list)):
                                # 如果 person_X 數(shù)據(jù)不為空
                                if str(self.face_feature_known_list[i][0]) != '0.0':
                                    e_distance_tmp = self.return_euclidean_distance(self.current_frame_face_feature_list[k],
                                                                                    self.face_feature_known_list[i])
                                    logging.debug("  With person %s, the e-distance is %f", str(i + 1), e_distance_tmp)
                                    current_frame_e_distance_list.append(e_distance_tmp)
                                else:
                                    # 空數(shù)據(jù) person_X
                                    current_frame_e_distance_list.append(999999999)
                            # 6. 尋找出最小的歐式距離匹配 / Find the one with minimum e-distance
                            similar_person_num = current_frame_e_distance_list.index(min(current_frame_e_distance_list))
                            logging.debug("Minimum e-distance with %s: %f", self.face_name_known_list[similar_person_num], min(current_frame_e_distance_list))

                            if min(current_frame_e_distance_list) < 0.4:
                                self.current_frame_face_name_list[k] = self.face_name_known_list[similar_person_num]
                                logging.debug("Face recognition result: %s", self.face_name_known_list[similar_person_num])
                            else:
                                logging.debug("Face recognition result: Unknown person")
                            logging.debug("\n")

                            # 矩形框 / Draw rectangle
                            for kk, d in enumerate(faces):
                                # 繪制矩形框
                                cv2.rectangle(img_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]),
                                              (255, 255, 255), 2)

                        self.current_frame_face_cnt = len(faces)

                        # 7. 在這里更改顯示的人名 / Modify name if needed
                        # self.show_chinese_name()

                        # 8. 寫名字 / Draw name
                        img_with_name = self.draw_name(img_rd)

                    else:
                        img_with_name = img_rd

                logging.debug("Faces in camera now: %s", self.current_frame_face_name_list)

                cv2.imshow("camera", img_with_name)

                # 9. 更新 FPS / Update stream FPS
                self.update_fps()
                logging.debug("Frame ends\n\n")

    # OpenCV 調(diào)用攝像頭并進(jìn)行 process
    def run(self):
        # cap = cv2.VideoCapture("video.mp4")  # Get video stream from video file
        cap = cv2.VideoCapture(0)              # Get video stream from camera
        cap.set(3, 480)                        # 640x480
        self.process(cap)

        cap.release()
        cv2.destroyAllWindows()


def main():
    # logging.basicConfig(level=logging.DEBUG) # Set log level to 'logging.DEBUG' to print debug info of every frame
    logging.basicConfig(level=logging.INFO)
    Face_Recognizer_con = Face_Recognizer()
    Face_Recognizer_con.run()


if __name__ == '__main__':
    main()

識(shí)別結(jié)果(我和我的無美顏照片):

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

(自己的臉,馬賽克一下)?

可以看出, 識(shí)別效果還是很不錯(cuò)的。

三、活體檢測

3.1 眨眼檢測

經(jīng)過查詢資料,得到廣為人使用的一個(gè)指標(biāo):眼睛縱橫比(EAR)

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

分別得到兩只眼睛的縱橫比并取平均值,作為眨眼的指標(biāo),經(jīng)過多次測試后,選取0.3作為閾值。

在連續(xù)檢測到兩次EAR小于閾值,即眼睛一睜一閉時(shí),我們將記錄為一次眨眼。

代碼如下,實(shí)驗(yàn)結(jié)果如圖:

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

from scipy.spatial import distance as dist
from imutils.video import VideoStream
from imutils import face_utils
import imutils
import time
import dlib
import cv2


def EAR(eye):
	# 計(jì)算眼睛的兩組垂直關(guān)鍵點(diǎn)之間的歐式距離
	A = dist.euclidean(eye[1], eye[5])		# 1,5是一組垂直關(guān)鍵點(diǎn)
	B = dist.euclidean(eye[2], eye[4])		# 2,4是一組
	# 計(jì)算眼睛的一組水平關(guān)鍵點(diǎn)之間的歐式距離
	C = dist.euclidean(eye[0], eye[3])		# 0,3是一組水平關(guān)鍵點(diǎn)

	return (A + B) / (2.0 * C)

def main():

	EAR_THRESH = 0.3		# 眨眼閾值
	EYE_close = 2		# 閉眼次數(shù)閾值

	# 初始化眨眼幀計(jì)數(shù)器和總眨眼次數(shù)
	count_eye = 0
	total = 0
	detector = dlib.get_frontal_face_detector()
	predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

	# 左右眼的索引
	(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
	(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]

	vs = VideoStream(src=0).start()
	time.sleep(1.0)

	while True:

		frame = vs.read()
		frame = imutils.resize(frame, width=600)
		gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

		# 在灰度框中檢測人臉
		rects = detector(gray, 0)

		# 進(jìn)入循環(huán)
		for rect in rects:
			shape = predictor(gray, rect)
			shape = face_utils.shape_to_np(shape)

			# 提取左眼和右眼坐標(biāo),然后使用該坐標(biāo)計(jì)算兩只眼睛的眼睛縱橫比
			leftEye = shape[lStart:lEnd]
			rightEye = shape[rStart:rEnd]
			ear = EAR(leftEye) + EAR(rightEye) / 2.0
			# 判斷眼睛縱橫比是否低于眨眼閾值
			if ear < EAR_THRESH:
				count_eye += 1
			else:
				# 檢測到一次閉眼
				if count_eye >= EYE_close:
					total += 1
				count_eye = 0

			# 畫出畫框上眨眼的總次數(shù)以及計(jì)算出的幀的眼睛縱橫比
			cv2.putText(frame, "Blinks: {}".format(total), (10, 30),
				cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
			cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
				cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

		cv2.imshow("Frame", frame)
		key = cv2.waitKey(1) & 0xFF

		if key == ord("q"):
			break

	cv2.destroyAllWindows()
	vs.stop()


if __name__ == '__main__':
	main()

3.2 張嘴檢測

同理,可以做張嘴檢測:

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

from imutils.video import VideoStream
from imutils import face_utils
import imutils
import time
import dlib
import cv2
import numpy as np

def MAR(mouth):
	# 默認(rèn)二范數(shù):求特征值,然后求最大特征值得算術(shù)平方根
	A = np.linalg.norm(mouth[2] - mouth[9])  # 51, 59(人臉68個(gè)關(guān)鍵點(diǎn))
	B = np.linalg.norm(mouth[4] - mouth[7])  # 53, 57
	C = np.linalg.norm(mouth[0] - mouth[6])  # 49, 55

	return (A + B) / (2.0 * C)

def main():

	MAR_THRESH = 0.5		# 張嘴閾值

	# 初始化
	COUNTER_MOUTH = 0
	TOTAL_MOUTH = 0
	detector = dlib.get_frontal_face_detector()
	predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

	# 嘴的索引
	(mStart, mEnd) = face_utils.FACIAL_LANDMARKS_IDXS["mouth"]

	vs = VideoStream(src=0).start()
	time.sleep(1.0)

	while True:

		frame = vs.read()
		frame = imutils.resize(frame, width=600)
		gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

		# 在灰度框中檢測人臉
		rects = detector(gray, 0)

		# 進(jìn)入循環(huán)
		for rect in rects:
			shape = predictor(gray, rect)
			shape = face_utils.shape_to_np(shape)

			# 提取嘴唇坐標(biāo),然后使用該坐標(biāo)計(jì)算嘴唇縱橫比
			Mouth = shape[mStart:mEnd]
			mar = MAR(Mouth)
			# 判斷嘴唇縱橫比是否高于張嘴閾值,如果是,則增加張嘴幀計(jì)數(shù)器
			if mar > MAR_THRESH:
				COUNTER_MOUTH += 1

			else:
				# 如果張嘴幀計(jì)數(shù)器不等于0,則增加張嘴的總次數(shù)
				if COUNTER_MOUTH >= 2:
					TOTAL_MOUTH += 1
				COUNTER_MOUTH = 0

			cv2.putText(frame, "Mouth is open: {}".format(TOTAL_MOUTH), (10, 60),
						cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
			cv2.putText(frame, "MAR: {:.2f}".format(mar), (300, 60),
						cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

		cv2.imshow("Frame", frame)
		key = cv2.waitKey(1) & 0xFF

		if key == ord("q"):
			break

	cv2.destroyAllWindows()
	vs.stop()


if __name__ == '__main__':
	main()

3.3 搖頭檢測

在手機(jī)很多App如支付寶中,搖頭也屬于非常常見的活體檢測手段,此項(xiàng)采用鼻子到左右臉的歐氏距離變化,判斷是否搖頭。

通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測

代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-401870.html

from scipy.spatial import distance as dist
from imutils.video import VideoStream
from imutils import face_utils
import imutils
import time
import dlib
import cv2


def nose_jaw_distance(nose, jaw):
	# 計(jì)算鼻子上一點(diǎn)"27"到左右臉邊界的歐式距離
	face_left1 = dist.euclidean(nose[0], jaw[0])		# 27, 0
	face_right1 = dist.euclidean(nose[0], jaw[16])		# 27, 16
	# 計(jì)算鼻子上一點(diǎn)"30"到左右臉邊界的歐式距離
	face_left2 = dist.euclidean(nose[3], jaw[2])  		# 30, 2
	face_right2 = dist.euclidean(nose[3], jaw[14])  	# 30, 14
	# 創(chuàng)建元組,用以保存4個(gè)歐式距離值
	face_distance = (face_left1, face_right1, face_left2, face_right2)

	return face_distance

def main():
	# 初始化眨眼幀計(jì)數(shù)器和總眨眼次數(shù)
	distance_left = 0
	distance_right = 0
	TOTAL_FACE = 0
	detector = dlib.get_frontal_face_detector()
	predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

	(nStart, nEnd) = face_utils.FACIAL_LANDMARKS_IDXS["nose"]
	(jStart, jEnd) = face_utils.FACIAL_LANDMARKS_IDXS['jaw']

	vs = VideoStream(src=0).start()
	time.sleep(1.0)

	while True:

		frame = vs.read()
		frame = imutils.resize(frame, width=600)
		gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

		# 在灰度框中檢測人臉
		rects = detector(gray, 0)

		# 進(jìn)入循環(huán)
		for rect in rects:
			shape = predictor(gray, rect)
			shape = face_utils.shape_to_np(shape)

			# 提取鼻子和下巴的坐標(biāo),然后使用該坐標(biāo)計(jì)算鼻子到左右臉邊界的歐式距離
			nose = shape[nStart:nEnd]
			jaw = shape[jStart:jEnd]
			NOSE_JAW_Distance = nose_jaw_distance(nose, jaw)
			# 移植鼻子到左右臉邊界的歐式距離
			face_left1 = NOSE_JAW_Distance[0]
			face_right1 = NOSE_JAW_Distance[1]
			face_left2 = NOSE_JAW_Distance[2]
			face_right2 = NOSE_JAW_Distance[3]

			# 根據(jù)鼻子到左右臉邊界的歐式距離,判斷是否搖頭
			# 左臉大于右臉
			if face_left1 >= face_right1 + 2 and face_left2 >= face_right2 + 2:
				distance_left += 1
			# 右臉大于左臉
			if face_right1 >= face_left1 + 2 and face_right2 >= face_left2 + 2:
				distance_right += 1
			# 左臉大于右臉,并且右臉大于左臉,判定搖頭
			if distance_left != 0 and distance_right != 0:
				TOTAL_FACE += 1
				distance_right = 0
				distance_left = 0

			# 畫出搖頭次數(shù)
			cv2.putText(frame, "shake one's head: {}".format(TOTAL_FACE), (10, 90),
						cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

		cv2.imshow("Frame", frame)
		key = cv2.waitKey(1) & 0xFF

		if key == ord("q"):
			break

	cv2.destroyAllWindows()
	vs.stop()


if __name__ == '__main__':
	main()

到了這里,關(guān)于通過Dlib和opencv實(shí)現(xiàn)人臉識(shí)別和活體檢測的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Win10環(huán)境下通過Qt(c++)結(jié)合dlib庫,實(shí)現(xiàn)人臉識(shí)別并統(tǒng)計(jì)現(xiàn)圖像中人臉數(shù)量,ui界面化

    Win10環(huán)境下通過Qt(c++)結(jié)合dlib庫,實(shí)現(xiàn)人臉識(shí)別并統(tǒng)計(jì)現(xiàn)圖像中人臉數(shù)量,ui界面化

    ??在win10平臺(tái),通過Qt5.12以及Dlib庫,制作一個(gè)UI界面用于,實(shí)現(xiàn)人臉識(shí)別并統(tǒng)計(jì)現(xiàn)圖像中人臉數(shù)量。該界面能夠顯示當(dāng)前識(shí)別的圖像,并顯示當(dāng)前圖像中的人臉的個(gè)數(shù)。 ??本實(shí)驗(yàn)?zāi)康脑谟?,?shí)現(xiàn)dlib庫在win10平臺(tái)的Qt上運(yùn)行,不同于在python環(huán)境下的dlib庫的使用,直接 pip i

    2024年01月17日
    瀏覽(21)
  • opencv、dlib、paddlehub人臉檢測

    opencv、dlib、paddlehub人臉檢測

    opencv、dlib、paddlehub檢測效果對比。dlib和paddlehub的效果相對好一點(diǎn)。 說明:本文只做人臉檢測不識(shí)別,找識(shí)別的不用看本文。 依賴(用1個(gè)就行) dlib需要C++編譯器(gcc 或 vs) opencv檢測 ? ? dlib檢測 ?PaddleHub檢測 APIPOST調(diào)接口測試 ? ? axios調(diào)用示例 jquery調(diào)用示例

    2024年02月08日
    瀏覽(24)
  • OpenCV、Dlib 和深度學(xué)習(xí)中的各種人臉檢測方法與性能比較--包含C++ 和 Python 代碼實(shí)現(xiàn)

    文末附基于Python和C++兩種方式實(shí)現(xiàn)的測試代碼下載鏈接 在本教程中,我們將討論 OpenCV、Dlib 和深度學(xué)習(xí)中的各種人臉檢測方法,并對這些方法進(jìn)行定量比較。我們將為以下面部檢測器共享 C++ 和 Python 代碼: OpenCV 中的 Haar 級(jí)聯(lián)人臉檢測器 OpenCV 中基于深度學(xué)習(xí)的人臉檢測器。

    2024年02月10日
    瀏覽(21)
  • 人臉檢測進(jìn)階:使用 dlib、OpenCV 和 Python 檢測面部標(biāo)記

    人臉檢測進(jìn)階:使用 dlib、OpenCV 和 Python 檢測面部標(biāo)記

    3、我們將看一些將面部標(biāo)記檢測應(yīng)用于圖像的結(jié)果。 什么是面部標(biāo)記? =================================================================== 人臉標(biāo)記點(diǎn)檢測是形狀預(yù)測問題的一個(gè)子集。給定一個(gè)輸入圖像(通常是一個(gè)指定感興趣對象的ROI),形狀預(yù)測器嘗試沿形狀定位感興趣的關(guān)鍵點(diǎn)。 在

    2024年04月13日
    瀏覽(32)
  • 基于OpenCV和Dlib的深度學(xué)習(xí)人臉識(shí)別技術(shù)實(shí)踐與應(yīng)用

    基于OpenCV和Dlib的深度學(xué)習(xí)人臉識(shí)別技術(shù)實(shí)踐與應(yīng)用

    計(jì)算機(jī)視覺技術(shù)在當(dāng)前人工智能發(fā)展進(jìn)程中已然達(dá)到較高成熟度,一系列基礎(chǔ)算法與應(yīng)用場景獲得廣泛實(shí)踐與驗(yàn)證。在算法層面,圖像處理、目標(biāo)檢測、語義分割等多個(gè)領(lǐng)域的技術(shù)不斷突破,準(zhǔn)確率與效率持續(xù)提升。在應(yīng)用上,人臉識(shí)別、車牌識(shí)別、醫(yī)學(xué)圖像分析等已步入商業(yè)化應(yīng)

    2024年02月03日
    瀏覽(23)
  • 基于Python+OpenCV+dlib+Tensorflow深度學(xué)習(xí)的人臉表情識(shí)別系統(tǒng)

    基于Python+OpenCV+dlib+Tensorflow深度學(xué)習(xí)的人臉表情識(shí)別系統(tǒng)

    歡迎大家點(diǎn)贊、收藏、關(guān)注、評(píng)論啦 ,由于篇幅有限,只展示了部分核心代碼。 ??人臉表情識(shí)別是一種重要的計(jì)算機(jī)視覺任務(wù),它涉及到對人臉圖像中的表情進(jìn)行分類和理解。在這個(gè)系統(tǒng)中,我們將使用Python、OpenCV、dlib和Tensorflow來實(shí)現(xiàn)深度學(xué)習(xí)模型,以識(shí)別人臉表情。

    2024年02月01日
    瀏覽(32)
  • 基于Python_opencv人臉錄入、識(shí)別系統(tǒng)(應(yīng)用dlib機(jī)器學(xué)習(xí)庫)

    基于Python_opencv人臉錄入、識(shí)別系統(tǒng)(應(yīng)用dlib機(jī)器學(xué)習(xí)庫)

    近幾年應(yīng)用opencv機(jī)器學(xué)習(xí)方法識(shí)別人臉的技術(shù)成為了熱潮,本人根據(jù)當(dāng)今的識(shí)別技術(shù)與方法,歷時(shí)四個(gè)多月開發(fā)出一套基于dlib機(jī)器學(xué)習(xí)庫的識(shí)別項(xiàng)目。希望大家能一起交流學(xué)習(xí)。 1、項(xiàng)目功能介紹 Tkinter 人臉錄入界面, 支持錄入時(shí)設(shè)置 (中文) 姓名; 調(diào)用攝像頭進(jìn)行人臉識(shí)別

    2024年02月08日
    瀏覽(25)
  • OpenCV筆記整理【人臉檢測之Harr級(jí)聯(lián)分類器&&dlib庫】

    OpenCV筆記整理【人臉檢測之Harr級(jí)聯(lián)分類器&&dlib庫】

    1. 級(jí)聯(lián)分類器: OpenCV提供的級(jí)聯(lián)分類器有Harr、HOG、LBP這3種,這些分類器以XML文件保存,這里主要演示Harr檢測人臉(OpenCV提供的分類器不僅限于檢測人臉,還包括下表特征檢測,當(dāng)然OpenCV還支持訓(xùn)練自己的級(jí)聯(lián)分類器,這里不做說明。。。)。 2. 函數(shù)介紹: object = cv2.Casca

    2024年01月22日
    瀏覽(20)
  • 人工智能-OpenCV+Python實(shí)現(xiàn)人臉識(shí)別(人臉檢測)

    在OpenCV中使用Haar特征檢測人臉,那么需要使用OpenCV提供的xml文件(級(jí)聯(lián)表)在haarcascades目錄下。這張級(jí)聯(lián)表有一個(gè)訓(xùn)練好的AdaBoost訓(xùn)練集。首先要采用樣本的Haar特征訓(xùn)練分類器,從而得到一個(gè)級(jí)聯(lián)的AdaBoost分類器。Haar特征值反映了圖像的灰度變化情況。例如:臉部的一些特征

    2024年02月06日
    瀏覽(91)
  • python人臉識(shí)別考勤系統(tǒng) dlib+OpenCV和Pyqt5、數(shù)據(jù)庫sqlite 人臉識(shí)別系統(tǒng) 計(jì)算機(jī) 畢業(yè)設(shè)計(jì) 源碼

    python人臉識(shí)別考勤系統(tǒng) dlib+OpenCV和Pyqt5、數(shù)據(jù)庫sqlite 人臉識(shí)別系統(tǒng) 計(jì)算機(jī) 畢業(yè)設(shè)計(jì) 源碼

    Python語言、dlib、OpenCV、Pyqt5界面設(shè)計(jì)、sqlite3數(shù)據(jù)庫 本系統(tǒng)使用dlib作為人臉識(shí)別工具,dlib提供一個(gè)方法可將人臉圖片數(shù)據(jù)映射到128維度的空間向量,如果兩張圖片來源于同一個(gè)人,那么兩個(gè)圖片所映射的空間向量距離就很近,否則就會(huì)很遠(yuǎn)。因此,可以通過提取圖片并映射到

    2024年02月08日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包