Python的人脸识别,欧式距离比对,机器训练,人脸采集,离线识别

Python 人脸识别,比对,机器训练,离线识别.人脸采集的功能实现及code

博主仍是抱着开源精神,由于下面这些code是通过了上千次baidu和google搜索出来获得的结果及其想法,提供给你们共同窗习进步,注释的都很清楚,功能彻底实现
先上一下效果图python

image.png
(我知道我很帅,请勿吐槽,谢谢.不然请直接exit())git

很长时间没发文了,今天跟你们分享一下关于Python原生的人脸识别(不调用任何第三方的接口),离线版本.

刚开始编写的时候,参考了不少的文章,首先在此先进行感谢一波!github

文章可能讲的比较片面,可是你把我在文章的code copy下去,确定包你能用,识别率能够达到百分之90以上,代码性能有待优化.可是授之以鱼,不如授之以渔.下方我会开始从环境的部署开始讲解.有讲错或者bug的地方,欢迎给我留言.
  • 文章会从所调用的库进行介绍.然后介绍库的安装及部署,但愿你们耐心看:算法

    1. OPENCVOpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,能够运行在Linux、Windows、Android和Mac OS操做系统上。它轻量级并且高效——由一系列 C 函数和少许 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的不少通用算法
    2. Dlib is a modern C++ toolkit containing machine learning algorithms and tools for creating complex software in C++ to solve real world problems. It is used in both industry and academia in a wide range of domains including robotics, embedded devices, mobile phones, and large high performance computing environments. Dlib's open source licensing allows you to use it in any application, free of charge.摘抄自于DLIB的官网
    3. face_recognition 这是整个咱们须要进行人脸识别,比对.欧式距离分析比较重要的库
    4. 剩下比较重要的两个库,在此不作简绍:json numpy.
  • 下面将会介绍库的导入,请务必按照文中顺序跟随(文中环境,命令以mac为主)json

    1. 在安装dlib以前,首先必须安装cmake库,直接命令pip3 install cmake
    2. 安装完cmake以后继续安装boost库,命令:pip3 install boost
    3. 安装opecv库,命令 pip3 install opencv.导入的时候注意,code为:import cv2;为何是cv2,我google查过,由于版本迭代的问题.因此无需太在乎
    4. 安装完上述两个库以后,到了最麻烦的dlib库,首先仍是用命令:pip3 install dlib 进行安装.可是这只是下载下来,以下载过程比较慢,建议使用切换一下源,建议使用阿里巴巴源或者清华大学的源,下载完毕后,会提示你运行setup.py文件.这时候你须要打开python3的库的目录(以mac示例:路径为:/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/),刚才下载的dilb库就在这里,这时候你须要用命令进入该目录.执行(请注意):python setup.py install命令,请别敲错了.
    5. 若是你成功完成了上一步,下面就很简单了.咱们继续安装face_recognition库,命令仍是:pip3 install face_recognition
    6. 而后剩下的经常使用库再也不作简绍
完成上述步骤后,首先得恭喜你,完成了opencv,face_recognition,dlib的部署.继续下面的工做,您须要先进行阅读下面的文章:来自Github的 face_recognition介绍,中文翻译为同济大学的 子豪兄Tommy;

看完子豪兄Tommy的github翻译以后,请继续看face_recognition的方法介绍,这是通过博主综合评估及踩坑以后力荐的;segmentfault

好的,若是你看完了上述资料,那么我开始给你们讲解此次整我的脸识别程序的流程app

  1. 打开电脑的摄像头
    camera = cv2.VideoCapture(0) # 调用笔记本内置摄像头,因此参数为0,若是有其余的摄像头能够调整参数为1,2
  2. 调用dlib的面部68点识别训练库文件(这个已是训练好了的库,请直接使用)直接附上下载连接 传送门文件90多M,慢慢下.
    predictor = dlib.shape_predictor("lib/shape_predictor_68_face_landmarks.dat")
  3. 使用dlib进行面部识别
    detector = dlib.get_frontal_face_detector();

5.而后开始while死循环.进行检测.
6.检测到人脸后,生成特征码face_recognition.face_encodings,然后利用face_recognition的compare_faces方法进行比对
7.返回识别结果dom

8.文件目录
image.png机器学习

ok,废话已经不少.so,下面直接上code,首先从功能性示范开始(代码注释的已经很是详细了,由于我是python菜鸡)
import numpy as np;
import cv2;
import dlib;

camera = cv2.VideoCapture(0)  # 调用笔记本内置摄像头,因此参数为0,若是有其余的摄像头能够调整参数为1,2

# 注释掉opencv的面部分类识别器,由于感受不是很好使
# detector = cv2.CascadeClassifier('lib/haarcascade_frontalface_default.xml')  # 加载面部识别的分类器

# 改用dlib的面部识别
detector = dlib.get_frontal_face_detector();

# 调用dlib的面部68点识别训练库文件
predictor = dlib.shape_predictor("lib/shape_predictor_68_face_landmarks.dat")


while True:
    result, img = camera.read()  # 由于read方法反回了两个变量.因此须要定义两个变量进行接收该方法的返回值
    # exit();
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换图片为灰度
    faces = detector(gray, 1) # 检测出人脸数
    # len(faces) > 1
    # 利用cv2.putText输出
    for i in range(len(faces)):
        landmarks = np.matrix([[p.x, p.y] for p in predictor(img, faces[i]).parts()])
        # enumerate是一个Python的内置方法,用于遍历索引
        # index是序号;face是dets中取出的dlib.rectangle类的对象,包含了人脸的区域等信息
        # left()、top()、right()、bottom()都是dlib.rectangle类的方法,对应矩形四条边的位置
        for index, face in enumerate(faces):
            # 这里画出人脸框
            left = face.left()
            top = face.top()
            right = face.right()
            bottom = face.bottom()
            cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 3)

            shape = predictor(img, face)  # 寻找人脸的68个标定点
            print(shape)
            print(shape.num_parts)
            # 遍历全部点,打印出其坐标,并用蓝色的圈表示出来
            for index, pt in enumerate(shape.parts()):
                print('Part {}: {}'.format(index, pt))
                pt_pos = (pt.x, pt.y)
                cv2.circle(img, pt_pos, 2, (0, 255, 0), 1)
                
                cv2.imshow('frame', img)  # 展现

    if cv2.waitKey(1) & 0xFF == ord('q'):  # 监听键盘 每一秒检测一下是否按下了Q.
        break
    else:
        pass  


camera.release()  # 释放摄像头资源
cv2.destroyAllWindows(); # 关闭全部弹出的窗口
下面的是人脸采集
import numpy as np
import cv2
import dlib
import face_recognition

# 注释掉opencv的面部分类识别器,由于感受不是很好使
# detector = cv2.CascadeClassifier('xml/haarcascade_frontalface_default.xml')

# 改用dlib的面部识别
detector = dlib.get_frontal_face_detector()

# 调用dlib的面部68点识别训练库文件
predictor = dlib.shape_predictor("lib/shape_predictor_68_face_landmarks.dat")


camera = cv2.VideoCapture(0)  # 调用笔记本内置摄像头,因此参数为0,若是有其余的摄像头能够调整参数为1,2

i = 0 # 设置计步器

UID = input('enter your id: ')

while True:
    result, img = camera.read() # 接收噶你方法返回的结果

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为灰度

    faces = detector(gray, 1)  # 检测出人脸数

    if len(faces) == 1:

        for index, face in enumerate(faces):
            left = face.left()
            top = face.top()
            right = face.right()
            bottom = face.bottom()
            cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 3) # 画出框子
            
            i += 1 #计步器自增
            cv2.imwrite("img/user." + str(UID) + '.' + str(i) +
                        ".jpg", gray[top:bottom, left:right])  # 存储照片

            cv2.imshow('frame', img) # 展现图片
    else:
        cv2.putText(img, "Warning: can only appear for one person", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
        cv2.imshow('frame', img)
    

    if cv2.waitKey(100) & 0xFF == ord('q'): #每秒检查是否按下Q
        break
    elif i >= 20: # 20次后自动退出
        break

camera.release()
cv2.destroyAllWindows()
下面的是人脸训练
import cv2
import os
import numpy as np
from PIL import Image
import face_recognition
import json

def get_images_and_labels(path):
    image_paths = [os.path.join(path, f) for f in os.listdir(path)]
    # print(image_paths);
    faces = []
    for src in image_paths:
        data = {}
        img = cv2.imread(src)
        list_of_face_encodings = face_recognition.face_encodings(img)
        # print(list_of_face_encodings)
        if len(list_of_face_encodings):
            data['face'] = list_of_face_encodings[0].tolist()
            image_id = int(src.split('.')[1])
            data['id'] = image_id
            # print(data)
            faces.append(data)
            print(faces)
            

    return faces


result = get_images_and_labels('img')
# print(result);exit();
# print(json.jumps(result))
with open("data/data.json", "w") as f:
    json.dump(result, f, sort_keys=True, indent=4, ensure_ascii=False)
    print("加载入文件完成...")
人脸识别
import cv2
import numpy as np
import dlib
import face_recognition
import json


def bejson():
    f = open("data/data.json", encoding='utf-8') # 设置以utf-8解码模式读取文件,encoding参数必须设置,不然默认以gbk模式读取文件,当文件中包含中文时,会报错
    data = json.load(f)
    faces = []
    ids = []
    for value in data:
        faces.append(np.asarray(value['face']));
        ids.append(value['id']);
    return ids, faces


camera = cv2.VideoCapture(0)  # 调用笔记本内置摄像头,因此参数为0,若是有其余的摄像头能够调整参数为1,2

# 改用dlib的面部识别
detector = dlib.get_frontal_face_detector()

# 调用dlib的面部68点识别训练库文件
predictor = dlib.shape_predictor("lib/shape_predictor_68_face_landmarks.dat")


font = cv2.FONT_HERSHEY_SIMPLEX


def max_count(lt):
    # 定义一个字典,记录元素及次数
    d = {}
    # 记录最大次数的元素
    max_key = None
    for i in lt:
        # 判断字典中是否没有该元素
        if i not in d:
            # 计算该元素在列表中出现的次数
            count = lt.count(i)
            # 保存到字典中
            d[i] = count
            # 记录最大元素
            if count > d.get(max_key, 0):
                max_key = i
    # for key in d:
    #     if d.get(max_key, 0) < d[key]:
    #         max_key = key
    return max_key


while True:
    result, img = camera.read()  # 由于read方法反回了两个变量.因此须要定义两个变量进行接收该方法的返回值
    # exit();
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换图片为灰度
    faces = detector(gray, 1)  # 检测出人脸数
    if len(faces) == 1:
        # print(face_recognition.face_encodings(img))
        face_encoding_to_check = face_recognition.face_encodings(img)
        # print(face_encoding_to_check[0]);exit()
        # 读取json
        ids,data = bejson();
        # print(data);exit();
        result = face_recognition.compare_faces(
            data, face_encoding_to_check[0], tolerance=0.4)
        print(result)
        uidArray = []  # 识别经过的id
        for index, value in enumerate(result):
            # print(value)
            if value:
                uidArray.append(index);
        # print(uidArray)

        if uidArray:
            key = max_count(uidArray)
                # 根据索引找到json中的这我的的id
                # print(ids[key])
            cv2.putText(img, "Verify Success User: No--" +
                            str(ids[key])+"--", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
        else:
            cv2.putText(img, "Verify Fail-2", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2)

        # 利用cv2.putText输出
        for i in range(len(faces)):
            landmarks = np.matrix([[p.x, p.y] for p in predictor(img, faces[i]).parts()])
            # enumerate是一个Python的内置方法,用于遍历索引
            # index是序号;face是dets中取出的dlib.rectangle类的对象,包含了人脸的区域等信息
            # left()、top()、right()、bottom()都是dlib.rectangle类的方法,对应矩形四条边的位置
            for index, face in enumerate(faces):
                # 这里画出人脸框
                left = face.left()
                top = face.top()
                right = face.right()
                bottom = face.bottom()
                cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 3)

                shape = predictor(img, face)  # 寻找人脸的68个标定点
                # print(shape)
                # print(shape.num_parts)
                # 遍历全部点,打印出其坐标,并用蓝色的圈表示出来
                for index, pt in enumerate(shape.parts()):
                    # print('Part {}: {}'.format(index, pt))
                    pt_pos = (pt.x, pt.y)
                    cv2.circle(img, pt_pos, 2, (0, 255, 0), 1)
    else:
        cv2.putText(img, "Warning: can only appear for one person", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
    cv2.imshow('face verify-3', img)
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

camera.release()
cv2.destroyAllWindows()

由于博主并非很精通python,若是有不太ok的地方,望谅解.仅供学习!ide

happy coding! bye see you!

相关文章
相关标签/搜索