最近在做人脸识别的一个需求,要给客户看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秒以内识别出人

100、网页端的人脸识别-LMLPHP

 

完整的代码请参考如下的github链接:

https://github.com/weizhenzhao/Face_Recognise

 

Thanks

WeiZhen

11-21 21:14