溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么使用VUE+faceApi.js實(shí)現(xiàn)攝像頭拍攝人臉識別

發(fā)布時(shí)間:2023-05-04 14:36:43 來源:億速云 閱讀:261 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“怎么使用VUE+faceApi.js實(shí)現(xiàn)攝像頭拍攝人臉識別”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么使用VUE+faceApi.js實(shí)現(xiàn)攝像頭拍攝人臉識別”吧!

    需求:

    前端獲取到攝像頭信息,通過模型來進(jìn)行判斷人像是否在鏡頭中,鏡頭是否有被遮擋。

    實(shí)現(xiàn)步驟:

    1、通過video標(biāo)簽來展示攝像頭中的內(nèi)容

    2、通過canvas來繪制視頻中信息進(jìn)行展示

    3、在拍照時(shí)候?qū)anvas的當(dāng)前幀轉(zhuǎn)成圖片

    第一步:下載引入必要包

    下載依賴

    face-api.js是核心依賴必須要下

    npm install face-api.js

    element-ui為了按鈕好看一點(diǎn)(可以不下) ,axios用于請求發(fā)送

    npm istall element-ui axios -S

     element-ui根據(jù)官方文檔進(jìn)行引入使用

    import Vue from 'vue';
    import ElementUI from 'element-ui';
    import 'element-ui/lib/theme-chalk/index.css';
    import App from './App.vue';
    Vue.use(ElementUI);
    new Vue({
      el: '#app',
      render: h => h(App)
    });

    下載model

    將項(xiàng)目中的model放入VUE中的public文件加下

    怎么使用VUE+faceApi.js實(shí)現(xiàn)攝像頭拍攝人臉識別

    怎么使用VUE+faceApi.js實(shí)現(xiàn)攝像頭拍攝人臉識別

    第二步:先把HTML寫上去 

    <template>
        <div>
            <el-button type="primary" @click="useCamera">打開攝像頭</el-button>
            <el-button type="plain" @click="photoShoot">拍照</el-button>
            <el-alert
                :title="httpsAlert"
                type="info"
                :closable="false"
                v-show="httpsAlert !== ''">
            </el-alert>
            <div class="videoImage" ref="faceBox">
                <video ref="video" ></video>
                <canvas ref="canvas" width="400" height="400" v-show="videoShow"></canvas>
                <img ref="image" :src="picture" alt="" v-show="pictureShow">
            </div>
        </div>
    </template>

    第三步 可以開始代碼了

    首先引入下載好的face-api.js包

    import * as faceApi from 'face-api.js'

     以下是需要用到的屬性

    1、視頻和圖片不同時(shí)出現(xiàn)

    videoShow: false,
    pictureShow: false,

    2、生成圖片后用于保存圖片路徑

    picture: '',

    3、因?yàn)樵诓僮鲿r(shí)會用到DOM所以將要用到虛擬DOM保存在data中

    canvas: null,
    video: null,
    image: null,

     4、模型識別時(shí)直接傳入此屬性,在初始化時(shí)賦值(可省略,直接卸載邏輯代碼中)

    options: ''

     5、在人臉識別時(shí)對結(jié)果進(jìn)行反饋(識別出人像數(shù)量大于1或小于1時(shí)給出提示)

    noOne: '',
    moreThanOne: '',

    6、如果用戶不是在https下進(jìn)行使用攝像頭調(diào)用給出提示

    httpsAlert: ''

    屬性準(zhǔn)備好之后就可以開始初始化了

    1、初始化模型

    2、獲取需要用到的虛擬DOM

    async init() {
        await faceApi.nets.ssdMobilenetv1.loadFromUri("/models");
        await faceApi.loadFaceLandmarkModel("/models");
        this.options = new faceApi.SsdMobilenetv1Options({
            minConfidence: 0.5, // 0.1 ~ 0.9
        });
        // 視頻中識別使用的節(jié)點(diǎn)
        this.video = this.$refs.video
        this.canvas = this.$refs.canvas
        this.image = this.$refs.image
    }

    調(diào)用攝像頭

    通過navigator.mediaDevices.getUserMedia()

    useCamera(){
        this.videoShow = true
        this.pictureShow = false
        this.cameraOptions()
    },
    cameraOptions(){
        let constraints = {
            video: {
                width: 400,
                height: 400
            }
        }
        // 如果不是通過loacalhost或者通過https訪問會將報(bào)錯(cuò)捕獲并提示
        try{
            let promise = navigator.mediaDevices.getUserMedia(constraints);
            promise.then((MediaStream) => {
                // 返回參數(shù)
                this.video.srcObject = MediaStream;
                this.video.play();
                this.recognizeFace()
            }).catch((error) => {
                console.log(error);
            });
        }catch(err){
            this.httpsAlert = `您現(xiàn)在在使用非Https訪問,
            請先在chrome://flags/#unsafely-treat-insecure-origin-as-secure中修改配置,
            添將當(dāng)前鏈接${window.location.href}添加到列表,
            并且將Insecure origins treated as secure修改為enabled,
            修改完成后請重啟瀏覽器后再次訪問!`
        }
    }

    識別視頻中的人像

    這里通過遞歸的方式將視頻中的內(nèi)容用canvas顯示

    將canvas的節(jié)點(diǎn)傳入到faceApi的方法中進(jìn)行識別

    通過faceApi返回的數(shù)組可以得到當(dāng)前人臉的識別狀況(數(shù)組長度0沒有識別到人臉,長度1識別到一個(gè)人臉...以此類推)

    async recognizeFace(){
        if (this.video.paused) return clearTimeout(this.timeout);
        this.canvas.getContext('2d', { willReadFrequently: true }).drawImage(this.video, 0, 0, 400, 400);
        const results = await faceApi.detectAllFaces(this.canvas, this.options).withFaceLandmarks();
        if(results.length === 0){
            if(this.moreThanOne !== ''){
                this.moreThanOne.close()
                this.moreThanOne = ''
            }
            if(this.noOne === ''){
                this.noOne = this.$message({
                    message: '未識別到人臉',
                    type: 'warning',
                    duration: 0
                });
            }
        }else if(results.length > 1){
            if(this.noOne !== ''){
                this.noOne.close()
                this.noOne = ''
            }
            if(this.moreThanOne === ''){
                this.moreThanOne = this.$message({
                    message: '檢測到鏡頭中有多個(gè)人',
                    type: 'warning',
                    duration: 0
                });
            }
        }else{
            if(this.noOne !== ''){
                this.noOne.close()
                this.noOne = ''
            }
            if(this.moreThanOne !== ''){
                this.moreThanOne.close()
                this.moreThanOne = ''
            }
        }
        this.timeout = setTimeout(() => {
            return this.recognizeFace()
        });
    },

    拍照上傳 

    async photoShoot(){
        // 拿到圖片的base64
        let canvas = this.canvas.toDataURL("image/png");
        // 拍照以后將video隱藏
        this.videoShow = false
        this.pictureShow = true
        // 停止攝像頭成像
        this.video.srcObject.getTracks()[0].stop()
        this.video.pause()
        if(canvas) {
            // 拍照將base64轉(zhuǎn)為file流文件
            let blob = this.dataURLtoBlob(canvas);
            let file = this.blobToFile(blob, "imgName");
            // 將blob圖片轉(zhuǎn)化路徑圖片
            let image = window.URL.createObjectURL(file)
            this.picture = image
            return
            let formData = new FormData()
            formData.append('file', this.picture)
            axios({
                method: 'post',
                url: '/user/12345',
                data: formData
            }).then(res => {
                console.log(res)
            }).catch(err => {
                console.log(err)
            })
        } else {
            console.log('canvas生成失敗')
        }
    },

    需要用到的圖片格式轉(zhuǎn)換方法 

    方法1:先將base64轉(zhuǎn)為文件

    方法2:設(shè)置新的文件中的參數(shù)信息

    dataURLtoBlob(dataurl) {
        let arr = dataurl.split(','),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);
        while(n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], {
            type: mime
        });
    },
    blobToFile(theBlob, fileName) {
        theBlob.lastModifiedDate = new Date().toLocaleDateString();
        theBlob.name = fileName;
        return theBlob;
    },

    完整代碼

    import bingImage from '@/assets/bbt1.jpg';
    import BingWallpaper from '@/assets/BingWallpaper.jpg';
    import * as faceApi from 'face-api.js'
    export default {
        name: 'Recognize',
        data(){
            return{
                videoShow: false,
                pictureShow: false,
                // 圖片地址
                picture: '',
                // 用于視頻識別的節(jié)點(diǎn)
                canvas: null,
                video: null,
                image: null,
                timeout: 0,
                // 模型識別的條件
                options: '',
                // 提示控制
                noOne: '',
                moreThanOne: '',
                // 不是通過Https訪問提示
                httpsAlert: '',
            }
        },
        mounted() {
            // 初始化
            this.init()
        },
        beforeDestroy() {
            clearTimeout(this.timeout);
        },
        methods: {
            async init() {
                await faceApi.nets.ssdMobilenetv1.loadFromUri("/models");
                await faceApi.loadFaceLandmarkModel("/models");
                this.options = new faceApi.SsdMobilenetv1Options({
                    minConfidence: 0.5, // 0.1 ~ 0.9
                });
                // 視頻中識別使用的節(jié)點(diǎn)
                this.video = this.$refs.video
                this.canvas = this.$refs.canvas
                this.image = this.$refs.image
            },
            /**
             * 使用視頻來成像攝像頭
             */
            useCamera(){
                this.videoShow = true
                this.pictureShow = false
                this.cameraOptions()
            },
            /**
             * 使用攝像頭
             */
            cameraOptions(){
                let constraints = {
                    video: {
                        width: 400,
                        height: 400
                    }
                }
                // 如果不是通過loacalhost或者通過https訪問會將報(bào)錯(cuò)捕獲并提示
                try{
                    let promise = navigator.mediaDevices.getUserMedia(constraints);
                    promise.then((MediaStream) => {
                        // 返回參數(shù)
                        this.video.srcObject = MediaStream;
                        this.video.play();
                        this.recognizeFace()
                    }).catch((error) => {
                        console.log(error);
                    });
                }catch(err){
                    this.httpsAlert = `您現(xiàn)在在使用非Https訪問,
                    請先在chrome://flags/#unsafely-treat-insecure-origin-as-secure中修改配置,
                    添將當(dāng)前鏈接${window.location.href}添加到列表,
                    并且將Insecure origins treated as secure修改為enabled,
                    修改完成后請重啟瀏覽器后再次訪問!`
                }
            },
            /**
             * 人臉識別方法
             * 通過canvas節(jié)點(diǎn)識別
             * 節(jié)點(diǎn)對象執(zhí)行遞歸識別繪制
             */
            async recognizeFace(){
                if (this.video.paused) return clearTimeout(this.timeout);
                this.canvas.getContext('2d', { willReadFrequently: true }).drawImage(this.video, 0, 0, 400, 400);
                const results = await faceApi.detectAllFaces(this.canvas, this.options).withFaceLandmarks();
                if(results.length === 0){
                    if(this.moreThanOne !== ''){
                        this.moreThanOne.close()
                        this.moreThanOne = ''
                    }
                    if(this.noOne === ''){
                        this.noOne = this.$message({
                            message: '未識別到人臉',
                            type: 'warning',
                            duration: 0
                        });
                    }
                }else if(results.length > 1){
                    if(this.noOne !== ''){
                        this.noOne.close()
                        this.noOne = ''
                    }
                    if(this.moreThanOne === ''){
                        this.moreThanOne = this.$message({
                            message: '檢測到鏡頭中有多個(gè)人',
                            type: 'warning',
                            duration: 0
                        });
                    }
                }else{
                    if(this.noOne !== ''){
                        this.noOne.close()
                        this.noOne = ''
                    }
                    if(this.moreThanOne !== ''){
                        this.moreThanOne.close()
                        this.moreThanOne = ''
                    }
                }
                // 通過canvas顯示video信息
                this.timeout = setTimeout(() => {
                    return this.recognizeFace()
                });
            },
            /**
             * 拍照上傳
             */
            async photoShoot(){
                // 拿到圖片的base64
                let canvas = this.canvas.toDataURL("image/png");
                // 拍照以后將video隱藏
                this.videoShow = false
                this.pictureShow = true
                // 停止攝像頭成像
                this.video.srcObject.getTracks()[0].stop()
                this.video.pause()
                if(canvas) {
                    // 拍照將base64轉(zhuǎn)為file流文件
                    let blob = this.dataURLtoBlob(canvas);
                    console.log(blob)
                    let file = this.blobToFile(blob, "imgName");
                    console.info(file);
                    // 將blob圖片轉(zhuǎn)化路徑圖片
                    let image = window.URL.createObjectURL(file)
                    this.picture = image
                    // 將拍照后的圖片發(fā)送給后端
                    let formData = new FormData()
                    formData.append('file', this.picture)
                    axios({
                        method: 'post',
                        url: '/user/12345',
                        data: formData
                    }).then(res => {
                        console.log(res)
                    }).catch(err => {
                        console.log(err)
                    })
                } else {
                    console.log('canvas生成失敗')
                }
            },
            /**
             * 將圖片轉(zhuǎn)為blob格式
             * dataurl 拿到的base64的數(shù)據(jù)
             */
            dataURLtoBlob(dataurl) {
                let arr = dataurl.split(','),
                    mime = arr[0].match(/:(.*?);/)[1],
                    bstr = atob(arr[1]),
                    n = bstr.length,
                    u8arr = new Uint8Array(n);
                while(n--) {
                    u8arr[n] = bstr.charCodeAt(n);
                }
                return new Blob([u8arr], {
                    type: mime
                });
            },
            /**
             * 生成文件信息
             * theBlob 文件
             * fileName 文件名字
             */
            blobToFile(theBlob, fileName) {
                theBlob.lastModifiedDate = new Date().toLocaleDateString();
                theBlob.name = fileName;
                return theBlob;
            },
        }
    }

    感謝各位的閱讀,以上就是“怎么使用VUE+faceApi.js實(shí)現(xiàn)攝像頭拍攝人臉識別”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對怎么使用VUE+faceApi.js實(shí)現(xiàn)攝像頭拍攝人臉識別這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    vue
    AI