是一个项目的一个功能之一,调试了两小时,终于能够
javascript设置开始计和暂停计时 监控人脸 记录时间了
效果图:



离开页面之后回到页面会从0计时(不是关闭页面,而是页面失去焦点)

离开摄像头时会弹出提示。

离开摄像头反馈给后端的时间。

全部代码:


<template><div class="camera_outer"><video src="../assets/shu.mp4" style="width: 600px;height: 600px;margin-left: 150px" controls="controls"></video>
<hr><el-button type="warning" @click.native="gettime()" style="margin-left: 300px"><i class="el-icon-video-camera-solid"></i> 开始听课</el-button><el-button type="primary" @click="computetime()"><i class="el-icon-price-tag"></i> 结束听课</el-button><el-button type="success" @click="out()"><i class="el-icon-loading
"></i> 暂时离开</el-button><div style="width: 130px;background: #00eeee;margin-left: 350px" v-if="this.set==true"><i class="el-icon-alarm-clock"></i>您上课的时间:<div ref="startTimer"></div></div><videoid="videoCamera":width="videoWidth":height="videoHeight"autoplay></video><br><canvasid="canvasCamera":width="videoWidth":height="videoHeight"></canvas></div></template>
<script>export default {beforeRouteLeave (to, from, next) {// 这里需要elementui的支持,如果使用其他界面组件自行替换即可this.$confirm('正在离开本页面,本页面时间将从零开始计时', '警告', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {// 正常跳转next()}).catch(() => {// 如果取消跳转地址栏会变化,这时保持地址栏不变window.history.go(1)})},data() {return {activeIndex2: '1',timer: "",content: "",hour: 0,minutes: 0,seconds: 0,videoWidth: 150,videoHeight: 150,imgSrc: "",thisCancas: null,thisContext: null,thisVideo: null,total:0,nowtime:[],set:true,yes:true,begintime:''};},created() {document.addEventListener('visibilitychange', this.startStopVideo)},mounted() {this.getCompetence();//this.gettime()var _this = this;this.thisCancas = document.getElementById("canvasCamera");this.thisContext = this.thisCancas.getContext("2d");this.thisVideo = document.getElementById("videoCamera");window.setInterval(this.setImage, 2000);},methods: {startStopVideo() {if (document.visibilityState === 'hidden') {if(this.yes==true){var stop1 = clearInterval(this.startTimer);this.yes = false;}else if(this.yes==false) {var stop2 = clearInterval(this.startTimer);this.yes = true}
window.location.reload()} else if (document.visibilityState === 'visible') {this.$message({message: '您刚刚离开了观看页面,将从零开始计时!',type: 'warning'});this.getCompetence();var _this = this;this.thisCancas = document.getElementById("canvasCamera");this.thisContext = this.thisCancas.getContext("2d");this.thisVideo = document.getElementById("videoCamera");window.setInterval(this.setImage, 2000);}
},out(){var stop1 = clearInterval(this.timer);},startTimer () {this.seconds += 1;if (this.seconds >= 60) {this.seconds = 0;this.minutes = this.minutes + 1;}if (this.minutes >= 60) {this.minutes = 0;this.hour = this.hour + 1;}this.total = this.minutes + this.hour * 60this.$refs.startTimer.innerHTML = (this.minutes < 10 ? '0' + this.minutes : this.minutes) + ':' + (this.seconds < 10 ? '0' + this.seconds : this.seconds) + '  total:' + this.total;},computetime(){var that = thisthis.set = false;this.$axios.post("/gettime",{timenot: this.nowtime,total: this.total + '分',begintime: this.begintime}).then(resp => {if (resp && resp.status === 200) {//that.$message({type: 'success',message: '您有一条新的学习记录生成!'})}})},gettime(){this.begintime=new Date().toLocaleTimeString();this.timer = setInterval(this.startTimer, 1000);},// 调用权限(打开摄像头功能)getCompetence() {var _this = this;this.thisCancas = document.getElementById("canvasCamera");this.thisContext = this.thisCancas.getContext("2d");this.thisVideo = document.getElementById("videoCamera");// 旧版本浏览器可能根本不支持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 ||navigator.getUserMedia;// 有些浏览器不支持,会返回错误信息// 保持接口一致if (!getUserMedia) {return Promise.reject(new Error("getUserMedia is not implemented in this browser"));}// 否则,使用Promise将调用包装到旧的navigator.getUserMediareturn new Promise(function (resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject);});};}var constraints = {audio: false,video: {width: this.videoWidth,height: this.videoHeight,transform: "scaleX(-1)",},};navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {// 旧的浏览器可能没有srcObjectif ("srcObject" in _this.thisVideo) {_this.thisVideo.srcObject = stream;} else {// 避免在新的浏览器中使用它,因为它正在被弃用。_this.thisVideo.src = window.URL.createObjectURL(stream);}_this.thisVideo.onloadedmetadata = function (e) {_this.thisVideo.play();};}).catch((err) => {console.log(err);});},//  绘制图片(拍照功能)setImage() {var date = new Date();date .getYear(); //获取当前年份(2位)date .getFullYear(); //获取完整的年份(4位)date .getMonth(); //获取当前月份(0-11,0代表1月)date .getDate(); //获取当前日(1-31)date.getDay(); //获取当前星期X(0-6,0代表星期天)date.getTime(); //获取当前时间(从1970.1.1开始的毫秒数)date.getHours(); //获取当前小时数(0-23)date.getMinutes(); //获取当前分钟数(0-59)date.getSeconds(); //获取当前秒数(0-59)var _this = this;_this.thisContext.drawImage(_this.thisVideo,0,0,_this.videoWidth,_this.videoHeight);// 获取图片base64链接var image = this.thisCancas.toDataURL("image/png").split('base64,')[1];_this.imgSrc = image;console.log(_this.imgSrc)this.$axios.post('http://localhost:5000/getpic', {data: _this.imgSrc}).then(resp => {if (resp && resp.status === 200) {//状态码为200为请求成功//手动构造base64路径:前缀+返回码this.base64code = 'data:image/png;base64,' + resp.data.base64codeif(resp.data == 'b'){  this.$message.error( date.getHours()+':'+date.getMinutes()+':'+date.getSeconds()+"请您勿离开摄像头视野!")let thistime =date.getHours()+':'+date.getMinutes()+':'+date.getSeconds()this.nowtime.push(thistime)}_this.thisContext.clearRect(0,0, _this.videoWidth,_this.videoHeight);// location.reload();//console.log(this.base64code)}})}}, beforeDestroy() {document.removeEventListener('visibilitychange', this.startStopVideo)}};
</script>

其中包含了图片解码编码,打开摄像头,获取后端结果。
服务器有两个,一个是python的pytorch深度学习处理图片 在flask框架下,一个是java的springboot来获得离开摄像头的时间。
java部分:
实体类:

package com.naughty.userlogin02.bean;import lombok.Data;@Data
public class Nowtime {int id;String timenot;String total;String  nowtime;String begintime;}

跨域请求:

@RestController
public class Timecontroller {@AutowiredTimeDao timeDao;static int id = 0;@CrossOrigin@PostMapping("/gettime")public String getteacherList(@RequestBody String time){id++;System.out.println(time);//    System.out.println(nowtime.getId());Map<String, Object> jsonMap = JSON.parseObject(time);System.out.println(jsonMap.get("total"));LocalDate date = LocalDate.now();System.out.println(date);Nowtime nowtime = new Nowtime();nowtime.setNowtime(date.toString());String ns=jsonMap.get("timenot").toString();String totaltime=jsonMap.get("total").toString();String begintime = jsonMap.get("begintime").toString();nowtime.setTimenot(ns);nowtime.setTotal(totaltime);nowtime.setId(id);nowtime.setBegintime(begintime);timeDao.addtime(nowtime);return "ok";//return timenot;}@GetMapping("/gettime")public String getalltime(){System.out.println("time!");List<Nowtime> nowtimes = timeDao.getall();HashMap<String, Object> res = new HashMap<>();res.put("data",nowtimes);String users_json = JSON.toJSONString(res);return users_json;}}

xml语句:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.naughty.userlogin02.dao.TimeDao"><insert id="addtime" parameterType="com.naughty.userlogin02.bean.Nowtime">insert into data1.gettime(timenot,total,nowtime,begintime) values (#{timenot},#{total},#{nowtime},#{begintime});</insert><select id="getall" resultType="com.naughty.userlogin02.bean.Nowtime">SELECT * FROM gettime<if test="nowtime !=null">WHERE nowtime like #{nowtime}</if></select>
</mapper>

python的主程序:

import base64
from predict import class_names
import torch
from torchvision import datasets, models, transforms
import cv2
import numpy as np
import requests
from flask import Flask,make_response, jsonify
import flask
from flask_cors import CORS
import socket
import threading
import json
import os
from io import BytesIO
from multiprocessing import Process
import io
from PIL import Image
# 配置全局app
app = Flask(__name__)
# 导入index中定义的所有函数
#from autotrade.server.index import *def run_index():# 启动web服务器,使用多线程方式,接收所有http请求app.run(host='0.0.0.0', port=5000, threaded=True)def make_new_response(data):res = make_response(jsonify({'code': 0, 'data': data}))res.headers['Access-Control-Allow-Origin'] = '*'res.headers['Access-Control-Allow-Method'] = '*'res.headers['Access-Control-Allow-Headers'] = '*'return resdef decode_base64(data):"""Decode base64, padding being optional.:param data: Base64 data as an ASCII byte string:returns: The decoded byte string."""missing_padding = len(data) % 4if missing_padding != 0:data += b'='* (4 - missing_padding)# return base64.decodestring(data)return base64.b64decode(data)@app.route("/test")
def test():res = "{'no':'dddd'}"return make_new_response(res)CORS(app, resources=r'/*', supports_credentials=True)basedir = os.path.abspath(os.path.dirname(__file__))transform=transforms.Compose([transforms.Resize(224),transforms.CenterCrop(224),transforms.ToTensor(),transforms.Normalize(mean=[0.485,0.456,0.406],std=[0.229,0.224,0.225])])
@app.route('/getpic', methods=['POST'])
def getpic():data = json.loads(flask.request.get_data("data"))data_64 = str.encode(data['data'])print(type(data_64))#print(data_64)print('------------------------')print(str(data_64, 'utf8'))imgdata = decode_base64(data_64)file = open('1.jpg', 'wb')file.write(imgdata)file.close()image = Image.open(r"1.jpg").convert('RGB')image = transform(image).unsqueeze(0)modelme = torch.load('modefresnet.pkl')modelme.eval()outputs = modelme(image)_, predict = torch.max(outputs.data, 1)for j in range(image.size()[0]):print('predicted: {}'.format(class_names[predict[j]]))return class_names[predict[j]]if __name__ == "__main__":app.run(debug=True)

深度学习的处理图片的网络模型就不贴了,需要的可以留言
用的是Resnet残差网络。识别速度还是很快的,判断的正确率也比较高。(训练的数据集很少,只有六百多张)

##Y1BCojf69##4;1%yBNfY3ne6a!/
下例为从指定的层提取ResNet50的特征。

import torch
from torch import nn
import torchvision.models as models
import torchvision.transforms as transforms
import cv2class FeatureExtractor(nn.Module): # 提取特征工具def __init__(self, submodule, extracted_layers):super(FeatureExtractor, self).__init__()self.submodule = submoduleself.extracted_layers = extracted_layersdef forward(self, x):outputs = []for name, module in self.submodule._modules.items():if name is "fc": x = x.view(x.size(0), -1)x = module(x)if name in self.extracted_layers:outputs.append(x)return outputsmodel = models.resnet50(pretrained=True) # 加载resnet50工具
model = model.cuda()
model.eval()img=cv2.imread('test.jpg') # 加载图片
img=cv2.resize(img,(224,224));
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
img=transform(img).cuda()
img=img.unsqueeze(0)model2 = FeatureExtractor(model, ['layer3']) # 指定提取 layer3 层特征
with torch.no_grad():out=model2(img)print(len(out), out[0].shape)

【项目实战】vue-springboot-pytorch前后端结合pytorch深度学习 html打开本地摄像头 监控人脸和记录时间相关推荐

  1. 基于vue springboot的前后端分离的化妆品商城

    基于vue springboot的前后端分离的化妆品商城 技术介绍 后端: springboot mybatis ORM框架 mysql数据库 redis分布式缓存 Druid数据库连接池 前端: V ...

  2. 【想稳,必看】毕业设计写这个你就赢了《Vue+Node 项目实战:拼多多前后端商城》

    拒绝白嫖,各位看客记得点赞评论"妙-啊~~~"在此占坑 在某个年纪之前,你可以靠透支身体.小聪明和老天给你的运气一直取巧地活着.然而到了某个年纪之后, 真正能让你走远的,都是自律. ...

  3. 停车系统源码-基于springboot+uniapp前后端完全开源的多终端智慧停车场系统源码

    一.项目简介 基于springboot+uniapp前后端完全开源的多终端智慧停车场系统源码,不存在任何私有jar. 停车场系统源码,停车源码,停车系统源码 1.功能 (1)兼容各种相机,可以根据自己 ...

  4. Vue 脚手架结合 SpringBoot 构建前后端分离入门项目(实现增删改查)

    Vue 脚手架构建前后端分离项目 项目简介与预览 数据库建表 主要模块代码 index.js 路由代码 User.vue 用户组件 RAP2 创建接口进行测试 切换路由组件的显示: this.$rou ...

  5. 使用SpringBoot + Vue (若依前后端分离版) 写项目的一些总结(持续更新...)

    使用SpringBoot + Vue(若依前后端分离版) 写项目的一些总结 获取Redis服务 @Autowired private RedisCache redisCache; String cap ...

  6. 《Vue+Spring Boot前后端分离开发实战》专著累计发行上万册

                杰哥的学术专著<Vue+Spring Boot前后端分离开发实战>由清华大学出版社于2021年3月首次出版发行,虽受疫情影响但热度不减,受到业界读者的热捧,截至今日 ...

  7. 第十六节 springboot 打包vue代码实现前后端统一部署

    svbadmin学习日志 本学习日志是使用Springboot和Vue来搭建的后台管理系统: 演示地址:http://118.31.68.110:8081/index.html 账号:root 密码: ...

  8. Vue+Spring Boot 前后端分离的商城项目开源啦!

    1 新蜂商城 Vue 移动端版本开源啦! 去年开源新蜂商城项目后,就一直在计划这个项目 Vue 版本的改造,2020 年开始开发并且自己私下一直在测试,之前也有文章介绍过测试过程和存在的问题,修改完成 ...

  9. springBoot 解决前后端分离项目中跨越请求,同源策略

    今天在做项目的过程,采用前后端分离技术的时遇到采用ajax请求无法访问后台接口,按F12,查看浏览器运行状态时,报如下错误 为了解决浏览的同源策略,就必须了解什么是同源策略. 1.什么是同源策略 同源 ...

最新文章

  1. 广东蓝桥杯c语言编译器_小软访谈之榜样充电站 千里之行,始于足下——“蓝桥杯”获奖者采访...
  2. 把现有的typesctipt+react项目接入到electron
  3. 如何得到iterator的当前元素_链表进化!双向链表+迭代器(Iterator)!
  4. 2000坐标系高程与85高程转换_科普 | 如何在大疆智图中设置坐标系
  5. 换个角度看敏捷1-敏捷问题解决方式
  6. 逻辑分析仪抓取波形参数设置
  7. 基于python + tushare 的股票盯盘脚本
  8. 解决error C2760:语法错误: 意外的令牌“标识符”,预期的令牌为“类型说明符”
  9. go io.reader 多次读取_Go 经典入门系列 24:Select
  10. 操作系统实验报告6:进程间通信—共享内存
  11. JavaScript模块化不算漫长的发展史
  12. JAVA获得当前时间的几种方法
  13. 老马的原创空间搬家通告
  14. 使用windbg调试程序
  15. GitHub的page构建自己的博客以及添加自己的域名
  16. 计算机指令与运算基础原理笔记
  17. 服务器搭建说明以及接口调用文档
  18. 【干货】信息系统项目监理浅视简识,附高清下载
  19. 启动Maven程序时报错 Error executing Maven
  20. 白嫖服务器——搭建个人简历网站(转载)

热门文章

  1. python怎么调出某年某月日历_Python 写的计算指定年指定月日历的脚本
  2. 一、华为云ModelArts环配置
  3. 五十五、手把手教你从零到一,完成淘宝数据分析案例
  4. 多元线性回归分析问题
  5. AIRAVATA:量化机器学习中的参数泄露
  6. 将“softmax+交叉熵”推广到多标签分类问题
  7. 飞桨全新发布,核心框架首次完整公开解读
  8. Java第三章 类和对象3.1+3.2
  9. Neo4j【环境部署 01】图形数据库(简介+下载地址+安装+配置+demo源码+学习教程地址)
  10. Java对象间的转化