百度AI人臉識別體驗

調用百度人臉AI接口實現人臉識別(深層次算法屬於BaiduAI,研究整個流程仍是花了一些時間,畢竟是新東西)前端

首先咱們先從獲取攝像頭中的人臉開始python

調用攝像頭

一開始我在想一會兒就想到的方法,openvc來調用攝像頭獲取人臉照片
可是這是針對網頁應用,若是能經過前端獲取帶有人臉的照片不更好嗎?把負載加到用戶瀏覽器處
因此就有了下面的js代碼nginx

$(document).ready(function () {
        var video = document.getElementById('video'),
        canvas = document.getElementById('canvas'),
        regButton = document.getElementById('regButton'),
        student_id = document.getElementById('student'),
        vendorUrl = window.URL || window.webkitURL;
        //媒體對象
        // 老的瀏覽器可能根本沒有實現 mediaDevices,因此咱們能夠先設置一個空的對象
        if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
        }
        // 一些瀏覽器部分支持 mediaDevices。咱們不能直接給對象設置 getUserMedia 
        // 由於這樣可能會覆蓋已有的屬性。這裏咱們只會在沒有getUserMedia屬性的時候添加它。
        if (navigator.mediaDevices.getUserMedia === undefined) {
        navigator.mediaDevices.getUserMedia = function (constraints) {

        // 首先,若是有getUserMedia的話,就得到它
        var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

        // 一些瀏覽器根本沒實現它 - 那麼就返回一個error到promise的reject來保持一個統一的接口
        if (!getUserMedia) {
            return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
        }

        // 不然,爲老的navigator.getUserMedia方法包裹一個Promise
        return new Promise(function (resolve, reject) {
                getUserMedia.call(navigator, constraints, resolve, reject);
                });
        }
        }

        navigator.mediaDevices.getUserMedia({ audio: false, video: { 'facingMode': "user" } })
            .then(function (stream) {
                    var video = document.querySelector('video');
                    // 舊的瀏覽器可能沒有srcObject
                    if ("srcObject" in video) {
                    video.srcObject = stream;
                    } else {
                    // 防止在新的瀏覽器裏使用它,由於它已經再也不支持了
                    video.src = window.URL.createObjectURL(stream);
                    }
                    video.onloadedmetadata = function (e) {
                    video.play();
                    };
                    })
        .catch(function (err) {
                console.log(err.name + ": " + err.message);
                });
        regButton.addEventListener('click', function () {

                //繪製canvas圖形
                canvas.getContext('2d').drawImage(video, 0, 0, 400, 300);

                //把canvas圖像轉爲img圖片
                var data = {
                    img: canvas.toDataURL("image/png"),
                    student_id: student_id.value
                }
                $.ajax(
                {
                    type: 'POST',
                    url: '../checkReg',
                    data: JSON.stringify(data),
                    dataType: "json",
                    complete: function(res){
                        console.log(res);
                        if (res.responseJSON) {
                            alert(res.responseJSON.msg);
                        }
                        else {
                            alert("服務端發生錯誤")
                        }
                    }
                }
                )
    });
})

這裏咱們使用navigator來調用攝像頭設備並經過canvas將video對象繪製成圖片
再經過post傳給後端就好了,這裏採用了base64的方式
同時百度接口也只接受base64格式的圖片,至此獲取圖片步掫咱們已經完成了web

後端調用百度AI接口

後端接收到圖像以後,通過一些必要的過濾措施
就能夠向百度接口post數據了,可是咱們首先要注意的就是把前端的圖像處理一下data,base64數據須要刪除","以後的數據
base64.b64decode(image.split(',')[-1])
其餘的咱們都直接放置到config文件中,方便維護和調用,具體代碼以下ajax

client = current_app.config['CLIENT']
image = base64.b64decode(image.split(',')[-1])
det_options = current_app.config['DETOPTIONS']
check_image = client.detect(image, det_options)
if check_image['result'][0]['face_probability'] != 1:
    return jsonify({"status": False, 'msg': "請對準人臉"})
groupId = current_app.config['GROUP_ID']
add_options = current_app.config['ADDOPTIONS']
userInfo = ''
result = client.addUser(result_id, userInfo,
        groupId, image, add_options)
if 'error_code' in result:
    return jsonify({"status": False, 'msg': "請檢查是否對準了攝像頭"})
check_stu_num.log_id = result['log_id']
if check_stu_num.log_id:
    return jsonify({"status": True, 'msg': "人臉更新成功"})
else:
    return jsonify({"status": True, 'msg': "註冊成功"})

其實咱們需求很簡單,就是在圖片中對比人臉庫裏的人臉識別出來他是誰,使用百度AI有點大材小用的感受
咱們能夠本身使用opencv的相關第三方庫來實現的,也能夠是使用一些簡單的機器學習算法來實現
(懶字當頭,固然使用這兩個的前提是你要去先熟悉一下他們~)算法

關於IP的肯定

這裏採用了nginx記錄x-header-ip數據來實現真實IP檢測
在nginx配置裏set一個X-Real-Ip,後端就可使用request.header['X-Real-Ip']來獲取IP地址了
一些基礎的IP僞造仍是能夠過濾掉的數據庫

關於簽到和簽出

這裏是經過判斷用戶的sign_status字段值和目前簽到距離上次簽到的時間來判斷是否上次簽出了和此次是不是簽出動做
關鍵代碼以下:json

```python
if user.sign_statue and now_time-user.signlogs[-1].signtime < timedelta(days=1):
    user.sign_statue = False
    return jsonify({"status": True, 'msg': user.name+"\n您簽出成功了~"})
    elif not user.sign_statue:
    user.sign_statue = True
    return jsonify({"status": True, 'msg': user.name+"\n您簽到成功了~\n記得簽出!!!!!!!!!"})
    else:
    user.sign_statue = True
    return jsonify({"status": False, 'msg': user.name+"\n您上次值班沒有簽出~\n就先放過你,下次別忘了哦~\n簽到成功~"})
```

關於記錄下載

就是一個對數據庫查詢和對xls文件寫入的操做
而後爲了辦公方便,讀取傳入的指定days來肯定要下載的天數
而後爲了省事,也就是辦公只須要簽到歷史,就採用了文件直接下載的形式
拋卻了後臺,只是構造密碼形式的路由就好了
類似的,用戶的錄入也是同理只是對xls的讀取操做罷了~canvas

for user in users:
    for user_signlog in user.signlogs:
        now_time = datetime.now()
        if not now_time-user_signlog.signtime < timedelta(hours=20*int(days)):
            continue
...
data.save(current_app.config['SIGN_LOGS_CONTENS']+r'/result.xls')
return send_from_directory(current_app.config['SIGN_LOGS_CONTENS'], 'result.xls')

前端頁面的實現

剛纔已經說了一個攝像頭的調用
固然也會在前端實時顯示攝像頭以便用戶拍照操做
而後也是採用了相似微信登錄頁面的樣式(或許是爲了懶省事)
中間的盒子模型,定義一下各類元素的位置和大小(後期維護能夠根據須要調整)後端

還有就是簽到點擊按鈕會有一段時間的延遲

這個動做我正在添加loading界面
以防用戶不斷的點擊button按鈕,來催促網頁有回顯

PS:數據庫的創建是一對多的形式形式

QQ截圖20180509012945.png

相關文章
相關標籤/搜索