from cv2 import cv2 as cv2
import os
import dlib
from skimage import io
import csv
import numpy as np# 要讀取人臉圖像文件的路徑
path_images_from_camera ="F:/my/"# Dlib 正向人臉檢測器
detector = dlib.get_frontal_face_detector()# Dlib 人臉預(yù)測器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")# Dlib 人臉識別模型# Face recognition model, the object maps human faces into 128D vectors
face_rec = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat")# 返回單張圖像的 128D 特征defreturn_128d_features(path_img):img_rd = io.imread(path_img)s=path_imga=s[16:17]i1=str(a)a1=s[17:]str1="/"b=a1[a1.index(str1):-4]b1=b[1:]i2=str(b1)img_gray = cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB)faces = detector(img_gray,1)for i inrange(len(faces)):landmarks = np.matrix([[p.x, p.y]for p in predictor(img_rd,faces[i]).parts()])for idx, point inenumerate(landmarks):# 68點(diǎn)的坐標(biāo)pos =(point[0,0], point[0,1])add="F:/jupyter/feature/face"+i1+"_feature"+i2+".csv"withopen(add,"a", newline="")as csvfile:writer1 = csv.writer(csvfile)writer1.writerow((idx,pos))print(add)print("%-40s %-20s"%("檢測到人臉的圖像 / image with faces detected:", path_img),'\n')# 因?yàn)橛锌赡芙叵聛淼娜四樤偃z測,檢測不出來人臉了# 所以要確保是 檢測到人臉的人臉圖像 拿去算特征iflen(faces)!=0:shape = predictor(img_gray, faces[0])face_descriptor = face_rec.compute_face_descriptor(img_gray, shape)else:face_descriptor =0print("no face")return face_descriptor# 將文件夾中照片特征提取出來, 寫入 CSVdefreturn_features_mean_personX(path_faces_personX):features_list_personX =[]photos_list = os.listdir(path_faces_personX)if photos_list:for i inrange(len(photos_list)):# 調(diào)用return_128d_features()得到128d特征print("%-40s %-20s"%("正在讀的人臉圖像 / image to read:", path_faces_personX +"/"+ photos_list[i]))features_128d = return_128d_features(path_faces_personX +"/"+ photos_list[i])# print(features_128d)# 遇到?jīng)]有檢測出人臉的圖片跳過if features_128d ==0:i +=1else:features_list_personX.append(features_128d)else:print("文件夾內(nèi)圖像文件為空 / Warning: No images in "+ path_faces_personX +'/','\n')# 計(jì)算 128D 特征的均值# N x 128D -> 1 x 128Dif features_list_personX:features_mean_personX = np.array(features_list_personX).mean(axis=0)else:features_mean_personX ='0'return features_mean_personX# 讀取某人所有的人臉圖像的數(shù)據(jù)
people = os.listdir(path_images_from_camera)
people.sort()withopen("F:/jupyter/feature/face_feature_mean.csv","w", newline="")as csvfile:#程序會(huì)新建一個(gè)表格文件來保存特征值,方便以后比對writer = csv.writer(csvfile)for person in people:print("##### "+ person +" #####")# Get the mean/average features of face/personX, it will be a list with a length of 128Dfeatures_mean_personX = return_features_mean_personX(path_images_from_camera + person)writer.writerow(features_mean_personX)print("特征均值 / The mean of features:",list(features_mean_personX))print('\n')print("所有錄入人臉數(shù)據(jù)存入 / Save all the features of faces registered into: F:/jupyter/feature/face_feature_mean.csv")
運(yùn)行結(jié)果:
三、人臉識別
代碼:
import os
import winsound # 系統(tǒng)音效from playsound import playsound # 音頻播放import dlib # 人臉處理的庫 Dlibimport csv # 存入表格import time
import sys
import numpy as np # 數(shù)據(jù)處理的庫 numpyfrom cv2 import cv2 as cv2 # 圖像處理的庫 OpenCvimport pandas as pd # 數(shù)據(jù)處理的庫 Pandas# 人臉識別模型,提取128D的特征矢量# face recognition model, the object maps human faces into 128D vectors# Refer this tutorial: http://dlib.net/python/index.html#dlib.face_recognition_model_v1
facerec = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat")#我這是在同一路徑下的,dlib_face_recognition_resnet_model_v1.dat不在#要寫為絕對路徑:"D:/****/****/dlib_face_recognition_resnet_model_v1.dat"# 計(jì)算兩個(gè)128D向量間的歐式距離# compute the e-distance between two 128D featuresdefreturn_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# 處理存放所有人臉特征的 csv
path_features_known_csv ="F:/jupyter/feature/face_feature_mean.csv"
csv_rd = pd.read_csv(path_features_known_csv, header=None)# 用來存放所有錄入人臉特征的數(shù)組# the array to save the features of faces in the database
features_known_arr =[]# 讀取已知人臉數(shù)據(jù)# print known facesfor i inrange(csv_rd.shape[0]):features_someone_arr =[]for j inrange(0,len(csv_rd.loc[i,:])):features_someone_arr.append(csv_rd.loc[i,:][j])features_known_arr.append(features_someone_arr)print("Faces in Database:",len(features_known_arr))# Dlib 檢測器和預(yù)測器# The detector and predictor will be used
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')#我這是在同一路徑下的,shape_predictor_68_face_landmarks.dat不在#要寫為絕對路徑:"D:/****/****/shape_predictor_68_face_landmarks.dat# 創(chuàng)建 cv2 攝像頭對象# cv2.VideoCapture(0) to use the default camera of PC,# and you can use local video name by use cv2.VideoCapture(filename)
cap = cv2.VideoCapture(0)# cap.set(propId, value)# 設(shè)置視頻參數(shù),propId 設(shè)置的視頻參數(shù),value 設(shè)置的參數(shù)值
cap.set(3,480)# cap.isOpened() 返回 true/false 檢查初始化是否成功# when the camera is openwhile cap.isOpened():flag, img_rd = cap.read()kk = cv2.waitKey(1)# 取灰度img_gray = cv2.cvtColor(img_rd, cv2.COLOR_RGB2GRAY)# 人臉數(shù) facesfaces = detector(img_gray,0)# 待會(huì)要寫的字體 font to write laterfont = cv2.FONT_HERSHEY_COMPLEX# 存儲(chǔ)當(dāng)前攝像頭中捕獲到的所有人臉的坐標(biāo)/名字# the list to save the positions and names of current faces capturedpos_namelist =[]name_namelist =[]# 按下 q 鍵退出# press 'q' to exitif kk ==ord('q'):breakelse:# 檢測到人臉 when face detectediflen(faces)!=0:# 獲取當(dāng)前捕獲到的圖像的所有人臉的特征,存儲(chǔ)到 features_cap_arr# get the features captured and save into features_cap_arrfeatures_cap_arr =[]for i inrange(len(faces)):shape = predictor(img_rd, faces[i])features_cap_arr.append(facerec.compute_face_descriptor(img_rd, shape))# 遍歷捕獲到的圖像中所有的人臉# traversal all the faces in the databasefor k inrange(len(faces)):print("##### camera person", k+1,"#####")# 讓人名跟隨在矩形框的下方# 確定人名的位置坐標(biāo)# 先默認(rèn)所有人不認(rèn)識,是 unknown# set the default names of faces with "unknown"name_namelist.append("unknown")# 每個(gè)捕獲人臉的名字坐標(biāo) the positions of faces capturedpos_namelist.append(tuple([faces[k].left(),int(faces[k].bottom()+(faces[k].bottom()- faces[k].top())/4)]))# 對于某張人臉,遍歷所有存儲(chǔ)的人臉特征# for every faces detected, compare the faces in the databasee_distance_list =[]for i inrange(len(features_known_arr)):# 如果 person_X 數(shù)據(jù)不為空ifstr(features_known_arr[i][0])!='0.0':print("with person",str(i +1),"the e distance: ", end='')e_distance_tmp = return_euclidean_distance(features_cap_arr[k], features_known_arr[i])print(e_distance_tmp)e_distance_list.append(e_distance_tmp)else:# 空數(shù)據(jù) person_Xe_distance_list.append(999999999)# 找出最接近的一個(gè)人臉數(shù)據(jù)是第幾個(gè)# Find the one with minimum e distancesimilar_person_num = e_distance_list.index(min(e_distance_list))print("Minimum e distance with person",int(similar_person_num)+1)# 計(jì)算人臉識別特征與數(shù)據(jù)集特征的歐氏距離# 距離小于0.4則標(biāo)出為可識別人物ifmin(e_distance_list)<0.4:# 這里可以修改攝像頭中標(biāo)出的人名# Here you can modify the names shown on the camera# 1、遍歷文件夾目錄folder_name ='F:/my/'# 最接近的人臉sum=similar_person_num+1key_id=1# 從第一個(gè)人臉數(shù)據(jù)文件夾進(jìn)行對比# 獲取文件夾中的文件名:1wang、2zhou、3...file_names = os.listdir(folder_name)for name in file_names:# print(name+'->'+str(key_id))ifsum==key_id:#winsound.Beep(300,500)# 響鈴:300頻率,500持續(xù)時(shí)間name_namelist[k]= name[1:]#人名刪去第一個(gè)數(shù)字(用于視頻輸出標(biāo)識)key_id +=1# 播放歡迎光臨音效#playsound('D:/myworkspace/JupyterNotebook/People/music/welcome.wav')# print("May be person "+str(int(similar_person_num)+1))# -----------篩選出人臉并保存到visitor文件夾------------for i, d inenumerate(faces):x1 = d.top()if d.top()>0else0y1 = d.bottom()if d.bottom()>0else0x2 = d.left()if d.left()>0else0y2 = d.right()if d.right()>0else0face = img_rd[x1:y1,x2:y2]size =64face = cv2.resize(face,(size,size))# 要存儲(chǔ)visitor人臉圖像文件的路徑path_visitors_save_dir ="F:/my/known"#自己在faces路徑下先建一個(gè)known文件,否則可能會(huì)報(bào)錯(cuò)# 存儲(chǔ)格式:2019-06-24-14-33-40wang.jpgnow_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())save_name =str(now_time)+str(name_namelist[k])+'.jpg'# print(save_name)# 本次圖片保存的完整urlsave_path = path_visitors_save_dir+'/'+ save_name # 遍歷visitor文件夾所有文件名visitor_names = os.listdir(path_visitors_save_dir)visitor_name=''for name in visitor_names:# 名字切片到分鐘數(shù):2019-06-26-11-33-00wangyu.jpgvisitor_name=(name[0:16]+'-00'+name[19:])# print(visitor_name)visitor_save=(save_name[0:16]+'-00'+save_name[19:])# print(visitor_save)# 一分鐘之內(nèi)重復(fù)的人名不保存if visitor_save!=visitor_name:cv2.imwrite(save_path, face)print('新存儲(chǔ):'+path_visitors_save_dir+'/'+str(now_time)+str(name_namelist[k])+'.jpg')else:print('重復(fù),未保存!')else:# 播放無法識別音效#playsound('D:/myworkspace/JupyterNotebook/People/music/sorry.wav')print("Unknown person")# -----保存圖片-------# -----------篩選出人臉并保存到visitor文件夾------------for i, d inenumerate(faces):x1 = d.top()if d.top()>0else0y1 = d.bottom()if d.bottom()>0else0x2 = d.left()if d.left()>0else0y2 = d.right()if d.right()>0else0face = img_rd[x1:y1,x2:y2]size =64face = cv2.resize(face,(size,size))# 要存儲(chǔ)visitor-》unknown人臉圖像文件的路徑path_visitors_save_dir ="F:/my/unknown"#自己在faces路徑下先建一個(gè)unknown文件,否則可能會(huì)報(bào)錯(cuò)# 存儲(chǔ)格式:2019-06-24-14-33-40unknown.jpgnow_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())# print(save_name)# 本次圖片保存的完整urlsave_path = path_visitors_save_dir+'/'+str(now_time)+'unknown.jpg'cv2.imwrite(save_path, face)print('新存儲(chǔ):'+path_visitors_save_dir+'/'+str(now_time)+'unknown.jpg')# 矩形框# draw rectanglefor kk, d inenumerate(faces):# 繪制矩形框cv2.rectangle(img_rd,tuple([d.left(), d.top()]),tuple([d.right(), d.bottom()]),(0,255,255),2)print('\n')# 在人臉框下面寫人臉名字# write names under rectanglefor i inrange(len(faces)):cv2.putText(img_rd, name_namelist[i], pos_namelist[i], font,0.8,(0,255,255),1, cv2.LINE_AA)print("Faces in camera now:", name_namelist,"\n")#cv2.putText(img_rd, "Press 'q': Quit", (20, 450), font, 0.8, (84, 255, 159), 1, cv2.LINE_AA)cv2.putText(img_rd,"Face Recognition",(20,40), font,1,(0,0,255),1, cv2.LINE_AA)cv2.putText(img_rd,"Visitors: "+str(len(faces)),(20,100), font,1,(0,0,255),1, cv2.LINE_AA)# 窗口顯示 show with opencvcv2.imshow("camera", img_rd)k = cv2.waitKey(1)if k ==27:# press 'ESC' to quitbreak# 釋放攝像頭 release camera
cap.release()# 刪除建立的窗口 delete all the windows
cv2.destroyAllWindows()