概述
如之前的文章所述桑驱,筆者的項(xiàng)目需求是:公司預(yù)先將員工的照片錄入系統(tǒng)懂盐,此后員工訪問系統(tǒng)時(shí)褥赊,可以由前端的照相設(shè)備采集面孔,使用人臉識(shí)別技術(shù)莉恼,找到員工對(duì)應(yīng)的身份信息拌喉,實(shí)現(xiàn) 刷臉登錄 的功能,此外俐银,最好身份信息和照片都在系統(tǒng)內(nèi)尿背,盡量不使用互聯(lián)網(wǎng)服務(wù)。
Face Recognition 庫簡介
經(jīng)過前面對(duì) Face Recognition
庫的學(xué)習(xí)捶惜,實(shí)現(xiàn)了通過Python腳本實(shí)現(xiàn)命令行對(duì)2張人臉的比對(duì)與識(shí)別田藐。再次說明, Face Recognition
庫的主要接口API為:
- 人臉檢測:
face_recognition.face_locations(img, number_of_times_to_upsample=1, model="hog")
- 檢測面部特征點(diǎn):
face_landmarks(face_image, face_locations=None, model="large")
- 給臉部編碼:
face_encodings(face_image, known_face_locations=None, num_jitters=1)
- 從編碼中找出人的名字:
compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)
Face Recognition
庫簡單來說就是:給定一張照片吱七,它可以從中框出人臉汽久,并將人臉提取為特征向量。
人臉查找
關(guān)鍵在于怎么實(shí)現(xiàn)人臉的比對(duì)陪捷。如果僅僅是2張照片回窘,庫中給出的examples
是通過對(duì)特征向量求距離實(shí)現(xiàn)的。
在這個(gè)過程中市袖,根據(jù)照片求特征向量是較慢的啡直,而向量距離是很快的,因?yàn)樗皇菆?zhí)行了簡單矩陣計(jì)算苍碟,這步很快酒觅。
那么如何實(shí)現(xiàn)已有100名員工的照片,傳入一張新照片微峰,查找他是誰呢舷丹?
我也Google了網(wǎng)上其他網(wǎng)友實(shí)現(xiàn)的基于Face Recognition
庫的人臉查找,他們實(shí)現(xiàn)的方式大多擴(kuò)展了一下2張照片比對(duì)的情形蜓肆,比如face-recognition-service颜凯。它的邏輯就是:讀取圖片庫中的100張照片,逐照片分析得出特征向量1-100仗扬,形成特征向量矩陣M症概,然后對(duì)新照片,得出特征向量A早芭,計(jì)算矩陣M和A的距離彼城,選距離小于閾值的那個(gè)向量,反求對(duì)應(yīng)的人。
人臉查找邏輯優(yōu)化
前面的邏輯是可以的募壕,唯一問題在于新增人臉后特征向量增加怎么處理调炬。有的項(xiàng)目是再次執(zhí)行預(yù)處理過程,求特征矩陣這步很耗時(shí)舱馅,求距離矩陣這步非崇峙荩快速。
所以我將特征向量存入redis數(shù)據(jù)庫代嗤,查找時(shí)匀谣,直接從數(shù)據(jù)庫取出人名和他對(duì)應(yīng)的特征向量,然后組成特征矩陣资溃,計(jì)算相似度(距離矩陣)
代碼實(shí)現(xiàn)
本代碼基于 Python3
,使用的庫有 flask
烈炭、redis
溶锭、numpy
以及 face_recognition
。
#!/usr/bin/python
# -*- coding: utf-8 -*-
from flask import Flask, Response, request, jsonify
import redis
import face_recognition
import numpy as np
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
# 首頁
@app.route('/', methods=['GET'])
def index():
return '''
<!doctype html>
<title>人臉服務(wù)</title>
<a href="upload">人臉錄入</a><br>
<a href="search">人臉?biāo)阉?lt;/a>
'''
# 人臉錄入頁
@app.route('/upload', methods=['GET'])
def uploadHtml():
return '''
<!doctype html>
<title>人臉錄入</title>
<h1>人臉錄入</h1>
<form method="POST" action="upload" enctype="multipart/form-data">
姓名:<input type="text" name="name"><br>
<input type="file" name="file">
<input type="submit" value="提交">
</form>
'''
# 人臉錄入
@app.route('/upload', methods=['POST'])
def upload():
if 'file' not in request.files:
return jsonify({'code': 500, 'msg': '沒有文件'})
file = request.files['file']
name = request.form['name']
image = face_recognition.load_image_file(file)
face_locations = face_recognition.face_locations(image)
if len(face_locations) != 1:
return jsonify({'code': 500, 'msg': '人臉數(shù)量有誤'})
face_encodings = face_recognition.face_encodings(image, face_locations)
# 連數(shù)據(jù)庫
r = redis.Redis(connection_pool=pool)
# 錄入人名-對(duì)應(yīng)特征向量
r.set(name, face_encodings[0].tobytes())
return jsonify({'code': 0, 'msg': '錄入成功'})
# 人臉?biāo)阉黜?@app.route('/search', methods=['GET'])
def searchHtml():
return '''
<!doctype html>
<title>人臉?biāo)阉?lt;/title>
<h1>人臉?biāo)阉?lt;/h1>
<form method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="提交">
</form>
'''
# 人臉?biāo)阉?@app.route('/search', methods=['POST'])
def search():
if 'file' not in request.files:
return jsonify({'code': 500, 'msg': '沒有文件'})
file = request.files['file']
image = face_recognition.load_image_file(file)
face_locations = face_recognition.face_locations(image)
if len(face_locations) != 1:
return jsonify({'code': 500, 'msg': '人臉數(shù)量有誤'})
face_encodings = face_recognition.face_encodings(image, face_locations)
# 連數(shù)據(jù)庫
r = redis.Redis(connection_pool=pool)
# 取出所有的人名和它對(duì)應(yīng)的特征向量
names = r.keys()
faces = r.mget(names)
# 組成矩陣符隙,計(jì)算相似度(歐式距離)
matches = face_recognition.compare_faces([np.frombuffer(x) for x in faces], face_encodings[0])
return jsonify({'code': 0, 'names': [str(name, 'utf-8') for name, match in zip(names, matches) if match]})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5001, debug=True)
測試
- 將代碼保存為
face.py
- 通過命令啟動(dòng)代碼
python3 face.py
- 通過瀏覽器訪問
http://127.0.0.1:5001
就可以訪問服務(wù)