最近在做人脸识别的一个需求,要给客户看Demo证明我们公司可以做
其实很多时候,别的同事一听到这个需求就先说要直接调用微软云上面的服务。
其实他不懂什么叫做神经网络,也不知道什么叫做Res-net 更不知道什么叫做VGG16 , VGG19
其实也很对,知道和不知道,并没有什么区别。
即使知道了也不能怎么滴呢。也不会给你涨工资、
所以知道的意义何在。
不扯这些了,下面开始进入正题
1、前端使用的是python 的 django web框架。
2、后端使用的是face_recognition的人脸识别库
3、通过websocket 进行视频人脸识别
第一部分websocket
前端js部分代码如下所示
主要目的是建立Websocket链接,然后每200毫秒截一下视频,并且将截好的图片通过websocket发送到后台
var ws = null;
var video = $("#live").get()[0];
var canvas = $("#canvas");
var ctx = canvas.get()[0].getContext('2d');
if (window.location.protocol === "https:") {
wsproto = "wss";
} else {
wsproto = "ws";
}
if (window.location.protocol === "file:") {
wsuri = wsproto + "://127.0.0.1:8080/ws";
} else {
wsuri = wsproto + "://" + window.location.hostname + ":9001/ws";
}
if ("WebSocket" in window) {
ws = new WebSocket(wsuri);
} else if ("MozWebSocket" in window) {
ws = new MozWebSocket(wsuri);
} else {
console.log("Browser does not support WebSocket!");
}
if (ws) {
ws.onopen = function () {
console.log("Openened connection to websocket");
}
// 收到WebSocket服务器数据
ws.onmessage = function(e) {
var name = eval('('+e.data+')');
var labelName = $("#recognise_name");
// e.data contains received string.
console.log("onmessage: " + name["face_found_in_image"]);
if(name["face_found_in_image"]!=""&&name["face_found_in_image"]!=null){
stop();
labelName.text("Hi dear " + name["face_found_in_image"] + " we find you");
labelName.show();
ws.close();
}
};
// 关闭WebSocket连接
ws.onclose = function(e) {
console.log("Connection closed (wasClean = " + e.wasClean + ", code = " + e.code + ", reason = '" + e.reason + "')");
ws = null;
};
}
navigator.webkitGetUserMedia({video:true, audio:true},
function(stream) {
video.src = window.webkitURL.createObjectURL(stream);
},
function(err) {
console.log("Unable to get video stream!")
}
);
var dataURI = function dataURIToBlob(dataurl){
var arr = dataurl.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
start();
timer = setInterval(
function () {
ctx.drawImage(video, 0, 0, 480, 360);
var data = canvas.get()[0].toDataURL('image/png', 1.0);
newblob = dataURI(data);
if (ws.readyState===1) {
ws.send(newblob);
console.log(newblob)
}else{
//do something
}
}, 200);
下面部分是python的后台代码。
主要目的是通过Websocket接收前台传递过来的图片。并且将图片存储到指定目录下面
class EchoServerProtocol(WebSocketServerProtocol):
def __init__(self):
super(WebSocketServerProtocol, self).__init__()
def onMessage(self, payload, isBinary):
result = {}
face_rec_rsult=""
if isBinary:
#self.detect_faces_in_image(img_b64decode)
if len(payload) >0:
byte_stream = io.BytesIO(payload)
roiImg = Image.open(byte_stream)
imgByteArr = io.BytesIO()
roiImg.save(imgByteArr, format='png')
imgByteArr = imgByteArr.getvalue()
now = datetime.datetime.now()
tempPicturePath = "./"+now.strftime('%Y-%m-%d-%H-%M-%S')+".png"
tempPicture = open(tempPicturePath, "wb")
tempPicture.write(imgByteArr)
tempPicture.close()
face_rec_rsult = self.detect_faces_in_image(tempPicturePath)
os.remove(tempPicturePath)
print("temp picture removed")
print(face_rec_rsult)
self.sendMessage(json.dumps(face_rec_rsult).encode(encoding="utf-8"))
else:
#print("Text message received: {}".format(payload))
self.sendMessage(payload)
再下面是调用face_recognition包进行人脸识别的部分。
这里要说明,人脸的向量,是在websocket server端代码启动的时候,加载完成的。这样就可以在新的请求到来的时候
直接进行人脸识别的计算,不需要再进行Res-net的前向encoding了。提高了web的识别时间
当然下面只是代码片段。完整的代码可以去本文最下面github的链接中查看。
要说明的是开发环境是在linux下面,centos 7 。如果要在windows上面运行需要装docker或者虚拟机。之后再虚拟环境中运行本Demo
def detect_faces_in_image(self,file_stream):
#load unknow face image and encode it
imgunknow = face_recognition.load_image_file(file_stream)
unknown_face_encodings = face_recognition.face_encodings(imgunknow)
imgknow = know_user_encoding
known_face_names = [
"LiHui",
"Dehua",
"GuoMeng",
"WeiZhen"
]
face_found = False
is_weizhen = False
face_names = []
if len(unknown_face_encodings) > 0:
face_found = True
# See if the first face in the uploaded image matches the known face of Obama
start = time.time()
match_results = face_recognition.compare_faces(imgknow, unknown_face_encodings[0],tolerance=0.45)
end = time.time()
print(time.ctime(), "face_recognition_compare_faces : ", end - start)
print(match_results)
if True in match_results:
first_match_index = match_results.index(True)
name = known_face_names[first_match_index]
face_names.append(name)
# Return the result as json
result = {
"face_found_in_image": face_names
}
return result
总体的效果如下图所示。可以看出,在光线合适,角度合适,距离合适的情况下,基本能在2秒以内识别出人
完整的代码请参考如下的github链接:
https://github.com/weizhenzhao/Face_Recognise
Thanks
WeiZhen