yolov5 web端部署进行图片和视频检测

目录

1、思路

2、代码结构

3、代码运行

4、api接口代码

5、web ui界面

6、参考资料

7、代码分享 


1、思路

通过搭建flask微型服务器后端,以后通过vue搭建网页前端。flask是第一个第三方库。与其他模块一样,安装时可以直接使用python的pip命令实现。flask是web开发框架,简单易学,因此用flask来搭建web服务也非常简单。

在pycharm新建一个项目,命名为web2020,然后新建一个python文件,命名为main.py。在代码中输入如下代码:

from flask import  Flask    #导入Flask类
app=Flask(__name__)         #实例化并命名为app实例
if __name__=="__main__":app.run(port=2020,host="127.0.0.1",debug=True)   #调用run方法,设定端口号,启动服务

路由定义:

from flask import  Flask
app=Flask(__name__)@app.route('/')
def index():return 'welcome to my webpage!'if __name__=="__main__":app.run(port=2020,host="127.0.0.1",debug=True)

通过这种方式,实现python调用模型,然后通过web服务器进行数据输入输出,最后通过浏览器web页面进行展示。

2、代码结构

前端代码结构

后端代码结构

3、代码运行

4、api接口代码

import datetime
import logging as rel_log
import os
import shutil
from datetime import timedelta
from flask import *
from flask import Flask, render_template, Response
from processor.AIDetector_pytorch import Detectorimport core.main# import camera driver
if os.environ.get('CAMERA'):Camera = import_module('camera_' + os.environ['CAMERA']).Camera
else:from camera import CameraUPLOAD_FOLDER = r'./uploads'ALLOWED_EXTENSIONS = set(['png', 'jpg'])
app = Flask(__name__)
app.secret_key = 'secret!'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDERwerkzeug_logger = rel_log.getLogger('werkzeug')
werkzeug_logger.setLevel(rel_log.ERROR)# 解决缓存刷新问题
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = timedelta(seconds=1)# 添加header解决跨域
@app.after_request
def after_request(response):response.headers['Access-Control-Allow-Origin'] = '*'response.headers['Access-Control-Allow-Credentials'] = 'true'response.headers['Access-Control-Allow-Methods'] = 'POST'response.headers['Access-Control-Allow-Headers'] = 'Content-Type, X-Requested-With'return response#图片检测接口
def allowed_file(filename):return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS#@app.route('/')
#def hello_world():
#    return redirect(url_for('static', filename='./index.html'))
@app.route('/')
def index():"""Video streaming home page."""return render_template('index.html')@app.route('/upload', methods=['GET', 'POST'])
def upload_file():file = request.files['file']print(datetime.datetime.now(), file.filename)#if file and allowed_file(file.filename):src_path = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)file.save(src_path)shutil.copy(src_path, './tmp/ct')image_path = os.path.join('./tmp/ct', file.filename)pid, image_info = core.main.c_main(image_path, current_app.model, file.filename.rsplit('.', 1)[1])return jsonify({'status': 1,'image_url': 'http://127.0.0.1:5003/tmp/ct/' + pid,'draw_url': 'http://127.0.0.1:5003/tmp/draw/' + pid,'image_info': image_info})#return jsonify({'status': 0})@app.route("/download", methods=['GET'])
def download_file():# 需要知道2个参数, 第1个参数是本地目录的path, 第2个参数是文件名(带扩展名)return send_from_directory('data', 'testfile.zip', as_attachment=True)# show photo
@app.route('/tmp/<path:file>', methods=['GET'])
def show_photo(file):if request.method == 'GET':if not file is None:image_data = open(f'tmp/{file}', "rb").read()response = make_response(image_data)response.headers['Content-Type'] = 'image/png'return response#视频检测接口
def gen(camera):"""Video streaming generator function."""while True:frame = camera.get_frame()yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')@app.route('/video_start')
def video_feed():"""Video streaming route. Put this in the src attribute of an img tag."""return Response(gen(Camera()),mimetype='multipart/x-mixed-replace; boundary=frame')#视频流检测接口
#@app.route('/livestream_start')#程序启动入口
if __name__=='__main__': files = ['uploads', 'tmp/ct', 'tmp/draw','tmp/image', 'tmp/mask', 'tmp/uploads']for ff in files:if not os.path.exists(ff):os.makedirs(ff)with app.app_context():current_app.model = Detector()app.run(host='127.0.0.1', port=5003, debug=True)

5、web ui界面

<template><el-tabs stretch=true v-model="activeName" type="card" @tab-click="handleClick"><el-tab-pane  label="图片检测" name="first"><div id="Content"><el-dialogtitle="AI预测中":visible.sync="dialogTableVisible":show-close="false":close-on-press-escape="false":append-to-body="true":close-on-click-modal="false":center="true"><el-progress :percentage="percentage"></el-progress><span slot="footer" class="dialog-footer">请耐心等待约3秒钟</span></el-dialog><div id="CT"><div id="CT_image"><el-cardid="CT_image_1"class="box-card"style="border-radius: 8px;width: 800px;height: 360px;margin-bottom: -30px;"><div class="demo-image__preview1"><divv-loading="loading"element-loading-text="上传图片中"element-loading-spinner="el-icon-loading"><el-image:src="url_1"class="image_1":preview-src-list="srcList"style="border-radius: 3px 3px 0 0"><div slot="error"><div slot="placeholder" class="error"><el-buttonv-show="showbutton"type="primary"icon="el-icon-upload"class="download_bt"v-on:click="true_upload">上传图像<inputref="upload"style="display: none"name="file"type="file"@change="update"/></el-button></div></div></el-image></div><div class="img_info_1" style="border-radius: 0 0 5px 5px"><span style="color: white; letter-spacing: 6px">原始图像</span></div></div><div class="demo-image__preview2"><divv-loading="loading"element-loading-text="处理中,请耐心等待"element-loading-spinner="el-icon-loading"><el-image:src="url_2"class="image_1":preview-src-list="srcList1"style="border-radius: 3px 3px 0 0"><div slot="error"><div slot="placeholder" class="error">{{ wait_return }}</div></div></el-image></div><div class="img_info_1" style="border-radius: 0 0 5px 5px"><span style="color: white; letter-spacing: 4px">检测结果</span></div></div></el-card></div><div id="info_patient"><!-- 卡片放置表格 --><el-card style="border-radius: 8px"><div slot="header" class="clearfix"><span>检测目标</span><el-buttonstyle="margin-left: 35px"v-show="!showbutton"type="primary"icon="el-icon-upload"class="download_bt"v-on:click="true_upload2">重新选择图像<inputref="upload2"style="display: none"name="file"type="file"@change="update"/></el-button></div><el-tabs v-model="activeName"><el-tab-pane label="检测到的目标" name="first"><!-- 表格存放特征值 --><el-table:data="feature_list"height="390"borderstyle="width: 750px; text-align: center"v-loading="loading"element-loading-text="数据正在处理中,请耐心等待"element-loading-spinner="el-icon-loading"lazy><el-table-column label="目标类别" width="250px"><template slot-scope="scope"><span>{{ scope.row[2] }}</span></template></el-table-column><el-table-column label="目标大小" width="250px"><template slot-scope="scope"><span>{{ scope.row[0] }}</span></template></el-table-column><el-table-column label="置信度" width="250px"><template slot-scope="scope"><span>{{ scope.row[1] }}</span></template></el-table-column></el-table></el-tab-pane></el-tabs></el-card></div></div></div></el-tab-pane><el-tab-pane label="视频检测" name="second"><h3>视频名称</h3><img :src="vidoedectetion"> </el-tab-pane><el-tab-pane label="视频流检测" name="third"></el-tab-pane><el-tab-pane label="多路视频流检测" name="fourth"></el-tab-pane></el-tabs></template><script>
import axios from "axios";export default {name: "Content",data() {return {vidoedectetion:"http://127.0.0.1:5003" + "/video_start",server_url: "http://127.0.0.1:5003",activeName: "first",active: 0,centerDialogVisible: true,url_1: "",url_2: "",textarea: "",srcList: [],srcList1: [],feature_list: [],feature_list_1: [],feat_list: [],url: "",visible: false,wait_return: "等待上传",wait_upload: "等待上传",loading: false,table: false,isNav: false,showbutton: true,percentage: 0,fullscreenLoading: false,opacitys: {opacity: 0,},dialogTableVisible: false,};},created: function () {document.title = "Yolov5安全帽检测web推理部署";},methods: {true_upload() {this.$refs.upload.click();},true_upload2() {this.$refs.upload2.click();},next() {this.active++;},// 获得目标文件getObjectURL(file) {var url = null;if (window.createObjcectURL != undefined) {url = window.createOjcectURL(file);} else if (window.URL != undefined) {url = window.URL.createObjectURL(file);} else if (window.webkitURL != undefined) {url = window.webkitURL.createObjectURL(file);}return url;},// 上传文件update(e) {this.percentage = 0;this.dialogTableVisible = true;this.url_1 = "";this.url_2 = "";this.srcList = [];this.srcList1 = [];this.wait_return = "";this.wait_upload = "";this.feature_list = [];this.feat_list = [];this.fullscreenLoading = true;this.loading = true;this.showbutton = false;let file = e.target.files[0];this.url_1 = this.$options.methods.getObjectURL(file);let param = new FormData(); //创建form对象param.append("file", file, file.name); //通过append向form对象添加数据var timer = setInterval(() => {this.myFunc();}, 30);let config = {headers: { "Content-Type": "multipart/form-data" },}; //添加请求头axios.post(this.server_url + "/upload", param, config).then((response) => {this.percentage = 100;clearInterval(timer);this.url_1 = response.data.image_url;this.srcList.push(this.url_1);this.url_2 = response.data.draw_url;this.srcList1.push(this.url_2);this.fullscreenLoading = false;this.loading = false;this.feat_list = Object.keys(response.data.image_info);for (var i = 0; i < this.feat_list.length; i++) {response.data.image_info[this.feat_list[i]][2] = this.feat_list[i];this.feature_list.push(response.data.image_info[this.feat_list[i]]);}this.feature_list.push(response.data.image_info);this.feature_list_1 = this.feature_list[0];this.dialogTableVisible = false;this.percentage = 0;this.notice1();});},myFunc() {if (this.percentage + 33 < 99) {this.percentage = this.percentage + 33;} else {this.percentage = 99;}},drawChart() {},notice1() {this.$notify({title: "预测成功",message: "点击图片可以查看大图",duration: 0,type: "success",});},},mounted() {this.drawChart();},
};
</script><style>
.el-button {padding: 12px 20px !important;
}#hello p {font-size: 15px !important;/*line-height: 25px;*/
}.n1 .el-step__description {padding-right: 20%;font-size: 14px;line-height: 20px;/* font-weight: 400; */
}
</style><style scoped>
* {box-sizing: border-box;margin: 0;padding: 0;
}.dialog_info {margin: 20px auto;
}.text {font-size: 14px;
}.item {margin-bottom: 18px;
}.clearfix:before,
.clearfix:after {display: table;content: "";
}.clearfix:after {clear: both;
}.box-card {width: 680px;height: 200px;border-radius: 8px;margin-top: -20px;
}.divider {width: 50%;
}#CT {display: flex;height: 100%;width: 100%;flex-wrap: wrap;justify-content: center;margin: 0 auto;margin-right: 0px;max-width: 1800px;
}#CT_image_1 {width: 90%;height: 40%;margin: 0px auto;padding: 0px auto;margin-right: 180px;margin-bottom: 0px;border-radius: 4px;
}#CT_image {margin-bottom: 60px;margin-left: 30px;margin-top: 5px;
}.image_1 {width: 275px;height: 260px;background: #ffffff;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}.img_info_1 {height: 30px;width: 275px;text-align: center;background-color: #21b3b9;line-height: 30px;
}.demo-image__preview1 {width: 250px;height: 290px;margin: 20px 60px;float: left;
}.demo-image__preview2 {width: 250px;height: 290px;margin: 20px 460px;/* background-color: green; */
}.error {margin: 100px auto;width: 50%;padding: 10px;text-align: center;
}.block-sidebar {position: fixed;display: none;left: 50%;margin-left: 600px;top: 350px;width: 60px;z-index: 99;
}.block-sidebar .block-sidebar-item {font-size: 50px;color: lightblue;text-align: center;line-height: 50px;margin-bottom: 20px;cursor: pointer;display: block;
}div {display: block;
}.block-sidebar .block-sidebar-item:hover {color: #187aab;
}.download_bt {padding: 10px 16px !important;
}#upfile {width: 104px;height: 45px;background-color: #187aab;color: #fff;text-align: center;line-height: 45px;border-radius: 3px;box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.2);color: #fff;font-family: "Source Sans Pro", Verdana, sans-serif;font-size: 0.875rem;
}.file {width: 200px;height: 130px;position: absolute;left: -20px;top: 0;z-index: 1;-moz-opacity: 0;-ms-opacity: 0;-webkit-opacity: 0;opacity: 0; /*css属性&mdash;&mdash;opcity不透明度,取值0-1*/filter: alpha(opacity=0);cursor: pointer;
}#upload {position: relative;margin: 0px 0px;
}#Content {width: 85%;height: 800px;background-color: #ffffff;margin: 15px auto;display: flex;min-width: 1200px;
}.divider {background-color: #eaeaea !important;height: 2px !important;width: 100%;margin-bottom: 50px;
}.divider_1 {background-color: #ffffff;height: 2px !important;width: 100%;margin-bottom: 20px;margin: 20px auto;
}.steps {font-family: "lucida grande", "lucida sans unicode", lucida, helvetica,"Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;color: #21b3b9;text-align: center;margin: 15px auto;font-size: 20px;font-weight: bold;text-align: center;
}.step_1 {/*color: #303133 !important;*/margin: 20px 26px;
}#info_patient {margin-top: 10px;margin-right: 160px;
}
</style>

6、参考资料

yolov5-flask-web - 知乎 (zhihu.com)

Flask部署YOLOv5 - 知乎 (zhihu.com)

https://zhuanlan.zhihu.com/p/104273184

特别感谢作者

GitHub - Sharpiless/Yolov5-Flask-VUE: 基于Flask+VUE前后端,在阿里云公网WEB端部署YOLOv5目标检测模型

7、代码分享 

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

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

相关文章

【audio】alsa pcm音频路径

文章目录 AML方案音频路径分析dump alsa pcm各个音频路径的原始音频流数据 AML方案音频路径分析 一个Audio Patch用来表示一个或多个source端到一个或多个sink端。这个是从代码的注释翻译来的&#xff0c;大家可以把它比作大坝&#xff0c;可以有好几个入水口和出水口&#xf…

【Kotlin精简】第1章 基础类型

1 Kotlin基础类型 Kotlin中&#xff0c;我们可以调用任何变量的成员函数和属性&#xff0c;从这个角度来说&#xff0c;一切皆对象。某些类型可以有特殊的内部表现。例如&#xff1a;数字、字符和布尔型在运行时可以表现为基础类型&#xff08;primitivetypes&#xff09;。 …

架构师选择题--计算机网络

架构师选择题--计算机网络 22年考题21年考题20年考题19年真题2017考题 22年考题 d http:80 https:httpssl &#xff1a;443 b b pop3是邮件接收协议&#xff1a;110 SMTP是邮件发送协议&#xff1a;25 http:80 A 网络隔离&#xff1a;防火墙&#xff08;逻辑&#xff09;&…

五.docker+jenkins自动部署项目

一.敏捷开发相关概念 1.微服务的痛点 再来看一下我们的微服务架构 &#xff0c; 每个组件都需要服务器去部署&#xff0c;加起来可能需要几十个甚至上百个服务器。这样的微服务项目在部署上会遇到什么问题&#xff1f; 需要很多很多的服务器&#xff0c;服务器的采购安装&am…

【iOS】——仿写计算器

文章目录 一、实现思路二、实现方法三、判错处理 一、实现思路 先搭建好MVC框架&#xff0c;接着在各个模块中实现各自的任务。首先要创建好UI界面&#xff0c;接着根据UI界面的元素来与数据进行互动&#xff0c;其中创建UI界面需要用到Masonry布局。 二、实现方法 在calcu…

【C++面向对象侯捷下】4. pointer-like classes,关于智能指针 | 5. function-like classes,所谓仿函数

文章目录 4. pointer-like classes,关于智能指针pointer-like classes,关于智能指针 shared_ptrpointer-like classes,关于迭代器5. function-like classes&#xff0c;所谓仿函数【不懂&#xff0c;跳过】 4. pointer-like classes,关于智能指针 pointer-like classes,关于智…

win11系统下,将WSL2从系统盘(C盘)迁移到迁移到数据盘(D盘)

WSL2迁移磁盘 网上的一些方法 今天希望把WSL迁移到D盘&#xff0c;原因就是C盘剩余空间太少了&#xff0c;系统有一点卡顿&#xff0c;然后百度了一下迁移的方法&#xff0c;发现真的是八仙过海&#xff0c;各显神通啊&#xff0c;改注册表、exclude为.tar然后重新导入等等&a…

阿里云轻量应用服务器有月流量限制吗?

阿里云轻量应用服务器限制流量吗&#xff1f;部分限制&#xff0c;2核2G3M和2核4G4M这两款轻量应用服务器不限制月流量&#xff0c;其他的轻量服务器套餐有月流量限制。 腾讯云轻量应用服务器价格便宜&#xff0c;活动页面&#xff1a;aliyunbaike.com/go/tencent 细心的同学看…

Eclipse iceoryx™ - 真正的零拷贝进程间通信

1 序言 通过一个快速的背景教程&#xff0c;介绍项目范围和安装所需的所有内容以及第一个运行示例。 首先&#xff1a;什么是冰羚&#xff1f; iceoryx是一个用于各种操作系统的进程间通信&#xff08;IPC&#xff09;中间件&#xff08;目前我们支持Linux、macOS、QNX、FreeBS…

掌握 BERT:自然语言处理 (NLP) 从初级到高级的综合指南(1)

简介 BERT&#xff08;来自 Transformers 的双向编码器表示&#xff09;是 Google 开发的革命性自然语言处理 (NLP) 模型。它改变了语言理解任务的格局&#xff0c;使机器能够理解语言的上下文和细微差别。在本文[1]中&#xff0c;我们将带您踏上从 BERT 基础知识到高级概念的旅…

【单元测试】如何使用 JUnit5 框架?

JUnit5 单元测试框架使用教程 一、Junit5 是什么&#xff1f; Junit5是一个用于在Java平台上进行单元测试的框架。JUnit 5 框架主要由三部分组成&#xff1a;JUnit Platform、JUnit Jupiter 和 JUnit Vintage。 JUnit Platform&#xff1a;定义了测试引擎的 API&#xff0c;是…

No168.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…