用Flask搭建简单的web模型部署服务

目录结构如下:
在这里插入图片描述

分类模型web部署

classification.py

import os
import cv2
import numpy as np
import onnxruntime
from flask import Flask, render_template, request, jsonifyapp = Flask(__name__)onnx_session = onnxruntime.InferenceSession("mobilenet_v2.onnx", providers=['CPUExecutionProvider'])input_name = []
for node in onnx_session.get_inputs():input_name.append(node.name)output_name = []
for node in onnx_session.get_outputs():output_name.append(node.name)def allowed_file(filename):return '.' in filename and filename.rsplit('.', 1)[1] in set(['bmp', 'jpg', 'JPG', 'png', 'PNG'])def preprocess(image):if image.shape[0] < image.shape[1]: #h<wimage = cv2.resize(image, (int(256*image.shape[1]/image.shape[0]), 256))else:image = cv2.resize(image, (256, int(256*image.shape[0]/image.shape[1])))crop_size = min(image.shape[0], image.shape[1])left = int((image.shape[1]-crop_size)/2)top = int((image.shape[0]-crop_size)/2)image_crop = image[top:top+crop_size, left:left+crop_size]image_crop = cv2.resize(image_crop, (224,224))image_crop = image_crop[:,:,::-1].transpose(2,0,1).astype(np.float32)   #BGR2RGB和HWC2CHWimage_crop[0,:] = (image_crop[0,:] - 123.675) / 58.395   image_crop[1,:] = (image_crop[1,:] - 116.28) / 57.12image_crop[2,:] = (image_crop[2,:] - 103.53) / 57.375return  np.expand_dims(image_crop, axis=0)  @app.route('/classification', methods=['POST', 'GET'])  # 添加路由
def classification():if request.method == 'POST':f = request.files['file']if not (f and allowed_file(f.filename)):return jsonify({"error": 1001, "msg": "only support image formats: .bmp .png .PNG .jpg .JPG"})basepath = os.path.dirname(__file__)  # 当前文件所在路径upload_path = os.path.join(basepath, 'static/images/temp.jpg')  # 注意:没有的文件夹一定要先创建,不然会提示没有该路径f.save(upload_path)image = cv2.imread(upload_path)     tensor = preprocess(image)inputs = {}for name in input_name:inputs[name] = tensor   outputs = onnx_session.run(None, inputs)[0]label = np.argmax(outputs)score = np.exp(outputs[0][label]) / np.sum(np.exp(outputs), axis=1)return render_template('classification.html', label=label, score=score[0])return render_template('upload.html')if __name__ == '__main__':app.run(host='0.0.0.0', port=8000, debug=True)

classification.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
</head>
<body><h1>请上传本地图片</h1><form action="" enctype='multipart/form-data' method='POST'><input type="file" name="file" style="margin-top:20px;"/><input type="submit" value="上传" class="button-new" style="margin-top:15px;"/></form><h2>图片类别为:{{label}}        置信度为:{{score}} </h2><img src="{{ url_for('static', filename= './images/temp.jpg') }}"  alt="你的图片被外星人劫持了~~"/>
</body>
</html>

运行程序,在浏览器输入http://127.0.0.1:8000/classification,效果展示:
在这里插入图片描述

检测模型web部署

detection.py

import os
import cv2
import numpy as np
import onnxruntime
from flask import Flask, render_template, request, jsonifyapp = Flask(__name__)class_names = ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light','fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow','elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee','skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard','tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple','sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch','potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone','microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear','hair drier', 'toothbrush'] #coco80类别      
input_shape = (640, 640) 
score_threshold = 0.2  
nms_threshold = 0.5
confidence_threshold = 0.2   onnx_session = onnxruntime.InferenceSession("yolov5n.onnx", providers=['CPUExecutionProvider'])input_name = []
for node in onnx_session.get_inputs():input_name.append(node.name)output_name = []
for node in onnx_session.get_outputs():output_name.append(node.name)def allowed_file(filename):return '.' in filename and filename.rsplit('.', 1)[1] in set(['bmp', 'jpg', 'JPG', 'png', 'PNG'])def nms(boxes, scores, score_threshold, nms_threshold):x1 = boxes[:, 0]y1 = boxes[:, 1]x2 = boxes[:, 2]y2 = boxes[:, 3]areas = (y2 - y1 + 1) * (x2 - x1 + 1)keep = []index = scores.argsort()[::-1] while index.size > 0:i = index[0]keep.append(i)x11 = np.maximum(x1[i], x1[index[1:]]) y11 = np.maximum(y1[i], y1[index[1:]])x22 = np.minimum(x2[i], x2[index[1:]])y22 = np.minimum(y2[i], y2[index[1:]])w = np.maximum(0, x22 - x11 + 1)                              h = np.maximum(0, y22 - y11 + 1) overlaps = w * hious = overlaps / (areas[i] + areas[index[1:]] - overlaps)idx = np.where(ious <= nms_threshold)[0]index = index[idx + 1]return keepdef xywh2xyxy(x):y = np.copy(x)y[:, 0] = x[:, 0] - x[:, 2] / 2y[:, 1] = x[:, 1] - x[:, 3] / 2y[:, 2] = x[:, 0] + x[:, 2] / 2y[:, 3] = x[:, 1] + x[:, 3] / 2return ydef filter_box(outputs): #过滤掉无用的框    outputs = np.squeeze(outputs)outputs = outputs[outputs[..., 4] > confidence_threshold]classes_scores = outputs[..., 5:]boxes = []scores = []class_ids = []for i in range(len(classes_scores)):class_id = np.argmax(classes_scores[i])outputs[i][4] *= classes_scores[i][class_id]outputs[i][5] = class_idif outputs[i][4] > score_threshold:boxes.append(outputs[i][:6])scores.append(outputs[i][4])class_ids.append(outputs[i][5])if len(boxes) == 0 :return      boxes = np.array(boxes)boxes = xywh2xyxy(boxes)scores = np.array(scores)indices = nms(boxes, scores, score_threshold, nms_threshold) output = boxes[indices]return outputdef letterbox(im, new_shape=(416, 416), color=(114, 114, 114)):# Resize and pad image while meeting stride-multiple constraintsshape = im.shape[:2]  # current shape [height, width]# Scale ratio (new / old)r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])# Compute paddingnew_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))    dw, dh = (new_shape[1] - new_unpad[0])/2, (new_shape[0] - new_unpad[1])/2  # wh padding top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))left, right = int(round(dw - 0.1)), int(round(dw + 0.1))if shape[::-1] != new_unpad:  # resizeim = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add borderreturn imdef scale_boxes(boxes, shape): # Rescale boxes (xyxy) from input_shape to shapegain = min(input_shape[0] / shape[0], input_shape[1] / shape[1])  # gain  = old / newpad = (input_shape[1] - shape[1] * gain) / 2, (input_shape[0] - shape[0] * gain) / 2  # wh paddingboxes[..., [0, 2]] -= pad[0]  # x paddingboxes[..., [1, 3]] -= pad[1]  # y paddingboxes[..., :4] /= gainboxes[..., [0, 2]] = boxes[..., [0, 2]].clip(0, shape[1])  # x1, x2boxes[..., [1, 3]] = boxes[..., [1, 3]].clip(0, shape[0])  # y1, y2return boxesdef draw(image, box_data):box_data = scale_boxes(box_data, image.shape)boxes = box_data[...,:4].astype(np.int32) scores = box_data[...,4]classes = box_data[...,5].astype(np.int32)for box, score, cl in zip(boxes, scores, classes):top, left, right, bottom = boxcv2.rectangle(image, (top, left), (right, bottom), (255, 0, 0), 1)cv2.putText(image, '{0} {1:.2f}'.format(class_names[cl], score), (top, left), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 1)def preprocess(img):input = letterbox(img, input_shape)input = input[:, :, ::-1].transpose(2, 0, 1).astype(dtype=np.float32)input = input / 255.0input = np.expand_dims(input, axis=0)return input@app.route('/detection', methods=['POST', 'GET'])  # 添加路由
def detection():if request.method == 'POST':f = request.files['file']if not (f and allowed_file(f.filename)):return jsonify({"error": 1001, "msg": "only support image formats: .bmp .png .PNG .jpg .JPG"})basepath = os.path.dirname(__file__)  # 当前文件所在路径upload_path = os.path.join(basepath, 'static/images/temp.jpg')  # 注意:没有的文件夹一定要先创建,不然会提示没有该路径f.save(upload_path)image = cv2.imread(upload_path)     tensor = preprocess(image)inputs = {}for name in input_name:inputs[name] = tensor   outputs = onnx_session.run(None, inputs)[0]boxes = filter_box(outputs)if boxes is not None:draw(image, boxes)cv2.imwrite(os.path.join(basepath, 'static/images/temp.jpg'), image)return render_template('detection.html')return render_template('upload.html')if __name__ == '__main__':app.run(host='0.0.0.0', port=8000, debug=True)

detection.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
</head>
<body><h1>请上传本地图片</h1><form action="" enctype='multipart/form-data' method='POST'><input type="file" name="file" style="margin-top:20px;"/><input type="submit" value="上传" class="button-new" style="margin-top:15px;"/></form><img src="{{ url_for('static', filename= './images/temp.jpg') }}"  alt="你的图片被外星人劫持了~~"/>
</body>
</html>

运行程序,在浏览器输入http://127.0.0.1:8000/detection,效果展示:
在这里插入图片描述

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

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

相关文章

Tomcat部署Activiti官方 流程设计器【数据库更换为Mysql !!!】

一、官网下载activiti6 解压后结构如下: database&#xff1a; 存放数据库对象相关脚本&#xff0c;包含不同的数据库脚本 libs&#xff1a; 包含activiti开发过程中需要用到的jar包和源码&#xff0c;不建议通过jar包直接引用&#xff0c;建议通过maven进行管理 wars&am…

大模型应用_FastGPT

1 功能 整体功能&#xff0c;想解决什么问题 官方说明&#xff1a;FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排&#xff0c;从而实现复杂的问答场景&#xff01;个人体会…

ubuntu将本机的wifi网络通过网线分享给另一台机器(用于没有有线网络,重装系统后无wifi驱动或者另一台设备没有wifi网卡)

1.将两台机器通过网线连接 2.在pci ethernet中设置选择另一台机器的mac address&#xff0c;ipv4中选择share to other computer&#xff0c;另一台机器上设置为动态ip&#xff0c;连接上之后另一台机器即可上网。

大数据机器学习深度解读DBSCAN聚类算法:技术与实战全解析

大数据机器学习深度解读DBSCAN聚类算法&#xff1a;技术与实战全解析 一、简介 在机器学习的众多子领域中&#xff0c;聚类算法一直占据着不可忽视的地位。它们无需预先标注的数据&#xff0c;就能将数据集分组&#xff0c;组内元素相似度高&#xff0c;组间差异大。这种无监…

Github 2023-12-14开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-14统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量非开发语言项目5TypeScript项目2JavaScript项目1Jupyter Notebook项目1PHP项目1 基于项目的学习 创建周期&a…

Python进阶(一)

1.Python中一切皆对象 1.1 Python中一切皆对象 JAVA中有class和object这两个概念&#xff0c;object只是class的一个实例。 而在Python中面向对象更加的彻底&#xff0c;class和函数都是对象。代码也是对象&#xff0c;模块也是对象。 函数和类也是对象&#xff0c;对象有四…

AUTOSAR_SWS_LogAndTrace文档中文翻译

1 Introduction and functional overview 本规范规定了AUTOSAR自适应平台日志和跟踪的功能。 日志和跟踪为AA提供接口&#xff0c;以便将日志信息转发到通信总线、控制台或文件系统。 提供的每个日志记录信息都有自己的严重性级别。对于每个严重级别&#xff0c;都提供了一个单…

bugku--source

dirsearch扫一下 题目提示源代码&#xff08;source&#xff09; 也就是源代码泄露&#xff0c;然后发现有.git 猜到是git泄露 拼接后发现有文件 但是点开啥也没有 kali里面下载下来 wegt -r 下载网站的所有内容 ls 查看目录 cd 进入到目录里面 gie reflog 引用日志使用…

如何用python编写抢票软件,python爬虫小程序抢购

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python小程序抢购脚本怎么写&#xff0c;如何用python编写抢票软件&#xff0c;现在让我们一起来看看吧&#xff01; 大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python小程序抢购脚本怎么写&#xff0c;如…

【洛谷算法题】P1422-小玉家的电费【入门2分支结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P1422-小玉家的电费【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…

diag_service的GLINK_IST是怎么来的

背景 平台&#xff1a;SA8155,QA 1.2.1 8155上集成了很多IP核&#xff0c;其中有不少的IP本质上是arm M核或者R核&#xff0c;这些模块在开发或者使用过程中也是需要监控和诊断的&#xff0c;但是他们并没有外部的调试接口&#xff0c;高通设计了整套诊断框架通过APSS&#x…

OpenHarmony应用开发——实现Toast提示功能-鸿蒙物联网应用开发-HarmonyOs应用开发

一、前言 本文我们将实现Toast样式的功能&#xff0c;以便于和用户进行简单、基本的信息交互。需要注意的是&#xff0c;本专栏&#xff08;OpenHarmony应用开发&#xff09;不阐述UI设计内容&#xff0c;而主要介绍大家开发中常遇到、常使用的功能问题&#xff0c;以及在物联网…

基于Dockerfile创建LNMP

实验组件 172.111.0.10&#xff1a;nginx docker-nginx 172.111.0.20&#xff1a;mysql docker-mysql 172.111.0.30&#xff1a;php docker-php 实验步骤 1.建立nginx-lnmp镜像及容器 cd /opt mkdir nginx cd nginx/ --上传nginx-1.22.0.tar.gz和wordpress-6.4.2-zh_C…

Android13适配所有文件管理权限

Android13适配所有文件管理权限 前言&#xff1a; 很早之前在Android11上面就适配过所有文件管理权限&#xff0c;这次是海外版升级到Android13&#xff0c;由于选择相册用的是第三方库&#xff0c;组内的同事没有上架Google的经验直接就提交代码&#xff0c;虽然功能没有问题…

自动化补丁管理软件

什么是自动化补丁管理 自动补丁管理&#xff08;或自动补丁&#xff09;是指整个补丁管理过程的自动化&#xff0c;从扫描网络中的所有系统到检测缺失的补丁&#xff0c;在一组测试系统上测试补丁&#xff0c;将它们部署到所需的系统&#xff0c;并提供定期更新和补丁部署状态…

国产数据库适配-达梦(DM)

1、通用性 达梦数据库管理系统兼容多种硬件体系&#xff0c;可运行于X86、X64、SPARC、POWER等硬件体系之上。DM各种平台上的数据存储结构和消息通信结构完全一致&#xff0c;使得DM各种组件在不同的硬件平台上具有一致的使用特性。 达梦数据库管理系统产品实现了平台无关性&…

【算法与数据结构】37、LeetCode解数独

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题也是一道困难题&#xff0c;难点在于如何构建数独棋盘&#xff0c;如何检查棋盘的合法性&#xff…

H5开发App应用程序的常见问题以及解决方案

Hello大家好&#xff0c;我是咕噜铁蛋&#xff0c;天冷记得添衣&#xff0c;ok话说回来H5开发成为了一种流行的方式来构建跨平台的移动应用程序。然而&#xff0c;在H5开发App应用程序的过程中&#xff0c;我们常常会遇到一些问题&#xff0c;这些问题可能涉及性能、兼容性、用…

人工智能_机器学习065_SVM支持向量机KKT条件_深度理解KKT条件下的损失函数求解过程_公式详细推导---人工智能工作笔记0105

之前我们已经说了KKT条件,其实就是用来解决 如何实现对,不等式条件下的,目标函数的求解问题,之前我们说的拉格朗日乘数法,是用来对 等式条件下的目标函数进行求解. KKT条件是这样做的,添加了一个阿尔法平方对吧,这个阿尔法平方肯定是大于0的,那么 可以结合下面的文章去看,也…

3、ollvm移植

github: https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0 先复制 include Obfuscation: /home/nowind/llvm/ollvm/obfuscator/include/llvm/Transforms/Obfuscation /home/nowind/llvm/llvm-project-9.0.1/llvm/include/llvm/Transforms/Obfuscation lib Ob…