NVIDIA 7th SkyHackathon(八)使用 Flask 与 Vue 开发 Web

news/2024/4/25 20:13:33/文章来源:https://blog.csdn.net/u011815404/article/details/128114268

1.页面效果

Web 采用 flask+vue 开发,效果图如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.后端

import sys
import subprocess
import os
from PIL import Image
from datetime import datetime
from ASR_metrics import utils as metricsfrom werkzeug.wrappers import Request, Response
from flask import Flask, render_template, request, jsonifysys.path.append('/home/nvidia/7th_CV')
sys.path.append('/home/nvidia/7th_ASR')# ASR 路径
pathASR = "/home/nvidia/7th_ASR"# 项目路径
pathSky = '/home/nvidia'app = Flask(__name__, static_folder='')# 上传路径
uploadPath = 'uploads/'
try_model_1 = None# 主页
@app.route('/')
def index():return render_template('sky7.html', template_folder='templates')# ------------------ASR------------------
# ASR 模型加载
@app.route('/asr/load')
def asrLoad():global try_model_1if try_model_1 == None:import nemo.collections.asr as nemo_asrprint('Loading Nemo')# 加载模型try_model_1 = nemo_asr.models.EncDecCTCModel.restore_from("/home/nvidia/7th_ASR/7th_asr_model.nemo")print('Done loading Nemo')return 'ok'# POST 请求上传音频
@app.route('/asr/upload', methods=['POST'])
def asrUpload():if request.method == 'POST':f = request.files['file']if(f.headers.get('Content-Type') != 'audio/wav'):return '音频格式有错误', 400else:fileName = f'{uploadPath}audio.wav'f.save(fileName)dt = datetime.now()ts = str(int(datetime.timestamp(dt)))return jsonify(f'/{uploadPath}audio.wav?t={ts}')# 识别上传的音频
@app.route('/asr/identify', methods=['GET', 'POST'])
def asrIdentify():global try_model_1if try_model_1 == None:return '模型无效,请重新加载', 500try:asr_result = try_model_1.transcribe(paths2audio_files=["uploads/audio.wav"])s1 = request.form.get('defaultText')s2 = " ".join(asr_result)#识别结果result = {"asr_result": asr_result,"word_error_rate": metrics.calculate_cer(s1,s2),"word_accuracy_rate":1-metrics.calculate_cer(s1,s2)}return jsonify(result)except Exception as e:return '无法识别', 400# ------------------CV------------------# POST 请求上传图片
@app.route("/cv/upload", methods=['POST'])
def cvUpload():if request.method == 'POST':f = request.files['file']print('image', f, f.filename)if not 'image' in f.headers.get('Content-Type'):return '图片有错误', 400original = f'{uploadPath}original.jpg'try:# Convert image to jpegim = Image.open(f)rgb_im = im.convert('RGB')rgb_im.save(original)# Add timestampdt = datetime.now()ts = str(int(datetime.timestamp(dt)))return jsonify(original+'?t='+ts)except Exception as e:return '有错误', 400# 检测图片
@app.route("/api/detect/image")
def detectImage():cv_results = subprocess.Popen('python3 /home/nvidia/7th_CV/detection_image.py /home/nvidia/uploads/original.jpg', shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)print('code', cv_results.returncode)cv_results = str(cv_results.stdout.read()).split('\\n')[-2]dt = datetime.now()ts = str(int(datetime.timestamp(dt)))result = {"detection_result_image_path": f'/uploads/result.jpg?t={ts}'}return jsonify(result)# 获取 FPS,以 Json 格式返回前端
@app.route("/api/detect/fps")
def detectFPS():# Code herefps_results = subprocess.Popen('python3 /home/nvidia/7th_CV/cv_fps.py', shell = True, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)fps_results = str(fps_results.stdout.read()).split('\\n')[-2]fps_results = fps_results.split(" ")[-1]result = {"detection_FPS": fps_results,}return jsonify(result)# 获取 mAP
@app.route("/api/detect/map")
def detectMAP():# Code heremap_results = subprocess.Popen('python3 /home/nvidia/7th_CV/cv_map.py', shell = True, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)map_results = str(map_results.stdout.read())bytes(map_results, encoding="utf-8").decode()map_results = map_results[-9:-3]result = {"detection_mAP": map_results,}return jsonify(result)if __name__ == "__main__":app.run(debug=True)

3.前端

3.1 html

<html><meta http-equiv="content-type" content="text/html; charset=UTF-8"><head><script src="https://unpkg.com/vue@3"></script><script src="https://unpkg.com/axios/dist/axios.min.js"></script><link rel="stylesheet" href="//unpkg.com/layui@2.6.8/dist/css/layui.css"><script src="//unpkg.com/layui@2.6.8/dist/layui.js"></script><link rel="stylesheet" type="text/css" href="/style.css"></head><body id="app"><!-- 模型加载中 --><div class="loading" v-if="loading!=''"><div class="pad">%%loading%%</div></div><h1>7th Sky Hackathon</h1><h5>team:早八睡不醒</h5><div class="content"><div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief"><ul class="layui-tab-title"><li class="layui-this"><i class="layui-icon panel-title layui-icon">&#xe6dc;&nbsp;ASR</i></li><li><i class="layui-icon panel-title layui-icon">&#xe660;&nbsp;CV</i></li></ul><div class="layui-tab-content"><!-- ASR 开始--><div class="layui-tab-item layui-show"><div class="layui-anim layui-anim-up"><fieldset class="asr"><legend><span class="panel-title">ASR</span></legend><div class="layui-container"><!-- 1 开始 --><div class="layui-row"><div class="layui-col-md4">1.请加载语音识别模型</div><div class="layui-col-md4"><button class="layui-btn" @click="loadModel()" v-if="!modelLoaded"><iclass="layui-icon">&#xe601;&nbsp;加载</i></button><div v-if="modelLoaded" class="modelLoaded">模型加载成功</div></div></div><!-- 1 结束 --><!-- 2、3 开始 --><div class="field file"><div class="newFileUpload"><!-- 2 开始 --><div class="layui-row"><div class="layui-col-md4"><label for="file">2.请选择音频文件</label><div class="note">&nbsp;&nbsp;&nbsp;仅支持 .wav 和单声道格式</div></div><div class="layui-col-md4"><div class="userdefined-file"><input type="text" name="userdefinedFile"id="userdefinedFileAudio" value="未选择任何文件" /><button type="button">选择</button></div><input type="file" name="file" id="fileAudio"@change="handleFileUploadAudio($event)" /></div></div><!-- 2 结束 --></div><!-- 3 开始 --><div class="layui-row"><div class="layui-col-md4"> 3.请上传音频文件</div><div class="layui-col-md4"><button class="layui-btn" @click="submitFile('asr')"><iclass="layui-icon">&#xe67c;&nbsp;上传</i></button></div></div><!-- 3 结束 --></div><!-- 2、3 结束 --><!-- 4 开始 --><div class="layui-row"><div class="field"><div class="layui-col-md4"><label>4.请试听上传语音并输入正确答案</label></div><div class="layui-col-md4"><input id="answer" type="text" name="defaultText"v-model="defaultText" /></div></div></div><!-- 4 结束 --><div class="field" v-if="asrStatus=='uploaded' || asrStatus=='identified'"><!-- 试听 开始 --><div class="layui-row"><div class="audio"><div class="layui-col-md4">&nbsp;&nbsp;&nbsp; 试听 </div><div class="layui-col-md4"><audio controls :src="audioOriginal"></audio></div></div></div><!-- 试听 结束 --><!-- 5 开始 --><div class="layui-row"><div class="layui-col-md4">5.识别语音</div><div class="layui-col-md4"><div class="action"><button class="layui-btn" @click="identifyAudio()"><iclass="layui-icon">&#xe615;&nbsp;识别</i></button></div></div></div><!-- 5 结束 --></div><!-- 6 开始 --><div class="layui-row"><div class="field result asr" v-if="asrStatus=='identified'"><div class="layui-col-md4">6.指标</div><div class="layui-col-md4"><ul><li v-for="(value, key) in asrResult">%%key%%: %%value%%</li></ul></div></div></div><!-- 6 结束 --></div></fieldset></div></div><!-- ASR 结束 --><!-- CV 开始 --><div class="layui-tab-item"><div class="layui-anim layui-anim-up"><fieldset class="cv"><legend><span class="panel-title">CV</span></legend><div class="layui-container"><!-- 1 开始 --><div class="field"><div class="layui-row"><div class="layui-col-md4"><p>1. 获取 FPS</p><div class="item result">&nbsp;&nbsp;&nbsp; FPS: %%cvFps%%</div></div><div class="layui-col-md4"><div class="item action"><button @click="getFps()" class="inline layui-btn"><iclass="layui-icon">&#xe601;&nbsp;获取</i></button></div></div></div></div><!-- 1 结束 --><!-- 2 开始 --><div class="field"><div class="layui-row"><div class="layui-col-md4"><p>2. 获取 mAP</p><div class="item result">&nbsp;&nbsp;&nbsp; mAP: %%cvMap%%</div></div><div class="layui-col-md4"><div class="item"><button @click="getMap()" class="inline layui-btn"><iclass="layui-icon">&#xe601;&nbsp;获取</i></button></div></div></div></div><!-- 2 结束 --><!-- 3、4 开始 --><div class="field file"><!-- 3 开始 --><div class="newFileUpload"><div class="layui-row"><div class="layui-col-md4"><label for="file">3.请选择图像文件 </label><div class="note">&nbsp;</div></div><div class="layui-col-md4"><div class="userdefined-file"><input type="text" name="userdefinedFile"id="userdefinedFileImage" value="未选择任何文件" /><button type="button">选择</button></div><input type="file" name="file" ref="file" id="fileImage"@change="handleFileUploadImage($event)" /></div></div></div><!-- 3 结束 --><!-- 4 开始 --><div class="layui-row"><div class="layui-col-md4">4.请上传图像文件 </div><div class="layui-col-md4"><button @click="submitFile('cv')" class="layui-btn"><iclass="layui-icon">&#xe67c;&nbsp;上传</i></button></div></div><!-- 4 结束 --></div><!-- 3、4 结束 --><div class="action" v-if="imageOriginal!=''"><div class="layui-row"><div class="layui-col-md4">5.识别图片</div><div class="layui-col-md4"><button class="layui-btn" @click="identifyImage()"><iclass="layui-icon">&#xe615;&nbsp;识别</i></button><br></div></div></div><div class="field"><div class="layui-row"><div class="image original" v-if="imageOriginal!=''"><div class="layui-col-md1"><div class="label">原图</div></div><div class="layui-col-md3"><image :src="imageOriginal" /></div></div><div class="image result cv" v-if="imageResult!=''"><div class="layui-col-md1"><div class="label">结果图</div></div><div class="layui-col-md3"><image :src="imageResult" /></div></div></div></div></div></fieldset></div></div><!-- CV 结束 --></div></div></div></body><script>const {createApp} = VuecreateApp({data() {return {file: '',defaultText: '请检测出纸箱、瓶子和果皮',modelLoaded: false,imageOriginal: '',imageResult: '',audioOriginal: '',error: '',asrResult: {},cvMap: '',cvFps: '',loading: '',asrStatus: 'pending',cvStatus: 'pending'}},// Avoid conflict with Flask delimiterscompilerOptions: {delimiters: ["%%", "%%"]},methods: {async loadModel() {if (this.loading != '') return showError('在运行中,无法执行')this.loading = '加载模型中,请耐心等待...'this.modelLoaded = falsetry {var {data,status} = await axios.get('/asr/load')if (status == 200) {this.modelLoaded = true}} catch (err) {showError(err.response.data)}this.loading = ''},async submitFile(fileType) {let formData = new FormData()formData.append('file', this.file)if (this.file == "") {showError("请选择文件");return false;}statusType = fileType + 'Status'this.loading = '上传中...'try {var {data,status} = await axios.post('/' + fileType + '/upload', formData, {headers: {'Content-Type': 'multipart/form-data'}})if (status == 200) {this[statusType] = 'uploaded'if (fileType == 'cv') {this.imageOriginal = data} else {this.audioOriginal = data}}} catch (err) {showError(err.response.data)}this.loading = ''},handleFileUploadAudio(event) {document.getElementById("userdefinedFileAudio").value = document.getElementById("fileAudio").value;this.file = event.target.files[0];},handleFileUploadImage(event) {document.getElementById("userdefinedFileImage").value = document.getElementById("fileImage").value;this.file = event.target.files[0];},async identifyAudio(event) {// if (this.loading != '') return showError('在运行中,无法执行')this.loading = '识别中...'try {let formData = new FormData()formData.append('defaultText', this.defaultText)console.log('t', this.defaultText)var result = await axios.post('/asr/identify', formData)this['asrStatus'] = 'identified'this.asrResult = result.data} catch (err) {if (err.response.status == 500) this.modelLoaded = falseshowError(err.response.data)}this.loading = ''},async identifyImage(event) {if (this.loading != '') return showError('在运行中,无法执行')this.loading = '识别中...'this.cvStatus = 'pending'try {var {data} = await axios.get('/api/detect/image')this.imageResult = data['detection_result_image_path']} catch (err) {showError(err.response.data)}this.loading = ''},async getFps(event) {if (this.loading != '') return showError('在运行中,无法执行')this.loading = '获取 FPS...'try {var {data} = await axios.get('/api/detect/fps')this.cvFps = data['detection_FPS']} catch (err) {showError(err.response.data)}this.loading = ''},async getMap(event) {// 接口路径: /api/detect/map// 方式: GETif (this.loading != '') return showError('在运行中,无法执行')this.loading = '获取 mAP...'try {var {data} = await axios.get('/api/detect/map')this.cvMap = data['detection_mAP']} catch (err) {showError(err.response.data)}this.loading = ''}}}).mount('#app')function showError(msg) {layer.msg(msg || '错误')}</script>
</html>

3.2 CSS

body {font-size: 20px;margin: 0;
}.content {padding: 10px;margin: 40px;
}fieldset {border: 1px solid #ccc;padding: 10px;
}.modelLoaded {color: green;
}.note {color: #999;margin: 5px 0;font-size: 12px;
}.field {margin: 10px 0;
}.action {margin-top: 10px;
}.loading {position: fixed;top: 0;background: #E8F9D9;text-align: center;width: 100%;
}.pad {padding: 5px;
}.inline {display: inline-block;
}.field .item {margin: 5px 0;
}.image {display: inline-block;margin-right: 10px;
}.image img {max-height: 600px;
}/* 标题 */
h1,
h5 {margin: 40px;
}/* 队名 */
h5 {margin-left: 210px;
}/* 面板title */
.panel-title {font-size: 25px;
}/* 答案输入框 */
#answer {height: 40px;width: 200px;font-size: 14px;display: inline-block;vertical-align: middle;padding-right: 14px;padding-left: 14px;
}/* 音频文件选择 */
.newFileUpload {position: relative;height: 40px;line-height: 40px;
}.newFileUpload label {display: inline-block;
}.userdefined-file {position: absolute;top: 0;/* left: 200px; */z-index: 2;width: 300px;height: 40px;line-height: 40px;font-size: 0;/*应对子元素为 inline-block 引起的外边距*/
}.userdefined-file input[type="text"] {display: inline-block;vertical-align: middle;padding-right: 14px;padding-left: 14px;width: 220px;box-sizing: border-box;border: 1px solid #ccc;height: 40px;line-height: 40px;font-size: 14px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}.userdefined-file button {display: inline-block;vertical-align: middle;width: 80px;text-align: center;height: 40px;line-height: 40px;font-size: 14px;background-color: #009688;/* background-color: #f54; */border: none;color: #fff;cursor: pointer;
}.newFileUpload input[type="file"] {position: absolute;top: 0;/* left: 200px; */z-index: 3;opacity: 0;width: 300px;height: 40px;line-height: 40px;cursor: pointer;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_39222.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分层架构理论基础

一、三层架构 1、什么是三层架构 三层架构&#xff08;3-tier architecture&#xff09;通常意义上的三层架构就是将整个业务应用划分为&#xff1a;表示层&#xff08;User Interface layer&#xff09;、业务逻辑层&#xff08;Business Logic Layer&#xff09;、数据访问层…

数仓之hive自定义UDTF函数详解

学习目录一、自定义UDTF函数一、自定义UDTF函数 1.说明文档 A custom UDTF can be created by extending the GenericUDTF abstract class and then implementing the initialize, process, and possibly close methods. The initialize method is called by Hive to notify t…

本机使用python操作hdfs搭建及常见问题

一.虚拟机安装CentOS7并配置共享文件夹 二.CentOS 7 上hadoop伪分布式搭建全流程完整教程 三.本机使用python操作hdfs搭建及常见问题 四.mapreduce搭建 五.mapper-reducer编程搭建 本机使用python操作hdfs搭建及常见问题一、环境搭建1.打开虚拟机系统&#xff0c;打开hadoop2.修…

高效率开发Web安全扫描器之路(一)

一、背景 经常看到一些SRC和CNVD上厉害的大佬提交了很多的漏洞&#xff0c;一直好奇它们怎么能挖到这么多漏洞&#xff0c;开始还以为它们不上班除了睡觉就挖漏洞&#xff0c;后来有机会认识了一些大佬&#xff0c;发现它们大部分漏洞其实是通过工具挖掘的&#xff0c;比如说下…

安卓版微信8.0.31内测版出炉:安装包变小,功能变多!

人是社会性生物&#xff0c;建立依恋、经营亲密关系是人的本能&#xff0c;只不过到了网络时代之后&#xff0c;用户进行交流的方式几乎都变成了微信等社交软件。 不仅可以让用户很便捷的和朋友进行沟通&#xff0c;并且在上班办公的时候&#xff0c;也是可以轻松传输文件等&a…

MCUXpresso IDE下高度灵活的FreeMarker链接文件模板机制

一、准备工作 首先需要准备好环境&#xff0c;包含必要的软件&#xff0c;痞子衡的环境如下&#xff1a; 集成开发环境&#xff1a; MCUXpresso IDE_11.6.0_8187&#xff0c;点此下载软件开发包&#xff1a; SDK_2.12.1_EVK-MIMXRT1170&#xff08;Toolchain需包含MCUXpresso I…

Compose学习-> Text()

设置文本&#xff1a;text xxx 直接设置 Text(text "我是一个Text")引用资源文件&#xff1a;stringResource Text(text stringResource(id R.string.string_text))设置字体颜色&#xff1a;color xxx 引用系统自带的颜色 Text(text "我是一个Text"…

【毕业设计】17-基于单片机的矿井提升机_步进电机控制装置设计(原理图+仿真+源代码+实物图+答辩论文+答辩PPT)

typora-root-url: ./ 【毕业设计】17-基于单片机的矿井提升机_步进电机控制装置设计&#xff08;原理图仿真源代码实物图答辩论文答辩PPT&#xff09; 文章目录typora-root-url: ./【毕业设计】17-基于单片机的矿井提升机_步进电机控制装置设计&#xff08;原理图仿真源代码实…

C++习题2

指针调用数组元素 指针调用数组元素 int a[3][4] {{1,4,7,10},{2,5,8,11},{3,6,9,12}};int* pa[3] { a[0],a[1],a[2] };int(*pb)[4]; pb a;int** q pa;cout << *(a[2] 3)<<endl;cout << *(*(pa 2) 3)<<endl;cout << pb[2][3]<<en…

【JavaWeb】Filter

文章目录1.Filter过滤器2.Filter的初体验3.Filter的生命周期4.FilterConfig类5.FilterChain过滤器链6.Filter的拦截路径1.Filter过滤器 (1).概念及作用 Filter过滤器是JavaWeb的三大组件之一三大组件分别是:Servlet程序,Listener监听器,Filter过滤器Filter过滤器是JavaEE的规…

MBA管理类联考英语二题型答题时间及次序问题

还有不到一个月时间&#xff0c;2023年MBA联考也进入到最后的收官阶段&#xff0c;这个阶段对于多数已经系统复习过的考生&#xff0c;一般需要进行通盘梳理备考&#xff0c;而不是专注于单个模块的复习。在做试卷或真题的过程中&#xff0c;如何才能更有利于分数这个问题需要大…

闲人闲谈PS之三十五——物资备货与提前采购

惯例闲话&#xff1a;又一年快过去了&#xff0c;回想刚刚开始在CSDN上写笔记&#xff0c;还是2年前的事情。闲人其实是一个拖延症十分严重的人&#xff0c;自从开始走上写作这条路之后&#xff0c;治疗拖延症找到了办法&#xff0c;每天总有一些事情让闲人去思考&#xff0c;然…

Miniconda:在pycharm的terminal中无法使用Conda命令

在pycharm的terminal中无法使用Conda命令 问题&#xff1a; 在本地下载好conda系列后&#xff0c;在pycharm的terminal中无法使用conda命令 问题分析&#xff1a; 说的很清楚了&#xff0c;是因为当前支持的shells没有初始化conda 所以我们只需要把Shell 路径改成激活cond…

如何制作一个微信小程序【微信小程序是怎么做的】

为什么现在这么多人使用微信小程序呢&#xff1f;因为微信小程序除了便捷易开发&#xff0c;公司企业可以用来做小程序展示官网&#xff0c;商家也可以做小程序商城&#xff0c;甚至个人也可以拥有自己的小程序。那么如何制作一个微信小程序&#xff1f;微信小程序是怎么做的呢…

基于微信小程序奶茶店在线点单管理系统ssm框架-计算机毕业设计

面对目前奶茶店林立的现状&#xff0c;大城市奶茶店多为连锁奶茶店他们都有统一的管理和相应的系统。但是个别小县城和小城以及城区也有不少的奶茶店多为自营&#xff0c;这就必须店长自己管理和采购原料。大型连锁的奶茶店管理系统就不适用于分散的小型奶茶店。小型奶茶店的管…

vue开发测评系统思路及踩坑

最近公司做了一个测评系统&#xff0c;因为时间很短&#xff0c;本以为会很简单&#xff0c;没有想到踩了很多坑。 先看下部分效果图吧 然后在说下需求 1&#xff1a;所有的答案都是动态的&#xff08;例如选择是出来的是第二题&#xff0c;选择否出来的是第五题&#xff09…

如何用蓝牙实现无线定位(二)--信号塔设置

1. 配置BLE4.0模块 根据三点定位原理&#xff0c;本项目需要使用3个信号塔。3个信号塔的主体均为BLE4.0模块&#xff0c;需要把BLE4.0模块的AT指令设置为“从设备”。 方法为&#xff1a; &#xff08;1&#xff09;给控制板刷一套空的程序。初始打开arduino IDE或新建&#x…

React+Electron快速创建并打包成桌面应用

一、创建react项目 首先使用creat-react-app脚手架来创建一个react项目 # 安装 create-react-app 命令,如果已将安装请忽略 npm install -g create-react-app # 创建 react项目 create-react-app react-electron # 启动项目( create-react-app 真的超级方便啊) cd react-elec…

【电力运维】浅谈电力通信与泛在电力物联网技术的应用与发展

摘要&#xff1a;随着我国社会经济的快速发展&#xff0c;我国科技实力得到了巨大的提升&#xff0c;当前互联网通信技术在社会中得到了广泛的应用。随着电力通信技术的快速发展与更新&#xff0c;泛在电力物联网建设成为电力通讯发展的重要方向。本文已泛在电力物联网系统为核…

医院用故障电弧探测器AAFD 安科瑞 时丽花

摘 要&#xff1a; 医院运行中对于用电方面的要求越来越高&#xff0c;为了更好地体现用电价值&#xff0c;首先应该确保用电的安全性&#xff0c;尤其是对 于越来越繁杂的医院用电系统。基于此&#xff0c;在未来医院用电过程中应该加大关注力度&#xff0c;切实做好相关管理工…