uni-app基于百度人脸识别web实现人脸录入含活体检测

1、uni-app基于webview本地引入html文件

<template>
    <view>
        <web-view :src="url" @message="getMessage"></web-view>
    </view>
</template>

<script>
    
    export default {
        data() {
            return {
                url: '/hybrid/html/web/local.html#' // 
            }
        },
        methods: {
                        // html回调函数
            async getMessage(e) {
                // 处理人脸头像
                console.info(e.detail.data[0].photo)
                、、、
            }

        }
    }
</script>

<style>

</style>

2、html部分,上全部代码,可复制代码直接浏览器预览效果。活体检测部分,只做了微笑检测,可以根据需要进行调整。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
            content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
        <title>人脸录入</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }

            html,
            body {
                height: 100%;
            }

            .flex {
                display: flex;
            }

            .flex-row {
                flex-direction: row;
                justify-content: space-around;
                align-items: center;
            }

            .flex-column {
                flex-direction: column;
                justify-content: flex-start;
                align-items: center;
            }

            body {
                overflow: auto;
            }

            .wrap {
                width: 100%;
            }

            .wrap .reference {
                position: relative;
                padding: 10px;
                background-color: rgba(255, 255, 255, 0);
            }

            .wrap .reference img.face {
                display: block;
                width: 350px;
                height: auto;
                border-radius: 10px;
            }

            .wrap .reference img.toggle {
                position: absolute;
                right: 10px;
                top: 10px;
                width: 50px;
                height: 50px;
            }

            .wrap .scan video {
                background-color: rgba(0, 0, 0, .8);
                border-radius: 10px;
            }

            .wrap .control {
                justify-content: space-around;
                height: 456px;
                padding: 0 20px;
            }

            .wrap .control p {
                width: 160px;
                height: 60px;
                background-color: #f9f9f9;
                text-align: center;
                line-height: 60px;
                color: #ffffff;
                font-size: 24px;
                border-radius: 8px;
                cursor: pointer;
                transition: .5s;
            }

            .wrap .scan {
                position: relative;
                overflow: hidden;
            }

            .wrap .scan .strainer {
                position: absolute;
                top: 10px;
                width: 350px;
                z-index: 998;
                height: 3px;
            }

            .wrap .scan .strainer1 {
                position: absolute;
                top: 10px;
                width: 350px;
                z-index: 999;
                height: 3px;
            }

            .wrap .scan .capture {
                width: 350px;
                height: 350px;
            }

            .wrap .scan .strainer.on {
                background: linear-gradient(to left, transparent, #0bffb2, transparent);
                animation: scan 1s linear infinite;
            }

            .bg,
            .pane {
                width: 260px;
                height: 260px;
                margin: 40px auto;
                overflow: hidden;
                /* 隐藏显示区域外的内容*/
            }

            .bg {
                position: relative;
                /* background: url(images/rllr_bg.png) center center no-repeat; */
                /* border: 1px solid #b0f9e4; */
                background-size: 100% 100%;
            }

            .front {
                position: absolute;
                top: 0;
                width: 100%;
                height: 68%;
                /* background: url(images/rllr_bg.png) center center no-repeat; */
                background-size: 100% 100%;
                z-index: 9999;
            }

            .front-msg {
                position: relative;
                top: -50px;
                color: #95F9FC;
                font-size: 30px;
                width: 100%;
                height: 30px;
                text-align: center;
            }

            .btn {
                position: relative;
                top: 70px;
                border-radius: 25px;
                width: 80%;
                height: 50px;
                background: linear-gradient(-35deg, #398EF6, #3974F6);
                font-size: 18px;
            }

            .pane {
                position: absolute;
                z-index: -1;
                background: url(images/4.png) center center no-repeat;
                background-size: 100% 100%;
                animation: move 1.5s ease-in-out infinite;
                -webkit-animation: move 1.5s ease-in-out infinite;
            }

            @keyframes move {
                from {
                    top: -260px
                }

                /*网格移动到显示区域的外面*/
                to {
                    top: 0
                }
            }

            -webkit-@keyframes move {
                from {
                    top: -260px
                }

                to {
                    top: 0
                }
            }

            @keyframes scan {
                0% {
                    top: 10px;
                }

                50% {
                    top: 456px;
                }

                100% {
                    top: 10px;
                }
            }

            .btn {
                display: block;
                margin: 20px auto;
                padding: 5px;
                background-color: #007aff;
                border: none;
                color: #ffffff;
            }

            .btn::focus {
                border: none !important;
            }

            video {
                transform: rotateY(180deg);
                -webkit-transform: rotateY(180deg);
                /* Safari 和 Chrome */
                -moz-transform: rotateY(180deg);
            }
        </style>
        <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
        <!--  <script type="text/javascript" src="js/vconsole.min.js"></script> -->
        <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.1.js">
        </script>
    </head>
    <body style="background-color: #FFFFFF">
        <div class="title flex flex-column">
            <div style="width: 1px;height: 90px;"></div>
            <!--<textarea id="base64" class="title" style="width: 80%"></textarea>-->
        </div>
        <div class="wrap flex flex-row">
            <div class="control flex flex-column" style="display: none;">
                <p class="open">开启摄像头</p>
                <p class="recognition">显示到Canvas</p>
                <p class="close">关闭摄像头</p>
            </div>
            <div class="scan reference">

                <div class="strainer1">
                    <div class="bg">
                        <div class="pane"></div>
                    </div>
                </div>
                <video id="video" poster="images/2.png" class="capture" width="350" height="350" src=""
                    muted="true"></video>

            </div>

        </div>
        <div class="front">
            <img src="images/rllr_bg.png" width="100%" />
            <div class="front-msg" id="message">
            </div>
        </div>
        <button class="btn" type="button" onclick="goBackPage()">确认</button>
        <div class="title flex flex-column" dislpay="none">
            <!-- <button display="none" class="btn" type="button" id="postMessage">postMessage</button> -->
            <canvas style="display:none;" id="canvas" width="350" height="350"></canvas>
        </div>
        <script type="text/javascript">
            var buffer;
            var control = document.querySelector(".control");
            var video = document.getElementById('video');
            var canvas = document.getElementById('canvas');
            var message = document.getElementById('message');
            var context = canvas.getContext('2d');
            var count = 0,
                smile = false,
                eyeStatus = false,
                yaw = 0,
                successFace = false;

            var your_client_id = '替换成你的';
            var your_client_secret = '替换成你的';

            function closeCamera() {
                try {
                    buffer && buffer.getTracks()[1].stop(); //关闭摄像头
                } catch (e) {
                    //TODO handle the exception
                    return;
                }

            }

            (function() {
                window.addEventListener("DOMContentLoaded", function() {
                    // Grab elements, create settings, etc.
                    var mediaConfig = {
                        video: true
                    };
                    var errBack = function(e) {
                        console.log('An error has occurred!', e)
                    };
                    // Put video listeners into place
                    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
                        console.log("navigator.mediaDevices");
                        navigator.mediaDevices.getUserMedia(mediaConfig).then(function(stream) {
                            // video.src = window.URL.createObjectURL(stream);
                            video.srcObject = stream;
                            video.play();
                            buffer = stream;
                        });
                    }
                    /* Legacy code below! */
                    else if (navigator.getUserMedia) { // Standard
                        navigator.getUserMedia(mediaConfig, function(stream) {
                            video.src = stream;
                            video.play();
                            buffer = stream;
                        }, errBack);
                    } else if (navigator.mozGetUserMedia) { // Mozilla-prefixed
                        navigator.mozGetUserMedia(mediaConfig, function(stream) {
                            video.src = window.URL.createObjectURL(stream);
                            video.play();
                            buffer = stream;
                        }, errBack);
                    } else if (navigator.msGetUserMedia) { // Mozilla-prefixed
                        navigator.msGetUserMedia(mediaConfig, function(stream) {
                            video.src = window.URL.createObjectURL(stream);
                            video.play();
                            buffer = stream;
                        }, errBack);
                    } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
                        navigator.webkitGetUserMedia(mediaConfig, function(stream) {
                            video.src = window.webkitURL.createObjectURL(stream);
                            video.play();
                            buffer = stream;
                        }, errBack);
                    }
                }, false);
                document.addEventListener('UniAppJSBridgeReady', function() {
                    //获取access_token
                    var baiduAccessTokenApi =
                        `https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${your_client_id}&client_secret=${your_client_secret}`;
                    $.ajax({
                        url: baiduAccessTokenApi,
                        method: 'GET',
                        dataType: 'json',
                        success(res) {
                            var access_token = res.access_token;
                            matchFace(access_token);
                        },
                        complete() {
                            count++;
                            if (successFace || count > 30) {
                                closeCamera();
                                uni.reLaunch({
                                    url: '/pages/newMain/newMain?cheakFace=' + successFace
                                })
                            }
                        }
                    })

                    function matchFace(access_token) {
                        var baiduApi = 'https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=' +
                            access_token;
                        send();

                        function send() {
                            $.ajax({
                                url: baiduApi,
                                contentType: "application/json",
                                method: 'POST',
                                data: JSON.stringify({
                                    "image": "" + getImage(),
                                    "image_type": "BASE64",
                                    "face_type": "LIVE",
                                    "quality_control": "LOW",
                                    "liveness_control": "NORMAL",
                                    "face_field": "expression"
                                }),
                                dataType: 'json',
                                timeout: 7000,
                                success(data) {
                                    if (data.error_code == 0 && data.result.face_list[0].face_probability ==1) {
                                        successFace = true
                                        // 活体检测部分, 这里做了微笑检测,可以根据需求更改
                                        smile = data.result.face_list[0].expression.type == 'smile'
                                        message.innerHTML = '检测到人脸'
                                    } else if (!successFace) {
                                        send()
                                        successFace = false
                                        message.innerHTML = '未检测到人脸'
                                    }
                                    if (smile) {
                                        message.innerHTML = '人脸采集完成'
                                        video.pause()
                                    } else if (successFace) {
                                        send()
                                        message.innerHTML = '请保持微笑'
                                    }

                                },
                                fail() {
                                    send();
                                }
                            })
                        }
                    }
                });
            })();

            function goBackPage() {
                if (successFace && smile) {
                    closeCamera();
                    uni.postMessage({
                        data: {
                            photo: getImage()
                        }
                    });
                }
            }

            function getImage() {
                context.drawImage(video, 0, 0, 320, 320);
                // 把画布的内容转换为base64编码格式的图片
                var data = canvas.toDataURL('image/png', 1); //1表示质量(无损压缩)
                return data.replace('data:image/png;base64,', '');
            }
        </script>
    </body>
</html>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,002评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,777评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,341评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,085评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,110评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,868评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,528评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,422评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,938评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,067评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,199评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,877评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,540评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,079评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,192评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,514评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,190评论 2 357

推荐阅读更多精彩内容