feat(src/views/user): 人脸识别模块开发

duizhaopin_ui
duan 2 years ago
parent e213a5dc2f
commit caa026f687

@ -24,6 +24,7 @@
"path-to-regexp": "2.4.0",
"postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9",
"tracking": "^1.1.3",
"vue": "2.6.10",
"vue-router": "3.0.6",
"vuedraggable": "^2.24.3",

@ -1,5 +1,5 @@
<template>
<div></div>
<div />
</template>
<script>
export default {

@ -186,3 +186,25 @@ export function getALLRouter(data) {
return { asyncRoutes, option }
}
export let userMedia = function(constraints, success, error) {
if (navigator.mediaDevices.getUserMedia) {
userMedia = function(constraints, success, error) {
navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error)
}
} else if (navigator.webkitGetUserMedia) {
userMedia = function(constraints, success, error) {
navigator.webkitGetUserMedia(constraints, success, error)
}
} else if (navigator.mozGetUserMedia) {
userMedia = function(constraints, success, error) {
navigator.mozGetUserMedia(constraints, success, error)
}
} else if (navigator.getUserMedia) {
userMedia = function(constraints, success, error) {
navigator.getUserMedia(constraints, success, error)
}
}
userMedia(constraints, success, error)
}

@ -254,31 +254,3 @@ export default {
color: #909399;
}
</style>
<style lang="scss" scoped>
.home-top{
height: 6rem;
background: #FFFFFF;
display: flex;
align-items: center;
justify-content: space-between;
margin-right: 2rem;
margin-left: 2rem;
.home-top-left{
img{
height: 6rem;
}
}
.home-top-mid{
margin-right: 11.25rem;
img{
width: 31.25rem;
}
}
.home-top-right{
img{
height: 2.5rem;
}
}
}
</style>

@ -180,6 +180,26 @@
</div>
</span>
</el-dialog>
<el-dialog
:close-on-click-modal="false"
title="录入人脸"
:visible.sync="dialogFaceVisible"
width="400px"
@close="handleCancel"
>
<div>
<div class="face-content">
<video id="video" width="200px" height="200px" style="transform:rotateY(180deg)" autoplay />
<canvas id="canvas" width="200px" height="200px" style="transform:rotateY(180deg)" />
</div>
<div class="name">程小红</div>
<div class="code">工号779</div>
<div class="result">
请稍后<br>
正在为您录入人脸信息..
</div>
</div>
</el-dialog>
</div>
</template>
@ -187,6 +207,10 @@
import UserForm from '@/components/UserForm'
import { get_user_list, add, update, del, get_module_list, get_user_power_list, add_user_power, get_role_name_list } from '@/api/user/user'
import stringify from '@/utils/stringify'
import { userMedia } from '@/utils'
require('tracking/build/tracking-min.js')
require('tracking/build/data/face-min.js')
export default {
name: 'User',
components: { UserForm },
@ -236,7 +260,11 @@ export default {
standard_module_id: [],
consumables_module_id: [],
instrument_module_id: []
}
},
//
dialogFaceVisible: false,
videoObj: null,
trackerTask: null
}
},
created() {
@ -244,6 +272,9 @@ export default {
this.getRoleList()
this.getModelList()
},
beforeDestroy() {
this.handleCancel()
},
methods: {
getModelList() {
get_module_list().then(res => {
@ -283,7 +314,6 @@ export default {
this['isIndeterminate_' + t] = false
},
handleCheckedCitiesChange(value, t) {
console.log(value)
const checkedCount = value.length
this.$set(this, 'checkAll_' + t, checkedCount === this[t + 'Options'].length)
this['isIndeterminate_' + t] = checkedCount > 0 && checkedCount < this[ t + 'Options'].length
@ -331,7 +361,8 @@ export default {
this.dialogVisible = true
},
handleFace(index, row) {
this.dialogFaceVisible = true
this.openCamera()
},
handleRole(index, row) {
this.roleDialogVisible = true
@ -409,6 +440,65 @@ export default {
consumables_module_id: [],
instrument_module_id: []
}
},
/*
人脸识别相关
*/
openCamera() {
//
this.$nextTick(() => {
const canvas = document.getElementById('canvas')
const context = canvas.getContext('2d')
this.videoObj = document.getElementById('video')
// eslint-disable-next-line no-undef
const tracker = new tracking.ObjectTracker('face') //
tracker.setInitialScale(4)
tracker.setStepSize(2)
tracker.setEdgesDensity(0.1)
// eslint-disable-next-line no-undef
this.trackerTask = tracking.track('#video', tracker, { camera: true })
const constraints = {
video: { width: 200, height: 200 },
audio: false
}
userMedia(constraints, this.success, this.error)
tracker.on('track', (event) => {
event.data.forEach((rect) => {
// canvas
context.drawImage(this.videoObj, 0, 0, canvas.width, canvas.height)
context.font = '16px Helvetica'
context.strokeStyle = '#1890ff'
context.strokeRect(rect.x, rect.y, rect.width, rect.height)
})
if (event.data.length !== 0) {
//
// canvas toDataURL
const base64Img = canvas.toDataURL('image/jpeg')
console.log(base64Img)
}
})
})
},
handleCancel() {
this.videoObj.srcObject.getTracks()[0].stop()
this.trackerTask.stop()
},
//
success(stream) {
this.videoObj.srcObject = stream
this.videoObj.play()
},
//
error(error) {
//
console.log(`访问用户媒体设备失败${error.name}, ${error.message}`)
}
}
}
@ -439,6 +529,38 @@ export default {
float: right;
}
}
video,canvas{
position: absolute;
top: 100px;
left: 120px;
border-radius: 50%;
border: 1px solid #707070;
}
.face-content{
text-align: center;
height: 18.75rem;
width: 100%;
}
.name{
text-align: center;
font-size: 30px;
font-weight: 400;
color: #000000;
}
.code{
text-align: center;
font-size: 20px;
font-weight: 400;
color: #409EFF;
margin-top: 1rem;
}
.result {
margin-top: 1rem;
text-align: center;
color: #C0C4CC;
font-size: 24px;
font-weight: 400;
}
}
</style>

Loading…
Cancel
Save