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!

相關文章
相關標籤/搜索